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


\pgfkeys{/pgf/.cd,
    fixed point arithmetic/.code={%
        \pgfmathfp@plots@install%
        \pgfmathfp@parser@install%
        \let\pgfmathparse=\pgfmathfpparse%
        \pgfkeys{/pgf/fixed point/.cd, #1}%
    },%
    fixed point/.cd,
    scale results/.code={%
        \pgfmathfpparse{#1}%
        \let\pgfmathfpscale=\pgfmathresult%
    }%
}%

\def\pgfmathfpscale{1}%

\def\pgfmathfpparse{%
    \begingroup%
        \let\pgfmathpostparse=\relax%
        \pgfmath@catcodes%
        \pgfmath@quickparsefalse%
        \pgfmathfpparse@}%

\def\pgfmathfpparse@#1{%
    \edef\pgfmathfp@expression{#1}%
    \expandafter\pgfmathfpparse@@\pgfmathfp@expression\pgfmathfp@}%

\def\pgfmathfp@char@asterisk{*}%
\def\pgfmathfpparse@@#1#2\pgfmathfp@{%
    \def\pgfmathfp@test{#1}%
    \ifx\pgfmathfp@test\pgfmathfp@char@asterisk%
        \edef\pgfmathfp@expression{\pgfmathfpscale#1#2}%
    \else%
        \edef\pgfmathfp@expression{#1#2}%
    \fi%
    \expandafter\pgfmathparse@\expandafter{\pgfmathfp@expression}%
    % \endgroup provided by \pgfpathmarse@end
}%

% Crude handling of file plots
%
\pgfkeys{/pgf/fixed point/.cd,
  scale file plot x/.code=\pgfmathfpparse{#1}\edef\pgfmathfpplotscalex{\pgfmathresult*},
  scale file plot y/.code=\pgfmathfpparse{#1}\edef\pgfmathfpplotscaley{\pgfmathresult*},
  scale file plot z/.code=\pgfmathfpparse{#1}\edef\pgfmathfpplotscalez{\pgfmathresult*},
}%

\def\pgfmathfp@plots@install{%
    \let\pgfmathfpplotscalex=\pgfutil@empty
    \let\pgfmathfpplotscaley=\pgfutil@empty
    \let\pgfmathfpplotscalez=\pgfutil@empty
    \let\pgf@parsexyline=\pgfmathfp@parsexyline%
    \let\pgf@parsexyzline=\pgfmathfp@parsexyzline%
}%

\def\pgfmathfp@parsexyline#1 #2 #3\pgf@stop{%
    \edef\pgfmathfp@marshal{%
        \noexpand\pgfplotstreampoint{\noexpand\pgfpointxy{\pgfmathfpplotscalex#1}{\pgfmathfpplotscaley#2}}%
    }%
    \pgfmathfp@marshal%
}%

\def\pgfmathfp@parsexyzline#1 #2 #3 #4\pgf@stop{%
    \edef\pgfmathfp@marshal{%
        \noexpand\pgfplotstreampoint{%
            \noexpand\pgfpointxyz{\pgfmathfpplotscalex#1}{\pgfmathfpplotscaley#2}{\pgfmathfpplotscalez#3}%
        }%
    }%
    \pgfmathfp@marshal%
}%

%
\def\pgfmathfp@parser@install{%
    %
    \expandafter\ifx\csname FP@version\endcsname\relax%
        \pgferror{You need to say `\string\usepackage{fp}' to use %
          fixed point arithmetic}%
    \else%
        %
        % Don't want messages.
        %
        \FPmessagesfalse%
        \FPdebugfalse%
        %
        % Install float commands...
        %
        \let\pgfmathadd@=\pgfmathfpadd@%
        \let\pgfmathsubtract@=\pgfmathfpsubtract@%
        \let\pgfmathmultiply@=\pgfmathfpmultiply@%
        \let\pgfmathdivide@=\pgfmathfpdivide@%
        \let\pgfmathabs@=\pgfmathfpabs@%
        \let\pgfmathneg@=\pgfmathfpneg@%
        \let\pgfmathround@=\pgfmathfpround@%
        \let\pgfmathfloor@=\pgfmathfpfloor@%
        \let\pgfmathceil@=\pgfmathfpceil@%
        \let\pgfmathmod@=\pgfmathfpmod@%
        \let\pgfmathmax@=\pgfmathfpmax@%
        \let\pgfmathmin@=\pgfmathfpmin@%
        \let\pgfmathsin@=\pgfmathfpsin@%
        \let\pgfmathcos@=\pgfmathfpcos@%
        \let\pgfmathtan@=\pgfmathfptan@%
        \let\pgfmathdeg@=\pgfmathfpdeg@%
        \let\pgfmathrad@=\pgfmathfprad@%
        \let\pgfmathatan@=\pgfmathfpatan@%
        \let\pgfmathasin@=\pgfmathfpasin@%
        \let\pgfmathacos@=\pgfmathfpacos@%
        \let\pgfmathcot@=\pgfmathfpcot@%
        \let\pgfmathsec@=\pgfmathfpsec@%
        \let\pgfmathcosec@=\pgfmathfpcosec@%
        \let\pgfmathpow@=\pgfmathfppow@%
        \let\pgfmathexp@=\pgfmathfpexp@%
        \let\pgfmathln@=\pgfmathfpln@%
        \let\pgfmathsqrt@=\pgfmathfpsqrt@%
        \let\pgfmath@pi=\pgfmathfppi@%
        \let\pgfmathveclen@=\pgfmathfpveclen@%
        \let\pgfmathe@=\pgfmathfpe@%
        %
        \let\pgfmathlessthan@=\pgfmathfplessthan@%
        \let\pgfmathgreaterthan@=\pgfmathfpgreaterthan@%
        \let\pgfmathequalto@=\pgfmathfpequalto@%
        %
        \let\pgfmathrnd=\pgfmathfprnd%
        \let\pgfmathrand=\pgfmathfprand%
        \let\pgfmathsetseed=\pgfmathfpsetseed%
        %
        \let\pgfmathscientific=\pgfmathfpscientific%
    \fi%
}%

\def\pgfmathfpe@{let\pgfmathresult=\FPe}%
\def\pgfmathfppi@{let\pgfmathresult=\FPpi}%


% Scientific notation.

\def\pgfmathfpscientific#1#2{%
    \begingroup%
        \FPpow\pgfmathresult{10}{#2}\unskip% Needed.
        \FPmul\pgfmathresult{#1}{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% Comparison stuff...

% lessthan
%
\def\pgfmathfplessthan#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfplessthan@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfplessthan@#1#2{%
    \begingroup%
        \FPiflt{#1}{#2}%
            \def\pgfmathresult{1.0}%
        \else%
            \def\pgfmathresult{0.0}%
        \fi%
       \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% greaterthan
%
\def\pgfmathfpgreaterthan#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpgreaterthan@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpgreaterthan@#1#2{%
    \begingroup%
        \FPifgt{#1}{#2}%
            \def\pgfmathresult{1.0}%
        \else%
            \def\pgfmathresult{0.0}%
        \fi%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% equalto
%
\def\pgfmathfpequalto#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpequalto@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpequalto@#1#2{%
    \begingroup%
        \FPifeq{#1}{#2}%
            \def\pgfmathresult{1.0}%
        \else%
            \def\pgfmathresult{0.0}%
        \fi%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%


% Basic arithmetic stuff...

% add
%
\def\pgfmathfpadd#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpadd@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpadd@#1#2{%
    \begingroup%
        \FPadd\pgfmathresult{#1}{#2}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% subtract
%
\def\pgfmathfpsubtract#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpsubtract@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpsubtract@#1#2{%
    \begingroup%
        \FPsub\pgfmathresult{#1}{#2}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% multiply
%
\def\pgfmathfpmultiply#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpmultiply@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpmultiply@#1#2{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{#2}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% divide
%
\def\pgfmathfpdivide#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpdivide@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpdivide@#1#2{%
    \begingroup%
        \FPdiv\pgfmathresult{#1}{#2}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% abs
%
\def\pgfmathfpabs#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpabs@{\pgfmathresult}%
}%
\def\pgfmathfpabs@#1{%
    \begingroup%
        \FPabs\pgfmathresult{#1}%
    \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% neg
%
\def\pgfmathfpneg#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpneg@{\pgfmathresult}%
}%
\def\pgfmathfpneg@#1{%
    \begingroup%
        \FPneg\pgfmathresult{#1}%
        \pgfmath@smuggleone\pgfmathresult
    \endgroup%
}%

% round
%
\def\pgfmathfpround#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpround@{\pgfmathresult}%
}%
\def\pgfmathfpround@#1{%
    \begingroup%
        \FPround\pgfmathresult{#1}{0}%
        \edef\pgfmathresult{\pgfmathresult.0}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% floor
%
\def\pgfmathfpfloor#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpfloor@{\pgfmathresult}%
}%
\def\pgfmathfpfloor@#1{%
    \begingroup%
        \FPtrunc\pgfmathresult{#1}{0}%
        \FPifneg{#1}%
            \FPsub\pgfmathresult{\pgfmathresult}{1}%
        \fi%
        \edef\pgfmathresult{\pgfmathresult.0}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% ceil
%
\def\pgfmathfpceil#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpceil@{\pgfmathresult}%
}%
\def\pgfmathfpceil@#1{%
    \begingroup%
        \FPtrunc\pgfmathresult{#1}{0}%
        \FPifpos{#1}%
            \FPadd\pgfmathresult{\pgfmathresult}{1}%
        \fi%
        \edef\pgfmathresult{\pgfmathresult.0}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% mod
%
\def\pgfmathfpmod#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpmod@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpmod@#1#2{%
    \begingroup%
        \FPdiv\pgfmathresult{#1}{#2}%
        \FPtrunc\pgfmathresult{\pgfmathresult}{0}%
        \FPmul\pgfmathresult{\pgfmathresult}{#2}%
        \FPsub\pgfmathresult{#1}{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% max
%
\def\pgfmathfpmax#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpmax@@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpmax@#1{%
    \pgfmathfpmax@@#1%
}%
\def\pgfmathfpmax@@#1#2{%
    \begingroup%
        \FPifgt{#1}{#2}%
            \def\pgfmathresult{#1}%
        \else%
            \def\pgfmathresult{#2}%
        \fi%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% min
%
\def\pgfmathfpmin#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpmin@@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpmin@#1{%
    \pgfmathfpmin@@#1%
}%
\def\pgfmathfpmin@@#1#2{%
    \begingroup%
        \FPiflt{#1}{#2}%
            \def\pgfmathresult{#1}%
        \else%
            \def\pgfmathresult{#2}%
        \fi%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% Functions...

% pow
%
\def\pgfmathfppow#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfppow@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfppow@#1#2{%
    \begingroup%
        \FPpow\pgfmathresult{#1}{#2}\unskip%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% exp
%
\def\pgfmathfpexp#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpexp@{\pgfmathresult}%
}%
\def\pgfmathfpexp@#1{%
    \begingroup%
        \FPexp\pgfmathresult{#1}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% ln
%
\def\pgfmathfpln#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpln@{\pgfmathresult}%
}%
\def\pgfmathfpln@#1{%
    \begingroup%
        \FPln\pgfmathresult{#1}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% sqrt
%
\def\pgfmathfpsqrt#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpsqrt@{\pgfmathresult}%
}%
\def\pgfmathfpsqrt@#1{%
    \begingroup%
        \FProot\pgfmathresult{#1}{2}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% veclen
%
\def\pgfmathfpveclen#1#2{%
    \pgfmathfpparse{#2}\let\pgfmath@result=\pgfmathresult%
    \pgfmathfpparse{#1}%
    \pgfmathfpveclen@{\pgfmathresult}{\pgfmath@result}%
}%
\def\pgfmathfpveclen@#1#2{%
    \begingroup%
      \FPmul\pgfmath@result{#1}{#1}%
      \FPmul\pgfmath@@result{#2}{#2}%
      \FPadd\pgfmathresult{\pgfmath@result}{\pgfmath@@result}%
      \FProot\pgfmathresult{\pgfmathresult}{2}%
      \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% Trigonometric stuff...

% sin
%
\def\pgfmathfpsin#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpsin@{\pgfmathresult}%
}%
\def\pgfmathfpsin@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPsin\pgfmathresult{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% cos
%
\def\pgfmathfpcos#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpcos@{\pgfmathresult}%
}%
\def\pgfmathfpcos@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPcos\pgfmathresult{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% tan
%
\def\pgfmathfptan#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfptan@{\pgfmathresult}%
}%
\def\pgfmathfptan@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPtan\pgfmathresult{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% acos
%
\def\pgfmathfpacos#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpacos@{\pgfmathresult}%
}%
\def\pgfmathfpacos@#1{%
    \begingroup%
        \FParccos\pgfmathresult{#1}%
        \FPmul\pgfmathresult{\pgfmathresult}{57.295779513082320885}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% asin
%
\def\pgfmathfpasin#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpasin@{\pgfmathresult}%
}%
\def\pgfmathfpasin@#1{%
    \begingroup%
        \FParcsin\pgfmathresult{#1}%
        \FPmul\pgfmathresult{\pgfmathresult}{57.295779513082320885}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% atan
%
\def\pgfmathfpatan#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpatan@{\pgfmathresult}%
}%
\def\pgfmathfpatan@#1{%
    \begingroup%
        \FParctan\pgfmathresult{#1}%
        \FPmul\pgfmathresult{\pgfmathresult}{57.295779513082320885}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% cot
%
\def\pgfmathfpcot#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpcot@{\pgfmathresult}%
}%
\def\pgfmathfpcot@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPcot\pgfmathresult{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% sec
%
\def\pgfmathfpsec#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpsec@{\pgfmathresult}%
}%
\def\pgfmathfpsec@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPcos\pgfmathresult{\pgfmathresult}%
        \FPdiv\pgfmathresult{1}{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% cosec
%
\def\pgfmathfpcosec#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpcosec@{\pgfmathresult}%
}%
\def\pgfmathfpcosec@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.017453292519943295}%
        \FPsin\pgfmathresult{\pgfmathresult}%
        \FPdiv\pgfmathresult{1}{\pgfmathresult}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% deg
%
\def\pgfmathfpdeg#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfpdeg@{\pgfmathresult}%
}%
\def\pgfmathfpdeg@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{57.295779513082320885}%
    \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% rad
%
\def\pgfmathfprad#1{%
    \pgfmathfpparse{#1}%
    \pgfmathfprad@{\pgfmathresult}%
}%
\def\pgfmathfprad@#1{%
    \begingroup%
        \FPmul\pgfmathresult{#1}{0.01745329251994325}%
    \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% Random stuff...

\def\pgfmathfpsetseed#1{%
    \pgfmathfpparse{#1}%
    \afterassignment\pgfmath@gobbletilpgfmath@%
    \FPseed\pgfmathresult\relax\pgfmath@%
}%

% rnd
%
\def\pgfmathfprnd{%
    \begingroup%
        \FPrandom\pgfmathresult%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%

% rand
%
\def\pgfmathfprand{%
    \begingroup%
        \FPrandom\pgfmathresult%
        \FPmul\pgfmathresult{2}{\pgfmathresult}%
        \FPsub\pgfmathresult{\pgfmathresult}{1}%
        \pgfmath@smuggleone\pgfmathresult%
    \endgroup%
}%
