• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

form-dev / form / 18873894527

28 Oct 2025 11:54AM UTC coverage: 57.024% (+0.01%) from 57.013%
18873894527

push

github

cbmarini
feat: add StrictRounding statement to round floats and to trim excess GMP precision
- The user can specify a precision (in bits or digits) for the rounding. If no number is given, the default precision is used.
- Ensures that extra internal GMP precision (used for tracking accuracy) is cut off and properly rounded
- Internally the mpf_get_str and mpf_set_str are used. This means we could also implement base 2 rounding.
- refactor: changed AO.floatsize such that it can now also hold floats in base 2.
- This resolves #698
- added a test and  documentation for strictrounding.

52 of 61 new or added lines in 3 files covered. (85.25%)

11 existing lines in 1 file now uncovered.

46998 of 82418 relevant lines covered (57.02%)

5629878.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.52
/sources/float.c
1
/** @file float.c
2
 * 
3
 *  This file contains numerical routines that deal with floating point numbers.
4
 *        We use the GMP for arbitrary precision floating point arithmetic.
5
 *        The functions of the type sin, cos, ln, sqrt etc are handled by the
6
 *        mpfr library. The reason that for MZV's and the general notation we use
7
 *        the GMP (mpf_) is because the contents of the structs have been frozen
8
 *        and can be used for storage in a Form function float_. With mpfr_ this
9
 *        is not safely possible. All mpfr_ related code is in the file evaluate.c.
10
 */
11
/* #[ License : */
12
/*
13
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
14
 *   When using this file you are requested to refer to the publication
15
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
16
 *   This is considered a matter of courtesy as the development was paid
17
 *   for by FOM the Dutch physics granting agency and we would like to
18
 *   be able to track its scientific use to convince FOM of its value
19
 *   for the community.
20
 *
21
 *   This file is part of FORM.
22
 *
23
 *   FORM is free software: you can redistribute it and/or modify it under the
24
 *   terms of the GNU General Public License as published by the Free Software
25
 *   Foundation, either version 3 of the License, or (at your option) any later
26
 *   version.
27
 *
28
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
29
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
31
 *   details.
32
 *
33
 *   You should have received a copy of the GNU General Public License along
34
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
35
 */
36
/* #] License : */ 
37
/*
38
          #[ Includes : float.c
39
*/
40

41
#include "form3.h"
42
#include <math.h>
43
#include <gmp.h>
44

45
#define WITHCUTOFF
46

47
#define GMPSPREAD (GMP_LIMB_BITS/BITSINWORD)
48

49
void Form_mpf_init(mpf_t t);
50
void Form_mpf_clear(mpf_t t);
51
void Form_mpf_set_prec_raw(mpf_t t,ULONG newprec);
52
void FormtoZ(mpz_t z,UWORD *a,WORD na);
53
void ZtoForm(UWORD *a,WORD *na,mpz_t z);
54
long FloatToInteger(UWORD *out, mpf_t floatin, long *bitsused);
55
void IntegerToFloat(mpf_t result, UWORD *formlong, int longsize);
56
int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin);
57
int AddFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
58
int MulFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
59
int DivFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
60
int AddRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
61
int MulRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
62
void SimpleDelta(mpf_t sum, int m);
63
void SimpleDeltaC(mpf_t sum, int m);
64
void SingleTable(mpf_t *tabl, int N, int m, int pow);
65
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow);
66
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow);
67
void deltaMZV(mpf_t, WORD *, int);
68
void deltaEuler(mpf_t, WORD *, int);
69
void deltaEulerC(mpf_t, WORD *, int);
70
void CalculateMZVhalf(mpf_t, WORD *, int);
71
void CalculateMZV(mpf_t, WORD *, int);
72
void CalculateEuler(mpf_t, WORD *, int);
73
int ExpandMZV(WORD *term, WORD level);
74
int ExpandEuler(WORD *term, WORD level);
75
int PackFloat(WORD *,mpf_t);
76
int UnpackFloat(mpf_t, WORD *);
77
void RatToFloat(mpf_t result, UWORD *formrat, int ratsize);
78
 
79
/*
80
          #] Includes : 
81
          #[ Some GMP float info :
82

83
        From gmp.h:
84

85
        typedef struct
86
        {
87
          int _mp_prec;     Max precision, in number of `mp_limb_t's.
88
                        Set by mpf_init and modified by
89
                        mpf_set_prec.  The area pointed to by the
90
                        _mp_d field contains `prec' + 1 limbs.
91
          int _mp_size;     abs(_mp_size) is the number of limbs the
92
                        last field points to.  If _mp_size is
93
                        negative this is a negative number.
94
          mp_exp_t _mp_exp; Exponent, in the base of `mp_limb_t'.
95
          mp_limb_t *_mp_d; Pointer to the limbs.
96
        } __mpf_struct;
97

98
        typedef __mpf_struct mpf_t[1];
99

100
        Currently:
101
                sizeof(int) = 4
102
                sizeof(mpf_t) = 24
103
                sizeof(mp_limb_t) = 8,
104
                sizeof(mp_exp_t) = 8,
105
                sizeof a pointer is 8.
106
        If any of this changes in the future we would have to change the
107
        PackFloat and UnpackFloat routines.
108

109
        Our float_ function is packed with the 4 arguments:
110
                -SNUMBER _mp_prec
111
                -SNUMBER _mp_size
112
                exponent which can be -SNUMBER or a regular term
113
                the limbs as n/1 in regular term format, or just an -SNUMBER.
114
        During normalization the sign is taken away from the second argument
115
        and put as the sign of the complete term. This is easier for the
116
        WriteInnerTerm routine in sch.c
117

118
        Wildcarding of functions excludes matches with float_
119
        Float_ always ends up inside the bracket, just like poly(rat)fun.
120

121
        From mpfr.h
122

123
        The formats here are different. This has, among others, to do with
124
        the rounding. The result is that we need different aux variables
125
        when working with mpfr and we need a different conversion routine
126
        to float. It also means that we need to treat the mzv_ etc functions
127
        completely separately. For now we try to develop that in the file
128
        Evaluate.c. At a later stage we may merge the two files.
129
        Originally we had the sqrt in float.c but it seems better to put
130
        it in Evaluate.c
131

132
          #] Some GMP float info : 
133
          #[ Low Level :
134

135
                In the low level routines we interact directly with the content
136
                of the GMP structs. This can be done safely, because their
137
                layout is documented. We pay particular attention to the init
138
                and clear routines, because they involve malloc/free calls.
139

140
                 #[ Explanations :
141

142
        We need a number of facilities inside Form to deal with floating point
143
        numbers, taking into account that they are only meant for sporadic use.
144
        1: We need a special function float_ who's arguments contain a limb
145
           representation of the mpf_t of the gmp.
146
        2: Some functions may return a floating point number. This is then in
147
           the form of an occurrence of the function float_.
148
        3: We need a print routine to print this float_.
149
        4: We need routines for conversions:
150
                a: (long) int to float.
151
                b: rat to float.
152
                c: float to rat (if possible)
153
                d: float to integer (with rounding toward zero).
154
        5: We need calculational operations for add, sub, mul, div, exp.
155
        6: We need service routines to pack and unpack the function float_.
156
        7: The coefficient should be pulled inside float_.
157
        8: Float_ cannot occur inside PolyRatFun.
158
        9: We need to be able to treat float_ as the coefficient during sorting.
159
        10: For now, we need the functions mzvf_ and eulerf_ for the evaluation
160
                of mzv's and euler sums.
161
        11: We need a setting for the default precision.
162
        12: We need a special flag for the dirty field of arguments to avoid
163
                the normalization of the argument with the limbs.
164
                Alternatively, the float_ should be not a regular function, but
165
                get a status < FUNCTION. Just like SNUMBER, LNUMBER etc.
166

167
        Note that we can keep this thread-safe. The only routine that is not
168
        thread-safe is the print routine, but that is in accordance with all
169
        other print routines in Form. When called from MesPrint it needs to
170
        be protected by a lock, as is done standard inside Form.
171

172
                 #] Explanations : 
173
                 #[ Form_mpf_init :
174
*/
175

176
void Form_mpf_init(mpf_t t)
×
177
{
178
        mp_limb_t *d;
×
179
        int i, prec;
×
180
        if ( t->_mp_d ) { M_free(t->_mp_d,"Form_mpf_init"); t->_mp_d = 0; }
×
181
        prec = (AC.DefaultPrecision + 8*sizeof(mp_limb_t)-1)/(8*sizeof(mp_limb_t)) + 1;
×
182
        t->_mp_prec = prec;
×
183
        t->_mp_size = 0;
×
184
        t->_mp_exp = 0;
×
185
        d = (mp_limb_t *)Malloc1(prec*sizeof(mp_limb_t),"Form_mpf_init");
×
186
        if ( d == 0 ) {
×
187
                MesPrint("Fatal error in Malloc1 call in Form_mpf_init. Trying to allocate %ld bytes.",
×
188
                        prec*sizeof(mp_limb_t));
189
                Terminate(-1);
×
190
        }
191
        t->_mp_d = d;
×
192
        for ( i = 0; i < prec; i++ ) d[i] = 0;
×
193
}
×
194

195
/*
196
                 #] Form_mpf_init : 
197
                 #[ Form_mpf_clear :
198
*/
199

200
void Form_mpf_clear(mpf_t t)
×
201
{
202
        if ( t->_mp_d ) { M_free(t->_mp_d,"Form_mpf_init"); t->_mp_d = 0; }
×
203
        t->_mp_prec = 0;
×
204
        t->_mp_size = 0;
×
205
        t->_mp_exp = 0;
×
206
}
×
207

208
/*
209
                 #] Form_mpf_clear : 
210
                 #[ Form_mpf_empty :
211
*/
212

213
void Form_mpf_empty(mpf_t t)
18✔
214
{
215
        int i;
18✔
216
        for ( i = 0; i < t->_mp_prec; i++ ) t->_mp_d[i] = 0;
198✔
217
        t->_mp_size = 0;
18✔
218
        t->_mp_exp = 0;
18✔
219
}
18✔
220

221
/*
222
                 #] Form_mpf_empty : 
223
                 #[ Form_mpf_set_prec_raw :
224
*/
225

226
void Form_mpf_set_prec_raw(mpf_t t,ULONG newprec)
×
227
{
228
        ULONG newpr = (newprec + 8*sizeof(mp_limb_t)-1)/(8*sizeof(mp_limb_t)) + 1;
×
229
        if ( newpr <= (ULONG)(t->_mp_prec) ) {
×
230
                int i, used = ABS(t->_mp_size) ;
×
231
                if ( newpr > (ULONG)used ) {
×
232
                        for ( i = used; i < (int)newpr; i++ ) t->_mp_d[i] = 0;
×
233
                }
234
                if ( t->_mp_size < 0 ) newpr = -newpr;
×
235
                t->_mp_size = newpr;
×
236
        }
237
        else {
238
/*
239
                We can choose here between "forget about it" or making a new malloc.
240
                If the program is well designed, we should never get here though.
241
                For now we choose the "forget it" option.
242
*/
243
                MesPrint("Trying too big a precision %ld in Form_mpf_set_prec_raw.",newprec);
×
244
                MesPrint("Old maximal precision is %ld.",
×
245
                        (size_t)(t->_mp_prec-1)*sizeof(mp_limb_t)*8);
×
246
                Terminate(-1);
×
247
        }
248
}
×
249

250
/*
251
                 #] Form_mpf_set_prec_raw : 
252
                 #[ PackFloat :
253

254
        Puts an object of type mpf_t inside a function float_
255
        float_(prec, nlimbs, exp, limbs);
256
        Complication: the limbs and the exponent are long's. That means
257
        two times the size of a Form (U)WORD.
258
        To save space we could split the limbs in two because Form stores
259
        coefficients as rationals with equal space for numerator and denominator.
260
        Hence for each limb we could put the most significant UWORD in the 
261
        numerator and the least significant limb in the denominator.
262
        This gives a problem with the compilation and subsequent potential
263
        normalization of the 'fraction'. Hence for now we take the wasteful
264
        approach. At a later stage we can try to veto normalization of FLOATFUN.
265
        Caution: gmp/fmp is little endian and Form is big endian.
266

267
        Zero is represented by zero limbs (and zero exponent).
268
*/
269

270
int PackFloat(WORD *fun,mpf_t infloat)
2,922✔
271
{
272
        WORD *t, nlimbs, num, nnum;
2,922✔
273
        mp_limb_t *d = infloat->_mp_d; /* Pointer to the limbs.  */
2,922✔
274
        int i;
2,922✔
275
        long e = infloat->_mp_exp;
2,922✔
276
        
277
        t = fun;
2,922✔
278
        *t++ = FLOATFUN;
2,922✔
279
        t++;
2,922✔
280
        FILLFUN(t);
2,922✔
281
        *t++ = -SNUMBER;
2,922✔
282
        *t++ = infloat->_mp_prec;
2,922✔
283
        *t++ = -SNUMBER;
2,922✔
284
        *t++ = infloat->_mp_size;
2,922✔
285
/*
286
        Now the exponent which is a signed long
287
*/
288
        if ( e < 0 ) {
2,922✔
289
                e = -e;
×
290
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
×
291
                        *t++ = -SNUMBER; *t++ = -e;
×
292
                }
293
                else {
294
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
×
295
                        *t++ = 6;
×
296
                        *t++ = (UWORD)e;
×
297
                        *t++ = (UWORD)(e >> BITSINWORD);
×
298
                        *t++ = 1; *t++ = 0; *t++ = -5;
×
299
                }
300
        }
301
        else {
302
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
2,922✔
303
                        *t++ = -SNUMBER; *t++ = e;
2,922✔
304
                }
