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

form-dev / form / 20068474439

09 Dec 2025 03:15PM UTC coverage: 57.334% (+0.2%) from 57.16%
20068474439

push

github

cbmarini
fix: fixed the compiler warning in CoStrictRounding. Added two more tests for the StrictRounding statement to have full coverage.

47337 of 82564 relevant lines covered (57.33%)

5681406.02 hits per line

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

85.25
/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)
10,314✔
271
{
272
        WORD *t, nlimbs, num, nnum;
10,314✔
273
        mp_limb_t *d = infloat->_mp_d; /* Pointer to the limbs.  */
10,314✔
274
        int i;
10,314✔
275
        long e = infloat->_mp_exp;
10,314✔
276
        
277
        t = fun;
10,314✔
278
        *t++ = FLOATFUN;
10,314✔
279
        t++;
10,314✔
280
        FILLFUN(t);
10,314✔
281
        *t++ = -SNUMBER;
10,314✔
282
        *t++ = infloat->_mp_prec;
10,314✔
283
        *t++ = -SNUMBER;
10,314✔
284
        *t++ = infloat->_mp_size;
10,314✔
285
/*
286
        Now the exponent which is a signed long
287
*/
288
        if ( e < 0 ) {
10,314✔
289
                e = -e;
348✔
290
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
348✔
291
                        *t++ = -SNUMBER; *t++ = -e;
186✔
292
                }
293
                else {
294
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
162✔
295
                        *t++ = 6;
162✔
296
                        *t++ = (UWORD)e;
162✔
297
                        *t++ = (UWORD)(e >> BITSINWORD);
162✔
298
                        *t++ = 1; *t++ = 0; *t++ = -5;
162✔
299
                }
300
        }
301
        else {
302
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
9,966✔
303
                        *t++ = -SNUMBER; *t++ = e;
9,804✔
304
                }
