summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/fp
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/fp
Initial commit
Diffstat (limited to 'macros/latex/contrib/fp')
-rw-r--r--macros/latex/contrib/fp/README465
-rw-r--r--macros/latex/contrib/fp/defpattern.sty31
-rw-r--r--macros/latex/contrib/fp/documentation.pdfbin0 -> 213303 bytes
-rw-r--r--macros/latex/contrib/fp/fp-addons.sty66
-rw-r--r--macros/latex/contrib/fp/fp-basic.sty1121
-rw-r--r--macros/latex/contrib/fp/fp-eqn.sty382
-rw-r--r--macros/latex/contrib/fp/fp-eval.sty155
-rw-r--r--macros/latex/contrib/fp/fp-exp.sty500
-rw-r--r--macros/latex/contrib/fp/fp-pas.sty118
-rw-r--r--macros/latex/contrib/fp/fp-random.sty120
-rw-r--r--macros/latex/contrib/fp/fp-snap.sty242
-rw-r--r--macros/latex/contrib/fp/fp-trigo.sty1119
-rw-r--r--macros/latex/contrib/fp/fp-upn.sty237
-rw-r--r--macros/latex/contrib/fp/fp.sty32
-rw-r--r--macros/latex/contrib/fp/fp.tex49
-rw-r--r--macros/latex/contrib/fp/lfp.sty34
16 files changed, 4671 insertions, 0 deletions
diff --git a/macros/latex/contrib/fp/README b/macros/latex/contrib/fp/README
new file mode 100644
index 0000000000..f729cb69c4
--- /dev/null
+++ b/macros/latex/contrib/fp/README
@@ -0,0 +1,465 @@
+fp-package
+
+(c) Michael Mehlich 1994 -- 1999
+contributions by: Denis Girou
+acknowledgment to: Denis Girou, Miroslav Balda, Ricardo Sanchez Carmenes
+
+% Copyright 1994 -- 1999 Michael Mehlich
+% This package can be redistributed and/or modified under the terms
+% of the LaTeX Project Public License Distributed from CTAN
+% archives at http://www.latex-project.org/lppl.txt either
+% version 1 of the License, or any later version.
+
+(current) e-mail: mmehlich@semdesigns.com; michael@mehlich.com
+
+Fixed point arithmetic for TeX with numbers ranging from
+ -999999999999999999.999999999999999999
+to
+ +999999999999999999.999999999999999999
+
+TODO:
+ - better documentation (it is really bad)
+
+USAGE:
+ - LaTeX2e:
+ \usepackage[<options>]{fp}
+ where the following options are known:
+ nomessages: don't print messages about the functions that are
+ just computed
+ debug: print debug messages (mainly for \FPupn)
+ - LaTeX2.09:
+ include lfp.sty in the document preamble, i.e.
+ \documentstyle[...,lfp,...]{...}
+ - TeX:
+ \input fp.tex
+
+MsDos/Windows Users:
+ It may be necessary to rename some files such that they just have a length of
+ eight characters (plus a three character suffix).
+ The following renaming e.g. works for emtex:
+ Original name Name for emtex
+ defpattern.sty defpaern.sty
+ fp-addons.sty fp-adons.sty
+ fp-random.sty fp-radom.sty
+
+FILES AND THEIR CONTENTS:
+ - readme.fp:
+ this file
+ - fp.sty
+ includes all files
+ - defpattern.sty:
+ only for internal usage
+ - fp-basic.sty:
+ The following macros are public ones to be used in the document:
+ %controlling messages
+ \FPmessagestrue % print standard FP-messages (default)
+ \FPmessagesfalse % suppress standard FP-messages
+ \FPdebugtrue % print debug messages (mainly for upn)
+ \FPdebugfalse % suppress debug messages (default)
+ %introduction of new values
+ \FPset#1#2 % #1 := #2 (#1 may be macro or string)
+ %print values
+ \FPprint#1 % prints #1 (#1 may be macro or string)
+ %binary operations
+ \FPadd#1#2#3 % #1 := #2+#3
+ \FPdiv#1#2#3 % #1 := #2/#3
+ \FPmul#1#2#3 % #1 := #2*#3
+ \FPsub#1#2#3 % #1 := #2-#3
+ %unary operations
+ \FPabs#1#2 % #1 := abs(#2)
+ \FPneg#1#2 % #1 := -#2
+ %binary relations
+ \FPiflt#1#2...\else...\fi % #1 < #2 ?
+ \FPifeq#1#2...\else...\fi % #1 = #2 ?
+ \FPifgt#1#2...\else...\fi % #1 > #2 ?
+ %unary relations
+ \FPifneg#1 ...\else...\fi % #1 < 0 ?
+ \FPifpos#1 ...\else...\fi % #1 >= 0 ?
+ \FPifzero#1...\else...\fi % #1 = 0 ?
+ \FPifint#1 ...\else...\fi % #1 is integer ?
+ %repeat last test
+ \ifFPtest ...\else...\fi % repeat last test
+ - fp-addons.sty
+ The following macros are public ones to be used in the document:
+ %binary operations
+ \FPmin#1#2#3 % #1 = min(#2,#3)
+ \FPmax#1#2#3 % #1 = max(#2,#3)
+ - fp-eqn.sty (No warranty on correctness and especially on numerical problems!)
+ The following macros are public ones to be used in the document:
+ \FPlsolve#1#2#3
+ % #1 := x with #2*x+#3=0
+ \FPqsolve#1#2#3#4#5
+ % #1,#2 := x with #3*x^2+#4*x+#5 = 0
+ \FPcsolve#1#2#3#4#5#6#7
+ % #1,#2,#3 := x with #4*x^3+#5*x^2+#6*x+#7 = 0
+ \FPqqsolve#1#2#3#4#5#6#7#8#9
+ % #1,#2,#3,#4 := x with #5*x^4+#6*x^3+#7*x^2+#8*x+#9 = 0
+ The resulting solutions are all real values. If there do not
+ exist as much solutions you get a warning message and some
+ other solutions occur several times in the solution vector.
+ - fp-exp.sty
+ The following macros are public ones to be used in the document:
+ \FPe % 2.718281828459045235
+ \FPexp#1#2 % #1 := e^(#2)
+ \FPln#1#2 % #1 := ln(#2)
+ \FPpow#1#2#3 % #1 := (#2)^(#3)
+ \FProot#1#2#3 % #1 := (#2)^(1/#3)
+ - fp-random.sty
+ The following macros are public ones to be used in the document:
+ \FPseed=#1 % set seed counter for random number generation
+ \FPrandom#1 % #1 := a random number between 0 and 1
+ - fp-pas.sty
+ The following macros are public ones to be used in the document:
+ \FPpascal#1#2 % #1 := #2-th line of the pascal triangle
+ - fp-snap.sty:
+ The following macros are public ones to be used in the document:
+ \FPround#1#2#3 % #1 := #2 rounded to #3 digits after '.'
+ \FPtrunc#1#2#3 % #1 := #2 truncated to #3 digits after '.'
+ \FPclip#1#2 % #1 := #2 with all unnecessary 0's removed
+ - fp-trigo.sty:
+ The following macros are public ones to be used in the document:
+ \FPpi % 3.141592653589793238
+ \FPsin#1#2 % #1 := sin(#2)
+ \FPcos#1#2 % #1 := cos(#2)
+ \FPsincos#1#2#3 % #1 := sin(#3), #2 := cos(#3)
+ \FPtan#1#2 % #1 := tan(#2)
+ \FPcot#1#2 % #1 := cot(#2)
+ \FPtancot#1#2#3 % #1 := tan(#3), #2 := cot(#3)
+ \FParcsin#1#2 % #1 := arcsin(#2)
+ \FParccos#1#2 % #1 := arccos(#2)
+ \FParcsincos#1#2#3 % #1 := arcsin(#3), #2 := arccos(#3)
+ \FParctan#1#2 % #1 := arctan(#2)
+ \FParccot#1#2 % #1 := arccot(#2)
+ \FParctancot#1#2#3 % #1 := arctan(#3), #2 := arccot(#3)
+ - fp-upn.sty:
+ The following macros are public ones to be used in the document:
+ \FPupn#1#2 % #1 := eval(#2) where eval evaluates the
+ upn-expression #2
+ Known operations are:
+ +,add,-,sub,*,mul,/,div,abs,neg,min,max,
+ round,trunc,clip,e,exp,ln,pow,root,pi,sin,cos,
+ sincos,tan,cot,tancot,arcsin,arccos,arcsincos,
+ arctan,arccot,arctancot,pop,swap,copy
+ where
+ pop removes the top element
+ swap exchanges the first two elements
+ copy copies the top element
+ Example 1:
+ The macro call
+ \FPupn\result{17 2.5 + 17.5 - 2 1 + * 2 swap /}
+ is equivalent to
+ \result := ((17.5 - (17 + 2.5)) * (2 + 1)) / 2
+ and evaluates to
+ \def\result{-3.000000000000000000}
+ Afterwards the macro call
+ \FPupn\result{\result{} -1 * 0.2 + sin 2 round}
+ ^^ the "{}" is necessary!
+ is equivalent to
+ \result := round_2(sin((\result * -1) + 0.2))
+ and evaluates to
+ \def\result{-0.06}
+ Example 2:
+ As "result" is an abbreviation of "\result{}" you may
+ write
+ \FPupn{result}{17 2.5 + 17.5 - 2 1 + * 2 swap /}
+ and
+ \FPupn{result}{result -1 * 0.2 + sin 2 round}
+ instead leading to the same results.
+ This is even true for other macro names using e.g. "x" for "\x{}"
+ and so on. But be careful with it. We may introduce new constants
+ in further versions overwriting these abbreviations.
+ - fp-eval.sty:
+ The following macros are public ones to be used in the document:
+ \FPeval#1#2 % #1 := eval(#2) where eval evaluates the
+ expression #2
+ ATTENTION: Do not use macro names with \. for its own
+ Use only the name or the macro surrounded by (, and ) instead,
+ i.e. do not write "\value{}" but "value" or "(\value)".
+ This is needed to avoid problems with a prefix "-" of numbers.
+ (I do not intend to write a more complex parsing routine in future.
+ But if you do so, just send it to me.
+ )
+ Known infix operations are
+ +, -, *, /, ^ for add, sub, mul, div, pow
+ Each other operation is a prefix one that needs
+ a (comma or colon seperated) list of subexpressions.
+ Exception: The unary prefix operation - is not known!
+ (Use the function neg instead.)
+ Example 1:
+ With
+ \edef\result{11}
+ and
+ \FPeval\result{round(root(2,sin(result + 2.5)):2)}
+ or
+ \FPeval{result}{round(root(2,sin(result + 2.5)):2)}
+ \result becomes the value 0.90
+ Example 2:
+ \FPeval\result{clip(2*3+5*6)} results to 36
+ \FPeval\result{clip(2*(3+5)*6)} results to 96
+
+KNOWN BUGS:
+ - does not work with multido.sty/multido.tex
+ Reason:
+ multido uses the same macro names \FPadd and \FPsub
+ Recommended Solution:
+ Patch multido.tex, i.e. apply the following substitutions:
+ FPadd -> mdo@FPadd
+ FPsub -> mdo@FPsub
+
+ - incompatibility with french style of babel
+ this only affects macros using the colon (:)
+ Recommended Solution:
+ Load the fp-package before babel with french style
+ Other Possible Solution:
+ Use \catcode`\:=12 after loading babel with french style
+
+ - others:
+ Currently not known, but, though we do not, we could give
+ a warranty of their existence ...
+
+HISTORY:
+ Date By File New Version
+
+ Jan. 14, 2019 Peter Wang documentation V2.1d
+ improved documentation based on the original README.txt, with examples to show the syntax.
+
+ Jan. 14, 2019 Enrico Gregorio `fp-exp.sty' and `lfp.sty` V2.1d
+ Fixed two unprotected end-of-lines in the above files that can, under certain circumstances, add spaces in the output, causing unwanted drifting.
+
+ Oct. 21, 1996 Michael Mehlich fp-upn.sty V2.1c
+ better debug messages (especially giving results of one step computations)
+
+ May. 13, 1996 Michael Mehlich fp-basic.sty V1.2d
+ \newcount and \countdef have interfered each other
+ when the first newcount uses a counter number less
+ than 60, the result has been wrong results when using
+ the package with plain tex (a problem that has been
+ reported by Ricardo Sanchez Carmenes)
+
+ May. 13, 1996 Michael Mehlich all files -
+ problems with unwanted spaces removed
+ (bug reported by Ricardo Sanchez Carmenes)
+
+ May. 28, 1995 Michael Mehlich fp-basic.sty V1.2c
+ modified \FPset and added \FPprint
+
+ Apr. 27, 1995 Michael Mehliche fp-trigo.sty V0.9e
+ incorrect result of sine for 3/2pi fixed
+ (bug reported by Miroslav Balda)
+
+ Apr. 14, 1995 Michael Mehlich fp-trigo.sty V0.9d
+ infinite loop in computing sine and cosine fixed
+ (bug reported by Miroslav Balda)
+
+ Apr. 05, 1995 Michael Mehlich fp-snap.sty V1.0a
+ rounding bug in FPround fixed
+ (bug reported by Miroslav Balda)
+
+ Apr. 04, 1995 Michael Mehlich fp.tex -
+ lfp.sty -
+ a redefinition of \loop..\repeat added not to get into
+ trouble with its behaviour within my macros
+ (bug reported by Miroslav Balda)
+
+ Apr. 04, 1995 Michael Mehlich fp-basic.sty V1.2b
+ added a value introduction command FPset
+
+ Apr. 03, 1995 Michael Mehlich fp-eqn.sty V0.4
+ added solution algorithms for cubic and 4-th degree equations
+
+ Apr. 03, 1995 Michael Mehlich fp-trigo.sty V0.9c
+ added some % at end of lines not to introduce unwanted spaces
+ removed some debug informations that have accidently been left in
+
+ Apr. 03, 1995 Michael Mehlich fp-exp.sty V0.7e
+ added some % at end of lines not to introduce unwanted spaces
+
+ Apr. 03, 1995 Michael Mehlich fp-upn.sty V2.1b
+ fp-eval.sty V0.9a
+ added support of sgn
+
+ Apr. 03, 1995 Michael Mehlich fp-basic.sty V1.2a
+ added new command \FPsgn
+
+ Apr. 02, 1995 Michael Mehlich fp-exp.sty V0.7d
+ bug corrected, power of 0 by f # 0 now is 0 and no longer
+ leads to an error message
+
+ Apr. 02, 1995 Michael Mehlich fp.sty V0.8
+ added fp-eval.sty to list of required packages
+
+ Apr. 02, 1995 Michael Mehlich fp-upn.sty V2.1a
+ some modifications to work with fp-eval.sty
+
+ Apr. 02, 1995 Michael Mehlich fp-eval.sty V0.9
+ inital version
+
+ Mar. 15, 1995 Michael Mehlich fp.sty V0.7a
+ added fp-addons.sty, fp-eqn.sty to list of required packages
+
+ Mar. 15, 1995 Michael Mehlich fp-eqn.sty V0.2
+ initial version
+
+ Mar. 15, 1995 Michael Mehlich fp-exp.sty V0.7c
+ bug corrected, root of 0 now is 0 and no longer leads to
+ an error message
+
+ Mar. 15, 1995 Michael Mehlich fp-upn.sty V2.1
+ allow macros to be given without \ and {} surrounding
+ support of min, max added
+
+ Mar. 15, 1995 Michael Mehlich fp-addons.sty V0.1
+ initial version
+
+ Feb. 23, 1995 Denis Girou fp-random.sty V1.0a
+ more elaborated comments
+
+ Feb. 21, 1995 Michael Mehlich fp-trigo.sty V0.9b
+ corrected overflow test for arcsin and arccos
+
+ Feb. 18, 1995 Michael Mehlich fp-upn.sty V2.0
+ added debug messages for fp-upn.sty
+ (recommended by Denis Girou)
+
+ Feb. 18, 1995 Michael Mehlich fp.sty V0.7
+ added fp-random.sty to list of required packages
+
+ Feb. 18, 1995 Michael Mehlich fp-basic.sty V1.2
+ printing fp-messages is conditional only (default: true)
+ introduced macro for printing debug messages (default: do not print)
+ (recommmended by Denis Girou)
+
+ Feb. 18, 1995 Michael Mehlich fp-exp.sty V0.7c
+ corrected bugs in \FP@pow and \FP@root writing messages to
+ ordinary text
+ (reported by Denis Girou)
+
+ Feb. 17, 1995 Denis Girou fp-random.sty V1.0
+ introduced
+
+ Feb. 17, 1995 Michael Mehlich fp-basic.sty V1.1f
+ corrected \FP@strip introduced in version V1.1e
+ as it has to but did not hande + and -
+
+ Feb. 17, 1995 Michael Mehlich fp-basic.sty V1.1e
+ corrected \FP@strip introduced in version V1.1d
+ as it has to but did not hande empty parameters
+
+ Feb. 17, 1995 Michael Mehlich fp-basic.sty V1.1d
+ bug in scanning numbers by \FP@readvalue in connection
+ with number-macros of \FPupn corrected
+ (thanks for Denis Girou reporting this bug)
+
+ Nov. 19, 1994 Michael Mehlich fp.sty V0.6
+ package date changed
+
+ Nov. 19, 1994 Michael Mehlich fp-basic.sty V1.1c
+ bug in \FP@correctintcounter corrected
+
+ Nov. 19, 1994 Michael Mehlich fp-upn.sty V1.1
+ handling of arctan, arccot, arctancot added
+
+ Nov. 19, 1994 Michael Mehlich fp-trigo.sty V0.9a
+ \FParctan, \FParccot, \FParctancot added
+
+ Oct. 27, 1994 Michael Mehlich lfp.sty -
+ introduced
+
+ Oct. 27, 1994 Michael Mehlich fp.tex -
+ introduced
+
+ Oct. 15, 1994 Michael Mehlich readme.fp -
+ this history changed for better readability
+
+ Oct. 15, 1994 Michael Mehlich fp-exp.sty V0.7b
+ subtraction bug in \FP@@exp corrected
+
+ Oct. 15, 1994 Michael Mehlich fp-basic.sty V1.1b
+ subtraction in \FP@counttimes changed
+
+ Oct. 15, 1994 Michael Mehlich fp-trigo.sty V0.7b
+ error message, if \FP@modtwopi does not lead to correct result
+ (this shouldn't be possible)
+ subtraction in \FP@@cos corrected
+
+ Oct. 12, 1994 Michael Mehlich fp.sty V0.5b
+ prevent files included from sending messages
+
+ Oct. 12, 1994 Michael Mehlich readme.fp -
+ changed entry for defpattern.sty in this history to reflect
+ original source for defpattern.sty
+
+ Oct. 12, 1994 Michael Mehlich defpattern.sty -
+ source notice in message corrected
+
+ Oct. 12, 1994 Michael Mehlich fp-exp.sty -
+ start message for \FPpow changed
+
+ Oct. 12, 1994 Michael Mehlich fp-trigo.sty -
+ unnecessary \typeout removed
+
+ Oct. 3, 1994 Michael Mehlich, fp.sty V0.5
+ additional styles included by fp.sty
+
+ Oct. 3, 1994 Michael Mehlich fp-upn.sty V1.0
+ first version
+
+ Oct. 3, 1994 Michael Mehlich defpattern.sty -
+ modification of the \howto-macro in TeX and TUG NEWS
+ from an article by Alan Jeffrey
+ no version number, no copyright (public domain)
+ TeX and TUG News 2(2) writes in the section "Mission Statement":
+ "The entire contents of this newsletter are being placed in
+ the public domain."
+
+ Oct. 3, 1994 Michael Mehlich fp-basic.sty V1.1
+ bug in \FPadd corrected
+
+ Aug. 29, 1994 Michael Mehlich fp.sty V0.3
+ additional styles included by fp.sty
+
+ Aug. 29, 1994 Michael Mehlich fp-trigo.sty V0.7
+ first version
+
+ Aug. 29, 1994 Michael Mehlich fp-pas.sty V1.0
+ first version
+
+ Aug. 29, 1994 Michael Mehlich fp-exp.sty V0.7
+ first version
+
+ Aug. 12, 1994 Michael Mehlich fp.sty V0.2
+ first version
+
+ Aug. 10, 1994 Michael Mehlich fp-snap.sty V1.0
+ first version
+
+ Apr. 20, 1994 Michael Mehlich fp-basic.sty V1.0
+ \FPabs added
+
+ Apr. 12, 1994 Michael Mehlich fp-basic.sty V0.99
+ division algorithm added
+
+ Feb. 03, 1994 Michael Mehlich fp-basic.sty V0.8
+ all macros are completely rewritten to be able to use an increased
+ range of numbers
+
+ Jan. 18, 1994 Michael Mehlich fp-basic.sty V0.2
+ bug in \FP@store corrected
+
+ Jan. 17, 1994 Michael Mehlich fp-basic.sty V0.1
+ the file realcalc.tex V1.0, (C) Frank Buchholz has been renamed to
+ fp-basic.sty V0.1 with all macros renamed, \@trunc removed
+
+COPYING:
+ - Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice, the above history with your
+ modifications added, and this permission notice appear in all copies
+ and modified versions.
+ - The copyright holder disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability and
+ fitness, in no event shall the copyright holder be liable for any
+ special, indirect or consequential damages or any damages whatsoever
+ resulting from loss of use, data or profits, whether in an action of
+ contract, negligence or other tortious action, arising out of or in
+ connection with the use or performance of this software.
diff --git a/macros/latex/contrib/fp/defpattern.sty b/macros/latex/contrib/fp/defpattern.sty
new file mode 100644
index 0000000000..1d5787ff13
--- /dev/null
+++ b/macros/latex/contrib/fp/defpattern.sty
@@ -0,0 +1,31 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{defpattern}[1994/10/12]
+
+\message{%
+ `\string\defpattern-macro (adapted from \string\howto\space (A. Jeffrey: TeX and TUG NEWS 2(2)))'%
+}
+
+%define a macro \defpattern for defining ML-like pattern matching macros
+%adapted from the \howto-macro from tugboat
+
+\def\xcs#1#2{\expandafter#1\csname#2\endcsname}
+\newcount\actioncount
+\def\defpattern#1[#2]#3{%
+ \xcs\ifx{\expandafter\gobble\string#1}\relax%
+ \def#1{\erroraction#1}\fi%
+ \advance\actioncount by 1\relax%
+ \expandafter\defaction\expandafter{#1}{#3}{#2}%
+ \def\temp##1##2##3##4##5##6##7##8##9{\def\temp{[#2]}}%
+ \temp\empty\empty\empty\empty\empty\empty\empty\empty\empty%
+ \edef#1{\noexpand\doaction\xcs\noexpand%
+ {action-\the\actioncount}\temp}}
+\def\defaction#1#2#3{%
+ \xcs\def{action-\the\actioncount}##1[#3]{\applyto{#1}{#2}}}
+\def\gobble#1{}
+\def\applyto#1#2#3{#3{#1}{#2}}
+\def\doaction#1[#2][#3]{#1[#3]\success[#2]\failure[#3]}
+\def\success#1#2[#3]\failure[#4]{#2}
+\def\failure#1#2{#1}
+\def\erroraction#1[#2]{%
+ \errmessage{I don't know how to \string#1[#2]}}
+
diff --git a/macros/latex/contrib/fp/documentation.pdf b/macros/latex/contrib/fp/documentation.pdf
new file mode 100644
index 0000000000..3c44ce904d
--- /dev/null
+++ b/macros/latex/contrib/fp/documentation.pdf
Binary files differ
diff --git a/macros/latex/contrib/fp/fp-addons.sty b/macros/latex/contrib/fp/fp-addons.sty
new file mode 100644
index 0000000000..d91057d2eb
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-addons.sty
@@ -0,0 +1,66 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-addons}[1995/03/15]
+
+\def\FP@addonsversion{0.1}
+\message{%
+ `Fixed Point Arithmetic Addons',\space%
+ Version \FP@addonsversion\space%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space\space%
+}
+
+%%%public area (macros which may be used)%%%
+
+\def\FPmin#1#2#3{\FP@min#1{#2}{#3}} % #1:=min(#2,#3)
+\def\FPmax#1#2#3{\FP@max#1{#2}{#3}} % #1:=max(#2,#3)
+
+%%%private fp-area (don't use these macros)%%%
+
+%compute minimum of two values
+\def\FP@min#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 value one
+ % #3 value two
+ \FP@beginmessage{MIN}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPiflt{#2}{#3}%
+ \edef\FP@tmp{#2}%
+ \else%
+ \edef\FP@tmp{#3}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute maximum of two values
+\def\FP@max#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 value one
+ % #3 value two
+ \FP@beginmessage{MAX}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifgt{#2}{#3}%
+ \edef\FP@tmp{#2}%
+ \else%
+ \edef\FP@tmp{#3}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
diff --git a/macros/latex/contrib/fp/fp-basic.sty b/macros/latex/contrib/fp/fp-basic.sty
new file mode 100644
index 0000000000..8091f63b5c
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-basic.sty
@@ -0,0 +1,1121 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-basic}[1996/05/13]
+
+%version information
+\def\FP@basicversion{1.2d}
+\message{%
+ `Basic Fixed Point Arithmetic',\space\space%
+ Version \FP@basicversion%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%fixed point arithmetic with values between (including)
+% -999999999999999999.999999999999999999
+% and +999999999999999999.999999999999999999
+
+
+
+%%%public area (macros which may be used)%%%
+
+%introduce and print new values
+\def\FPset#1#2{\FP@set[#1|#2]}
+\def\FPprint#1{\FP@print[#1]}
+
+%binary operations
+\def\FPadd#1#2#3{\FP@callc\FP@add#1{#2}{#3}+\relax} % #1 := #2+#3
+\def\FPdiv#1#2#3{\FP@callc\FP@div#1{#2}{#3}} % #1 := #2/#3
+\def\FPmul#1#2#3{\FP@callc\FP@mul#1{#2}{#3}} % #1 := #2*#3
+\def\FPsub#1#2#3{\FP@callc\FP@add#1{#2}{-#3}-\relax}% #1 := #2-#3
+%unary operations
+\def\FPabs#1#2{\FP@calld\FP@abs#1{#2}} % #1 := abs(#2)
+\def\FPneg#1#2{\FP@calld\FP@neg#1{#2}} % #1 := -#2
+\def\FPsgn#1#2{\FP@calld\FP@sgn#1{#2}} % #1 := sgn(#2)
+%binary relations
+\def\FPiflt#1#2{\FP@callb\FP@iflt{#1}{#2}+\relax} % #1 < #2 ?
+\def\FPifeq#1#2{\FP@callb\FP@ifeq{#1}{#2}} % #1 = #2 ?
+\def\FPifgt#1#2{\FP@callb\FP@iflt{#2}{#1}-\relax} % #1 > #2 ?
+%unary relations
+\def\FPifneg#1{\FP@calla\FP@ifneg{#1}} % #1 < 0 ?
+\def\FPifpos#1{\FP@calla\FP@ifpos{#1}} % #1 >= 0 ?
+\def\FPifzero#1{\FP@calla\FP@ifzero{#1}} % #1 = 0 ?
+\def\FPifint#1{\FP@calla\FP@ifint{#1}} % #1 is integer ?
+%repeat last test
+%\ifFPtest % repeat last test
+
+%%%private fp-area (don't use these macros)%%%
+
+% To debug FP functions (enable intermediate messages on computations)
+\newif\ifFPdebug
+\FPdebugfalse
+\def\FP@debug#1{\ifFPdebug\typeout{FP debug: #1}\fi}
+
+%conditional printing of messages (only if \FPmessagestrue defined)
+\newif\ifFPmessages
+\FPmessagestrue
+\def\FP@beginmessage#1{\ifFPmessages\message{( FP-#1}\fi}
+\def\FP@endmessage#1{\ifFPmessages\message{)}\fi}
+\def\FP@errmessage#1{\errmessage{FP error: #1!}}
+\def\FP@warnmessage#1{\message{FP warning: #1!}}
+
+%allocation of registers
+
+\countdef\FP@actcounter=10 % register 0 for counter
+\ifnum\FP@actcounter<60\relax%
+ \FP@actcounter=60%
+\fi
+
+\newcount\FP@xs %sign of 1st value
+\newcount\FP@xia%integer part of 1st value
+\newcount\FP@xib%integer part of 1st value
+\newcount\FP@xfa%fractional part of 1st value
+\newcount\FP@xfb%fractional part of 1st value
+
+\countdef\FP@ys=5 %sign of 2nd value
+\countdef\FP@yia=6%integer part of 2nd value
+\countdef\FP@yib=7%integer part of 2nd value
+\countdef\FP@yfa=8%fractional part of 2nd value
+\countdef\FP@yfb=9%fractional part of 2nd value
+
+\countdef\FP@xk=10 %registers for splitting 1st value
+\countdef\FP@xl=11
+\countdef\FP@xm=12
+\countdef\FP@xn=13
+\countdef\FP@xo=14
+\countdef\FP@xp=15
+\countdef\FP@xq=16
+\countdef\FP@xr=17
+\countdef\FP@xz=18
+\countdef\FP@xt=19
+\countdef\FP@xu=20
+\countdef\FP@xv=21
+
+\countdef\FP@yk=22 %registers for splitting 2nd value
+\countdef\FP@yl=23
+\countdef\FP@ym=24
+\countdef\FP@yn=25
+\countdef\FP@yo=26
+\countdef\FP@yp=27
+\countdef\FP@yq=28
+\countdef\FP@yr=29
+\countdef\FP@yz=30
+\countdef\FP@yt=31
+\countdef\FP@yu=32
+\countdef\FP@yv=33
+
+\newcount\FP@rega %auxiliary registers
+\newcount\FP@regb
+\countdef\FP@regc=36
+\countdef\FP@regd=37
+\countdef\FP@rege=38
+
+\countdef\FP@rs=39 %result registers
+\countdef\FP@ria=40
+\countdef\FP@rib=41
+\countdef\FP@rfa=42
+\countdef\FP@rfb=43
+
+\newcount\FP@regs %local auxiliary registers
+\countdef\FP@count=45
+\countdef\FP@res=46
+\countdef\FP@shift=47
+\newcount\FP@times
+\countdef\FP@prod=49
+
+%set values
+\def\FP@set[#1#2|#3#4]{%
+ \ifx#3\@undefined%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\FP@tmp\expandafter\expandafter\expandafter{\csname #3#4\endcsname}%
+ \else\ifcat\noexpand#3\relax%
+ \expandafter\def\expandafter\FP@tmp\expandafter{#3#4}%
+ \else\ifcat#32\relax%
+ \expandafter\def\expandafter\FP@tmp\expandafter{#3#4}%
+ \else%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\FP@tmp\expandafter\expandafter\expandafter{\csname #3#4\endcsname}%
+ \fi\fi\fi%
+ \ifx#1\@undefined%
+ \let#1\FP@tmp%
+ \else\ifcat\noexpand#1\relax%
+ \let#1\FP@tmp%
+ \else%
+ \expandafter\let\csname #1#2\endcsname\FP@tmp%
+ \fi\fi%
+}
+
+%print values
+\def\FP@print[#1#2]{%
+ \ifx#1\@undefined%
+ \csname #1#2\endcsname%
+ \else\ifcat\noexpand#1\relax%
+ #1#2%
+ \else\ifcat#12\relax%
+ #1#2%
+ \else%
+ \csname #1#2\endcsname%
+ \fi\fi\fi%
+}
+
+%auxiliary macros which may be used in all of the following macros
+\newif\ifFP@test
+
+\def\FP@ignorenext#1{}
+\def\FP@first#1#2\relax{#1}
+\def\FP@swallow#1\relax{}
+
+\def\ifFP@zero#1{%
+ \ifnum%
+ \expandafter\ifnum\csname FP@#1ia\endcsname=0 0\else1\fi%
+ \expandafter\ifnum\csname FP@#1ib\endcsname=0 0\else1\fi%
+ \expandafter\ifnum\csname FP@#1fa\endcsname=0 0\else1\fi%
+ \expandafter\ifnum\csname FP@#1fb\endcsname=0 0\else1\fi%
+ =0\relax%
+}
+
+%read value
+
+\def\FP@correctintcounter#1\relax{%
+ {\edef\FP@tmp{#1}%
+ \FP@count=0\relax%
+ \loop%
+ \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \expandafter\ifx\FP@tmpa0\relax%
+ \advance\FP@count1\relax%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \repeat%
+ \ifnum\FP@count>18\relax%
+ \FP@errmessage{Overflow}%
+ \fi%
+ \expandafter\if!\FP@tmp!%
+ \advance\FP@count-18\relax%
+ \FP@count=-\FP@count%
+ \loop%
+ \ifnum\FP@count>0\relax%
+ \FP@regc=\FP@rega%
+ \divide\FP@rega10\relax\multiply\FP@rega10\relax%
+ \advance\FP@regc-\FP@rega\multiply\FP@regc100000000\relax%
+ \divide\FP@rega10\relax%
+ \divide\FP@regb10\relax\advance\FP@regb\FP@regc%
+ \advance\FP@count-1\relax%
+ \repeat%
+ \global\FP@rega=\FP@rega%
+ \global\FP@regb=\FP@regb%
+ \else%
+ \FP@errmessage{Number too big}%
+ \fi%
+ }%
+}
+\def\FP@@setintcounter#1#2#3#4#5#6#7#8#9{%
+ \FP@regb=#1#2#3#4#5#6#7#8#9\relax%
+ \FP@correctintcounter%
+}
+\def\FP@setintcounter#1#2#3#4#5#6#7#8#9{%
+ \FP@rega=#1#2#3#4#5#6#7#8#9\relax%
+ \FP@@setintcounter%
+}
+
+\def\FP@@setfractcounter#1#2#3#4#5#6#7#8#9{%
+ \FP@regb=#1#2#3#4#5#6#7#8#9\relax%
+ \FP@swallow%
+}
+\def\FP@setfractcounter#1#2#3#4#5#6#7#8#9{%
+ \FP@rega=#1#2#3#4#5#6#7#8#9\relax%
+ \FP@@setfractcounter%
+}
+
+\def\FP@getsign#1\relax{%
+ {\FP@regs=1\relax%
+ \edef\FP@tmp{#1}%
+ \loop%
+ \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \expandafter\ifx\FP@tmpa-\relax%
+ \multiply\FP@regs-1\relax%
+ \fi%
+ \ifnum\expandafter\ifx\FP@tmpa-1\else0\fi\expandafter\ifx\FP@tmpa+1\else0\fi>0%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \repeat%
+ \global\let\FP@tmp\FP@tmp%
+ \global\FP@regs=\FP@regs%
+ }%
+}
+
+\def\FP@removeleadingzeros#1\relax{%
+ {\edef\FP@tmp{#1}%
+ \loop%
+ \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \expandafter\ifx\FP@tmpa0\relax%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \repeat%
+ \global\let\FP@tmp\FP@tmp%
+ }%
+}
+
+\newif\ifFP@nonstop
+\def\FP@strip#1{%
+ {\edef\FP@tmp{#1}%
+ \edef\FP@tmpb{}%
+ \ifx\FP@tmp\@empty\else%
+ \FP@nonstoptrue%
+ \loop%
+ \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \expandafter\ifx\FP@tmpa-\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa+\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa0\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa1\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa2\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa3\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa4\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa5\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa6\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa7\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa8\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \expandafter\ifx\FP@tmpa9\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
+ \ifx\FP@tmpa\@empty\FP@nonstopfalse\else%
+ \ifx\FP@tmpa\space\FP@nonstopfalse\else%
+ \FP@errmessage{Illegal character \FP@tmpa\space found in float number}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \ifx\FP@tmp\@empty\FP@nonstopfalse\fi%
+ \ifFP@nonstop%
+ \repeat%
+ \fi%
+ \global\let\FP@tmp\FP@tmpb%
+ }%
+}
+
+\def\FP@readvalue#1#2#3{%
+ % #1 macro family to catch the value
+ % #2.#3 value
+ %
+ % regular expression [+|-]*[d]_0^18.[d]*
+ %
+ \FP@strip{#2}%
+ %sign
+ \expandafter\FP@getsign\FP@tmp\relax%
+ \csname FP@#1s\endcsname=\FP@regs%
+ %
+ %integer part
+ \FP@removeleadingzeros\FP@tmp\relax%
+ \expandafter\FP@setintcounter\FP@tmp000000000000000000\relax%
+ \csname FP@#1ia\endcsname=\FP@rega%
+ \csname FP@#1ib\endcsname=\FP@regb%
+ %
+ %fractional part
+ \FP@strip{#3}%
+ \expandafter\FP@setfractcounter\FP@tmp000000000000000000\relax%
+ \csname FP@#1fa\endcsname=\FP@rega%
+ \csname FP@#1fb\endcsname=\FP@regb%
+ %
+ %correct sign
+ \ifnum\FP@rega=0\relax%
+ \ifnum\FP@regb=0\relax%
+ \expandafter\ifnum\csname FP@#1ib\endcsname=0\relax%
+ \expandafter\ifnum\csname FP@#1ia\endcsname=0\relax%
+ \csname FP@#1s\endcsname=1\relax%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+}
+
+%store value in macro
+
+\def\FP@store#1#2{%
+ % #1 macro
+ % #2 macro family (value) to store
+ %
+ \ifFP@zero{#2}%
+ \csname FP@#2s\endcsname=1\relax%
+ \fi%
+ \expandafter\ifnum\csname FP@#2s\endcsname<0\relax%
+ \edef#1{-}%
+ \else%
+ \edef#1{}%
+ \fi%
+ \expandafter\ifnum\csname FP@#2ia\endcsname=0\relax%
+ \expandafter\ifnum\csname FP@#2ib\endcsname=0\relax%
+ \edef#1{#10}%
+ \else%
+ \edef#1{#1\expandafter\the\csname FP@#2ib\endcsname}%
+ \fi%
+ \else%
+ \expandafter\advance\csname FP@#2ib\endcsname1000000000\relax%
+ \edef#1{#1\expandafter\the\csname FP@#2ia\endcsname\expandafter\FP@ignorenext\the\csname FP@#2ib\endcsname}%
+ \fi%
+ \expandafter\advance\csname FP@#2fa\endcsname1000000000\relax%
+ \expandafter\advance\csname FP@#2fb\endcsname1000000000\relax%
+ \edef#1{#1\noexpand.\expandafter\FP@ignorenext\the\csname FP@#2fa\endcsname\expandafter\FP@ignorenext\the\csname FP@#2fb\endcsname}%
+}
+
+%macros to expand some arguments
+
+\def\FP@calla#1#2{%
+ % #1 macro to call
+ % #2 value
+ % expand the value and split them into the integer and the fractional part
+ \edef\next{\noexpand#1#2..\noexpand\relax}%
+ \next%
+}
+
+\def\FP@callb#1#2#3{%
+ % #1 macro to call
+ % #2 1st value
+ % #3 2nd value
+ % expand the values and split them into the integer and the fractional parts
+ \edef\next{\noexpand#1#2..\noexpand\relax#3..\noexpand\relax}%
+ \next%
+}
+
+\def\FP@callc#1#2#3#4{%
+ % #1 macro to call
+ % #2 macro, which gets the result
+ % #3 1st value
+ % #4 2nd value
+ % expand the values and split them into the integer and the fractional parts
+ \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax#4..\noexpand\relax}%
+ \next%
+}
+
+\def\FP@calld#1#2#3{%
+ % #1 macro to call
+ % #2 macro, which gets the result
+ % #3 value
+ \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax}%
+ \next%
+}
+
+\def\FP@calle#1#2#3#4{%
+ % #1 macro to call
+ % #2 macro, which gets the first result
+ % #3 macro, which gets the second result
+ % #4 value
+ \edef\next{\noexpand#1\noexpand#2\noexpand#3#4..\noexpand\relax}%
+ \next%
+}
+
+%add two values
+
+\def\FP@add#1#2.#3.#4\relax#5.#6.#7\relax#8\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of 1st value
+ % #3 fractional part of 1st value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ % #5 integer part of 2nd value
+ % #6 fractional part of 2nd value
+ % #7 dummy to swallow everthing after the 2nd '.'
+ %
+ {\ifx#8+\relax%
+ \FP@beginmessage{ADD}%
+ \else%
+ \FP@beginmessage{SUB}%
+ \fi%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ \FP@readvalue{y}{#5}{#6}%
+ %
+ \ifnum\FP@xs=\FP@ys%
+ \advance\FP@xfb\FP@yfb%
+ \advance\FP@xfa\FP@yfa%
+ \ifnum\FP@xfb<1000000000\relax\else%
+ \advance\FP@xfb-1000000000\relax%
+ \advance\FP@xfa1\relax%
+ \fi%
+ \advance\FP@xib\FP@yib%
+ \ifnum\FP@xfa<1000000000\relax\else%
+ \advance\FP@xfa-1000000000\relax%
+ \advance\FP@xib1\relax%
+ \fi%
+ \advance\FP@xia\FP@yia%
+ \ifnum\FP@xib<1000000000\relax\else%
+ \advance\FP@xib-1000000000\relax%
+ \advance\FP@xia1\relax%
+ \fi%
+ \ifnum\FP@xia<1000000000\relax\else%
+ \FP@errmessage{Overflow}%
+ \fi%
+ \FP@store\FP@tmp{x}%
+ \else%
+ \advance\FP@xfb-\FP@yfb%
+ \ifnum\FP@xfb<0\relax%
+ \advance\FP@yfa1\relax%
+ \advance\FP@xfb1000000000\relax%
+ \fi%
+ \advance\FP@xfa-\FP@yfa%
+ \ifnum\FP@xfa<0\relax%
+ \advance\FP@yib1\relax%
+ \advance\FP@xfa1000000000\relax%
+ \fi%
+ \advance\FP@xib-\FP@yib%
+ \ifnum\FP@xib<0\relax%
+ \advance\FP@yia1\relax%
+ \advance\FP@xib1000000000\relax%
+ \fi%
+ \advance\FP@xia-\FP@yia%
+ \ifnum\FP@xia<0\relax%
+ \FP@xs=-\FP@xs%
+ \ifnum\FP@xfb=0\relax\else%
+ \advance\FP@xfb-1000000000\relax\FP@xfb=-\FP@xfb%
+ \advance\FP@xfa1\relax%
+ \fi%
+ \ifnum\FP@xfa=0\relax\else%
+ \advance\FP@xfa-1000000000\relax\FP@xfa=-\FP@xfa%
+ \advance\FP@xib1\relax%
+ \fi%
+ \ifnum\FP@xib=0\relax\else%
+ \advance\FP@xib-1000000000\relax\FP@xib=-\FP@xib%
+ \advance\FP@xia1\relax%
+ \fi%
+ \relax\FP@xia=-\FP@xia%
+ \fi%
+ \FP@store\FP@tmp{x}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%multiply two values
+
+\def\FP@firstnine#1#2#3#4#5#6#7#8#9{%
+ \FP@res=#1#2#3#4#5#6#7#8#9\relax%
+}
+\def\FP@@ninesplit#1\relax#2\end#3{%
+ #1%
+ \edef#3{#2}%
+}
+\def\FP@ninesplit#1{%
+ \edef#1{\expandafter\FP@firstnine\FP@rd}%
+ \expandafter\FP@@ninesplit#1\end#1\relax%
+}
+
+\def\FP@split#1#2#3#4{%
+ % #1 highest three digits
+ % #2 medium three digits
+ % #3 least three digits
+ % #4 counter
+ \FP@regc=#4%
+ \divide\FP@regc1000000\relax%
+ #1=\FP@regc%
+ \multiply\FP@regc-1000000\relax\advance\FP@regc#4%
+ #3=\FP@regc%
+ \divide\FP@regc1000\relax%
+ #2=\FP@regc%
+ \multiply\FP@regc-1000\relax\advance\FP@regc#3%
+ #3=\FP@regc%
+}
+
+\def\FP@@mul#1#2#3{%
+ \FP@regc=\csname FP@x#1\endcsname%
+ \multiply\FP@regc\csname FP@y#2\endcsname%
+ \advance\FP@prod\FP@regc%
+ %
+ \ifx#3\relax%
+ \let\next=\relax%
+ \else%
+ \let\next=\FP@@mul%
+ \fi%
+ \next#3%
+}
+
+\def\FP@saveshift{%
+ % save rightmost three digits
+ \FP@regc=\FP@prod%
+ \divide\FP@prod1000\relax%
+ \multiply\FP@prod1000\relax%
+ \advance\FP@regc-\FP@prod%
+ \advance\FP@regc1000\relax%
+ \edef\FP@rd{\expandafter\FP@ignorenext\the\FP@regc\FP@rd}%
+ %
+ \divide\FP@prod1000\relax%
+}
+
+\def\FP@mul#1#2.#3.#4\relax#5.#6.#7\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of 1st value
+ % #3 fractional part of 1st value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ % #5 integer part of 2nd value
+ % #6 fractional part of 2nd value
+ % #7 dummy to swallow everthing after the 2nd '.'
+ %
+ % split value in various parts
+ % x y = 123 456 789 123 456 789 . 123 456 789 123 456 789
+ % -> xk xl xm xn xo xp xq xr xs xt xu xv
+ % -> yk yl ym yn yo yp yq yr ys yt yu yv
+ % multiply these parts and save the result wrt the necessary shifts
+ %
+ {\FP@beginmessage{MUL}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ \FP@readvalue{y}{#5}{#6}%
+ %
+ %sign
+ \multiply\FP@xs\FP@ys%
+ \FP@rs=\FP@xs%
+ %
+ % split parts
+ \FP@split\FP@xk\FP@xl\FP@xm\FP@xia\FP@split\FP@xn\FP@xo\FP@xp\FP@xib%
+ \FP@split\FP@xq\FP@xr\FP@xz\FP@xfa\FP@split\FP@xt\FP@xu\FP@xv\FP@xfb%
+ \FP@split\FP@yk\FP@yl\FP@ym\FP@yia\FP@split\FP@yn\FP@yo\FP@yp\FP@yib%
+ \FP@split\FP@yq\FP@yr\FP@yz\FP@yfa\FP@split\FP@yt\FP@yu\FP@yv\FP@yfb%
+ %
+ \FP@prod=0\relax%
+ \edef\FP@rd{}%
+ %
+ %compute result
+ \FP@@mul vv \relax\FP@saveshift%
+ \FP@@mul vu uv \relax\FP@saveshift%
+ \FP@@mul uu vt tv \relax\FP@saveshift%
+ \FP@@mul ut tu vz zv \relax\FP@saveshift%
+ \FP@@mul tt zu uz rv vr \relax\FP@saveshift%
+ \FP@@mul zt tz ur ru vq qv \relax\FP@saveshift%
+ \FP@@mul zz rt tr uq qu vp pv \relax\FP@saveshift%
+ \FP@@mul zr rz tq qt up pu vo ov \relax\FP@saveshift%
+ \FP@@mul rr qz zq tp pt uo ou vn nv \relax\FP@saveshift%
+ \FP@@mul rq qr zp pz to ot un nu vm mv \relax\FP@saveshift%
+ \FP@@mul qq rp pr zo oz tn nt um mu vl lv \relax\FP@saveshift%
+ \FP@@mul qp pq ro or zn nz tm mt ul lu kv vk \relax\FP@saveshift%
+ \FP@@mul pp oq qo rn nr zm mz tl lt ku uk \relax\FP@saveshift%
+ \FP@@mul op po nq qn rm mr zl lz tk kt \relax\FP@saveshift%
+ \FP@@mul oo pn np mq qm rl lr kz zk \relax\FP@saveshift%
+ \FP@@mul no on mp pm lq ql kr rk \relax\FP@saveshift%
+ \FP@@mul nn mo om pl lp qk kq \relax\FP@saveshift%
+ \FP@@mul mn nm lo ok pk kp \relax\FP@saveshift%
+ \FP@@mul mm ln nl ko ok \relax\FP@saveshift%
+ \FP@@mul lm ml kn nk \relax\FP@saveshift%
+ \FP@@mul ll km mk \relax\FP@saveshift%
+ \FP@@mul kl lk \relax\FP@saveshift%
+ \FP@@mul kk \relax\FP@saveshift\FP@saveshift%
+ \FP@ninesplit\FP@rd%
+ \ifnum\FP@res=0\relax%
+ \FP@ninesplit\FP@rd%
+ \ifnum\FP@res=0\relax%
+ \FP@ninesplit\FP@rd\FP@ria=\FP@res%
+ \FP@ninesplit\FP@rd\FP@rib=\FP@res%
+ \FP@ninesplit\FP@rd\FP@rfa=\FP@res%
+ \FP@ninesplit\FP@rd\FP@rfb=\FP@res%
+ \FP@store\FP@tmp{r}%
+ \else%
+ \FP@errmessage{Overflow}%
+ \fi%
+ \else%
+ \FP@errmessage{Overflow}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmp%
+}
+
+%divide one value by another one
+
+\def\FP@divten#1{%
+ \expandafter\FP@regc\csname FP@#1ia\endcsname%
+ \expandafter\divide\csname FP@#1ia\endcsname10\relax%
+ \expandafter\FP@regb\csname FP@#1ia\endcsname%
+ \multiply\FP@regb10\relax%
+ \advance\FP@regc-\FP@regb%
+ \multiply\FP@regc100000000\relax%
+ %
+ \expandafter\FP@rega\csname FP@#1ib\endcsname%
+ \expandafter\divide\csname FP@#1ib\endcsname10\relax%
+ \expandafter\FP@regb\csname FP@#1ib\endcsname%
+ \multiply\FP@regb10\relax%
+ \advance\FP@rega-\FP@regb%
+ \multiply\FP@rega100000000\relax%
+ \expandafter\advance\csname FP@#1ib\endcsname\FP@regc%
+ %
+ \expandafter\FP@regc\csname FP@#1fa\endcsname%
+ \expandafter\divide\csname FP@#1fa\endcsname10\relax%
+ \expandafter\FP@regb\csname FP@#1fa\endcsname%
+ \multiply\FP@regb10\relax%
+ \advance\FP@regc-\FP@regb%
+ \multiply\FP@regc100000000\relax%
+ \expandafter\advance\csname FP@#1fa\endcsname\FP@rega%
+ %
+ \expandafter\divide\csname FP@#1fb\endcsname10\relax%
+ \expandafter\advance\csname FP@#1fb\endcsname\FP@regc%
+}
+
+\def\FP@multen#1{%
+ \expandafter\multiply\csname FP@#1ia\endcsname10\relax%
+ \expandafter\ifnum\csname FP@#1ib\endcsname<100000000\relax%
+ \else%
+ \expandafter\FP@regc\csname FP@#1ib\endcsname%
+ \divide\FP@regc100000000%
+ \expandafter\advance\csname FP@#1ia\endcsname\FP@regc%
+ \multiply\FP@regc100000000%
+ \expandafter\advance\csname FP@#1ib\endcsname-\FP@regc%
+ \fi%
+ \expandafter\multiply\csname FP@#1ib\endcsname10\relax%
+ \expandafter\ifnum\csname FP@#1fa\endcsname<100000000\relax%
+ \else%
+ \expandafter\FP@regc\csname FP@#1fa\endcsname%
+ \divide\FP@regc100000000%
+ \expandafter\advance\csname FP@#1ib\endcsname\FP@regc%
+ \multiply\FP@regc100000000%
+ \expandafter\advance\csname FP@#1fa\endcsname-\FP@regc%
+ \fi%
+ \expandafter\multiply\csname FP@#1fa\endcsname10\relax%
+ \expandafter\ifnum\csname FP@#1fb\endcsname<100000000\relax%
+ \else%
+ \expandafter\FP@regc\csname FP@#1fb\endcsname%
+ \divide\FP@regc100000000%
+ \expandafter\advance\csname FP@#1fa\endcsname\FP@regc%
+ \multiply\FP@regc100000000%
+ \expandafter\advance\csname FP@#1fb\endcsname-\FP@regc%
+ \fi%
+ \expandafter\multiply\csname FP@#1fb\endcsname10\relax%
+}
+
+\def\FP@counttimes{%
+ {\global\FP@times=0\relax%
+ \loop%
+ \ifnum%
+ \ifnum\FP@xia>\FP@yia1%
+ \else\ifnum\FP@xia<\FP@yia0%
+ \else%
+ \ifnum\FP@xib>\FP@yib1%
+ \else\ifnum\FP@xib<\FP@yib0%
+ \else%
+ \ifnum\FP@xfa>\FP@yfa1%
+ \else\ifnum\FP@xfa<\FP@yfa0%
+ \else%
+ \ifnum\FP@xfb>\FP@yfb1%
+ \else\ifnum\FP@xfb<\FP@yfb0%
+ \else%
+ 1%
+ \fi\fi%
+ \fi\fi%
+ \fi\fi%
+ \fi\fi%
+ =1\relax%
+ \global\advance\FP@times1\relax%
+ \global\advance\FP@xfb-\FP@yfb%
+ \ifnum\FP@xfb<0\relax%
+ \global\advance\FP@xfb1000000000\relax%
+ \global\advance\FP@xfa-1\relax%
+ \fi%
+ \global\advance\FP@xfa-\FP@yfa%
+ \ifnum\FP@xfa<0\relax%
+ \global\advance\FP@xfa1000000000\relax%
+ \global\advance\FP@xib-1\relax%
+ \fi%
+ \global\advance\FP@xib-\FP@yib%
+ \ifnum\FP@xib<0\relax%
+ \global\advance\FP@xib1000000000\relax%
+ \global\advance\FP@xia-1\relax%
+ \fi%
+ \global\advance\FP@xia-\FP@yia%
+ \repeat%
+ }%
+}
+
+\def\FP@div#1#2.#3.#4\relax#5.#6.#7\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of 1st value
+ % #3 fractional part of 1st value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ % #5 integer part of 2nd value
+ % #6 fractional part of 2nd value
+ % #7 dummy to swallow everthing after the 2nd '.'
+ %
+ % algorithmic idea (for x>0, y>0)
+ % - %determine \FP@shift such that y*10^\FP@shift <100000000<=y*10^(\FP@shift+1)
+ % - %determine \FP@shift' such that x*10^\FP@shift'<100000000<=x*10^(\FP@shift+1)
+ % - x=x*\FP@shift'
+ % - y=y*\FP@shift
+ % - \FP@shift=\FP@shift-\FP@shift'
+ % - res=0
+ % - while y>0 %fixed-point representation!
+ % - \FP@times=0
+ % - while x>y
+ % - \FP@times=\FP@times+1
+ % - x=x-y
+ % - end
+ % - y=y/10
+ % - res=10*res+\FP@times/1000000000
+ % - end
+ % - %shift the result according to \FP@shift
+ %
+ {\FP@beginmessage{DIV}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ \FP@readvalue{y}{#5}{#6}%
+ %
+ %sign
+ \multiply\FP@xs\FP@ys%
+ \FP@rs=\FP@xs%
+ %
+ %compute division
+ \ifFP@zero{y}%
+ \FP@errmessage{Division by zero}%
+ \else%
+ \ifFP@zero{x}\def\next##1{\edef\FP@tmp{0}}\else\def\next##1{##1}\fi%
+ \next%
+ {\FP@shift=0\relax%
+ \loop%
+ \ifnum\FP@yia<100000000\relax%
+ \FP@multen{y}%
+ \advance\FP@shift1\relax%
+ \repeat%
+ \loop%
+ \ifnum\FP@xia<100000000\relax%
+ \FP@multen{x}%
+ \advance\FP@shift-1\relax%
+ \repeat%
+ \FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
+ \loop%
+ \ifFP@zero{y}\else%
+ \FP@counttimes%divides x by \FP@times*y
+ \FP@divten{y}%
+ \FP@multen{r}%
+ \advance\FP@rfb\FP@times%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\advance\FP@rfb-1000000000\relax%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\advance\FP@rfa-1000000000\relax%
+ \ifnum\FP@rib<1000000000\relax\else%
+ \advance\FP@ria1\advance\FP@rib-1000000000\relax%
+ \fi%
+ \fi%
+ \fi%
+ \repeat%
+ \loop%
+ \ifnum\FP@shift>17%
+ \advance\FP@shift-1\relax%
+ \ifnum\FP@ria<100000000\else\FP@ria=-1\fi%
+ \ifnum\FP@ria<0\FP@ria=-1\fi%
+ \FP@multen{r}%
+ \repeat%
+ \ifnum\FP@ria<1000000000\else\FP@ria=-1\fi%
+ \loop%
+ \ifnum\FP@shift<17%
+ \advance\FP@shift1\relax%
+ \FP@divten{r}%
+ \repeat%
+ \ifnum\FP@ria<0\relax%
+ \FP@errmessage{Overflow}%
+ \else%
+ \FP@store\FP@tmp{r}%
+ \fi%
+ }%
+ \fi%
+ %
+ \global\let\FP@tmp=\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%absolute value
+
+\def\FP@abs#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{ABS}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ \FP@xs=1\relax%
+ \FP@store\FP@tmp{x}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%negate value
+
+\def\FP@neg#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{NEG}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ \multiply\FP@xs-1\relax%
+ \FP@store\FP@tmp{x}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%sign of value
+
+\def\FP@sgn#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{SGN}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ %
+ \ifFP@zero{x}%
+ \edef\FP@tmp{0}%
+ \else%
+ \edef\FP@tmp{\the\FP@xs}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%test if 1st value is less than 2nd value
+
+\def\FP@iflt#1.#2.#3\relax#4.#5.#6\relax#7\relax{%
+ % #1 integer part of 1st value
+ % #2 fractional part of 1st value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ % #4 integer part of 2nd value
+ % #5 fractional part of 2nd value
+ % #6 dummy to swallow everthing after the 2nd '.'
+ %
+ {\ifx#7+\relax%
+ \FP@beginmessage{LT?}%
+ \else%
+ \FP@beginmessage{GT?}%
+ \fi%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ \FP@readvalue{y}{#4}{#5}%
+ %
+ \ifnum\FP@xs<\FP@ys%
+ \FP@testtrue%
+ \else\ifnum\FP@xs>\FP@ys%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xs>0\relax%
+ \ifnum\FP@xia<\FP@yia%
+ \FP@testtrue%
+ \else\ifnum\FP@xia>\FP@yia%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xib<\FP@yib%
+ \FP@testtrue%
+ \else\ifnum\FP@xib>\FP@yib%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xfa<\FP@yfa%
+ \FP@testtrue%
+ \else\ifnum\FP@xfa>\FP@yfa%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xfb<\FP@yfb%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \fi\fi%
+ \fi\fi%
+ \fi\fi%
+ \else%
+ \ifnum\FP@xia>\FP@yia%
+ \FP@testtrue%
+ \else\ifnum\FP@xia<\FP@yia%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xib>\FP@yib%
+ \FP@testtrue%
+ \else\ifnum\FP@xib<\FP@yib%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xfa>\FP@yfa%
+ \FP@testtrue%
+ \else\ifnum\FP@xfa<\FP@yfa%
+ \FP@testfalse%
+ \else%
+ \ifnum\FP@xfb>\FP@yfb%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \fi\fi%
+ \fi\fi%
+ \fi\fi%
+ \fi%
+ \fi\fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
+
+%test if two values are equal
+
+\def\FP@ifeq#1.#2.#3\relax#4.#5.#6\relax{%
+ % #1 integer part of 1st value
+ % #2 fractional part of 1st value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ % #4 integer part of 2nd value
+ % #5 fractional part of 2nd value
+ % #6 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{EQ?}%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ \FP@readvalue{y}{#4}{#5}%
+ %
+ \ifnum\FP@xs=\FP@ys%
+ \ifnum\FP@xia=\FP@yia%
+ \ifnum\FP@xib=\FP@yib%
+ \ifnum\FP@xfa=\FP@yfa%
+ \ifnum\FP@xfb=\FP@yfb%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \else%
+ \FP@testfalse%
+ \fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
+
+%test if value is negative
+
+\def\FP@ifneg#1.#2.#3\relax{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{NEG?}%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifnum\FP@xs<0\relax%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
+
+%test if value is positive
+
+\def\FP@ifpos#1.#2.#3\relax{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{POS?}%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifnum\FP@xs<0\relax%
+ \FP@testfalse%
+ \else%
+ \FP@testtrue%
+ \fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
+
+%test if value is equal to zero
+
+\def\FP@ifzero#1.#2.#3\relax{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{ZERO?}%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifFP@zero{x}%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
+
+%test if value is an integer
+
+\def\FP@ifint#1.#2.#3\relax{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ % #3 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{INT?}%
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifnum\FP@xfa=0\relax%
+ \ifnum\FP@xfb=0\relax%
+ \FP@testtrue%
+ \else%
+ \FP@testfalse%
+ \fi%
+ \else%
+ \FP@testfalse%
+ \fi%
+ %
+ \global\let\ifFP@test\ifFP@test%
+ %
+ \FP@endmessage{}%
+ }%
+ \let\ifFPtest\ifFP@test%
+ %
+ \ifFPtest%
+}
diff --git a/macros/latex/contrib/fp/fp-eqn.sty b/macros/latex/contrib/fp/fp-eqn.sty
new file mode 100644
index 0000000000..9841ff2256
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-eqn.sty
@@ -0,0 +1,382 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-eqn}[1995/04/03]
+
+%version information
+\def\FP@eqnversion{0.4}
+\message{%
+ `Fixed Point Equation Solver',%
+ \space\space\space%
+ Version \FP@eqnversion\space%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp}
+
+%%%public area (macros which may be used)%%%
+
+\def\FPlsolve#1#2#3{\FP@lsolve#1{#2}{#3}} % #1 := x with #2*x+#3=0
+\def\FPqsolve#1#2#3#4#5{\FP@qsolve#1#2{#3}{#4}{#5}} % #1,#2 := x with #3*x^2+#4*x+#5 = 0
+\def\FPcsolve#1#2#3#4#5#6#7{\FP@csolve#1#2#3{#4}{#5}{#6}{#7}}
+ % #1,#2,#3 := x with #4*x^3+#5*x^2+#6*x+#7 = 0
+\def\FPqqsolve#1#2#3#4#5#6#7#8#9{\FP@qqsolve#1#2#3#4{#5}{#6}{#7}{#8}{#9}}
+ % #1,#2,#3,#4 := x with #5*x^4+#6*x^3+#7*x^2+#8*x+#9 = 0
+
+%%%private fp-area (don't use these macros)%%%
+
+%compute the solution of a*x + b = 0
+\def\FP@lsolve@warn#1{%
+ %value determining warning
+ \FPifzero{#1}%
+ \FP@warnmessage{Linear equation has infinitely many solutions, choosing 0}%
+ \edef\FP@tmp{0}%
+ \else%
+ \FP@errmessage{Linear equation does not have a solution}%
+ \fi%
+}
+
+\def\FP@@lsolve#1#2{%
+ \FPdiv\FP@tmp{#2}{#1}%
+ \FPneg\FP@tmp\FP@tmp%
+}
+
+\def\FP@lsolve#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 value a
+ % #3 value b
+ %
+ \FP@beginmessage{LSOLVE}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#2}%
+ \FP@lsolve@warn{#3}%
+ \else%
+ \FP@@lsolve{#2}{#3}%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \let#1\FP@tmp%
+ %
+ \FP@endmessage{}%
+}
+
+%compute the solutions of a*x^2 + b*x + c = 0
+\def\FP@@qsolve#1#2#3{%
+ % \FP@tmpc := 2*a
+ \FPadd\FP@tmpc{#1}{#1}%
+ %
+ % \FP@tmpb := b*b
+ \FPmul\FP@tmpd{#2}{#2}%
+ %
+ % \FP@tmpc := 4*a*c
+ \FPmul\FP@tmpe\FP@tmpc{#3}%
+ \FPadd\FP@tmpe\FP@tmpe\FP@tmpe%
+ %
+ % \FP@tmpf := b^2 - 4*a*c
+ \FPsub\FP@tmpf\FP@tmpd\FP@tmpe%
+ %
+ \FPifneg\FP@tmpf%
+ \FP@errmessage{Quadratic equation does not have a solution}%
+ \else%
+ % \FP@tmpd := sqrt(b^2 - 4*a*c)
+ \FProot\FP@tmpd\FP@tmpf{2}%
+ %
+ % solution 1: x = (-b + sqrt(b^2 - 4*a*c))/(2*a)
+ \FPsub\FP@tmp\FP@tmpd{#2}%
+ \FPdiv\FP@tmpe\FP@tmp\FP@tmpc%
+ %
+ % solution 2: x = (-b + sqrt(b^2 - 4*a*c))/(2*a)
+ \FPadd\FP@tmp\FP@tmpd{#2}%
+ \FPdiv\FP@tmpd\FP@tmp\FP@tmpc%
+ \FPneg\FP@tmpd\FP@tmpd%
+ \fi%
+}
+
+\def\FP@qsolve#1#2#3#4#5{%
+ % #1 macro, which gets the 1st result
+ % #2 macro, which gets the 2nd result
+ % #3 value a
+ % #4 value b
+ % #5 value c
+ %
+ \FP@beginmessage{QSOLVE}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#3}%
+ \FP@warnmessage{Quadratic equation is linear}%
+ \FP@lsolve\FP@tmpe{#4}{#5}%
+ \let\FP@tmpd\FP@tmpe%
+ \else%
+ \FP@@qsolve{#3}{#4}{#5}%
+ \fi%
+ %
+ \global\let\FP@tmpa\FP@tmpe%
+ \global\let\FP@tmpb\FP@tmpd%
+ }%
+ %
+ \let#1\FP@tmpa%
+ \let#2\FP@tmpb%
+ %
+ \FP@endmessage{}%
+}
+
+%compute the solutions of a*x^3 + b*x^2 + c*x + d = 0
+\def\FP@@csolve#1#2#3#4{%
+ %reducation of cubic equation
+ %\FPeval\FP@tmpp{(#3)/(3*(#1)) - mul(copy((#2)/(3*(#1))))}%
+ \FPupn\FP@tmpp{#3 3 #1 mul div #2 3 #1 mul div copy mul sub}%
+ %\FPeval\FP@tmpq{mul(mul(copy(copy((#2)/(3*(#1)))))) - (#2)*(#3)/(6*(#1)*(#1)) + (#4)/(2*(#1))}%
+ \FPupn\FP@tmpq{#2 3 #1 mul div copy copy mul mul #2 #3 mul 6 #1 mul #1 mul div sub #4 2 #1 mul div add}%
+ %
+ %check whether solution is trivial
+ \FPifzero\FP@tmpp%
+ %\FPeval\FP@tmpf{root(3,abs(2*\FP@tmpq)) * sgn(\FP@tmpq)}%
+ \FPupn\FP@tmpf{3 2 \FP@tmpq{} mul abs root \FP@tmpq{} sgn mul}%
+ \let\FP@tmpe\FP@tmpf%
+ \let\FP@tmpd\FP@tmpf%
+ \else%
+ %compute D
+ %\FPeval\FP@tmpD{mul(copy(\FP@tmpq)) + mul(mul(copy(copy(\FP@tmpp))))}%
+ \FPupn\FP@tmpD{\FP@tmpq{} copy mul \FP@tmpp{} copy copy mul mul add}%
+ \FPsgn\FP@tmp\FP@tmpD%
+ \expandafter\ifnum\FP@tmp=1\relax%
+ %only one real valued solution, compute it
+ \FProot\FP@tmpD\FP@tmpD{2}%
+ \FPsub\FP@tmpf\FP@tmpD\FP@tmpq%
+ \FPadd\FP@tmpe\FP@tmpD\FP@tmpq%
+ \FPneg\FP@tmpe\FP@tmpe%
+ %\FPeval\FP@tmpf{root(3,abs(\FP@tmpf)) * sgn(\FP@tmpf) + root(3,abs(\FP@tmpe)) * sgn(\FP@tmpe)}%
+ \FPupn\FP@tmpf{3 \FP@tmpf{} abs root \FP@tmpf{} sgn mul 3 \FP@tmpe{} abs root \FP@tmpe{} sgn mul add}%
+ \FP@warnmessage{Cubic equation has only one real valued solution}%
+ \let\FP@tmpe\FP@tmpf%
+ \let\FP@tmpd\FP@tmpf%
+ \else%
+ %compute r and phi/3
+ %\FPeval\FP@tmpr{root(2,abs(\FP@tmpp)) * sgn(\FP@tmpq) * 2}%
+ \FPupn\FP@tmpr{2 \FP@tmpp{} abs root \FP@tmpq{} sgn mul}%
+ %\FPeval\FP@tmpp{arccos(\FP@tmpq/\FP@tmpr/\FP@tmpr/\FP@tmpr)/3}%
+ \FPupn\FP@tmpp{\FP@tmpq{} \FP@tmpr{} div \FP@tmpr{} div \FP@tmpr{} div arccos 3 div}%
+ %compute the three solutions
+ \FPmul\FP@tmpr{2}\FP@tmpr%
+ \FPeval\FP@tmpf{neg(\FP@tmpr) * cos(\FP@tmpp)}%
+ \FPeval\FP@tmpe{(\FP@tmpr) * cos(1.047197551196597746-(\FP@tmpp))}%
+ \FPeval\FP@tmpd{(\FP@tmpr) * cos(1.047197551196597746+(\FP@tmpp))}%
+ \fi%
+ \fi%
+ %
+ \FPeval\FP@tmpf{(\FP@tmpf)-(#2)/(3*(#1))}%
+ \FPeval\FP@tmpe{(\FP@tmpe)-(#2)/(3*(#1))}%
+ \FPeval\FP@tmpd{(\FP@tmpd)-(#2)/(3*(#1))}%
+}
+
+\def\FP@csolve#1#2#3#4#5#6#7{%
+ % #1 macro, which gets the 1st result
+ % #2 macro, which gets the 2nd result
+ % #3 macro, which gets the 3nd result
+ % #4 value a
+ % #5 value b
+ % #6 value c
+ % #7 value d
+ %
+ \FP@beginmessage{CSOLVE}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#4}%
+ \FP@warnmessage{Cubic equation is quadratic}%
+ \FP@qsolve\FP@tmpe\FP@tmpf{#5}{#6}{#7}%
+ \let\FP@tmpd\FP@tmpe%
+ \else%
+ \FP@@csolve{#4}{#5}{#6}{#7}%
+ \fi%
+ %
+ \global\let\FP@tmpa\FP@tmpf%
+ \global\let\FP@tmpb\FP@tmpe%
+ \global\let\FP@tmpc\FP@tmpd%
+ }%
+ %
+ \let#1\FP@tmpa%
+ \let#2\FP@tmpb%
+ \let#3\FP@tmpc%
+ %
+ \FP@endmessage{}%
+}
+
+%compute the solutions of a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+\def\FP@qqsolveAy#1#2#3{%
+ \FPeval\FP@tmpA{8*(\FP@tmpyc)+((#2)*(#2)/(#1)-4*(#3))/(#1)}%
+ \FPsgn\FP@tmp\FP@tmpA%
+ \expandafter\ifnum\FP@tmp>0\relax%
+ \let\FP@tmpy\FP@tmpyc%
+ \else%
+ \FPeval\FP@tmpA{8*(\FP@tmpyb)+((#2)*(#2)/(#1)-4*(#3))/(#1)}%
+ \FPsgn\FP@tmp\FP@tmpA%
+ \expandafter\ifnum\FP@tmp>0\relax%
+ \let\FP@tmpy\FP@tmpyb%
+ \else%
+ \FPeval\FP@tmpA{8*(\FP@tmpya)+((#2)*(#2)/(#1)-4*(#3))/(#1)}%
+ \FPsgn\FP@tmp\FP@tmpA%
+ \expandafter\ifnum\FP@tmp>0\relax%
+ \let\FP@tmpy\FP@tmpya%
+ \else%
+ \FP@errmessage{Equation of 4-th degree has no solution}%
+ \fi%
+ \fi%
+ \fi%
+ \FProot\FP@tmpA\FP@tmpA{2}%
+}
+
+\def\FP@@qqsolve#1#2#3#4#5{%
+ %compute cubic equation
+ \FPeval\FP@tmpyb{neg(4*(#3)/(#1))}%
+ \FPeval\FP@tmpyc{2*(#2)*(#4)/(#1)/(#1) - 8*(#5)/(#1)}%
+ \FPeval\FP@tmpyd{(#5)/(#1)*(4*(#3)/(#1) - (#2)*(#2)/(#1)/(#1)) - (#4)*(#4)/(#1)/(#1)}%
+ %solve cubic equation
+ \FP@@csolve{8}\FP@tmpyb\FP@tmpyc\FP@tmpyd%
+ %hold an arbitrary solution
+ \let\FP@tmpya\FP@tmpd%
+ \let\FP@tmpyb\FP@tmpe%
+ \let\FP@tmpyc\FP@tmpf%
+ %compute A and y from these solutions
+ \FP@qqsolveAy{#1}{#2}{#3}%
+ %compute first quadratic equation
+ \FPeval\FP@tmpp{((#2)/(#1)+(\FP@tmpA))/2}%
+ \FPeval\FP@tmpq{(\FP@tmpy)+((#2)*(\FP@tmpy)-(#4))/(#1)/(\FP@tmpA)}%
+ \FP@qsolve\FP@tmpg\FP@tmpf{1}\FP@tmpp\FP@tmpq%
+ %compute second quadratic equation
+ \FPeval\FP@tmpp{((#2)/(#1)-(\FP@tmpA))/2}%
+ \FPeval\FP@tmpq{(\FP@tmpy)-((#2)*(\FP@tmpy)-(#4))/(#1)/(\FP@tmpA)}%
+ \FP@qsolve\FP@tmpe\FP@tmpd{1}\FP@tmpp\FP@tmpq%
+}
+
+%subsolve a*x^4 + c*x^2 + e = 0
+\def\FP@qsolve@zero#1#2#3{%
+ \FPeval\FP@tmpy{(#2)*(#2) - 4*(#1)*(#3)}%
+ \FPsgn\FP@tmp\FP@tmpy%
+ \expandafter\ifnum\FP@tmp<0\relax%
+ \FP@errmessage{Equation of 4-th degree has no solution}%
+ \else%
+ %compute solutions
+ \FPeval\FP@tmpya{neg(root(2,\FP@tmpy)+(#2))/(2*(#1))}%
+ \FPeval\FP@tmpyb{(root(2,\FP@tmpy)-(#2))/(2*(#1))}%
+ \FPsgn\FP@tmpf\FP@tmpya%
+ \FPsgn\FP@tmpg\FP@tmpyb%
+ \ifnum\expandafter\ifnum\FP@tmpf<0 0\else1\fi\expandafter\ifnum\FP@tmpg<0 0\else1\fi=0\relax%
+ \FP@errmessage{Equation of 4-th degree has no solution}%
+ \else%
+ \expandafter\ifnum\FP@tmpf<0\relax%
+ \FP@warnmessage{Equation of 4-th degree only has two solutions}%
+ \let\FP@tmpya\FP@tmpyb%
+ \else%
+ \expandafter\ifnum\FP@tmpg<0\relax%
+ \FP@warnmessage{Equation of 4-th degree only has two solutions}%
+ \let\FP@tmpyb\FP@tmpya%
+ \fi%
+ \fi%
+ %compute solutions
+ \FProot\FP@tmpg\FP@tmpya{2}%
+ \FPneg\FP@tmpf\FP@tmpg%
+ \FProot\FP@tmpe\FP@tmpyb{2}%
+ \FPneg\FP@tmpd\FP@tmpe%
+ \fi%
+ \fi%
+}
+
+%subsolve a*x^4 + b*x^3 + c*x^2 + b*x + a = 0
+\def\FP@qsolve@eq#1#2#3{%
+ \FPeval\FP@tmpy{(#2)*(#2) - 4*(#1)*(#3) + 8*(#1)*(#1)}%
+ \FPsgn\FP@tmp\FP@tmpy%
+ \expandafter\ifnum\FP@tmp<0\relax%
+ \FP@errmessage{Equation of 4-th degree has no solution}%
+ \else%
+ %compute solutions
+ \FPeval\FP@tmpya{neg(root(2,\FP@tmpy)+(#2))/(2*(#1))}%
+ \FPeval\FP@tmpyb{(root(2,\FP@tmpy)-(#2))/(2*(#1))}%
+ \FPeval\FP@tmpyc{(\FP@tmpya)*(\FP@tmpya)-4}%
+ \FPeval\FP@tmpyd{(\FP@tmpyb)*(\FP@tmpyb)-4}%
+ \FPsgn\FP@tmpf\FP@tmpyc%
+ \FPsgn\FP@tmpg\FP@tmpyd%
+ \ifnum\expandafter\ifnum\FP@tmpf<0 0\else1\fi\expandafter\ifnum\FP@tmpg<0 0\else1\fi=0\relax%
+ \FP@errmessage{Equation of 4-th degree has no solution}%
+ \else%
+ \expandafter\ifnum\FP@tmpf<0\relax%
+ \FP@warnmessage{Equation of 4-th degree only has two solutions}%
+ \let\FP@tmpya\FP@tmpyb%
+ \let\FP@tmpyc\FP@tmpyd%
+ \else%
+ \expandafter\ifnum\FP@tmpg<0\relax%
+ \FP@warnmessage{Equation of 4-th degree only has two solutions}%
+ \let\FP@tmpyb\FP@tmpya%
+ \let\FP@tmpyd\FP@tmpyc%
+ \fi%
+ \fi%
+ %compute solutions
+ \FPeval\FP@tmpg{((\FP@tmpya)+root(2,(\FP@tmpyc)))/2}%
+ \FPeval\FP@tmpf{((\FP@tmpya)-root(2,(\FP@tmpyc)))/2}%
+ \FPeval\FP@tmpe{((\FP@tmpyb)+root(2,(\FP@tmpyd)))/2}%
+ \FPeval\FP@tmpd{((\FP@tmpyb)-root(2,(\FP@tmpyd)))/2}%
+ \fi%
+ \fi%
+}
+
+%complete solve of equation of 4-th degree
+\def\FP@qqsolve#1#2#3#4#5#6#7#8#9{%
+ % #1 macro, which gets the 1st result
+ % #2 macro, which gets the 2nd result
+ % #3 macro, which gets the 3nd result
+ % #4 macro, which gets the 4th result
+ % #5 value a
+ % #6 value b
+ % #7 value c
+ % #8 value d
+ % #9 value e
+ %
+ \FP@beginmessage{QQSOLVE}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#5}%
+ \FP@warnmessage{Equation of 4-th degree is cubic}%
+ \FP@csolve\FP@tmpd\FP@tmpe\FP@tmpf{#6}{#7}{#8}{#9}%
+ \let\FP@tmpg\FP@tmpd%
+ \else%
+ \FPsgn\FP@tmpg{#6}%
+ \FPsgn\FP@tmpf{#8}%
+ \ifnum\expandafter\ifnum\FP@tmpg=0 0\else1\fi\expandafter\ifnum\FP@tmpf=0 0\else1\fi=0\relax%
+ %case b=d=0
+ \FP@qsolve@zero{#5}{#7}{#9}%
+ \else%
+ \FPupn\FP@tmpg{#5 #9 sub sgn}%
+ \FPupn\FP@tmpf{#6 #8 sub sgn}%
+ \ifnum\expandafter\ifnum\FP@tmpg=0 0\else1\fi\expandafter\ifnum\FP@tmpf=0 0\else1\fi=0\relax%
+ %case a=e, b=d
+ \FP@qsolve@eq{#5}{#6}{#7}%
+ \else%
+ \FP@@qqsolve{#5}{#6}{#7}{#8}{#9}%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \global\let\FP@tmpa\FP@tmpg%
+ \global\let\FP@tmpb\FP@tmpf%
+ \global\let\FP@tmpc\FP@tmpe%
+ \global\let\FP@tmpd\FP@tmpd%
+ }%
+ %
+ \let#1\FP@tmpa%
+ \let#2\FP@tmpb%
+ \let#3\FP@tmpc%
+ \let#4\FP@tmpd%
+ %
+ \FP@endmessage{}%
+}
diff --git a/macros/latex/contrib/fp/fp-eval.sty b/macros/latex/contrib/fp/fp-eval.sty
new file mode 100644
index 0000000000..1a81f9a6ea
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-eval.sty
@@ -0,0 +1,155 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-eval}[1995/04/03]
+
+%version information
+\def\FP@evalversion{0.9a}
+\message{%
+ `Fixed Point Calculator',%
+ \space\space\space\space%
+ \space\space\space\space%
+ Version \FP@evalversion%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{defpattern}
+\RequirePackage{fp-upn}
+
+%%%public area (macros which may be used)%%%
+\def\FPeval#1#2{\FP@eval{#1}{#2}} % #1 := eval(#2)
+
+%%%private fp-area (don't use these macros)%%%
+
+%%%%%make postfix notation from prefix/infix notation
+
+%%%handle constants and function applications
+
+%constants
+\defpattern\FP@gen@app[#2]{#2}
+
+%function applications from prefix to postfix
+\defpattern\FP@gen@app[add #2]{#2 add}
+\defpattern\FP@gen@app[sub #2]{#2 sub}
+\defpattern\FP@gen@app[mul #2]{#2 mul}
+\defpattern\FP@gen@app[div #2]{#2 div}
+\defpattern\FP@gen@app[abs #2]{#2 abs}
+\defpattern\FP@gen@app[neg #2]{#2 neg}
+\defpattern\FP@gen@app[sgn #2]{#2 sgn}
+\defpattern\FP@gen@app[min #2]{#2 min}
+\defpattern\FP@gen@app[max #2]{#2 max}
+\defpattern\FP@gen@app[round #2]{#2 round}
+\defpattern\FP@gen@app[trunc #2]{#2 trunc}
+\defpattern\FP@gen@app[clip #2]{#2 clip}
+\defpattern\FP@gen@app[exp #2]{#2 exp}
+\defpattern\FP@gen@app[ln #2]{#2 ln}
+\defpattern\FP@gen@app[pow #2]{#2 pow}
+\defpattern\FP@gen@app[root #2]{#2 root}
+\defpattern\FP@gen@app[seed #2]{#2 seed}
+\defpattern\FP@gen@app[random #2]{#2 random}
+\defpattern\FP@gen@app[sin #2]{#2 sin}
+\defpattern\FP@gen@app[cos #2]{#2 cos}
+\defpattern\FP@gen@app[sincos #2]{#2 sincos}
+\defpattern\FP@gen@app[tan #2]{#2 tan}
+\defpattern\FP@gen@app[cot #2]{#2 cot}
+\defpattern\FP@gen@app[tancot #2]{#2 tancot}
+\defpattern\FP@gen@app[arcsin #2]{#2 arcsin}
+\defpattern\FP@gen@app[arccos #2]{#2 arccos}
+\defpattern\FP@gen@app[arcsincos #2]{#2 arcsincos}
+\defpattern\FP@gen@app[arctan #2]{#2 arctan}
+\defpattern\FP@gen@app[arccot #2]{#2 arccot}
+\defpattern\FP@gen@app[arctancot #2]{#2 arctancot}
+\defpattern\FP@gen@app[pop #2]{#2 pop}
+\defpattern\FP@gen@app[swap #2]{#2 swap}
+\defpattern\FP@gen@app[copy #2]{#2 copy}
+\defpattern\FP@gen@app[ #2]{\FP@gen@app[#2]}
+
+\def\FP@gen@app@handle#1{\FP@gen@app[#1]}
+
+%%%handle ^, right to left
+\defpattern\FP@gen@exp[#2]{\FP@gen@app@handle{#2}}
+\defpattern\FP@gen@exp[#2^#3]{\FP@gen@exp[#3] \FP@gen@exp[#2] pow}
+
+\def\FP@gen@exp@handle#1{\FP@gen@exp[#1]}
+
+%%%handle * and /, left to right
+
+%handle two or more occurrences of * and /
+\defpattern\FP@gen@mul@splitted[#2|/|#3|#4|#5]{\FP@gen@mul@handle{\FP@gen@exp@handle{#2} \FP@gen@exp@handle{#3} div #4#5}}
+\defpattern\FP@gen@mul@splitted[#2|*|#3|#4|#5]{\FP@gen@mul@handle{\FP@gen@exp@handle{#2} \FP@gen@exp@handle{#3} mul #4#5}}
+
+%split second * or / if exists
+\defpattern\FP@gen@mul@split@two@div[#2|#3|#4|#5|#6]{\FP@gen@mul@splitted[#2|#3|#4|#5|#6]}
+\defpattern\FP@gen@mul@split@two@div[#2|#3|#4/#5|#6|#7]{\FP@gen@mul@splitted[#2|#3|#4|/|#5#6#7]}
+\defpattern\FP@gen@mul@split@two[#2|/|#3]{\FP@gen@exp@handle{#2} \FP@gen@exp@handle{#3} div}
+\defpattern\FP@gen@mul@split@two[#2|*|#3]{\FP@gen@exp@handle{#2} \FP@gen@exp@handle{#3} mul}
+\defpattern\FP@gen@mul@split@two[#2|#3|#4/#5]{\FP@gen@mul@splitted[#2|#3|#4|/|#5]}
+\defpattern\FP@gen@mul@split@two[#2|#3|#4*#5]{\FP@gen@mul@split@two@div[#2|#3|#4|*|#5]}
+
+%split first * or / if exists
+\defpattern\FP@gen@mul@split@one@div[#2|#3|#4]{\FP@gen@mul@split@two[#2|#3|#4]}
+\defpattern\FP@gen@mul@split@one@div[#2/#3|#4|#5]{\FP@gen@mul@split@two[#2|/|#3#4#5]}
+\defpattern\FP@gen@mul@split@one[#2]{\FP@gen@exp@handle{#2}}
+\defpattern\FP@gen@mul@split@one[#2/#3]{\FP@gen@mul@split@two[#2|/|#3]}
+\defpattern\FP@gen@mul@split@one[#2*#3]{\FP@gen@mul@split@one@div[#2|*|#3]}
+
+%generate code for a series of * and /
+\def\FP@gen@mul@handle#1{\FP@gen@mul@split@one[#1]}
+
+%%%handle + and -, left to right
+
+%handle two or more occurrences of + and -
+\defpattern\FP@gen@add@splitted[#2|-|#3|#4|#5]{\FP@gen@add@handle{\FP@gen@mul@handle{#2} \FP@gen@mul@handle{#3} sub #4#5}}
+\defpattern\FP@gen@add@splitted[#2|+|#3|#4|#5]{\FP@gen@add@handle{\FP@gen@mul@handle{#2} \FP@gen@mul@handle{#3} add #4#5}}
+
+%split second + or - if exists
+\defpattern\FP@gen@add@split@two@minus[#2|#3|#4|#5|#6]{\FP@gen@add@splitted[#2|#3|#4|#5|#6]}
+\defpattern\FP@gen@add@split@two@minus[#2|#3|#4-#5|#6|#7]{\FP@gen@add@splitted[#2|#3|#4|-|#5#6#7]}
+\defpattern\FP@gen@add@split@two[#2|-|#3]{\FP@gen@mul@handle{#2} \FP@gen@mul@handle{#3} sub}
+\defpattern\FP@gen@add@split@two[#2|+|#3]{\FP@gen@mul@handle{#2} \FP@gen@mul@handle{#3} add}
+\defpattern\FP@gen@add@split@two[#2|#3|#4-#5]{\FP@gen@add@splitted[#2|#3|#4|-|#5]}
+\defpattern\FP@gen@add@split@two[#2|#3|#4+#5]{\FP@gen@add@split@two@minus[#2|#3|#4|+|#5]}
+
+%split first + or - if exists
+\defpattern\FP@gen@add@split@one@minus[#2|#3|#4]{\FP@gen@add@split@two[#2|#3|#4]}
+\defpattern\FP@gen@add@split@one@minus[#2-#3|#4|#5]{\FP@gen@add@split@two[#2|-|#3#4#5]}
+\defpattern\FP@gen@add@split@one[#2]{\FP@gen@mul@handle{#2}}
+\defpattern\FP@gen@add@split@one[#2-#3]{\FP@gen@add@split@two[#2|-|#3]}
+\defpattern\FP@gen@add@split@one[#2+#3]{\FP@gen@add@split@one@minus[#2|+|#3]}
+
+%generate code for a series of + and -
+\def\FP@gen@add@handle#1{\FP@gen@add@split@one[#1]}
+
+%%%handle , and : as argument lists for functions with surrounding ( and )
+\defpattern\FP@gen@komma[#2]{\FP@gen@add@handle{#2}}
+\defpattern\FP@gen@komma[#2,#3]{\FP@gen@komma[#2] \FP@gen@komma[#3] }
+\defpattern\FP@gen@komma[#2:#3]{\FP@gen@komma[#2] \FP@gen@komma[#3] }
+
+%%%generate code for each paranthesis
+\def\FP@gen@code#1{\FP@gen@komma[#1]}
+
+%%%handle paranthesis
+\defpattern\FP@kl@handle@one[#2|#3|#4]{\FP@kl@handle[#2 \FP@gen@code{#3}#4]}
+\defpattern\FP@kl@handle@one[#2|#3(#4|#5]{\FP@kl@handle@one[#2(#3|#4|#5]}
+
+\defpattern\FP@kl@handle[#2]{\FP@gen@code{#2}}
+\defpattern\FP@kl@handle[#2(#3)#4]{%
+ \FP@kl@handle@one[#2|#3|#4]%
+}
+
+\defpattern\FP@gen[#2]{\FP@kl@handle[#2]}
+\defpattern\FP@gen[#2(-#3]{\FP@gen[#2(0-#3]}
+\defpattern\FP@gen[#2(+#3]{\FP@gen[#2(#3]}
+\defpattern\FP@gen[#2( #3]{\FP@gen[#2(#3]}
+
+\def\FP@mkupn#1{%
+ \expandafter\FP@gen\expandafter[#1]%
+}
+
+%%%%%compute expression via upn
+\def\FP@eval#1#2{%
+ \FP@beginmessage{EVAL}%
+ \FPupn{#1}{\FP@mkupn{#2}}%
+ \FP@endmessage{}%
+}
diff --git a/macros/latex/contrib/fp/fp-exp.sty b/macros/latex/contrib/fp/fp-exp.sty
new file mode 100644
index 0000000000..19da37ae46
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-exp.sty
@@ -0,0 +1,500 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-exp}[1995/04/03]
+
+%version information
+\def\FP@expversion{0.7e}
+\message{%
+ `Fixed Point Exponentiation',%
+ \space\space\space\space%
+ Version \FP@expversion%
+ \space (C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp-basic}
+
+%%%public area (macros which may be used)%%%
+
+%constants
+\edef\FPe{2.718281828459045235}
+%unary functions
+\def\FPexp#1#2{\FP@calld\FP@exp#1{#2}}
+\def\FPln#1#2{\FP@calld\FP@ln#1{#2}}
+%binary functions
+\def\FPpow#1#2#3{\FP@pow#1{#2}{#3}}
+\def\FProot#1#2#3{\FP@root#1{#2}{#3}}
+
+%%%private fp-area (don't use these macros)%%%
+
+%allocation of registers
+
+\countdef\FP@ls=50
+\countdef\FP@lfa=51
+\countdef\FP@lfb=52
+
+\countdef\FP@regd=53
+\countdef\FP@rege=54
+
+%compute e pow x
+
+\expandafter\edef\csname FP@e0\endcsname{1.000000000000000000}
+\expandafter\edef\csname FP@e1\endcsname{2.718281828459045235}
+\expandafter\edef\csname FP@e2\endcsname{7.389056098930650227}
+\expandafter\edef\csname FP@e3\endcsname{20.085536923187667741}
+\expandafter\edef\csname FP@e4\endcsname{54.598150033144239078}
+\expandafter\edef\csname FP@e5\endcsname{148.413159102576603421}
+\expandafter\edef\csname FP@e6\endcsname{403.428793492735122608}
+\expandafter\edef\csname FP@e7\endcsname{1096.633158428458599264}
+\expandafter\edef\csname FP@e8\endcsname{2980.957987041728274744}
+\expandafter\edef\csname FP@e9\endcsname{8103.083927575384007710}
+\expandafter\edef\csname FP@e10\endcsname{22026.465794806716516958}
+\expandafter\edef\csname FP@e11\endcsname{59874.141715197818455326}
+\expandafter\edef\csname FP@e12\endcsname{162754.791419003920808005}
+\expandafter\edef\csname FP@e13\endcsname{442413.392008920503326103}
+\expandafter\edef\csname FP@e14\endcsname{1202604.284164776777749237}
+\expandafter\edef\csname FP@e15\endcsname{3269017.372472110639301855}
+\expandafter\edef\csname FP@e16\endcsname{8886110.520507872636763024}
+\expandafter\edef\csname FP@e17\endcsname{24154952.753575298214775435}
+\expandafter\edef\csname FP@e18\endcsname{65659969.137330511138786503}
+\expandafter\edef\csname FP@e19\endcsname{178482300.963187260844910034}
+\expandafter\edef\csname FP@e20\endcsname{485165195.409790277969106831}
+\expandafter\edef\csname FP@e21\endcsname{1318815734.483214697209998884}
+\expandafter\edef\csname FP@e22\endcsname{3584912846.131591561681159946}
+\expandafter\edef\csname FP@e23\endcsname{9744803446.248902600034632685}
+\expandafter\edef\csname FP@e24\endcsname{26489122129.843472294139162153}
+\expandafter\edef\csname FP@e25\endcsname{72004899337.385872524161351466}
+\expandafter\edef\csname FP@e26\endcsname{195729609428.838764269776397876}
+\expandafter\edef\csname FP@e27\endcsname{532048240601.798616683747304341}
+\expandafter\edef\csname FP@e28\endcsname{1446257064291.475173677047422997}
+\expandafter\edef\csname FP@e29\endcsname{3931334297144.042074388620580844}
+\expandafter\edef\csname FP@e30\endcsname{10686474581524.462146990468650741}
+\expandafter\edef\csname FP@e31\endcsname{29048849665247.425231085682111680}
+\expandafter\edef\csname FP@e32\endcsname{78962960182680.695160978022635108}
+\expandafter\edef\csname FP@e33\endcsname{214643579785916.064624297761531261}
+\expandafter\edef\csname FP@e34\endcsname{583461742527454.881402902734610391}
+\expandafter\edef\csname FP@e35\endcsname{1586013452313430.728129644625774660}
+\expandafter\edef\csname FP@e36\endcsname{4311231547115195.227113422292856925}
+\expandafter\edef\csname FP@e37\endcsname{11719142372802611.308772939791190195}
+\expandafter\edef\csname FP@e38\endcsname{31855931757113756.220328671701298646}
+\expandafter\edef\csname FP@e39\endcsname{86593400423993746.953606932719264934}
+\expandafter\edef\csname FP@e40\endcsname{235385266837019985.407899910749034805}
+\expandafter\edef\csname FP@e41\endcsname{639843493530054949.222663403515570819}
+
+\expandafter\edef\csname FP@e-0\endcsname{1.000000000000000000}
+\expandafter\edef\csname FP@e-1\endcsname{0.367879441171442322}
+\expandafter\edef\csname FP@e-2\endcsname{0.135335283236612692}
+\expandafter\edef\csname FP@e-3\endcsname{0.049787068367863943}
+\expandafter\edef\csname FP@e-4\endcsname{0.018315638888734180}
+\expandafter\edef\csname FP@e-5\endcsname{0.006737946999085467}
+\expandafter\edef\csname FP@e-6\endcsname{0.002478752176666358}
+\expandafter\edef\csname FP@e-7\endcsname{0.000911881965554516}
+\expandafter\edef\csname FP@e-8\endcsname{0.000335462627902512}
+\expandafter\edef\csname FP@e-9\endcsname{0.000123409804086680}
+\expandafter\edef\csname FP@e-10\endcsname{0.000045399929762485}
+\expandafter\edef\csname FP@e-11\endcsname{0.000016701700790246}
+\expandafter\edef\csname FP@e-12\endcsname{0.000006144212353328}
+\expandafter\edef\csname FP@e-13\endcsname{0.000002260329406981}
+\expandafter\edef\csname FP@e-14\endcsname{0.000000831528719104}
+\expandafter\edef\csname FP@e-15\endcsname{0.000000305902320502}
+\expandafter\edef\csname FP@e-16\endcsname{0.000000112535174719}
+\expandafter\edef\csname FP@e-17\endcsname{0.000000041399377188}
+\expandafter\edef\csname FP@e-18\endcsname{0.000000015229979745}
+\expandafter\edef\csname FP@e-19\endcsname{0.000000005602796438}
+\expandafter\edef\csname FP@e-20\endcsname{0.000000002061153622}
+\expandafter\edef\csname FP@e-21\endcsname{0.000000000758256043}
+\expandafter\edef\csname FP@e-22\endcsname{0.000000000278946809}
+\expandafter\edef\csname FP@e-23\endcsname{0.000000000102618796}
+\expandafter\edef\csname FP@e-24\endcsname{0.000000000037751345}
+\expandafter\edef\csname FP@e-25\endcsname{0.000000000013887944}
+\expandafter\edef\csname FP@e-26\endcsname{0.000000000005109089}
+\expandafter\edef\csname FP@e-27\endcsname{0.000000000001879529}
+\expandafter\edef\csname FP@e-28\endcsname{0.000000000000691440}
+\expandafter\edef\csname FP@e-29\endcsname{0.000000000000254367}
+\expandafter\edef\csname FP@e-30\endcsname{0.000000000000093576}
+\expandafter\edef\csname FP@e-31\endcsname{0.000000000000034425}
+\expandafter\edef\csname FP@e-32\endcsname{0.000000000000012664}
+\expandafter\edef\csname FP@e-33\endcsname{0.000000000000004659}
+\expandafter\edef\csname FP@e-34\endcsname{0.000000000000001714}
+\expandafter\edef\csname FP@e-35\endcsname{0.000000000000000631}
+\expandafter\edef\csname FP@e-36\endcsname{0.000000000000000232}
+\expandafter\edef\csname FP@e-37\endcsname{0.000000000000000085}
+\expandafter\edef\csname FP@e-38\endcsname{0.000000000000000031}
+\expandafter\edef\csname FP@e-39\endcsname{0.000000000000000012}
+\expandafter\edef\csname FP@e-40\endcsname{0.000000000000000004}
+\expandafter\edef\csname FP@e-41\endcsname{0.000000000000000002}
+\expandafter\edef\csname FP@e-42\endcsname{0.000000000000000001}
+
+\def\FP@exp@mul#1#2#3#4#5#6{%
+ % #1 macro which gets fractional part 1
+ % #2 macro which fractional part 1
+ % #3 first value part 1
+ % #4 first value part 2
+ % #5 second value part 1
+ % #6 second value part 2
+ \FP@split\FP@xq\FP@xr\FP@xz{#3}\FP@split\FP@xt\FP@xu\FP@xv{#4}%
+ \FP@split\FP@yq\FP@yr\FP@yz{#5}\FP@split\FP@yt\FP@yu\FP@yv{#6}%
+ \FP@prod=0\relax%
+ \edef\FP@rd{}%
+ \FP@@mul vv \relax\FP@saveshift%
+ \FP@@mul vu uv \relax\FP@saveshift%
+ \FP@@mul uu vt tv \relax\FP@saveshift%
+ \FP@@mul ut tu vz zv \relax\FP@saveshift%
+ \FP@@mul tt uz zu vr rv \relax\FP@saveshift%
+ \FP@@mul zt tz ur ru qv vq \relax\FP@saveshift%
+ \FP@@mul zz rt tr qu uq \relax\FP@saveshift%
+ \FP@@mul rz zr qt tq \relax\FP@saveshift%
+ \FP@@mul rr qz zq \relax\FP@saveshift%
+ \FP@@mul qr rq \relax\FP@saveshift%
+ \FP@@mul qq \relax\FP@saveshift\FP@saveshift%
+ \FP@ninesplit\FP@rd#1=\FP@res%
+ \FP@ninesplit\FP@rd#2=\FP@res%
+}
+
+\def\FP@exp@divn#1#2#3#4#5{%
+ % #1 macro which gets fractional part 1
+ % #2 macro which fractional part 1
+ % #3 value part 1
+ % #4 value part 2
+ % #5 integer (0,..,1000)
+ \FP@rega=#3\divide\FP@rega#5%
+ \FP@regd=\FP@rega%
+ \multiply\FP@rega#5\relax%
+ \advance\FP@rega-#3\relax%
+ \multiply\FP@rega-1000\relax%
+ \FP@regb=#4\divide\FP@regb1000000\relax%
+ \advance\FP@rega\FP@regb%
+ \FP@regc=\FP@rega\divide\FP@regc#5\relax%
+ \FP@rege=\FP@regc\multiply\FP@rege1000000\relax%
+ \multiply\FP@regc#5\advance\FP@rega-\FP@regc\multiply\FP@rega1000000\relax%
+ \multiply\FP@regb1000000\relax\advance\FP@regb-#4\relax%
+ \advance\FP@rega-\FP@regb%
+ \divide\FP@rega#5\relax%
+ \advance\FP@rege\FP@rega%
+ #1=\FP@regd%
+ #2=\FP@rege%
+}
+
+%exp (for values between -1 and 1)
+\def\FP@@exp#1#2#3#4{%
+ % #1 macro which gets the result
+ % #2 sign
+ % #3 fractional part 1
+ % #4 fractional part 2
+ \ifnum\ifnum#3=0 0\else1\fi\ifnum#4=0 0\else1\fi=0\relax%
+ \edef#1{1}%
+ \else%
+ \FP@rs=1\relax%
+ \FP@ria=0\relax%
+ \ifnum#2>0\relax%
+ \FP@rib=1\relax%
+ \FP@rfa=#3\relax%
+ \FP@rfb=#4\relax%
+ \else%
+ \FP@rib=0\relax%
+ \ifnum#4=0\relax%
+ \FP@rfa=1000000000\relax\FP@rfb=0\relax%
+ \else%
+ \FP@rfa=999999999\relax\FP@rfb=1000000000\relax%
+ \fi%
+ \advance\FP@rfa-#3\relax%
+ \advance\FP@rfb-#4\relax%
+ \fi%
+ \FP@ls=#2\relax%
+ \FP@lfa=#3\relax%
+ \FP@lfb=#4\relax%
+ \FP@count=1\relax%
+ \loop%
+ \advance\FP@count1\relax%
+ \multiply\FP@ls#2\relax%
+ \FP@exp@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb#3#4\relax%
+ \FP@exp@divn\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@count%
+ \ifnum\ifnum\FP@lfa=0 0\else1\fi\ifnum\FP@lfb=0 0\else1\fi>0\relax%
+ \ifnum\FP@ls>0\relax%
+ \advance\FP@rfa\FP@lfa%
+ \advance\FP@rfb\FP@lfb%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\relax%
+ \advance\FP@rfb-1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\relax%
+ \advance\FP@rfa-1000000000\relax%
+ \fi%
+ \else%
+ \advance\FP@rfa-\FP@lfa%
+ \advance\FP@rfb-\FP@lfb%
+ \ifnum\FP@rfb<0\relax%
+ \advance\FP@rfa-1\relax%
+ \advance\FP@rfb1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<0\relax%
+ \advance\FP@rib-1\relax%
+ \advance\FP@rfa1000000000\relax%
+ \fi%
+ \fi%
+ \repeat%
+ \FP@store#1{r}%
+ \fi%
+}
+
+\def\FP@exp#1#2.#3.#4\relax{%
+ % #1 macro which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ \FP@beginmessage{EXP}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ \FP@readvalue{x}{#2}{#3}%
+ \ifnum\FP@xia=0\relax%
+ \ifnum\FP@xs<0\relax%
+ \ifnum\FP@xib>42\relax%
+ \edef\FP@tmp{0}%
+ \else%
+ \edef\FP@tmp{\csname FP@e-\the\FP@xib\endcsname}%
+ \fi%
+ \else%
+ \ifnum\FP@xib>41\relax%
+ \FP@errmessage{Overflow}%
+ \else%
+ \edef\FP@tmp{\csname FP@e\the\FP@xib\endcsname}%
+ \fi%
+ \fi%
+ \FP@@exp\FP@tmpa\FP@xs\FP@xfa\FP@xfb%
+ \FPmul\FP@tmp\FP@tmpa\FP@tmp%
+ \global\let\FP@tmp=\FP@tmp%
+ \else%
+ \FP@errmessage{Overflow}%
+ \fi%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute ln x
+
+\expandafter\edef\csname FP@ln2-0\endcsname{0.000000000000000000}
+\expandafter\edef\csname FP@ln2-1\endcsname{0.693147180559945309}
+\expandafter\edef\csname FP@ln2-2\endcsname{1.386294361119890618}
+\expandafter\edef\csname FP@ln2-3\endcsname{2.079441541679835928}
+
+\expandafter\edef\csname FP@ln10-0\endcsname{0.000000000000000000}
+\expandafter\edef\csname FP@ln10-1\endcsname{2.302585092994045684}
+\expandafter\edef\csname FP@ln10-2\endcsname{4.605170185988091368}
+\expandafter\edef\csname FP@ln10-3\endcsname{6.907755278982137052}
+\expandafter\edef\csname FP@ln10-4\endcsname{9.210340371976182736}
+\expandafter\edef\csname FP@ln10-5\endcsname{11.512925464970228420}
+\expandafter\edef\csname FP@ln10-6\endcsname{13.815510557964274104}
+\expandafter\edef\csname FP@ln10-7\endcsname{16.118095650958319788}
+\expandafter\edef\csname FP@ln10-8\endcsname{18.420680743952365472}
+\expandafter\edef\csname FP@ln10-9\endcsname{20.723265836946411156}
+\expandafter\edef\csname FP@ln10-10\endcsname{23.025850929940456840}
+\expandafter\edef\csname FP@ln10-11\endcsname{25.328436022934502524}
+\expandafter\edef\csname FP@ln10-12\endcsname{27.631021115928548208}
+\expandafter\edef\csname FP@ln10-13\endcsname{29.933606208922593892}
+\expandafter\edef\csname FP@ln10-14\endcsname{32.236191301916639576}
+\expandafter\edef\csname FP@ln10-15\endcsname{34.538776394910685260}
+\expandafter\edef\csname FP@ln10-16\endcsname{36.841361487904730944}
+\expandafter\edef\csname FP@ln10-17\endcsname{39.143946580898776628}
+\expandafter\edef\csname FP@ln10-18\endcsname{41.446531673892822312}
+
+\def\FP@ln@divtwo#1#2#3#4#5#6{%
+ % #1 macro which gets integer part
+ % #2 macro which gets fractional part 1
+ % #3 macro which fractional part 2
+ % #4 integer part 1
+ % #5 fractional part 1
+ % #6 fractional part 2
+ #1=#4\relax%
+ #2=#5\relax\ifodd#4\advance#21000000000\relax\fi%
+ #3=#6\relax\ifodd#5\advance#31000000000\relax\fi%
+ \divide#32\relax%
+ \divide#22\relax%
+ \divide#12\relax%
+}
+
+%ln for values between (1 and 2)
+\def\FP@@ln#1#2#3#4{%
+ % #1 macro which gets the result
+ % #2 integer part (1 or 2)
+ % #3 fractional part 1
+ % #4 fractional part 2
+ {\FP@xs=1\FP@xia=0\FP@xib=#2\FP@xfa=#3\FP@xfb=#4%
+ {\advance\FP@xib-1\relax\FP@store\FP@tmpa{x}\global\let\FP@tmpa\FP@tmpa}%
+ {\advance\FP@xib+1\relax\FP@store\FP@tmpb{x}\global\let\FP@tmpb\FP@tmpb}%
+ \FPdiv\FP@tmpa\FP@tmpa\FP@tmpb%
+ %
+ \def\next##1.##2.##3\relax{\FP@readvalue{x}{##1}{##2}}%
+ \expandafter\next\FP@tmpa..\relax%
+ %
+ \FP@lfa=\FP@xfa%
+ \FP@lfb=\FP@xfb%
+ %
+ \FP@rs=1\relax%
+ \FP@ria=0\relax%
+ \FP@rib=0\relax%
+ \FP@rfa=\FP@xfa%
+ \FP@rfb=\FP@xfb%
+ %
+ \FP@count=1\relax%
+ \FP@exp@mul\FP@xfa\FP@xfb\FP@xfa\FP@xfb\FP@xfa\FP@xfb%
+ %
+ \loop%
+ \advance\FP@count2\relax%
+ \FP@exp@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@xfa\FP@xfb%
+ \ifnum\ifnum\FP@lfa=0 0\else1\fi\ifnum\FP@lfb=0 0\else1\fi=0\relax\else%
+ \FP@exp@divn\FP@yfa\FP@yfb\FP@lfa\FP@lfb\FP@count%
+ \advance\FP@rfb\FP@yfb%
+ \advance\FP@rfa\FP@yfa%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\relax%
+ \advance\FP@rfb-1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\relax%
+ \advance\FP@rfa-1000000000\relax%
+ \fi%
+ \repeat%
+ %
+ \advance\FP@rfa\FP@rfa%
+ \ifnum\FP@rfb<500000000\relax\else%
+ \advance\FP@rfa1\relax%
+ \advance\FP@rfb-500000000\relax%
+ \fi%
+ \advance\FP@rfb\FP@rfb%
+ %
+ \FP@store\FP@tmpa{r}%
+ %
+ \global\let\FP@tmpa\FP@tmpa%
+ }%
+ %
+ \let#1\FP@tmpa%
+}
+
+\def\FP@ln#1#2.#3.#4\relax{%
+ % #1 macro which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ \FP@beginmessage{LN}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ %
+ \ifFP@zero{x}%
+ \FP@errmessage{Logarithm of zero}%
+ \else\ifnum\FP@xs<0\relax%
+ \FP@errmessage{Logarithm of negative value}%
+ \else%
+ \FP@count=0\relax%
+ \loop%
+ \ifnum\ifnum\FP@xia>0 1\else0\fi\ifnum\FP@xib>9 1\else0\fi>0\relax%
+ \advance\FP@count1\relax%
+ \FP@divten{x}%
+ \repeat%
+ \loop%
+ \ifnum\ifnum\FP@xia=0 0\else1\fi\ifnum\FP@xib=0 0\else1\fi=0\relax%
+ \advance\FP@count-1\relax%
+ \FP@multen{x}%
+ \repeat%
+ \ifnum\FP@count<0\relax%
+ \FP@count=-\FP@count%
+ \edef\FP@tmpc{-\csname FP@ln10-\the\FP@count\endcsname}%
+ \else%
+ \edef\FP@tmpc{\csname FP@ln10-\the\FP@count\endcsname}%
+ \fi%
+ \FP@count=0\relax%
+ \loop%
+ \ifnum\FP@xib<2\relax\else%
+ \advance\FP@count1\relax%
+ \FP@ln@divtwo\FP@xib\FP@xfa\FP@xfb\FP@xib\FP@xfa\FP@xfb%
+ \repeat%
+ \FPadd\FP@tmpc\FP@tmpc{\csname FP@ln2-\the\FP@count\endcsname}%
+ \FP@@ln\FP@tmpb\FP@xib\FP@xfa\FP@xfb%
+ \FPadd\FP@tmp\FP@tmpc\FP@tmpb%
+ \fi\fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute x pow y
+
+\def\FP@pow@zero#1{%
+ \FPifzero{#1}%
+ \FP@errmessage{0-th pow of 0 not defined}%
+ \else%
+ \edef\FP@tmp{0}%
+ \fi%
+}
+
+\def\FP@pow#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 base
+ % #3 exponent
+ %
+ \FP@beginmessage{POW}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#2}%
+ \FP@pow@zero{#3}%
+ \else%
+ \FPln\FP@tmpd{#2}%
+ \FPmul\FP@tmpd\FP@tmpd{#3}%
+ \FPexp\FP@tmp\FP@tmpd%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute y-th root of x
+
+\def\FP@root#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 base
+ % #3 which root
+ %
+ \FP@beginmessage{ROOT}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FPifzero{#3}%
+ \FP@errmessage{0-th root not defined}%
+ \fi%
+ %
+ \FPifzero{#2}%
+ \edef\FP@tmp{0}%
+ \else%
+ \FPln\FP@tmpd{#2}%
+ \FPdiv\FP@tmpd\FP@tmpd{#3}%
+ \FPexp\FP@tmp\FP@tmpd%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
diff --git a/macros/latex/contrib/fp/fp-pas.sty b/macros/latex/contrib/fp/fp-pas.sty
new file mode 100644
index 0000000000..8cef34d97a
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-pas.sty
@@ -0,0 +1,118 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-pas}[1994/08/29]
+
+%version information
+\def\FP@pasversion{1.0}
+\message{%
+ `Fixed Point Pascal Triangle',%
+ \space\space\space%
+ Version \FP@pasversion\space%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp-basic}
+
+%%%public area (macros which may be used)%%%
+
+\def\FPpascal#1#2{\FP@pascal{#1}{#2}}%pascal triangle for lines 0,...,63
+
+%%%private fp-area (don't use these macros)%%%
+
+%allocation of registers
+\countdef\FP@pas=50
+\countdef\FP@pasc=51
+
+%addition of two natural numbers
+\def\FP@pasadd#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 1st value
+ % #3 2nd value
+ {\FP@removeleadingzeros#2\relax%
+ \expandafter\FP@setintcounter\FP@tmp000000000000000000\relax%
+ \FP@xia=\FP@rega%
+ \FP@xib=\FP@regb%
+ %
+ \FP@removeleadingzeros#3\relax%
+ \expandafter\FP@setintcounter\FP@tmp000000000000000000\relax%
+ \FP@yia=\FP@rega%
+ \FP@yib=\FP@regb%
+ %
+ \advance\FP@xia\FP@yia%
+ \advance\FP@xib\FP@yib%
+ \ifnum\FP@xib<1000000000\relax\else%
+ \advance\FP@xia1\relax%
+ \advance\FP@xib-1000000000\relax%
+ \fi%
+ \ifnum\FP@xia<1000000000\relax\else%
+ \FP@errmessage{Overflow}%
+ \fi%
+ %
+ \ifnum\FP@xia=0\relax%
+ \edef\FP@tmpa{\the\FP@xib}%
+ \else%
+ \advance\FP@xib1000000000%
+ \edef\FP@tmpa{\the\FP@xia\expandafter\FP@ignorenext\the\FP@xib}%
+ \fi%
+ %
+ \global\let\FP@tmpa\FP@tmpa%
+ }%
+ %
+ \let#1\FP@tmpa%
+}
+
+%the first two entries of the pascal-triangle
+\expandafter\edef\csname FP@pas0\endcsname{[1]}
+\expandafter\edef\csname FP@pas1\endcsname{[1,1]}
+
+%which is the highest line of the pascal-triangle we have already computed?
+\expandafter\edef\csname FP@pascount\endcsname{1}
+
+%compute next line of pascal-triangle
+\def\FP@pasdouble[#1]{%
+ % #1 previous line of pascal-triangle
+ \edef\FP@old{}%
+ \edef\FP@tmpb{}%
+ \@for\FP@new:=#1\do{%
+ \expandafter\if!\FP@old!\relax%
+ \edef\FP@old{\FP@new}%
+ \else%
+ \FP@pasadd{\FP@tmpa}{\FP@old}{\FP@new}%
+ \edef\FP@tmpb{\FP@tmpb,\FP@tmpa}%
+ \edef\FP@old{\FP@new}%
+ \fi%
+ }%
+ \global\edef\FP@tmpb{[1\FP@tmpb,1]}%
+}
+
+%compute n-th line of pascal-triangle
+\def\FP@pascomp#1{%
+ % #1 which line to compute
+ \expandafter\FP@pasc\FP@pascount\relax%
+ \ifnum\FP@pasc<#1\relax%
+ \loop%
+ \ifnum\FP@pasc<#1\relax%
+ \expandafter\expandafter\expandafter\FP@pasdouble\csname FP@pas\the\FP@pasc\endcsname%
+ \advance\FP@pasc1\relax%
+ \edef\next{\noexpand\global\noexpand\let\csname FP@pas\the\FP@pasc\endcsname\noexpand\FP@tmpb}%
+ \next%
+ \repeat%
+ \fi%
+ \global\edef\FP@pascount{\the\FP@pasc}%
+}
+
+\def\FP@pascal#1#2{%
+ % #1 macro, which gets the result
+ % #2 which line of the pascal-triangle to compute
+ {\FP@beginmessage{PASCAL}%
+ %
+ \FP@pas#2\relax%
+ \FP@pascomp\FP@pas%
+ \global\edef\FP@tmp{\csname FP@pas\the\FP@pas\endcsname}%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
diff --git a/macros/latex/contrib/fp/fp-random.sty b/macros/latex/contrib/fp/fp-random.sty
new file mode 100644
index 0000000000..72bf17f1f1
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-random.sty
@@ -0,0 +1,120 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-random}[1995/02/23]
+
+% Version information
+\def\FP@randomversion{1.0a}
+\message{%
+ `Fixed Point Random,%
+ \space\space\space\space\space\space%
+ \space\space\space\space\space\space\space%
+ Version \FP@randomversion%
+ \space(C) Denis Girou (CNRS/IDRIS)%
+ \space\space\space%
+}
+
+% Resolve dependencies
+\RequirePackage{fp-basic}
+
+% Uniform random value
+
+\newcount\FPseed % Seed value
+
+\def\FPrandom#1{%
+ % #1 macro, which gets the result
+ %
+ % Uniform random number generator (numbers between 0 and 1)
+ %
+ % Algorithm reproduce from a very old Fortran program (unknown origin!)
+ %
+ % double precision function RANF()
+ %
+ % integer SEED
+ % common /COMSEED/SEED
+ % *
+ % integer A,M,Q,R
+ % parameter(A=16807,M=2147483647,Q=127773,R=2836)
+ % *
+ % integer LO,HI,TEST
+ % *
+ % HI = SEED/Q
+ % LO = SEED-HI*Q
+ % TEST = A*LO-R*HI
+ % if(TEST.gt.0) then
+ % SEED = TEST
+ % else
+ % SEED = TEST+M
+ % endif
+ % *
+ % RANF = DFLOAT(SEED)/DFLOAT(M)
+ % *
+ % end
+ %
+ % The macro used a seed value, defined by the counter \FPseed.
+ % If it's unknown at first call, we used an arbitrary value.
+ %
+ % We verify that we obtain the same results as in Fortran
+ %
+ % The algorithm seems fairly good. With the Fortran version, we obtain
+ % typically something like 49954 numbers between 0 and 0.5 and 50046 between
+ % 0.5 and 1 for 100000 random numbers, depending of the seed value used.
+ %
+ % To generate a "pseudo-random" seed, you can consider to use the \time
+ % macro, to intialize the random numbers generator according to the time.
+ % Something like:
+ % \FPseed=\the\time
+ % \multiply\FPseed\the\day
+ % \multiply\FPseed\the\month
+ % \multiply\FPseed\the\year
+ %
+ % Of course, it is very slow comparing to "standard" programming
+ % languages. On a RS 6000 370, it's take 51s to generate 100 numbers,
+ % loading time of the test program included (and 0.2s for the Fortran
+ % version ... for 100000 numbers!)
+ % But you must also notice that Hans van der Meer published in TUGboat
+ % Vol. 15, 1, March 1994, pages 57-58, an article on "Random bit generator
+ % in TeX". In fact, he doesn't give a complete solution to generate uniform
+ % random numbers, but at least give some interesting ideas, and also the
+ % code of a simple but powerful macro \SRtest{choice 1}{choice 2}, which
+ % allow to execute the instructions of "choice 1" or those of "choice 2"
+ % with a probability of 1/2 each. As his method is based on shifts of bits
+ % with almost no computations, it's very fast (around 1000 faster than to do
+ % the same thing that \SRtest with \FPrandom.)
+ %
+ {\FP@beginmessage{RANDOM}%
+ %
+ \ifnum\FPseed=0%
+ \FPseed=123456789%
+ \FP@debug{random: seed value undefined! We will used \the\FPseed.^^J%
+ Define it if you want to generate a different sequence of random%
+ numbers.}%
+ \else%
+ \FP@debug{random: seed value used: \the\FPseed}%
+ \fi%
+ %
+ \FP@xia=\FPseed%
+ \divide\FP@xia by 127773%
+ \FP@xib=\FP@xia%
+ \multiply\FP@xib by 127773%
+ \advance\FP@xib by -\FPseed%
+ \FP@xib=-\FP@xib%
+ \multiply\FP@xia by 2836%
+ \FPseed=\FP@xib%
+ \multiply\FPseed by 16807%
+ \advance\FPseed by -\FP@xia%
+ %
+ \ifnum\FPseed>0%
+ \else%
+ \advance\FPseed by 2147483647%
+ \fi%
+ \FPdiv\FP@tmpa{\the\FPseed}{2147483647}%
+ \global\let\FP@tmp\FP@tmpa%
+ \global\FPseed=\FPseed%
+ \FP@debug{random: random number: \FP@tmp\space%
+ (new seed value: \the\FPseed)}%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+\endinput
diff --git a/macros/latex/contrib/fp/fp-snap.sty b/macros/latex/contrib/fp/fp-snap.sty
new file mode 100644
index 0000000000..f4961b7d3f
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-snap.sty
@@ -0,0 +1,242 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-snap}[1995/04/05]
+
+%version information
+\def\FP@snapversion{1.0a}
+\message{%
+ `Fixed Point Snap Off',%
+ \space\space\space\space\space\space\space\space\space\space%
+ Version \FP@snapversion%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp-basic}
+
+%%%public area (macros which may be used)%%%
+
+\def\FPround#1#2#3{\FP@calld\FP@round#1{#2}{#3}}
+\def\FPtrunc#1#2#3{\FP@calld\FP@trunc#1{#2}{#3}}
+\def\FPclip#1#2{\FP@calld\FP@clip#1{#2}}
+
+%%%private fp-area (don't use these macros)%%%
+
+%round value
+\def\FP@round#1#2.#3.#4\relax#5{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the second '.'
+ % #5 round position
+ {\FP@beginmessage{ROUND}%
+ %
+ \FP@count=#5\relax%
+ %
+ \ifnum\FP@count<0\relax%
+ \FP@errmessage{Rounding value before point not allowed}%
+ \else%
+ \FP@readvalue{x}{#2}{#3}%
+ \ifnum\FP@count=0\relax%
+ \ifnum\FP@xfa<500000000\relax%
+ \edef\FP@tmp{#2}%
+ \else%
+ \advance\FP@xib1\relax%
+ \ifnum\FP@xib<1000000000\relax\else%
+ \advance\FP@xia1\relax%
+ \advance\FP@xib-1000000000\relax%
+ \fi%
+ \ifnum\FP@xs<0\relax%
+ \edef\FP@tmp{-}%
+ \else%
+ \edef\FP@tmp{}%
+ \fi%
+ \ifnum\FP@xia=0\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xib}%
+ \else%
+ \advance\FP@xib1000000000\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xia\expandafter\FP@ignorenext\the\FP@xib}%
+ \fi%
+ \fi%
+ \else%
+ \ifnum\FP@count>18\relax%
+ \FP@count=18\relax%
+ \fi%
+ \advance\FP@xfa1000000000\relax%
+ \advance\FP@xfb1000000000\relax%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\the\FP@xfa\expandafter\FP@ignorenext\the\FP@xfb}%
+ \edef\FP@rd{}%
+ \FP@shift=\FP@count%
+ \FP@times=1\relax%
+ \loop%
+ \ifnum\FP@count>0\relax%
+ \edef\FP@rd{\FP@rd\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \advance\FP@count-1\relax%
+ \multiply\FP@times10\relax\ifnum\FP@times=1000000000\relax\FP@times=1\relax\fi%
+ \repeat%
+ \edef\FP@tmp{\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \expandafter\FP@rega\FP@tmp\relax%
+ \ifnum\FP@rega>4\relax%
+ \ifnum\FP@shift>8\relax%
+ \FP@ninesplit\FP@rd%
+ \expandafter\FP@rega\expandafter0\FP@rd\relax%
+ \advance\FP@rega1\relax%
+ \ifnum\FP@rega<\FP@times%
+ \advance\FP@rega\FP@times%
+ \advance\FP@res1000000000\relax%
+ \else%
+ \advance\FP@res1\relax%
+ \ifnum\FP@res<1000000000\relax%
+ \advance\FP@res1000000000\relax%
+ \else%
+ \advance\FP@xib1\relax%
+ \ifnum\FP@xib<1000000000\relax\else%
+ \advance\FP@xia1\relax%
+ \advance\FP@xib-1000000000\relax%
+ \fi%
+ \fi%
+ \fi%
+ \edef\FP@tmpa{\expandafter\FP@ignorenext\the\FP@res\expandafter\FP@ignorenext\the\FP@rega}%
+ \else%
+ \expandafter\FP@rega\FP@rd\relax%
+ \advance\FP@rega1\relax%
+ \ifnum\FP@rega<\FP@times%
+ \advance\FP@rega\FP@times%
+ \else%
+ \advance\FP@xib1\relax%
+ \ifnum\FP@xib<1000000000\relax\else%
+ \advance\FP@xia1\relax%
+ \advance\FP@xib-1000000000\relax%
+ \fi%
+ \fi%
+ \edef\FP@tmpa{\expandafter\FP@ignorenext\the\FP@rega}%
+ \fi%
+ \else%
+ \edef\FP@tmpa{\FP@rd}%
+ \fi%
+ \ifnum\FP@xs<0\relax%
+ \edef\FP@tmp{-}%
+ \else%
+ \edef\FP@tmp{}%
+ \fi%
+ \ifnum\FP@xia=0\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xib.\FP@tmpa}%
+ \else%
+ \advance\FP@xib1000000000\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xia\expandafter\FP@ignorenext\the\FP@xib.\FP@tmpa}%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%trunc value
+
+\def\FP@trunc#1#2.#3.#4\relax#5{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the second '.'
+ % #5 trunc position
+ {\FP@beginmessage{TRUNC}%
+ %
+ \FP@count=#5\relax%
+ %
+ \ifnum\FP@count<0\relax%
+ \FP@errmessage{Truncating value before point not allowed}%
+ \else\ifnum\FP@count=0\relax%
+ \edef\FP@tmp{#2}%
+ \else%
+ \ifnum\FP@count>18\relax%
+ \FP@count=18\relax%
+ \fi%
+ \FP@readvalue{x}{#2}{#3}%
+ \advance\FP@xfa1000000000\relax%
+ \advance\FP@xfb1000000000\relax%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\the\FP@xfa\expandafter\FP@ignorenext\the\FP@xfb}%
+ \edef\FP@tmpa{}%
+ \loop%
+ \ifnum\FP@count>0\relax%
+ \edef\FP@tmpa{\FP@tmpa\expandafter\FP@first\FP@tmp\noexpand\relax}%
+ \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
+ \advance\FP@count-1\relax%
+ \repeat%
+ \ifnum\FP@xs<0\relax%
+ \edef\FP@tmp{-}%
+ \else%
+ \edef\FP@tmp{}%
+ \fi%
+ \ifnum\FP@xia=0\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xib.\FP@tmpa}%
+ \else%
+ \advance\FP@xib1000000000\relax%
+ \edef\FP@tmp{\FP@tmp\the\FP@xia\expandafter\FP@ignorenext\the\FP@xib.\FP@tmpa}%
+ \fi%
+ \fi\fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
+
+%clip value
+
+\def\FP@revert#1#2{%
+ % #1 macro, which gets the result
+ % #2 value
+ {\edef\FP@tmpa{#2}%
+ \edef\FP@tmp{}%
+ \loop%
+ \expandafter\if!\FP@tmpa!\relax\else%
+ \edef\FP@tmpb{\expandafter\FP@first\FP@tmpa\noexpand\relax}%
+ \edef\FP@tmpa{\expandafter\FP@ignorenext\FP@tmpa}%
+ \edef\FP@tmp{\FP@tmpb\FP@tmp}%
+ \repeat%
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ \let#1\FP@tmp%
+}
+
+\def\FP@clip#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everthing after the 2nd '.'
+ %
+ {\FP@beginmessage{CLIP}%
+ %
+ \FP@revert\FP@tmpb{#3}%
+ \FP@removeleadingzeros\FP@tmpb\relax%
+ \FP@revert\FP@tmpb\FP@tmp%
+ \edef\FP@tmpa{#2}%
+ \FP@removeleadingzeros\FP@tmpa\relax%
+ \edef\FP@tmpa{\FP@tmp}%
+ \expandafter\if!\FP@tmpa!\relax%
+ \expandafter\if!\FP@tmpb!\relax%
+ \edef\FP@tmp{0}%
+ \else%
+ \edef\FP@tmp{0.\FP@tmpb}%
+ \fi%
+ \else%
+ \expandafter\if!\FP@tmpb!\relax%
+ \edef\FP@tmp{\FP@tmpa}%
+ \else%
+ \edef\FP@tmp{\FP@tmpa.\FP@tmpb}%
+ \fi%
+ \fi%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ \let#1\FP@tmp%
+}
diff --git a/macros/latex/contrib/fp/fp-trigo.sty b/macros/latex/contrib/fp/fp-trigo.sty
new file mode 100644
index 0000000000..06cfa30f9f
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-trigo.sty
@@ -0,0 +1,1119 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-trigo}[1995/04/14]
+
+%version information
+\def\FP@trigoversion{0.9e}
+\message{%
+ `Fixed Point Trigonometry',%
+ \space\space\space\space\space\space%
+ Version \FP@trigoversion%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp-basic}
+
+%%%public area (macros which may be used)%%%
+
+%constants
+\edef\FPpi{3.141592653589793238}
+
+%unary functions
+\def\FPsin#1#2{\FP@calld\FP@sin#1{#2}}
+\def\FPcos#1#2{\FP@calld\FP@cos#1{#2}}
+\def\FPsincos#1#2#3{\FP@calle\FP@sincos#1#2{#3}}
+\def\FPtan#1#2{\FP@calld\FP@tan#1{#2}}
+\def\FPcot#1#2{\FP@calld\FP@cot#1{#2}}
+\def\FPtancot#1#2#3{\FP@calle\FP@tancot#1#2{#3}}
+\def\FParcsin#1#2{\FP@calld\FP@arcsin#1{#2}}
+\def\FParccos#1#2{\FP@calld\FP@arccos#1{#2}}
+\def\FParcsincos#1#2#3{\FP@calle\FP@arcsincos#1#2{#3}}
+\def\FParctan#1#2{\FP@calld\FP@arctan#1{#2}}
+\def\FParccot#1#2{\FP@calld\FP@arccot#1{#2}}
+\def\FParctancot#1#2#3{\FP@calle\FP@arctancot#1#2{#3}}
+
+%%%private fp-area (don't use these macros)%%%
+
+%allocate registers
+
+\countdef\FP@ls=50
+\countdef\FP@lfa=51
+\countdef\FP@lfb=52
+
+\countdef\FP@loops=53
+\countdef\FP@oct=54
+
+\countdef\FP@@arccos=55
+\countdef\FP@oldvala=56
+\countdef\FP@oldvalb=57
+\countdef\FP@subfpih=58
+
+%compute 0<=x<2pi for value 2pi*n + x
+
+\def\FP@modtwopi#1#2{%result is the family {x}
+ % #1 integer part of value
+ % #2 fractional part of value
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifnum\ifnum\FP@xib=0 1\else0\fi\ifnum\FP@xia<6 1\else0\fi<11\relax%
+ %compute modulo without caring about sign
+ \FP@shift=0\relax%
+ \FP@ys=1\FP@yia=628318530\FP@yib=717958647\FP@yfa=692528676\FP@yfb=655900577\relax%2*pi
+ \loop%
+ \ifnum\FP@xia<100000000\relax%
+ \FP@multen{x}%
+ \advance\FP@shift-1\relax%
+ \repeat%
+ \FP@loops=18\relax\advance\FP@loops\FP@shift%
+ \loop%
+ \ifnum\FP@loops=0\else%
+ \advance\FP@loops-1\relax%
+ \FP@counttimes%divides x by \FP@times*y%
+ \FP@divten{y}%
+ \repeat%
+ \loop%
+ \ifnum\FP@shift<0%
+ \advance\FP@shift1\relax%
+ \FP@divten{x}%
+ \repeat%
+ \fi%
+ %correct the result for negative values (modulo is positive)
+ \loop%should be computed only once
+ \ifnum\FP@xs<0\relax%
+ \advance\FP@xfb-179586477\relax\FP@xfb=-\FP@xfb%
+ \ifnum\FP@xfb<0\relax%
+ \advance\FP@xfb1000000000\relax%
+ \advance\FP@xfa1\relax%
+ \fi%
+ \advance\FP@xfa-283185307\relax\FP@xfa=-\FP@xfa%
+ \ifnum\FP@xfa<0\relax%
+ \advance\FP@xfa1000000000\relax%
+ \advance\FP@xib1\relax%
+ \fi%
+ \advance\FP@xib-6\relax\FP@xib=-\FP@xib%
+ \ifnum\FP@xib<0%
+ \FP@errmessage{Error in calculation: This shouldn't happen!}%
+ \else%
+ \FP@xs=1\relax%
+ \fi%
+ \repeat%
+}
+
+%auxiliary functions
+
+\def\FP@trigocmpsval#1#2#3{%
+ % #1 macro, which gets the result
+ % #2 9 digits integer value
+ % #3 9 digits integer value
+ \ifnum#2<#3\relax%
+ #1=-1\relax%
+ \else\ifnum#2>#3\relax%
+ #1=1\relax%
+ \else%
+ #1=0\relax%
+ \fi\fi%
+}
+
+\def\FP@trigocmpval#1#2#3#4#5#6#7{%
+ % #1 macro, which gets the result
+ % #2 9 digits integer value
+ % #3 9 digits integer value
+ % #4 9 digits integer value
+ % #5 9 digits integer value
+ % #6 9 digits integer value
+ % #7 9 digits integer value
+ %
+ \FP@trigocmpsval#1{#2}{#5}%
+ \ifnum#1=0\relax\FP@trigocmpsval#1{#3}{#6}\relax\fi%
+ \ifnum#1=0\relax\FP@trigocmpsval#1{#4}{#7}\relax\fi%
+}
+
+\def\FP@trigosub#1#2#3#4#5#6{%
+ % #1 resulting fractional part one
+ % #2 resulting fractional part two
+ % #3 1st value fractional part one
+ % #4 1st value fractional part two
+ % #5 2nd value fractional part one
+ % #6 2nd value fractional part two
+ \FP@rfb=#4\relax\advance\FP@rfb-#6\relax%
+ \FP@rfa=#3\relax\advance\FP@rfa-#5\relax%
+ \ifnum\FP@rfb<0\relax%
+ \advance\FP@rfa-1\relax%
+ \advance\FP@rfb1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<0\relax%
+ \advance\FP@rfa1000000000\relax%
+ \fi%
+ #1=\FP@rfa%
+ #2=\FP@rfb%
+}
+
+%compute octand of value and transform value to one between 0 and pi/4
+
+\def\FP@octand#1#2{%resulting values \FP@oct, family {x}
+ % #1 integer part of value
+ % #2 fractional part of value
+ %
+ \FP@modtwopi{#1}{#2}%
+ %now it is 0<={x}<2pi
+ %
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{3}{141592653}{589793238}%
+ \ifnum\FP@oct>0\relax%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{4}{712388980}{384689858}%
+ \ifnum\FP@oct>0\relax%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{5}{497787143}{782138167}%
+ \ifnum\FP@oct>0\relax%
+ \FP@oct=7\relax%
+ \FP@trigosub\FP@xfa\FP@xfb{283185307}{179586477}\FP@xfa\FP@xfb%
+ \else%
+ \FP@oct=6\relax%
+ \FP@trigosub\FP@xfa\FP@xfb\FP@xfa\FP@xfb{712388980}{384689858}%
+ \fi%
+ \else%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{3}{926990816}{987241548}%
+ \ifnum\FP@oct>0\relax%
+ \FP@oct=5\relax%
+ \FP@trigosub\FP@xfa\FP@xfb{712388980}{384689858}\FP@xfa\FP@xfb%
+ \else%
+ \FP@oct=4\relax%
+ \FP@trigosub\FP@xfa\FP@xfb\FP@xfa\FP@xfb{141592653}{589793238}%
+ \fi%
+ \fi%
+ \else%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{1}{570796326}{794896619}%
+ \ifnum\FP@oct>0\relax%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{2}{356194490}{192344929}%
+ \ifnum\FP@oct>0\relax%
+ \FP@oct=3\relax%
+ \FP@trigosub\FP@xfa\FP@xfb{141592653}{589793238}\FP@xfa\FP@xfb%
+ \else%
+ \FP@oct=2\relax%
+ \FP@trigosub\FP@xfa\FP@xfb\FP@xfa\FP@xfb{570796326}{794896619}%
+ \fi%
+ \else%
+ \FP@trigocmpval\FP@oct\FP@xib\FP@xfa\FP@xfb{0}{785398163}{397448310}%
+ \ifnum\FP@oct>0\relax%
+ \FP@oct=1\relax%
+ \FP@trigosub\FP@xfa\FP@xfb{570796326}{794896619}\FP@xfa\FP@xfb%
+ \else%
+ \FP@oct=0\relax%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \FP@xib=0\relax%
+}
+
+%auxiliary functions
+
+\def\FP@trigo@mul#1#2#3#4#5#6{%
+ % #1 macro which gets fractional part 1
+ % #2 macro which fractional part 1
+ % #3 first value part 1
+ % #4 first value part 2
+ % #5 second value part 1
+ % #6 second value part 2
+ \FP@split\FP@xq\FP@xr\FP@xz{#3}\FP@split\FP@xt\FP@xu\FP@xv{#4}%
+ \FP@split\FP@yq\FP@yr\FP@yz{#5}\FP@split\FP@yt\FP@yu\FP@yv{#6}%
+ \FP@prod=0\relax%
+ \edef\FP@rd{}%
+ \FP@@mul vv \relax\FP@saveshift%
+ \FP@@mul vu uv \relax\FP@saveshift%
+ \FP@@mul uu vt tv \relax\FP@saveshift%
+ \FP@@mul ut tu vz zv \relax\FP@saveshift%
+ \FP@@mul tt uz zu vr rv \relax\FP@saveshift%
+ \FP@@mul zt tz ur ru qv vq \relax\FP@saveshift%
+ \FP@@mul zz rt tr qu uq \relax\FP@saveshift%
+ \FP@@mul rz zr qt tq \relax\FP@saveshift%
+ \FP@@mul rr qz zq \relax\FP@saveshift%
+ \FP@@mul qr rq \relax\FP@saveshift%
+ \FP@@mul qq \relax\FP@saveshift\FP@saveshift%
+ \FP@ninesplit\FP@rd#1=\FP@res%
+ \FP@ninesplit\FP@rd#2=\FP@res%
+}
+
+\def\FP@trigo@divn#1#2#3#4#5{%
+ % #1 macro which gets fractional part 1
+ % #2 macro which gets fractional part 2
+ % #3 value part 1
+ % #4 value part 2
+ % #5 integer (0,..,1000)
+ \FP@rega=#3\divide\FP@rega#5%
+ \FP@regd=\FP@rega%
+ \multiply\FP@rega#5\relax%
+ \advance\FP@rega-#3\relax%
+ \multiply\FP@rega-1000\relax%
+ \FP@regb=#4\divide\FP@regb1000000\relax%
+ \advance\FP@rega\FP@regb%
+ \FP@regc=\FP@rega\divide\FP@regc#5\relax%
+ \FP@rege=\FP@regc\multiply\FP@rege1000000\relax%
+ \multiply\FP@regc#5\advance\FP@rega-\FP@regc\multiply\FP@rega1000000\relax%
+ \multiply\FP@regb1000000\relax\advance\FP@regb-#4\relax%
+ \advance\FP@rega-\FP@regb%
+ \divide\FP@rega#5\relax%
+ \advance\FP@rege\FP@rega%
+ #1=\FP@regd%
+ #2=\FP@rege%
+}
+
+%sine and cosine
+
+\def\FP@sincos@loop#1#2{%
+ % #1 fractional part 1 of value
+ % #2 fractional part 2 of value
+ \loop%
+ \FP@ls=-\FP@ls%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb{#1}{#2}%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb{#1}{#2}%
+ \FP@trigo@divn\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@count%
+ \advance\FP@count1\relax%
+ \FP@trigo@divn\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@count%
+ \advance\FP@count1\relax%
+ \ifnum\ifnum\FP@lfa=0 0\else1\fi\ifnum\FP@lfb=0 0\else1\fi>0\relax%
+ \ifnum\FP@ls>0\relax%
+ \advance\FP@rfa\FP@lfa%
+ \advance\FP@rfb\FP@lfb%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\relax%
+ \advance\FP@rfb-1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\relax%
+ \advance\FP@rfa-1000000000\relax%
+ \fi%
+ \else%
+ \advance\FP@rfa-\FP@lfa%
+ \advance\FP@rfb-\FP@lfb%
+ \ifnum\FP@rfb<0\relax%
+ \advance\FP@rfa-1\relax%
+ \advance\FP@rfb1000000000\relax%
+ \fi%
+ \ifnum\FP@rfa<0\relax%
+ \advance\FP@rib-1\relax%
+ \advance\FP@rfa1000000000\relax%
+ \fi%
+ \fi%
+ \repeat%
+}
+
+%sine for values 0<=v<=pi/4
+\def\FP@@sin#1#2{%
+ % #1 fractional part 1
+ % #2 fractional part 2
+ \ifnum\ifnum#1=0 0\else1\fi\ifnum#2=0 0\else1\fi=0\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
+ \else%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=#1\FP@rfb=#2\relax%
+ \FP@ls=1\FP@lfa=#1\FP@lfb=#2\relax%
+ \FP@count=2\relax%
+ \FP@sincos@loop{#1}{#2}%
+ \fi%
+}
+
+%cosine for values 0<=v<=pi/4
+\def\FP@@cos#1#2{%
+ % #1 fractional part 1
+ % #2 fractional part 2
+ \ifnum\ifnum#1=0 0\else1\fi\ifnum#2=0 0\else1\fi=0\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=1\FP@rfa=0\FP@rfb=0\relax%
+ \else%
+ \FP@ls=-1\FP@lfa=#1\FP@lfb=#2\relax%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@lfa\FP@lfb%
+ \FP@trigo@divn\FP@lfa\FP@lfb\FP@lfa\FP@lfb{2}%
+ \FP@count=3\relax%
+ \FP@rs=1\FP@ria=0\relax%
+ \ifnum\FP@lfb=0\relax%
+ \ifnum\FP@lfa=0\relax%
+ \FP@rib=1\FP@rfa=0\FP@rfb=0\relax%
+ \else%
+ \FP@rib=0\FP@rfa=1000000000\FP@rfb=0\relax%
+ \fi%
+ \else%
+ \FP@rib=0\FP@rfa=999999999\FP@rfb=1000000000\relax%
+ \fi%
+ \advance\FP@rfb-\FP@lfb\advance\FP@rfa-\FP@lfa%
+ \FP@sincos@loop{#1}{#2}%
+ \fi%
+}
+
+\def\FP@sin#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ \FP@beginmessage{SIN}%
+ %
+ {\FP@octand{#2}{#3}%
+ %
+ \ifnum\FP@oct<4\relax%
+ \ifnum\FP@oct<2\relax%
+ \ifnum\FP@oct<1\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \fi%
+ \else%
+ \ifnum\FP@oct<3\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \fi%
+ \fi%
+ \else%
+ \ifnum\FP@oct<6\relax%
+ \ifnum\FP@oct<5\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \fi%
+ \else%
+ \ifnum\FP@oct<7\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \FP@store\FP@tmp{r}%
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+\def\FP@cos#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ \FP@beginmessage{COS}%
+ %
+ {\FP@octand{#2}{#3}%
+ %
+ \ifnum\FP@oct<4\relax%
+ \ifnum\FP@oct<2\relax%
+ \ifnum\FP@oct<1\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \fi%
+ \else%
+ \ifnum\FP@oct<3\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \fi%
+ \fi%
+ \else%
+ \ifnum\FP@oct<6\relax%
+ \ifnum\FP@oct<5\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \fi%
+ \else%
+ \ifnum\FP@oct<7\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \fi%
+ \fi%
+ \fi%
+ %
+ \FP@store\FP@tmp{r}%
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+\def\FP@@sincos#1#2{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ %
+ \FP@octand{#1}{#2}%
+ %
+ \ifnum\FP@oct<4\relax%
+ \ifnum\FP@oct<2\relax%
+ \ifnum\FP@oct<1\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpc{r}%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpb{r}%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpc{r}%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpb{r}%
+ \fi%
+ \else%
+ \ifnum\FP@oct<3\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpc{r}%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpb{r}%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpc{r}%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpb{r}%
+ \fi%
+ \fi%
+ \else%
+ \ifnum\FP@oct<6\relax%
+ \ifnum\FP@oct<5\relax%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpc{r}%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpb{r}%
+ \else%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpc{r}%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpb{r}%
+ \fi%
+ \else%
+ \ifnum\FP@oct<7\relax%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpc{r}%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpb{r}%
+ \else%
+ \FP@@sin\FP@xfa\FP@xfb%
+ \FP@rs=-\FP@rs%
+ \FP@store\FP@tmpc{r}%
+ \FP@@cos\FP@xfa\FP@xfb%
+ \FP@store\FP@tmpb{r}%
+ \fi%
+ \fi%
+ \fi%
+}
+
+\def\FP@sincos#1#2#3.#4.#5\relax{%
+ % #1 macro, which gets the sine result
+ % #2 macro, which gets the cosine result
+ % #3 integer part of value
+ % #4 fractional part of value
+ % #5 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{SINCOS}%
+ %
+ \FP@@sincos{#3}{#4}%
+ %
+ \global\let\FP@tmpc\FP@tmpc%sine
+ \global\let\FP@tmpb\FP@tmpb%cosine
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmpc%
+ \let#2\FP@tmpb%
+ }
+
+%tan and cot
+
+\def\FP@tan#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ \FP@beginmessage{TAN}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FP@@sincos{#2}{#3}%
+ %
+ \FPdiv\FP@tmp\FP@tmpc\FP@tmpb%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+\def\FP@cot#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ \FP@beginmessage{COT}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FP@@sincos{#2}{#3}%
+ %
+ \FPdiv\FP@tmp\FP@tmpb\FP@tmpc%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmp%
+}
+
+\def\FP@tancot#1#2#3.#4.#5\relax{%
+ % #1 macro, which gets the tan result
+ % #1 macro, which gets the cot result
+ % #3 integer part of value
+ % #4 fractional part of value
+ % #5 dummy to swallow everything after the 2nd '.'
+ %
+ \FP@beginmessage{TANCOT}%
+ %
+ {\def\FP@beginmessage##1{}%
+ \def\FP@endmessage##1{}%
+ %
+ \FP@@sincos{#3}{#4}%
+ %
+ \FPdiv\FP@tmpd\FP@tmpc\FP@tmpb%
+ \FPdiv\FP@tmp\FP@tmpb\FP@tmpc%
+ %
+ \global\let\FP@tmpd\FP@tmpd%
+ \global\let\FP@tmp\FP@tmp%
+ }%
+ %
+ \FP@endmessage{}%
+ %
+ \let#1\FP@tmpd%
+ \let#2\FP@tmp%
+}
+
+%auxiliary functions
+
+% compute x/(x+1) for 0<=x<=1000000
+\def\FP@trigo@xy#1#2#3{%
+ % #1 macro, which gets fractional part 1
+ % #2 macro, which gets fractional part 2
+ % #3 natural number
+ \FP@rega=#3\relax\FP@regb=\FP@rega\advance\FP@regb1\relax%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ #1=\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ \multiply#11000\relax\advance#1\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ \multiply#11000\relax\advance#1\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ #2=\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ \multiply#21000\relax\advance#2\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+ \multiply\FP@rega1000\relax%
+ \FP@regc=\FP@rega\divide\FP@regc\FP@regb%
+ \multiply#21000\relax\advance#2\FP@regc%
+ \multiply\FP@regc\FP@regb\advance\FP@rega-\FP@regc%
+}
+
+%if x<=0.707106781 then x:=y else x:=y with x^2 + y^2 = 1
+%sets \FP@@arccos to 0 if x:=y otherwise to 1
+\def\FP@sincos@transform@Rii{%
+ \ifnum\FP@xfa>707106781\relax%
+ \FP@@arccos=1\relax%
+ \FP@trigo@mul\FP@rfa\FP@rfb\FP@xfa\FP@xfb\FP@xfa\FP@xfb%
+ \FP@lfa=1000000000\relax%
+ \advance\FP@lfa-\FP@rfa%
+ \ifnum\FP@rfb>0\relax%
+ \advance\FP@lfa-1\relax%
+ \FP@lfb=1000000000\relax%
+ \advance\FP@lfb-\FP@rfb%
+ \else%
+ \FP@lfb=0\relax%
+ \fi%
+ \FP@xia=710000000\FP@xib0\relax%
+ \FP@xfa=0\FP@xfb=0\relax%
+ \FP@oldvala=0\FP@oldvalb=0\relax%
+ \loop%
+ \ifnum\ifnum\FP@xia=\FP@xfa0\else1\fi\ifnum\FP@xib=\FP@xfb0\else1\fi>0\relax%
+ \FP@rfa\FP@xia\advance\FP@rfa\FP@xfa%
+ \FP@rfb\FP@xib\advance\FP@rfb\FP@xfb%
+ \divide\FP@rfb2\relax%
+ \ifodd\FP@rfa\advance\FP@rfb500000000\relax\fi%
+ \divide\FP@rfa2\relax%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfb-1000000000\relax%
+ \advance\FP@rfa1\relax%
+ \fi%
+ \FP@trigo@mul\FP@ria\FP@rib\FP@rfa\FP@rfb\FP@rfa\FP@rfb%
+ \ifnum\FP@ria<\FP@lfa%
+ \FP@oct=1\relax%
+ \else\ifnum\FP@ria>\FP@lfa%
+ \FP@oct=2\relax%
+ \else\ifnum\FP@rib<\FP@lfb%
+ \FP@oct=1\relax%
+ \else\ifnum\FP@rib>\FP@lfb%
+ \FP@oct=2\relax%
+ \else%
+ \FP@oct=3\relax%
+ \fi\fi\fi\fi%
+ \ifnum\ifnum\FP@ria=\FP@oldvala0\else1\fi\ifnum\FP@rib=\FP@oldvalb0\else1\fi>0\relax%
+ \FP@oldvala=\FP@ria\FP@oldvalb=\FP@rib%
+ \else%
+ \FP@oct=3\relax%
+ \fi%
+ \ifodd\FP@oct%
+ \FP@xfa\FP@rfa\FP@xfb\FP@rfb%
+ \fi%
+ \ifnum\FP@oct>1\relax%
+ \FP@xia\FP@rfa\FP@xib\FP@rfb%
+ \fi%
+ \repeat%
+ \else%
+ \FP@@arccos=0\relax%
+ \fi%
+}
+
+%compute arcsin(abs(x)) resp. arccos(abs(x)) for -1<=x<=1
+%\FP@@arccos determines whether arcsin or arccos has been computed
+\def\FP@arcsincos@loop{%
+ \FP@@arccos=0\relax%
+ \ifnum\ifnum\FP@xia=0 1\else0\fi\ifnum\FP@xib<2 1\else 0\fi>0\relax%
+ \ifnum\FP@xib=1\relax%
+ \ifnum\ifnum\FP@xfa=0 1\else0\fi\ifnum\FP@xfb=0 1\else0\fi>10\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=1\FP@rfa=570796326\FP@rfb=794896619\relax%
+ \else%
+ \FP@errmessage{Number too big}%
+ \fi%
+ \else%
+ \ifnum\ifnum\FP@xfa=0 0\else1\fi\ifnum\FP@xfb=0 0\else1\fi=0\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
+ \else%
+ \FP@sincos@transform@Rii%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=\FP@xfa\FP@rfb=\FP@xfb%
+ \FP@ls=1\FP@lfa=\FP@xfa\FP@lfb=\FP@xfb%
+ \FP@count=1\relax%
+ \loop%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@xfa\FP@xfb%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@xfa\FP@xfb%
+ \FP@trigo@xy\FP@yfa\FP@yfb\FP@count%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@yfa\FP@yfb%
+ \advance\FP@count2\relax%
+ \FP@trigo@divn\FP@yfa\FP@yfb\FP@lfa\FP@lfb\FP@count%
+ \ifnum\ifnum\FP@yfa=0 0\else1\fi\ifnum\FP@yfb=0 0\else 1\fi>0\relax%
+ \advance\FP@rfa\FP@yfa\advance\FP@rfb\FP@yfb%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfb-1000000000\relax%
+ \advance\FP@rfa1\relax%
+ \fi%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rfa-1000000000\relax%
+ \advance\FP@rib1\relax%
+ \fi%
+ \repeat%
+ \fi%
+ \fi%
+ \else%
+ \FP@errmessage{Number too big}%
+ \fi%
+}
+
+%compute sign(r)*r:=#1.#2#3-abs(r) (for abs(r)<=#1.#2#3)
+\def\FP@subrfrom#1#2#3{%
+ % #1 integer part of value to subtract from
+ % #2 fractional part 1 of value to subtract from
+ % #3 fractional part 2 of value to subtract from
+ \FP@ria=#1\relax\advance\FP@ria-\FP@rib\FP@rib\FP@ria%
+ \FP@ria=#2\relax\advance\FP@ria-\FP@rfa\FP@rfa\FP@ria%
+ \FP@ria=#3\relax\advance\FP@ria-\FP@rfb\FP@rfb\FP@ria%
+ \FP@ria=0\relax%
+ \ifnum\FP@rfb<0\relax%
+ \advance\FP@rfb1000000000\relax%
+ \advance\FP@rfa-1\relax%
+ \fi%
+ \ifnum\FP@rfa<0\relax%
+ \advance\FP@rfa1000000000\relax%
+ \advance\FP@rib-1\relax%
+ \fi%
+ \ifnum\FP@rib<0\relax%
+ \FP@errmessage{Subtraction lead to unaccepted value}%
+ \fi%
+}
+
+%compute r:= pi/2 - abs(r) (for abs(r)<=pi/2)
+\def\FP@pihalf@subr{\FP@subrfrom{1}{570796326}{794896619}}
+
+%compute sign(r)*r:= pi-abs(r) (for abs(r)<=pi)
+\def\FP@pi@subr{\FP@subrfrom{3}{141592653}{589793238}}
+
+%compute arcsin
+
+\def\FP@arcsin#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCSIN}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ %
+ \FP@arcsincos@loop%
+ %
+ \ifnum\FP@@arccos=1\relax%
+ \FP@pihalf@subr%
+ \fi%
+ \FP@rs=\FP@xs%
+ %
+ \FP@store\FP@tmp{r}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute arccos
+\def\FP@arccos#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCCOS}%
+ %
+ \FP@readvalue{x}{#2}{#3}%
+ %
+ \FP@arcsincos@loop%
+ %
+ \ifnum\FP@@arccos=0\relax%
+ \FP@pihalf@subr%
+ \fi%
+ \FP@rs=1%
+ \ifnum\FP@xs<0\relax%
+ \FP@pi@subr%
+ \fi%
+ %
+ \FP@store\FP@tmp{r}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute arcsin and arccos
+\def\FP@arcsincos#1#2#3.#4.#5\relax{%
+ % #1 macro, which gets the arcsin-result
+ % #2 macro, which gets the arccos-result
+ % #3 integer part of value
+ % #4 fractional part of value
+ % #5 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCSINCOS}%
+ %
+ \FP@readvalue{x}{#3}{#4}%
+ %
+ \FP@arcsincos@loop%
+ %
+ \FP@xia\FP@ria\FP@xib\FP@rib\FP@xfa\FP@rfa\FP@xfb\FP@rfb%
+ %
+ \ifnum\FP@@arccos=1\relax%
+ \FP@pihalf@subr%
+ \fi%
+ \FP@rs=\FP@xs%
+ \FP@store\FP@tmpa{r}%
+ %
+ \FP@ria\FP@xia\FP@rib\FP@xib\FP@rfa\FP@xfa\FP@rfb\FP@xfb%
+ %
+ \ifnum\FP@@arccos=0\relax%
+ \FP@pihalf@subr%
+ \fi%
+ \FP@rs=1%
+ \ifnum\FP@xs<0\relax%
+ \FP@pi@subr%
+ \fi%
+ \FP@store\FP@tmpb{r}%
+ %
+ \global\let\FP@tmpa\FP@tmpa%
+ \global\let\FP@tmpb\FP@tmpb%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmpa%
+ \let#2\FP@tmpb%
+}
+
+%compute arctan and arccot
+
+%compute 1/y for y>=1
+\def\FP@trigo@inv{%
+ \FP@shift=0\relax%
+ \FP@xia=1000000000\FP@xib=0\FP@xfa=0\FP@xfb=0\relax%
+ \loop%
+ \ifnum\FP@yia<100000000\relax%
+ \FP@multen{y}%
+ \advance\FP@shift1\relax%
+ \repeat%
+ \FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
+ \loop%
+ \ifFP@zero{y}\else%
+ \FP@counttimes%divides x by \FP@times*y%
+ \FP@divten{y}%
+ \FP@multen{r}%
+ \advance\FP@rfb\FP@times%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\advance\FP@rfb-1000000000\relax%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\advance\FP@rfa-1000000000\relax%
+ \ifnum\FP@rib<1000000000\relax\else%
+ \advance\FP@ria1\advance\FP@rib-1000000000\relax%
+ \fi%
+ \fi%
+ \fi%
+ \repeat%
+ \loop%
+ \ifnum\FP@shift<35\relax%
+ \advance\FP@shift1\relax%
+ \FP@divten{r}%
+ \repeat%
+}
+
+%compute 1/sqrt(1+x^2) for 0<=x<1
+\def\FP@trigo@sq\FP@xfa\FP@xfb{%
+ \FP@trigo@mul\FP@yfa\FP@yfb\FP@xfa\FP@xfb\FP@xfa\FP@xfb%
+ \ifnum\FP@yfb=0\relax\else%
+ \FP@yfb=-\FP@yfb%
+ \advance\FP@yfb1000000000\relax%
+ \advance\FP@yfa1\relax%
+ \fi%
+ \FP@yfa=-\FP@yfa%
+ \advance\FP@yfa1250000000\relax%
+ \FP@trigo@mul\FP@yfa\FP@yfb\FP@yfa\FP@yfb{444444444}{444444444}%
+ \FP@lfa=666666666\relax\FP@lfb=666666666\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=\FP@lfa\FP@rfb=\FP@lfb%
+ \FP@count=0\relax%
+ \loop%
+ \advance\FP@count2\relax%
+ \FP@trigo@divn\FP@yia\FP@yib{1000000000}{0}\FP@count%
+ \ifnum\ifnum\FP@yia=0 0\else1\fi\ifnum\FP@yib=0 0\else1\fi>0\relax%
+ \ifnum\FP@yib=0\relax\else%
+ \FP@yib=-\FP@yib%
+ \advance\FP@yib1000000000\relax%
+ \advance\FP@yia1\relax%
+ \fi%
+ \ifnum\FP@yia=0\relax\else%
+ \FP@yia=-\FP@yia%
+ \advance\FP@yia1000000000\relax%
+ \fi%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@yia\FP@yib%
+ \fi%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@yfa\FP@yfb%
+ \ifnum\ifnum\FP@lfa=0 0\else1\fi\ifnum\FP@lfb=0 0\else1\fi=0\relax\else%
+ \advance\FP@rfb\FP@lfb%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfa1\relax%
+ \advance\FP@rfb-1000000000\relax%
+ \fi%
+ \advance\FP@rfa\FP@lfa%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rib1\relax%
+ \advance\FP@rfa-1000000000\relax%
+ \fi%
+ \repeat%
+}
+
+%compute arctan for 0<=x<=0.5
+\def\FP@@arctan{%
+ \ifnum\ifnum\FP@xfa=0 0\else1\fi\ifnum\FP@xfb=0 0\else1\fi=0\relax%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
+ \else%
+ \FP@rs=1\FP@ria=0\FP@rib=0\FP@rfa=\FP@xfa\FP@rfb=\FP@xfb%
+ \FP@lfa=\FP@xfa\FP@lfb=\FP@xfb%
+ \FP@trigo@mul\FP@xfa\FP@xfb\FP@xfa\FP@xfb\FP@xfa\FP@xfb%
+ \FP@count=1\relax%
+ \FP@regs=1\relax%
+ \loop%
+ \FP@regs=-\FP@regs%
+ \advance\FP@count2\relax%
+ \FP@trigo@mul\FP@lfa\FP@lfb\FP@lfa\FP@lfb\FP@xfa\FP@xfb%
+ \FP@trigo@divn\FP@yfa\FP@yfb\FP@lfa\FP@lfb\FP@count%
+ \ifnum\ifnum\FP@yfa=0 0\else1\fi\ifnum\FP@yfb=0 0\else1\fi>0\relax%
+ \ifnum\FP@regs<0\relax%
+ \advance\FP@rfb-\FP@yfb%
+ \ifnum\FP@rfb<0\relax%
+ \advance\FP@rfb1000000000\relax%
+ \advance\FP@rfa-1\relax%
+ \fi%
+ \advance\FP@rfa-\FP@yfa%
+ \ifnum\FP@rfa<0\relax%
+ \advance\FP@rfa1000000000\relax%
+ \advance\FP@rib-1\relax%
+ \fi%
+ \else%
+ \advance\FP@rfb\FP@yfb%
+ \ifnum\FP@rfb<1000000000\relax\else%
+ \advance\FP@rfb-1000000000\relax%
+ \advance\FP@rfa1\relax%
+ \fi%
+ \advance\FP@rfa\FP@yfa%
+ \ifnum\FP@rfa<1000000000\relax\else%
+ \advance\FP@rfa-1000000000\relax%
+ \advance\FP@rib1\relax%
+ \fi%
+ \fi%
+ \repeat%
+ \fi%
+}
+
+%compute arctan
+\def\FP@@arctancot#1#2{%
+ % #1 integer part of value
+ % #2 fractional part of value
+ %
+ \FP@readvalue{x}{#1}{#2}%
+ %
+ \ifnum\ifnum\FP@xia=0 0\else1\fi\ifnum\FP@xib=1 0\else1\fi\ifnum\FP@xfa=0 0\else1\fi\ifnum\FP@xfb=0 0\else1\fi=0\relax%
+ \FP@ria=0\FP@rib=0\FP@rfa=785398163\FP@rfb=397448310\relax%
+ \FP@subfpih=0\relax%
+ \else%
+ \ifnum\ifnum\FP@xia=0 0\else1\fi\ifnum\FP@xib=0 0\else1\fi=0\relax%
+ \FP@subfpih=0\relax%
+ \else%
+ \FP@yia=\FP@xia\FP@yib=\FP@xib\FP@yfa=\FP@xfa\FP@yfb=\FP@xfb%
+ \FP@trigo@inv%
+ \FP@xia=\FP@ria\FP@xib=\FP@rib\FP@xfa=\FP@rfa\FP@xfb=\FP@rfb%
+ \FP@subfpih=1\relax%
+ \fi%
+ \ifnum\FP@xfa>880000000\relax%
+ \FP@trigo@sq\FP@xfa\FP@xfb%
+ \FP@xfa=\FP@rfa\FP@xfb=\FP@rfb%
+ \FP@arcsincos@loop%
+ \ifnum\FP@@arccos=0\relax%
+ \FP@pihalf@subr%
+ \fi%
+ \else%
+ \FP@@arctan\FP@xfa\FP@xfb%
+ \fi%
+ \fi%
+ %
+ \ifnum\FP@subfpih>0\relax%
+ \FP@pihalf@subr%
+ \fi%
+ %
+ \FP@rs=\FP@xs%
+}
+
+%compute arctan
+\def\FP@arctan#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCTAN}%
+ %
+ \FP@@arctancot{#2}{#3}%
+ %
+ \FP@store\FP@tmp{r}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute arccot
+\def\FP@arccot#1#2.#3.#4\relax{%
+ % #1 macro, which gets the result
+ % #2 integer part of value
+ % #3 fractional part of value
+ % #4 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCCOT}%
+ %
+ \FP@@arctancot{#2}{#3}%
+ \ifnum\FP@rs<0\relax%
+ \FP@rs=1\relax%
+ \FP@pihalf@subr%
+ \FP@pi@subr%
+ \else%
+ \FP@pihalf@subr%
+ \fi%
+ %
+ \FP@store\FP@tmp{r}%
+ %
+ \global\let\FP@tmp\FP@tmp%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmp%
+}
+
+%compute arctan and arccot
+\def\FP@arctancot#1#2#3.#4.#5\relax{%
+ % #1 macro, which gets the arcsin-result
+ % #2 macro, which gets the arccos-result
+ % #3 integer part of value
+ % #4 fractional part of value
+ % #5 dummy to swallow everything after the 2nd '.'
+ %
+ {\FP@beginmessage{ARCTANCOT}%
+ %
+ \FP@@arctancot{#3}{#4}%
+ \FP@xs\FP@rs\FP@xia\FP@ria\FP@xib\FP@rib\FP@xfa\FP@rfa\FP@xfb\FP@rfb%
+ \FP@store\FP@tmpa{x}%
+ %
+ \ifnum\FP@rs<0\relax%
+ \FP@rs=1\relax%
+ \FP@pihalf@subr%
+ \FP@pi@subr%
+ \else%
+ \FP@pihalf@subr%
+ \fi%
+ \FP@store\FP@tmpb{r}%
+ %
+ \global\let\FP@tmpa\FP@tmpa%
+ \global\let\FP@tmpb\FP@tmpb%
+ %
+ \FP@endmessage{}%
+ }%
+ %
+ \let#1\FP@tmpa%
+ \let#2\FP@tmpb%
+}
diff --git a/macros/latex/contrib/fp/fp-upn.sty b/macros/latex/contrib/fp/fp-upn.sty
new file mode 100644
index 0000000000..2a74c50bcf
--- /dev/null
+++ b/macros/latex/contrib/fp/fp-upn.sty
@@ -0,0 +1,237 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp-upn}[1996/10/21]
+
+%version information
+\def\FP@upnversion{2.1c}
+\message{%
+ `UPN Fixed Point Calculator',%
+ \space\space\space\space%
+ Version \FP@upnversion%
+ \space(C) Michael Mehlich%
+ \space\space\space\space\space\space\space%
+ \space\space\space\space\space\space%
+}
+
+%resolve dependencies
+\RequirePackage{fp}
+\RequirePackage{defpattern}
+
+%%%public area (macros which may be used)%%%
+\def\FPupn#1#2{\FP@@@upn{#1}{#2}} % #1 := eval(#2)
+
+%%%private fp-area (don't use these macros)%%%
+
+%routines for stack manipulation
+
+\edef\FP@stack{()}
+
+\defpattern\FP@@@putstack[(#2)#3]{\edef\FP@stack{(#3,#2)}}
+\defpattern\FP@@@putstack[()#2]{\edef\FP@stack{(#2)}}
+\def\FP@@putstack(#1)#2{\FP@@@putstack[(#1)#2]}
+\def\FP@putstack#1{\expandafter\FP@@putstack\FP@stack{#1}}
+
+\defpattern\FP@@@getstack[(#2)#3]{\edef\FP@stack{()}\edef#2{#3}}
+\defpattern\FP@@@getstack[(#2)#3,#4]{\edef\FP@stack{(#4)}\edef#2{#3}}
+\defpattern\FP@@@getstack[(#2)]{\FP@errmessage{UPN stack is empty}}
+\def\FP@@getstack(#1)#2{\FP@@@getstack[(#2)#1]}
+\def\FP@getstack#1{\expandafter\FP@@getstack\FP@stack{#1}}
+
+%local debug macro
+\def\FP@upn@debug#1{\FP@debug{upn: #1}}
+\def\FP@upnc@debug#1{\FP@upn@debug{calculating\space\string"#1\string"}}
+\def\FP@upnc@constant#1{\FP@upn@debug{constant\space\space\space\space\string"#1\string"}}
+\def\FP@upnc@result#1{\FP@upn@debug{result\space\space\space\space\space\space\string"#1\string"}}
+
+%call fp-functions with parameters from stack
+\def\FP@const#1{%
+ \FP@upnc@constant{#1}%
+ \expandafter\FP@putstack\csname FP#1\endcsname%
+}
+\def\FP@nullop#1{%
+ \FP@upnc@debug{#1()}%
+ \csname FP#1\endcsname\FP@valc%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@monop#1{%
+ \FP@getstack\FP@vala%
+ \FP@upnc@debug{#1(\FP@vala)}%
+ \csname FP#1\endcsname\FP@valc\FP@vala%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@monopb#1{%
+ \FP@getstack\FP@vala%
+ \FP@upnc@debug{#1(\FP@vala)}%
+ \csname FP#1\endcsname\FP@valc\FP@vald\FP@vala%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@vald\FP@putstack\FP@valc%
+}
+\def\FP@binop#1{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upnc@debug{\FP@vala\space #1 \FP@valb}%
+ \csname FP#1\endcsname\FP@valc\FP@vala\FP@valb%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@binopv#1{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upnc@debug{\FP@valb\space #1 \FP@vala}%
+ \csname FP#1\endcsname\FP@valc\FP@valb\FP@vala%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@binopb#1{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upnc@debug{#1(\FP@valb:\FP@vala)}%
+ \csname FP#1\endcsname\FP@valc\FP@valb\FP@vala%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@binopc#1{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upnc@debug{\FP@valb-th #1 of \FP@vala}%
+ \csname FP#1\endcsname\FP@valc\FP@vala\FP@valb%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+\def\FP@binopd#1{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upnc@debug{#1(\FP@valb,\FP@vala)}%
+ \csname FP#1\endcsname\FP@valc\FP@vala\FP@valb%
+ \FP@upnc@result{\FP@valc}%
+ \FP@putstack\FP@valc%
+}
+
+%the calculation loop
+
+%put value to stack
+\def\FP@put#1\@upnend{%
+ \FP@upnc@result{#1}%
+ \FP@putstack{#1}%
+}
+
+\defpattern\FP@upn[#2#3]{%
+ \ifx#2\@undefined%
+ \FP@upnc@debug{#2#3}%
+ \expandafter\expandafter\expandafter\FP@put\csname #2#3\endcsname\@upnend%
+ \else\ifcat\noexpand#2\relax%
+ \FP@upnc@debug{\string#2#3}%
+ \expandafter\FP@put#2#3\@upnend%
+ \else\ifcat#22\relax%
+ \FP@upnc@debug{\string#2#3}%
+ \expandafter\FP@put#2#3\@upnend%
+ \else%
+ \FP@upnc@debug{#2#3}%
+ \expandafter\expandafter\expandafter\FP@put\csname #2#3\endcsname\@upnend%
+ \fi\fi\fi%
+}
+
+%binary functions from fp-basic
+\defpattern\FP@upn[+]{\FP@binop{add}}
+\defpattern\FP@upn[add]{\FP@binopv{add}}
+\defpattern\FP@upn[-]{\FP@binop{sub}}
+\defpattern\FP@upn[sub]{\FP@binopv{sub}}
+\defpattern\FP@upn[*]{\FP@binop{mul}}
+\defpattern\FP@upn[mul]{\FP@binopv{mul}}
+\defpattern\FP@upn[/]{\FP@binop{div}}
+\defpattern\FP@upn[div]{\FP@binopv{div}}
+
+%unary functions from fp-basic
+\defpattern\FP@upn[abs]{\FP@monop{abs}}
+\defpattern\FP@upn[neg]{\FP@monop{neg}}
+\defpattern\FP@upn[sgn]{\FP@monop{sgn}}
+
+%binary functions from fp-addons
+\defpattern\FP@upn[min]{\FP@binopd{min}}
+\defpattern\FP@upn[max]{\FP@binopd{max}}
+
+%functions from fp-snap
+\defpattern\FP@upn[round]{\FP@binopb{round}}
+\defpattern\FP@upn[trunc]{\FP@binopb{trunc}}
+\defpattern\FP@upn[clip]{\FP@monop{clip}}
+
+%functions from fp-exp
+\defpattern\FP@upn[e]{\FP@const{e}}
+\defpattern\FP@upn[exp]{\FP@monop{exp}}
+\defpattern\FP@upn[ln]{\FP@monop{ln}}
+\defpattern\FP@upn[pow]{\FP@binopc{pow}}
+\defpattern\FP@upn[root]{\FP@binopc{root}}
+
+%functions from fp-random
+\defpattern\FP@upn[seed]{%
+ \FP@getstack\FP@vala\FPseed=\FP@vala%
+}
+\defpattern\FP@upn[random]{\FP@nullop{random}}
+
+%functions from fp-trigo
+\defpattern\FP@upn[pi]{\FP@const{pi}}
+\defpattern\FP@upn[sin]{\FP@monop{sin}}
+\defpattern\FP@upn[cos]{\FP@monop{cos}}
+\defpattern\FP@upn[sincos]{\FP@monopb{sincos}}
+\defpattern\FP@upn[tan]{\FP@monop{tan}}
+\defpattern\FP@upn[cot]{\FP@monop{cot}}
+\defpattern\FP@upn[tancot]{\FP@monopb{tancot}}
+\defpattern\FP@upn[arcsin]{\FP@monop{arcsin}}
+\defpattern\FP@upn[arccos]{\FP@monop{arccos}}
+\defpattern\FP@upn[arcsincos]{\FP@monopb{arcsincos}}
+\defpattern\FP@upn[arctan]{\FP@monop{arctan}}
+\defpattern\FP@upn[arccot]{\FP@monop{arccot}}
+\defpattern\FP@upn[arctancot]{\FP@monopb{arctancot}}
+
+%stack manipulators
+\defpattern\FP@upn[pop]{%
+ \FP@getstack\FP@vala%
+ \FP@upn@debug{removing top number \string"\FP@vala\string"}%
+}
+\defpattern\FP@upn[swap]{%
+ \FP@getstack\FP@vala\FP@getstack\FP@valb%
+ \FP@upn@debug{exchanging top numbers \string"\FP@vala\string" and \string"\FP@valb\string"}%
+ \FP@putstack\FP@vala\FP@putstack\FP@valb%
+}
+\defpattern\FP@upn[copy]{%
+ \FP@getstack\FP@vala%
+ \FP@upn@debug{duplicating top number \string"\FP@vala\string"}%
+ \FP@putstack\FP@vala\FP@putstack\FP@vala%
+}
+
+%left-to-right loop
+\defpattern\FP@upn[#2 #3]{\FP@upn[#2]\FP@upn[#3]}
+\defpattern\FP@upn[#2 ]{\FP@upn[#2]}
+\defpattern\FP@upn[ #2]{\FP@upn[#2]}
+
+%get result from stacks with one value only
+\defpattern\FP@@upn@result[(#2)#3]{\edef#2{#3}}
+\defpattern\FP@@upn@result[(#2)]{\FP@errmessage{UPN stack is empty}\edef#2{0}}
+\defpattern\FP@@upn@result[(#2)#3,#4]{\FP@errmessage{Evaluation results in multiple values}\edef#2{#3}}
+\def\FP@upn@result(#1)#2{\FP@@upn@result[(#2)#1]}
+
+%save result of upn-expression to macro
+\def\FP@saveval[#1#2]{%
+ \ifx#1\@undefined%
+ \let#1\FP@tmp%
+ \else\ifcat\noexpand#1\relax%
+ \let#1\FP@tmp%
+ \else%
+ \expandafter\let\csname #1#2\endcsname\FP@tmp%
+ \fi\fi%
+}
+
+%the main routine
+\def\FP@@upn#1#2{%
+ \bgroup%
+ \FP@upn@debug{+++ computing upn-expression \string"#2\string"}%
+ \edef\FP@tmp{[#2]}%
+ \expandafter\FP@upn\FP@tmp%
+ \FP@upn@debug{+++ result of upn-expression is \string"\FP@stack\string"}%
+ \expandafter\FP@upn@result\FP@stack\FP@tmp%
+ \global\let\FP@tmp\FP@tmp%
+ \egroup%
+ \FP@saveval[#1]%
+}
+
+\def\FP@@@upn#1#2{%
+ \FP@beginmessage{UPN}%
+ \FP@@upn{#1}{#2}%
+ \FP@endmessage{}%
+}
diff --git a/macros/latex/contrib/fp/fp.sty b/macros/latex/contrib/fp/fp.sty
new file mode 100644
index 0000000000..8ad1e441b5
--- /dev/null
+++ b/macros/latex/contrib/fp/fp.sty
@@ -0,0 +1,32 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{fp}[1995/04/02]
+
+%version information
+\def\FP@version{Version 0.8, April 2, 1995}
+\message{`Fixed Point Package', \FP@version\space (C) Michael Mehlich}
+
+\let\FP@save@message\message
+\def\message#1{}
+
+%include all subpackages
+\RequirePackage{defpattern}
+\RequirePackage{fp-basic} %add, sub, mul, div, abs, neg, lt?, eq?, gt?,
+ %neg?, pos?, zero?, int?
+\RequirePackage{fp-addons} %min, max
+\RequirePackage{fp-snap} %trunc, round, clip
+\RequirePackage{fp-exp} %e, exp, ln, pow, root
+\RequirePackage{fp-trigo} %pi, sin, cos, sincos, tan, cot, tancot,
+ %arcsin, arccos, arcsincos
+\RequirePackage{fp-pas} %pascal
+\RequirePackage{fp-random} %seed, random
+\RequirePackage{fp-eqn} %lsolve, qsolve
+\RequirePackage{fp-upn} %upn
+\RequirePackage{fp-eval} %eval
+
+\let\message\FP@save@message
+
+\DeclareOption{nomessages}{\FPmessagesfalse}
+\DeclareOption{debug}{\FPdebugtrue}
+\ProcessOptions
+
+\endinput
diff --git a/macros/latex/contrib/fp/fp.tex b/macros/latex/contrib/fp/fp.tex
new file mode 100644
index 0000000000..39f62d60b3
--- /dev/null
+++ b/macros/latex/contrib/fp/fp.tex
@@ -0,0 +1,49 @@
+%load the fp-package for TeX
+\chardef\FPcatamp=\the\catcode`\@
+\catcode`@=11
+
+\def\NeedsTeXFormat#1{}
+\def\ProvidesPackage#1[#2]{}
+\def\DeclareOption#1#2{}
+\let\ProcessOptions\relax
+
+%the for-loop of latex2e
+\def\@nnil{\@nil}
+\def\@empty{}
+\def\@fornoop#1\@@#2#3{}
+
+\def\@for#1:=#2\do#3{\edef\@fortmp{#2}\ifx\@fortmp\@empty \else
+ \expandafter\@forloop#2,\@nil,\@nil\@@#1{#3}\fi}
+
+\def\@forloop#1,#2,#3\@@#4#5{\def#4{#1}\ifx #4\@nnil \else
+ #5\def#4{#2}\ifx #4\@nnil \else#5\@iforloop #3\@@#4{#5}\fi\fi}
+
+\def\@iforloop#1,#2\@@#3#4{\def#3{#1}\ifx #3\@nnil
+ \let\@nextwhile\@fornoop \else
+ #4\relax\let\@nextwhile\@iforloop\fi\@nextwhile#2\@@#3{#4}}
+
+\edef\FP@loadedfiles{fp.tex}
+
+\def\FP@alreadyloaded#1{}
+\def\FP@notyetloaded#1{
+ \edef\FP@loadedfiles{\FP@loadedfiles,#1}
+ \input #1.sty
+}
+\def\RequirePackage#1{%
+ \let\FP@in@\FP@notyetloaded%
+ \edef\@tempb{#1}%
+ \@for\@tempa:=\FP@loadedfiles\do{%
+ \ifx\@tempa\@tempb%
+ \let\FP@in@\FP@alreadyloaded%
+ \fi%
+ }%
+ \FP@in@{#1}%
+}
+
+\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%
+ \iterate \let\iterate\relax}
+\let\repeat=\fi
+
+\RequirePackage{fp}
+
+\catcode`\@=\FPcatamp
diff --git a/macros/latex/contrib/fp/lfp.sty b/macros/latex/contrib/fp/lfp.sty
new file mode 100644
index 0000000000..3b6728974c
--- /dev/null
+++ b/macros/latex/contrib/fp/lfp.sty
@@ -0,0 +1,34 @@
+%load the fp-package for LaTeX2.09
+\chardef\FPcatamp=\the\catcode`\@
+\catcode`@=11
+
+\def\NeedsTeXFormat#1{}
+\def\ProvidesPackage#1[#2]{}
+\def\DeclareOption#1#2{}
+\let\ProcessOptions\relax
+
+\edef\FP@loadedfiles{fp.tex}
+
+\def\FP@alreadyloaded#1{}
+\def\FP@notyetloaded#1{%
+ \edef\FP@loadedfiles{\FP@loadedfiles,#1}
+ \input #1.sty
+}
+\def\RequirePackage#1{%
+ \let\FP@in@\FP@notyetloaded%
+ \edef\@tempb{#1}%
+ \@for\@tempa:=\FP@loadedfiles\do{%
+ \ifx\@tempa\@tempb%
+ \let\FP@in@\FP@alreadyloaded%
+ \fi%
+ }%
+ \FP@in@{#1}%
+}
+
+\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%
+ \iterate \let\iterate\relax}
+\let\repeat=\fi
+
+\RequirePackage{fp}
+
+\catcode`\@=\FPcatamp