305
                else {
306
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
×
307
                        *t++ = 6;
×
308
                        *t++ = (UWORD)e;
×
309
                        *t++ = (UWORD)(e >> BITSINWORD);
×
310
                        *t++ = 1; *t++ = 0; *t++ = 5;
×
311
                }
312
        }
313
/*
314
        and now the limbs. Note that the number of active limbs could be less
315
        than prec+1 in which case we copy the smaller number.
316
*/
317
        nlimbs = infloat->_mp_size < 0 ? -infloat->_mp_size: infloat->_mp_size;
2,922✔
318
        if ( nlimbs == 0 ) {
2,922✔
319
        }
320
        else if ( nlimbs == 1 && (ULONG)(*d) < ((ULONG)1)<<(BITSINWORD-1) ) {
2,922✔
321
                *t++ = -SNUMBER;
18✔
322
                *t++ = (UWORD)(*d);
18✔
323
        }
324
        else {
325
          if ( d[nlimbs-1] < ((ULONG)1)<<BITSINWORD ) {
2,904✔
326
                num = 2*nlimbs-1; /* number of UWORDS needed */
1,296✔
327
          }
328
          else {
329
                num = 2*nlimbs;   /* number of UWORDS needed */
1,608✔
330
          }
331
          nnum = num;
2,904✔
332
          *t++ = 2*num+2+ARGHEAD;
2,904✔
333
          *t++ = 0;
2,904✔
334
          FILLARG(t);
2,904✔
335
          *t++ = 2*num+2;
2,904✔
336
          while ( num > 1 ) {
13,074✔
337
                *t++ = (UWORD)(*d); *t++ = (UWORD)(((ULONG)(*d))>>BITSINWORD); d++;
10,170✔
338
                num -= 2;
10,170✔
339
          }
340
          if ( num == 1 ) { *t++ = (UWORD)(*d); }
2,904✔
341
          *t++ = 1;
2,904✔
342
          for ( i = 1; i < nnum; i++ ) *t++ = 0;
21,636✔
343
          *t++ = 2*nnum+1; /* the sign is hidden in infloat->_mp_size */
2,904✔
344
        }
345
        fun[1] = t-fun;
2,922✔
346
        return(fun[1]);
2,922✔
347
}
348

349
/*
350
                 #] PackFloat : 
351
                 #[ UnpackFloat :
352

353
        Takes the arguments of a function float_ and puts it inside an mpf_t.
354
        For notation see commentary for PutInFloat.
355

356
        We should make a new allocation for the limbs if the precision exceeds
357
        the present precision of outfloat, or when outfloat has not been
358
        initialized yet.
359

360
        The return value is -1 if the contents of the FLOATFUN cannot be converted.
361
        Otherwise the return value is the number of limbs.
362
*/
363

364
int UnpackFloat(mpf_t outfloat,WORD *fun)
3,936✔
365
{
366
        UWORD *t;
3,936✔
367
        WORD *f;
3,936✔
368
        int num, i;
3,936✔
369
        mp_limb_t *d;
3,936✔
370
/*
371
        Very first step: check whether we can use float_:
372
*/
373
        GETIDENTITY
2,624✔
374
        if ( AT.aux_ == 0 ) {
3,936✔
375
                MesPrint("Illegal attempt at using a float_ function without proper startup.");
×
376
                MesPrint("Please use %#StartFloat <options> first.");
×
377
                Terminate(-1);
×
378
        }
379
/*
380
        Check first the number and types of the arguments
381
        There should be 4. -SNUMBER,-SNUMBER,-SNUMBER or a long number.
382
        + the limbs, either -SNUMBER or Long number in the form of a Form rational.
383
*/
384
        if ( TestFloat(fun) == 0 ) goto Incorrect;
3,936✔
385
        f = fun + FUNHEAD + 2;
3,936✔
386
        if ( ABS(f[1]) > f[-1]+1 ) goto Incorrect;
3,936✔
387
        if ( f[1] > outfloat->_mp_prec+1
3,936✔
388
          || outfloat->_mp_d == 0 ) {
3,936✔
389
                /*
390
                        We need to make a new allocation.
391
                        Unfortunately we cannot use Malloc1 because that is not
392
                        recognised by gmp and hence we cannot clear with mpf_clear.
393
                        Maybe we can do something about it by making our own
394
                        mpf_init and mpf_clear?
395
                */                     
396
                if ( outfloat->_mp_d != 0 ) free(outfloat->_mp_d);
×
397
                outfloat->_mp_d = (mp_limb_t *)malloc((f[1]+1)*sizeof(mp_limb_t));
×
398
        }
399
        num = f[1];
3,936✔
400
        outfloat->_mp_size = num;
3,936✔
401
        if ( num < 0 ) { num = -num; }
3,936✔
402
        f += 2;
3,936✔
403
        if ( *f == -SNUMBER ) {
3,936✔
404
                outfloat->_mp_exp = (mp_exp_t)(f[1]);
3,936✔
405
                f += 2;
3,936✔
406
        }
407
        else {
408
                f += ARGHEAD+6;
×
409
                if ( f[-1] == -5 ) {
×
410
                        outfloat->_mp_exp =
×
411
                                -(mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+f[-5]);
×
412
                }
413
                else if ( f[-1] == 5 ) {
×
414
                        outfloat->_mp_exp =
×
415
                                 (mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+f[-5]);
×
416
                }
417
        }
418
/*
419
        And now the limbs if needed
420
*/
421
        d = outfloat->_mp_d;
3,936✔
422
        if ( outfloat->_mp_size == 0 ) {
3,936✔
423
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
×
424
                return(0);
425
        }
426
        else if ( *f == -SNUMBER ) {
3,936✔
427
                *d++ = (mp_limb_t)f[1];
54✔
428
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
162✔
429
                return(0);
430
        }
431
        num = (*f-ARGHEAD-2)/2; /* 2*number of limbs in the argument */
3,882✔
432
        t = (UWORD *)(f+ARGHEAD+1);
3,882✔
433
        while ( num > 1 ) {
15,972✔
434
                *d++ = (mp_limb_t)((((ULONG)(t[1]))<<BITSINWORD)+t[0]);
12,090✔
435
                t += 2; num -= 2;
12,090✔
436
        }
437
        if ( num == 1 ) *d++ = (mp_limb_t)((UWORD)(*t));
3,882✔
438
        for ( i = d-outfloat->_mp_d; i <= outfloat->_mp_prec; i++ ) *d++ = 0;
6,564✔
439
        return(0);
440
Incorrect:
3,936✔
441
        return(-1);
442
}
443

444
/*
445
                 #] UnpackFloat : 
446
                 #[ TestFloat :
447

448
                Tells whether the function (with its arguments) is a legal float_.
449
                We assume, as in the whole float library that one limb is 2 WORDs.
450
*/
451

452
int TestFloat(WORD *fun)
9,138✔
453
{
454
        WORD *fstop, *f, num, nnum, i;
9,138✔
455
        fstop = fun+fun[1];
9,138✔
456
        f = fun + FUNHEAD;
9,138✔
457
        num = 0;
9,138✔
458
/*
459
        Count arguments
460
*/
461
        while ( f < fstop ) { num++; NEXTARG(f); }
45,690✔
462
        if ( num != 4 ) return(0);
9,138✔
463
        f = fun + FUNHEAD;
9,138✔
464
        if ( *f != -SNUMBER ) return(0);
9,138✔
465
        if ( f[1] < 0 ) return(0);
9,138✔
466
        f += 2;
9,138✔
467
        if ( *f != -SNUMBER ) return(0);
9,138✔
468
        num = ABS(f[1]); /* number of limbs */
9,138✔
469
        f += 2;
9,138✔
470
        if ( *f == -SNUMBER ) { f += 2; }
9,138✔
471
        else {
472
                if ( *f != ARGHEAD+6 ) return(0);
×
473
                if ( ABS(f[ARGHEAD+5]) != 5 ) return(0);
×
474
                if ( f[ARGHEAD+3] != 1 ) return(0);
×
475
                if ( f[ARGHEAD+4] != 0 ) return(0);
×
476
                f += *f;
×
477
        }
478
        if ( num == 0 ) return(1);
9,138✔
479
        if ( *f == -SNUMBER ) { if ( num != 1 ) return(0); }
9,138✔
480
        else {
481
                nnum = (ABS(f[*f-1])-1)/2;
9,024✔
482
                if ( ( *f != 4*num+2+ARGHEAD ) && ( *f != 4*num+ARGHEAD ) ) return(0);
9,024✔
483
                if ( ( nnum != 2*num ) && ( nnum != 2*num-1 ) ) return(0);
9,024✔
484
                f += ARGHEAD+nnum+1;
9,024✔
485
                if ( f[0] != 1 ) return(0);
9,024✔
486
                for ( i = 1; i < nnum; i++ ) {
62,268✔
487
                        if ( f[i] != 0 ) return(0);
53,244✔
488
                }
489
        }
490
        return(1);
491
}
492

493
/*
494
                 #] TestFloat : 
495
                 #[ FormtoZ :
496

497
                Converts a Form long integer to a GMP long integer.
498

499
                typedef struct
500
                {
501
                  int _mp_alloc;   Number of *limbs* allocated and pointed
502
                                   to by the _mp_d field.
503
                  int _mp_size;    abs(_mp_size) is the number of limbs the
504
                                   last field points to.  If _mp_size is
505
                                   negative this is a negative number.
506
                  mp_limb_t *_mp_d;Pointer to the limbs.
507
                } __mpz_struct;
508
                typedef __mpz_struct mpz_t[1];
509
*/
510

511
void FormtoZ(mpz_t z,UWORD *a,WORD na)
888✔
512
{
513
        int nlimbs, sgn = 1;
888✔
514
        mp_limb_t *d;
888✔
515
        UWORD *b = a;
888✔
516
        WORD nb = na;
888✔
517

518
        if ( nb == 0 ) {
888✔
519
                z->_mp_size = 0;
×
520
                z->_mp_d[0] = 0;
×
521
                return;
×
522
        }
523
        if ( nb < 0 ) { sgn = -1; nb = -nb; }
888✔
524
        nlimbs = (nb+1)/2;
888✔
525
        if ( mpz_cmp_si(z,0L) <= 1 ) {
888✔
526
                mpz_set_ui(z,10000000);
888✔
527
        }
528
        if ( z->_mp_alloc <= nlimbs ) {
888✔
529
                mpz_t zz;
888✔
530
                mpz_init(zz);
888✔
531
                while ( z->_mp_alloc <= nlimbs ) {
2,712✔
532
                        mpz_mul(zz,z,z);
1,824✔
533
                        mpz_set(z,zz);
1,824✔
534
                }
535
                mpz_clear(zz);
888✔
536
        }
537
        z->_mp_size = sgn*nlimbs;
888✔
538
        d = z->_mp_d;
888✔
539
        while ( nb > 1 ) {
1,368✔
540
                *d++ = (((mp_limb_t)(b[1]))<<BITSINWORD)+(mp_limb_t)(b[0]);
480✔
541
                b += 2; nb -= 2;
480✔
542
        }
543
        if ( nb == 1 ) { *d = (mp_limb_t)(*b); }
888✔
544
}
545

546
/*
547
                 #] FormtoZ : 
548
                 #[ ZtoForm :
549

550
                Converts a GMP long integer to a Form long integer.
551
                Mainly an exercise of going from little endian ULONGs.
552
                to big endian UWORDs
553
*/
554

555
void ZtoForm(UWORD *a,WORD *na,mpz_t z)
66✔
556
{
557
        mp_limb_t *d = z->_mp_d;
66✔
558
        int nlimbs = ABS(z->_mp_size), i;
66✔
559
        UWORD j;
66✔
560
        if ( nlimbs == 0 ) { *na = 0; return; }
66✔
561
        *na = 0;
66✔
562
        for ( i = 0; i < nlimbs-1; i++ ) {
108✔
563
                *a++ = (UWORD)(*d);
42✔
564
                *a++ = (UWORD)((*d++)>>BITSINWORD);
42✔
565
                *na += 2;
42✔
566
        }
567
        *na += 1;
66✔
568
        *a++ = (UWORD)(*d);
66✔
569
        j = (UWORD)((*d)>>BITSINWORD);
66✔
570
        if ( j != 0 ) { *a = j; *na += 1; }
66✔
571
        if ( z->_mp_size < 0 ) *na = -*na;
66✔
572
}
573

574
/*
575
                 #] ZtoForm : 
576
                 #[ FloatToInteger :
577

578
                Converts a GMP float to a long Form integer.
579
*/
580

581
long FloatToInteger(UWORD *out, mpf_t floatin, long *bitsused)
66✔
582
{
583
        mpz_t z;
66✔
584
        WORD nout, nx;
66✔
585
        UWORD x;
66✔
586
        mpz_init(z);
66✔
587
        mpz_set_f(z,floatin);
66✔
588
        ZtoForm(out,&nout,z);
66✔
589
        mpz_clear(z);
66✔
590
        x = out[0]; nx = 0;
66✔
591
        while ( x ) { nx++; x >>= 1; }
462✔
592
        *bitsused = (nout-1)*BITSINWORD + nx;
66✔
593
        return(nout);
66✔
594
}
595

596
/*
597
                 #] FloatToInteger : 
598
                 #[ IntegerToFloat :
599

600
                Converts a Form long integer to a gmp float of default size.
601
                We assume that sizeof(unsigned long int) = 2*sizeof(UWORD).
602
*/
603

604
void IntegerToFloat(mpf_t result, UWORD *formlong, int longsize)
672✔
605
{
606
        mpz_t z;
672✔
607
        mpz_init(z);
672✔
608
        FormtoZ(z,formlong,longsize);
672✔
609
        mpf_set_z(result,z);
672✔
610
        mpz_clear(z);
672✔
611
}
672✔
612

