% Copyright 2019 by Mark Wibrow
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.

% This file loads all the parsing, functions and operator stuff
%
% Version 1.414213 29/9/2007

% \pgfmathsetlength, \pgfmathaddtolength
%
% #1 = dimension register
% #2 = expression
%
% Description:
%
% These functions work similar to \setlength and \addtolength. Only,
% they allow #2 to contain an expression, which is evaluated before
% assignment. Furthermore, the font is setup before the assignment is
% done, so that dimensions like 1em are evaluated correctly.
%
% If #2 starts with "+", then a simple assignment is done (but the
% font is still setup). This is orders of magnitude faster than a
% parsed assignment.

\def\pgfmathsetlength#1#2{%
  \expandafter\pgfmath@onquick#2\pgfmath@%
  {%
    % Ok, quick version:
    \begingroup%
      \pgfmath@selectfont%
      #1#2\unskip%
    \expandafter\endgroup%
    \expandafter#1\the#1\relax%
  }%
  {%
    \pgfmathparse{#2}%
    \ifpgfmathmathunitsdeclared%
      #1\pgfmathresult mu\relax%
    \else%
      #1\pgfmathresult pt\relax%
    \fi%
  }%
  \ignorespaces%
}

% \pgfmathaddtolength
%
% Add to #1 the result of evaluating #2.
%
% #1 - a dimension register
% #2 - an expression
%
\def\pgfmathaddtolength#1#2{%
  \expandafter\pgfmath@onquick#2\pgfmath@%
  {%
    \begingroup%
      \pgfmath@selectfont%
      \advance#1#2\unskip%
      \expandafter%
    \endgroup%
    \expandafter#1\the#1\relax%
  }%
  {%
    \pgfmathparse{#2}%
    \ifpgfmathmathunitsdeclared%
      \advance#1\pgfmathresult mu\relax%
    \else%
      \advance#1\pgfmathresult pt\relax%
    \fi%
  }%
  \ignorespaces%
}

% \pgfmathsetcount
%
% Assign #1 the truncated evaluation of #2.
%
% #1 - a count register
% #2 - an expression
%
\def\pgfmathsetcount#1#2{%
  \expandafter\pgfmath@onquick#2\pgfmath@%
  {%
    \afterassignment\pgfmath@gobbletilpgfmath@%
    #1#2\relax\pgfmath@%
  }%
  {%
    \pgfmathparse{#2}%
    \afterassignment\pgfmath@gobbletilpgfmath@%
    #1\pgfmathresult\relax\pgfmath@%
  }%
  \ignorespaces%
}

% \pgfmathaddtocount
%
% Add to #1 the truncated evaluation of #2.
%
% #1 - a count register
% #2 - an expression
%
\def\pgfmathaddtocount#1#2{%
  \expandafter\pgfmath@onquick#2\pgfmath@%
  {%
    \edef\pgfmath@addtocounttemp{\the#1}%
    \afterassignment\pgfmath@gobbletilpgfmath@%
    #1#2\relax\pgfmath@%
    \advance#1\pgfmath@addtocounttemp\relax%
  }%
  {%
    \edef\pgfmath@addtocounttemp{\the#1}%
    \pgfmathparse{#2}%
    \afterassignment\pgfmath@gobbletilpgfmath@%
    #1\pgfmathresult\relax\pgfmath@%
    \advance#1\pgfmath@addtocounttemp\relax%
  }%
  \ignorespaces%
}

% \pgfmathnewcounter
%
% LaTeX style counter which also works in plain TeX. Defines
% \c@<name> as a count register and also defines \the<name>.
%
% #1 the name of the counter.
%
% Example:
%
% \pgfmathnewcounter{counter}
% \pgfmathsetcounter{counter}{12}
% \thecounter  (same as \the\c@counter)
%
\def\pgfmathnewcounter#1{%
  \expandafter\ifx\csname c@#1\endcsname\relax%
    \def\pgfmath@marshal{\csname newcount\endcsname}% Ha! Who cares about \outer?
    \expandafter\pgfmath@marshal\csname c@#1\endcsname%
    \expandafter\def\csname the#1\endcsname{\expandafter\the\csname c@#1\endcsname}%
  \fi%
}

% \pgfmathsetcounter
%
% Set the counter #1 to the evaluation of #2.
%
% #1 - a counter name
% #2 - an expression
%
\def\pgfmathsetcounter#1#2{%
   \expandafter\pgfmathsetcount\csname c@#1\endcsname{#2}%
}