305
                else {
306
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
162✔
307
                        *t++ = 6;
162✔
308
                        *t++ = (UWORD)e;
162✔
309
                        *t++ = (UWORD)(e >> BITSINWORD);
162✔
310
                        *t++ = 1; *t++ = 0; *t++ = 5;
162✔
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;
10,314✔
318
        if ( nlimbs == 0 ) {
10,314✔
319
        }
320
        else if ( nlimbs == 1 && (ULONG)(*d) < ((ULONG)1)<<(BITSINWORD-1) ) {
10,314✔
321
                *t++ = -SNUMBER;
1,824✔
322
                *t++ = (UWORD)(*d);
1,824✔
323
        }
324
        else {
325
          if ( d[nlimbs-1] < ((ULONG)1)<<BITSINWORD ) {
8,490✔
326
                num = 2*nlimbs-1; /* number of UWORDS needed */
6,432✔
327
          }
328
          else {
329
                num = 2*nlimbs;   /* number of UWORDS needed */
2,058✔
330
          }
331
          nnum = num;
8,490✔
332
          *t++ = 2*num+2+ARGHEAD;
8,490✔
333
          *t++ = 0;
8,490✔
334
          FILLARG(t);
8,490✔
335
          *t++ = 2*num+2;
8,490✔
336
          while ( num > 1 ) {
28,692✔
337
                *t++ = (UWORD)(*d); *t++ = (UWORD)(((ULONG)(*d))>>BITSINWORD); d++;
20,202✔
338
                num -= 2;
20,202✔
339
          }
340
          if ( num == 1 ) { *t++ = (UWORD)(*d); }
8,490✔
341
          *t++ = 1;
8,490✔
342
          for ( i = 1; i < nnum; i++ ) *t++ = 0;
46,836✔
343
          *t++ = 2*nnum+1; /* the sign is hidden in infloat->_mp_size */
8,490✔
344
        }
345
        fun[1] = t-fun;
10,314✔
346
        return(fun[1]);
10,314✔
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)
16,650✔
365
{
366
        UWORD *t;
16,650✔
367
        WORD *f;
16,650✔
368
        int num, i;
16,650✔
369
        mp_limb_t *d;
16,650✔
370
/*
371
        Very first step: check whether we can use float_:
372
*/
373
        GETIDENTITY
11,100✔
374
        if ( AT.aux_ == 0 ) {
16,650✔
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;
16,650✔
385
        f = fun + FUNHEAD + 2;
16,650✔
386
        if ( ABS(f[1]) > f[-1]+1 ) goto Incorrect;
16,650✔
387
        if ( f[1] > outfloat->_mp_prec+1
16,650✔
388
          || outfloat->_mp_d == 0 ) {
16,650✔
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];
16,650✔
400
        outfloat->_mp_size = num;
16,650✔
401
        if ( num < 0 ) { num = -num; }
16,650✔
402
        f += 2;
16,650✔
403
        if ( *f == -SNUMBER ) {
16,650✔
404
                outfloat->_mp_exp = (mp_exp_t)(f[1]);
16,326✔
405
                f += 2;
16,326✔
406
        }
407
        else {
408
                f += ARGHEAD+6;
324✔
409
                if ( f[-1] == -5 ) {
324✔
410
                        outfloat->_mp_exp =
162✔
411
                                -(mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+(UWORD)f[-5]);
162✔
412
                }
413
                else if ( f[-1] == 5 ) {
162✔
414
                        outfloat->_mp_exp =
162✔
415
                                 (mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+(UWORD)f[-5]);
162✔
416
                }
417
        }
418
/*
419
        And now the limbs if needed
420
*/
421
        d = outfloat->_mp_d;
16,650✔
422
        if ( outfloat->_mp_size == 0 ) {
16,650✔
423
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
×
424
                return(0);
425
        }
426
        else if ( *f == -SNUMBER ) {
16,650✔
427
                *d++ = (mp_limb_t)f[1];
1,896✔
428
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
5,688✔
429
                return(0);
430
        }
431
        num = (*f-ARGHEAD-2)/2; /* 2*number of limbs in the argument */
14,754✔
432
        t = (UWORD *)(f+ARGHEAD+1);
14,754✔
433
        while ( num > 1 ) {
47,490✔
434
                *d++ = (mp_limb_t)((((ULONG)(t[1]))<<BITSINWORD)+t[0]);
32,736✔
435
                t += 2; num -= 2;
32,736✔
436
        }
437
        if ( num == 1 ) *d++ = (mp_limb_t)((UWORD)(*t));
14,754✔
438
        for ( i = d-outfloat->_mp_d; i <= outfloat->_mp_prec; i++ ) *d++ = 0;
19,134✔
439
        return(0);
440
Incorrect:
16,650✔
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)
36,660✔
453
{
454
        WORD *fstop, *f, num, nnum, i;
36,660✔
455
        fstop = fun+fun[1];
36,660✔
456
        f = fun + FUNHEAD;
36,660✔
457
        num = 0;
36,660✔
458
/*
459
        Count arguments
460
*/
461
        while ( f < fstop ) { num++; NEXTARG(f); }
183,264✔
462
        if ( num != 4 ) return(0);
36,660✔
463
        f = fun + FUNHEAD;
36,648✔
464
        if ( *f != -SNUMBER ) return(0);
36,648✔
465
        if ( f[1] < 0 ) return(0);
36,636✔
466
        f += 2;
36,636✔
467
        if ( *f != -SNUMBER ) return(0);
36,636✔
468
        num = ABS(f[1]); /* number of limbs */
36,636✔
469
        f += 2;
36,636✔
470
        if ( *f == -SNUMBER ) { f += 2; }
36,636✔
471
        else {
472
                if ( *f != ARGHEAD+6 ) return(0);
648✔
473
                if ( ABS(f[ARGHEAD+5]) != 5 ) return(0);
648✔
474
                if ( f[ARGHEAD+3] != 1 ) return(0);
648✔
475
                if ( f[ARGHEAD+4] != 0 ) return(0);
648✔
476
                f += *f;
648✔
477
        }
478
        if ( num == 0 ) return(1);
36,636✔
479
        if ( *f == -SNUMBER ) { if ( num != 1 ) return(0); }
36,636✔
480
        else {
481
                nnum = (ABS(f[*f-1])-1)/2;
32,886✔
482
                if ( ( *f != 4*num+2+ARGHEAD ) && ( *f != 4*num+ARGHEAD ) ) return(0);
32,886✔
483
                if ( ( nnum != 2*num ) && ( nnum != 2*num-1 ) ) return(0);
32,886✔
484
                f += ARGHEAD+nnum+1;
32,886✔
485
                if ( f[0] != 1 ) return(0);
32,886✔
486
                for ( i = 1; i < nnum; i++ ) {
177,282✔
487
                        if ( f[i] != 0 ) return(0);
144,396✔
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)
9,240✔
512
{
513
        int nlimbs, sgn = 1;
9,240✔
514
        mp_limb_t *d;
9,240✔
515
        UWORD *b = a;
9,240✔
516
        WORD nb = na;
9,240✔
517

518
        if ( nb == 0 ) {
9,240✔
519
                z->_mp_size = 0;
×
520
                z->_mp_d[0] = 0;
×
521
                return;
×
522
        }
523
        if ( nb < 0 ) { sgn = -1; nb = -nb; }
9,240✔
524
        nlimbs = (nb+1)/2;
9,240✔
525
        if ( mpz_cmp_si(z,0L) <= 1 ) {
9,240✔
526
                mpz_set_ui(z,10000000);
9,240✔
527
        }
528
        if ( z->_mp_alloc <= nlimbs ) {
9,240✔
529
                mpz_t zz;
9,240✔
530
                mpz_init(zz);
9,240✔
531
                while ( z->_mp_alloc <= nlimbs ) {
27,786✔
532
                        mpz_mul(zz,z,z);
18,546✔
533
                        mpz_set(z,zz);
18,546✔
534
                }
535
                mpz_clear(zz);
9,240✔
536
        }
537
        z->_mp_size = sgn*nlimbs;
9,240✔
538
        d = z->_mp_d;
9,240✔
539
        while ( nb > 1 ) {
9,750✔
540
                *d++ = (((mp_limb_t)(b[1]))<<BITSINWORD)+(mp_limb_t)(b[0]);
510✔
541
                b += 2; nb -= 2;
510✔
542
        }
543
        if ( nb == 1 ) { *d = (mp_limb_t)(*b); }
9,240✔
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; }
450✔
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)
8,988✔
605
{
606
        mpz_t z;
8,988✔
607
        mpz_init(z);
8,988✔
608
        FormtoZ(z,formlong,longsize);
8,988✔
609
        mpf_set_z(result,z);
8,988✔
610
        mpz_clear(z);
8,988✔
611
}
8,988✔
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)
4,494✔
621
{
622
        GETIDENTITY
2,996✔
623
        int nnum, nden;
4,494✔
624
        UWORD *num, *den;
4,494✔
625
        int sgn = 0;
4,494✔
626
        if ( ratsize < 0 ) { ratsize = -ratsize; sgn = 1; }
4,494✔
627
        nnum = nden = (ratsize-1)/2;
4,494✔
628
        num = formrat; den = formrat+nnum;
4,494✔
629
        while ( num[nnum-1] == 0 ) { nnum--; }
5,322✔
630
        while ( den[nden-1] == 0 ) { nden--; }
4,572✔
631
        IntegerToFloat(aux2,num,nnum);
4,494✔
632
        IntegerToFloat(aux3,den,nden);
4,494✔
633
        mpf_div(result,aux2,aux3);
4,494✔
634
        if ( sgn > 0 ) mpf_neg(result,result);
4,494✔
635
}
4,494✔
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)
1,404✔
823
{
824
        GETIDENTITY
936✔
825
        SBYTE *ss, c;
1,404✔
826
        ss = s;
1,404✔
827
        while ( *ss > 0 ) ss++;
15,768✔
828
        c = *ss; *ss = 0;
1,404✔
829
        gmp_sscanf((char *)s,"%Ff",aux1);
1,404✔
830
        if ( AT.WorkPointer > AT.WorkTop ) {
1,404✔
831
                MLOCK(ErrorMessageLock);
×
832
                MesWork();
×
833
                MUNLOCK(ErrorMessageLock);
×
834
                Terminate(-1);
×
835
        }
836
        PackFloat(AT.WorkPointer,aux1);
1,404✔
837
        *ss = c;
1,404✔
838
        return(ss);
1,404✔
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,296,746✔
849
{
850
        GETIDENTITY
8,864,500✔
851
        UBYTE *s = ss;
13,296,746✔
852
        int zero = 1, gotdot = 0;
13,296,746✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
34,957,168✔
854
        *spec = 0;
13,296,746✔
855
        if ( FG.cTable[*s] == 1 ) {
13,296,746✔
856
                while ( *s == '0' ) s++;
14,942,498✔
857
                if ( FG.cTable[*s] == 1 ) {
13,296,704✔
858
                        s++;
11,650,988✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
20,407,712✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
13,296,704✔
863
        }
864
        else if ( *s == '.' ) {
42✔
865
dot:
42✔
866
                gotdot = 1;
1,404✔
867
                s++;
1,404✔
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
1,404✔
869
                while ( *s == '0' ) s++;
1,902✔
870
                if ( FG.cTable[*s] == 1 ) {
1,404✔
871
                        s++;
1,062✔
872
                        while ( FG.cTable[*s] == 1 ) s++;
2,166✔
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,296,746✔
882
                s++;
834✔
883
                if ( *s == '-' || *s == '+' ) s++;
834✔
884
                if ( FG.cTable[*s] == 1 ) {
834✔
885
                        s++;
834✔
886
                        while ( FG.cTable[*s] == 1 ) s++;
7,596✔
887
                }
888
                else { return(ss); }
889
        }
890
        else if ( gotdot == 0 ) return(ss);
13,295,912✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
1,404✔
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
1,404✔
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)
468✔
915
{
916
        if ( prec <= 0 ) {
468✔
917
                MesPrint("&Illegal value for number of bits for floating point constants: %d",prec);
×
918
                return(-1);
×
919
        }
920
        else {
921
                AC.DefaultPrecision = prec;
468✔
922
                if ( AO.floatspace != 0 ) M_free(AO.floatspace,"floatspace");
468✔
923
                AO.floatsize = (prec+20)*sizeof(char);
468✔
924
                AO.floatspace = (UBYTE *)Malloc1(AO.floatsize,"floatspace");
468✔
925
                mpf_set_default_prec(prec);
468✔
926
                return(0);
468✔
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)
4,260✔
944
{
945
        GETIDENTITY
2,840✔
946
        UBYTE *s1, *s2;
4,260✔
947
        int n = 0;
4,260✔
948
        int prec = (AC.DefaultPrecision-AC.MaxWeight-1)*log10(2.0);
4,260✔
949
        if ( numdigits > prec || numdigits == 0 ) {
4,260✔
950
                numdigits = prec;
3,972✔
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 )
4,260✔
957
                n = gmp_snprintf((char *)(AO.floatspace),AO.floatsize,"%.*Fe",numdigits-1,aux4);
4,260✔
958
        if ( n > 0 ) {
4,260✔
959
                int n1, n2 = n;
4,260✔
960
                s1 = AO.floatspace+n;
4,260✔
961
                while ( s1 > AO.floatspace && s1[-1] != 'e'
27,306✔
962
                 && s1[-1] != 'E' && s1[-1] != '.' ) { s1--; n2--; }
23,046✔
963
                if ( s1 > AO.floatspace && s1[-1] != '.' ) {
4,260✔
964
                        s1--; n2--;
4,260✔
965
                        s2 = s1; n1 = n2;
4,260✔
966
                        while ( s1[-1] == '0' ) { s1--; n1--; }
26,046✔
967
                        if ( s1[-1] == '.' ) { s1++; n1++; }
4,260✔
968
                        n -= (n2-n1);
4,260✔
969
                        while ( n1 < n ) { *s1++ = *s2++; n1++; }
27,306✔
970
                        *s1 = 0;
4,260✔
971
                }
972
                if ( AC.OutputMode == FORTRANMODE ) {
4,260✔
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 ) {
4,260✔
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);
4,260✔
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
                AB[id]->T.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
576✔
1105
                a = (mpf_t *)AB[id]->T.mpf_tab1;
576✔
1106
                for ( i = 0; i <=Nw; i++ ) {
40,496✔
1107
/*
1108
        As explained in the comment above, we could make this variable precision
1109
        using mpf_init2.
1110
*/
1111
                        mpf_init(a[i]);
39,920✔
1112
                }
1113
                AB[id]->T.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
576✔
1114
                a = (mpf_t *)AB[id]->T.mpf_tab2;
576✔
1115
                for ( i = 0; i <=Nw; i++ ) {
40,496✔
1116
                        mpf_init(a[i]);
39,920✔
1117
                }
1118
        }
1119
#else
1120
        int i, Nw;
72✔
1121
        size_t N;
72✔
1122
        Nw = AC.DefaultPrecision;
72✔
1123
        N = (size_t)Nw;
72✔
1124
        AT.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
72✔
1125
        for ( i = 0; i <= Nw; i++ ) {
5,062✔
1126
/*
1127
        As explained in the comment above, we could make this variable precision
1128
        using mpf_init2.
1129
*/
1130
                mpf_init(mpftab1[i]);
4,990✔
1131
        }
1132
        AT.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
72✔
1133
        for ( i = 0; i <= Nw; i++ ) {
5,062✔
1134
                mpf_init(mpftab2[i]);
4,990✔
1135
        }
1136
#endif
1137
        AS.delta_1 = (void *)Malloc1(sizeof(mpf_t),"delta1");
216✔
1138
        mpf_init(mpfdelta1);
216✔
1139
        SimpleDelta(mpfdelta1,1); /* this can speed up things. delta1 = ln(2) */
216✔
1140
}
216✔
1141

1142
/*
1143
                 #] SetupMZVTables : 
1144
                 #[ SetupMPFTables :
1145
        
1146
                Allocates the aux variables
1147
*/
1148

1149
void SetupMPFTables(void)
468✔
1150
{
1151
#ifdef WITHPTHREADS
1152
        int id, totnum;
312✔
1153
        mpf_t *a;
312✔
1154
#ifdef WITHSORTBOTS
1155
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
312✔
1156
#endif
1157
    for ( id = 0; id < totnum; id++ ) {
1,872✔
1158
/*
1159
                We work here with a[0] etc because the aux1 etc contain B which
1160
                in the current routine would be AB[0] only
1161
*/
1162
                AB[id]->T.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AB[id]->T.aux_");
1,560✔
1163
                a = (mpf_t *)AB[id]->T.aux_;
1,560✔
1164
                mpf_inits(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
1,560✔
1165
                if ( AB[id]->T.indi1 ) M_free(AB[id]->T.indi1,"indi1");
1,560✔
1166
                AB[id]->T.indi1 = (WORD *)Malloc1(sizeof(WORD)*AC.MaxWeight*2,"indi1");
1,560✔
1167
                AB[id]->T.indi2 = AB[id]->T.indi1 + AC.MaxWeight;
1,560✔
1168
        }
1169
#else
1170
        AT.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AT.aux_");
156✔
1171
        mpf_inits(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
156✔
1172
        if ( AT.indi1 ) M_free(AT.indi1,"indi1");
156✔
1173
        AT.indi1 = (WORD *)Malloc1(sizeof(WORD)*AC.MaxWeight*2,"indi1");
156✔
1174
        AT.indi2 = AT.indi1 + AC.MaxWeight;
156✔
1175
#endif
1176
}
468✔
1177

1178
/*
1179
                 #] SetupMPFTables : 
1180
                 #[ ClearMZVTables :
1181
*/
1182

1183
void ClearMZVTables(void)
252✔
1184
{
1185
#ifdef WITHPTHREADS
1186
        int i, id, totnum;
168✔
1187
        mpf_t *a;
168✔
1188
        totnum = AM.totalnumberofthreads;
168✔
1189
    for ( id = 0; id < totnum; id++ ) {
840✔
1190
                if ( AB[id]->T.mpf_tab1 ) { 
672✔
1191
/*
1192
                        We work here with a[0] etc because the aux1, mpftab1 etc contain B 
1193
                        which in the current routine would be AB[0] only
1194
*/
1195
                        a = (mpf_t *)AB[id]->T.mpf_tab1;
39,344✔
1196
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
39,344✔
1197
                                mpf_clear(a[i]);
38,784✔
1198
                        }
1199
                        M_free(AB[id]->T.mpf_tab1,"mpftab1"); 
560✔
1200
                        AB[id]->T.mpf_tab1 = 0; 
560✔
1201
                }
1202
                if ( AB[id]->T.mpf_tab2 ) { 
672✔
1203
                        a = (mpf_t *)AB[id]->T.mpf_tab2;
39,344✔
1204
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
39,344✔
1205
                                mpf_clear(a[i]);
38,784✔
1206
                        }
1207
                        M_free(AB[id]->T.mpf_tab2,"mpftab2"); 
560✔
1208
                        AB[id]->T.mpf_tab2 = 0; 
560✔
1209
                }
1210
        }
1211
#ifdef WITHSORTBOTS
1212
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
168✔
1213
#endif
1214
    for ( id = 0; id < totnum; id++ ) {
1,008✔
1215
                if ( AB[id]->T.aux_ ) { 
840✔
1216
                        a = (mpf_t *)AB[id]->T.aux_;
840✔
1217
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
840✔
1218
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
840✔
1219
                        AB[id]->T.aux_ = 0; 
840✔
1220
                }
1221
                if ( AB[id]->T.indi1 ) { M_free(AB[id]->T.indi1,"indi1"); AB[id]->T.indi1 = 0; }
840✔
1222
        }
1223
#else
1224
        int i;
84✔
1225
        if ( AT.mpf_tab1 ) { 
84✔
1226
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
4,918✔
1227
                        mpf_clear(mpftab1[i]);
4,848✔
1228
                }
1229
                M_free(AT.mpf_tab1,"mpftab1"); 
70✔
1230
                AT.mpf_tab1 = 0; 
70✔
1231
        }
1232
        if ( AT.mpf_tab2 ) { 
84✔
1233
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
4,918✔
1234
                        mpf_clear(mpftab2[i]);
4,848✔
1235
                }
1236
                M_free(AT.mpf_tab2,"mpftab2"); 
70✔
1237
                AT.mpf_tab2 = 0; 
70✔
1238
        }
1239
        if ( AT.aux_ ) { 
84✔
1240
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
84✔
1241
                M_free(AT.aux_,"AT.aux_"); 
84✔
1242
                AT.aux_ = 0; 
84✔
1243
        }
1244
        if ( AT.indi1 ) { M_free(AT.indi1,"indi1"); AT.indi1 = 0; }
84✔
1245
#endif
1246
        if ( AO.floatspace ) { M_free(AO.floatspace,"floatspace"); AO.floatspace = 0;
252✔
1247
                AO.floatsize = 0; }
252✔
1248
        if ( AS.delta_1 ) { 
252✔
1249
                mpf_clear(mpfdelta1);
210✔
1250
                M_free(AS.delta_1,"delta1"); 
210✔
1251
                AS.delta_1 = 0; 
210✔
1252
        }
1253
}
252✔
1254

1255
/*
1256
                 #] ClearMZVTables : 
1257
                 #[ CoToFloat :
1258
*/
1259

1260
int CoToFloat(UBYTE *s)
36✔
1261
{
1262
        GETIDENTITY
24✔
1263
        if ( AT.aux_ == 0 ) {
36✔
1264
                MesPrint("&Illegal attempt to convert to float_ without activating floating point numbers.");
6✔
1265
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
1266
                return(1);
6✔
1267
        }
1268
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
30✔
1269
        if ( *s ) {
30✔
1270
                MesPrint("&Illegal argument(s) in ToFloat statement: '%s'",s);
×
1271
                return(1);
×
1272
        }
1273
        Add2Com(TYPETOFLOAT);
30✔
1274
        return(0);
30✔
1275
}
1276

1277
/*
1278
                 #] CoToFloat : 
1279
                 #[ CoToRat :
1280
*/
1281

1282
int CoToRat(UBYTE *s)
12✔
1283
{
1284
        GETIDENTITY
8✔
1285
        if ( AT.aux_ == 0 ) {
12✔
1286
                MesPrint("&Illegal attempt to convert from float_ without activating floating point numbers.");
6✔
1287
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
1288
                return(1);
6✔
1289
        }
1290
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
6✔
1291
        if ( *s ) {
6✔
1292
                MesPrint("&Illegal argument(s) in ToRat statement: '%s'",s);
×
1293
                return(1);
×
1294
        }
1295
        Add2Com(TYPETORAT);
6✔
1296
        return(0);
6✔
1297
}
1298

1299
/*
1300
                 #] CoToRat : 
1301
                 #[ CoStrictRounding : 
1302

1303
                Syntax: StrictRounding [precision][base]
1304
                - precision: number of digits to round to (optional)
1305
                - base: 'd' for decimal (base 10) or 'b' for binary (base 2)
1306
                
1307
                If no arguments are provided, uses default precision with binary base.
1308
*/
1309
int CoStrictRounding(UBYTE *s)
42✔
1310
{
1311
        GETIDENTITY
28✔
1312
        WORD x;
42✔
1313
        int base;
42✔
1314
        if ( AT.aux_ == 0 ) {
42✔
1315
                MesPrint("&Illegal attempt for strict rounding without activating floating point numbers.");
6✔
1316
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
1317
                return(1);
6✔
1318
        }
1319
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
36✔
1320
        if ( *s == 0 ) {
36✔
1321
                /* No subkey, which means round to default precision */
1322
                x = AC.DefaultPrecision - AC.MaxWeight - 1;
6✔
1323
                base = 2;
6✔
1324
        }
1325
        else if ( FG.cTable[*s] == 1 ) { /* number */
30✔
1326
                ParseNumber(x,s)
48✔
1327
                if ( tolower(*s) == 'd' ) { base = 10; s++; }      /* decimal base */
24✔
1328
                else if ( tolower(*s) == 'b' ){ base = 2; s++; }  /* binary base */
18✔
1329
                else goto IllPar;  /* invalid base specification */
12✔
1330
        }
1331
        else {
1332
                goto IllPar;
6✔
1333
        }
1334
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
18✔
1335
        
1336
        /* Check for invalid arguments */
1337
        if ( *s ) {
18✔
1338
IllPar:
×
1339
                MesPrint("&Illegal argument(s) in StrictRounding statement: '%s'",s);
18✔
1340
                return(1);
18✔
1341
        }
1342
        Add4Com(TYPESTRICTROUNDING,x,base);
18✔
1343
        return(0);
18✔
1344
} 
1345
/*
1346
                 #] CoStrictRounding : 
1347
                 #[ CoChop :
1348

1349
                LHS notation of the chop statement: 
1350
                        TYPECHOP, length, FLOATFUN, ... 
1351
                where FLOATFUN, ... represents the threshold of the chop statement in 
1352
                the notation of a float_ function with its arguments. 
1353

1354
*/
1355

1356
int CoChop(UBYTE *s)
30✔
1357
{
1358
        GETIDENTITY
20✔
1359
        UBYTE *ss, c;
30✔
1360
        WORD *w, *OldWork;
30✔
1361
        int spec, pow = 1;
30✔
1362
        unsigned long x;
30✔
1363
        if ( AT.aux_ == 0 ) {
30✔
1364
                MesPrint("&Illegal attempt to chop a float_ without activating floating point numbers.");
×
1365
                MesPrint("&Forgotten %#startfloat instruction?");
×
1366
                return(1);
×
1367
        }
1368
        if ( *s == 0 ) {
30✔
1369
                MesPrint("&Chop needs a number (float or rational) as an argument.");
×
1370
                return(1);
×
1371
        }
1372
        /* Create TYPECHOP header */
1373
        w = OldWork = AT.WorkPointer;
30✔
1374
        *w++ = TYPECHOP; 
30✔
1375
        w++;
30✔
1376

1377
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
30✔
1378
        
1379
        /* 
1380
                The argument of chop can be 
1381
                 1: a floating-point number
1382
                 2: an integer, rational number or power
1383
         */
1384
        if ( FG.cTable[*s] == 1 || *s == '.' ) { 
30✔
1385
                /* 1: Attempt to parse as floating-point number */
1386
                ss = CheckFloat(s, &spec);
30✔
1387
                if ( ss > s ) {
30✔
1388
                        /* CheckFloat found a valid float */
1389
                        if ( spec == 1 ) { /* Zero */
6✔
1390
                                MesPrint("&The argument in Chop needs to be larger than 0.");
×
1391
                                return(1);
×
1392
                        }
1393
                        else if ( spec == -1 ) { 
6✔
1394
                                MesPrint("&The floating point system has not been started.");
×
1395
                                return(1);
×
1396
                        }
1397
                        else {
1398
                                AT.WorkPointer = w;
6✔
1399
                                /* 
1400
                                        Reads the floating point number and outputs it at AT.WorkPointer as if it were a float_ 
1401
                                        function with its arguments.
1402
                                 */
1403
                                ReadFloat((SBYTE *)s); 
6✔
1404
                                s = ss;
6✔
1405
                                w += w[1];
6✔
1406
                        }
1407
                }
1408
                else {
1409
                        /* 2: CheckFloat didn't find a float, we now try for rationals and powers */
1410
                        /* Parse the integer part (numerator for rationals) */
1411
                        if ( FG.cTable[*s] == 1 ) {
24✔
1412
                                ParseNumber(x,s)
60✔
1413
                                mpf_set_ui(aux1,x);
24✔
1414
                        }
1415
                        if ( mpf_sgn(aux1) == 0 ) {
24✔
1416
                                MesPrint("&The argument in Chop needs to be larger than 0.");
×
1417
                                return(1);
×
1418
                        }
1419
                        while ( *s == ' ' || *s == '\t' ) s++;
24✔
1420
                        /* Check for rational number or power*/
1421
                        if ( *s == '/' || *s == '^' ) {
24✔
1422
                                c = *s; s++; 
18✔
1423
                                while ( *s == ' ' || *s == '\t' ) s++;
18✔
1424
                                if ( *s == '-' ) { s++; pow = -1; } /* negative power */
18✔
1425
                                /* Parse the denominator or power */
1426
                                if ( FG.cTable[*s] == 1 ) {
18✔
1427
                                        ParseNumber(x,s)
60✔
1428
                                        if ( c == '/' ) { /* rational */
18✔
1429
                                                if ( x == 0 ) {
6✔
1430
                                                        MesPrint("&Division by zero in chop statement.");
×
1431
                                                        return(1);
×
1432
                                                }
1433
                                                /* Perform the division */
1434
                                                mpf_div_ui(aux1, aux1,x);
6✔
1435
                                        }
1436
                                        else { /* Power */
1437
                                                mpf_pow_ui(aux1,aux1,x);
12✔
1438
                                                if ( pow == -1 ) {
12✔
1439
                                                        mpf_ui_div(aux1,(unsigned long) 1, aux1);
6✔
1440
                                                }
1441
                                        }
1442
                                }
1443
                        }
1444
                        /* Put aux1 in the notation of a float_ function */
1445
                        PackFloat(w, aux1);
24✔
1446
                        w += w[1];
24✔
1447
                }
1448
        }
1449
        if ( *s ) {
30✔
1450
                MesPrint("&Illegal argument(s) in Chop statement: '%s'",s);
×
1451
                return(1);
×
1452
        }
1453
        AT.WorkPointer = OldWork;
30✔
1454
        AT.WorkPointer[1] = w - AT.WorkPointer;  /* Set total length */
30✔
1455
        AddNtoL(AT.WorkPointer[1],AT.WorkPointer); /* Add the LHS to the compiler buffer */
30✔
1456
        return(0);
30✔
1457
}
1458

1459
/*
1460
                 #] CoChop : 
1461
                 #[ ToFloat :
1462

1463
                Converts the coefficient to floating point if it is still a rat.
1464
*/
1465

1466
int ToFloat(PHEAD WORD *term, WORD level)
282✔
1467
{
1468
        WORD *t, *tstop, nsize, nsign = 3;
282✔
1469
        t = term+*term;
282✔
1470
        nsize = ABS(t[-1]);
282✔
1471
        tstop = t - nsize;
282✔
1472
        if ( t[-1] < 0 ) { nsign = -nsign; }
282✔
1473
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
282✔
1474
                t = term + 1;
144✔
1475
                while ( t < tstop ) {
282✔
1476
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
138✔
1477
                                return(Generator(BHEAD term,level));
×
1478
                        }
1479
                        t += t[1];
138✔
1480
                }
1481
        }
1482
        RatToFloat(aux4,(UWORD *)tstop,nsize);
282✔
1483
        PackFloat(tstop,aux4);
282✔
1484
        tstop += tstop[1];
282✔
1485
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
282✔
1486
        *term = tstop - term;
282✔
1487
        AT.WorkPointer = tstop;
282✔
1488
        return(Generator(BHEAD term,level));
282✔
1489
}
1490