613
/*
614
                 #] IntegerToFloat : 
615
                 #[ RatToFloat :
616

617
                Converts a Form rational to a gmp float of default size.
618
*/
619

620
void RatToFloat(mpf_t result, UWORD *formrat, int ratsize)
336✔
621
{
622
        GETIDENTITY
224✔
623
        int nnum, nden;
336✔
624
        UWORD *num, *den;
336✔
625
        int sgn = 0;
336✔
626
        if ( ratsize < 0 ) { ratsize = -ratsize; sgn = 1; }
336✔
627
        nnum = nden = (ratsize-1)/2;
336✔
628
        num = formrat; den = formrat+nnum;
336✔
629
        while ( num[nnum-1] == 0 ) { nnum--; }
1,164✔
630
        while ( den[nden-1] == 0 ) { nden--; }
354✔
631
        IntegerToFloat(aux2,num,nnum);
336✔
632
        IntegerToFloat(aux3,den,nden);
336✔
633
        mpf_div(result,aux2,aux3);
336✔
634
        if ( sgn > 0 ) mpf_neg(result,result);
336✔
635
}
336✔
636

637
/*
638
                 #] RatToFloat : 
639
                 #[ FloatFunToRat :
640
*/
641

642
WORD FloatFunToRat(PHEAD UWORD *ratout,WORD *in)
×
643
{
644
        WORD oldin = in[0], nratout;
×
645
        in[0] = FLOATFUN;
×
646
        UnpackFloat(aux4,in);
×
647
        FloatToRat(ratout,&nratout,aux4);
×
648
        in[0] = oldin;
×
649
        return(nratout);
×
650
}
651

652
/*
653
                 #] FloatFunToRat : 
654
                 #[ FloatToRat :
655

656
        Converts a gmp float to a Form rational.
657
        The algorithm we use is 'repeated fractions' of the style
658
                n0+1/(n1+1/(n2+1/(n3+.....)))
659
        The moment we get an n that is very large we should have the proper fraction
660
        Main problem: what if the sequence keeps going?
661
                     (there are always rounding errors)
662
        We need a cutoff with an error condition.
663
        Basically the product n0*n1*n2*... is an underlimit on the number of
664
        digits in the answer. We can put a limit on this.
665
        A return value of zero means that everything went fine.
666
*/
667

668
int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin)
6✔
669
{
670
        GETIDENTITY
4✔
671
        WORD *out = AT.WorkPointer;
6✔
672
        WORD s; /* the sign. */
6✔
673
        UWORD *a, *b, *c, *d, *mc;
6✔
674
        WORD na, nb, nc, nd, i;
6✔
675
        int nout;
6✔
676
        LONG oldpWorkPointer = AT.pWorkPointer;
6✔
677
        long bitsused = 0, totalbitsused = 0, totalbits = AC.DefaultPrecision;
6✔
678
        int retval = 0, startnul;
6✔
679
        WantAddPointers(AC.DefaultPrecision);  /* Horrible overkill */
30✔
680
        AT.pWorkSpace[AT.pWorkPointer++] = out;
6✔
681
        a = NumberMalloc("FloatToRat");
6✔
682
        b = NumberMalloc("FloatToRat");
6✔
683

684
        s = mpf_sgn(floatin);
6✔
685
        if ( s < 0 ) mpf_neg(floatin,floatin);
6✔
686

687
        Form_mpf_empty(aux1);
6✔
688
        Form_mpf_empty(aux2);
6✔
689
        Form_mpf_empty(aux3);
6✔
690

691
        mpf_trunc(aux1,floatin);     /* This should now be an integer */
6✔
692
        mpf_sub(aux2,floatin,aux1);  /* and this >= 0 */
6✔
693
        if ( mpf_sgn(aux1) == 0 ) { *out++ = 0; startnul = 1; }
6✔
694
        else {
695
                nout = FloatToInteger((UWORD *)out,aux1,&totalbitsused);
6✔
696
                out += nout;
6✔
697
                startnul = 0;
6✔
698
        }
699
        AT.pWorkSpace[AT.pWorkPointer++] = out;
6✔
700
        if ( mpf_sgn(aux2) ) {
6✔
701
          for(;;) {
114✔
702
                mpf_ui_div(aux3,1,aux2);
60✔
703
                mpf_trunc(aux1,aux3);
60✔
704
                mpf_sub(aux2,aux3,aux1);
60✔
705
                if ( mpf_sgn(aux1) == 0 ) { *out++ = 0; }
60✔
706
                else {
707
                        nout = FloatToInteger((UWORD *)out,aux1,&bitsused);
60✔
708
                        out += nout;
60✔
709
                        totalbitsused += bitsused;
60✔
710
                }
711
                if ( bitsused > (totalbits-totalbitsused)/2 ) { break; }
60✔
712
                if ( mpf_sgn(aux2) == 0 ) {
54✔
713
                        /*if ( startnul == 1 )*/ AT.pWorkSpace[AT.pWorkPointer++] = out;
×
714
                        break;
×
715
                }
716
                AT.pWorkSpace[AT.pWorkPointer++] = out;
54✔
717
          }
718
/*
719
          At this point we have the function with the repeated fraction.
720
          Now we should work out the fraction. Form code would be:
721
                repeat id   dum_(?a,x1?,x2?) = dum_(?a,x1+1/x2);
722
                id        dum_(x?) = x;
723
          We have to work backwards. This is why we made a list of pointers
724
          in AT.pWorkSpace
725

726
          Now we need the long integers a and b.
727
          Note that by construction there should never be a GCD!
728
*/
729
          out = (WORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
6✔
730
          na = 1; a[0] = 1;
6✔
731
          c = (UWORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
6✔
732
          nc = nb = ((UWORD *)out)-c;
6✔
733
          if ( nc > 10 ) {
6✔
734
                mc = c;
×
735
                c = (UWORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
×
736
                nc = nb = ((UWORD *)mc)-c;
×
737
          }
738
          for ( i = 0; i < nb; i++ ) b[i] = c[i];
12✔
739
          mc = c = NumberMalloc("FloatToRat");
6✔
740
          while ( AT.pWorkPointer > oldpWorkPointer ) {
60✔
741
                d = (UWORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
54✔
742
                nd = (UWORD *)(AT.pWorkSpace[AT.pWorkPointer+1])-d; /* This is the x1 in the formula */
54✔
743
                if ( nd == 1 && *d == 0 ) break;
54✔
744
                c = a; a = b; b = c; nc = na; na = nb; nb = nc; /* 1/x2 */
54✔
745
                MulLong(d,nd,a,na,mc,&nc);
54✔
746
                AddLong(mc,nc,b,nb,b,&nb);
54✔
747
          }
748
          NumberFree(mc,"FloatToRat");
6✔
749
          if ( startnul == 0 ) {
6✔
750
                c = a; a = b; b = c; nc = na; na = nb; nb = nc;
6✔
751
          }
752
        }
753
        else {
754
                c = (UWORD *)(AT.pWorkSpace[oldpWorkPointer]);
×
755
                na = (UWORD *)out - c;
×
756
                for ( i = 0; i < na; i++ ) a[i] = c[i];
×
757
                b[0] = 1; nb = 1;
×
758
        }
759
/*
760
        Now we have the fraction in a/b. Create the rational and add the sign.
761
*/
762
        d = ratout;
6✔
763
        if ( na == nb ) {
6✔
764
                *nratout = (2*na+1)*s;
6✔
765
                for ( i = 0; i < na; i++ ) *d++ = a[i];
12✔
766
                for ( i = 0; i < nb; i++ ) *d++ = b[i];
12✔
767
        }
768
        else if ( na < nb ) {
×
769
                *nratout = (2*nb+1)*s;
×
770
                for ( i = 0; i < na; i++ ) *d++ = a[i];
×
771
                for ( ; i < nb; i++ ) *d++ = 0;
×
772
                for ( i = 0; i < nb; i++ ) *d++ = b[i];
×
773
        }
774
        else {
775
                *nratout = (2*na+1)*s;
×
776
                for ( i = 0; i < na; i++ ) *d++ = a[i];
×
777
                for ( i = 0; i < nb; i++ ) *d++ = b[i];
×
778
                for ( ; i < na; i++ ) *d++ = 0;
×
779
        }
780
        *d = (UWORD)(*nratout);
6✔
781
        NumberFree(b,"FloatToRat");
6✔
782
        NumberFree(a,"FloatToRat");
6✔
783
        AT.pWorkPointer = oldpWorkPointer;
6✔
784
/*
785
        Just for check we go back to float
786
*/
787
        if ( s < 0 ) mpf_neg(floatin,floatin);
6✔
788
/*
789
        {
790
                WORD n = *ratout;
791
                RatToFloat(aux1,ratout,n);
792
                mpf_sub(aux2,floatin,aux1);
793
                gmp_printf("Diff is %.*Fe\n",40,aux2);
794
        }
795
*/
796
        return(retval);
6✔
797
}
798

799
/*
800
                 #] FloatToRat : 
801
                 #[ ZeroTable :
802
*/
803
        
804
void ZeroTable(mpf_t *tab, int N)
552✔
805
{
806
        int i, j;
552✔
807
        for ( i = 0; i < N; i++ ) {
43,536✔
808
                for ( j = 0; j < tab[i]->_mp_prec; j++ ) tab[i]->_mp_d[j] = 0;
171,936✔
809
        }
810
}
552✔
811
            
812
/*
813
                 #] ZeroTable : 
814
                 #[ ReadFloat :
815

816
        Used by the compiler. It reads a floating point number and
817
        outputs it at AT.WorkPointer as if it were a float_ function
818
        with its arguments.
819
        The call enters with s[-1] == TFLOAT.
820
*/
821

822
SBYTE *ReadFloat(SBYTE *s)
360✔
823
{
824
        GETIDENTITY
240✔
825
        SBYTE *ss, c;
360✔
826
        ss = s;
360✔
827
        while ( *ss > 0 ) ss++;
1,812✔
828
        c = *ss; *ss = 0;
360✔
829
        gmp_sscanf((char *)s,"%Ff",aux1);
360✔
830
        if ( AT.WorkPointer > AT.WorkTop ) {
360✔
831
                MLOCK(ErrorMessageLock);
×
832
                MesWork();
×
833
                MUNLOCK(ErrorMessageLock);
×
834
                Terminate(-1);
×
835
        }
836
        PackFloat(AT.WorkPointer,aux1);
360✔
837
        *ss = c;
360✔
838
        return(ss);
360✔
839
}
840

841
/*
842
                 #] ReadFloat : 
843
                 #[ CheckFloat :
844

845
        For the tokenizer. Tests whether the input string can be a float.
846
*/
847

848
UBYTE *CheckFloat(UBYTE *ss, int *spec)
13,294,220✔
849
{
850
        GETIDENTITY
8,862,816✔
851
        UBYTE *s = ss;
13,294,220✔
852
        int zero = 1, gotdot = 0;
13,294,220✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
34,944,922✔
854
        *spec = 0;
13,294,220✔
855
        if ( FG.cTable[*s] == 1 ) {
13,294,220✔
856
                while ( *s == '0' ) s++;
14,939,900✔
857
                if ( FG.cTable[*s] == 1 ) {
13,294,208✔
858
                        s++;
11,648,594✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
20,398,052✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
13,294,208✔
863
        }
864
        else if ( *s == '.' ) {
12✔
865
dot:
12✔
866
                gotdot = 1;
360✔
867
                s++;
360✔
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
360✔
869
                while ( *s == '0' ) s++;
600✔
870
                if ( FG.cTable[*s] == 1 ) {
360✔
871
                        s++;
156✔
872
                        while ( FG.cTable[*s] == 1 ) s++;
486✔
873
                        zero = 0;
874
                }
875
        }
876
        else return(ss);
877
/*
878
        Now we have had the mantissa part, which may be zero.
879
        Check for an exponent.
880
*/
881
        if ( *s == 'e' || *s == 'E' ) {
13,294,220✔
882
                s++;
6✔
883
                if ( *s == '-' || *s == '+' ) s++;
6✔
884
                if ( FG.cTable[*s] == 1 ) {
6✔
885
                        s++;
6✔
886
                        while ( FG.cTable[*s] == 1 ) s++;
6✔
887
                }
888
                else { return(ss); }
889
        }
890
        else if ( gotdot == 0 ) return(ss);
13,294,214✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
360✔
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
360✔
896
        return(s);
897
}
898

899
/*
900
                 #] CheckFloat : 
901
          #] Low Level : 
902
          #[ Float Routines :
903
                 #[ SetFloatPrecision :
904

905
                Sets the default precision (in bits) of the floats and allocate
906
                buffer space for an output string.
907
                The buffer is used by PrintFloat (decimal output) and Strictrounding 
908
                (binary or decimal output), so it must accommodate the larger space
909
                requirement:
910
                exponent: up to 12 chars.
911
                mantissa: prec + a little bit extra
912
*/
913

914
int SetFloatPrecision(WORD prec)
378✔
915
{
916
        if ( prec <= 0 ) {
378✔
917
                MesPrint("&Illegal value for number of bits for floating point constants: %d",prec);
×
918
                return(-1);
×
919
        }
920
        else {
921
                AC.DefaultPrecision = prec;
378✔
922
                if ( AO.floatspace != 0 ) M_free(AO.floatspace,"floatspace");
378✔
923
                AO.floatsize = (prec+20)*sizeof(char);
378✔
924
                AO.floatspace = (UBYTE *)Malloc1(AO.floatsize,"floatspace");
378✔
925
                mpf_set_default_prec(prec);
378✔
926
                return(0);
378✔
927
        }
928
}
929

930
/*
931
                 #] SetFloatPrecision : 
932
                 #[ PrintFloat :
933

934
        Print the float_ function with its arguments as a floating point
935
        number with numdigits digits.
936
        If however we use rawfloat as a format option it prints it as a
937
        regular Form function and it should never come here because the
938
        print routines in sch.c should intercept it.
939
        The buffer AO.floatspace is allocated when the precision of the
940
        floats is set in the routine SetFloatPrecision.
941
*/
942

943
int PrintFloat(WORD *fun,int numdigits)
3,198✔
944
{
945
        GETIDENTITY
2,132✔
946
        UBYTE *s1, *s2;
3,198✔
947
        int n = 0;
3,198✔
948
        int prec = (AC.DefaultPrecision-AC.MaxWeight-1)*log10(2.0);
3,198✔
949
        if ( numdigits > prec || numdigits == 0 ) {
3,198✔
950
                numdigits = prec;
2,910✔
951
        }
952
/* 
953
        GMP's gmp_snprintf always prints a non-zero number before the decimal point, so we 
954
        ask for one digit less. 
955
*/
956
        if ( UnpackFloat(aux4,fun) == 0 )
3,198✔
957
                n = gmp_snprintf((char *)(AO.floatspace),AO.floatsize,"%.*Fe",numdigits-1,aux4);
3,198✔
958
        if ( n > 0 ) {
3,198✔
959
                int n1, n2 = n;
3,198✔
960
                s1 = AO.floatspace+n;
3,198✔
961
                while ( s1 > AO.floatspace && s1[-1] != 'e'
15,990✔
962
                 && s1[-1] != 'E' && s1[-1] != '.' ) { s1--; n2--; }
12,792✔
963
                if ( s1 > AO.floatspace && s1[-1] != '.' ) {
3,198✔
964
                        s1--; n2--;
3,198✔
965
                        s2 = s1; n1 = n2;
3,198✔
966
                        while ( s1[-1] == '0' ) { s1--; n1--; }
15,822✔
967
                        if ( s1[-1] == '.' ) { s1++; n1++; }
3,198✔
968
                        n -= (n2-n1);
3,198✔
969
                        while ( n1 < n ) { *s1++ = *s2++; n1++; }
15,990✔
970
                        *s1 = 0;
3,198✔
971
                }
972
                if ( AC.OutputMode == FORTRANMODE ) {
3,198✔
973
                        s1 = AO.floatspace+n;
720✔
974
                        while ( s1 > AO.floatspace && *s1 != 'e' && *s1 != 'E' ) { 
3,600✔
975
                                s1--; 
2,880✔
976
                        }
977
                        if ( ( AO.DoubleFlag & 2 ) == 2 ) { *s1 = 'Q'; } /* Quadruple precision fortran */
720✔
978
                        else if ( ( AO.DoubleFlag & 1 ) == 1 ) { *s1 = 'D'; } /* Double precision fortran */
576✔
979
                        else { *s1 = 'E'; } /* Single precision fortran */
432✔
980
                }
981
                if ( AC.OutputMode == MATHEMATICAMODE ) {
3,198✔
982
                        s1 = AO.floatspace+n;
144✔
983
                        s2 = s1+2; *s2-- = 0;
144✔
984
                        while ( s1 > AO.floatspace && *s1 != 'e' && *s1 != 'E' ) { 
720✔
985
                                *s2-- = *s1--; 
576✔
986
                        }
987
                        *s2-- = '^'; *s2 = '*'; /* Replace 'e' by '^*' */
144✔
988
                        n++;
144✔
989
                }
990
        }
991
        return(n);
3,198✔
992
}
993

994
/*
995
                 #] PrintFloat : 
996
                 #[ AddFloats :
997
*/
998

999
int AddFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
1000
{
1001
        int retval = 0;
×
1002
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
1003
                mpf_add(aux1,aux1,aux2);
×
1004
                PackFloat(fun3,aux1);
×
1005
        }
1006
        else { retval = -1; }
1007
        return(retval);
×
1008
}
1009

1010
/*
1011
                 #] AddFloats : 
1012
                 #[ MulFloats :
1013
*/
1014

1015
int MulFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
1016
{
1017
        int retval = 0;
×
1018
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
1019
                mpf_mul(aux1,aux1,aux2);
×
1020
                PackFloat(fun3,aux1);
×
1021
        }
1022
        else { retval = -1; }
1023
        return(retval);
×
1024
}
1025

1026
/*
1027
                 #] MulFloats : 
1028
                 #[ DivFloats :
1029
*/
1030

1031
int DivFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
1032
{
1033
        int retval = 0;
×
1034
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
1035
                mpf_div(aux1,aux1,aux2);
×
1036
                PackFloat(fun3,aux1);
×
1037
        }
1038
        else { retval = -1; }
1039
        return(retval);
×
1040
}
1041

1042
/*
1043
                 #] DivFloats : 
1044
                 #[ AddRatToFloat :
1045

1046
                Note: this can be optimized, because often the rat is rather simple.
1047
*/
1048

1049
int AddRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat)
×
1050
{
1051
        int retval = 0;
×
1052
        if ( UnpackFloat(aux2,infun) == 0 ) {
×
1053
                RatToFloat(aux1,formrat,nrat);
×
1054
                mpf_add(aux2,aux2,aux1);
×
1055
                PackFloat(outfun,aux2);
×
1056
        }
1057
        else retval = -1;
1058
        return(retval);
×
1059
}
1060

1061
/*
1062
                 #] AddRatToFloat : 
1063
                 #[ MulRatToFloat :
1064

1065
                Note: this can be optimized, because often the rat is rather simple.
1066
*/
1067

1068
int MulRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat)
×
1069
{
1070
        int retval = 0;
×
1071
        if ( UnpackFloat(aux2,infun) == 0 ) {
×
1072
                RatToFloat(aux1,formrat,nrat);
×
1073
                mpf_mul(aux2,aux2,aux1);
×
1074
                PackFloat(outfun,aux2);
×
1075
        }
1076
        else retval = -1;
1077
        return(retval);
×
1078
}
1079

1080
/*
1081
                 #] MulRatToFloat : 
1082
                 #[ SetupMZVTables :
1083
*/
1084

1085
void SetupMZVTables(void)
216✔
1086
{
1087
/*
1088
        Sets up a table of N+1 mpf_t floats with variable precision.
1089
        It assumes that each next element needs one bit less.
1090
        Initializes all of them.
1091
        We take some extra space, to have one limb overflow everywhere.
1092
        Because the depth of the MZV's can get close to the weight
1093
        and each deeper sum goes one higher, we make the tablesize a bit bigger.
1094
        This may not be needed if we fiddle with the sum boundaries.
1095
*/
1096
#ifdef WITHPTHREADS
1097
        int i, Nw, id, totnum;
144✔
1098
        size_t N;
144✔
1099
        mpf_t *a;
144✔
1100
        Nw = AC.DefaultPrecision;
144✔
1101
        N = (size_t)Nw;
144✔
1102
        totnum = AM.totalnumberofthreads;
144✔
1103
    for ( id = 0; id < totnum; id++ ) {
720✔
1104
                if ( AB[id]->T.mpf_tab1 ) {
576✔
1105
                        a = (mpf_t *)AB[id]->T.mpf_tab1;
1106
                        for ( i = 0; i <=Nw; i++ ) {
1107
                                mpf_clear(a[i]);
1108
                        }
1109
                        M_free(AB[id]->T.mpf_tab1,"mpftab1");
1110
                }
1111
                AB[id]->T.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
576✔
1112
                a = (mpf_t *)AB[id]->T.mpf_tab1;
576✔
1113
                for ( i = 0; i <=Nw; i++ ) {
40,496✔
1114
/*
1115
        As explained in the comment above, we could make this variable precision
1116
        using mpf_init2.
1117
*/
1118
                        mpf_init(a[i]);
39,920✔
1119
                }
1120
                if ( AB[id]->T.mpf_tab2 ) {
576✔
1121
                        a = (mpf_t *)AB[id]->T.mpf_tab2;
1122
                        for ( i = 0; i <=Nw; i++ ) {
1123
                                mpf_clear(a[i]);
1124
                        }
1125
                        M_free(AB[id]->T.mpf_tab2,"mpftab2");
1126
                }
1127
                AB[id]->T.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
576✔
1128
                a = (mpf_t *)AB[id]->T.mpf_tab2;
576✔
1129
                for ( i = 0; i <=Nw; i++ ) {
40,496✔
1130
                        mpf_init(a[i]);
39,920✔
1131
                }
1132
        }
1133
#else
1134
        int i, Nw;
72✔
1135
        size_t N;
72✔
1136
        Nw = AC.DefaultPrecision;
72✔
1137
        N = (size_t)Nw;
72✔
1138
        if ( AT.mpf_tab1 ) {
72✔
1139
                for ( i = 0; i <= Nw; i++ ) {
1140
                        mpf_clear(mpftab1[i]);
1141
                }
1142
                M_free(AT.mpf_tab1,"mpftab1");
1143
        }
1144
        AT.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
72✔
1145
        for ( i = 0; i <= Nw; i++ ) {
5,062✔
1146
/*
1147
        As explained in the comment above, we could make this variable precision
1148
        using mpf_init2.
1149
*/
1150
                mpf_init(mpftab1[i]);
4,990✔
1151
        }
1152
        if ( AT.mpf_tab2 ) {
72✔
1153
                for ( i = 0; i <= Nw; i++ ) {
1154
                        mpf_clear(mpftab2[i]);
1155
                }
1156
                M_free(AT.mpf_tab2,"mpftab2");
1157
        }
1158
        AT.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
72✔
1159
        for ( i = 0; i <= Nw; i++ ) {
5,062✔
1160
                mpf_init(mpftab2[i]);
4,990✔
1161
        }
1162
#endif
1163
        if ( AS.delta_1 ) {
216✔
1164
                mpf_clear(mpfdelta1);
×
1165
                M_free(AS.delta_1,"delta1");
×
1166
        }
1167
        AS.delta_1 = (void *)Malloc1(sizeof(mpf_t),"delta1");
216✔
1168
        mpf_init(mpfdelta1);
216✔
1169
        SimpleDelta(mpfdelta1,1); /* this can speed up things. delta1 = ln(2) */
216✔
1170
/*
1171
        Finally the character buffer for printing
1172
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1173
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1174
*/
1175
}
216✔
1176

1177
/*
1178
                 #] SetupMZVTables : 
1179
                 #[ SetupMPFTables :
1180
*/
1181

1182
void SetupMPFTables(void)
378✔
1183
{
1184
#ifdef WITHPTHREADS
1185
        int id, totnum;
252✔
1186
        mpf_t *a;
252✔
1187
/*
1188
        Now the aux variables
1189
*/
1190
#ifdef WITHSORTBOTS
1191
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
252✔
1192
#endif
1193
    for ( id = 0; id < totnum; id++ ) {
1,512✔
1194
                if ( AB[id]->T.aux_ ) {
1,260✔
1195
/*
1196
                        We work here with a[0] etc because the aux1 etc contain B which
1197
                        in the current routine would be AB[0] only
1198
*/
1199
                        a = (mpf_t *)AB[id]->T.aux_;
1200
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
1201
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
1202
                }
1203
                AB[id]->T.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AB[id]->T.aux_");
1,260✔
1204
                a = (mpf_t *)AB[id]->T.aux_;
1,260✔
1205
                mpf_inits(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
1,260✔
1206
                if ( AB[id]->T.indi1 ) M_free(AB[id]->T.indi1,"indi1");
1,260✔
1207
                AB[id]->T.indi1 = (WORD *)Malloc1(sizeof(WORD)*AC.MaxWeight*2,"indi1");
1,260✔
1208
                AB[id]->T.indi2 = AB[id]->T.indi1 + AC.MaxWeight;
1,260✔
1209
        }
1210
#else
1211
/*
1212
        Now the aux variables
1213
*/
1214
        if ( AT.aux_ ) {
126✔
1215
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
1216
                M_free(AT.aux_,"AT.aux");
1217
        }
1218
        AT.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AT.aux_");
126✔
1219
        mpf_inits(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
126✔
1220
        if ( AT.indi1 ) M_free(AT.indi1,"indi1");
126✔
1221
        AT.indi1 = (WORD *)Malloc1(sizeof(WORD)*AC.MaxWeight*2,"indi1");
126✔
1222
        AT.indi2 = AT.indi1 + AC.MaxWeight;
126✔
1223
#endif
1224
/*
1225
        Finally the character buffer for printing
1226
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1227
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1228
*/
1229
}
378✔
1230

1231
/*
1232
                 #] SetupMPFTables : 
1233
                 #[ ClearMZVTables :
1234
*/
1235

1236
void ClearMZVTables(void)
222✔
1237
{
1238
#ifdef WITHPTHREADS
1239
        int i, id, totnum;
148✔
1240
        mpf_t *a;
148✔
1241
        totnum = AM.totalnumberofthreads;
148✔
1242
    for ( id = 0; id < totnum; id++ ) {
740✔
1243
                if ( AB[id]->T.mpf_tab1 ) { 
592✔
1244
/*
1245
                        We work here with a[0] etc because the aux1, mpftab1 etc contain B 
1246
                        which in the current routine would be AB[0] only
1247
*/
1248
                        a = (mpf_t *)AB[id]->T.mpf_tab1;
40,496✔
1249
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
40,496✔
1250
                                mpf_clear(a[i]);
39,920✔
1251
                        }
1252
                        M_free(AB[id]->T.mpf_tab1,"mpftab1"); 
576✔
1253
                        AB[id]->T.mpf_tab1 = 0; 
576✔
1254
                }
1255
                if ( AB[id]->T.mpf_tab2 ) { 
592✔
1256
                        a = (mpf_t *)AB[id]->T.mpf_tab2;
40,496✔
1257
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
40,496✔
1258
                                mpf_clear(a[i]);
39,920✔
1259
                        }
1260
                        M_free(AB[id]->T.mpf_tab2,"mpftab2"); 
576✔
1261
                        AB[id]->T.mpf_tab2 = 0; 
576✔
1262
                }
1263
        }
1264
#ifdef WITHSORTBOTS
1265
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
148✔
1266
#endif
1267
    for ( id = 0; id < totnum; id++ ) {
888✔
1268
                if ( AB[id]->T.aux_ ) { 
740✔
1269
                        a = (mpf_t *)AB[id]->T.aux_;
740✔
1270
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
740✔
1271
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
740✔
1272
                        AB[id]->T.aux_ = 0; 
740✔
1273
                }
1274
                if ( AB[id]->T.indi1 ) { M_free(AB[id]->T.indi1,"indi1"); AB[id]->T.indi1 = 0; }
740✔
1275
        }
1276
#else
1277
        int i;
74✔
1278
        if ( AT.mpf_tab1 ) { 
74✔
1279
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
5,062✔
1280
                        mpf_clear(mpftab1[i]);
4,990✔
1281
                }
1282
                M_free(AT.mpf_tab1,"mpftab1"); 
72✔
1283
                AT.mpf_tab1 = 0; 
72✔
1284
        }
1285
        if ( AT.mpf_tab2 ) { 
74✔
1286
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
5,062✔
1287
                        mpf_clear(mpftab2[i]);
4,990✔
1288
                }
1289
                M_free(AT.mpf_tab2,"mpftab2"); 
72✔
1290
                AT.mpf_tab2 = 0; 
72✔
1291
        }
1292
        if ( AT.aux_ ) { 
74✔
1293
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
74✔
1294
                M_free(AT.aux_,"AT.aux_"); 
74✔
1295
                AT.aux_ = 0; 
74✔
1296
        }
1297
        if ( AT.indi1 ) { M_free(AT.indi1,"indi1"); AT.indi1 = 0; }
74✔
1298
#endif
1299
        if ( AO.floatspace ) { M_free(AO.floatspace,"floatspace"); AO.floatspace = 0;
222✔
1300
                AO.floatsize = 0; }
222✔
1301
        if ( AS.delta_1 ) { 
222✔
1302
                mpf_clear(mpfdelta1);
216✔
1303
                M_free(AS.delta_1,"delta1"); 
216✔
1304
                AS.delta_1 = 0; 
216✔
1305
        }
1306
}
222✔
1307

1308
/*
1309
                 #] ClearMZVTables : 
1310
                 #[ CoToFloat :
1311
*/
1312

1313
int CoToFloat(UBYTE *s)
36✔
1314
{
1315
        GETIDENTITY
24✔
1316
        if ( AT.aux_ == 0 ) {
36✔
1317
                MesPrint("&Illegal attempt to convert to float_ without activating floating point numbers.");
6✔
1318
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
1319
                return(1);
6✔
1320
        }
1321
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
30✔
1322
        if ( *s ) {
30✔
1323
                MesPrint("&Illegal argument(s) in ToFloat statement: '%s'",s);
×
1324
                return(1);
×
1325
        }
1326
        Add2Com(TYPETOFLOAT);
30✔
1327
        return(0);
30✔
1328
}
1329

1330
/*
1331
                 #] CoToFloat : 
1332
                 #[ CoToRat :
1333
*/
1334

1335
int CoToRat(UBYTE *s)
12✔
1336
{
1337
        GETIDENTITY
8✔
1338
        if ( AT.aux_ == 0 ) {
12✔
1339
                MesPrint("&Illegal attempt to convert from float_ without activating floating point numbers.");
6✔
1340
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
1341
                return(1);
6✔
1342
        }
1343
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
6✔
1344
        if ( *s ) {
6✔
1345
                MesPrint("&Illegal argument(s) in ToRat statement: '%s'",s);
×
1346
                return(1);
×
1347
        }
1348
        Add2Com(TYPETORAT);
6✔
1349
        return(0);
6✔
1350
}
1351

1352
/*
1353
                 #] CoToRat : 
1354
                 #[ CoStrictRounding : 
1355

1356
                Syntax: StrictRounding [precision][base]
1357
                - precision: number of digits to round to (optional)
1358
                - base: 'd' for decimal (base 10) or 'b' for binary (base 2)
1359
                
1360
                If no arguments are provided, uses default precision with binary base.
1361
*/
1362
int CoStrictRounding(UBYTE *s)
12✔
1363
{
1364
        GETIDENTITY
8✔
1365
        WORD x;
12✔
1366
        int base;
12✔
1367
        if ( AT.aux_ == 0 ) {
12✔
NEW
1368
                MesPrint("&Illegal attempt for strict rounding without activating floating point numbers.");
×
NEW
1369
                MesPrint("&Forgotten %#startfloat instruction?");
×
NEW
1370
                return(1);
×
1371
        }
1372
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
12✔
1373
        if ( *s == 0 ) {
12✔
1374
                /* No subkey, which means round to default precision */
1375
                x = AC.DefaultPrecision - AC.MaxWeight - 1;
6✔
1376
                Add4Com(TYPESTRICTROUNDING,x,2);
6✔
1377
                return(0);
6✔
1378
        }
1379
        if ( FG.cTable[*s] == 1 ) { /* number */
6✔
1380
                ParseNumber(x,s)
12✔
1381
                if ( tolower(*s) == 'd' ) { base = 10; s++; }      /* decimal base */
6✔
NEW
1382
                else if ( tolower(*s) == 'b' ){ base = 2; s++; }  /* binary base */
×
NEW
1383
                else goto IllPar;  /* invalid base specification */
×
1384
        }
1385
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
6✔
1386
        
1387
        /* Check for invalid arguments */
1388
        if ( *s ) {
6✔
NEW
1389
IllPar:
×
NEW
1390
                MesPrint("&Illegal argument(s) in StrictRounding statement: '%s'",s);
×
NEW
1391
                return(1);
×
1392
        }
1393
        Add4Com(TYPESTRICTROUNDING,x,base);
6✔
1394
        return(0);
6✔
1395
} 
1396
/*
1397
                 #] CoStrictRounding : 
1398
                 #[ ToFloat :
1399

1400
                Converts the coefficient to floating point if it is still a rat.
1401
*/
1402

1403
int ToFloat(PHEAD WORD *term, WORD level)
282✔
1404
{
1405
        WORD *t, *tstop, nsize, nsign = 3;
282✔
1406
        t = term+*term;
282✔
1407
        nsize = ABS(t[-1]);
282✔
1408
        tstop = t - nsize;
282✔
1409
        if ( t[-1] < 0 ) { nsign = -nsign; }
282✔
1410
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
282✔
1411
                t = term + 1;
144✔
1412
                while ( t < tstop ) {
282✔
1413
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
138✔
1414
                                return(Generator(BHEAD term,level));
×
1415
                        }
1416
                        t += t[1];
138✔
1417
                }
1418
        }
1419
        RatToFloat(aux4,(UWORD *)tstop,nsize);
282✔
1420
        PackFloat(tstop,aux4);
282✔
1421
        tstop += tstop[1];
282✔
1422
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
282✔
1423
        *term = tstop - term;
282✔
1424
        AT.WorkPointer = tstop;
282✔
1425
        return(Generator(BHEAD term,level));
282✔
1426
}
1427

1428
/*
1429
                 #] ToFloat : 
1430
                 #[ ToRat :
1431

1432
                Tries to convert the coefficient to rational if it is still a float.
1433
*/
1434

1435
int ToRat(PHEAD WORD *term, WORD level)
6✔
1436
{
1437
        WORD *tstop, *t, nsize, nsign, ncoef;
6✔
1438
/*
1439
        1: find the float which should be at the end.
1440
*/
1441
        tstop = term + *term; nsize = ABS(tstop[-1]);
6✔
1442
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
6✔
1443
        t = term+1;
6✔
1444
        while ( t < tstop ) {
6✔
1445
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
6✔
1446
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
6✔
1447
                t += t[1];
×
1448
        }
1449
        if ( t < tstop ) {
6✔
1450
/*
1451
                Now t points at the float_ function and everything is correct.
1452
                The result can go straight over the float_ function.
1453
*/
1454
                UnpackFloat(aux4,t);
6✔
1455
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
6✔
1456
                        t += ABS(ncoef);
6✔
1457
                        t[-1] = ncoef*nsign;
6✔
1458
                        *term = t - term;
6✔
1459
                }
1460
        }
1461
        return(Generator(BHEAD term,level));
6✔
1462
}
1463

1464
/*
1465
                 #] ToRat : 
1466
                 #[ StrictRounding : 
1467

1468
                Rounds floating point numbers to a specified precision
1469
                in a given base (decimal or binary).
1470
*/
1471
int StrictRounding(PHEAD WORD *term, WORD level, WORD prec, WORD base) {
30✔
1472
        WORD *t,*tstop;
30✔
1473
        int sign,size,maxprec = AC.DefaultPrecision-AC.MaxWeight-1;
30✔
1474
        /* maxprec is in bits */
1475
        if ( base == 2 && prec > maxprec ) {
30✔
1476
                prec = maxprec;
1477
        }
1478
        if ( base == 10 && prec > (int)(maxprec*log10(2.0)) ) {
30✔
NEW
1479
                prec = maxprec*log10(2.0);
×
1480
        }
1481
        /* Find the float which should be at the end. */
1482
        tstop = term + *term; size = ABS(tstop[-1]);
30✔
1483
        sign = tstop[-1] < 0 ? -1: 1; tstop -= size;
30✔
1484
        t = term+1;
30✔
1485
        while ( t < tstop ) {
42✔
1486
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
30✔
1487
                size == 3 && tstop[0] == 1 && tstop[1] == 1) {
18✔
1488
                        break;
1489
                }
1490
                t += t[1];
12✔
1491
        }
1492
        if ( t < tstop ) {
30✔
1493
/*
1494
                Now t points at the float_ function and everything is correct.
1495
                The result can go straight over the float_ function.
1496
*/
1497
                char *s;
18✔
1498
                mp_exp_t exp;
18✔
1499
                /* Extract the floating point value */
1500
                UnpackFloat(aux4,t);
18✔
1501
                /* Convert to string: 
1502
                   - Format as MeN with M the mantissa and N the exponent 
1503
                   - the generated string by mpf_get_str is the fraction/mantissa with 
1504
                   an implicit radix point immediately to the left of the first digit. 
1505
                   The applicable exponent is written in exp. */
1506
                s = (char *)AO.floatspace;
18✔
1507
                *s++ = '.';
18✔
1508
                mpf_get_str(s,&exp, base, prec, aux4);
18✔
1509
                while ( *s != 0 ) s++;
54✔
1510
                *s++ = 'e';
18✔
1511
                snprintf(s,AO.floatsize-(s-(char *)AO.floatspace),"%ld",exp);
18✔
1512
                /* Negative base values are used to specify that the exponent is in decimal */
1513
                mpf_set_str(aux4,(char *)AO.floatspace,-base);
18✔
1514
                /* Pack the rounded floating point value back into the term */
1515
                PackFloat(t,aux4);
18✔
1516
                t+=t[1];
18✔
1517
                *t++ = 1; *t++ = 1; *t++ = 3*sign;
18✔
1518
                *term = t - term;
18✔
1519
        }
1520
        return(Generator(BHEAD term,level));
30✔
1521
}
1522
/*
1523
                 #] StrictRounding : 
1524
          #] Float Routines : 
1525
          #[ Sorting :
1526

1527
                We need a method to see whether two terms need addition that could
1528
                involve floating point numbers.
1529
                1: if PolyWise is active, we do not need anything, because
1530
                   Poly(Rat)Fun and floating point are mutually exclusive.
1531
                2: This means that there should be only interference in AddCoef.
1532
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1533
                   and PF_GetLoser.
1534
                The compare routine(s) should recognise the float_ and give off
1535
                a code (SortFloatMode) inside the AT struct:
1536
                0: no float_
1537
                1: float_ in term1 only
1538
                2: float_ in term2 only
1539
                3: float_ in both terms
1540
                Be careful: we have several compare routines, because various codes
1541
                use their own routines and we just set a variable with its address.
1542
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1543
                Only Compare1 should be active for this. The others should make sure
1544
                that the proper variable is always zero.
1545
                Remember: the sign of the coefficient is in the last word of the term.
1546

1547
                We need two routines:
1548
                1: AddWithFloat for SplitMerge which sorts by pointer.
1549
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1550
                   as possible in their location.
1551
                The routines start out the same, because AT.SortFloatMode, set in
1552
                Compare1, tells more or less what should be done.
1553
                The difference is in where we leave the result.
1554

1555
                In the future we may want to add a feature that makes the result
1556
                zero if the sum comes within a certain distance of the numerical
1557
                accuracy, like for instance 5% of the number of bits.
1558

1559
                 #[ AddWithFloat :
1560
*/
1561

