summaryrefslogtreecommitdiff
path: root/source/luametatex/source/mp/mpw
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/mp/mpw')
-rw-r--r--source/luametatex/source/mp/mpw/mp.w19
-rw-r--r--source/luametatex/source/mp/mpw/mpmathdecimal.w288
-rw-r--r--source/luametatex/source/mp/mpw/mpmathdouble.w138
-rw-r--r--source/luametatex/source/mp/mpw/mpmathposit.w1428
4 files changed, 1517 insertions, 356 deletions
diff --git a/source/luametatex/source/mp/mpw/mp.w b/source/luametatex/source/mp/mpw/mp.w
index f4bdb58ca..7390181ea 100644
--- a/source/luametatex/source/mp/mpw/mp.w
+++ b/source/luametatex/source/mp/mpw/mp.w
@@ -200,6 +200,7 @@ abstraction.
# include "avl.h"
# include "auxmemory.h"
+# include "auxposit.h"
# include <string.h>
# include <setjmp.h>
@@ -231,6 +232,7 @@ typedef struct MP_instance {
# include "mpmathdouble.h"
# include "mpmathbinary.h"
# include "mpmathdecimal.h"
+# include "mpmathposit.h"
# include "mpstrings.h"
@h @<Declarations@>
@@ -293,13 +295,15 @@ typedef enum mp_number_type {
mp_angle_type,
mp_double_type,
mp_binary_type,
- mp_decimal_type
+ mp_decimal_type,
+ mp_posit_type
} mp_number_type;
typedef union mp_number_store {
void *num;
double dval;
int val;
+ posit_t pval;
} mp_number_store;
typedef struct mp_number_data {
@@ -568,6 +572,9 @@ MP mp_initialize (MP_options * opt)
case mp_math_binary_mode:
mp->math = mp_initialize_binary_math(mp);
break;
+ case mp_math_posit_mode:
+ mp->math = mp_initialize_posit_math(mp);
+ break;
default:
mp->math = mp_initialize_double_math(mp);
break;
@@ -586,6 +593,9 @@ MP mp_initialize (MP_options * opt)
case mp_math_decimal_mode:
set_internal_string(mp_number_system_internal, mp_intern(mp, "decimal"));
break;
+ case mp_math_posit_mode:
+ set_internal_string(mp_number_system_internal, mp_intern(mp, "posit"));
+ break;
case mp_math_binary_mode:
set_internal_string(mp_number_system_internal, mp_intern(mp, "binary"));
break;
@@ -1868,7 +1878,8 @@ typedef enum mp_math_mode {
mp_math_scaled_mode,
mp_math_double_mode,
mp_math_binary_mode,
- mp_math_decimal_mode
+ mp_math_decimal_mode,
+ mp_math_posit_mode
} mp_math_mode;
@ @<Option variables@>=
@@ -22558,7 +22569,7 @@ static void mp_do_unary (MP mp, int c)
case mp_cos_d_operation:
/*
This is rather inefficient, esp decimal, to calculate both each time. We could
- pass NULL as signal to do only one.
+ pass NULL as signal to do only one, or just have n_sin and n_cos.
*/
if (mp->cur_exp.type != mp_known_type) {
mp_bad_unary(mp, c);
@@ -22569,7 +22580,7 @@ static void mp_do_unary (MP mp, int c)
new_fraction(n_sin);
new_fraction(n_cos);
number_clone(arg1, cur_exp_value_number);
- number_clone(arg2, unity_t);
+ number_clone(arg2, unity_t); /* maybe dp360 */
number_multiply_int(arg2, 360);
number_modulo(arg1, arg2);
convert_scaled_to_angle(arg1);
diff --git a/source/luametatex/source/mp/mpw/mpmathdecimal.w b/source/luametatex/source/mp/mpw/mpmathdecimal.w
index 124c77ecb..359223271 100644
--- a/source/luametatex/source/mp/mpw/mpmathdecimal.w
+++ b/source/luametatex/source/mp/mpw/mpmathdecimal.w
@@ -227,6 +227,8 @@ mp_decimal_info mp_decimal_data = {
.initialized = 0,
};
+@ See mpmathdouble for documentation. @c
+
static void checkZero(decNumber *ret)
{
if (decNumberIsZero(ret) && decNumberIsNegative(ret)) {
@@ -277,21 +279,26 @@ static double decNumberToDouble(decNumber *A)
}
}
-@ Borrowed code from libdfp:
+/*tex
-$$ \arctan(x) = x - \frac {x^3}{3} + \frac {x^5{5} - \frac {x^7}{7} + \ldots$$
+ \startformula
+ \arctan(x) = x - \frac {x^3}{3} + \frac {x^5{5} - \frac {x^7}{7} + \ldots
+ \stopformula
-This power series works well, if $x$ is close to zero ($|x|<0.5$). If x is
-larger, the series converges too slowly, so in order to get a smaller x, we apply
-the identity
+ This power series works well, if $x$ is close to zero ($|x|<0.5$). If x is
+ larger, the series converges too slowly, so in order to get a smaller x, we apply
+ the identity
-$$ \arctan(x) = 2 \arctan \left (\frac {\sqrt{1 + x^2}-1} {x} \right) $$
+ \startformula
+ \arctan(x) = 2 \arctan \left (\frac {\sqrt{1 + x^2}-1} {x} \right)
+ \stopformula
-twice. The first application gives us a new $x$ with $x < 1$. The second
-application gives us a new x with $x < 0.4142136$. For that $x$, we use the power
-series and multiply the result by four.
+ twice. The first application gives us a new $x$ with $x < 1$. The second
+ application gives us a new x with $x < 0.4142136$. For that $x$, we use the power
+ series and multiply the result by four.
+
+*/
-@c
static void decNumberAtan(decNumber *result, decNumber *x_orig, decContext *localset)
{
decNumber x;
@@ -373,7 +380,6 @@ static void decNumberAtan2(decNumber *result, decNumber *y, decNumber *x, decCon
}
}
-@ @c
math_data *mp_initialize_decimal_math (MP mp)
{
math_data *math = (math_data *) mp_memory_allocate(sizeof(math_data));
@@ -613,10 +619,6 @@ void mp_free_decimal_math (MP mp)
mp_memory_free(mp->math);
}
-@ Creating and destruction of |mp_number| objects. Let's hope that mimalloc keeps
-a pool for these.
-
-@ @c
void mp_allocate_number (MP mp, mp_number *n, mp_number_type t)
{
(void) mp;
@@ -625,7 +627,6 @@ void mp_allocate_number (MP mp, mp_number *n, mp_number_type t)
decNumberZero(n->data.num);
}
-@ @c
void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v)
{
(void) mp;
@@ -635,7 +636,6 @@ void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v)
decNumberCopy(n->data.num, v->data.num);
}
-@ @c
void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v)
{
(void) mp;
@@ -654,7 +654,6 @@ void mp_allocate_double (MP mp, mp_number *n, double v)
decNumberFromDouble(n->data.num, v);
}
-@ @c
void mp_free_number (MP mp, mp_number *n)
{
(void) mp;
@@ -857,13 +856,6 @@ void mp_number_scaled_to_angle(mp_number *A)
decNumberMultiply(A->data.num, A->data.num, &mp_decimal_data.angle_multiplier_decNumber, &mp_decimal_data.set);
}
-@* Query functions.
-
-@ Convert a number to a scaled value. |decNumberToInt32| is not able to make this
-conversion properly, so instead we are using |decNumberToDouble| and a typecast.
-Bad!
-
-@c
int mp_number_to_scaled(mp_number *A)
{
int result;
@@ -958,26 +950,6 @@ int mp_number_nonequalabs(mp_number *A, mp_number *B)
return ! decNumberIsZero(&res);
}
-@ Fixed-point arithmetic is done on {\sl scaled integers} that are multiples of
-$2^{-16}$. In other words, a binary point is assumed to be sixteen bit positions
-from the right end of a binary computer word.
-
-@ One of \MP's most common operations is the calculation of
-$\lfloor{a+b\over2}\rfloor$, the midpoint of two given integers |a| and~|b|. The
-most decent way to do this is to write |(a+b)/2|; but on many machines it is
-more efficient to calculate |(a+b)>>1|.
-
-Therefore the midpoint operation will always be denoted by |half(a+b)| in this
-program. If \MP\ is being implemented with languages that permit binary shifting,
-the |half| macro should be changed to make this operation as efficient as
-possible. Since some systems have shift operators that can only be trusted to
-work on positive numbers, there is also a macro |halfp| that is used only when
-the quantity being halved is known to be positive or zero.
-
-@ Here is a procedure analogous to |print_int|. The current version is fairly
-stupid, and it is not round-trip safe, but this is good enough for a beta test.
-
-@c
char *mp_decnumber_tostring(decNumber *n)
{
decNumber corrected;
@@ -994,7 +966,6 @@ char *mp_decimal_number_tostring (MP mp, mp_number *n)
return mp_decnumber_tostring(n->data.num);
}
-@ @c
void mp_decimal_print_number (MP mp, mp_number *n)
{
char *str = mp_decnumber_tostring(n->data.num);
@@ -1002,51 +973,12 @@ void mp_decimal_print_number (MP mp, mp_number *n)
mp_memory_free(str);
}
-@ Addition is not always checked to make sure that it doesn't overflow, but in
-places where overflow isn't too unlikely the |slow_add| routine is used.
-
-@c
void mp_decimal_slow_add (MP mp, mp_number *ret, mp_number *A, mp_number *B)
{
(void) mp;
decNumberAdd(ret->data.num, A->data.num, B->data.num, &mp_decimal_data.set);
}
-@ The |make_fraction| routine produces the |fraction| equivalent of |p/q|, given
-integers |p| and~|q|; it computes the integer
-$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are positive. If |p| and
-|q| are both of the same scaled type |t|, the \quote {type relation}
-|make_fraction(t,t)=fraction| is valid; and it's also possible to use the
-subroutine \quote {backwards,} using the relation |make_fraction(t,fraction)=t|
-between scaled types.
-
-If the result would have magnitude $2^{31}$ or more, |make_fraction| sets
-|arith_error:=true|. Most of \MP's internal computations have been designed to
-avoid this sort of error.
-
-If this subroutine were programmed in assembly language on a typical machine, we
-could simply compute |(@t$2^{28}$@>*p)div q|, since a double-precision product
-can often be input to a fixed-point division instruction. But when we are
-restricted to int-eger arithmetic it is necessary either to resort to
-multiple-precision maneuvering or to use a simple but slow iteration. The
-multiple-precision technique would be about three times faster than the code
-adopted here, but it would be comparatively long and tricky, involving about
-sixteen additional multiplications and divisions.
-
-This operation is part of \MP's \quote {inner loop}; indeed, it will consume nearly
-10\pct! of the running time (exclusive of input and output) if the code below is
-left unchanged. A machine-dependent recoding will therefore make \MP\ run faster.
-The present implementation is highly portable, but slow; it avoids multiplication
-and division except in the initial stage. System wizards should be careful to
-replace it with a routine that is guaranteed to produce identical results in all
-cases. @^system dependencies@>
-
-As noted below, a few more routines should also be replaced by machine-dependent
-code, for efficiency. But when a procedure is not part of the \quote {inner loop,}
-such changes aren't advisable; simplicity and robustness are preferable to
-trickery, unless the cost is too high. @^inner loop@>
-
-@c
void mp_decimal_make_fraction (MP mp, decNumber *ret, decNumber *p, decNumber *q)
{
decNumberDivide(ret, p, q, &mp_decimal_data.set);
@@ -1059,16 +991,6 @@ void mp_decimal_number_make_fraction (MP mp, mp_number *ret, mp_number *p, mp_nu
mp_decimal_make_fraction(mp, ret->data.num, p->data.num, q->data.num);
}
-@ The dual of |make_fraction| is |take_fraction|, which multiplies a given
-integer~|q| by a fraction~|f|. When the operands are positive, it computes
-$p=\lfloor qf/2^{28}+{1\over2}\rfloor$, a symmetric function of |q| and~|f|.
-
-This routine is even more \quote {inner loopy} than |make_fraction|; the present
-implementation consumes almost 20\pct! of \MP's computation time during typical
-jobs, so a machine-language substitute is advisable. @^inner loop@> @^system
-dependencies@>
-
-@c
void mp_decimal_take_fraction (MP mp, decNumber *ret, decNumber *p, decNumber *q)
{
(void) mp;
@@ -1081,39 +1003,18 @@ void mp_decimal_number_take_fraction (MP mp, mp_number *ret, mp_number *p, mp_nu
mp_decimal_take_fraction(mp, ret->data.num, p->data.num, q->data.num);
}
-@ When we want to multiply something by a |scaled| quantity, we use a scheme
-analogous to |take_fraction| but with a different scaling. Given positive
-operands, |take_scaled| computes the quantity $p=\lfloor
-qf/2^{16}+{1\over2}\rfloor$.
-
-Once again it is a good idea to use a machine-language replacement if possible;
-otherwise |take_scaled| will use more than 2\pct! of the running time when the
-Computer Modern fonts are being generated. @^inner loop@>
-
-@c
void mp_decimal_number_take_scaled (MP mp, mp_number *ret, mp_number *p_orig, mp_number *q_orig)
{
(void) mp;
decNumberMultiply(ret->data.num, p_orig->data.num, q_orig->data.num, &mp_decimal_data.set);
}
-@ For completeness, there's also |make_scaled|, which computes a quotient as a
-|scaled| number instead of as a |fraction|. In other words, the result is
-$\lfloor2^{16}p/q+{1\over2}\rfloor$, if the operands are positive. \ (This
-procedure is not used especially often, so it is not part of \MP's inner loop.)
-
-@c
void mp_decimal_number_make_scaled (MP mp, mp_number *ret, mp_number *p_orig, mp_number *q_orig)
{
decNumberDivide(ret->data.num, p_orig->data.num, q_orig->data.num, &mp_decimal_data.set);
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ @* Scanning numbers in the input.
-
-The definitions below are temporarily here
-
-@ @c
void mp_wrapup_numeric_token (MP mp, unsigned char *start, unsigned char *stop)
{
decNumber result;
@@ -1161,7 +1062,6 @@ void mp_wrapup_numeric_token (MP mp, unsigned char *start, unsigned char *stop)
set_cur_cmd((mp_variable_type) mp_numeric_command);
}
-@ @c
static void find_exponent (MP mp)
{
if (mp->buffer[mp->cur_input.loc_field] == 'e'
@@ -1196,9 +1096,6 @@ void mp_decimal_scan_fractional_token (MP mp, int n)
mp_wrapup_numeric_token(mp, start, stop);
}
-@ We just have to collect bytes.
-
-@c
void mp_decimal_scan_numeric_token (MP mp, int n)
{
unsigned char *start = &mp->buffer[mp->cur_input.loc_field -1];
@@ -1218,32 +1115,6 @@ void mp_decimal_scan_numeric_token (MP mp, int n)
mp_wrapup_numeric_token(mp, start, stop);
}
-@ The |scaled| quantities in \MP\ programs are generally supposed to be less than
-$2^{12}$ in absolute value, so \MP\ does much of its internal arithmetic with
-28~significant bits of precision. A |fraction| denotes a scaled integer whose
-binary point is assumed to be 28 bit positions from the right.
-
-@ Here is a typical example of how the routines above can be used. It computes
-the function $${1\over3\tau}f(\theta,\phi)=
-{\tau^{-1}\bigl(2+\sqrt2\,(\sin\theta-{1\over16}\sin\phi)
-(\sin\phi-{1\over16}\sin\theta)(\cos\theta-\cos\phi)\bigr)\over
-3\,\bigl(1+{1\over2}(\sqrt5-1)\cos\theta+{1\over2}(3-\sqrt5\,)\cos\phi\bigr)},$$
-where $\tau$ is a |scaled| \quote {tension} parameter. This is \MP's magic fudge
-factor for placing the first control point of a curve that starts at an angle
-$\theta$ and ends at an angle $\phi$ from the straight path. (Actually, if the
-stated quantity exceeds 4, \MP\ reduces it to~4.)
-
-The trigonometric quantity to be multiplied by $\sqrt2$ is less than $\sqrt2$.
-(It's a sum of eight terms whose absolute values can be bounded using relations
-such as $\sin\theta\cos\theta|1\over2|$.) Thus the numerator is positive; and
-since the tension $\tau$ is constrained to be at least $3\over4$, the numerator
-is less than $16\over3$. The denominator is nonnegative and at most~6.
-
-The angles $\theta$ and $\phi$ are given implicitly in terms of |fraction|
-arguments |st|, |ct|, |sf|, and |cf|, representing $\sin\theta$, $\cos\theta$,
-$\sin\phi$, and $\cos\phi$, respectively.
-
-@c
void mp_decimal_velocity (MP mp, mp_number *ret, mp_number *st, mp_number *ct, mp_number *sf, mp_number *cf, mp_number *t)
{
decNumber acc, num, denom; /* registers for intermediate calculations */
@@ -1300,12 +1171,6 @@ void mp_decimal_velocity (MP mp, mp_number *ret, mp_number *st, mp_number *ct, m
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ The following somewhat different subroutine tests rigorously if $ab$ is greater
-than, equal to, or less than~$cd$, given integers $(a,b,c,d)$. In most cases a
-quick decision is reached. The result is $+1$, 0, or~$-1$ in the three respective
-cases.
-
-@c
int mp_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_number *d_orig)
{
decNumber a, b, c, d;
@@ -1325,33 +1190,6 @@ int mp_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_num
}
}
-@ Now here's a subroutine that's handy for all sorts of path computations: Given
-a quadratic polynomial $B(a,b,c;t)$, the |crossing_point| function returns the
-unique |fraction| value |t| between 0 and~1 at which $B(a,b,c;t)$ changes from
-positive to negative, or returns |t=fraction_one+1| if no such value exists. If
-|a<0| (so that $B(a,b,c;t)$ is already negative at |t=0|), |crossing_point|
-returns the value zero.
-
-The general bisection method is quite simple when $n=2$, hence |crossing_point|
-does not take much time. At each stage in the recursion we have a subinterval
-defined by |l| and~|j| such that $B(a,b,c;2^{-l}(j+t))=B(x_0,x_1,x_2;t)$, and we
-want to \quote {zero in} on the subinterval where $x_0\G0$ and $\min(x_1,x_2)<0$.
-
-It is convenient for purposes of calculation to combine the values of |l| and~|j|
-in a single variable $d=2^l+j$, because the operation of bisection then
-corresponds simply to doubling $d$ and possibly adding~1. Furthermore it proves
-to be convenient to modify our previous conventions for bisection slightly,
-maintaining the variables $X_0=2^lx_0$, $X_1=2^l(x_0-x_1)$, and
-$X_2=2^l(x_1-x_2)$. With these variables the conditions $x_0\ge0$ and
-$\min(x_1,x_2)<0$ are equivalent to $\max(X_1,X_1+X_2)>X_0\ge0$.
-
-The following code maintains the invariant relations
-$0\L|x0|<\max(|x1|,|x1|+|x2|)$, $\vert|x1|\vert<2^{30}$, $\vert|x2|\vert<2^{30}$;
-it has been constructed in such a way that no arithmetic overflow will occur if
-the inputs satisfy $a<2^{30}$, $\vert a-b\vert<2^{30}$, and $\vert
-b-c\vert<2^{30}$.
-
-@c
static void mp_decimal_crossing_point (MP mp, mp_number *ret, mp_number *aa, mp_number *bb, mp_number *cc)
{
decNumber a, b, c;
@@ -1426,20 +1264,11 @@ static void mp_decimal_crossing_point (MP mp, mp_number *ret, mp_number *aa, mp_
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ We conclude this set of elementary routines with some simple rounding and
-truncation operations.
-
-@ |round_unscaled| rounds a |scaled| and converts it to |int|
-
-@c
int mp_round_unscaled(mp_number *x_orig)
{
return (int) lround(mp_number_to_double(x_orig));
}
-@ |number_floor| floors a number
-
-@c
void mp_number_floor(mp_number *i)
{
int round = mp_decimal_data.set.round;
@@ -1448,20 +1277,12 @@ void mp_number_floor(mp_number *i)
mp_decimal_data.set.round = round;
}
-@ |fraction_to_scaled| rounds a |fraction| and converts it to |scaled|
-
-@c
void mp_decimal_fraction_to_round_scaled(mp_number *x_orig)
{
x_orig->type = mp_scaled_type;
decNumberDivide(x_orig->data.num, x_orig->data.num, &mp_decimal_data.fraction_multiplier_decNumber, &mp_decimal_data.set);
}
-@* Algebraic and transcendental functions. \MP\ computes all of the necessary
-special functions from scratch, without relying on |real| arithmetic or system
-subroutines for sines, cosines, etc.
-
-@ @c
void mp_decimal_square_rt (MP mp, mp_number *ret, mp_number *x_orig)
{
decNumber x;
@@ -1487,9 +1308,6 @@ void mp_decimal_square_rt (MP mp, mp_number *ret, mp_number *x_orig)
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Pythagorean addition $\psqrt{a^2+b^2}$ is implemented by a quick hack
-
-@c
void mp_decimal_pyth_add (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
{
decNumber a, b;
@@ -1509,9 +1327,6 @@ void mp_decimal_pyth_add (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Here is a similar algorithm for $\psqrt{a^2-b^2}$. Same quick hack, also.
-
-@c
void mp_decimal_pyth_sub (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
{
decNumber a, b;
@@ -1545,19 +1360,12 @@ void mp_decimal_pyth_sub (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Power $a^b}$:
-
-@c
void mp_decimal_power_of (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
{
decNumberPower(ret->data.num, a_orig->data.num, b_orig->data.num, &mp_decimal_data.set);
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Here is the routine that calculates $2^8$ times the natural logarithm of a
-|scaled| quantity;
-
-@c
void mp_decimal_m_log (MP mp, mp_number *ret, mp_number *x_orig)
{
if (! decNumberIsPositive((decNumber *) x_orig->data.num)) {
@@ -1583,10 +1391,6 @@ void mp_decimal_m_log (MP mp, mp_number *ret, mp_number *x_orig)
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Conversely, the exponential routine calculates $\exp(x/2^8)$, when |x| is
-|scaled|.
-
-@c
void mp_decimal_m_exp (MP mp, mp_number *ret, mp_number *x_orig)
{
decNumber temp, twofivesix;
@@ -1606,10 +1410,6 @@ void mp_decimal_m_exp (MP mp, mp_number *ret, mp_number *x_orig)
mp_decimal_data.limitedset.status = 0;
}
-@ Given integers |x| and |y|, not both zero, the |n_arg| function returns the
-|angle| whose tangent points in the direction $(x,y)$.
-
-@c
void mp_decimal_n_arg (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_orig)
{
if (decNumberIsZero((decNumber *) x_orig->data.num) && decNumberIsZero((decNumber *) y_orig->data.num)) {
@@ -1635,14 +1435,6 @@ void mp_decimal_n_arg (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_or
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ Conversely, the |n_sin_cos| routine takes an |angle| and produces the sine and
-cosine of that angle. The results of this routine are stored in global integer
-variables |n_sin| and |n_cos|.
-
-First, we need a decNumber function that calculates sines and cosines using the
-Taylor series. This function is fairly optimized.
-
-@c
static void sinecosine(decNumber *theangle, decNumber *c, decNumber *s)
{
int prec = mp_decimal_data.set.digits/2;
@@ -1688,9 +1480,6 @@ static void sinecosine(decNumber *theangle, decNumber *c, decNumber *s)
}
}
-@ Calculate sines and cosines.
-
-@c
void mp_decimal_sin_cos (MP mp, mp_number *z_orig, mp_number *n_cos, mp_number *n_sin)
{
decNumber rad;
@@ -1717,9 +1506,6 @@ void mp_decimal_sin_cos (MP mp, mp_number *z_orig, mp_number *n_cos, mp_number *
mp_decnumber_check(mp, n_sin->data.num, &mp_decimal_data.set);
}
-@ This is the {\tt http://www-cs-faculty.stanford.edu/~uno/programs/rng.c}
-with small cosmetic modifications.
-
@c
# define KK 100 /* the long lag */
# define LL 37 /* the short lag */
@@ -1743,10 +1529,6 @@ static mp_decimal_random_info mp_decimal_random_data = {
.ptr = &mp_decimal_random_data.dummy
};
-/* put n new random numbers in aa */
-/* long aa[] destination */
-/* int n array length (must be at least KK) */
-
static void ran_array(long aa[],int n)
{
int i, j;
@@ -1764,14 +1546,6 @@ static void ran_array(long aa[],int n)
}
}
-/*
- the following routines are from exercise 3.6--15L after calling |ran_start|,
- get new randoms by, e.g., "|x=ran_arr_next()|"
-
- Do this before using |ran_array|, |long seed| selector for different
- streams.
-*/
-
static void ran_start(long seed)
{
int t, j;
@@ -1826,8 +1600,6 @@ static void ran_start(long seed)
mp_decimal_random_data.ptr = &mp_decimal_random_data.started;
}
-# define ran_arr_next() (*mp_decimal_random_data.ptr>=0? *mp_decimal_random_data.ptr++: ran_arr_cycle())
-
static long ran_arr_cycle(void)
{
if (mp_decimal_random_data.ptr == &mp_decimal_random_data.dummy) {
@@ -1840,9 +1612,6 @@ static long ran_arr_cycle(void)
return mp_decimal_random_data.buf[0];
}
-@ To initialize the |randoms| table, we call the following routine.
-
-@c
void mp_init_randoms (MP mp, int seed)
{
int k = 1; /* more or less random integers */
@@ -1866,21 +1635,16 @@ void mp_init_randoms (MP mp, int seed)
ran_start((unsigned long) seed);
}
-@ @c
void mp_decimal_number_modulo(mp_number *a, mp_number *b)
{
decNumberRemainder(a->data.num, a->data.num, b->data.num, &mp_decimal_data.set);
}
-@ To consume a random integer for the uniform generator, the program below will
-say |next_unif_random|.
-
-@c
static void mp_next_unif_random (MP mp, mp_number *ret)
{
decNumber a;
decNumber b;
- unsigned long int op = (unsigned)ran_arr_next();
+ unsigned long int op = (unsigned) (*mp_decimal_random_data.ptr>=0? *mp_decimal_random_data.ptr++: ran_arr_cycle());
(void) mp;
decNumberFromInt32(&a, op);
decNumberFromInt32(&b, MM);
@@ -1889,9 +1653,6 @@ static void mp_next_unif_random (MP mp, mp_number *ret)
mp_decnumber_check(mp, ret->data.num, &mp_decimal_data.set);
}
-@ To consume a random fraction, the program below will say |next_random|.
-
-@c
static void mp_next_random (MP mp, mp_number *ret)
{
if (mp->j_random == 0) {
@@ -1902,14 +1663,6 @@ static void mp_next_random (MP mp, mp_number *ret)
mp_number_clone(ret, &(mp->randoms[mp->j_random]));
}
-@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x| or
-|0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
-
-Note that the call of |take_fraction| will produce the values 0 and~|x| with
-about half the probability that it will produce any other particular values
-between 0 and~|x|, because it rounds its answers.
-
-@c
static void mp_decimal_m_unif_rand (MP mp, mp_number *ret, mp_number *x_orig)
{
mp_number x, abs_x, u, y; /* |y| is trial value */
@@ -1932,11 +1685,6 @@ static void mp_decimal_m_unif_rand (MP mp, mp_number *ret, mp_number *x_orig)
mp_free_number(mp, &u);
}
-@ Finally, a normal deviate with mean zero and unit standard deviation can
-readily be obtained with the ratio method (Algorithm 3.4.1R in {\sl The Art of
-Computer Programming}).
-
-@c
static void mp_decimal_m_norm_rand (MP mp, mp_number *ret)
{
mp_number abs_x, u, r, la, xa;
diff --git a/source/luametatex/source/mp/mpw/mpmathdouble.w b/source/luametatex/source/mp/mpw/mpmathdouble.w
index 6f0f8df99..f5a91df75 100644
--- a/source/luametatex/source/mp/mpw/mpmathdouble.w
+++ b/source/luametatex/source/mp/mpw/mpmathdouble.w
@@ -71,7 +71,6 @@ First, here are some very important constants.
@ Here are the functions that are static as they are not used elsewhere.
@<Declarations@>=
-static int mp_ab_vs_cd (mp_number *a, mp_number *b, mp_number *c, mp_number *d);
static void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v);
static void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v);
static void mp_allocate_double (MP mp, mp_number *n, double v);
@@ -306,7 +305,7 @@ math_data *mp_initialize_double_math(MP mp)
math->md_print = mp_double_print_number;
math->md_tostring = mp_double_number_tostring;
math->md_modulo = mp_number_modulo;
- math->md_ab_vs_cd = mp_ab_vs_cd;
+ math->md_ab_vs_cd = mp_double_ab_vs_cd;
math->md_crossing_point = mp_double_crossing_point;
math->md_scan_numeric = mp_double_scan_numeric_token;
math->md_scan_fractional = mp_double_scan_fractional_token;
@@ -353,7 +352,7 @@ void mp_free_double_math (MP mp)
@ Creating an destroying |mp_number| objects
-@ @c
+@c
void mp_allocate_number (MP mp, mp_number *n, mp_number_type t)
{
(void) mp;
@@ -361,7 +360,6 @@ void mp_allocate_number (MP mp, mp_number *n, mp_number_type t)
n->type = t;
}
-@ @c
void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v)
{
(void) mp;
@@ -369,7 +367,6 @@ void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v)
n->data.dval = v->data.dval;
}
-@ @c
void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v)
{
(void) mp;
@@ -377,7 +374,6 @@ void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v)
n->data.dval = fabs(v->data.dval);
}
-@ @c
void mp_allocate_double (MP mp, mp_number *n, double v)
{
(void) mp;
@@ -385,7 +381,6 @@ void mp_allocate_double (MP mp, mp_number *n, double v)
n->data.dval = v;
}
-@ @c
void mp_free_number (MP mp, mp_number *n)
{
(void) mp;
@@ -901,46 +896,16 @@ quick decision is reached. The result is $+1$, 0, or~$-1$ in the three respectiv
cases.
@c
-int mp_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_number *d_orig)
+int mp_double_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_number *d_orig)
{
- return mp_double_ab_vs_cd(a_orig, b_orig, c_orig, d_orig);
-}
-
-@ @<Reduce to the case that |a...@>=
-if (a < 0) {
- a = -a;
- b = -b;
-}
-if (c < 0) {
- c = -c;
- d = -d;
-}
-if (d <= 0) {
- if (b >= 0) {
- if ((a == 0 || b == 0) && (c == 0 || d == 0)) {
- ret->data.dval = 0;
- } else {
- ret->data.dval = 1;
- }
- goto RETURN;
- } if (d == 0) {
- ret->data.dval = (a == 0 ? 0 : -1);
- goto RETURN;
- } else
- q = a;
- a = c;
- c = q;
- q = -b;
- b = -d;
- d = q;
- }
-} else if (b <= 0) {
- if (b < 0 && a > 0) {
- ret->data.dval = -1;
- return;
- } else
- ret->data.dval = (c == 0 ? 0 : -1);
- goto RETURN;
+ double ab = a_orig->data.dval * b_orig->data.dval;
+ double cd = c_orig->data.dval * d_orig->data.dval;
+ if (ab > cd) {
+ return 1;
+ } else if (ab < cd) {
+ return -1;
+ } else {
+ return 0;
}
}
@@ -1210,8 +1175,9 @@ void mp_double_n_arg (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_ori
} else {
ret->type = mp_angle_type;
ret->data.dval = atan2(y_orig->data.dval, x_orig->data.dval) * (180.0 / PI) * angle_multiplier;
- if (ret->data.dval == -0.0)
- ret->data.dval = 0.0;
+ if (ret->data.dval == -0.0) {
+ ret->data.dval = 0.0;
+ }
}
}
@@ -1249,7 +1215,8 @@ void mp_double_sin_cos (MP mp, mp_number *z_orig, mp_number *n_cos, mp_number *n
}
@ This is the http://www-cs-faculty.stanford.edu/~uno/programs/rng.c with small
-cosmetic modifications.
+cosmetic modifications. The code only documented here as the other non scaled
+number models use the same method.
@c
# define KK 100 /* the long lag */
@@ -1352,8 +1319,6 @@ static void mp_double_aux_ran_start(long seed)
mp_double_random_data.ptr = &mp_double_random_data.started;
}
-# define mp_double_aux_ran_arr_next() (*mp_double_random_data.ptr>=0? *mp_double_random_data.ptr++: mp_double_aux_ran_arr_cycle())
-
static long mp_double_aux_ran_arr_cycle(void)
{
if (mp_double_random_data.ptr == &mp_double_random_data.dummy) {
@@ -1394,16 +1359,6 @@ void mp_init_randoms (MP mp, int seed)
}
@ Here |frac| contains what's beyond the |.|. @c
-/*
-static double modulus(double left, double right)
-{
- double quota = left / right;
- double tmp;
- double frac = modf(quota, &tmp);
- frac *= right;
- return frac;
-}
-*/
void mp_number_modulo(mp_number *a, mp_number *b)
{
@@ -1417,7 +1372,7 @@ say |next_unif_random|.
@c
static void mp_next_unif_random (MP mp, mp_number *ret)
{
- unsigned long int op = (unsigned) mp_double_aux_ran_arr_next();
+ unsigned long int op = (unsigned) (*mp_double_random_data.ptr>=0? *mp_double_random_data.ptr++: mp_double_aux_ran_arr_cycle());
double a = op / (MM * 1.0);
(void) mp;
ret->data.dval = a;
@@ -1437,11 +1392,10 @@ static void mp_next_random (MP mp, mp_number *ret)
}
@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x| or
-|0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
-
-Note that the call of |take_fraction| will produce the values 0 and~|x| with
-about half the probability that it will produce any other particular values
-between 0 and~|x|, because it rounds its answers.
+|0=u=x|, given a |scaled| value~|x|, we proceed as shown here. Note that the
+call of |take_fraction| will produce the values 0 and~|x| with about half
+the probability that it will produce any other particular values between 0
+and~|x|, because it rounds its answers.
@c
static void mp_double_m_unif_rand (MP mp, mp_number *ret, mp_number *x_orig)
@@ -1504,20 +1458,40 @@ static void mp_double_m_norm_rand (MP mp, mp_number *ret)
mp_free_number(mp, &u);
}
-@ The following subroutine is used only in |norm_rand| and tests if $ab$ is
-greater than, equal to, or less than~$cd$. The result is $+1$, 0, or~$-1$ in the
-three respective cases.
-
-@c
-int mp_double_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_number *d_orig)
-{
- double ab = a_orig->data.dval * b_orig->data.dval;
- double cd = c_orig->data.dval * d_orig->data.dval;
- if (ab > cd) {
- return 1;
- } else if (ab < cd) {
- return -1;
- } else {
- return 0;
+@ @<Reduce to the case that |a...@>=
+if (a < 0) {
+ a = -a;
+ b = -b;
+}
+if (c < 0) {
+ c = -c;
+ d = -d;
+}
+if (d <= 0) {
+ if (b >= 0) {
+ if ((a == 0 || b == 0) && (c == 0 || d == 0)) {
+ ret->data.dval = 0;
+ } else {
+ ret->data.dval = 1;
+ }
+ goto RETURN;
+ } if (d == 0) {
+ ret->data.dval = (a == 0 ? 0 : -1);
+ goto RETURN;
+ } else
+ q = a;
+ a = c;
+ c = q;
+ q = -b;
+ b = -d;
+ d = q;
+ }
+} else if (b <= 0) {
+ if (b < 0 && a > 0) {
+ ret->data.dval = -1;
+ return;
+ } else
+ ret->data.dval = (c == 0 ? 0 : -1);
+ goto RETURN;
}
}
diff --git a/source/luametatex/source/mp/mpw/mpmathposit.w b/source/luametatex/source/mp/mpw/mpmathposit.w
new file mode 100644
index 000000000..8477ef27b
--- /dev/null
+++ b/source/luametatex/source/mp/mpw/mpmathposit.w
@@ -0,0 +1,1428 @@
+% This file is part of MetaPost. The MetaPost program is in the public domain.
+
+@ Introduction.
+
+TODO: collect constants like decimal
+TODO: share scanners and random
+
+@c
+# include "mpconfig.h"
+# include "mpmathposit.h"
+
+@h
+
+@ @c
+@<Declarations@>
+
+@ @(mpmathposit.h@>=
+# ifndef MPMATHPOSIT_H
+# define MPMATHPOSIT_H 1
+
+# include "mp.h"
+# include "softposit.h"
+
+math_data *mp_initialize_posit_math (MP mp);
+
+# endif
+
+@* Math initialization.
+
+First, here are some very important constants.
+
+@d mp_fraction_multiplier 4096
+@d mp_angle_multiplier 16
+@d mp_warning_limit pow(2.0,52)
+
+@d odd(A) (abs(A)%2==1)
+
+@d two_to_the(A) (1<<(unsigned)(A))
+@d set_cur_cmd(A) mp->cur_mod_->command = (A)
+@d set_cur_mod(A) mp->cur_mod_->data.n.data.pval = (A)
+
+@ Here are the functions that are static as they are not used elsewhere.
+
+@<Declarations@>=
+static void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v);
+static void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v);
+static void mp_allocate_double (MP mp, mp_number *n, double v);
+static void mp_allocate_number (MP mp, mp_number *n, mp_number_type t);
+static int mp_posit_ab_vs_cd (mp_number *a, mp_number *b, mp_number *c, mp_number *d);
+static void mp_posit_abs (mp_number *A);
+static void mp_posit_crossing_point (MP mp, mp_number *ret, mp_number *a, mp_number *b, mp_number *c);
+static void mp_posit_fraction_to_round_scaled (mp_number *x);
+static void mp_posit_m_exp (MP mp, mp_number *ret, mp_number *x_orig);
+static void mp_posit_m_log (MP mp, mp_number *ret, mp_number *x_orig);
+static void mp_posit_m_norm_rand (MP mp, mp_number *ret);
+static void mp_posit_m_unif_rand (MP mp, mp_number *ret, mp_number *x_orig);
+static void mp_posit_n_arg (MP mp, mp_number *ret, mp_number *x, mp_number *y);
+static void mp_posit_number_make_fraction (MP mp, mp_number *r, mp_number *p, mp_number *q);
+static void mp_posit_number_make_scaled (MP mp, mp_number *r, mp_number *p, mp_number *q);
+static void mp_posit_number_take_fraction (MP mp, mp_number *r, mp_number *p, mp_number *q);
+static void mp_posit_number_take_scaled (MP mp, mp_number *r, mp_number *p, mp_number *q);
+static void mp_posit_power_of (MP mp, mp_number *r, mp_number *a, mp_number *b);
+static void mp_posit_print_number (MP mp, mp_number *n);
+static void mp_posit_pyth_add (MP mp, mp_number *r, mp_number *a, mp_number *b);
+static void mp_posit_pyth_sub (MP mp, mp_number *r, mp_number *a, mp_number *b);
+static void mp_posit_scan_fractional_token (MP mp, int n);
+static void mp_posit_scan_numeric_token (MP mp, int n);
+static void mp_posit_set_precision (MP mp);
+static void mp_posit_sin_cos (MP mp, mp_number *z_orig, mp_number *n_cos, mp_number *n_sin);
+static void mp_posit_slow_add (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_orig);
+static void mp_posit_square_rt (MP mp, mp_number *ret, mp_number *x_orig);
+static void mp_posit_velocity (MP mp, mp_number *ret, mp_number *st, mp_number *ct, mp_number *sf, mp_number *cf, mp_number *t);
+static void mp_free_posit_math (MP mp);
+static void mp_free_number (MP mp, mp_number *n);
+static void mp_init_randoms (MP mp, int seed);
+static void mp_number_abs_clone (mp_number *A, mp_number *B);
+static void mp_number_add (mp_number *A, mp_number *B);
+static void mp_number_add_scaled (mp_number *A, int B); /* also for negative B */
+static void mp_number_angle_to_scaled (mp_number *A);
+static void mp_number_clone (mp_number *A, mp_number *B);
+static void mp_number_divide_int (mp_number *A, int B);
+static void mp_number_double (mp_number *A);
+static int mp_number_equal (mp_number *A, mp_number *B);
+static void mp_number_floor (mp_number *i);
+static void mp_number_fraction_to_scaled (mp_number *A);
+static int mp_number_greater (mp_number *A, mp_number *B);
+static void mp_number_half (mp_number *A);
+static int mp_number_less (mp_number *A, mp_number *B);
+static void mp_number_modulo (mp_number *a, mp_number *b);
+static void mp_number_multiply_int (mp_number *A, int B);
+static void mp_number_negate (mp_number *A);
+static void mp_number_negated_clone (mp_number *A, mp_number *B);
+static int mp_number_nonequalabs (mp_number *A, mp_number *B);
+static int mp_number_odd (mp_number *A);
+static void mp_number_scaled_to_angle (mp_number *A);
+static void mp_number_scaled_to_fraction (mp_number *A);
+static void mp_number_subtract (mp_number *A, mp_number *B);
+static void mp_number_swap (mp_number *A, mp_number *B);
+static int mp_number_to_boolean (mp_number *A);
+static double mp_number_to_double (mp_number *A);
+static int mp_number_to_int (mp_number *A);
+static int mp_number_to_scaled (mp_number *A);
+static int mp_round_unscaled (mp_number *x_orig);
+static void mp_set_posit_from_addition (mp_number *A, mp_number *B, mp_number *C);
+static void mp_set_posit_from_boolean (mp_number *A, int B);
+static void mp_set_posit_from_div (mp_number *A, mp_number *B, mp_number *C);
+static void mp_set_posit_from_double (mp_number *A, double B);
+static void mp_set_posit_from_int (mp_number *A, int B);
+static void mp_set_posit_from_int_div (mp_number *A, mp_number *B, int C);
+static void mp_set_posit_from_int_mul (mp_number *A, mp_number *B, int C);
+static void mp_set_posit_from_mul (mp_number *A, mp_number *B, mp_number *C);
+static void mp_set_posit_from_of_the_way (MP mp, mp_number *A, mp_number *t, mp_number *B, mp_number *C);
+static void mp_set_posit_from_scaled (mp_number *A, int B);
+static void mp_set_posit_from_subtraction (mp_number *A, mp_number *B, mp_number *C);
+static void mp_set_posit_half_from_addition (mp_number *A, mp_number *B, mp_number *C);
+static void mp_set_posit_half_from_subtraction (mp_number *A, mp_number *B, mp_number *C);
+static void mp_wrapup_numeric_token (MP mp, unsigned char *start, unsigned char *stop);
+static char *mp_posit_number_tostring (MP mp, mp_number *n);
+
+typedef struct mp_posit_info {
+ posit_t unity;
+ posit_t zero;
+ posit_t one;
+ posit_t two;
+ posit_t three;
+ posit_t four;
+ posit_t five;
+ posit_t eight;
+ posit_t seven;
+ posit_t sixteen;
+ posit_t half_unit;
+ posit_t minusone;
+ posit_t three_quarter_unit;
+ posit_t d16;
+ posit_t d64;
+ posit_t d256;
+ posit_t d4096;
+ posit_t d65536;
+ posit_t dp90;
+ posit_t dp180;
+ posit_t dp270;
+ posit_t dp360;
+ posit_t dm90;
+ posit_t dm180;
+ posit_t dm270;
+ posit_t dm360;
+ posit_t fraction_multiplier;
+ posit_t negative_fraction_multiplier; /* todo: also in decimal */
+ posit_t angle_multiplier;
+ posit_t fraction_one;
+ posit_t fraction_two;
+ posit_t fraction_three;
+ posit_t fraction_four;
+ posit_t fraction_half;
+ posit_t fraction_one_and_half;
+ posit_t one_eighty_degrees;
+ posit_t negative_one_eighty_degrees;
+ posit_t three_sixty_degrees;
+ posit_t no_crossing;
+ posit_t one_crossing;
+ posit_t zero_crossing;
+ posit_t error_correction;
+ posit_t pi;
+ posit_t pi_divided_by_180;
+ posit_t epsilon;
+ posit_t EL_GORDO;
+ posit_t negative_EL_GORDO;
+ posit_t one_third_EL_GORDO;
+ posit_t coef;
+ posit_t coef_bound;
+ posit_t scaled_threshold;
+ posit_t fraction_threshold;
+ posit_t equation_threshold;
+ posit_t near_zero_angle;
+ posit_t p_over_v_threshold;
+ posit_t warning_limit;
+ posit_t sqrt_two_mul_fraction_one;
+ posit_t sqrt_five_minus_one_mul_fraction_one_and_half;
+ posit_t three_minus_sqrt_five_mul_fraction_one_and_half;
+ posit_t d180_divided_by_pi_mul_angle;
+ int initialized;
+} mp_posit_info;
+
+mp_posit_info mp_posit_data = {
+ .initialized = 0,
+};
+
+inline static posit_t mp_posit_make_fraction (posit_t p, posit_t q) { return posit_mul(posit_div(p,q), mp_posit_data.fraction_multiplier); }
+inline static posit_t mp_posit_take_fraction (posit_t p, posit_t q) { return posit_div(posit_mul(p,q), mp_posit_data.fraction_multiplier); }
+inline static posit_t mp_posit_make_scaled (posit_t p, posit_t q) { return posit_div(p,q); }
+
+math_data *mp_initialize_posit_math(MP mp)
+{
+ math_data *math = (math_data *) mp_memory_allocate(sizeof(math_data));
+ /* alloc */
+ if (! mp_posit_data.initialized) {
+ mp_posit_data.initialized = 1;
+ mp_posit_data.unity = integer_to_posit(1);
+ mp_posit_data.zero = integer_to_posit(0);
+ mp_posit_data.one = integer_to_posit(1);
+ mp_posit_data.two = integer_to_posit(2);
+ mp_posit_data.three = integer_to_posit(3);
+ mp_posit_data.four = integer_to_posit(4);
+ mp_posit_data.five = integer_to_posit(5);
+ mp_posit_data.seven = integer_to_posit(7);
+ mp_posit_data.eight = integer_to_posit(8);
+ mp_posit_data.sixteen = integer_to_posit(16);
+ mp_posit_data.dp90 = integer_to_posit(90);
+ mp_posit_data.dp180 = integer_to_posit(180);
+ mp_posit_data.dp270 = integer_to_posit(270);
+ mp_posit_data.dp360 = integer_to_posit(360);
+ mp_posit_data.dm90 = integer_to_posit(-90);
+ mp_posit_data.dm180 = integer_to_posit(-180);
+ mp_posit_data.dm270 = integer_to_posit(-270);
+ mp_posit_data.dm360 = integer_to_posit(-360);
+ mp_posit_data.d16 = integer_to_posit(16);
+ mp_posit_data.d64 = integer_to_posit(64);
+ mp_posit_data.d256 = integer_to_posit(256);
+ mp_posit_data.d4096 = integer_to_posit(4096);
+ mp_posit_data.d65536 = integer_to_posit(65536);
+ mp_posit_data.minusone = posit_neg(mp_posit_data.one);
+ mp_posit_data.half_unit = posit_div(mp_posit_data.unity, mp_posit_data.two);
+ mp_posit_data.three_quarter_unit = posit_mul(mp_posit_data.three, posit_div(mp_posit_data.unity,mp_posit_data.four));
+ mp_posit_data.fraction_multiplier = integer_to_posit(mp_fraction_multiplier);
+ mp_posit_data.negative_fraction_multiplier = posit_neg(mp_posit_data.fraction_multiplier);
+ mp_posit_data.angle_multiplier = integer_to_posit(mp_angle_multiplier);
+ mp_posit_data.fraction_one = mp_posit_data.fraction_multiplier;
+ mp_posit_data.fraction_two = posit_mul(mp_posit_data.fraction_multiplier, mp_posit_data.two);
+ mp_posit_data.fraction_three = posit_mul(mp_posit_data.fraction_multiplier, mp_posit_data.three);
+ mp_posit_data.fraction_four = posit_mul(mp_posit_data.fraction_multiplier, mp_posit_data.four);
+ mp_posit_data.fraction_half = posit_div(mp_posit_data.fraction_multiplier, mp_posit_data.two);
+ mp_posit_data.fraction_one_and_half = posit_add(mp_posit_data.fraction_multiplier, mp_posit_data.fraction_half);
+ mp_posit_data.one_eighty_degrees = posit_mul(mp_posit_data.angle_multiplier, mp_posit_data.dp180);
+ mp_posit_data.negative_one_eighty_degrees = posit_mul(mp_posit_data.angle_multiplier, mp_posit_data.dm180);
+ mp_posit_data.three_sixty_degrees = posit_mul(mp_posit_data.angle_multiplier, mp_posit_data.dp360);
+ mp_posit_data.no_crossing = posit_add(mp_posit_data.fraction_multiplier, mp_posit_data.one);
+ mp_posit_data.one_crossing = mp_posit_data.fraction_multiplier;
+ mp_posit_data.zero_crossing = mp_posit_data.zero;
+ mp_posit_data.error_correction = double_to_posit(1E-12); /* debatable */
+ mp_posit_data.warning_limit = posit_pow(mp_posit_data.two, integer_to_posit(52)); /* this is a large value that can just be expressed without loss of precision */
+ mp_posit_data.pi = double_to_posit(3.1415926535897932384626433832795028841971);
+ mp_posit_data.pi_divided_by_180 = posit_div(mp_posit_data.pi, mp_posit_data.dp180);
+ mp_posit_data.epsilon = posit_pow(mp_posit_data.two, integer_to_posit(-52.0));
+ mp_posit_data.EL_GORDO = posit_sub(posit_div(double_to_posit(DBL_MAX),mp_posit_data.two), mp_posit_data.one); /* the largest value that \MP\ likes. */
+ mp_posit_data.negative_EL_GORDO = posit_neg(mp_posit_data.EL_GORDO);
+ mp_posit_data.one_third_EL_GORDO = posit_div(mp_posit_data.EL_GORDO, mp_posit_data.three);
+ mp_posit_data.coef = posit_div(mp_posit_data.seven, mp_posit_data.three); /* |fraction| approximation to 7/3 */
+ mp_posit_data.coef_bound = posit_mul(mp_posit_data.coef, mp_posit_data.fraction_multiplier);
+ mp_posit_data.scaled_threshold = double_to_posit(0.000122); /* a |scaled| coefficient less than this is zeroed */
+ mp_posit_data.near_zero_angle = posit_mul(double_to_posit(0.0256), mp_posit_data.angle_multiplier); /* an angle of about 0.0256 */
+ mp_posit_data.p_over_v_threshold = integer_to_posit(0x80000);
+ mp_posit_data.equation_threshold = double_to_posit(0.001);
+
+ mp_posit_data.sqrt_two_mul_fraction_one =
+ posit_mul(
+ posit_sqrt(mp_posit_data.two),
+ mp_posit_data.fraction_one
+ );
+
+ mp_posit_data.sqrt_five_minus_one_mul_fraction_one_and_half =
+ posit_mul(
+ posit_mul(
+ mp_posit_data.three,
+ mp_posit_data.fraction_half
+ ),
+ posit_sub(
+ posit_sqrt(mp_posit_data.five),
+ mp_posit_data.one
+ )
+ );
+
+ mp_posit_data.three_minus_sqrt_five_mul_fraction_one_and_half =
+ posit_mul(
+ posit_mul(
+ mp_posit_data.three,
+ mp_posit_data.fraction_half
+ ),
+ posit_sub(
+ mp_posit_data.three,
+ posit_sqrt(mp_posit_data.five)
+ )
+ );
+
+ mp_posit_data.d180_divided_by_pi_mul_angle =
+ posit_mul(
+ posit_div(
+ mp_posit_data.dp180,
+ mp_posit_data.pi
+ ),
+ mp_posit_data.angle_multiplier
+ );
+
+ }
+ /* alloc */
+ math->md_allocate = mp_allocate_number;
+ math->md_free = mp_free_number;
+ math->md_allocate_clone = mp_allocate_clone;
+ math->md_allocate_abs = mp_allocate_abs;
+ math->md_allocate_double = mp_allocate_double;
+ /* precission */
+ mp_allocate_number(mp, &math->md_precision_default, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_precision_max, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_precision_min, mp_scaled_type);
+ /* here are the constants for |scaled| objects */
+ mp_allocate_number(mp, &math->md_epsilon_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_inf_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_negative_inf_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_warning_limit_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_one_third_inf_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_unity_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_two_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_three_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_half_unit_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_three_quarter_unit_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_zero_t, mp_scaled_type);
+ /* |fractions| */
+ mp_allocate_number(mp, &math->md_arc_tol_k, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_fraction_one_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_fraction_half_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_fraction_three_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_fraction_four_t, mp_fraction_type);
+ /* |angles| */
+ mp_allocate_number(mp, &math->md_three_sixty_deg_t, mp_angle_type);
+ mp_allocate_number(mp, &math->md_one_eighty_deg_t, mp_angle_type);
+ mp_allocate_number(mp, &math->md_negative_one_eighty_deg_t, mp_angle_type);
+ /* various approximations */
+ mp_allocate_number(mp, &math->md_one_k, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_sqrt_8_e_k, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_twelve_ln_2_k, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_coef_bound_k, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_coef_bound_minus_1, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_twelvebits_3, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_twentysixbits_sqrt2_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_twentyeightbits_d_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_twentysevenbits_sqrt2_d_t, mp_fraction_type);
+ /* thresholds */
+ mp_allocate_number(mp, &math->md_fraction_threshold_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_half_fraction_threshold_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_scaled_threshold_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_half_scaled_threshold_t, mp_scaled_type);
+ mp_allocate_number(mp, &math->md_near_zero_angle_t, mp_angle_type);
+ mp_allocate_number(mp, &math->md_p_over_v_threshold_t, mp_fraction_type);
+ mp_allocate_number(mp, &math->md_equation_threshold_t, mp_scaled_type);
+ /* initializations */
+ math->md_precision_default.data.pval = posit_mul(mp_posit_data.d16, mp_posit_data.unity);
+ math->md_precision_max.data.pval = posit_mul(mp_posit_data.d16, mp_posit_data.unity);
+ math->md_precision_min.data.pval = posit_mul(mp_posit_data.d16, mp_posit_data.unity);
+ math->md_epsilon_t.data.pval = mp_posit_data.epsilon;
+ math->md_inf_t.data.pval = mp_posit_data.EL_GORDO;
+ math->md_negative_inf_t.data.pval = mp_posit_data.negative_EL_GORDO;
+ math->md_one_third_inf_t.data.pval = mp_posit_data.one_third_EL_GORDO;
+ math->md_warning_limit_t.data.pval = mp_posit_data.warning_limit;
+ math->md_unity_t.data.pval = mp_posit_data.unity;
+ math->md_two_t.data.pval = mp_posit_data.two;
+ math->md_three_t.data.pval = mp_posit_data.three;
+ math->md_half_unit_t.data.pval = mp_posit_data.half_unit;
+ math->md_three_quarter_unit_t.data.pval = mp_posit_data.three_quarter_unit;
+ math->md_arc_tol_k.data.pval = posit_div(mp_posit_data.unity, mp_posit_data.d4096); /* quit when change in arc length estimate reaches this */
+ math->md_fraction_one_t.data.pval = mp_posit_data.fraction_one;
+ math->md_fraction_half_t.data.pval = mp_posit_data.fraction_half;
+ math->md_fraction_three_t.data.pval = mp_posit_data.fraction_three;
+ math->md_fraction_four_t.data.pval = mp_posit_data.fraction_four;
+ math->md_three_sixty_deg_t.data.pval = mp_posit_data.three_sixty_degrees;
+ math->md_one_eighty_deg_t.data.pval = mp_posit_data.one_eighty_degrees;
+ math->md_negative_one_eighty_deg_t.data.pval = mp_posit_data.negative_one_eighty_degrees;
+ math->md_one_k.data.pval = posit_div(mp_posit_data.one, mp_posit_data.d64);
+ math->md_sqrt_8_e_k.data.pval = double_to_posit(1.71552776992141359295); /* $2^{16}\sqrt{8/e} \approx 112428.82793$ */
+ math->md_twelve_ln_2_k.data.pval = posit_mul(double_to_posit(8.31776616671934371292), mp_posit_data.d256); /* $2^{24}\cdot12\ln2 \approx139548959.6165 $ */
+ math->md_twelvebits_3.data.pval = posit_div(integer_to_posit(1365), mp_posit_data.unity); /* $1365 \approx 2^{12}/3 $ */
+ math->md_twentysixbits_sqrt2_t.data.pval = posit_div(integer_to_posit(94906266), mp_posit_data.d65536); /* $2^{26}\sqrt2 \approx 94906265.62 $ */
+ math->md_twentyeightbits_d_t.data.pval = posit_div(integer_to_posit(35596755), mp_posit_data.d65536); /* $2^{28}d \approx 35596754.69 $ */
+ math->md_twentysevenbits_sqrt2_d_t.data.pval = posit_div(integer_to_posit(25170707), mp_posit_data.d65536); /* $2^{27}\sqrt2\,d \approx 25170706.63 $ */
+ math->md_coef_bound_k.data.pval = mp_posit_data.coef_bound;
+ math->md_coef_bound_minus_1.data.pval = posit_sub(mp_posit_data.coef_bound, posit_div(mp_posit_data.one, mp_posit_data.d65536));
+ math->md_fraction_threshold_t.data.pval = double_to_posit(0.04096); /* a |fraction| coefficient less than this is zeroed */
+ math->md_half_fraction_threshold_t.data.pval = posit_div(mp_posit_data.fraction_threshold, mp_posit_data.two);
+ math->md_scaled_threshold_t.data.pval = mp_posit_data.scaled_threshold;
+ math->md_half_scaled_threshold_t.data.pval = posit_div(mp_posit_data.scaled_threshold,mp_posit_data.two);
+ math->md_near_zero_angle_t.data.pval = mp_posit_data.near_zero_angle;
+ math->md_p_over_v_threshold_t.data.pval = mp_posit_data.p_over_v_threshold;
+ math->md_equation_threshold_t.data.pval = mp_posit_data.equation_threshold;
+
+ /* functions */
+ math->md_from_int = mp_set_posit_from_int;
+ math->md_from_boolean = mp_set_posit_from_boolean;
+ math->md_from_scaled = mp_set_posit_from_scaled;
+ math->md_from_double = mp_set_posit_from_double;
+ math->md_from_addition = mp_set_posit_from_addition;
+ math->md_half_from_addition = mp_set_posit_half_from_addition;
+ math->md_from_subtraction = mp_set_posit_from_subtraction;
+ math->md_half_from_subtraction = mp_set_posit_half_from_subtraction;
+ math->md_from_oftheway = mp_set_posit_from_of_the_way;
+ math->md_from_div = mp_set_posit_from_div;
+ math->md_from_mul = mp_set_posit_from_mul;
+ math->md_from_int_div = mp_set_posit_from_int_div;
+ math->md_from_int_mul = mp_set_posit_from_int_mul;
+ math->md_negate = mp_number_negate;
+ math->md_add = mp_number_add;
+ math->md_subtract = mp_number_subtract;
+ math->md_half = mp_number_half;
+ math->md_do_double = mp_number_double;
+ math->md_abs = mp_posit_abs;
+ math->md_clone = mp_number_clone;
+ math->md_negated_clone = mp_number_negated_clone;
+ math->md_abs_clone = mp_number_abs_clone;
+ math->md_swap = mp_number_swap;
+ math->md_add_scaled = mp_number_add_scaled;
+ math->md_multiply_int = mp_number_multiply_int;
+ math->md_divide_int = mp_number_divide_int;
+ math->md_to_boolean = mp_number_to_boolean;
+ math->md_to_scaled = mp_number_to_scaled;
+ math->md_to_double = mp_number_to_double;
+ math->md_to_int = mp_number_to_int;
+ math->md_odd = mp_number_odd;
+ math->md_equal = mp_number_equal;
+ math->md_less = mp_number_less;
+ math->md_greater = mp_number_greater;
+ math->md_nonequalabs = mp_number_nonequalabs;
+ math->md_round_unscaled = mp_round_unscaled;
+ math->md_floor_scaled = mp_number_floor;
+ math->md_fraction_to_round_scaled = mp_posit_fraction_to_round_scaled;
+ math->md_make_scaled = mp_posit_number_make_scaled;
+ math->md_make_fraction = mp_posit_number_make_fraction;
+ math->md_take_fraction = mp_posit_number_take_fraction;
+ math->md_take_scaled = mp_posit_number_take_scaled;
+ math->md_velocity = mp_posit_velocity;
+ math->md_n_arg = mp_posit_n_arg;
+ math->md_m_log = mp_posit_m_log;
+ math->md_m_exp = mp_posit_m_exp;
+ math->md_m_unif_rand = mp_posit_m_unif_rand;
+ math->md_m_norm_rand = mp_posit_m_norm_rand;
+ math->md_pyth_add = mp_posit_pyth_add;
+ math->md_pyth_sub = mp_posit_pyth_sub;
+ math->md_power_of = mp_posit_power_of;
+ math->md_fraction_to_scaled = mp_number_fraction_to_scaled;
+ math->md_scaled_to_fraction = mp_number_scaled_to_fraction;
+ math->md_scaled_to_angle = mp_number_scaled_to_angle;
+ math->md_angle_to_scaled = mp_number_angle_to_scaled;
+ math->md_init_randoms = mp_init_randoms;
+ math->md_sin_cos = mp_posit_sin_cos;
+ math->md_slow_add = mp_posit_slow_add;
+ math->md_sqrt = mp_posit_square_rt;
+ math->md_print = mp_posit_print_number;
+ math->md_tostring = mp_posit_number_tostring;
+ math->md_modulo = mp_number_modulo;
+ math->md_ab_vs_cd = mp_posit_ab_vs_cd;
+ math->md_crossing_point = mp_posit_crossing_point;
+ math->md_scan_numeric = mp_posit_scan_numeric_token;
+ math->md_scan_fractional = mp_posit_scan_fractional_token;
+ math->md_free_math = mp_free_posit_math;
+ math->md_set_precision = mp_posit_set_precision;
+ return math;
+}
+
+void mp_posit_set_precision (MP mp)
+{
+ (void) mp;
+}
+
+void mp_free_posit_math (MP mp)
+{
+ /* Is this list up to date? Also check elewhere. */
+ mp_free_number(mp, &(mp->math->md_three_sixty_deg_t));
+ mp_free_number(mp, &(mp->math->md_one_eighty_deg_t));
+ mp_free_number(mp, &(mp->math->md_negative_one_eighty_deg_t));
+ mp_free_number(mp, &(mp->math->md_fraction_one_t));
+ mp_free_number(mp, &(mp->math->md_zero_t));
+ mp_free_number(mp, &(mp->math->md_half_unit_t));
+ mp_free_number(mp, &(mp->math->md_three_quarter_unit_t));
+ mp_free_number(mp, &(mp->math->md_unity_t));
+ mp_free_number(mp, &(mp->math->md_two_t));
+ mp_free_number(mp, &(mp->math->md_three_t));
+ mp_free_number(mp, &(mp->math->md_one_third_inf_t));
+ mp_free_number(mp, &(mp->math->md_inf_t));
+ mp_free_number(mp, &(mp->math->md_negative_inf_t));
+ mp_free_number(mp, &(mp->math->md_warning_limit_t));
+ mp_free_number(mp, &(mp->math->md_one_k));
+ mp_free_number(mp, &(mp->math->md_sqrt_8_e_k));
+ mp_free_number(mp, &(mp->math->md_twelve_ln_2_k));
+ mp_free_number(mp, &(mp->math->md_coef_bound_k));
+ mp_free_number(mp, &(mp->math->md_coef_bound_minus_1));
+ mp_free_number(mp, &(mp->math->md_fraction_threshold_t));
+ mp_free_number(mp, &(mp->math->md_half_fraction_threshold_t));
+ mp_free_number(mp, &(mp->math->md_scaled_threshold_t));
+ mp_free_number(mp, &(mp->math->md_half_scaled_threshold_t));
+ mp_free_number(mp, &(mp->math->md_near_zero_angle_t));
+ mp_free_number(mp, &(mp->math->md_p_over_v_threshold_t));
+ mp_free_number(mp, &(mp->math->md_equation_threshold_t));
+ mp_memory_free(mp->math);
+}
+
+@ See mpmathdouble for documentation. @c
+
+void mp_allocate_number (MP mp, mp_number *n, mp_number_type t)
+{
+ (void) mp;
+ n->data.pval = mp_posit_data.zero;
+ n->type = t;
+}
+
+void mp_allocate_clone (MP mp, mp_number *n, mp_number_type t, mp_number *v)
+{
+ (void) mp;
+ n->type = t;
+ n->data.pval = v->data.pval;
+}
+
+void mp_allocate_abs (MP mp, mp_number *n, mp_number_type t, mp_number *v)
+{
+ (void) mp;
+ n->type = t;
+ n->data.pval = posit_fabs(v->data.pval);
+}
+
+void mp_allocate_double (MP mp, mp_number *n, double v)
+{
+ (void) mp;
+ n->type = mp_scaled_type;
+ n->data.pval = double_to_posit(v);
+}
+
+void mp_free_number (MP mp, mp_number *n)
+{
+ (void) mp;
+ n->type = mp_nan_type;
+}
+
+void mp_set_posit_from_int(mp_number *A, int B)
+{
+ A->data.pval = integer_to_posit(B);
+}
+
+void mp_set_posit_from_boolean(mp_number *A, int B)
+{
+ A->data.pval = integer_to_posit(B);
+}
+
+void mp_set_posit_from_scaled(mp_number *A, int B)
+{
+ A->data.pval = posit_div(integer_to_posit(B), mp_posit_data.d65536);
+}
+
+void mp_set_posit_from_double(mp_number *A, double B)
+{
+ A->data.pval = double_to_posit(B);
+}
+
+void mp_set_posit_from_addition(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_add(B->data.pval, C->data.pval);
+}
+
+void mp_set_posit_half_from_addition(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_div(posit_add(B->data.pval,C->data.pval), mp_posit_data.two);
+}
+
+void mp_set_posit_from_subtraction(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_sub(B->data.pval, C->data.pval);
+}
+
+void mp_set_posit_half_from_subtraction(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_div(posit_sub(B->data.pval, C->data.pval), mp_posit_data.two);
+}
+
+void mp_set_posit_from_div(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_div(B->data.pval, C->data.pval);
+}
+
+void mp_set_posit_from_mul(mp_number *A, mp_number *B, mp_number *C)
+{
+ A->data.pval = posit_mul(B->data.pval, C->data.pval);
+}
+
+void mp_set_posit_from_int_div(mp_number *A, mp_number *B, int C)
+{
+ A->data.pval = posit_div(B->data.pval, integer_to_posit(C));
+}
+
+void mp_set_posit_from_int_mul(mp_number *A, mp_number *B, int C)
+{
+ A->data.pval = posit_mul(A->data.pval, integer_to_posit(C));
+}
+
+void mp_set_posit_from_of_the_way (MP mp, mp_number *A, mp_number *t, mp_number *B, mp_number *C)
+{
+ (void) mp;
+ A->data.pval = posit_sub(B->data.pval, mp_posit_take_fraction(posit_sub(B->data.pval, C->data.pval), t->data.pval));
+}
+
+void mp_number_negate(mp_number *A)
+{
+ A->data.pval = posit_neg(A->data.pval);
+}
+
+void mp_number_add(mp_number *A, mp_number *B)
+{
+ A->data.pval = posit_add(A->data.pval, B->data.pval);
+}
+
+void mp_number_subtract(mp_number *A, mp_number *B)
+{
+ A->data.pval = posit_sub(A->data.pval, B->data.pval);
+}
+
+void mp_number_half(mp_number *A)
+{
+ A->data.pval = posit_div(A->data.pval, mp_posit_data.two);
+}
+
+void mp_number_double(mp_number *A)
+{
+ A->data.pval = posit_mul(A->data.pval, mp_posit_data.two);
+}
+
+void mp_number_add_scaled(mp_number *A, int B)
+{
+ /* also for negative B */
+ A->data.pval = posit_add(A->data.pval, posit_div(integer_to_posit(B), mp_posit_data.d65536));
+}
+
+void mp_number_multiply_int(mp_number *A, int B)
+{
+ A->data.pval = posit_mul(A->data.pval, integer_to_posit(B));
+}
+
+void mp_number_divide_int(mp_number *A, int B)
+{
+ A->data.pval = posit_div(A->data.pval, integer_to_posit(B));
+}
+
+void mp_posit_abs(mp_number *A)
+{
+ A->data.pval = posit_fabs(A->data.pval);
+}
+
+void mp_number_clone(mp_number *A, mp_number *B)
+{
+ A->data.pval = B->data.pval;
+}
+
+void mp_number_negated_clone(mp_number *A, mp_number *B)
+{
+ A->data.pval = posit_neg(B->data.pval);
+}
+
+void mp_number_abs_clone(mp_number *A, mp_number *B)
+{
+ A->data.pval = posit_fabs(B->data.pval);
+}
+
+void mp_number_swap(mp_number *A, mp_number *B)
+{
+ posit_t swap_tmp = A->data.pval;
+ A->data.pval = B->data.pval;
+ B->data.pval = swap_tmp;
+}
+
+void mp_number_fraction_to_scaled(mp_number *A)
+{
+ A->type = mp_scaled_type;
+ A->data.pval = posit_div(A->data.pval, mp_posit_data.fraction_multiplier);
+}
+
+void mp_number_angle_to_scaled(mp_number *A)
+{
+ A->type = mp_scaled_type;
+ A->data.pval = posit_div(A->data.pval, mp_posit_data.angle_multiplier);
+}
+
+void mp_number_scaled_to_fraction(mp_number *A)
+{
+ A->type = mp_fraction_type;
+ A->data.pval = posit_mul(A->data.pval, mp_posit_data.fraction_multiplier);
+}
+
+void mp_number_scaled_to_angle(mp_number *A)
+{
+ A->type = mp_angle_type;
+ A->data.pval = posit_mul(A->data.pval, mp_posit_data.angle_multiplier);
+}
+
+int mp_number_to_scaled(mp_number *A)
+{
+ return posit_to_integer(posit_mul(A->data.pval, mp_posit_data.d65536));
+}
+
+int mp_number_to_int(mp_number *A)
+{
+ return posit_to_integer(A->data.pval);
+}
+
+int mp_number_to_boolean(mp_number *A)
+{
+ return posit_eq_zero(A->data.pval) ? 0 : 1;
+}
+
+double mp_number_to_double(mp_number *A)
+{
+ return posit_to_double(A->data.pval);
+}
+
+int mp_number_odd(mp_number *A)
+{
+ return odd(posit_to_integer(A->data.pval));
+}
+
+int mp_number_equal(mp_number *A, mp_number *B)
+{
+ return posit_eq(A->data.pval, B->data.pval);
+}
+
+int mp_number_greater(mp_number *A, mp_number *B)
+{
+ return posit_gt(A->data.pval, B->data.pval);
+}
+
+int mp_number_less(mp_number *A, mp_number *B)
+{
+ return posit_lt(A->data.pval, B->data.pval);
+}
+
+int mp_number_nonequalabs(mp_number *A, mp_number *B)
+{
+ return ! posit_eq(posit_fabs(A->data.pval), posit_fabs(B->data.pval));
+}
+
+char *mp_posit_number_tostring (MP mp, mp_number *n)
+{
+ static char set[64];
+ int l = 0;
+ char *ret = mp_memory_allocate(64);
+ (void) mp;
+ snprintf(set, 64, "%.20g", posit_to_double(n->data.pval));
+ while (set[l] == ' ') {
+ l++;
+ }
+ strcpy(ret, set+l);
+ return ret;
+}
+
+void mp_posit_print_number (MP mp, mp_number *n)
+{
+ char *str = mp_posit_number_tostring(mp, n);
+ mp_print_e_str(mp, str);
+ mp_memory_free(str);
+}
+
+/* Todo: it is hard to overflow posits. Also, we can check zero fast. */
+
+void mp_posit_slow_add (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_orig)
+{
+ if (posit_gt(x_orig->data.pval, mp_posit_data.zero)) {
+ if (posit_le(y_orig->data.pval, posit_sub(mp_posit_data.EL_GORDO, x_orig->data.pval))) {
+ ret->data.pval = posit_add(x_orig->data.pval, y_orig->data.pval);
+ } else {
+ mp->arith_error = 1;
+ ret->data.pval = mp_posit_data.EL_GORDO;
+ }
+ } else if (posit_le(posit_neg(y_orig->data.pval), posit_add(mp_posit_data.EL_GORDO, x_orig->data.pval))) {
+ ret->data.pval = posit_add(x_orig->data.pval, y_orig->data.pval);
+ } else {
+ mp->arith_error = 1;
+ ret->data.pval = mp_posit_data.negative_EL_GORDO;
+ }
+}
+
+void mp_posit_number_make_fraction (MP mp, mp_number *ret, mp_number *p, mp_number *q) {
+ (void) mp;
+ ret->data.pval = mp_posit_make_fraction(p->data.pval, q->data.pval);
+}
+
+void mp_posit_number_take_fraction (MP mp, mp_number *ret, mp_number *p, mp_number *q) {
+ (void) mp;
+ ret->data.pval = mp_posit_take_fraction(p->data.pval, q->data.pval);
+}
+
+void mp_posit_number_take_scaled (MP mp, mp_number *ret, mp_number *p_orig, mp_number *q_orig)
+{
+ (void) mp;
+ ret->data.pval = posit_mul(p_orig->data.pval, q_orig->data.pval);
+}
+
+void mp_posit_number_make_scaled (MP mp, mp_number *ret, mp_number *p_orig, mp_number *q_orig)
+{
+ (void) mp;
+ ret->data.pval = posit_div(p_orig->data.pval, q_orig->data.pval);
+}
+
+void mp_wrapup_numeric_token (MP mp, unsigned char *start, unsigned char *stop)
+{
+ double result;
+ char *end = (char *) stop;
+ errno = 0;
+ result = strtod((char *) start, &end);
+ if (errno == 0) {
+ set_cur_mod(double_to_posit(result));
+ if (result >= mp_warning_limit) {
+ if (posit_gt(internal_value(mp_warning_check_internal).data.pval, mp_posit_data.zero) && (mp->scanner_status != mp_tex_flushing_state)) {
+ char msg[256];
+ mp_snprintf(msg, 256, "Number is too large (%g)", result);
+ @.Number is too large@>
+ mp_error(
+ mp,
+ msg,
+ "Continue and I'll try to cope with that big value; but it might be dangerous."
+ "(Set warningcheck := 0 to suppress this message.)"
+ );
+ }
+ }
+ } else if (mp->scanner_status != mp_tex_flushing_state) {
+ mp_error(
+ mp,
+ "Enormous number has been reduced.",
+ "I could not handle this number specification probably because it is out of"
+ "range."
+ );
+ @.Enormous number...@>
+ set_cur_mod(mp_posit_data.EL_GORDO);
+ }
+ set_cur_cmd(mp_numeric_command);
+}
+
+static void mp_posit_aux_find_exponent (MP mp)
+{
+ if (mp->buffer[mp->cur_input.loc_field] == 'e' || mp->buffer[mp->cur_input.loc_field] == 'E') {
+ mp->cur_input.loc_field++;
+ if (!(mp->buffer[mp->cur_input.loc_field] == '+'
+ || mp->buffer[mp->cur_input.loc_field] == '-'
+ || mp->char_class[mp->buffer[mp->cur_input.loc_field]] == mp_digit_class)) {
+ mp->cur_input.loc_field--;
+ return;
+ }
+ if (mp->buffer[mp->cur_input.loc_field] == '+'
+ || mp->buffer[mp->cur_input.loc_field] == '-') {
+ mp->cur_input.loc_field++;
+ }
+ while (mp->char_class[mp->buffer[mp->cur_input.loc_field]] == mp_digit_class) {
+ mp->cur_input.loc_field++;
+ }
+ }
+}
+
+void mp_posit_scan_fractional_token (MP mp, int n) /* n is scaled */
+{
+ unsigned char *start = &mp->buffer[mp->cur_input.loc_field -1];
+ unsigned char *stop;
+ (void) n;
+ while (mp->char_class[mp->buffer[mp->cur_input.loc_field]] == mp_digit_class) {
+ mp->cur_input.loc_field++;
+ }
+ mp_posit_aux_find_exponent(mp);
+ stop = &mp->buffer[mp->cur_input.loc_field-1];
+ mp_wrapup_numeric_token(mp, start, stop);
+}
+
+void mp_posit_scan_numeric_token (MP mp, int n) /* n is scaled */
+{
+ unsigned char *start = &mp->buffer[mp->cur_input.loc_field -1];
+ unsigned char *stop;
+ (void) n;
+ while (mp->char_class[mp->buffer[mp->cur_input.loc_field]] == mp_digit_class) {
+ mp->cur_input.loc_field++;
+ }
+ if (mp->buffer[mp->cur_input.loc_field] == '.' && mp->buffer[mp->cur_input.loc_field+1] != '.') {
+ mp->cur_input.loc_field++;
+ while (mp->char_class[mp->buffer[mp->cur_input.loc_field]] == mp_digit_class) {
+ mp->cur_input.loc_field++;
+ }
+ }
+ mp_posit_aux_find_exponent(mp);
+ stop = &mp->buffer[mp->cur_input.loc_field-1];
+ mp_wrapup_numeric_token(mp, start, stop);
+}
+
+void mp_posit_velocity (MP mp, mp_number *ret, mp_number *st, mp_number *ct, mp_number *sf, mp_number *cf, mp_number *t)
+{
+ posit_t acc, num, denom; /* registers for intermediate calculations */
+ (void) mp;
+ acc = mp_posit_take_fraction(
+ mp_posit_take_fraction(
+ posit_sub(st->data.pval, posit_div(sf->data.pval, mp_posit_data.sixteen)),
+ posit_sub(sf->data.pval, posit_div(st->data.pval, mp_posit_data.sixteen))
+ ),
+ posit_sub(ct->data.pval,cf->data.pval)
+ );
+ num = posit_add(
+ mp_posit_data.fraction_two,
+ mp_posit_take_fraction(
+ acc,
+ mp_posit_data.sqrt_two_mul_fraction_one
+ )
+ );
+ denom = posit_add(
+ mp_posit_data.fraction_three,
+ posit_add(
+ mp_posit_take_fraction(
+ ct->data.pval,
+ mp_posit_data.sqrt_five_minus_one_mul_fraction_one_and_half
+ ),
+ mp_posit_take_fraction(
+ cf->data.pval,
+ mp_posit_data.three_minus_sqrt_five_mul_fraction_one_and_half
+ )
+ )
+ );
+ if (posit_ne(t->data.pval, mp_posit_data.unity)) {
+ num = mp_posit_make_scaled(num, t->data.pval);
+ }
+ if (posit_ge(posit_div(num, mp_posit_data.four), denom)) {
+ ret->data.pval = mp_posit_data.fraction_four;
+ } else {
+ ret->data.pval = mp_posit_make_fraction(num, denom);
+ }
+}
+
+int mp_posit_ab_vs_cd (mp_number *a_orig, mp_number *b_orig, mp_number *c_orig, mp_number *d_orig)
+{
+ posit_t ab = posit_mul(a_orig->data.pval, b_orig->data.pval);
+ posit_t cd = posit_mul(c_orig->data.pval, d_orig->data.pval);
+ if (posit_eq(ab,cd)) {
+ return 0;
+ } else if (posit_lt(ab,cd)) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+static void mp_posit_crossing_point (MP mp, mp_number *ret, mp_number *aa, mp_number *bb, mp_number *cc)
+{
+ posit_t d;
+ posit_t xx, x0, x1, x2;
+ posit_t a = aa->data.pval;
+ posit_t b = bb->data.pval;
+ posit_t c = cc->data.pval;
+ (void) mp;
+ if (posit_lt(a, mp_posit_data.zero)) {
+ ret->data.pval = mp_posit_data.zero_crossing;
+ return;
+ }
+ if (posit_ge(c, mp_posit_data.zero)) {
+ if (posit_ge(b, mp_posit_data.zero)) {
+ if (posit_gt(c, mp_posit_data.zero)) {
+ ret->data.pval = mp_posit_data.no_crossing;
+ } else if (posit_eq_zero(a) && posit_eq_zero(b)) {
+ ret->data.pval = mp_posit_data.no_crossing;
+ } else {
+ ret->data.pval = mp_posit_data.one_crossing;
+ }
+ return;
+ }
+ if (posit_eq_zero(a)) {
+ ret->data.pval = mp_posit_data.zero_crossing;
+ return;
+ }
+ } else if (posit_eq_zero(a) && posit_le(b, mp_posit_data.zero)) {
+ ret->data.pval = mp_posit_data.zero_crossing;
+ return;
+ }
+ /* Use bisection to find the crossing point... */
+ d = mp_posit_data.epsilon;
+ x0 = a;
+ x1 = posit_sub(a, b);
+ x2 = posit_sub(b, c);
+ do {
+ /* not sure why the error correction has to be >= 1E-12 */
+ posit_t x = posit_add(posit_div(posit_add(x1, x2), mp_posit_data.two), mp_posit_data.error_correction);
+ if (posit_gt(posit_sub(x1, x0), x0)) {
+ x2 = x;
+ x0 = posit_add(x0, x0);
+ d = posit_add(d, d);
+ } else {
+ xx = posit_sub(posit_add(x1, x), x0);
+ if (posit_gt(xx, x0)) {
+ x2 = x;
+ x0 = posit_add(x0, x0);
+ d = posit_add(d, d);
+ } else {
+ x0 = posit_sub(x0, xx);
+ if (posit_le(x, x0) && posit_le(posit_add(x, x2), x0)) {
+ ret->data.pval = mp_posit_data.no_crossing;
+ return;
+ }
+ x1 = x;
+ d = posit_add(posit_add(d, d), mp_posit_data.epsilon);
+ }
+ }
+ } while (posit_lt(d, mp_posit_data.fraction_one));
+ ret->data.pval = posit_sub(d, mp_posit_data.fraction_one);
+}
+
+@ See mpmathdouble for documentation. @c
+
+int mp_round_unscaled(mp_number *x_orig)
+{
+ return posit_i_round(x_orig->data.pval);
+}
+
+void mp_number_floor(mp_number *i)
+{
+ i->data.pval = posit_floor(i->data.pval);
+}
+
+void mp_posit_fraction_to_round_scaled(mp_number *x_orig)
+{
+ x_orig->type = mp_scaled_type;
+ x_orig->data.pval = posit_div(x_orig->data.pval, mp_posit_data.fraction_multiplier);
+}
+
+void mp_posit_square_rt (MP mp, mp_number *ret, mp_number *x_orig) /* return, x: scaled */
+{
+ if (posit_gt(x_orig->data.pval, mp_posit_data.zero)) {
+ ret->data.pval = posit_sqrt(x_orig->data.pval);
+ } else {
+ if (posit_lt(x_orig->data.pval, mp_posit_data.zero)) {
+ char msg[256];
+ char *xstr = mp_posit_number_tostring(mp, x_orig);
+ mp_snprintf(msg, 256, "Square root of %s has been replaced by 0", xstr);
+ mp_memory_free(xstr);
+ @.Square root...replaced by 0@>
+ mp_error(
+ mp,
+ msg,
+ "Since I don't take square roots of negative numbers, I'm zeroing this one.\n"
+ "Proceed, with fingers crossed."
+ );
+ }
+ ret->data.pval = mp_posit_data.zero;
+ }
+}
+
+void mp_posit_pyth_add (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
+{
+ ret->data.pval = posit_sqrt(
+ posit_add(
+ posit_mul(
+ a_orig->data.pval,
+ a_orig->data.pval
+ ),
+ posit_mul(
+ b_orig->data.pval,
+ b_orig->data.pval
+ )
+ )
+ );
+}
+
+void mp_posit_pyth_sub (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
+{
+ /* can be made nicer */
+ if (posit_gt(a_orig->data.pval,b_orig->data.pval)) {
+ a_orig->data.pval = posit_sqrt(
+ posit_sub(
+ posit_mul(
+ a_orig->data.pval,
+ a_orig->data.pval
+ ),
+ posit_mul(
+ b_orig->data.pval,
+ b_orig->data.pval
+ )
+ )
+ );
+ } else {
+ if (posit_lt(a_orig->data.pval,b_orig->data.pval)) {
+ char msg[256];
+ char *astr = mp_posit_number_tostring(mp, a_orig);
+ char *bstr = mp_posit_number_tostring(mp, b_orig);
+ mp_snprintf(msg, 256, "Pythagorean subtraction %s+-+%s has been replaced by 0", astr, bstr);
+ mp_memory_free(astr);
+ mp_memory_free(bstr);
+ @.Pythagorean...@>
+ mp_error(
+ mp,
+ msg,
+ "Since I don't take square roots of negative numbers, Im zeroing this one.\n"
+ "Proceed, with fingers crossed."
+ );
+ }
+ a_orig->data.pval = mp_posit_data.zero;
+ }
+ ret->data.pval = a_orig->data.pval;
+}
+
+void mp_posit_power_of (MP mp, mp_number *ret, mp_number *a_orig, mp_number *b_orig)
+{
+ errno = 0;
+ ret->data.pval = posit_pow(a_orig->data.pval, b_orig->data.pval);
+ if (errno) {
+ mp->arith_error = 1;
+ ret->data.pval = mp_posit_data.EL_GORDO;
+ }
+}
+
+void mp_posit_m_log (MP mp, mp_number *ret, mp_number *x_orig)
+{
+ /* TODO: int mult */
+ if (posit_gt(x_orig->data.pval,mp_posit_data.zero)) {
+ ret->data.pval = posit_mul(posit_log(x_orig->data.pval),mp_posit_data.d256);
+ } else {
+ char msg[256];
+ char *xstr = mp_posit_number_tostring(mp, x_orig);
+ mp_snprintf(msg, 256, "Logarithm of %s has been replaced by 0", xstr);
+ mp_memory_free(xstr);
+ mp_error(
+ mp,
+ msg,
+ "Since I don't take logs of non-positive numbers, I'm zeroing this one.\n"
+ "Proceed, with fingers crossed."
+ );
+ ret->data.pval = mp_posit_data.zero;
+ }
+}
+
+void mp_posit_m_exp (MP mp, mp_number *ret, mp_number *x_orig)
+{
+ errno = 0;
+ ret->data.pval = posit_exp(posit_div(x_orig->data.pval,mp_posit_data.d256));
+ if (errno) {
+ if (posit_gt(x_orig->data.pval,mp_posit_data.zero)) {
+ mp->arith_error = 1;
+ ret->data.pval = mp_posit_data.EL_GORDO;
+ } else {
+ ret->data.pval = mp_posit_data.zero;
+ }
+ }
+}
+
+void mp_posit_n_arg (MP mp, mp_number *ret, mp_number *x_orig, mp_number *y_orig)
+{
+ if (posit_eq_zero(x_orig->data.pval) && posit_eq_zero(y_orig->data.pval)) {
+ mp_error(
+ mp,
+ "angle(0,0) is taken as zero",
+ "The 'angle' between two identical points is undefined. I'm zeroing this one.\n"
+ "Proceed, with fingers crossed."
+ );
+ ret->data.pval = mp_posit_data.zero;
+ } else {
+ ret->type = mp_angle_type;
+ /* TODO */
+ ret->data.pval = posit_mul(
+ posit_atan2(
+ y_orig->data.pval,
+ x_orig->data.pval
+ ),
+ mp_posit_data.d180_divided_by_pi_mul_angle
+ );
+ }
+}
+
+void mp_posit_sin_cos (MP mp, mp_number *z_orig, mp_number *n_cos, mp_number *n_sin)
+{
+ posit_t rad = posit_div(z_orig->data.pval, mp_posit_data.angle_multiplier);
+ (void) mp;
+ if (posit_eq(rad, mp_posit_data.dp90) || posit_eq(rad, mp_posit_data.dm270)) {
+ n_cos->data.pval = mp_posit_data.zero;
+ n_sin->data.pval = mp_posit_data.fraction_multiplier;
+ } else if (posit_eq(rad, mp_posit_data.dm90) || posit_eq(rad, mp_posit_data.dp270)) {
+ n_cos->data.pval = mp_posit_data.zero;
+ n_sin->data.pval = mp_posit_data.negative_fraction_multiplier;
+ } else if (posit_eq(rad, mp_posit_data.dp180) || posit_eq(rad, mp_posit_data.dm180)) {
+ n_cos->data.pval = mp_posit_data.negative_fraction_multiplier;
+ n_sin->data.pval = mp_posit_data.zero;
+ } else {
+ rad = posit_mul(rad,mp_posit_data.pi_divided_by_180);
+ n_cos->data.pval = posit_mul(posit_cos(rad),mp_posit_data.fraction_multiplier);
+ n_sin->data.pval = posit_mul(posit_sin(rad),mp_posit_data.fraction_multiplier);
+ }
+}
+
+@ See mpmathdouble for documentation. @c
+
+# define KK 100 /* the long lag */
+# define LL 37 /* the short lag */
+# define MM (1L<<30) /* the modulus */
+# define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */
+# define TT 70 /* guaranteed separation between streams */
+# define is_odd(x) ((x)&1) /* units bit of x */
+# define QUALITY 1009 /* recommended quality level for high-res use */
+
+/* destination, array length (must be at least KK) */
+
+typedef struct mp_posit_random_info {
+ long x[KK];
+ long buf[QUALITY];
+ long dummy;
+ long started;
+ long *ptr;
+} mp_posit_random_info;
+
+static mp_posit_random_info mp_posit_random_data = {
+ .dummy = -1,
+ .started = -1,
+ .ptr = &mp_posit_random_data.dummy
+};
+
+/* the following routines are from exercise 3.6--15 */
+/* after calling |mp_aux_ran_start|, get new randoms by, e.g., |x=mp_aux_ran_arr_next()| */
+
+static void mp_posit_aux_ran_array(long aa[], int n)
+{
+ int i, j;
+ for (j = 0; j < KK; j++) {
+ aa[j] = mp_posit_random_data.x[j];
+ }
+ for (; j < n; j++) {
+ aa[j] = mod_diff(aa[j - KK], aa[j - LL]);
+ }
+ for (i = 0; i < LL; i++, j++) {
+ mp_posit_random_data.x[i] = mod_diff(aa[j - KK], aa[j - LL]);
+ }
+ for (; i < KK; i++, j++) {
+ mp_posit_random_data.x[i] = mod_diff(aa[j - KK], mp_posit_random_data.x[i - LL]);
+ }
+}
+
+/* Do this before using |mp_aux_ran_array|, long seed selector for different streams. */
+
+static void mp_posit_aux_ran_start(long seed)
+{
+ int t, j;
+ long x[KK + KK - 1]; /* the preparation buffer */
+ long ss = (seed+2) & (MM - 2);
+ for (j = 0; j < KK; j++) {
+ /* bootstrap the buffer */
+ x[j] = ss;
+ /* cyclic shift 29 bits */
+ ss <<= 1;
+ if (ss >= MM) {
+ ss -= MM - 2;
+ }
+ }
+ /* make x[1] (and only x[1]) odd */
+ x[1]++;
+ for (ss = seed & (MM - 1), t = TT - 1; t;) {
+ for (j = KK - 1; j > 0; j--) {
+ /* "square" */
+ x[j + j] = x[j];
+ x[j + j - 1] = 0;
+ }
+ for (j = KK + KK - 2; j >= KK; j--) {
+ x[j - (KK -LL)] = mod_diff(x[j - (KK - LL)], x[j]);
+ x[j - KK] = mod_diff(x[j - KK], x[j]);
+ }
+ if (is_odd(ss)) {
+ /* "multiply by z" */
+ for (j = KK; j>0; j--) {
+ x[j] = x[j-1];
+ }
+ x[0] = x[KK];
+ /* shift the buffer cyclically */
+ x[LL] = mod_diff(x[LL], x[KK]);
+ }
+ if (ss) {
+ ss >>= 1;
+ } else {
+ t--;
+ }
+ }
+ for (j = 0; j < LL; j++) {
+ mp_posit_random_data.x[j + KK - LL] = x[j];
+ }
+ for (;j < KK; j++) {
+ mp_posit_random_data.x[j - LL] = x[j];
+ }
+ for (j = 0; j < 10; j++) {
+ /* warm things up */
+ mp_posit_aux_ran_array(x, KK + KK - 1);
+ }
+ mp_posit_random_data.ptr = &mp_posit_random_data.started;
+}
+
+static long mp_posit_aux_ran_arr_cycle(void)
+{
+ if (mp_posit_random_data.ptr == &mp_posit_random_data.dummy) {
+ /* the user forgot to initialize */
+ mp_posit_aux_ran_start(314159L);
+ }
+ mp_posit_aux_ran_array(mp_posit_random_data.buf, QUALITY);
+ mp_posit_random_data.buf[KK] = -1;
+ mp_posit_random_data.ptr = mp_posit_random_data.buf + 1;
+ return mp_posit_random_data.buf[0];
+}
+
+void mp_init_randoms (MP mp, int seed)
+{
+ int k = 1;
+ int j = abs(seed);
+ int f = (int) mp_fraction_multiplier; /* avoid warnings */
+ while (j >= f) {
+ j = j/2;
+ }
+ for (int i = 0; i <= 54; i++) {
+ int jj = k;
+ k = j - k;
+ j = jj;
+ if (k < 0) {
+ k += f;
+ }
+ mp->randoms[(i * 21) % 55].data.pval = integer_to_posit(j);
+ }
+ mp_new_randoms(mp);
+ mp_new_randoms(mp);
+ mp_new_randoms(mp);
+ /* warm up the array */
+ mp_posit_aux_ran_start((unsigned long) seed);
+}
+
+void mp_number_modulo(mp_number *a, mp_number *b)
+{
+ a->data.pval = posit_mul(posit_modf(posit_div(a->data.pval, b->data.pval)), b->data.pval);
+}
+
+static void mp_next_unif_random (MP mp, mp_number *ret)
+{
+ unsigned long int op = (unsigned) (*mp_posit_random_data.ptr >=0 ? *mp_posit_random_data.ptr++: mp_posit_aux_ran_arr_cycle());
+ double a = op / (MM * 1.0);
+ (void) mp;
+ ret->data.pval = double_to_posit(a);
+}
+
+static void mp_next_random (MP mp, mp_number *ret)
+{
+ if ( mp->j_random==0) {
+ mp_new_randoms(mp);
+ } else {
+ mp->j_random = mp->j_random-1;
+ }
+ mp_number_clone(ret, &(mp->randoms[mp->j_random]));
+}
+
+static void mp_posit_m_unif_rand (MP mp, mp_number *ret, mp_number *x_orig)
+{
+ mp_number x, abs_x, u, y;
+ mp_allocate_number(mp, &y, mp_fraction_type);
+ mp_allocate_clone(mp, &x, mp_scaled_type, x_orig);
+ mp_allocate_abs(mp, &abs_x, mp_scaled_type, &x);
+ mp_allocate_number(mp, &u, mp_scaled_type);
+ mp_next_unif_random(mp, &u);
+ y.data.pval = posit_mul(abs_x.data.pval, u.data.pval);
+ mp_free_number(mp, &u);
+ if (mp_number_equal(&y, &abs_x)) {
+ mp_number_clone(ret, &((math_data *)mp->math)->md_zero_t);
+ } else if (mp_number_greater(&x, &((math_data *)mp->math)->md_zero_t)) {
+ mp_number_clone(ret, &y);
+ } else {
+ mp_number_negated_clone(ret, &y);
+ }
+ mp_free_number(mp, &abs_x);
+ mp_free_number(mp, &x);
+ mp_free_number(mp, &y);
+}
+
+static void mp_posit_m_norm_rand (MP mp, mp_number *ret)
+{
+ mp_number abs_x, u, r, la, xa;
+ mp_allocate_number(mp, &la, mp_scaled_type);
+ mp_allocate_number(mp, &xa, mp_scaled_type);
+ mp_allocate_number(mp, &abs_x, mp_scaled_type);
+ mp_allocate_number(mp, &u, mp_scaled_type);
+ mp_allocate_number(mp, &r, mp_scaled_type);
+ do {
+ do {
+ mp_number v;
+ mp_allocate_number(mp, &v, mp_scaled_type);
+ mp_next_random(mp, &v);
+ mp_number_subtract(&v, &((math_data *)mp->math)->md_fraction_half_t);
+ mp_posit_number_take_fraction(mp, &xa, &((math_data *)mp->math)->md_sqrt_8_e_k, &v);
+ mp_free_number(mp, &v);
+ mp_next_random(mp, &u);
+ mp_number_clone(&abs_x, &xa);
+ mp_posit_abs(&abs_x);
+ } while (! mp_number_less(&abs_x, &u));
+ mp_posit_number_make_fraction(mp, &r, &xa, &u);
+ mp_number_clone(&xa, &r);
+ mp_posit_m_log(mp, &la, &u);
+ mp_set_posit_from_subtraction(&la, &((math_data *)mp->math)->md_twelve_ln_2_k, &la);
+ } while (mp_posit_ab_vs_cd(&((math_data *)mp->math)->md_one_k, &la, &xa, &xa) < 0);
+ mp_number_clone(ret, &xa);
+ mp_free_number(mp, &r);
+ mp_free_number(mp, &abs_x);
+ mp_free_number(mp, &la);
+ mp_free_number(mp, &xa);
+ mp_free_number(mp, &u);
+}
+
+@ @<Reduce to the case that |a...@>=
+if (posit_lt(a, mp_posit_data.zero)) {
+ a = posit_neg(a);
+ b = posit_neg(b);
+}
+if (posit_lt(c, mp_posit_data.zero)) {
+ c = posit_neg(c);
+ d = posit_neg(d);
+}
+if ((posit_le(d, mp_posit_data.zero)) {
+ if ((posit_ge(b, mp_posit_data.zero)) {
+ if ((posit_eq_zero(a) || posit_eq_zero(b) && (posit_eq_zero(c) || posit_eq_zero(d))) {
+ ret->data.pval = mp_posit_data.zero;
+ } else {
+ ret->data.pval = mp_posit_data.one;
+ }
+ goto RETURN;
+ } if (posit_eq_zero(d)) {
+ ret->data.pval = posit_eq_zero(a) ? mp_posit_data.zero : mp_posit_data.minusone;
+ goto RETURN;
+ } else
+ q = a;
+ a = c;
+ c = q;
+ q = -b;
+ b = -d;
+ d = q;
+ }
+} else if (posit_le(b, mp_posit_data.zero) {
+ if (posit_lt(b, mp_posit_data.zero) && posit_gt(a, mp_posit_data.zero)) {
+ ret->data.pval = mp_posit_data.minusone;
+ return;
+ } else
+ ret->data.pval = posit_eq_zero(c) ? mp_posit_data.zero : mp_posit_data.minusone;
+ goto RETURN;
+ }
+}