1491
/*
1492
                 #] ToFloat : 
1493
                 #[ ToRat :
1494

1495
                Tries to convert the coefficient to rational if it is still a float.
1496
*/
1497

1498
int ToRat(PHEAD WORD *term, WORD level)
6✔
1499
{
1500
        WORD *tstop, *t, nsize, nsign, ncoef;
6✔
1501
/*
1502
        1: find the float which should be at the end.
1503
*/
1504
        tstop = term + *term; nsize = ABS(tstop[-1]);
6✔
1505
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
6✔
1506
        t = term+1;
6✔
1507
        while ( t < tstop ) {
6✔
1508
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
6✔
1509
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
6✔
1510
                t += t[1];
×
1511
        }
1512
        if ( t < tstop ) {
6✔
1513
/*
1514
                Now t points at the float_ function and everything is correct.
1515
                The result can go straight over the float_ function.
1516
*/
1517
                UnpackFloat(aux4,t);
6✔
1518
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
6✔
1519
                        t += ABS(ncoef);
6✔
1520
                        t[-1] = ncoef*nsign;
6✔
1521
                        *term = t - term;
6✔
1522
                }
1523
        }
1524
        return(Generator(BHEAD term,level));
6✔
1525
}
1526

1527
/*
1528
                 #] ToRat : 
1529
                 #[ StrictRounding : 
1530

1531
                Rounds floating point numbers to a specified precision
1532
                in a given base (decimal or binary).
1533
*/
1534
int StrictRounding(PHEAD WORD *term, WORD level, WORD prec, WORD base) {
36✔
1535
        WORD *t,*tstop;
36✔
1536
        int sign,size,maxprec = AC.DefaultPrecision-AC.MaxWeight-1;
36✔
1537
        /* maxprec is in bits */
1538
        if ( base == 2 && prec > maxprec ) {
36✔
1539
                prec = maxprec;
1540
        }
1541
        if ( base == 10 && prec > (int)(maxprec*log10(2.0)) ) {
36✔
1542
                prec = maxprec*log10(2.0);
×
1543
        }
1544
        /* Find the float which should be at the end. */
1545
        tstop = term + *term; size = ABS(tstop[-1]);
36✔
1546
        sign = tstop[-1] < 0 ? -1: 1; tstop -= size;
36✔
1547
        t = term+1;
36✔
1548
        while ( t < tstop ) {
48✔
1549
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
36✔
1550
                size == 3 && tstop[0] == 1 && tstop[1] == 1) {
24✔
1551
                        break;
1552
                }
1553
                t += t[1];
12✔
1554
        }