1562
int AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
174✔
1563
{
1564
        GETBIDENTITY
1565
        SORTING *S = AT.SS;
174✔
1566
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
174✔
1567
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
174✔
1568
        s1 = *ps1;
174✔
1569
        s2 = *ps2;
174✔
1570
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
174✔
1571
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
174✔
1572
        if ( AT.SortFloatMode == 3 ) {
174✔
1573
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
198✔
1574
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
198✔
1575
                UnpackFloat(aux1,fun1);
168✔
1576
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
168✔
1577
                UnpackFloat(aux2,fun2);
168✔
1578
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
168✔
1579
        }
1580
        else if ( AT.SortFloatMode == 1 ) {
6✔
1581
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1582
                UnpackFloat(aux1,fun1);
×
1583
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1584
                fun2 = coef2;
×
1585
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1586
        }
1587
        else if ( AT.SortFloatMode == 2 ) {
6✔
1588
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
12✔
1589
                fun1 = coef1;
6✔
1590
                RatToFloat(aux1,(UWORD *)coef1,size1);
6✔
1591
                UnpackFloat(aux2,fun2);
6✔
1592
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
6✔
1593
        }
1594
        else {
1595
                MLOCK(ErrorMessageLock);
×
1596
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1597
                MUNLOCK(ErrorMessageLock);
×
1598
                Terminate(-1);
×
1599
                return(0);
×
1600
        }
1601
        mpf_add(aux3,aux1,aux2);
174✔
1602
        sign3 = mpf_sgn(aux3);
174✔
1603
        if ( sign3 == 0 ) {        /* May be rare! */
126✔
1604
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1605
        }
1606
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
174✔
1607
        fun3 = TermMalloc("AddWithFloat");
174✔
1608
        PackFloat(fun3,aux3);
174✔
1609
/*
1610
        Now we have to calculate where the sumterm fits.
1611
        If we are sloppy, we can be faster, but run the risk to need the
1612
        extension space, even when it is not needed. At slightly lower speed
1613
        (ie first creating the result in scribble space) we are better off.
1614
        This is why we use TermMalloc.
1615

1616
        The new term will have a rational coefficient of 1,1,+-3.
1617
        The size will be (fun1 or fun2 - term) + fun3 +3;
1618
*/
1619
        if ( AT.SortFloatMode == 3 ) {
174✔
1620
                if ( fun1[1] == fun3[1]  ) {
168✔
1621
Over1:
42✔
1622
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
5,676✔
1623
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
126✔
1624
                        *s1 = t1-s1; goto Finished;
126✔
1625
                }
1626
                else if ( fun2[1] == fun3[1]  ) {
126✔
1627
Over2:
36✔
1628
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
2,052✔
1629
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
42✔
1630
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
42✔
1631
                }
1632
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
90✔
1633
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1634
        }
1635
        else if ( AT.SortFloatMode == 1 ) {
6✔
1636
                if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1637
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1638
        }
1639
        else if ( AT.SortFloatMode == 2 ) {
6✔
1640
                if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1641
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1642
        }
1643
/*
1644
        Does not fit. Go to extension space.
1645
*/
1646
        jj = fun1-s1;
6✔
1647
        j = jj+fun3[1]+3; /* space needed */
6✔
1648
        if ( (S->sFill + j) >= S->sTop2 ) {
6✔
1649
                GarbHand();
×
1650
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1651
                fun1 = s1+jj;
×
1652
        }
1653
        t1 = S->sFill;
6✔
1654
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
12✔
1655
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
336✔
1656
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
6✔
1657
        *ps1 = S->sFill;
6✔
1658
        **ps1 = t1-*ps1;
6✔
1659
        S->sFill = t1;
6✔
1660
Finished:
174✔
1661
        *ps2 = 0;
174✔
1662
        TermFree(fun3,"AddWithFloat");
174✔
1663
        AT.SortFloatMode = 0;
174✔
1664
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
174✔
1665
                MLOCK(ErrorMessageLock);
×
1666
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1667
                AM.MaxTer/sizeof(WORD));
×
1668
                MUNLOCK(ErrorMessageLock);
×
1669
                Terminate(-1);
×
1670
        }
1671
        return(1);
1672
}
1673

1674
/*
1675
                 #] AddWithFloat : 
1676
                 #[ MergeWithFloat :
1677

1678
                Note that we always park the result on top of term1.
1679
                This makes life easier, because the original AddRat in MergePatches
1680
                does this as well.
1681
*/
1682

1683
int MergeWithFloat(PHEAD WORD **interm1, WORD **interm2)
×
1684
{
1685
        GETBIDENTITY
1686
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3, *tt;
×
1687
        WORD sign3,j,jj, *t1, *t2, i, *term1 = *interm1, *term2 = *interm2;
×
1688
        int retval = 0;
×
1689
        coef1 = term1+*term1; size1 = coef1[-1]; coef1 -= ABS(size1);
×
1690
        coef2 = term2+*term2; size2 = coef2[-1]; coef2 -= ABS(size2);
×
1691
        if ( AT.SortFloatMode == 3 ) {
×
1692
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1693
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1694
                UnpackFloat(aux1,fun1);
×
1695
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1696
                UnpackFloat(aux2,fun2);
×
1697
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1698
        }
1699
        else if ( AT.SortFloatMode == 1 ) {
×
1700
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1701
                UnpackFloat(aux1,fun1);
×
1702
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1703
                fun2 = coef2;
×
1704
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1705
        }
1706
        else if ( AT.SortFloatMode == 2 ) {
×
1707
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1708
                fun1 = coef1;
×
1709
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
1710
                UnpackFloat(aux2,fun2);
×
1711
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1712
        }
1713
        else {
1714
                MLOCK(ErrorMessageLock);
×
1715
                MesPrint("Illegal value %d for AT.SortFloatMode in MergeWithFloat.",AT.SortFloatMode);
×
1716
                MUNLOCK(ErrorMessageLock);
×
1717
                Terminate(-1);
×
1718
                return(0);
×
1719
        }
1720
        mpf_add(aux3,aux1,aux2);
×
1721
        sign3 = mpf_sgn(aux3);
×
1722
        if ( sign3 == 0 ) {        /* May be very rare! */
×
1723
                AT.SortFloatMode = 0; return(0);
×
1724
        }
1725
/*
1726
        Now check whether we can park the result on top of one of the input terms.
1727
*/
1728
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
1729
        fun3 = TermMalloc("MergeWithFloat");
×
1730
        PackFloat(fun3,aux3);
×
1731
        if ( AT.SortFloatMode == 3 ) {
×
1732
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) {
×
1733
OnTopOf1:        t1 = fun3; t2 = fun1;
×
1734
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1735
                        *t2++ = 1; *t2++ = 1; *t2++ = sign3 < 0 ? -3: 3;
×
1736
                        retval = 1;
×
1737
                }
1738
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) {
×
1739
Shift1:                t2 = term1 + *term1; tt = t2;
×
1740
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1741
                        t1 = fun3 + fun3[1]; for ( i = 0; i < fun3[1]; i++ ) *--t2 = *--t1;
×
1742
                        t1 = fun1;
1743
                        while ( t1 > term1 ) *--t2 = *--t1;
×
1744
                        *t2 = tt-t2; term1 = t2;
×
1745
                        retval = 1;
×
1746
                }
1747
                else { /* Here we have to move term1 to the left to make room. */
1748
Over1:                jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
×
1749
                        t2 = term1-jj; t1 = term1;
×
1750
                        while ( t1 < fun1 ) *t2++ = *t1++;
×
1751
                        term1 -= jj;
×
1752
                        *term1 += jj;
×
1753
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = fun3[i];
×
1754
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1755
                        retval = 1;
×
1756
                }
1757
        }
1758
        else if ( AT.SortFloatMode == 1 ) {
×
1759
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) goto OnTopOf1;
×
1760
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) goto Shift1;
×
1761
                else goto Over1;
×
1762
        }
1763
        else { /* Can only be 2, based on previous tests */
1764
                if ( fun3[1] + 3 == ABS(size1) ) {
×
1765
                        t2 = coef1; t1 = fun3;
1766
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1767
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1768
                        retval = 1;
×
1769
                }
1770
                else if ( fun3[1] + 3 < ABS(size1) ) {
×
1771
                        j = ABS(size1) - fun3[1] - 3;
×
1772
                        t2 = term1 + *term1; tt = t2;
×
1773
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1774
                        t2 -= fun3[1]; t1 = t2-j;
×
1775
                        while ( t2 > term1 ) *--t2 = *--t1;
×
1776
                        *t2 = tt-t2; term1 = t2;
×
1777
                        retval = 1;
×
1778
                }
1779
                else goto Over1;
×
1780
        }
1781
        *interm1 = term1;
×
1782
        TermFree(fun3,"MergeWithFloat");
×
1783
        AT.SortFloatMode = 0;
×
1784
        return(retval);
×
1785
}
1786

1787
/*
1788
                 #] MergeWithFloat : 
1789
          #] Sorting : 
1790
          #[ MZV :
1791

1792
                The functions here allow the arbitrary precision calculation
1793
                of MZV's and Euler sums.
1794
                They are called when the functions mzv_ and/or euler_ are used
1795
                and the evaluate statement is applied.
1796
                The output is in a float_ function.
1797
                The expand statement tries to express the functions in terms of a basis.
1798
                The bases are the 'standard basis for the euler sums and the
1799
                pushdown bases from the datamine, unless otherwise specified.
1800

1801
                 #[ SimpleDelta :
1802
*/
1803

1804
void SimpleDelta(mpf_t sum, int m)
2,910✔
1805
{
1806
        long s = 1;
2,910✔
1807
        long prec = AC.DefaultPrecision;
2,910✔
1808
        unsigned long xprec = (unsigned long)prec, x;
2,910✔
1809
        int j, jmax, n;
2,910✔
1810
        mpf_t jm,jjm;
2,910✔
1811
        mpf_init(jm); mpf_init(jjm);
2,910✔
1812
        if ( m < 0 ) { s = -1; m = -m; }
2,910✔
1813

1814
/*
1815
        We will loop until 1/2^j/j^m is smaller than the default precision.
1816
        Just running to prec is however overkill, specially when m is large.
1817
        We try to estimate a better value.
1818
        jmax = prec - ((log2(prec)-1)*m).
1819
        Hence we need the leading bit of prec.
1820
        We are still overshooting a bit.
1821
*/
1822
        n = 0; x = xprec;
2,910✔
1823
        while ( x ) { x >>= 1; n++; }
27,042✔
1824
/* 
1825
        We have now n = floor(log2(x))+1. 
1826
*/
1827
        n--;
2,910✔
1828
        jmax = (int)((int)xprec - (n-1)*m);
2,910✔
1829
        mpf_set_ui(sum,0);
2,910✔
1830
        for ( j = 1; j <= jmax; j++ ) {
792,222✔
1831
#ifdef WITHCUTOFF
1832
                xprec--;
786,402✔
1833
                mpf_set_prec_raw(jm,xprec);
786,402✔
1834
                mpf_set_prec_raw(jjm,xprec);
786,402✔
1835
#endif
1836
                mpf_set_ui(jm,1L);
786,402✔
1837
                mpf_div_ui(jjm,jm,(unsigned long)j);
786,402✔
1838
                mpf_pow_ui(jm,jjm,(unsigned long)m);
786,402✔
1839
                mpf_div_2exp(jjm,jm,(unsigned long)j);
786,402✔
1840
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
786,402✔
1841
                else                       mpf_add(sum,sum,jjm);
777,798✔
1842
        }
1843
        mpf_clear(jjm); mpf_clear(jm);
2,910✔
1844
}
2,910✔
1845

1846
/*
1847
                 #] SimpleDelta : 
1848
                 #[ SimpleDeltaC :
1849
*/
1850

1851
void SimpleDeltaC(mpf_t sum, int m)
240✔
1852
{
1853
        long s = 1;
240✔
1854
        long prec = AC.DefaultPrecision;
240✔
1855
        unsigned long xprec = (unsigned long)prec, x;
240✔
1856
        int j, jmax, n;
240✔
1857
        mpf_t jm,jjm;
240✔
1858
        mpf_init(jm); mpf_init(jjm);
240✔
1859
        if ( m < 0 ) { s = -1; m = -m; }
240✔
1860
/*
1861
        We will loop until 1/2^j/j^m is smaller than the default precision.
1862
        Just running to prec is however overkill, specially when m is large.
1863
        We try to estimate a better value.
1864
        jmax = prec - ((log2(prec)-1)*m).
1865
        Hence we need the leading bit of prec.
1866
        We are still overshooting a bit.
1867
*/
1868
        n = 0; x = xprec;
240✔
1869
        while ( x ) { x >>= 1; n++; }
1,920✔
1870
/* 
1871
        We have now n = floor(log2(x))+1. 
1872
*/
1873
        n--;
240✔
1874
        jmax = (int)((int)xprec - (n-1)*m);
240✔
1875
        if ( s < 0 ) jmax /= 2;
240✔
1876
        mpf_set_si(sum,0L);
240✔
1877
        for ( j = 1; j <= jmax; j++ ) {
8,988✔
1878
#ifdef WITHCUTOFF
1879
                xprec--;
8,508✔
1880
                mpf_set_prec_raw(jm,xprec);
8,508✔
1881
                mpf_set_prec_raw(jjm,xprec);
8,508✔
1882
#endif
1883
                mpf_set_ui(jm,1L);
8,508✔
1884
                mpf_div_ui(jjm,jm,(unsigned long)j);
8,508✔
1885
                mpf_pow_ui(jm,jjm,(unsigned long)m);
8,508✔
1886
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
8,508✔
1887
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
1888
                mpf_add(sum,sum,jjm);
8,508✔
1889
        }
1890
        mpf_clear(jjm); mpf_clear(jm);
240✔
1891
}
240✔
1892

1893
/*
1894
                 #] SimpleDeltaC : 
1895
                 #[ SingleTable :
1896
*/
1897