% \pgfmathaddtocounter
%
% Add the counter #1 to the evaluation of #2.
%
% #1 - a counter name
% #2 - an expression
%
\def\pgfmathaddtocounter#1#2{%
  \expandafter\pgfmathaddtocount\csname c@#1\endcsname{#2}%
}

% \pgfmathmakecounterglobal
%
% Make the current value of a counter globally defined.
%
% #1 - a (valid) counter name.
%
\def\pgfmath@pgftext{pgf}
\def\pgfmath@tikztext{tikz}
\def\pgfmathmakecounterglobal#1{%
  \pgfmath@ifundefined{c@#1}{}{%
    \expandafter\pgfmath@in@\expandafter{\pgfmath@pgftext}{#1}%
    \ifpgfmath@in@%
    \else%
      \expandafter\pgfmath@in@\expandafter{\pgfmath@tikztext}{#1}%
      \ifpgfmath@in@%
      \else%
        \expandafter\global\csname c@#1\endcsname\csname c@#1\endcsname\relax%
      \fi%
    \fi%
  }%
}

% \pgfmathsetmacro
%
% \edef#1 as the result of evaluating #2.
%
% #1 - a macro
% #2 - an expression
%
\def\pgfmathsetmacro#1#2{%
  \begingroup%
    \pgfmathparse{#2}%
    \let#1=\pgfmathresult
    \pgfmath@smuggleone{#1}%
  \endgroup%
}

% \pgfmathsetlengthmacro
%
% \edef#1 as the result of evaluating #2 with pt.
%
% #1 - a macro
% #2 - an expression
%
\def\pgfmathsetlengthmacro#1#2{%
  \begingroup%
    \pgfmathsetlength\pgfmath@x{#2}%
    \edef#1{\the\pgfmath@x}%
    \pgfmath@smuggleone{#1}%
  \endgroup%
}

% \pgfmathtruncatemacro
%
% \edef#1 as the truncated result of evaluating #2.
%
% #1 - a macro
% #2 - an expression
%
\def\pgfmathtruncatemacro#1#2{%
  \begingroup%
    \pgfmathsetcount\c@pgfmath@counta{#2}%
    \edef#1{\the\c@pgfmath@counta}%
    \pgfmath@smuggleone{#1}%
  \endgroup%
}

% Check whether a given parameter starts with quick.
%
% The command should be followed by nonempty text, ending with
% \pgfmath@ as a stop-token. Then should follow
%
% #1 - code to execute if text starts with +
% #2 - code to execute if text does not
%
% Example:
%
% \pgfmath@onquick+0pt\pgfmath@{is quick}{is slow}

\def\pgfmath@onquick{%
  \futurelet\pgfmath@next%
  \pgfmath@@onquick}
\def\pgfmath@@onquick#1\pgfmath@{%
  \ifx\pgfmath@next+%
    \let\pgfmath@next=\pgfmath@firstoftwo%
  \else%
    \let\pgfmath@next=\pgfmath@secondoftwo%
  \fi%
  \pgfmath@next%
}

% *** The following commands DO NOT WORK without the rest of PGF ***
%
% (a dumping ground for stuff that doesn't really belong anywhere else)

% \pgfmathanglebetweenpoints
%
% Define \pgfmathresult as the angle between points #1 and #2
% Should get the quadrants right as well.
%
\def\pgfmathanglebetweenpoints#1#2{%
  \begingroup%
    \pgf@process{\pgfpointdiff{#1}{#2}}%
    \edef\pgf@marshall{\expandafter\noexpand\csname pgfmathatan2@\endcsname{\expandafter\Pgf@geT\the\pgf@y}{\expandafter\Pgf@geT\the\pgf@x}}%
    \pgf@marshall%
    \ifdim\pgfmathresult pt<0pt%
      \pgfmathparse{\pgfmathresult+360}%
    \fi%
    \expandafter%
  \endgroup\expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult}%
}

%
% \pgfmathrotatepointaround
%
% Rotate point #1 about point #2 by #3 degrees.
%
\def\pgfmathrotatepointaround#1#2#3{%
  \pgf@process{%
    \pgf@process{#1}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgf@process{#2}%
    \pgf@xa\pgf@x%
    \pgf@ya\pgf@y%
    \pgf@xb\pgf@x%
    \pgf@yb\pgf@y%
    \pgf@x=\pgf@xc%
    \pgf@y=\pgf@yc%
    \advance\pgf@x-\pgf@xa%
    \advance\pgf@y-\pgf@ya%
    \pgfmathsetmacro\angle{#3}%
    \pgfmathsin@{\angle}%
    \let\sineangle\pgfmathresult%
    \pgfmathcos@{\angle}%
    \let\cosineangle\pgfmathresult%
    \pgf@xa\cosineangle\pgf@x%
    \advance\pgf@xa-\sineangle\pgf@y%
    \pgf@ya\sineangle\pgf@x%
    \advance\pgf@ya\cosineangle\pgf@y%
    \pgf@x\pgf@xb%
    \pgf@y\pgf@yb%
    \advance\pgf@x\pgf@xa%
    \advance\pgf@y\pgf@ya%
  }%
}

% \pgfmathanglebetweenlines
%
% Calculate the clockwise angle between a line from point #1
% to point #2 and a line from #3 to point #4.
%
\def\pgfmathanglebetweenlines#1#2#3#4{%
  \begingroup%
    \pgfmathanglebetweenpoints{#1}{#2}%
    \let\firstangle\pgfmathresult%
    \pgfmathanglebetweenpoints{#3}{#4}%
    \let\secondangle\pgfmathresult%
    \ifdim\firstangle pt>\secondangle pt\relax%
      \pgfmathadd@{\secondangle}{360}%
      \let\secondangle\pgfmathresult%
    \fi%
    \pgfmathsubtract@{\secondangle}{\firstangle}%
    \pgfmath@smuggleone\pgfmathresult%
  \endgroup%
}

% \pgfmathpointreflectalongaxis
%
% Reflects point #1 around an axis centered on #2 at an angle #3.
%
\def\pgfmathreflectpointalongaxis#1#2#3{%
  \pgf@process{%
    \pgfmathanglebetweenpoints{#2}{#1}%
    \pgfmath@tempdima\pgfmathresult pt\relax%
    \pgfmathparse{#3}%
    \advance\pgfmath@tempdima-\pgfmathresult pt\relax%
    \pgfmath@tempdima-2.0\pgfmath@tempdima%
    \pgfmathrotatepointaround{#1}{#2}{\pgfmath@tonumber{\pgfmath@tempdima}}%
  }%
}



% \pgfmathpointintersectionoflineandarc
%
% A bit experimental at the moment:
%
% Locates the point where a line crosses an eliptical arc. If the line
% does not cross the arc, a meaningless point will result.
%
% #1 the point of the line on the "convex" side of the arc.
% #2 the point of the line on the "concave" side of the arc.
% #3 the center of the eliptical arc.
% #4 start angle of the arc.
% #5 end angle of the arc.
% #6 radii of the arc.
%
\def\pgfmathpointintersectionoflineandarc#1#2#3#4#5#6{%
  \pgf@process{%
    %
    % Get the required angle.
    %
    \pgfmathanglebetweenpoints{#2}{#1}%
    \let\x\pgfmathresult%
    %
    % Get the radii of the arc.
    %
    \pgfmath@in@{and }{#6}%
    \ifpgfmath@in@%
      \pgf@polar@#6\@@%
    \else%
      \pgf@polar@#6 and #6\@@%
    \fi%
    \edef\xarcradius{\the\pgf@x}%
    \edef\yarcradius{\the\pgf@y}%
     %
    % Get the start and end angles of the arc...
    %
    \pgfmathsetmacro\s{#4}%
    \pgfmathsetmacro\e{#5}%
    %
    % ...and also with rounding.
    %
    \pgfmathmod@{\s}{360}%
    \ifdim\pgfmathresult pt<0pt\relax%
      \pgfmathadd@{\pgfmathresult}{360}%
    \fi%
    \let\ss\pgfmathresult%
    \pgfmathmod@{\e}{360}%
    \ifdim\pgfmathresult pt<0pt\relax%
      \pgfmathadd@{\pgfmathresult}{360}%
    \fi%
    \let\ee\pgfmathresult%
    %
    % Hackery for when arc straddles zero.
    %
    \ifdim\ee pt<\ss pt\relax%
      \pgfmathadd@{\x}{180}%
      \pgfmathmod@{\pgfmathresult}{360}%
      \let\x\pgfmathresult%
    \fi%
    \def\m{360}% Measure of nearness.
    \pgfmathadd@{\s}{\e}%
    \pgfmathdivide@{\pgfmathresult}{2}%
    \let\n\pgfmathresult% The best estimate (default to middle of arc).
    \pgfmathloop%
      \pgfmathadd@{\s}{\e}%
      \pgfmathdivide@{\pgfmathresult}{2}%
      \let\p\pgfmathresult%
      \ifdim\p pt=\s pt\relax%
      \else%
        \pgfmathanglebetweenpoints{#2}{%
          \pgfpointadd{#3}{%
            \pgf@x\xarcradius\relax%
            \pgfmathcos@{\p}%
            \pgf@x\pgfmathresult\pgf@x%
            \pgf@y\yarcradius\relax%
            \pgfmathsin@{\p}%
            \pgf@y\pgfmathresult\pgf@y%
          }%
        }%
        %
        % Hackery for when arc straddles zero.
        %
        \ifdim\ee pt<\ss pt\relax%
          \pgfmathadd@{\pgfmathresult}{180}%
          \pgfmathmod@{\pgfmathresult}{360}%
        \fi%
        \let\q\pgfmathresult%
        %
        % More hackery...
        %
        \ifdim\x pt>335pt\relax%
          \ifdim\q pt<45pt\relax%
            \pgfmathadd@{\q}{360}%
            \let\q\pgfmathresult%
          \fi%
        \fi%
        \ifdim\x pt=\q pt% Found it!
            \pgfmathbreakloop% Breaks after current iteration is complete.
          \else
            \ifdim\x pt<\q pt\relax%
              \let\e\p%
            \else%
              \let\s\p%
            \fi%
          \fi%
          \pgfmathsubtract@{\x}{\q}%
          \pgfmathabs@{\pgfmathresult}%
          %
          % Save the estimate if it is better than any previous estimate.
          %
          \ifdim\pgfmathresult pt<\m pt\relax%
            \let\m\pgfmathresult%
            \let\n\p%
          \fi%
    \repeatpgfmathloop%
    \pgfpointadd{#3}{\pgfpointpolar{\n}{\xarcradius and \yarcradius}}%
  }%
}

% \pgfmathangleonellipse
%
% Find the angle corresponding to a point on the border of an ellispe.
%
% #1 - the point on the border.
% #2 - the radii of the ellipse.
%
\def\pgfmathangleonellipse#1#2{%
  \begingroup%
    \pgfmath@in@{and }{#2}%
    \ifpgfmath@in@%
      \pgf@polar@#2\@@%
    \else%
      \pgf@polar@#2 and #2\@@%
    \fi%
    \pgf@xa\pgf@x%
    \pgf@ya\pgf@y%
    \pgf@process{#1}%
    \ifdim\pgf@x=0pt\relax%
      \pgfutil@tempdima1pt\relax%
    \else%
      \pgfutil@tempdima\pgf@x%
      \pgfmathdivide@{\pgfmath@tonumber{\pgf@xa}}{\pgfmath@tonumber{\pgfutil@tempdima}}%
      \pgfutil@tempdima\pgfmathresult pt\relax%
    \fi%
    \ifdim\pgf@y=0pt\relax%
      \pgfutil@tempdima1pt\relax%
    \else%
      \pgfmathdivide@{\pgfmath@tonumber{\pgf@y}}{\pgfmath@tonumber{\pgf@ya}}%
      \pgfutil@tempdima\pgfmathresult\pgfutil@tempdima%
      \pgfmathatan@{\pgfmath@tonumber{\pgfutil@tempdima}}%
    \fi%
    %
    \pgfutil@tempdima\pgfmathresult pt\relax%
    \ifdim\pgfutil@tempdima<0pt\relax%
      \advance\pgfutil@tempdima360pt\relax%
    \fi%
    \ifdim\pgf@x<0pt\relax%
      \ifdim\pgf@y=0pt\relax%
        \pgfutil@tempdima180pt\relax%
      \else%
        \ifdim\pgf@y<0pt\relax%
          \advance\pgfutil@tempdima180pt\relax%
        \else%
          \advance\pgfutil@tempdima-180pt\relax%
        \fi%
      \fi%
    \else%
      \ifdim\pgf@x=0pt\relax%
        \ifdim\pgf@y<0pt\relax%
          \pgfutil@tempdima270pt\relax%
        \else%
          \pgfutil@tempdima90pt\relax%
        \fi%
      \else%
        \ifdim\pgf@y=0pt\relax%
          \pgfutil@tempdima0pt\relax%
        \fi%
      \fi%
    \fi%
    \pgfmath@returnone\pgfutil@tempdima%
  \endgroup%
}


% Local Variables:
% tab-width: 2
% End:
