diff --git a/thesis/Abschlussarbeit.tex b/thesis/Abschlussarbeit.tex index 25966e5..a9aaa08 100644 --- a/thesis/Abschlussarbeit.tex +++ b/thesis/Abschlussarbeit.tex @@ -10,7 +10,7 @@ listof=totoc, ]{scrartcl} \usepackage{thesisstyle} -\usepackage{algpseudocodex} +\usepackage[noend]{algpseudocodex} \usepackage{xcolor} \usepackage{tikz} \usepackage{multicol} @@ -302,8 +302,7 @@ This section shows that \igame implies the UF-NMA security if the EdDSA signatur \end{algorithmic} \columnbreak \begin{algorithmic}[1] - \Procedure{\ioracle}{$\agmgroupelement{R_i}{r_i}$} - \State $\groupelement{R}_i = r_1 \groupelement{B} + r_2 \groupelement{A}$ + \Procedure{\ioracle}{$\groupelement{R_i} \in \group{G}$} \State $c_i \randomsample \{0,1\}^{2b}$ \State $Q \assign Q \cup \{ (\groupelement{R}_i, c_i) \}$ \State \Return $c_i$ @@ -370,11 +369,10 @@ Assuming that $r_2 + 2^c c$ is invertible in $\field{L}$ (not equal to $0$) we c \State $c_i \randomsample \{0,1\}^{2b}$ \BeginBox[draw=blue] \State \textbf{If} $2^c c_i \equiv -r_2 \pmod L$ \textbf{then} - \State \text{ } $bad \assign true$ + \State \quad $bad \assign true$ \BeginBox[draw=red,dashed] - \State \text{ } $abort$ + \State \quad $abort$ \EndBox - \State \textbf{endIf} \EndBox \State $Q \assign Q \cup \{ (\groupelement{R}_i, c_i) \}$ \State \Return $c_i$ @@ -436,9 +434,8 @@ Game $G_0$ is defined in Figure \ref{fig:igamewithabort} by ignoring all boxes. \State $\groupelement{R}_i = r_1 \groupelement{B} + r_2 \groupelement{A}$ \State $c_i \randomsample \{0,1\}^{2b}$ \State \textbf{If} $2^c c_i \equiv -r_2 \pmod L$ \textbf{then} - \State \text{ } $bad \assign true$ - \State \text{ } $abort$ - \State \textbf{endIf} + \State \quad $bad \assign true$ + \State \quad $abort$ \State $Q \assign Q \cup \{ (\agmgroupelement{R_i}{r_i}, c_i) \}$ \State \Return $c_i$ \EndProcedure diff --git a/thesis/algpseudocodex.sty b/thesis/algpseudocodex.sty new file mode 100644 index 0000000..9fb43d1 --- /dev/null +++ b/thesis/algpseudocodex.sty @@ -0,0 +1,634 @@ +% Pseudocodex Algorithmic Style +% +% Copyright 2017 Christian Matt +% Based on Szasz Janos' algpseudocode.sty +% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{algpseudocodex} +\RequirePackage{algorithmicx} +\RequirePackage{etoolbox} +\RequirePackage{fifo-stack} +\RequirePackage{varwidth} +\RequirePackage{tikz} +\usetikzlibrary{calc,fit,tikzmark} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Package options +% +\newbool{algpx@noEnd} +\newbool{algpx@indLine} + +\DeclareOption{noend}{\setbool{algpx@noEnd}{true}} +\DeclareOption{end}{\setbool{algpx@noEnd}{false}} +\DeclareOption{noindline}{\setbool{algpx@indLine}{false}} +\DeclareOption{indline}{\setbool{algpx@indLine}{true}} +\ProcessOptions* + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Styles +% +\tikzset{% + defaultCodeBox/.style={draw},% + algpxIndentLine/.style={draw=lightgray,very thin}% +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Declarations +% +\algnewlanguage{pseudocodex} +\alglanguage{pseudocodex} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Macros for boxes around code +% + +% \tikzmark is only available on next compilation; the following command immediately after using it +\newcommand{\@tikzmarkNow}[2][]{\tikz[overlay,remember picture] \node[#1] (#2) {};} + +\long\def\@ifnodedefined#1#2#3{% + \@ifundefined{pgf@sh@ns@#1}{#3}{#2}% +} + +\newlength{\algpx@codeBoxInnerSep}% distance between box and its content +\newlength{\algpx@codeBoxSep}% distance between nested boxes +\newlength{\algpx@codeBoxOuterSep}% additional space before and after box +\newlength{\algpx@minIndDist}% minimum distance between start and end of indent line to draw line +\setlength{\algpx@codeBoxInnerSep}{2pt} +\setlength{\algpx@codeBoxSep}{3pt} +\setlength{\algpx@codeBoxOuterSep}{1pt} + +\newbool{algpx@firstLine} +\newbool{algpx@setNorth} +\newbool{algpx@executeEndVarwidth} +\newbool{algpx@adjustHeight} +\newbool{algpx@restorePrevdepth} +\newcounter{algpx@codeBoxCount} +\newcounter{algpx@nestedCBoxCount} +\newcounter{algpx@startedBoxesCount} +\newcounter{algpx@endedBoxesCount} +\newcounter{algpx@nestedBoxedStringCount} +\newcounter{algpx@nestedBoxedStringMaxCount} +\newlength{\algpx@oldPos} +\newlength{\algpx@newPos} +\newlength{\algpx@tmpLen} +\FSCreate{algpx@startNewCodeBoxQueue}{0} +\FSCreate{algpx@codeBoxStack}{0} +\FSCreate{algpx@codeBoxStackTmp}{0} + +\newsavebox{\algpx@boxedStringBox} + + +\newcommand{\algpx@drawCodeBox}[5]{% + \tikz[overlay,remember picture]{% + \node[inner sep=\algpx@codeBoxInnerSep,#1,fit={(pic cs:#2) (pic cs:#3) (pic cs:#4) (pic cs:#5)}] {};% + }% +} + +% execute after \State, \If etc. +\newcommand{\algpx@startCodeCommand}{% + \setbool{algpx@indJustEnded}{false}% + \setcounter{algpx@startedBoxesCount}{0}% + \setcounter{algpx@endedBoxesCount}{0}% + \setcounter{algpx@nestedBoxedStringMaxCount}{0}% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}% + \algpx@drawCodeBox{algpx@codeBoxStyle\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}% + \FSPop{algpx@startNewCodeBoxQueue}% + \setbool{algpx@setNorth}{true}% + \stepcounter{algpx@startedBoxesCount}% + }% + \algpx@setCodeBoxWest% + \setbool{algpx@firstLine}{false}% + \setbool{algpx@executeEndVarwidth}{true}% + % create box from here to end of line + \begin{varwidth}[t]{\dimexpr \linewidth - \algorithmicindent * \numexpr \value{ALG@nested} - 1 \relax \relax}% +} + +% executed before \State, \If etc., i.e., at end of previous line +% first argument 1 if after \EndIf etc. and noend +\newcommand{\algpx@endCodeCommand}[1][0]{% + \ifbool{algpx@executeEndVarwidth}{% + \par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982 + \end{varwidth}\setbox0=\lastbox\usebox0% + \setbool{algpx@executeEndVarwidth}{false}% + \setbool{algpx@adjustHeight}{true}% + \setbool{algpx@restorePrevdepth}{true}% + }{}% + \ifbool{algpx@setNorth}{% + % todo: north should not be set again if highest element in current line is BoxedString + \algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line + \setbool{algpx@setNorth}{false}% + }{}% + \algpx@setCodeBoxEast% + \ifbool{algpx@adjustHeight}{% + % todo: if highest or deepest element in current line is BoxedString, \ht0 or \dp0 should be adjusted for different sep values + \algpx@addBoxSpacing{\value{algpx@startedBoxesCount}}{\the\ht0}{\value{algpx@endedBoxesCount}}{\the\dp0}% + \setbool{algpx@adjustHeight}{false}% + }{}% + \ifboolexpr{bool{algpx@restorePrevdepth} and test{\ifstrequal{#1}{0}}}{% + \par\prevdepth\algpx@pdtemp% + \setbool{algpx@restorePrevdepth}{false}% + }{}% +} + +% set algpx@codeBoxNorthMax of current box and all ancestors; argument is amount to shift up from current baseline +\newcommand{\algpx@setCodeBoxNorth}[1]{% + \setcounter{algpx@nestedCBoxCount}{0}% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% + \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp + \@ifnodedefined{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{% + % get current position; shift according to nest-level to ensure nested boxes don't collide + \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthHere}% + % extract y-coordinate of previously stored north + \tikz[overlay,remember picture]{% + \pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{center}}% + \pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxNorthHere}{center}}% + \global\algpx@oldPos=\algpx@oldPos% + \global\algpx@newPos=\algpx@newPos% + }% + \ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{% + % new y is greater than old one, so set it + \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}% + }{% + \@tikzmarkNow{algpx@codeBoxNorthDummy}% set something to keep in sync + }% + }{% + \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}% + }% + \FSPop{algpx@codeBoxStack}% + \stepcounter{algpx@nestedCBoxCount}% + }% + % restore stack from tmp + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% + \FSPop{algpx@codeBoxStackTmp}% + }% +} + + +% set algpx@codeBoxSouthMax of current box and all ancestors; argument is amount to shift down from current baseline +\newcommand{\algpx@setCodeBoxSouth}[1]{% + \setcounter{algpx@nestedCBoxCount}{0}% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% + \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp + \@ifnodedefined{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{% + % get current position; shift according to nest-level to ensure nested boxes don't collide + \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthHere}% + % extract y-coordinate of previously stored south + \tikz[overlay,remember picture]{% + \pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{center}}% + \pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxSouthHere}{center}}% + \global\algpx@oldPos=\algpx@oldPos% + \global\algpx@newPos=\algpx@newPos% + }% + \ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{% + % new y is less than old one, so set it + \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}% + }{% + \@tikzmarkNow{algpx@codeBoxSouthDummy}% set something to keep in sync + }% + }{% + \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}% + }% + \FSPop{algpx@codeBoxStack}% + \stepcounter{algpx@nestedCBoxCount}% + }% + % restore stack from tmp + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% + \FSPop{algpx@codeBoxStackTmp}% + }% +} + +% set algpx@codeBoxWestMax of current box and all ancestors; argument is amount to shift left from current position +\newcommand{\algpx@setCodeBoxWest}[1][0pt]{% + \setcounter{algpx@nestedCBoxCount}{0}% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% + \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp + \@ifnodedefined{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{% + % get current position; shift according to nest-level to ensure nested boxes don't collide + \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestHere}% + % extract x-coordinate of previously stored west + \tikz[overlay,remember picture]{% + \pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{center}}% + \pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxWestHere}{center}}% + \global\algpx@oldPos=\algpx@oldPos% + \global\algpx@newPos=\algpx@newPos% + }% + \ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{% + % new x is smaller than old one, so set it + \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}% + }{% + \@tikzmarkNow{algpx@codeBoxWestDummy}% set something to keep in sync + }% + }{% + \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}% + }% + \FSPop{algpx@codeBoxStack}% + \stepcounter{algpx@nestedCBoxCount}% + }% + % restore stack from tmp + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% + \FSPop{algpx@codeBoxStackTmp}% + }% +} + +% set algpx@codeBoxEastMax of current box and all ancestors +\newcommand{\algpx@setCodeBoxEast}{% + \setcounter{algpx@nestedCBoxCount}{0}% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% + \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp + \@ifnodedefined{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{% + % get current position; shift according to nest-level to ensure nested boxes don't collide + \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastHere}% + % extract x-coordinate of previously stored east + \tikz[overlay,remember picture]{% + \pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{center}}% + \pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxEastHere}{center}}% + \global\algpx@oldPos=\algpx@oldPos% + \global\algpx@newPos=\algpx@newPos% + }% + \ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{% + % new x is greater than old one, so set it + \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}% + }{% + \@tikzmarkNow{algpx@codeBoxEastDummy}% set something to keep in sync + }% + }{% + \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}% + }% + \FSPop{algpx@codeBoxStack}% + \stepcounter{algpx@nestedCBoxCount}% + }% + % restore stack from tmp + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% + \FSPop{algpx@codeBoxStackTmp}% + }% +} + +\newcommand{\algpx@setBoxesToStoredMax}{% + \tikz[overlay,remember picture]{% + \tikzmark{algpx@codeBoxNorth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack})}% + \tikzmark{algpx@codeBoxSouth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack})}% + \tikzmark{algpx@codeBoxWest-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack})}% + \tikzmark{algpx@codeBoxEast-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack})}% + }% +} + +% add some space above and below box; more if several boxes are nested +% first argument: number of boxes above +% second argument: height of content +% third argument: number of boxes below +% fourth argument: depth of content +\newcommand{\algpx@addBoxSpacing}[4]{% + \ifnumcomp{0}{<}{#1}{% + \rule{0pt}{\dimexpr #2 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#1 - 1))\relax}% + }{}% + \ifnumcomp{0}{<}{#3}{% + \rule[\dimexpr -#4 - \algpx@codeBoxInnerSep - \algpx@codeBoxOuterSep - (\algpx@codeBoxSep * (#3 - 1))\relax]{0pt}{\dimexpr #4 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#3 - 1))\relax}% + }{}% +} + +% must be followed by \State, \If, \For etc. +\newcommand{\BeginBox}[1][defaultCodeBox]{% + \FSUnshift{algpx@startNewCodeBoxQueue}{\thealgpx@codeBoxCount}% add to queue; processed by \algpx@startCodeCommand + %globally set tikz style (https://tex.stackexchange.com/a/47918) + \begingroup% + \globaldefs=1\relax% + \pgfqkeys{/tikz}{algpx@codeBoxStyle\thealgpx@codeBoxCount/.style={#1}}% + \endgroup% + \stepcounter{algpx@codeBoxCount}% +} + +\newcommand{\EndBox}{% + \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{% + \PackageError{algpseudocodex}{BeginBox must be followed by State, If, For, etc. Use BoxedString instead}{}% + \FSClear{algpx@startNewCodeBoxQueue}% + }{% + \ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}{% + \unskip% + \ifbool{algpx@executeEndVarwidth}{% + \par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982 + \end{varwidth}\setbox0=\lastbox\usebox0% + \setbool{algpx@executeEndVarwidth}{false}% + \setbool{algpx@adjustHeight}{true}% + \setbool{algpx@restorePrevdepth}{true}% + }{}% + \ifbool{algpx@setNorth}{% + \algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line + \setbool{algpx@setNorth}{false}% + }{}% + \algpx@setCodeBoxEast% + \algpx@setCodeBoxSouth{\the\dp0}% set south here shifted by depth of current line + %adjust stored prevdepth for ended boxes + \ifnumcomp{0}{<}{\value{algpx@endedBoxesCount}}{% + \edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxSep \relax}% + }{% + \edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep \relax}% + }% + \algpx@setBoxesToStoredMax% + \FSPop{algpx@codeBoxStack}% + \stepcounter{algpx@endedBoxesCount}% + }{% + \PackageError{algpseudocodex}{No box to end}{}% + }% + }% +} + +\newcommand{\BoxedString}[2][defaultCodeBox]{% + \ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{% + \setcounter{algpx@nestedBoxedStringMaxCount}{0}% reset max count for new boxes + }{}% + \stepcounter{algpx@nestedBoxedStringCount}% + \ifnumcomp{\value{algpx@nestedBoxedStringMaxCount}}{<}{\value{algpx@nestedBoxedStringCount}}{% + \setcounter{algpx@nestedBoxedStringMaxCount}{\value{algpx@nestedBoxedStringCount}}% + }{}% + \algpx@drawCodeBox{#1}{algpx@codeBoxNorth-\thealgpx@codeBoxCount}{algpx@codeBoxWest-\thealgpx@codeBoxCount}{algpx@codeBoxEast-\thealgpx@codeBoxCount}{algpx@codeBoxSouth-\thealgpx@codeBoxCount}% + \FSPush{algpx@codeBoxStack}{\thealgpx@codeBoxCount}% + \stepcounter{algpx@codeBoxCount}% + \algpx@setCodeBoxWest% + \ifmmode% + % This works in equation but not in align / displaystyle etc. gets lost + \savebox{\algpx@boxedStringBox}{$\m@th#2$}% + \usebox{\algpx@boxedStringBox}% + \else% + \savebox{\algpx@boxedStringBox}{#2}% + \usebox{\algpx@boxedStringBox}% + \fi% + \algpx@setCodeBoxEast% + \algpx@setCodeBoxNorth{\the\ht\algpx@boxedStringBox}% + \algpx@setCodeBoxSouth{\the\dp\algpx@boxedStringBox}% + \algpx@setBoxesToStoredMax% + \FSPop{algpx@codeBoxStack}% + \addtocounter{algpx@nestedBoxedStringCount}{-1}% BoxedString ends here + \ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{% + \algpx@addBoxSpacing{\value{algpx@nestedBoxedStringMaxCount}}{\the\ht\algpx@boxedStringBox}{\value{algpx@nestedBoxedStringMaxCount}}{\the\dp\algpx@boxedStringBox}% + }{}% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Macros for indentation lines +% + +\newcounter{algpx@indentCount} +\FSCreate{algpx@indentStack}{0} +\newbool{algpx@indJustEnded} % true after end with noend +\newcounter{algpx@justUsedIndentCount} +\newlength{\algpx@indStartY} +\newlength{\algpx@indEndY} +\newlength{\algpx@indStartX} % x coordinate of indent line + +% start indented block +\newcommand{\algpx@startIndent}{% + \ifbool{algpx@indLine}{% + \@tikzmarkNow{algpx@indentStart-\thealgpx@indentCount}% + \FSPush{algpx@indentStack}{\thealgpx@indentCount}% + \stepcounter{algpx@indentCount}% + }{}% +} + +% end of indented block; optional argument 1 means that only interrupted by else +\newcommand{\algpx@endIndent}[1][0]{% + \ifbool{algpx@indLine}{% + \ifbool{algpx@noEnd}{% + \setlength{\algpx@minIndDist}{1pt}% + }{% + \setlength{\algpx@minIndDist}{\dimexpr \baselineskip + 1ex \relax}% + }% + \@tikzmarkNow{algpx@indentEnd-\FSTop{algpx@indentStack}}% + \tikz[overlay,remember picture]{% + \pgfextractx{\algpx@indStartX}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% + \ifbool{algpx@indJustEnded}{% + % use same coordinates as for previous end + \pgfextracty{\algpx@indEndY}{\pgfpointanchor{algpx@indentEnd-\thealgpx@justUsedIndentCount}{center}}% + \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(\algpx@indStartX,\algpx@indEndY)+(0.12em,0ex)$) -- +(0.5em,0);% + }{% + % only draw if at least one line between start and end + \pgfextracty{\algpx@indStartY}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% + \pgfextracty{\algpx@indEndY}{\pgfpointanchor{algpx@indentEnd-\FSTop{algpx@indentStack}}{center}}% + \ifdimcomp{\algpx@indStartY-\algpx@minIndDist}{>}{\algpx@indEndY}{% + \ifboolexpr{bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{% + % x of end is at end of line, extract x of start and use that instead + \pgfextractx{\algpx@indStartX}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% + % draw additional line to right if noend and line is not interrupted + \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(\algpx@indStartX,\algpx@indEndY)+(0.12em,0ex)$) -- +(0.5em,0);% + }{% + \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(algpx@indentEnd-\FSTop{algpx@indentStack})+(0.12em,2.0ex)$);% + }% + }{}% + }% + }% + \ifboolexpr{not bool{algpx@indJustEnded} and bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{% + \setbool{algpx@indJustEnded}{true}% + \setcounter{algpx@justUsedIndentCount}{\FSTop{algpx@indentStack}}% + }{}% + \FSPop{algpx@indentStack}% + \ifstrequal{#1}{1}{% + \algpx@startIndent% start new line if only interrupted + }{}% + }{}% +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Keywords +% +\algnewcommand\algorithmicend{\textbf{end}} +\algnewcommand\algorithmicdo{\textbf{do}} +\algnewcommand\algorithmicwhile{\textbf{while}} +\algnewcommand\algorithmicfor{\textbf{for}} +\algnewcommand\algorithmicforall{\textbf{for all}} +\algnewcommand\algorithmicloop{\textbf{loop}} +\algnewcommand\algorithmicrepeat{\textbf{repeat}} +\algnewcommand\algorithmicuntil{\textbf{until}} +\algnewcommand\algorithmicprocedure{\textbf{procedure}} +\algnewcommand\algorithmicfunction{\textbf{function}} +\algnewcommand\algorithmicif{\textbf{if}} +\algnewcommand\algorithmicthen{\textbf{then}} +\algnewcommand\algorithmicelse{\textbf{else}} +\algnewcommand\algorithmicrequire{\textbf{Require:}} +\algnewcommand\algorithmicensure{\textbf{Ensure:}} +\algnewcommand\algorithmicreturn{\textbf{return}} +\algnewcommand\algorithmicoutput{\textbf{output}} +\algnewcommand\textproc{\textsc} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Loops +% +\algdef{SE}[WHILE]{While}{EndWhile}[1]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicwhile\ #1\ \algorithmicdo% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicwhile% +} +\algdef{SE}[FOR]{For}{EndFor}[1]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicfor\ #1\ \algorithmicdo% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicfor% +} +\algdef{S}[FOR]{ForAll}[1]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicforall\ #1\ \algorithmicdo% +} +\algdef{SE}[LOOP]{Loop}{EndLoop}{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicloop% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicloop% +} +\algdef{SE}[REPEAT]{Repeat}{Until}{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicrepeat% +}[1]{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicuntil\ #1% +} +\algdef{SE}[IF]{If}{EndIf}[1]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicif\ #1\ \algorithmicthen% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicif% +} +\algdef{C}[IF]{IF}{ElsIf}[1]{% + \algpx@endIndent[1]\algpx@startCodeCommand\algorithmicelse\ \algorithmicif\ #1\ \algorithmicthen% +} +\algdef{Ce}[ELSE]{IF}{Else}{EndIf}{% + \algpx@endIndent[1]\algpx@startCodeCommand\algorithmicelse% +} +\algdef{SE}[PROCEDURE]{Procedure}{EndProcedure}[2]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicprocedure\ \textproc{#1}\ifstrempty{#2}{}{(#2)}% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicprocedure% +} +\algdef{SE}[FUNCTION]{Function}{EndFunction}[2]{% + \algpx@startIndent\algpx@startCodeCommand\algorithmicfunction\ \textproc{#1}\ifstrempty{#2}{}{(#2)}% +}{% + \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicfunction% +} + +\ifbool{algpx@noEnd}{% + \algtext*{EndWhile}% + \algtext*{EndFor}% + \algtext*{EndLoop}% + \algtext*{EndIf}% + \algtext*{EndProcedure}% + \algtext*{EndFunction}% + % + \pretocmd{\EndWhile}{\algpx@endIndent}{}{}% + \pretocmd{\EndFor}{\algpx@endIndent}{}{}% + \pretocmd{\EndLoop}{\algpx@endIndent}{}{}% + \pretocmd{\EndIf}{\algpx@endIndent}{}{}% + \pretocmd{\EndProcedure}{\algpx@endIndent}{}{}% + \pretocmd{\EndFunction}{\algpx@endIndent}{}{}% +}{}% + +\apptocmd{\State}{\algpx@startCodeCommand}{}{} + +\pretocmd{\State}{\algpx@endCodeCommand}{}{} +\pretocmd{\While}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndWhile}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} +\pretocmd{\For}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndFor}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} +\pretocmd{\ForAll}{\algpx@endCodeCommand}{}{} +\pretocmd{\Loop}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndLoop}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} +\pretocmd{\Repeat}{\algpx@endCodeCommand}{}{} +\pretocmd{\Until}{\algpx@endCodeCommand}{}{} +\pretocmd{\If}{\algpx@endCodeCommand}{}{} +\pretocmd{\ElsIf}{\algpx@endCodeCommand}{}{} +\pretocmd{\Else}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndIf}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} +\pretocmd{\Procedure}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndProcedure}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} +\pretocmd{\Function}{\algpx@endCodeCommand}{}{} +\pretocmd{\EndFunction}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Other declarations +% + +% dirty hack: execute drawing in argument of item and rest of \algpx@startCodeCommand outside +% argument: text in item[.] +\newcommand{\algpx@drawInItem}[1]{% + \item[% + \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% + \FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}% + \algpx@drawCodeBox{algpx@codeBoxStyle\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}% + \FSPop{algpx@startNewCodeBoxQueue}% + \stepcounter{algpx@startedBoxesCount}% + }% + #1% + ]% + \setbool{algpx@indJustEnded}{false}% + \setcounter{algpx@startedBoxesCount}{0}% + \setcounter{algpx@endedBoxesCount}{0}% + \setcounter{algpx@nestedBoxedStringMaxCount}{0}% + \settowidth{\algpx@tmpLen}{#1}% + \algpx@setCodeBoxWest[\dimexpr \labelsep + \algpx@tmpLen \relax]% + \setbool{algpx@firstLine}{false}% + \setbool{algpx@executeEndVarwidth}{true}% + \begin{varwidth}[t]{\dimexpr \linewidth - \labelsep - \algpx@tmpLen + \leftmargin \relax}% + \settoheight{\algpx@tmpLen}{#1}% + \rule{0pt}{\algpx@tmpLen}% +} + +\algnewcommand\Require{% + \algpx@endCodeCommand% + \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}% + \ifbool{algpx@firstLine}{% + }{% + \medskip% + }% + \algpx@drawInItem{\algorithmicrequire}% +} + +\algnewcommand\Ensure{% + \algpx@endCodeCommand% + \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}% + \algpx@drawInItem{\algorithmicensure}% +} + +\algnewcommand\Return{\algorithmicreturn{} } +\algnewcommand\Output{\algorithmicoutput{} } +\algnewcommand\Call[2]{\textproc{#1}\ifstrempty{#2}{}{(#2)}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Execute at beginning and end of algorithmic environment +\AtBeginEnvironment{algorithmic}{% + \setbool{algpx@firstLine}{true}% + \setbool{algpx@setNorth}{false}% + \setbool{algpx@executeEndVarwidth}{false}% + \setbool{algpx@adjustHeight}{false}% + \setbool{algpx@restorePrevdepth}{false}% + \setcounter{algpx@startedBoxesCount}{0}% + \setcounter{algpx@endedBoxesCount}{0}% +} + +\AtEndEnvironment{algorithmic}{% + \algpx@endCodeCommand% + % Error checking + \ifboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}} or test {\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% + \PackageError{algpseudocodex}{Some boxes have not ended}{}% + }{}% +} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Patch varwidth to allow \hfill +\newif\if@useMaxWidth +\AtBeginEnvironment{varwidth}{% + \@useMaxWidthfalse% + \renewcommand{\hfill}{\global\@useMaxWidthtrue\hspace{\fill}}% +} + +% only set width to measured width if hfill was not used +\patchcmd{\endvarwidth}{\ifdim\@vwid@<\hsize\hsize\@vwid@\fi}% +{\ifdim\@vwid@<\hsize\if@useMaxWidth\else\hsize\@vwid@\fi\fi}% +{}{\PackageWarning{algpseudocodex}{Failed to patch varwidth. \hfill probably does not work inside algorithmic.}} + +\algrenewcommand{\algorithmiccomment}[1]{{\color{gray}// #1}} \ No newline at end of file