1898
void SingleTable(mpf_t *tabl, int N, int m, int pow)
3,606✔
1899
{
1900
/*
1901
        Creates a table T(1,...,N) with
1902
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
1903
        To make this table we have two options:
1904
        1: run the sum backwards with the potential problem that the 
1905
           precision is difficult to manage.
1906
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
1907
        When doing Euler sums we may need also 1/4^j
1908
        pow: 1 -> 1/2^j
1909
             2 -> 1/4^j
1910
*/
1911
        GETIDENTITY
2,404✔
1912
        long s = 1;
3,606✔
1913
        int j;
3,606✔
1914
#ifdef WITHCUTOFF
1915
        long prec = mpf_get_default_prec();
3,606✔
1916
#endif
1917
        mpf_t jm,jjm;
3,606✔
1918
        mpf_init(jm); mpf_init(jjm);
3,606✔
1919
        if ( pow < 1 || pow > 2 ) {
3,606✔
1920
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1921
                exit(-1);
×
1922
        }
1923
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
1924
        mpf_set_si(auxsum,0L);
3,606✔
1925
        for ( j = N; j > 0; j-- ) {
779,850✔
1926
#ifdef WITHCUTOFF
1927
                mpf_set_prec_raw(jm,prec-j);
772,638✔
1928
                mpf_set_prec_raw(jjm,prec-j);
772,638✔
1929
#endif
1930
                mpf_set_ui(jm,1L);
772,638✔
1931
                mpf_div_ui(jjm,jm,(unsigned long)j);
772,638✔
1932
                mpf_pow_ui(jm,jjm,(unsigned long)m);
772,638✔
1933
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
772,638✔
1934
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
772,638✔
1935
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
740,982✔
1936
                else                       mpf_add(auxsum,auxsum,jjm);
725,286✔
1937
/*
1938
                And now copy auxsum to tablelement j
1939
*/
1940
                mpf_set(tabl[j],auxsum);
772,638✔
1941
        }
1942
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
1943
}
3,606✔
1944

1945
/*
1946
                 #] SingleTable : 
1947
                 #[ DoubleTable :
1948
*/
1949

1950
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
4,674✔
1951
{
1952
        GETIDENTITY
3,116✔
1953
        long s = 1;
4,674✔
1954
#ifdef WITHCUTOFF
1955
        long prec = mpf_get_default_prec();
4,674✔
1956
#endif
1957
        int j;
4,674✔
1958
        mpf_t jm,jjm;
4,674✔
1959
        mpf_init(jm); mpf_init(jjm);
4,674✔
1960
        if ( pow < -1 || pow > 2 ) {
4,674✔
1961
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1962
                exit(-1);
×
1963
        }
1964
        if ( m < 0 ) { m = -m; s = -1; }
4,674✔
1965
        mpf_set_ui(auxsum,0L);
4,674✔
1966
        for ( j = N; j > 0; j-- ) {
1,709,796✔
1967
#ifdef WITHCUTOFF
1968
                mpf_set_prec_raw(jm,prec-j);
1,700,448✔
1969
                mpf_set_prec_raw(jjm,prec-j);
1,700,448✔
1970
#endif
1971
                mpf_set_ui(jm,1L);
1,700,448✔
1972
                mpf_div_ui(jjm,jm,(unsigned long)j);
1,700,448✔
1973
                mpf_pow_ui(jm,jjm,(unsigned long)m);
1,700,448✔
1974
                if ( pow == -1 ) {
1,700,448✔
1975
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
8,232✔
1976
                        mpf_mul(jm,jjm,tabin[j+1]);
8,232✔
1977
                }
1978
                else if ( pow > 0 ) {
1,692,216✔
1979
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
3,648✔
1980
                        mpf_mul(jm,jjm,tabin[j+1]);
3,648✔
1981
                }
1982
                else {
1983
                        mpf_mul(jm,jm,tabin[j+1]);
1,688,568✔
1984
                }
1985
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
1,700,448✔
1986
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
1,700,448✔
1987
                else                       mpf_add(auxsum,auxsum,jm);
1,694,496✔
1988
/*
1989
                And now copy auxsum to tablelement j
1990
*/
1991
                mpf_set(tabout[j],auxsum);
1,700,448✔
1992
        }
1993
        mpf_clear(jjm); mpf_clear(jm);
4,674✔
1994
}
4,674✔
1995

1996
/*
1997
                 #] DoubleTable : 
1998
                 #[ EndTable :
1999
*/
2000

2001
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
3,606✔
2002
{
2003
        long s = 1;
3,606✔
2004
#ifdef WITHCUTOFF
2005
        long prec = mpf_get_default_prec();
3,606✔
2006
#endif
2007
        int j;
3,606✔
2008
        mpf_t jm,jjm;
3,606✔
2009
        mpf_init(jm); mpf_init(jjm);
3,606✔
2010
        if ( pow < -1 || pow > 2 ) {
3,606✔
2011
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2012
                exit(-1);
×
2013
        }
2014
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
2015
        mpf_set_si(sum,0L);
3,606✔
2016
        for ( j = N; j > 0; j-- ) {
770,970✔
2017
#ifdef WITHCUTOFF
2018
                mpf_set_prec_raw(jm,prec-j);
763,758✔
2019
                mpf_set_prec_raw(jjm,prec-j);
763,758✔
2020
#endif
2021
                mpf_set_ui(jm,1L);
763,758✔
2022
                mpf_div_ui(jjm,jm,(unsigned long)j);
763,758✔
2023
                mpf_pow_ui(jm,jjm,(unsigned long)m);
763,758✔
2024
                if ( pow == -1 ) {
763,758✔
2025
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
13,050✔
2026
                        mpf_mul(jm,jjm,tabin[j+1]);
13,050✔
2027
                }
2028
                else if ( pow > 0 ) {
750,708✔
2029
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
11,700✔
2030
                        mpf_mul(jm,jjm,tabin[j+1]);
11,700✔
2031
                }
2032
                else {
2033
                        mpf_mul(jm,jm,tabin[j+1]);
739,008✔
2034
                }
2035
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
763,758✔
2036
                else                       mpf_add(sum,sum,jm);
751,218✔
2037
        }
2038
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
2039
}
3,606✔
2040

2041
/*
2042
                 #] EndTable : 
2043
                 #[ deltaMZV :
2044
*/
2045

2046
void deltaMZV(mpf_t result, WORD *indexes, int depth)
7,566✔
2047
{
2048
        GETIDENTITY
5,044✔
2049
/*
2050
        Because all sums go roughly like 1/2^j we need about depth steps.
2051
*/
2052
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
2053
        if ( depth == 1 ) {
7,566✔
2054
                if ( indexes[0] == 1 ) {
3,804✔
2055
                        mpf_set(result,mpfdelta1);
1,650✔
2056
                        return;
1,650✔
2057
                }
2058
                SimpleDelta(result,indexes[0]);
2,154✔
2059
        }
2060
        else if ( depth == 2 ) {
3,762✔
2061
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
1,470✔
2062
                        mpf_pow_ui(result,mpfdelta1,2);
486✔
2063
                        mpf_div_2exp(result,result,1);
486✔
2064
                }
2065
                else {
2066
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
984✔
2067
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
984✔
2068
                };
2069
        }
2070
        else if ( depth > 2 ) {
2,292✔
2071
                mpf_t *mpftab3;
2072
                int d;
2073
/*
2074
                Check first whether this is a power of delta1 = ln(2)
2075
*/
2076
                for ( d = 0; d < depth; d++ ) {
7,548✔
2077
                        if ( indexes[d] != 1 ) break;
6,678✔
2078
                }
2079
                if ( d == depth ) {        /* divide by fac_(depth) */
2,292✔
2080
                        mpf_pow_ui(result,mpfdelta1,depth);
870✔
2081
                        for ( d = 2; d <= depth; d++ ) {
5,196✔
2082
                                mpf_div_ui(result,result,(unsigned long)d);
3,456✔
2083
                        }
2084
                }
2085
                else {
2086
                        d = depth-1;
1,422✔
2087
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
1,422✔
2088
                        d--; indexes++;
1,422✔
2089
                        for(;;) {
6,726✔
2090
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
4,074✔
2091
                                d--; indexes++;
4,074✔
2092
                                if ( d == 0 ) {
4,074✔
2093
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
1,422✔
2094
                                        break;
1,422✔
2095
                                }
2096
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
2,652✔
2097
                                AT.mpf_tab2 = (void *)mpftab3;
2,652✔
2098
                        }
2099
                }
2100
        }
2101
        else if ( depth == 0 ) {
×
2102
                mpf_set_ui(result,1L);
×
2103
        }
2104
}
2105

2106
/*
2107
                 #] deltaMZV : 
2108
                 #[ deltaEuler :
2109

2110
                Regular Euler delta with - signs, but everywhere 1/2^j
2111
*/
2112

2113
void deltaEuler(mpf_t result, WORD *indexes, int depth)
990✔
2114
{
2115
        GETIDENTITY
660✔
2116
        int m;
990✔
2117
#ifdef DEBUG
2118
        int i;
2119
        printf(" deltaEuler(");
2120
        for ( i = 0; i < depth; i++ ) {
2121
                if ( i != 0 ) printf(",");
2122
                printf("%d",indexes[i]);
2123
        }
2124
        printf(") = ");
2125
#endif
2126
        if ( depth == 1 ) {
990✔
2127
                SimpleDelta(result,indexes[0]);
390✔
2128
        }
2129
        else if ( depth == 2 ) {
600✔
2130
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
348✔
2131
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
348✔
2132
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,0);
348✔
2133
        }
2134
        else if ( depth > 2 ) {
252✔
2135
                int d;
252✔
2136
                mpf_t *mpftab3;
252✔
2137
                d = depth-1;
252✔
2138
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
252✔
2139
                d--; indexes++;
252✔
2140
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
252✔
2141
                for(;;) {
348✔
2142
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
300✔
2143
                        d--; indexes++;
300✔
2144
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
300✔
2145
                        if ( d == 0 ) {
300✔
2146
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
252✔
2147
                                break;
252✔
2148
                        }
2149
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2150
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2151
                }
2152
        }
2153
        else if ( depth == 0 ) {
×
2154
                mpf_set_ui(result,1L);
×
2155
        }
2156
#ifdef DEBUG
2157
        gmp_printf("%.*Fe\n",40,result);
2158
#endif
2159
}
990✔
2160

2161
/*
2162
                 #] deltaEuler : 
2163
                 #[ deltaEulerC :
2164

2165
                Conjugate Euler delta without - signs, but possibly 1/4^j
2166
                When there is a - in the string we have 1/4.
2167
*/
2168

2169
void deltaEulerC(mpf_t result, WORD *indexes, int depth)
990✔
2170
{
2171
        GETIDENTITY
660✔
2172
        int m;
990✔
2173
#ifdef DEBUG
2174
        int i;
2175
        printf(" deltaEulerC(");
2176
        for ( i = 0; i < depth; i++ ) {
2177
                if ( i != 0 ) printf(",");
2178
                printf("%d",indexes[i]);
2179
        }
2180
        printf(") = ");
2181
#endif
2182
        mpf_set_ui(result,0);
990✔
2183
        if ( depth == 1 ) {
990✔
2184
                if ( indexes[0] == 0 ) {
390✔
2185
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2186
                }
2187
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
390✔
2188
                else                  SimpleDelta(result,indexes[0]);
150✔
2189
        }
2190
        else if ( depth == 2 ) {
600✔
2191
                int par;
348✔
2192
                m = indexes[0];
348✔
2193
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth,-m,2);
348✔
2194
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth, m,1);
132✔
2195
                m = indexes[1];
348✔
2196
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
348✔
2197
                else { par = indexes[0] < 0 ? -1: 0; }
150✔
2198
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
348✔
2199
        }
2200
        else if ( depth > 2 ) {
252✔
2201
                int d, par;
252✔
2202
                mpf_t *mpftab3;
252✔
2203
                d = depth-1;
252✔
2204
                m = indexes[0];
252✔
2205
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
252✔
2206
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
252✔
2207
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
60✔
2208
                d--; indexes++; m = indexes[0];
252✔
2209
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
252✔
2210
                else { par = indexes[-1] < 0 ? -1: 0; }
120✔
2211
                for(;;) {
348✔
2212
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
300✔
2213
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
300✔
2214
                        d--; indexes++; m = indexes[0];
300✔
2215
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
300✔
2216
                        else { par = indexes[-1] < 0 ? -1: 0; }
144✔
2217
                        if ( d == 0 ) {
300✔
2218
                                mpf_set_ui(result,0);
252✔
2219
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
252✔
2220
                                break;
252✔
2221
                        }
2222
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2223
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2224
                }
2225
        }
2226
        else if ( depth == 0 ) {
×
2227
                mpf_set_ui(result,1L);
×
2228
        }
2229
#ifdef DEBUG
2230
        gmp_printf("%.*Fe\n",40,result);
2231
#endif
2232
}
990✔
2233

2234
/*
2235
                 #] deltaEulerC : 
2236
                 #[ CalculateMZVhalf :
2237

2238
                 This routine is mainly for support when large numbers of
2239
                MZV's have to be calculated at the same time.
2240
*/
2241

2242
void CalculateMZVhalf(mpf_t result, WORD *indexes, int depth)
378✔
2243
{
2244
        int i;
378✔
2245
        if ( depth < 0 ) {
378✔
2246
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
2247
                exit(-1);
×
2248
        }
2249
        for ( i = 0; i < depth; i++ ) {
1,530✔
2250
                if ( indexes[i] <= 0 ) {
1,152✔
2251
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2252
                        exit(-1);
×
2253
                }
2254
        }
2255
        deltaMZV(result,indexes,depth);
378✔
2256
}
378✔
2257

2258
/*
2259
                 #] CalculateMZVhalf : 
2260
                 #[ CalculateMZV :
2261
*/
2262