1555
        if ( t < tstop ) {
36✔
1556
/*
1557
                Now t points at the float_ function and everything is correct.
1558
                The result can go straight over the float_ function.
1559
*/
1560
                char *s;
24✔
1561
                mp_exp_t exp;
24✔
1562
                /* Extract the floating point value */
1563
                UnpackFloat(aux4,t);
24✔
1564
                /* Convert to string: 
1565
                   - Format as MeN with M the mantissa and N the exponent 
1566
                   - the generated string by mpf_get_str is the fraction/mantissa with 
1567
                   an implicit radix point immediately to the left of the first digit. 
1568
                   The applicable exponent is written in exp. */
1569
                s = (char *)AO.floatspace;
24✔
1570
                *s++ = '.';
24✔
1571
                mpf_get_str(s,&exp, base, prec, aux4);
24✔
1572
                while ( *s != 0 ) s++;
90✔
1573
                *s++ = 'e';
24✔
1574
                snprintf(s,AO.floatsize-(s-(char *)AO.floatspace),"%ld",exp);
24✔
1575
                /* Negative base values are used to specify that the exponent is in decimal */
1576
                mpf_set_str(aux4,(char *)AO.floatspace,-base);
24✔
1577
                /* Pack the rounded floating point value back into the term */
1578
                PackFloat(t,aux4);
24✔
1579
                t+=t[1];
24✔
1580
                *t++ = 1; *t++ = 1; *t++ = 3*sign;
24✔
1581
                *term = t - term;
24✔
1582
        }
1583
        return(Generator(BHEAD term,level));
36✔
1584
}
1585
/*
1586
                 #] StrictRounding : 
1587
                 #[ Chop :
1588

1589
        Removes terms with a floating point number smaller than a given threshold. 
1590
 
1591
        Search for a FLOATFUN and compares its absolute value against the threshold 
1592
        specified in the chop statement. This threshold can be obtained from the 
1593
        LHS of the chop statement in the compiler buffer.
1594
 
1595
 */
1596
int Chop(PHEAD WORD *term, WORD level)
150✔
1597
{
1598
        WORD *tstop, *t, nsize, *threshold; 
150✔
1599
        CBUF *C = cbuf+AM.rbufnum;
150✔
1600
        /* Find the float which should be at the end. */
1601
        tstop = term + *term; 
150✔
1602
        nsize = ABS(tstop[-1]); tstop -= nsize;
150✔
1603
        t = term+1;
150✔
1604
        while ( t < tstop ) {
300✔
1605
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
270✔
1606
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
120✔
1607
                t += t[1];
150✔
1608
        }
1609
        if ( t < tstop ) {
150✔
1610
                /* Get threshold value from compiler buffer */
1611
                threshold = C->lhs[level];
120✔
1612
                threshold += 2;  /* Skip TYPECHOP header */
120✔
1613
                UnpackFloat(aux5, threshold); 
120✔
1614
                
1615
                /* Extract float and compute its absolute value */
1616
                UnpackFloat(aux4, t);
120✔
1617
                mpf_abs(aux4, aux4);
120✔
1618
                
1619
                /* Remove if < threshold */
1620
                if ( mpf_cmp(aux4, aux5) < 0 ) return(0);
120✔
1621
        }
1622
        return(Generator(BHEAD term,level));
66✔
1623
}
1624

1625
/*
1626
                 #] Chop : 
1627
          #] Float Routines : 
1628
          #[ Sorting :
1629

1630
                We need a method to see whether two terms need addition that could
1631
                involve floating point numbers.
1632
                1: if PolyWise is active, we do not need anything, because
1633
                   Poly(Rat)Fun and floating point are mutually exclusive.
1634
                2: This means that there should be only interference in AddCoef.
1635
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1636
                   and PF_GetLoser.
1637
                The compare routine(s) should recognise the float_ and give off
1638
                a code (SortFloatMode) inside the AT struct:
1639
                0: no float_
1640
                1: float_ in term1 only
1641
                2: float_ in term2 only
1642
                3: float_ in both terms
1643
                Be careful: we have several compare routines, because various codes
1644
                use their own routines and we just set a variable with its address.
1645
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1646
                Only Compare1 should be active for this. The others should make sure
1647
                that the proper variable is always zero.
1648
                Remember: the sign of the coefficient is in the last word of the term.
1649

1650
                We need two routines:
1651
                1: AddWithFloat for SplitMerge which sorts by pointer.
1652
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1653
                   as possible in their location.
1654
                The routines start out the same, because AT.SortFloatMode, set in
1655
                Compare1, tells more or less what should be done.
1656
                The difference is in where we leave the result.
1657

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

1662
                 #[ AddWithFloat :
1663
*/
1664

1665
int AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
2,424✔
1666
{
1667
        GETBIDENTITY
1668
        SORTING *S = AT.SS;
2,424✔
1669
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
2,424✔
1670
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
2,424✔
1671
        s1 = *ps1;
2,424✔
1672
        s2 = *ps2;
2,424✔
1673
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
2,424✔
1674
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
2,424✔
1675
        if ( AT.SortFloatMode == 3 ) {
2,424✔
1676
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
3,534✔
1677
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
3,534✔
1678
                UnpackFloat(aux1,fun1);
1,836✔
1679
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
1,836✔
1680
                UnpackFloat(aux2,fun2);
1,836✔
1681
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
1,836✔
1682
        }
1683
        else if ( AT.SortFloatMode == 1 ) {
588✔
1684
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
300✔
1685
                UnpackFloat(aux1,fun1);
150✔
1686
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
150✔
1687
                fun2 = coef2;
150✔
1688
                RatToFloat(aux2,(UWORD *)coef2,size2);
150✔
1689
        }
1690
        else if ( AT.SortFloatMode == 2 ) {
438✔
1691
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
876✔
1692
                fun1 = coef1;
438✔
1693
                RatToFloat(aux1,(UWORD *)coef1,size1);
438✔
1694
                UnpackFloat(aux2,fun2);
438✔
1695
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
438✔
1696
        }
1697
        else {
1698
                MLOCK(ErrorMessageLock);
×
1699
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1700
                MUNLOCK(ErrorMessageLock);
×
1701
                Terminate(-1);
×
1702
                return(0);
×
1703
        }
1704
        mpf_add(aux3,aux1,aux2);
2,424✔
1705
        sign3 = mpf_sgn(aux3);
2,424✔
1706
        if ( sign3 == 0 ) {        /* May be rare! */
1,368✔
1707
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
486✔
1708
        }
1709
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
1,938✔
1710
        fun3 = TermMalloc("AddWithFloat");
1,938✔
1711
        PackFloat(fun3,aux3);
1,938✔
1712
/*
1713
        Now we have to calculate where the sumterm fits.
1714
        If we are sloppy, we can be faster, but run the risk to need the
1715
        extension space, even when it is not needed. At slightly lower speed
1716
        (ie first creating the result in scribble space) we are better off.
1717
        This is why we use TermMalloc.
1718

1719
        The new term will have a rational coefficient of 1,1,+-3.
1720
        The size will be (fun1 or fun2 - term) + fun3 +3;
1721
*/
1722
        if ( AT.SortFloatMode == 3 ) {
1,938✔
1723
                if ( fun1[1] == fun3[1]  ) {
1,446✔
1724
Over1:
360✔
1725
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
27,444✔
1726
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
1,428✔
1727
                        *s1 = t1-s1; goto Finished;
1,428✔
1728
                }
1729
                else if ( fun2[1] == fun3[1]  ) {
1,086✔
1730
Over2:
150✔
1731
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
8,676✔
1732
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
498✔
1733
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
498✔
1734
                }
1735
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
936✔
1736
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
12✔
1737
        }
1738
        else if ( AT.SortFloatMode == 1 ) {
492✔
1739
                if ( fun1[1] >= fun3[1]  ) goto Over1;
144✔
1740
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1741
        }
1742
        else if ( AT.SortFloatMode == 2 ) {
348✔
1743
                if ( fun2[1] >= fun3[1]  ) goto Over2;
348✔
1744
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
6✔
1745
        }
1746
/*
1747
        Does not fit. Go to extension space.
1748
*/
1749
        jj = fun1-s1;
12✔
1750
        j = jj+fun3[1]+3; /* space needed */
12✔
1751
        if ( (S->sFill + j) >= S->sTop2 ) {
12✔
1752
                GarbHand();
×
1753
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1754
                fun1 = s1+jj;
×
1755
        }
1756
        t1 = S->sFill;
12✔
1757
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
60✔
1758
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
456✔
1759
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
12✔
1760
        *ps1 = S->sFill;
12✔
1761
        **ps1 = t1-*ps1;
12✔
1762
        S->sFill = t1;
12✔
1763
Finished:
1,938✔
1764
        *ps2 = 0;
1,938✔
1765
        TermFree(fun3,"AddWithFloat");
1,938✔
1766
        AT.SortFloatMode = 0;
1,938✔
1767
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
1,938✔
1768
                MLOCK(ErrorMessageLock);
×
1769
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1770
                AM.MaxTer/sizeof(WORD));
×
1771
                MUNLOCK(ErrorMessageLock);
×
1772
                Terminate(-1);
×
1773
        }
1774
        return(1);
1775
}
1776

1777
/*
1778
                 #] AddWithFloat : 
1779
                 #[ MergeWithFloat :
1780

1781
                Note that we always park the result on top of term1.
1782
                This makes life easier, because the original AddRat in MergePatches
1783
                does this as well.
1784
*/
1785

1786
int MergeWithFloat(PHEAD WORD **interm1, WORD **interm2)
2,040✔
1787
{
1788
        GETBIDENTITY
1789
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3, *tt;
2,040✔
1790
        WORD sign3,jj, *t1, *t2, i, *term1 = *interm1, *term2 = *interm2;
2,040✔
1791
        int retval = 0;
2,040✔
1792
        coef1 = term1+*term1; size1 = coef1[-1]; coef1 -= ABS(size1);
2,040✔
1793
        coef2 = term2+*term2; size2 = coef2[-1]; coef2 -= ABS(size2);
2,040✔
1794
        if ( AT.SortFloatMode == 3 ) {
2,040✔
1795
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
2,820✔
1796
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
2,820✔
1797
                UnpackFloat(aux1,fun1);
1,410✔
1798
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
1,410✔
1799
                UnpackFloat(aux2,fun2);
1,410✔
1800
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
1,410✔
1801
        }
1802
        else if ( AT.SortFloatMode == 1 ) {
630✔
1803
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
600✔
1804
                UnpackFloat(aux1,fun1);
300✔
1805
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
300✔
1806
                fun2 = coef2;
300✔
1807
                RatToFloat(aux2,(UWORD *)coef2,size2);
300✔
1808
        }
1809
        else if ( AT.SortFloatMode == 2 ) {
330✔
1810
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
660✔
1811
                fun1 = coef1;
330✔
1812
                RatToFloat(aux1,(UWORD *)coef1,size1);
330✔
1813
                UnpackFloat(aux2,fun2);
330✔
1814
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
330✔
1815
        }
1816
        else {
1817
                MLOCK(ErrorMessageLock);
×
1818
                MesPrint("Illegal value %d for AT.SortFloatMode in MergeWithFloat.",AT.SortFloatMode);
×
1819
                MUNLOCK(ErrorMessageLock);
×
1820
                Terminate(-1);
×
1821
                return(0);
×
1822
        }
1823
        mpf_add(aux3,aux1,aux2);
2,040✔
1824
        sign3 = mpf_sgn(aux3);
2,040✔
1825
        if ( sign3 == 0 ) {        /* May be very rare! */
1,224✔
1826
                AT.SortFloatMode = 0; return(0);
468✔
1827
        }
1828
/*
1829
        Now check whether we can park the result on top of one of the input terms.
1830
*/
1831
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
1,572✔
1832
        fun3 = TermMalloc("MergeWithFloat");
1,572✔
1833
        PackFloat(fun3,aux3);
1,572✔
1834
        if ( AT.SortFloatMode == 3 ) {
1,572✔
1835
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) {
1,068✔
1836
OnTopOf1:        t1 = fun3; t2 = fun1;
246✔
1837
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
3,432✔
1838
                        *t2++ = 1; *t2++ = 1; *t2++ = sign3 < 0 ? -3: 3;
258✔
1839
                        retval = 1;
258✔
1840
                }
1841
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) {
822✔
1842
Shift1:                t2 = term1 + *term1; tt = t2;
804✔
1843
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
1,044✔
1844
                        t1 = fun3 + fun3[1]; for ( i = 0; i < fun3[1]; i++ ) *--t2 = *--t1;
16,512✔
1845
                        t1 = fun1;
1846
                        while ( t1 > term1 ) *--t2 = *--t1;
8,928✔
1847
                        *t2 = tt-t2; term1 = t2;
1,044✔
1848
                        retval = 1;
1,044✔
1849
                }
1850
                else { /* Here we have to move term1 to the left to make room. */
1851
                        jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
18✔
1852
Over1:                t2 = term1-jj; t1 = term1;
270✔
1853
                        while ( t1 < fun1 ) *t2++ = *t1++;
2,220✔
1854
                        term1 -= jj;
270✔
1855
                        *term1 += jj;
270✔
1856
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = fun3[i];
4,104✔
1857
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
270✔
1858
                        retval = 1;
270✔
1859
                }
1860
        }
1861
        else if ( AT.SortFloatMode == 1 ) {
504✔
1862
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) goto OnTopOf1;
252✔
1863
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) goto Shift1;
240✔
1864
                else {
1865
                        jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
6✔
1866
                        goto Over1;
6✔
1867
                }
1868
        }
1869
        else { /* Can only be 2, based on previous tests */
1870
                if ( fun3[1] + 3 == ABS(size1) ) goto OnTopOf1;
252✔
1871
                else if ( fun3[1] + 3 < ABS(size1) ) goto Shift1;
252✔
1872
                else {
1873
                        jj = fun3[1]+3-ABS(size1); /* This is positive */
246✔
1874
                        goto Over1;
246✔
1875
                }
1876
        }
1877
        *interm1 = term1;
1,572✔
1878
        TermFree(fun3,"MergeWithFloat");
1,572✔
1879
        AT.SortFloatMode = 0;
1,572✔
1880
        return(retval);
1,572✔
1881
}
1882

1883
/*
1884
                 #] MergeWithFloat : 
1885
          #] Sorting : 
1886
          #[ MZV :
1887

1888
                The functions here allow the arbitrary precision calculation
1889
                of MZV's and Euler sums.
1890
                They are called when the functions mzv_ and/or euler_ are used
1891
                and the evaluate statement is applied.
1892
                The output is in a float_ function.
1893
                The expand statement tries to express the functions in terms of a basis.
1894
                The bases are the 'standard basis for the euler sums and the
1895
                pushdown bases from the datamine, unless otherwise specified.
1896

1897
                 #[ SimpleDelta :
1898
*/
1899

1900
void SimpleDelta(mpf_t sum, int m)
2,910✔
1901
{
1902
        long s = 1;
2,910✔
1903
        long prec = AC.DefaultPrecision;
2,910✔
1904
        unsigned long xprec = (unsigned long)prec, x;
2,910✔
1905
        int j, jmax, n;
2,910✔
1906
        mpf_t jm,jjm;
2,910✔
1907
        mpf_init(jm); mpf_init(jjm);
2,910✔
1908
        if ( m < 0 ) { s = -1; m = -m; }
2,910✔
1909

1910
/*
1911
        We will loop until 1/2^j/j^m is smaller than the default precision.
1912
        Just running to prec is however overkill, specially when m is large.
1913
        We try to estimate a better value.
1914
        jmax = prec - ((log2(prec)-1)*m).
1915
        Hence we need the leading bit of prec.
1916
        We are still overshooting a bit.
1917
*/
1918
        n = 0; x = xprec;
2,910✔
1919
        while ( x ) { x >>= 1; n++; }
27,042✔
1920
/* 
1921
        We have now n = floor(log2(x))+1. 
1922
*/
1923
        n--;
2,910✔
1924
        jmax = (int)((int)xprec - (n-1)*m);
2,910✔
1925
/*
1926
        For small prec and large m, the estimate can be wrong and even be negative, 
1927
        so we increase jmax until jmax + m*log2(jmax) > prec
1928
*/
1929
        if ( jmax < 0 ) jmax = 1;
2,910✔
1930
        do {
2,910✔
1931
                n = 0;
2,910✔
1932
                x = (unsigned long)jmax;
2,910✔
1933
                while (x) { x >>= 1; n++; }
25,350✔
1934
                n--; // floor(log2(jmax))
2,910✔
1935
                jmax++; 
2,910✔
1936
        } while ( jmax + m * n <= prec );
2,910✔
1937
        mpf_set_ui(sum,0);
2,910✔
1938
        for ( j = 1; j <= jmax; j++ ) {
795,132✔
1939
#ifdef WITHCUTOFF
1940
                xprec--;
789,312✔
1941
                mpf_set_prec_raw(jm,xprec);
789,312✔
1942
                mpf_set_prec_raw(jjm,xprec);
789,312✔
1943
#endif
1944
                mpf_set_ui(jm,1L);
789,312✔
1945
                mpf_div_ui(jjm,jm,(unsigned long)j);
789,312✔
1946
                mpf_pow_ui(jm,jjm,(unsigned long)m);
789,312✔
1947
                mpf_div_2exp(jjm,jm,(unsigned long)j);
789,312✔
1948
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
789,312✔
1949
                else                       mpf_add(sum,sum,jjm);
780,564✔
1950
        }
1951
        mpf_clear(jjm); mpf_clear(jm);
2,910✔
1952
}
2,910✔
1953

1954
/*
1955
                 #] SimpleDelta : 
1956
                 #[ SimpleDeltaC :
1957
*/
1958

1959
void SimpleDeltaC(mpf_t sum, int m)
240✔
1960
{
1961
        long s = 1;
240✔
1962
        long prec = AC.DefaultPrecision;
240✔
1963
        unsigned long xprec = (unsigned long)prec, x;
240✔
1964
        int j, jmax, n;
240✔
1965
        mpf_t jm,jjm;
240✔
1966
        mpf_init(jm); mpf_init(jjm);
240✔
1967
        if ( m < 0 ) { s = -1; m = -m; }
240✔
1968
/*
1969
        We will loop until 1/2^j/j^m is smaller than the default precision.
1970
        Just running to prec is however overkill, specially when m is large.
1971
        We try to estimate a better value.
1972
        jmax = prec - ((log2(prec)-1)*m).
1973
        Hence we need the leading bit of prec.
1974
        We are still overshooting a bit.
1975
*/
1976
        n = 0; x = xprec;
240✔
1977
        while ( x ) { x >>= 1; n++; }
1,920✔
1978
/* 
1979
        We have now n = floor(log2(x))+1. 
1980
*/
1981
        n--;
240✔
1982
        jmax = (int)((int)xprec - (n-1)*m);
240✔
1983
/*
1984
        For small prec and large m, the estimate can be wrong and even be negative, 
1985
        so we increase jmax until jmax + m*log2(jmax) > prec
1986
*/
1987
        if ( jmax < 0 ) jmax = 1;
240✔
1988
        do {
240✔
1989
                n = 0;
240✔
1990
                x = (unsigned long)jmax;
240✔
1991
                while (x) { x >>= 1; n++; }
1,908✔
1992
                n--; // floor(log2(jmax))
240✔
1993
                jmax++; 
240✔
1994
        } while ( jmax + m * n <= prec );
240✔
1995
        if ( s < 0 ) jmax /= 2;
240✔
1996
        mpf_set_si(sum,0L);
240✔
1997
        for ( j = 1; j <= jmax; j++ ) {
9,084✔
1998
#ifdef WITHCUTOFF
1999
                xprec--;
8,604✔
2000
                mpf_set_prec_raw(jm,xprec);
8,604✔
2001
                mpf_set_prec_raw(jjm,xprec);
8,604✔
2002
#endif
2003
                mpf_set_ui(jm,1L);
8,604✔
2004
                mpf_div_ui(jjm,jm,(unsigned long)j);
8,604✔
2005
                mpf_pow_ui(jm,jjm,(unsigned long)m);
8,604✔
2006
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
8,604✔
2007
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
2008
                mpf_add(sum,sum,jjm);
8,604✔
2009
        }
2010
        mpf_clear(jjm); mpf_clear(jm);
240✔
2011
}
240✔
2012

2013
/*
2014
                 #] SimpleDeltaC : 
2015
                 #[ SingleTable :
2016
*/
2017

2018
void SingleTable(mpf_t *tabl, int N, int m, int pow)
3,606✔
2019
{
2020
/*
2021
        Creates a table T(1,...,N) with
2022
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
2023
        To make this table we have two options:
2024
        1: run the sum backwards with the potential problem that the 
2025
           precision is difficult to manage.
2026
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
2027
        When doing Euler sums we may need also 1/4^j
2028
        pow: 1 -> 1/2^j
2029
             2 -> 1/4^j
2030
*/
2031
        GETIDENTITY
2,404✔
2032
        long s = 1;
3,606✔
2033
        int j;
3,606✔
2034
#ifdef WITHCUTOFF
2035
        long prec = mpf_get_default_prec();
3,606✔
2036
#endif
2037
        mpf_t jm,jjm;
3,606✔
2038
        mpf_init(jm); mpf_init(jjm);
3,606✔
2039
        if ( pow < 1 || pow > 2 ) {
3,606✔
2040
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2041
                exit(-1);
×
2042
        }
2043
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
2044
        mpf_set_si(auxsum,0L);
3,606✔
2045
        for ( j = N; j > 0; j-- ) {
779,850✔
2046
#ifdef WITHCUTOFF
2047
                mpf_set_prec_raw(jm,prec-j);
772,638✔
2048
                mpf_set_prec_raw(jjm,prec-j);
772,638✔
2049
#endif
2050
                mpf_set_ui(jm,1L);
772,638✔
2051
                mpf_div_ui(jjm,jm,(unsigned long)j);
772,638✔
2052
                mpf_pow_ui(jm,jjm,(unsigned long)m);
772,638✔
2053
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
772,638✔
2054
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
772,638✔
2055
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
740,982✔
2056
                else                       mpf_add(auxsum,auxsum,jjm);
725,286✔
2057
/*
2058
                And now copy auxsum to tablelement j
2059
*/
2060
                mpf_set(tabl[j],auxsum);
772,638✔
2061
        }
2062
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
2063
}
3,606✔
2064

2065
/*
2066
                 #] SingleTable : 
2067
                 #[ DoubleTable :
2068
*/
2069

2070
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
4,674✔
2071
{
2072
        GETIDENTITY
3,116✔
2073
        long s = 1;
4,674✔
2074
#ifdef WITHCUTOFF
2075
        long prec = mpf_get_default_prec();
4,674✔
2076
#endif
2077
        int j;
4,674✔
2078
        mpf_t jm,jjm;
4,674✔
2079
        mpf_init(jm); mpf_init(jjm);
4,674✔
2080
        if ( pow < -1 || pow > 2 ) {
4,674✔
2081
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2082
                exit(-1);
×
2083
        }
2084
        if ( m < 0 ) { m = -m; s = -1; }
4,674✔
2085
        mpf_set_ui(auxsum,0L);
4,674✔
2086
        for ( j = N; j > 0; j-- ) {
1,709,796✔
2087
#ifdef WITHCUTOFF
2088
                mpf_set_prec_raw(jm,prec-j);
1,700,448✔
2089
                mpf_set_prec_raw(jjm,prec-j);
1,700,448✔
2090
#endif
2091
                mpf_set_ui(jm,1L);
1,700,448✔
2092
                mpf_div_ui(jjm,jm,(unsigned long)j);
1,700,448✔
2093
                mpf_pow_ui(jm,jjm,(unsigned long)m);
1,700,448✔
2094
                if ( pow == -1 ) {
1,700,448✔
2095
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
8,232✔
2096
                        mpf_mul(jm,jjm,tabin[j+1]);
8,232✔
2097
                }
2098
                else if ( pow > 0 ) {
1,692,216✔
2099
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
3,648✔
2100
                        mpf_mul(jm,jjm,tabin[j+1]);
3,648✔
2101
                }
2102
                else {
2103
                        mpf_mul(jm,jm,tabin[j+1]);
1,688,568✔
2104
                }
2105
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
1,700,448✔
2106
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
1,700,448✔
2107
                else                       mpf_add(auxsum,auxsum,jm);
1,694,496✔
2108
/*
2109
                And now copy auxsum to tablelement j
2110
*/
2111
                mpf_set(tabout[j],auxsum);
1,700,448✔
2112
        }
2113
        mpf_clear(jjm); mpf_clear(jm);
4,674✔
2114
}
4,674✔
2115

2116
/*
2117
                 #] DoubleTable : 
2118
                 #[ EndTable :
2119
*/
2120

2121
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
3,606✔
2122
{
2123
        long s = 1;
3,606✔
2124
#ifdef WITHCUTOFF
2125
        long prec = mpf_get_default_prec();
3,606✔
2126
#endif
2127
        int j;
3,606✔
2128
        mpf_t jm,jjm;
3,606✔
2129
        mpf_init(jm); mpf_init(jjm);
3,606✔
2130
        if ( pow < -1 || pow > 2 ) {
3,606✔
2131
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2132
                exit(-1);
×
2133
        }
2134
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
2135
        mpf_set_si(sum,0L);
3,606✔
2136
        for ( j = N; j > 0; j-- ) {
770,970✔
2137
#ifdef WITHCUTOFF
2138
                mpf_set_prec_raw(jm,prec-j);
763,758✔
2139
                mpf_set_prec_raw(jjm,prec-j);
763,758✔
2140
#endif
2141
                mpf_set_ui(jm,1L);
763,758✔
2142
                mpf_div_ui(jjm,jm,(unsigned long)j);
763,758✔
2143
                mpf_pow_ui(jm,jjm,(unsigned long)m);
763,758✔
2144
                if ( pow == -1 ) {
763,758✔
2145
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
13,050✔
2146
                        mpf_mul(jm,jjm,tabin[j+1]);
13,050✔
2147
                }
2148
                else if ( pow > 0 ) {
750,708✔
2149
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
11,700✔
2150
                        mpf_mul(jm,jjm,tabin[j+1]);
11,700✔
2151
                }
2152
                else {
2153
                        mpf_mul(jm,jm,tabin[j+1]);
739,008✔
2154
                }
2155
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
763,758✔
2156
                else                       mpf_add(sum,sum,jm);
751,218✔
2157
        }
2158
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
2159
}
3,606✔
2160

2161
/*
2162
                 #] EndTable : 
2163
                 #[ deltaMZV :
2164
*/
2165

2166
void deltaMZV(mpf_t result, WORD *indexes, int depth)
7,566✔
2167
{
2168
        GETIDENTITY
5,044✔
2169
/*
2170
        Because all sums go roughly like 1/2^j we need about depth steps.
2171
*/
2172
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
2173
        if ( depth == 1 ) {
7,566✔
2174
                if ( indexes[0] == 1 ) {
3,804✔
2175
                        mpf_set(result,mpfdelta1);
1,650✔
2176
                        return;
1,650✔
2177
                }
2178
                SimpleDelta(result,indexes[0]);
2,154✔
2179
        }
2180
        else if ( depth == 2 ) {
3,762✔
2181
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
1,470✔
2182
                        mpf_pow_ui(result,mpfdelta1,2);
486✔
2183
                        mpf_div_2exp(result,result,1);
486✔
2184
                }
2185
                else {
2186
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
984✔
2187
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
984✔
2188
                };
2189
        }
2190
        else if ( depth > 2 ) {
2,292✔
2191
                mpf_t *mpftab3;
2192
                int d;
2193
/*
2194
                Check first whether this is a power of delta1 = ln(2)
2195
*/
2196
                for ( d = 0; d < depth; d++ ) {
7,548✔
2197
                        if ( indexes[d] != 1 ) break;
6,678✔
2198
                }
2199
                if ( d == depth ) {        /* divide by fac_(depth) */
2,292✔
2200
                        mpf_pow_ui(result,mpfdelta1,depth);
870✔
2201
                        for ( d = 2; d <= depth; d++ ) {
5,196✔
2202
                                mpf_div_ui(result,result,(unsigned long)d);
3,456✔
2203
                        }
2204
                }
2205
                else {
2206
                        d = depth-1;
1,422✔
2207
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
1,422✔
2208
                        d--; indexes++;
1,422✔
2209
                        for(;;) {
6,726✔
2210
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
4,074✔
2211
                                d--; indexes++;
4,074✔
2212
                                if ( d == 0 ) {
4,074✔
2213
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
1,422✔
2214
                                        break;
1,422✔
2215
                                }
2216
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
2,652✔
2217
                                AT.mpf_tab2 = (void *)mpftab3;
2,652✔
2218
                        }
2219
                }
2220
        }
2221
        else if ( depth == 0 ) {
×
2222
                mpf_set_ui(result,1L);
×
2223
        }
2224
}
2225

2226
/*
2227
                 #] deltaMZV : 
2228
                 #[ deltaEuler :
2229

2230
                Regular Euler delta with - signs, but everywhere 1/2^j
2231
*/
2232

2233
void deltaEuler(mpf_t result, WORD *indexes, int depth)
990✔
2234
{
2235
        GETIDENTITY
660✔
2236
        int m;
990✔
2237
#ifdef DEBUG
2238
        int i;
2239
        printf(" deltaEuler(");
2240
        for ( i = 0; i < depth; i++ ) {
2241
                if ( i != 0 ) printf(",");
2242
                printf("%d",indexes[i]);
2243
        }
2244
        printf(") = ");
2245
#endif
2246
        if ( depth == 1 ) {
990✔
2247
                SimpleDelta(result,indexes[0]);
390✔
2248
        }
2249
        else if ( depth == 2 ) {
600✔
2250
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
348✔
2251
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
348✔
2252
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,0);
348✔
2253
        }
2254
        else if ( depth > 2 ) {
252✔
2255
                int d;
252✔
2256
                mpf_t *mpftab3;
252✔
2257
                d = depth-1;
252✔
2258
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
252✔
2259
                d--; indexes++;
252✔
2260
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
252✔
2261
                for(;;) {
348✔
2262
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
300✔
2263
                        d--; indexes++;
300✔
2264
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
300✔
2265
                        if ( d == 0 ) {
300✔
2266
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
252✔
2267
                                break;
252✔
2268
                        }
2269
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2270
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2271
                }
2272
        }
2273
        else if ( depth == 0 ) {
×
2274
                mpf_set_ui(result,1L);
×
2275
        }
2276
#ifdef DEBUG
2277
        gmp_printf("%.*Fe\n",40,result);
2278
#endif
2279
}
990✔
2280

2281
/*
2282
                 #] deltaEuler : 
2283
                 #[ deltaEulerC :
2284

2285
                Conjugate Euler delta without - signs, but possibly 1/4^j
2286
                When there is a - in the string we have 1/4.
2287
*/
2288

2289
void deltaEulerC(mpf_t result, WORD *indexes, int depth)
990✔
2290
{
2291
        GETIDENTITY
660✔
2292
        int m;
990✔
2293
#ifdef DEBUG
2294
        int i;
2295
        printf(" deltaEulerC(");
2296
        for ( i = 0; i < depth; i++ ) {
2297
                if ( i != 0 ) printf(",");
2298
                printf("%d",indexes[i]);
2299
        }
2300
        printf(") = ");
2301
#endif
2302
        mpf_set_ui(result,0);
990✔
2303
        if ( depth == 1 ) {
990✔
2304
                if ( indexes[0] == 0 ) {
390✔
2305
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2306
                }
2307
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
390✔
2308
                else                  SimpleDelta(result,indexes[0]);
150✔
2309
        }
2310
        else if ( depth == 2 ) {
600✔
2311
                int par;
348✔
2312
                m = indexes[0];
348✔
2313
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth,-m,2);
348✔
2314
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth, m,1);
132✔
2315
                m = indexes[1];
348✔
2316
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
348✔
2317
                else { par = indexes[0] < 0 ? -1: 0; }
150✔
2318
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
348✔
2319
        }
2320
        else if ( depth > 2 ) {
252✔
2321
                int d, par;
252✔
2322
                mpf_t *mpftab3;
252✔
2323
                d = depth-1;
252✔
2324
                m = indexes[0];
252✔
2325
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
252✔
2326
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
252✔
2327
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
60✔
2328
                d--; indexes++; m = indexes[0];
252✔
2329
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
252✔
2330
                else { par = indexes[-1] < 0 ? -1: 0; }
120✔
2331
                for(;;) {
348✔
2332
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
300✔
2333
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
300✔
2334
                        d--; indexes++; m = indexes[0];
300✔
2335
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
300✔
2336
                        else { par = indexes[-1] < 0 ? -1: 0; }
144✔
2337
                        if ( d == 0 ) {
300✔
2338
                                mpf_set_ui(result,0);
252✔
2339
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
252✔
2340
                                break;
252✔
2341
                        }
2342
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2343
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2344
                }
2345
        }
2346
        else if ( depth == 0 ) {
×
2347
                mpf_set_ui(result,1L);
×
2348
        }
2349
#ifdef DEBUG
2350
        gmp_printf("%.*Fe\n",40,result);
2351
#endif
2352
}
990✔
2353

2354
/*
2355
                 #] deltaEulerC : 
2356
                 #[ CalculateMZVhalf :
2357

2358
                 This routine is mainly for support when large numbers of
2359
                MZV's have to be calculated at the same time.
2360
*/
2361

2362
void CalculateMZVhalf(mpf_t result, WORD *indexes, int depth)
378✔
2363
{
2364
        int i;
378✔
2365
        if ( depth < 0 ) {
378✔
2366
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
2367
                exit(-1);
×
2368
        }
2369
        for ( i = 0; i < depth; i++ ) {
1,530✔
2370
                if ( indexes[i] <= 0 ) {
1,152✔
2371
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2372
                        exit(-1);
×
2373
                }
2374
        }
2375
        deltaMZV(result,indexes,depth);
378✔
2376
}
378✔
2377

2378
/*
2379
                 #] CalculateMZVhalf : 
2380
                 #[ CalculateMZV :
2381
*/
2382

2383
void CalculateMZV(mpf_t result, WORD *indexes, int depth)
822✔
2384
{
2385
        GETIDENTITY
548✔
2386
        int num1, num2 = 0, i, j = 0;
822✔
2387
        if ( depth < 0 ) {
822✔
2388
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
2389
                exit(-1);
×
2390
        }
2391
        if ( indexes[0] == 1 ) {
822✔
2392
                printf("Divergent MZV in CalculateMZV\n");
×
2393
                exit(-1);
×
2394
        }
2395
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2396
        for ( i = 0; i < depth; i++ ) {
2,076✔
2397
                if ( indexes[i] <= 0 ) {
1,254✔
2398
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
2399
                        exit(-1);
×
2400
                }
2401
                AT.indi1[i] = indexes[i];
1,254✔
2402
        }
2403
        num1 = depth; i = 0;
822✔
2404
        deltaMZV(result,indexes,depth);
822✔
2405
        for(;;) {
6,366✔
2406
                if ( AT.indi1[0] > 1 ) {
3,594✔
2407
                        AT.indi1[0] -= 1;
2,340✔
2408
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
7,794✔
2409
                        AT.indi2[0] = 1; num2++;
2,340✔
2410
                }
2411
                else {
2412
                        AT.indi2[0] += 1;
1,254✔
2413
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,926✔
2414
                        num1--;
1,254✔
2415
                        if ( num1 == 0 ) break;
1,254✔
2416
                }
2417
                deltaMZV(aux1,AT.indi1,num1);
2,772✔
2418
                deltaMZV(aux2,AT.indi2,num2);
2,772✔
2419
                mpf_mul(aux3,aux1,aux2);
2,772✔
2420
                mpf_add(result,result,aux3);
2,772✔
2421
        }
2422
        deltaMZV(aux3,AT.indi2,num2);
822✔
2423
        mpf_add(result,result,aux3);
822✔
2424
}
822✔
2425

2426
/*
2427
                 #] CalculateMZV : 
2428
                 #[ CalculateEuler :
2429

2430
                There is a problem of notation here.
2431
                Basically there are two notations.
2432
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2433
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2434
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2435
                   See Broadhurst,1996
2436
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2437
                                 sum_(j2,1,inf,sign_(m2)*
2438
                                 sum_(j3,1,inf,sign_(m3)
2439
                                                        /j3^abs_(m3)
2440
                                                        /(j2+j3)^abs_(m2)
2441
                                                        /(j1+j2+j3)^abs_(m1) )))
2442
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2443
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2444
                The algorithm follows 2, but the more common notation is 1.
2445
                Hence we start with a conversion.
2446
*/
2447

2448
void CalculateEuler(mpf_t result, WORD *Zindexes, int depth)
318✔
2449
{
2450
        GETIDENTITY
212✔
2451
        int s1, num1, num2, i, j;
318✔
2452

2453
        WORD *indexes = AT.WorkPointer;
318✔
2454
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
1,128✔
2455
        for ( i = 0; i < depth-1; i++ ) {
810✔
2456
                if ( Zindexes[i] < 0 ) {
492✔
2457
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
864✔
2458
                }
2459
        }
2460

2461
        if ( depth < 0 ) {
318✔
2462
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
2463
                exit(-1);
×
2464
        }
2465
        if ( indexes[0] == 1 ) {
318✔
2466
                printf("Divergent Euler sum in CalculateEuler\n");
×
2467
                exit(-1);
×
2468
        }
2469
        for ( i = 0, j = 0; i < depth; i++ ) {
1,128✔
2470
                if ( indexes[i] == 0 ) {
810✔
2471
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2472
                        exit(-1);
×
2473
                }
2474
                if ( indexes[i] < 0 ) j = 1;
810✔
2475
                AT.indi1[i] = indexes[i];
810✔
2476
        }
2477
        if ( j == 0 ) {
318✔
2478
                CalculateMZV(result,indexes,depth);
42✔
2479
                return;
42✔
2480
        }
2481
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
276✔
2482
        deltaEuler(result,AT.indi1,depth);
276✔
2483
        s1 = 0;
276✔
2484
        for(;;) {
990✔
2485
                s1++;
990✔
2486
                if ( AT.indi1[0] > 1 ) {
990✔
2487
                        AT.indi1[0] -= 1;
90✔
2488
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
162✔
2489
                        AT.indi2[0] = 1; num2++;
90✔
2490
                }
2491
                else if ( AT.indi1[0] < -1 ) {
900✔
2492
                        AT.indi1[0] += 1;
162✔
2493
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
270✔
2494
                        AT.indi2[0] = 1; num2++;
162✔
2495
                }
2496
                else if ( AT.indi1[0] == -1 ) {
738✔
2497
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
1,026✔
2498
                        AT.indi2[0] = -1; num2++;
486✔
2499
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,026✔
2500
                        num1--;
486✔
2501
                }
2502
                else {
2503
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
252✔
2504
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
432✔
2505
                        num1--;
252✔
2506
                }
2507
                if ( num1 == 0 ) break;
990✔
2508
                deltaEuler(aux1,AT.indi1,num1);
714✔
2509
                deltaEulerC(aux2,AT.indi2,num2);
714✔
2510
                mpf_mul(aux3,aux1,aux2);
714✔
2511
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
714✔
2512
                else                               mpf_sub(result,result,aux3);
408✔
2513
        }
2514
        deltaEulerC(aux3,AT.indi2,num2);
276✔
2515
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
276✔
2516
        else                          mpf_sub(result,result,aux3);
162✔
2517
}
2518

2519
/*
2520
                 #] CalculateEuler : 
2521
                 #[ ExpandMZV :
2522
*/
2523

2524
int ExpandMZV(WORD *term, WORD level)
×
2525
{
2526
        DUMMYUSE(term);
×
2527
        DUMMYUSE(level);
×
2528
        return(0);
×
2529
}
2530

2531
/*
2532
                 #] ExpandMZV : 
2533
                 #[ ExpandEuler :
2534
*/
2535

2536
int ExpandEuler(WORD *term, WORD level)
×
2537
{
2538
        DUMMYUSE(term);
×
2539
        DUMMYUSE(level);
×
2540
        return(0);
×
2541
}
2542

2543
/*
2544
                 #] ExpandEuler : 
2545
                 #[ EvaluateEuler :
2546

2547
        There are various steps here:
2548
        1: locate an Euler function.
2549
        2: evaluate it into a float.
2550
        3: convert the coefficient to a float and multiply.
2551
        4: Put the new term together.
2552
        5: Restart to see whether there are more Euler functions.
2553
        The compiler should check that there is no conflict between
2554
        the evaluate command and a potential polyfun or polyratfun.
2555
        Yet, when reading in expressions there can be a conflict.
2556
        Hence the Normalize routine should check as well.
2557

2558
        par == MZV: MZV
2559
        par == EULER: Euler
2560
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2561
        par == ALLMZVFUNCTIONS: all of the above.
2562
*/
2563

2564
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
1,350✔
2565
{
2566
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
1,350✔
2567
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
1,350✔
2568
        int retval;
1,350✔
2569
        tstop = term + *term; tstop -= ABS(tstop[-1]);
1,350✔
2570
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
1,350✔
2571
/*
2572
        Step 1. We also need to verify that the argument we find is legal
2573
*/
2574
        t = term+1;
1,350✔
2575
        while ( t < tstop ) {
3,972✔
2576
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
2,622✔
2577
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
264✔
2578
        /* all arguments should be small integers */
2579
                        indexes = AT.WorkPointer;
1,494✔
2580
                        sumweight = 0; depth = 0;
1,494✔
2581
                        tnext = t + t[1]; tt = t + FUNHEAD;
1,494✔
2582
                        while ( tt < tnext ) {
4,638✔
2583
                                if ( *tt != -SNUMBER ) goto nextfun;
3,144✔
2584
                                if ( tt[1] == 0 ) goto nextfun;
3,144✔
2585
                                indexes[depth] = tt[1];
3,144✔
2586
                                sumweight += ABS(tt[1]); depth++;
3,144✔
2587
                                tt += 2;
3,144✔
2588
                        }
2589
                        /* euler sum without arguments, i.e. mzv_(), euler_() or mzvhalf_() */
2590
                        if ( depth == 0) goto nextfun;
1,494✔
2591
                        if ( sumweight > AC.MaxWeight ) {
1,476✔
2592
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
2593
                                MesPrint("Please increase MaxWeight in form.set.");
×
2594
                                Terminate(-1);
×
2595
                        }
2596
/*
2597
                        Step 2: evaluate:
2598
*/
2599
                        AT.WorkPointer += depth;
1,476✔
2600
                        if ( first ) {
1,476✔
2601
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
1,152✔
2602
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
696✔
2603
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
378✔
2604
                                first = 0;
2605
                        }
2606
                        else {
2607
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
324✔
2608
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
2609
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2610
                                mpf_mul(aux4,aux4,aux5);
324✔
2611
                        }
2612
                        *t = 0;
1,476✔
2613
                }
2614
nextfun:
1,128✔
2615
                t += t[1];
2,622✔
2616
        }
2617
        if ( first == 1 ) return(Generator(BHEAD term,level));
1,350✔
2618
/*
2619
        Step 3:
2620
        Now the regular coefficient, if it is not 1/1.
2621
        We have two cases: size +- 3, or bigger.
2622
*/
2623
        nsize = term[*term-1];
1,152✔
2624
        if ( nsize < 0 ) {
1,152✔
2625
                mpf_neg(aux4,aux4);
72✔
2626
                nsize = -nsize;
72✔
2627
        }
2628
        if ( nsize == 3 ) {
1,152✔
2629
                if ( tstop[0] != 1 ) {
1,152✔
2630
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
132✔
2631
                }
2632
                if ( tstop[1] != 1 ) {
1,152✔
2633
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
132✔
2634
                }
2635
        }
2636
        else {
2637
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2638
                mpf_mul(aux4,aux4,aux5);
×
2639
        }
2640
/*
2641
        Now we have to locate possible other float_ functions.
2642
*/
2643
        t = term+1;
2644
        while ( t < tstop ) {
3,510✔
2645
                if ( *t == FLOATFUN ) {
2,358✔
2646
                        UnpackFloat(aux5,t);
×
2647
                        mpf_mul(aux4,aux4,aux5);
×
2648
                }
2649
                t += t[1];
2,358✔
2650
        }
2651
/*
2652
        Now we should compose the new term in the WorkSpace.
2653
*/
2654
        t = term+1;
1,152✔
2655
        newterm = AT.WorkPointer;
1,152✔
2656
        tt = newterm+1;
1,152✔
2657
        while ( t < tstop ) {
1,152✔
2658
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
2,358✔
2659
                else {
2660
                        i = t[1]; NCOPY(tt,t,i);
11,922✔
2661
                }
2662
        }
2663
        PackFloat(tt,aux4);
1,152✔
2664
        tt += tt[1];
1,152✔
2665
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
1,152✔
2666
        *newterm = tt-newterm;
1,152✔
2667
        AT.WorkPointer = tt;
1,152✔
2668
        retval = Generator(BHEAD newterm,level);
1,152✔
2669
        AT.WorkPointer = oldworkpointer;
1,152✔
2670
        return(retval);
1,152✔
2671
}
2672

2673
/*
2674
                 #] EvaluateEuler : 
2675
          #] MZV : 
2676
          #[ Functions :
2677
                 #[ CoEvaluate :
2678

2679
                Current subkeys: mzv_, euler_ and sqrt_.
2680
*/
2681

2682
int CoEvaluate(UBYTE *s)
390✔
2683
{
2684
        GETIDENTITY
260✔
2685
        UBYTE *subkey, c;
390✔
2686
        WORD numfun, type;
390✔
2687
        int error = 0;
390✔
2688
        if ( AT.aux_ == 0 ) {
390✔
2689
                MesPrint("&Illegal attempt to evaluate a function without activating floating point numbers.");
6✔
2690
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
2691
                return(1);
6✔
2692
        }
2693
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
384✔
2694
        if ( *s == 0 ) {
384✔
2695
/*
2696
                No subkey, which means all functions.
2697
*/
2698
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
42✔
2699
/*
2700
                The MZV, EULER and MZVHALF are done separately
2701
*/
2702
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
42✔
2703
                return(0);        
42✔
2704
        }
2705
        while ( *s ) {
660✔
2706
        subkey = s;
2707
        while ( FG.cTable[*s] == 0 ) s++;
1,656✔
2708
          if ( *s == '2' ) s++; /* cases li2_ and atan2_ */
360✔
2709
          if ( *s == '_' ) s++;
360✔
2710
          c = *s; *s = 0;
360✔
2711
/*
2712
                We still need provisions for pi_ and possibly other constants.
2713
*/
2714
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
360✔
2715
                        || ( functions[numfun].spec != 0 ) ) {
318✔
2716

2717
                if ( type == CSYMBOL ) {
42✔
2718
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
36✔
2719
                        break;
36✔
2720
                }
2721
/*
2722
                        This cannot work.
2723
*/
2724
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
6✔
2725
                return(1);
6✔
2726
          }
2727
          else {
2728
                switch ( numfun+FUNCTION ) {
318✔
2729
                        case MZV:
318✔
2730
                        case EULER:
2731
                        case MZVHALF:
2732
/*
2733
                        The following functions are treated in evaluate.c
2734
*/
2735
                        case SQRTFUNCTION:
2736
                        case LNFUNCTION:
2737
                        case EXPFUNCTION:
2738
                        case SINFUNCTION:
2739
                        case COSFUNCTION:
2740
                        case TANFUNCTION:
2741
                        case ASINFUNCTION:
2742
                        case ACOSFUNCTION:
2743
                        case ATANFUNCTION:
2744
                        case ATAN2FUNCTION:
2745
                        case SINHFUNCTION:
2746
                        case COSHFUNCTION:
2747
                        case TANHFUNCTION:
2748
                        case ASINHFUNCTION:
2749
                        case ACOSHFUNCTION:
2750
                        case ATANHFUNCTION:
2751
                        case LI2FUNCTION:
2752
                        case LINFUNCTION:
2753
                        case AGMFUNCTION:
2754
                        case GAMMAFUN:
2755
/*
2756
                        At a later stage we can add more functions from mpfr here
2757
                                mpfr_(number,arg(s))
2758
*/
2759
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
318✔
2760
                                break;
318✔
2761
                        default:
×
2762
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2763
                                error = 1;
×
2764
                                break;
×
2765
                }
2766
          }
2767
          *s = c;
318✔
2768
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
336✔
2769
        }
2770
        return(error);
2771
}
2772

2773
/*
2774
                 #] CoEvaluate : 
2775
          #] Functions : 
2776
*/
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