2263
void CalculateMZV(mpf_t result, WORD *indexes, int depth)
822✔
2264
{
2265
        GETIDENTITY
548✔
2266
        int num1, num2 = 0, i, j = 0;
822✔
2267
        if ( depth < 0 ) {
822✔
2268
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
2269
                exit(-1);
×
2270
        }
2271
        if ( indexes[0] == 1 ) {
822✔
2272
                printf("Divergent MZV in CalculateMZV\n");
×
2273
                exit(-1);
×
2274
        }
2275
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2276
        for ( i = 0; i < depth; i++ ) {
2,076✔
2277
                if ( indexes[i] <= 0 ) {
1,254✔
2278
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
2279
                        exit(-1);
×
2280
                }
2281
                AT.indi1[i] = indexes[i];
1,254✔
2282
        }
2283
        num1 = depth; i = 0;
822✔
2284
        deltaMZV(result,indexes,depth);
822✔
2285
        for(;;) {
6,366✔
2286
                if ( AT.indi1[0] > 1 ) {
3,594✔
2287
                        AT.indi1[0] -= 1;
2,340✔
2288
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
7,794✔
2289
                        AT.indi2[0] = 1; num2++;
2,340✔
2290
                }
2291
                else {
2292
                        AT.indi2[0] += 1;
1,254✔
2293
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,926✔
2294
                        num1--;
1,254✔
2295
                        if ( num1 == 0 ) break;
1,254✔
2296
                }
2297
                deltaMZV(aux1,AT.indi1,num1);
2,772✔
2298
                deltaMZV(aux2,AT.indi2,num2);
2,772✔
2299
                mpf_mul(aux3,aux1,aux2);
2,772✔
2300
                mpf_add(result,result,aux3);
2,772✔
2301
        }
2302
        deltaMZV(aux3,AT.indi2,num2);
822✔
2303
        mpf_add(result,result,aux3);
822✔
2304
}
822✔
2305

2306
/*
2307
                 #] CalculateMZV : 
2308
                 #[ CalculateEuler :
2309

2310
                There is a problem of notation here.
2311
                Basically there are two notations.
2312
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2313
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2314
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2315
                   See Broadhurst,1996
2316
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2317
                                 sum_(j2,1,inf,sign_(m2)*
2318
                                 sum_(j3,1,inf,sign_(m3)
2319
                                                        /j3^abs_(m3)
2320
                                                        /(j2+j3)^abs_(m2)
2321
                                                        /(j1+j2+j3)^abs_(m1) )))
2322
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2323
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2324
                The algorithm follows 2, but the more common notation is 1.
2325
                Hence we start with a conversion.
2326
*/
2327

2328
void CalculateEuler(mpf_t result, WORD *Zindexes, int depth)
318✔
2329
{
2330
        GETIDENTITY
212✔
2331
        int s1, num1, num2, i, j;
318✔
2332

2333
        WORD *indexes = AT.WorkPointer;
318✔
2334
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
1,128✔
2335
        for ( i = 0; i < depth-1; i++ ) {
810✔
2336
                if ( Zindexes[i] < 0 ) {
492✔
2337
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
864✔
2338
                }
2339
        }
2340

2341
        if ( depth < 0 ) {
318✔
2342
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
2343
                exit(-1);
×
2344
        }
2345
        if ( indexes[0] == 1 ) {
318✔
2346
                printf("Divergent Euler sum in CalculateEuler\n");
×
2347
                exit(-1);
×
2348
        }
2349
        for ( i = 0, j = 0; i < depth; i++ ) {
1,128✔
2350
                if ( indexes[i] == 0 ) {
810✔
2351
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2352
                        exit(-1);
×
2353
                }
2354
                if ( indexes[i] < 0 ) j = 1;
810✔
2355
                AT.indi1[i] = indexes[i];
810✔
2356
        }
2357
        if ( j == 0 ) {
318✔
2358
                CalculateMZV(result,indexes,depth);
42✔
2359
                return;
42✔
2360
        }
2361
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
276✔
2362
        deltaEuler(result,AT.indi1,depth);
276✔
2363
        s1 = 0;
276✔
2364
        for(;;) {
990✔
2365
                s1++;
990✔
2366
                if ( AT.indi1[0] > 1 ) {
990✔
2367
                        AT.indi1[0] -= 1;
90✔
2368
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
162✔
2369
                        AT.indi2[0] = 1; num2++;
90✔
2370
                }
2371
                else if ( AT.indi1[0] < -1 ) {
900✔
2372
                        AT.indi1[0] += 1;
162✔
2373
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
270✔
2374
                        AT.indi2[0] = 1; num2++;
162✔
2375
                }
2376
                else if ( AT.indi1[0] == -1 ) {
738✔
2377
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
1,026✔
2378
                        AT.indi2[0] = -1; num2++;
486✔
2379
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,026✔
2380
                        num1--;
486✔
2381
                }
2382
                else {
2383
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
252✔
2384
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
432✔
2385
                        num1--;
252✔
2386
                }
2387
                if ( num1 == 0 ) break;
990✔
2388
                deltaEuler(aux1,AT.indi1,num1);
714✔
2389
                deltaEulerC(aux2,AT.indi2,num2);
714✔
2390
                mpf_mul(aux3,aux1,aux2);
714✔
2391
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
714✔
2392
                else                               mpf_sub(result,result,aux3);
408✔
2393
        }
2394
        deltaEulerC(aux3,AT.indi2,num2);
276✔
2395
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
276✔
2396
        else                          mpf_sub(result,result,aux3);
162✔
2397
}
2398

2399
/*
2400
                 #] CalculateEuler : 
2401
                 #[ ExpandMZV :
2402
*/
2403

2404
int ExpandMZV(WORD *term, WORD level)
×
2405
{
2406
        DUMMYUSE(term);
×
2407
        DUMMYUSE(level);
×
2408
        return(0);
×
2409
}
2410

2411
/*
2412
                 #] ExpandMZV : 
2413
                 #[ ExpandEuler :
2414
*/
2415

2416
int ExpandEuler(WORD *term, WORD level)
×
2417
{
2418
        DUMMYUSE(term);
×
2419
        DUMMYUSE(level);
×
2420
        return(0);
×
2421
}
2422

2423
/*
2424
                 #] ExpandEuler : 
2425
                 #[ EvaluateEuler :
2426

2427
        There are various steps here:
2428
        1: locate an Euler function.
2429
        2: evaluate it into a float.
2430
        3: convert the coefficient to a float and multiply.
2431
        4: Put the new term together.
2432
        5: Restart to see whether there are more Euler functions.
2433
        The compiler should check that there is no conflict between
2434
        the evaluate command and a potential polyfun or polyratfun.
2435
        Yet, when reading in expressions there can be a conflict.
2436
        Hence the Normalize routine should check as well.
2437

2438
        par == MZV: MZV
2439
        par == EULER: Euler
2440
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2441
        par == ALLMZVFUNCTIONS: all of the above.
2442
*/
2443

2444
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
1,296✔
2445
{
2446
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
1,296✔
2447
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
1,296✔
2448
        int retval;
1,296✔
2449
        tstop = term + *term; tstop -= ABS(tstop[-1]);
1,296✔
2450
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
1,296✔
2451
/*
2452
        Step 1. We also need to verify that the argument we find is legal
2453
*/
2454
        t = term+1;
1,296✔
2455
        while ( t < tstop ) {
3,810✔
2456
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
2,514✔
2457
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
156✔
2458
        /* all arguments should be small integers */
2459
                        indexes = AT.WorkPointer;
1,494✔
2460
                        sumweight = 0; depth = 0;
1,494✔
2461
                        tnext = t + t[1]; tt = t + FUNHEAD;
1,494✔
2462
                        while ( tt < tnext ) {
4,638✔
2463
                                if ( *tt != -SNUMBER ) goto nextfun;
3,144✔
2464
                                if ( tt[1] == 0 ) goto nextfun;
3,144✔
2465
                                indexes[depth] = tt[1];
3,144✔
2466
                                sumweight += ABS(tt[1]); depth++;
3,144✔
2467
                                tt += 2;
3,144✔
2468
                        }
2469
                        /* euler sum without arguments, i.e. mzv_(), euler_() or mzvhalf_() */
2470
                        if ( depth == 0) goto nextfun;
1,494✔
2471
                        if ( sumweight > AC.MaxWeight ) {
1,476✔
2472
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
2473
                                MesPrint("Please increase MaxWeight in form.set.");
×
2474
                                Terminate(-1);
×
2475
                        }
2476
/*
2477
                        Step 2: evaluate:
2478
*/
2479
                        AT.WorkPointer += depth;
1,476✔
2480
                        if ( first ) {
1,476✔
2481
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
1,152✔
2482
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
696✔
2483
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
378✔
2484
                                first = 0;
2485
                        }
2486
                        else {
2487
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
324✔
2488
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
2489
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2490
                                mpf_mul(aux4,aux4,aux5);
324✔
2491
                        }
2492
                        *t = 0;
1,476✔
2493
                }
2494
nextfun:
1,020✔
2495
                t += t[1];
2,514✔
2496
        }
2497
        if ( first == 1 ) return(Generator(BHEAD term,level));
1,296✔
2498
/*
2499
        Step 3:
2500
        Now the regular coefficient, if it is not 1/1.
2501
        We have two cases: size +- 3, or bigger.
2502
*/
2503
        nsize = term[*term-1];
1,152✔
2504
        if ( nsize < 0 ) {
1,152✔
2505
                mpf_neg(aux4,aux4);
72✔
2506
                nsize = -nsize;
72✔
2507
        }
2508
        if ( nsize == 3 ) {
1,152✔
2509
                if ( tstop[0] != 1 ) {
1,152✔
2510
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
132✔
2511
                }
2512
                if ( tstop[1] != 1 ) {
1,152✔
2513
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
132✔
2514
                }
2515
        }
2516
        else {
2517
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2518
                mpf_mul(aux4,aux4,aux5);
×
2519
        }
2520
/*
2521
        Now we have to locate possible other float_ functions.
2522
*/
2523
        t = term+1;
2524
        while ( t < tstop ) {
3,510✔
2525
                if ( *t == FLOATFUN ) {
2,358✔
2526
                        UnpackFloat(aux5,t);
×
2527
                        mpf_mul(aux4,aux4,aux5);
×
2528
                }
2529
                t += t[1];
2,358✔
2530
        }
2531
/*
2532
        Now we should compose the new term in the WorkSpace.
2533
*/
2534
        t = term+1;
1,152✔
2535
        newterm = AT.WorkPointer;
1,152✔
2536
        tt = newterm+1;
1,152✔
2537
        while ( t < tstop ) {
1,152✔
2538
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
2,358✔
2539
                else {
2540
                        i = t[1]; NCOPY(tt,t,i);
11,922✔
2541
                }
2542
        }
2543
        PackFloat(tt,aux4);
1,152✔
2544
        tt += tt[1];
1,152✔
2545
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
1,152✔
2546
        *newterm = tt-newterm;
1,152✔
2547
        AT.WorkPointer = tt;
1,152✔
2548
        retval = Generator(BHEAD newterm,level);
1,152✔
2549
        AT.WorkPointer = oldworkpointer;
1,152✔
2550
        return(retval);
1,152✔
2551
}
2552

2553
/*
2554
                 #] EvaluateEuler : 
2555
          #] MZV : 
2556
          #[ Functions :
2557
                 #[ CoEvaluate :
2558

2559
                Current subkeys: mzv_, euler_ and sqrt_.
2560
*/
2561

2562
int CoEvaluate(UBYTE *s)
378✔
2563
{
2564
        GETIDENTITY
252✔
2565
        UBYTE *subkey, c;
378✔
2566
        WORD numfun, type;
378✔
2567
        int error = 0;
378✔
2568
        if ( AT.aux_ == 0 ) {
378✔
2569
                MesPrint("&Illegal attempt to evaluate a function without activating floating point numbers.");
6✔
2570
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
2571
                return(1);
6✔
2572
        }
2573
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
372✔
2574
        if ( *s == 0 ) {
372✔
2575
/*
2576
                No subkey, which means all functions.
2577
*/
2578
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
30✔
2579
/*
2580
                The MZV, EULER and MZVHALF are done separately
2581
*/
2582
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
30✔
2583
                return(0);        
30✔
2584
        }
2585
        while ( *s ) {
660✔
2586
        subkey = s;
2587
        while ( FG.cTable[*s] == 0 ) s++;
1,656✔
2588
          if ( *s == '2' ) s++; /* cases li2_ and atan2_ */
360✔
2589
          if ( *s == '_' ) s++;
360✔
2590
          c = *s; *s = 0;
360✔
2591
/*
2592
                We still need provisions for pi_ and possibly other constants.
2593
*/
2594
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
360✔
2595
                        || ( functions[numfun].spec != 0 ) ) {
318✔
2596

2597
                if ( type == CSYMBOL ) {
42✔
2598
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
36✔
2599
                        break;
36✔
2600
                }
2601
/*
2602
                        This cannot work.
2603
*/
2604
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
6✔
2605
                return(1);
6✔
2606
          }
2607
          else {
2608
                switch ( numfun+FUNCTION ) {
318✔
2609
                        case MZV:
318✔
2610
                        case EULER:
2611
                        case MZVHALF:
2612
/*
2613
                        The following functions are treated in evaluate.c
2614
*/
2615
                        case SQRTFUNCTION:
2616
                        case LNFUNCTION:
2617
                        case SINFUNCTION:
2618
                        case COSFUNCTION:
2619
                        case TANFUNCTION:
2620
                        case ASINFUNCTION:
2621
                        case ACOSFUNCTION:
2622
                        case ATANFUNCTION:
2623
                        case ATAN2FUNCTION:
2624
                        case SINHFUNCTION:
2625
                        case COSHFUNCTION:
2626
                        case TANHFUNCTION:
2627
                        case ASINHFUNCTION:
2628
                        case ACOSHFUNCTION:
2629
                        case ATANHFUNCTION:
2630
                        case LI2FUNCTION:
2631
                        case LINFUNCTION:
2632
                        case AGMFUNCTION:
2633
                        case GAMMAFUN:
2634
/*
2635
                        At a later stage we can add more functions from mpfr here
2636
                                mpfr_(number,arg(s))
2637
*/
2638
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
318✔
2639
                                break;
318✔
2640
                        default:
×
2641
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2642
                                error = 1;
×
2643
                                break;
×
2644
                }
2645
          }
2646
          *s = c;
318✔
2647
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
336✔
2648
        }
2649
        return(error);
2650
}
2651

2652
/*
2653
                 #] CoEvaluate : 
2654
          #] Functions : 
2655
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc