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

form-dev / form / 20064665963

09 Dec 2025 01:11PM UTC coverage: 57.16% (+0.008%) from 57.152%
20064665963

push

github

cbmarini
feat: reserved the function names hpl_ and mpl_.
- These names are now preserved for future numerical evaluation support.

47204 of 82582 relevant lines covered (57.16%)

5673867.73 hits per line

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

76.84
/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)
3,270✔
271
{
272
        WORD *t, nlimbs, num, nnum;
3,270✔
273
        mp_limb_t *d = infloat->_mp_d; /* Pointer to the limbs.  */
3,270✔
274
        int i;
3,270✔
275
        long e = infloat->_mp_exp;
3,270✔
276
        
277
        t = fun;
3,270✔
278
        *t++ = FLOATFUN;
3,270✔
279
        t++;
3,270✔
280
        FILLFUN(t);
3,270✔
281
        *t++ = -SNUMBER;
3,270✔
282
        *t++ = infloat->_mp_prec;
3,270✔
283
        *t++ = -SNUMBER;
3,270✔
284
        *t++ = infloat->_mp_size;
3,270✔
285
/*
286
        Now the exponent which is a signed long
287
*/
288
        if ( e < 0 ) {
3,270✔
289
                e = -e;
×
290
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
×
291
                        *t++ = -SNUMBER; *t++ = -e;
×
292
                }
293
                else {
294
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
×
295
                        *t++ = 6;
×
296
                        *t++ = (UWORD)e;
×
297
                        *t++ = (UWORD)(e >> BITSINWORD);
×
298
                        *t++ = 1; *t++ = 0; *t++ = -5;
×
299
                }
300
        }
301
        else {
302
                if ( ( e >> (BITSINWORD-1) ) == 0 ) {
3,270✔
303
                        *t++ = -SNUMBER; *t++ = e;
3,270✔
304
                }
305
                else {
306
                        *t++ = ARGHEAD+6; *t++ = 0; FILLARG(t);
×
307
                        *t++ = 6;
×
308
                        *t++ = (UWORD)e;
×
309
                        *t++ = (UWORD)(e >> BITSINWORD);
×
310
                        *t++ = 1; *t++ = 0; *t++ = 5;
×
311
                }
312
        }
313
/*
314
        and now the limbs. Note that the number of active limbs could be less
315
        than prec+1 in which case we copy the smaller number.
316
*/
317
        nlimbs = infloat->_mp_size < 0 ? -infloat->_mp_size: infloat->_mp_size;
3,270✔
318
        if ( nlimbs == 0 ) {
3,270✔
319
        }
320
        else if ( nlimbs == 1 && (ULONG)(*d) < ((ULONG)1)<<(BITSINWORD-1) ) {
3,270✔
321
                *t++ = -SNUMBER;
30✔
322
                *t++ = (UWORD)(*d);
30✔
323
        }
324
        else {
325
          if ( d[nlimbs-1] < ((ULONG)1)<<BITSINWORD ) {
3,240✔
326
                num = 2*nlimbs-1; /* number of UWORDS needed */
1,572✔
327
          }
328
          else {
329
                num = 2*nlimbs;   /* number of UWORDS needed */
1,668✔
330
          }
331
          nnum = num;
3,240✔
332
          *t++ = 2*num+2+ARGHEAD;
3,240✔
333
          *t++ = 0;
3,240✔
334
          FILLARG(t);
3,240✔
335
          *t++ = 2*num+2;
3,240✔
336
          while ( num > 1 ) {
14,226✔
337
                *t++ = (UWORD)(*d); *t++ = (UWORD)(((ULONG)(*d))>>BITSINWORD); d++;
10,986✔
338
                num -= 2;
10,986✔
339
          }
340
          if ( num == 1 ) { *t++ = (UWORD)(*d); }
3,240✔
341
          *t++ = 1;
3,240✔
342
          for ( i = 1; i < nnum; i++ ) *t++ = 0;
23,544✔
343
          *t++ = 2*nnum+1; /* the sign is hidden in infloat->_mp_size */
3,240✔
344
        }
345
        fun[1] = t-fun;
3,270✔
346
        return(fun[1]);
3,270✔
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)
4,518✔
365
{
366
        UWORD *t;
4,518✔
367
        WORD *f;
4,518✔
368
        int num, i;
4,518✔
369
        mp_limb_t *d;
4,518✔
370
/*
371
        Very first step: check whether we can use float_:
372
*/
373
        GETIDENTITY
3,012✔
374
        if ( AT.aux_ == 0 ) {
4,518✔
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;
4,518✔
385
        f = fun + FUNHEAD + 2;
4,518✔
386
        if ( ABS(f[1]) > f[-1]+1 ) goto Incorrect;
4,518✔
387
        if ( f[1] > outfloat->_mp_prec+1
4,518✔
388
          || outfloat->_mp_d == 0 ) {
4,518✔
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];
4,518✔
400
        outfloat->_mp_size = num;
4,518✔
401
        if ( num < 0 ) { num = -num; }
4,518✔
402
        f += 2;
4,518✔
403
        if ( *f == -SNUMBER ) {
4,518✔
404
                outfloat->_mp_exp = (mp_exp_t)(f[1]);
4,518✔
405
                f += 2;
4,518✔
406
        }
407
        else {
408
                f += ARGHEAD+6;
×
409
                if ( f[-1] == -5 ) {
×
410
                        outfloat->_mp_exp =
×
411
                                -(mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+f[-5]);
×
412
                }
413
                else if ( f[-1] == 5 ) {
×
414
                        outfloat->_mp_exp =
×
415
                                 (mp_exp_t)((((ULONG)(f[-4]))<<BITSINWORD)+f[-5]);
×
416
                }
417
        }
418
/*
419
        And now the limbs if needed
420
*/
421
        d = outfloat->_mp_d;
4,518✔
422
        if ( outfloat->_mp_size == 0 ) {
4,518✔
423
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
×
424
                return(0);
425
        }
426
        else if ( *f == -SNUMBER ) {
4,518✔
427
                *d++ = (mp_limb_t)f[1];
102✔
428
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
306✔
429
                return(0);
430
        }
431
        num = (*f-ARGHEAD-2)/2; /* 2*number of limbs in the argument */
4,416✔
432
        t = (UWORD *)(f+ARGHEAD+1);
4,416✔
433
        while ( num > 1 ) {
17,760✔
434
                *d++ = (mp_limb_t)((((ULONG)(t[1]))<<BITSINWORD)+t[0]);
13,344✔
435
                t += 2; num -= 2;
13,344✔
436
        }
437
        if ( num == 1 ) *d++ = (mp_limb_t)((UWORD)(*t));
4,416✔
438
        for ( i = d-outfloat->_mp_d; i <= outfloat->_mp_prec; i++ ) *d++ = 0;
7,200✔
439
        return(0);
440
Incorrect:
4,518✔
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)
10,902✔
453
{
454
        WORD *fstop, *f, num, nnum, i;
10,902✔
455
        fstop = fun+fun[1];
10,902✔
456
        f = fun + FUNHEAD;
10,902✔
457
        num = 0;
10,902✔
458
/*
459
        Count arguments
460
*/
461
        while ( f < fstop ) { num++; NEXTARG(f); }
54,474✔
462
        if ( num != 4 ) return(0);
10,902✔
463
        f = fun + FUNHEAD;
10,890✔
464
        if ( *f != -SNUMBER ) return(0);
10,890✔
465
        if ( f[1] < 0 ) return(0);
10,878✔
466
        f += 2;
10,878✔
467
        if ( *f != -SNUMBER ) return(0);
10,878✔
468
        num = ABS(f[1]); /* number of limbs */
10,878✔
469
        f += 2;
10,878✔
470
        if ( *f == -SNUMBER ) { f += 2; }
10,878✔
471
        else {
472
                if ( *f != ARGHEAD+6 ) return(0);
×
473
                if ( ABS(f[ARGHEAD+5]) != 5 ) return(0);
×
474
                if ( f[ARGHEAD+3] != 1 ) return(0);
×
475
                if ( f[ARGHEAD+4] != 0 ) return(0);
×
476
                f += *f;
×
477
        }
478
        if ( num == 0 ) return(1);
10,878✔
479
        if ( *f == -SNUMBER ) { if ( num != 1 ) return(0); }
10,878✔
480
        else {
481
                nnum = (ABS(f[*f-1])-1)/2;
10,716✔
482
                if ( ( *f != 4*num+2+ARGHEAD ) && ( *f != 4*num+ARGHEAD ) ) return(0);
10,716✔
483
                if ( ( nnum != 2*num ) && ( nnum != 2*num-1 ) ) return(0);
10,716✔
484
                f += ARGHEAD+nnum+1;
10,716✔
485
                if ( f[0] != 1 ) return(0);
10,716✔
486
                for ( i = 1; i < nnum; i++ ) {
72,144✔
487
                        if ( f[i] != 0 ) return(0);
61,428✔
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)
960✔
512
{
513
        int nlimbs, sgn = 1;
960✔
514
        mp_limb_t *d;
960✔
515
        UWORD *b = a;
960✔
516
        WORD nb = na;
960✔
517

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

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

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

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

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

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

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

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

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

604
void IntegerToFloat(mpf_t result, UWORD *formlong, int longsize)
708✔
605
{
606
        mpz_t z;
708✔
607
        mpz_init(z);
708✔
608
        FormtoZ(z,formlong,longsize);
708✔
609
        mpf_set_z(result,z);
708✔
610
        mpz_clear(z);
708✔
611
}
708✔
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)
354✔
621
{
622
        GETIDENTITY
236✔
623
        int nnum, nden;
354✔
624
        UWORD *num, *den;
354✔
625
        int sgn = 0;
354✔
626
        if ( ratsize < 0 ) { ratsize = -ratsize; sgn = 1; }
354✔
627
        nnum = nden = (ratsize-1)/2;
354✔
628
        num = formrat; den = formrat+nnum;
354✔
629
        while ( num[nnum-1] == 0 ) { nnum--; }
1,182✔
630
        while ( den[nden-1] == 0 ) { nden--; }
372✔
631
        IntegerToFloat(aux2,num,nnum);
354✔
632
        IntegerToFloat(aux3,den,nden);
354✔
633
        mpf_div(result,aux2,aux3);
354✔
634
        if ( sgn > 0 ) mpf_neg(result,result);
354✔
635
}
354✔
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)
612✔
823
{
824
        GETIDENTITY
408✔
825
        SBYTE *ss, c;
612✔
826
        ss = s;
612✔
827
        while ( *ss > 0 ) ss++;
3,360✔
828
        c = *ss; *ss = 0;
612✔
829
        gmp_sscanf((char *)s,"%Ff",aux1);
612✔
830
        if ( AT.WorkPointer > AT.WorkTop ) {
612✔
831
                MLOCK(ErrorMessageLock);
×
832
                MesWork();
×
833
                MUNLOCK(ErrorMessageLock);
×
834
                Terminate(-1);
×
835
        }
836
        PackFloat(AT.WorkPointer,aux1);
612✔
837
        *ss = c;
612✔
838
        return(ss);
612✔
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,295,162✔
849
{
850
        GETIDENTITY
8,863,444✔
851
        UBYTE *s = ss;
13,295,162✔
852
        int zero = 1, gotdot = 0;
13,295,162✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
34,947,292✔
854
        *spec = 0;
13,295,162✔
855
        if ( FG.cTable[*s] == 1 ) {
13,295,162✔
856
                while ( *s == '0' ) s++;
14,940,914✔
857
                if ( FG.cTable[*s] == 1 ) {
13,295,120✔
858
                        s++;
11,649,404✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
20,399,420✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
13,295,120✔
863
        }
864
        else if ( *s == '.' ) {
42✔
865
dot:
42✔
866
                gotdot = 1;
612✔
867
                s++;
612✔
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
612✔
869
                while ( *s == '0' ) s++;
1,068✔
870
                if ( FG.cTable[*s] == 1 ) {
612✔
871
                        s++;
312✔
872
                        while ( FG.cTable[*s] == 1 ) s++;
780✔
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,295,162✔
882
                s++;
72✔
883
                if ( *s == '-' || *s == '+' ) s++;
72✔
884
                if ( FG.cTable[*s] == 1 ) {
72✔
885
                        s++;
72✔
886
                        while ( FG.cTable[*s] == 1 ) s++;
138✔
887
                }
888
                else { return(ss); }
889
        }
890
        else if ( gotdot == 0 ) return(ss);
13,295,090✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
612✔
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
612✔
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)
432✔
915
{
916
        if ( prec <= 0 ) {
432✔
917
                MesPrint("&Illegal value for number of bits for floating point constants: %d",prec);
×
918
                return(-1);
×
919
        }
920
        else {
921
                AC.DefaultPrecision = prec;
432✔
922
                if ( AO.floatspace != 0 ) M_free(AO.floatspace,"floatspace");
432✔
923
                AO.floatsize = (prec+20)*sizeof(char);
432✔
924
                AO.floatspace = (UBYTE *)Malloc1(AO.floatsize,"floatspace");
432✔
925
                mpf_set_default_prec(prec);
432✔
926
                return(0);
432✔
927
        }
928
}
929

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1400
                LHS notation of the chop statement: 
1401
                        TYPECHOP, length, FLOATFUN, ... 
1402
                where FLOATFUN, ... represents the threshold of the chop statement in 
1403
                the notation of a float_ function with its arguments. 
1404

1405
*/
1406

1407
int CoChop(UBYTE *s)
30✔
1408
{
1409
        GETIDENTITY
20✔
1410
        UBYTE *ss, c;
30✔
1411
        WORD *w, *OldWork;
30✔
1412
        int spec, pow = 1;
30✔
1413
        unsigned long x;
30✔
1414
        if ( AT.aux_ == 0 ) {
30✔
1415
                MesPrint("&Illegal attempt to chop a float_ without activating floating point numbers.");
×
1416
                MesPrint("&Forgotten %#startfloat instruction?");
×
1417
                return(1);
×
1418
        }
1419
        if ( *s == 0 ) {
30✔
1420
                MesPrint("&Chop needs a number (float or rational) as an argument.");
×
1421
                return(1);
×
1422
        }
1423
        /* Create TYPECHOP header */
1424
        w = OldWork = AT.WorkPointer;
30✔
1425
        *w++ = TYPECHOP; 
30✔
1426
        w++;
30✔
1427

1428
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
30✔
1429
        
1430
        /* 
1431
                The argument of chop can be 
1432
                 1: a floating-point number
1433
                 2: an integer, rational number or power
1434
         */
1435
        if ( FG.cTable[*s] == 1 || *s == '.' ) { 
30✔
1436
                /* 1: Attempt to parse as floating-point number */
1437
                ss = CheckFloat(s, &spec);
30✔
1438
                if ( ss > s ) {
30✔
1439
                        /* CheckFloat found a valid float */
1440
                        if ( spec == 1 ) { /* Zero */
6✔
1441
                                MesPrint("&The argument in Chop needs to be larger than 0.");
×
1442
                                return(1);
×
1443
                        }
1444
                        else if ( spec == -1 ) { 
6✔
1445
                                MesPrint("&The floating point system has not been started.");
×
1446
                                return(1);
×
1447
                        }
1448
                        else {
1449
                                AT.WorkPointer = w;
6✔
1450
                                /* 
1451
                                        Reads the floating point number and outputs it at AT.WorkPointer as if it were a float_ 
1452
                                        function with its arguments.
1453
                                 */
1454
                                ReadFloat((SBYTE *)s); 
6✔
1455
                                s = ss;
6✔
1456
                                w += w[1];
6✔
1457
                        }
1458
                }
1459
                else {
1460
                        /* 2: CheckFloat didn't find a float, we now try for rationals and powers */
1461
                        /* Parse the integer part (numerator for rationals) */
1462
                        if ( FG.cTable[*s] == 1 ) {
24✔
1463
                                ParseNumber(x,s)
60✔
1464
                                mpf_set_ui(aux1,x);
24✔
1465
                        }
1466
                        if ( mpf_sgn(aux1) == 0 ) {
24✔
1467
                                MesPrint("&The argument in Chop needs to be larger than 0.");
×
1468
                                return(1);
×
1469
                        }
1470
                        while ( *s == ' ' || *s == '\t' ) s++;
24✔
1471
                        /* Check for rational number or power*/
1472
                        if ( *s == '/' || *s == '^' ) {
24✔
1473
                                c = *s; s++; 
18✔
1474
                                while ( *s == ' ' || *s == '\t' ) s++;
18✔
1475
                                if ( *s == '-' ) { s++; pow = -1; } /* negative power */
18✔
1476
                                /* Parse the denominator or power */
1477
                                if ( FG.cTable[*s] == 1 ) {
18✔
1478
                                        ParseNumber(x,s)
60✔
1479
                                        if ( c == '/' ) { /* rational */
18✔
1480
                                                if ( x == 0 ) {
6✔
1481
                                                        MesPrint("&Division by zero in chop statement.");
×
1482
                                                        return(1);
×
1483
                                                }
1484
                                                /* Perform the division */
1485
                                                mpf_div_ui(aux1, aux1,x);
6✔
1486
                                        }
1487
                                        else { /* Power */
1488
                                                mpf_pow_ui(aux1,aux1,x);
12✔
1489
                                                if ( pow == -1 ) {
12✔
1490
                                                        mpf_ui_div(aux1,(unsigned long) 1, aux1);
6✔
1491
                                                }
1492
                                        }
1493
                                }
1494
                        }
1495
                        /* Put aux1 in the notation of a float_ function */
1496
                        PackFloat(w, aux1);
24✔
1497
                        w += w[1];
24✔
1498
                }
1499
        }
1500
        if ( *s ) {
30✔
1501
                MesPrint("&Illegal argument(s) in Chop statement: '%s'",s);
×
1502
                return(1);
×
1503
        }
1504
        AT.WorkPointer = OldWork;
30✔
1505
        AT.WorkPointer[1] = w - AT.WorkPointer;  /* Set total length */
30✔
1506
        AddNtoL(AT.WorkPointer[1],AT.WorkPointer); /* Add the LHS to the compiler buffer */
30✔
1507
        return(0);
30✔
1508
}
1509

1510
/*
1511
                 #] CoChop : 
1512
                 #[ ToFloat :
1513

1514
                Converts the coefficient to floating point if it is still a rat.
1515
*/
1516

1517
int ToFloat(PHEAD WORD *term, WORD level)
282✔
1518
{
1519
        WORD *t, *tstop, nsize, nsign = 3;
282✔
1520
        t = term+*term;
282✔
1521
        nsize = ABS(t[-1]);
282✔
1522
        tstop = t - nsize;
282✔
1523
        if ( t[-1] < 0 ) { nsign = -nsign; }
282✔
1524
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
282✔
1525
                t = term + 1;
144✔
1526
                while ( t < tstop ) {
282✔
1527
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
138✔
1528
                                return(Generator(BHEAD term,level));
×
1529
                        }
1530
                        t += t[1];
138✔
1531
                }
1532
        }
1533
        RatToFloat(aux4,(UWORD *)tstop,nsize);
282✔
1534
        PackFloat(tstop,aux4);
282✔
1535
        tstop += tstop[1];
282✔
1536
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
282✔
1537
        *term = tstop - term;
282✔
1538
        AT.WorkPointer = tstop;
282✔
1539
        return(Generator(BHEAD term,level));
282✔
1540
}
1541

1542
/*
1543
                 #] ToFloat : 
1544
                 #[ ToRat :
1545

1546
                Tries to convert the coefficient to rational if it is still a float.
1547
*/
1548

1549
int ToRat(PHEAD WORD *term, WORD level)
6✔
1550
{
1551
        WORD *tstop, *t, nsize, nsign, ncoef;
6✔
1552
/*
1553
        1: find the float which should be at the end.
1554
*/
1555
        tstop = term + *term; nsize = ABS(tstop[-1]);
6✔
1556
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
6✔
1557
        t = term+1;
6✔
1558
        while ( t < tstop ) {
6✔
1559
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
6✔
1560
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
6✔
1561
                t += t[1];
×
1562
        }
1563
        if ( t < tstop ) {
6✔
1564
/*
1565
                Now t points at the float_ function and everything is correct.
1566
                The result can go straight over the float_ function.
1567
*/
1568
                UnpackFloat(aux4,t);
6✔
1569
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
6✔
1570
                        t += ABS(ncoef);
6✔
1571
                        t[-1] = ncoef*nsign;
6✔
1572
                        *term = t - term;
6✔
1573
                }
1574
        }
1575
        return(Generator(BHEAD term,level));
6✔
1576
}
1577

1578
/*
1579
                 #] ToRat : 
1580
                 #[ StrictRounding : 
1581

1582
                Rounds floating point numbers to a specified precision
1583
                in a given base (decimal or binary).
1584
*/
1585
int StrictRounding(PHEAD WORD *term, WORD level, WORD prec, WORD base) {
30✔
1586
        WORD *t,*tstop;
30✔
1587
        int sign,size,maxprec = AC.DefaultPrecision-AC.MaxWeight-1;
30✔
1588
        /* maxprec is in bits */
1589
        if ( base == 2 && prec > maxprec ) {
30✔
1590
                prec = maxprec;
1591
        }
1592
        if ( base == 10 && prec > (int)(maxprec*log10(2.0)) ) {
30✔
1593
                prec = maxprec*log10(2.0);
×
1594
        }
1595
        /* Find the float which should be at the end. */
1596
        tstop = term + *term; size = ABS(tstop[-1]);
30✔
1597
        sign = tstop[-1] < 0 ? -1: 1; tstop -= size;
30✔
1598
        t = term+1;
30✔
1599
        while ( t < tstop ) {
42✔
1600
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
30✔
1601
                size == 3 && tstop[0] == 1 && tstop[1] == 1) {
18✔
1602
                        break;
1603
                }
1604
                t += t[1];
12✔
1605
        }
1606
        if ( t < tstop ) {
30✔
1607
/*
1608
                Now t points at the float_ function and everything is correct.
1609
                The result can go straight over the float_ function.
1610
*/
1611
                char *s;
18✔
1612
                mp_exp_t exp;
18✔
1613
                /* Extract the floating point value */
1614
                UnpackFloat(aux4,t);
18✔
1615
                /* Convert to string: 
1616
                   - Format as MeN with M the mantissa and N the exponent 
1617
                   - the generated string by mpf_get_str is the fraction/mantissa with 
1618
                   an implicit radix point immediately to the left of the first digit. 
1619
                   The applicable exponent is written in exp. */
1620
                s = (char *)AO.floatspace;
18✔
1621
                *s++ = '.';
18✔
1622
                mpf_get_str(s,&exp, base, prec, aux4);
18✔
1623
                while ( *s != 0 ) s++;
54✔
1624
                *s++ = 'e';
18✔
1625
                snprintf(s,AO.floatsize-(s-(char *)AO.floatspace),"%ld",exp);
18✔
1626
                /* Negative base values are used to specify that the exponent is in decimal */
1627
                mpf_set_str(aux4,(char *)AO.floatspace,-base);
18✔
1628
                /* Pack the rounded floating point value back into the term */
1629
                PackFloat(t,aux4);
18✔
1630
                t+=t[1];
18✔
1631
                *t++ = 1; *t++ = 1; *t++ = 3*sign;
18✔
1632
                *term = t - term;
18✔
1633
        }
1634
        return(Generator(BHEAD term,level));
30✔
1635
}
1636
/*
1637
                 #] StrictRounding : 
1638
                 #[ Chop :
1639

1640
        Removes terms with a floating point number smaller than a given threshold. 
1641
 
1642
        Search for a FLOATFUN and compares its absolute value against the threshold 
1643
        specified in the chop statement. This threshold can be obtained from the 
1644
        LHS of the chop statement in the compiler buffer.
1645
 
1646
 */
1647
int Chop(PHEAD WORD *term, WORD level)
150✔
1648
{
1649
        WORD *tstop, *t, nsize, *threshold; 
150✔
1650
        CBUF *C = cbuf+AM.rbufnum;
150✔
1651
        /* Find the float which should be at the end. */
1652
        tstop = term + *term; 
150✔
1653
        nsize = ABS(tstop[-1]); tstop -= nsize;
150✔
1654
        t = term+1;
150✔
1655
        while ( t < tstop ) {
300✔
1656
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
270✔
1657
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
120✔
1658
                t += t[1];
150✔
1659
        }
1660
        if ( t < tstop ) {
150✔
1661
                /* Get threshold value from compiler buffer */
1662
                threshold = C->lhs[level];
120✔
1663
                threshold += 2;  /* Skip TYPECHOP header */
120✔
1664
                UnpackFloat(aux5, threshold); 
120✔
1665
                
1666
                /* Extract float and compute its absolute value */
1667
                UnpackFloat(aux4, t);
120✔
1668
                mpf_abs(aux4, aux4);
120✔
1669
                
1670
                /* Remove if < threshold */
1671
                if ( mpf_cmp(aux4, aux5) < 0 ) return(0);
120✔
1672
        }
1673
        return(Generator(BHEAD term,level));
66✔
1674
}
1675

1676
/*
1677
                 #] Chop : 
1678
          #] Float Routines : 
1679
          #[ Sorting :
1680

1681
                We need a method to see whether two terms need addition that could
1682
                involve floating point numbers.
1683
                1: if PolyWise is active, we do not need anything, because
1684
                   Poly(Rat)Fun and floating point are mutually exclusive.
1685
                2: This means that there should be only interference in AddCoef.
1686
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1687
                   and PF_GetLoser.
1688
                The compare routine(s) should recognise the float_ and give off
1689
                a code (SortFloatMode) inside the AT struct:
1690
                0: no float_
1691
                1: float_ in term1 only
1692
                2: float_ in term2 only
1693
                3: float_ in both terms
1694
                Be careful: we have several compare routines, because various codes
1695
                use their own routines and we just set a variable with its address.
1696
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1697
                Only Compare1 should be active for this. The others should make sure
1698
                that the proper variable is always zero.
1699
                Remember: the sign of the coefficient is in the last word of the term.
1700

1701
                We need two routines:
1702
                1: AddWithFloat for SplitMerge which sorts by pointer.
1703
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1704
                   as possible in their location.
1705
                The routines start out the same, because AT.SortFloatMode, set in
1706
                Compare1, tells more or less what should be done.
1707
                The difference is in where we leave the result.
1708

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

1713
                 #[ AddWithFloat :
1714
*/
1715

1716
int AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
174✔
1717
{
1718
        GETBIDENTITY
1719
        SORTING *S = AT.SS;
174✔
1720
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
174✔
1721
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
174✔
1722
        s1 = *ps1;
174✔
1723
        s2 = *ps2;
174✔
1724
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
174✔
1725
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
174✔
1726
        if ( AT.SortFloatMode == 3 ) {
174✔
1727
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
198✔
1728
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
198✔
1729
                UnpackFloat(aux1,fun1);
168✔
1730
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
168✔
1731
                UnpackFloat(aux2,fun2);
168✔
1732
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
168✔
1733
        }
1734
        else if ( AT.SortFloatMode == 1 ) {
6✔
1735
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1736
                UnpackFloat(aux1,fun1);
×
1737
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1738
                fun2 = coef2;
×
1739
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1740
        }
1741
        else if ( AT.SortFloatMode == 2 ) {
6✔
1742
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
12✔
1743
                fun1 = coef1;
6✔
1744
                RatToFloat(aux1,(UWORD *)coef1,size1);
6✔
1745
                UnpackFloat(aux2,fun2);
6✔
1746
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
6✔
1747
        }
1748
        else {
1749
                MLOCK(ErrorMessageLock);
×
1750
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1751
                MUNLOCK(ErrorMessageLock);
×
1752
                Terminate(-1);
×
1753
                return(0);
×
1754
        }
1755
        mpf_add(aux3,aux1,aux2);
174✔
1756
        sign3 = mpf_sgn(aux3);
174✔
1757
        if ( sign3 == 0 ) {        /* May be rare! */
126✔
1758
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1759
        }
1760
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
174✔
1761
        fun3 = TermMalloc("AddWithFloat");
174✔
1762
        PackFloat(fun3,aux3);
174✔
1763
/*
1764
        Now we have to calculate where the sumterm fits.
1765
        If we are sloppy, we can be faster, but run the risk to need the
1766
        extension space, even when it is not needed. At slightly lower speed
1767
        (ie first creating the result in scribble space) we are better off.
1768
        This is why we use TermMalloc.
1769

1770
        The new term will have a rational coefficient of 1,1,+-3.
1771
        The size will be (fun1 or fun2 - term) + fun3 +3;
1772
*/
1773
        if ( AT.SortFloatMode == 3 ) {
174✔
1774
                if ( fun1[1] == fun3[1]  ) {
168✔
1775
Over1:
42✔
1776
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
5,676✔
1777
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
126✔
1778
                        *s1 = t1-s1; goto Finished;
126✔
1779
                }
1780
                else if ( fun2[1] == fun3[1]  ) {
126✔
1781
Over2:
36✔
1782
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
2,052✔
1783
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
42✔
1784
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
42✔
1785
                }
1786
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
90✔
1787
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1788
        }
1789
        else if ( AT.SortFloatMode == 1 ) {
6✔
1790
                if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1791
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1792
        }
1793
        else if ( AT.SortFloatMode == 2 ) {
6✔
1794
                if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1795
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1796
        }
1797
/*
1798
        Does not fit. Go to extension space.
1799
*/
1800
        jj = fun1-s1;
6✔
1801
        j = jj+fun3[1]+3; /* space needed */
6✔
1802
        if ( (S->sFill + j) >= S->sTop2 ) {
6✔
1803
                GarbHand();
×
1804
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1805
                fun1 = s1+jj;
×
1806
        }
1807
        t1 = S->sFill;
6✔
1808
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
12✔
1809
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
336✔
1810
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
6✔
1811
        *ps1 = S->sFill;
6✔
1812
        **ps1 = t1-*ps1;
6✔
1813
        S->sFill = t1;
6✔
1814
Finished:
174✔
1815
        *ps2 = 0;
174✔
1816
        TermFree(fun3,"AddWithFloat");
174✔
1817
        AT.SortFloatMode = 0;
174✔
1818
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
174✔
1819
                MLOCK(ErrorMessageLock);
×
1820
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1821
                AM.MaxTer/sizeof(WORD));
×
1822
                MUNLOCK(ErrorMessageLock);
×
1823
                Terminate(-1);
×
1824
        }
1825
        return(1);
1826
}
1827

1828
/*
1829
                 #] AddWithFloat : 
1830
                 #[ MergeWithFloat :
1831

1832
                Note that we always park the result on top of term1.
1833
                This makes life easier, because the original AddRat in MergePatches
1834
                does this as well.
1835
*/
1836

1837
int MergeWithFloat(PHEAD WORD **interm1, WORD **interm2)
×
1838
{
1839
        GETBIDENTITY
1840
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3, *tt;
×
1841
        WORD sign3,j,jj, *t1, *t2, i, *term1 = *interm1, *term2 = *interm2;
×
1842
        int retval = 0;
×
1843
        coef1 = term1+*term1; size1 = coef1[-1]; coef1 -= ABS(size1);
×
1844
        coef2 = term2+*term2; size2 = coef2[-1]; coef2 -= ABS(size2);
×
1845
        if ( AT.SortFloatMode == 3 ) {
×
1846
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1847
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1848
                UnpackFloat(aux1,fun1);
×
1849
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1850
                UnpackFloat(aux2,fun2);
×
1851
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1852
        }
1853
        else if ( AT.SortFloatMode == 1 ) {
×
1854
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1855
                UnpackFloat(aux1,fun1);
×
1856
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1857
                fun2 = coef2;
×
1858
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1859
        }
1860
        else if ( AT.SortFloatMode == 2 ) {
×
1861
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1862
                fun1 = coef1;
×
1863
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
1864
                UnpackFloat(aux2,fun2);
×
1865
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1866
        }
1867
        else {
1868
                MLOCK(ErrorMessageLock);
×
1869
                MesPrint("Illegal value %d for AT.SortFloatMode in MergeWithFloat.",AT.SortFloatMode);
×
1870
                MUNLOCK(ErrorMessageLock);
×
1871
                Terminate(-1);
×
1872
                return(0);
×
1873
        }
1874
        mpf_add(aux3,aux1,aux2);
×
1875
        sign3 = mpf_sgn(aux3);
×
1876
        if ( sign3 == 0 ) {        /* May be very rare! */
×
1877
                AT.SortFloatMode = 0; return(0);
×
1878
        }
1879
/*
1880
        Now check whether we can park the result on top of one of the input terms.
1881
*/
1882
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
1883
        fun3 = TermMalloc("MergeWithFloat");
×
1884
        PackFloat(fun3,aux3);
×
1885
        if ( AT.SortFloatMode == 3 ) {
×
1886
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) {
×
1887
OnTopOf1:        t1 = fun3; t2 = fun1;
×
1888
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1889
                        *t2++ = 1; *t2++ = 1; *t2++ = sign3 < 0 ? -3: 3;
×
1890
                        retval = 1;
×
1891
                }
1892
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) {
×
1893
Shift1:                t2 = term1 + *term1; tt = t2;
×
1894
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1895
                        t1 = fun3 + fun3[1]; for ( i = 0; i < fun3[1]; i++ ) *--t2 = *--t1;
×
1896
                        t1 = fun1;
1897
                        while ( t1 > term1 ) *--t2 = *--t1;
×
1898
                        *t2 = tt-t2; term1 = t2;
×
1899
                        retval = 1;
×
1900
                }
1901
                else { /* Here we have to move term1 to the left to make room. */
1902
Over1:                jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
×
1903
                        t2 = term1-jj; t1 = term1;
×
1904
                        while ( t1 < fun1 ) *t2++ = *t1++;
×
1905
                        term1 -= jj;
×
1906
                        *term1 += jj;
×
1907
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = fun3[i];
×
1908
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1909
                        retval = 1;
×
1910
                }
1911
        }
1912
        else if ( AT.SortFloatMode == 1 ) {
×
1913
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) goto OnTopOf1;
×
1914
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) goto Shift1;
×
1915
                else goto Over1;
×
1916
        }
1917
        else { /* Can only be 2, based on previous tests */
1918
                if ( fun3[1] + 3 == ABS(size1) ) {
×
1919
                        t2 = coef1; t1 = fun3;
1920
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1921
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1922
                        retval = 1;
×
1923
                }
1924
                else if ( fun3[1] + 3 < ABS(size1) ) {
×
1925
                        j = ABS(size1) - fun3[1] - 3;
×
1926
                        t2 = term1 + *term1; tt = t2;
×
1927
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1928
                        t2 -= fun3[1]; t1 = t2-j;
×
1929
                        while ( t2 > term1 ) *--t2 = *--t1;
×
1930
                        *t2 = tt-t2; term1 = t2;
×
1931
                        retval = 1;
×
1932
                }
1933
                else goto Over1;
×
1934
        }
1935
        *interm1 = term1;
×
1936
        TermFree(fun3,"MergeWithFloat");
×
1937
        AT.SortFloatMode = 0;
×
1938
        return(retval);
×
1939
}
1940

1941
/*
1942
                 #] MergeWithFloat : 
1943
          #] Sorting : 
1944
          #[ MZV :
1945

1946
                The functions here allow the arbitrary precision calculation
1947
                of MZV's and Euler sums.
1948
                They are called when the functions mzv_ and/or euler_ are used
1949
                and the evaluate statement is applied.
1950
                The output is in a float_ function.
1951
                The expand statement tries to express the functions in terms of a basis.
1952
                The bases are the 'standard basis for the euler sums and the
1953
                pushdown bases from the datamine, unless otherwise specified.
1954

1955
                 #[ SimpleDelta :
1956
*/
1957

1958
void SimpleDelta(mpf_t sum, int m)
2,910✔
1959
{
1960
        long s = 1;
2,910✔
1961
        long prec = AC.DefaultPrecision;
2,910✔
1962
        unsigned long xprec = (unsigned long)prec, x;
2,910✔
1963
        int j, jmax, n;
2,910✔
1964
        mpf_t jm,jjm;
2,910✔
1965
        mpf_init(jm); mpf_init(jjm);
2,910✔
1966
        if ( m < 0 ) { s = -1; m = -m; }
2,910✔
1967

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;
2,910✔
1977
        while ( x ) { x >>= 1; n++; }
27,042✔
1978
/* 
1979
        We have now n = floor(log2(x))+1. 
1980
*/
1981
        n--;
2,910✔
1982
        jmax = (int)((int)xprec - (n-1)*m);
2,910✔
1983
        mpf_set_ui(sum,0);
2,910✔
1984
        for ( j = 1; j <= jmax; j++ ) {
792,222✔
1985
#ifdef WITHCUTOFF
1986
                xprec--;
786,402✔
1987
                mpf_set_prec_raw(jm,xprec);
786,402✔
1988
                mpf_set_prec_raw(jjm,xprec);
786,402✔
1989
#endif
1990
                mpf_set_ui(jm,1L);
786,402✔
1991
                mpf_div_ui(jjm,jm,(unsigned long)j);
786,402✔
1992
                mpf_pow_ui(jm,jjm,(unsigned long)m);
786,402✔
1993
                mpf_div_2exp(jjm,jm,(unsigned long)j);
786,402✔
1994
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
786,402✔
1995
                else                       mpf_add(sum,sum,jjm);
777,798✔
1996
        }
1997
        mpf_clear(jjm); mpf_clear(jm);
2,910✔
1998
}
2,910✔
1999

2000
/*
2001
                 #] SimpleDelta : 
2002
                 #[ SimpleDeltaC :
2003
*/
2004

2005
void SimpleDeltaC(mpf_t sum, int m)
240✔
2006
{
2007
        long s = 1;
240✔
2008
        long prec = AC.DefaultPrecision;
240✔
2009
        unsigned long xprec = (unsigned long)prec, x;
240✔
2010
        int j, jmax, n;
240✔
2011
        mpf_t jm,jjm;
240✔
2012
        mpf_init(jm); mpf_init(jjm);
240✔
2013
        if ( m < 0 ) { s = -1; m = -m; }
240✔
2014
/*
2015
        We will loop until 1/2^j/j^m is smaller than the default precision.
2016
        Just running to prec is however overkill, specially when m is large.
2017
        We try to estimate a better value.
2018
        jmax = prec - ((log2(prec)-1)*m).
2019
        Hence we need the leading bit of prec.
2020
        We are still overshooting a bit.
2021
*/
2022
        n = 0; x = xprec;
240✔
2023
        while ( x ) { x >>= 1; n++; }
1,920✔
2024
/* 
2025
        We have now n = floor(log2(x))+1. 
2026
*/
2027
        n--;
240✔
2028
        jmax = (int)((int)xprec - (n-1)*m);
240✔
2029
        if ( s < 0 ) jmax /= 2;
240✔
2030
        mpf_set_si(sum,0L);
240✔
2031
        for ( j = 1; j <= jmax; j++ ) {
8,988✔
2032
#ifdef WITHCUTOFF
2033
                xprec--;
8,508✔
2034
                mpf_set_prec_raw(jm,xprec);
8,508✔
2035
                mpf_set_prec_raw(jjm,xprec);
8,508✔
2036
#endif
2037
                mpf_set_ui(jm,1L);
8,508✔
2038
                mpf_div_ui(jjm,jm,(unsigned long)j);
8,508✔
2039
                mpf_pow_ui(jm,jjm,(unsigned long)m);
8,508✔
2040
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
8,508✔
2041
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
2042
                mpf_add(sum,sum,jjm);
8,508✔
2043
        }
2044
        mpf_clear(jjm); mpf_clear(jm);
240✔
2045
}
240✔
2046

2047
/*
2048
                 #] SimpleDeltaC : 
2049
                 #[ SingleTable :
2050
*/
2051

2052
void SingleTable(mpf_t *tabl, int N, int m, int pow)
3,606✔
2053
{
2054
/*
2055
        Creates a table T(1,...,N) with
2056
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
2057
        To make this table we have two options:
2058
        1: run the sum backwards with the potential problem that the 
2059
           precision is difficult to manage.
2060
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
2061
        When doing Euler sums we may need also 1/4^j
2062
        pow: 1 -> 1/2^j
2063
             2 -> 1/4^j
2064
*/
2065
        GETIDENTITY
2,404✔
2066
        long s = 1;
3,606✔
2067
        int j;
3,606✔
2068
#ifdef WITHCUTOFF
2069
        long prec = mpf_get_default_prec();
3,606✔
2070
#endif
2071
        mpf_t jm,jjm;
3,606✔
2072
        mpf_init(jm); mpf_init(jjm);
3,606✔
2073
        if ( pow < 1 || pow > 2 ) {
3,606✔
2074
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2075
                exit(-1);
×
2076
        }
2077
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
2078
        mpf_set_si(auxsum,0L);
3,606✔
2079
        for ( j = N; j > 0; j-- ) {
779,850✔
2080
#ifdef WITHCUTOFF
2081
                mpf_set_prec_raw(jm,prec-j);
772,638✔
2082
                mpf_set_prec_raw(jjm,prec-j);
772,638✔
2083
#endif
2084
                mpf_set_ui(jm,1L);
772,638✔
2085
                mpf_div_ui(jjm,jm,(unsigned long)j);
772,638✔
2086
                mpf_pow_ui(jm,jjm,(unsigned long)m);
772,638✔
2087
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
772,638✔
2088
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
772,638✔
2089
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
740,982✔
2090
                else                       mpf_add(auxsum,auxsum,jjm);
725,286✔
2091
/*
2092
                And now copy auxsum to tablelement j
2093
*/
2094
                mpf_set(tabl[j],auxsum);
772,638✔
2095
        }
2096
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
2097
}
3,606✔
2098

2099
/*
2100
                 #] SingleTable : 
2101
                 #[ DoubleTable :
2102
*/
2103

2104
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
4,674✔
2105
{
2106
        GETIDENTITY
3,116✔
2107
        long s = 1;
4,674✔
2108
#ifdef WITHCUTOFF
2109
        long prec = mpf_get_default_prec();
4,674✔
2110
#endif
2111
        int j;
4,674✔
2112
        mpf_t jm,jjm;
4,674✔
2113
        mpf_init(jm); mpf_init(jjm);
4,674✔
2114
        if ( pow < -1 || pow > 2 ) {
4,674✔
2115
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2116
                exit(-1);
×
2117
        }
2118
        if ( m < 0 ) { m = -m; s = -1; }
4,674✔
2119
        mpf_set_ui(auxsum,0L);
4,674✔
2120
        for ( j = N; j > 0; j-- ) {
1,709,796✔
2121
#ifdef WITHCUTOFF
2122
                mpf_set_prec_raw(jm,prec-j);
1,700,448✔
2123
                mpf_set_prec_raw(jjm,prec-j);
1,700,448✔
2124
#endif
2125
                mpf_set_ui(jm,1L);
1,700,448✔
2126
                mpf_div_ui(jjm,jm,(unsigned long)j);
1,700,448✔
2127
                mpf_pow_ui(jm,jjm,(unsigned long)m);
1,700,448✔
2128
                if ( pow == -1 ) {
1,700,448✔
2129
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
8,232✔
2130
                        mpf_mul(jm,jjm,tabin[j+1]);
8,232✔
2131
                }
2132
                else if ( pow > 0 ) {
1,692,216✔
2133
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
3,648✔
2134
                        mpf_mul(jm,jjm,tabin[j+1]);
3,648✔
2135
                }
2136
                else {
2137
                        mpf_mul(jm,jm,tabin[j+1]);
1,688,568✔
2138
                }
2139
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
1,700,448✔
2140
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
1,700,448✔
2141
                else                       mpf_add(auxsum,auxsum,jm);
1,694,496✔
2142
/*
2143
                And now copy auxsum to tablelement j
2144
*/
2145
                mpf_set(tabout[j],auxsum);
1,700,448✔
2146
        }
2147
        mpf_clear(jjm); mpf_clear(jm);
4,674✔
2148
}
4,674✔
2149

2150
/*
2151
                 #] DoubleTable : 
2152
                 #[ EndTable :
2153
*/
2154

2155
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
3,606✔
2156
{
2157
        long s = 1;
3,606✔
2158
#ifdef WITHCUTOFF
2159
        long prec = mpf_get_default_prec();
3,606✔
2160
#endif
2161
        int j;
3,606✔
2162
        mpf_t jm,jjm;
3,606✔
2163
        mpf_init(jm); mpf_init(jjm);
3,606✔
2164
        if ( pow < -1 || pow > 2 ) {
3,606✔
2165
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
2166
                exit(-1);
×
2167
        }
2168
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
2169
        mpf_set_si(sum,0L);
3,606✔
2170
        for ( j = N; j > 0; j-- ) {
770,970✔
2171
#ifdef WITHCUTOFF
2172
                mpf_set_prec_raw(jm,prec-j);
763,758✔
2173
                mpf_set_prec_raw(jjm,prec-j);
763,758✔
2174
#endif
2175
                mpf_set_ui(jm,1L);
763,758✔
2176
                mpf_div_ui(jjm,jm,(unsigned long)j);
763,758✔
2177
                mpf_pow_ui(jm,jjm,(unsigned long)m);
763,758✔
2178
                if ( pow == -1 ) {
763,758✔
2179
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
13,050✔
2180
                        mpf_mul(jm,jjm,tabin[j+1]);
13,050✔
2181
                }
2182
                else if ( pow > 0 ) {
750,708✔
2183
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
11,700✔
2184
                        mpf_mul(jm,jjm,tabin[j+1]);
11,700✔
2185
                }
2186
                else {
2187
                        mpf_mul(jm,jm,tabin[j+1]);
739,008✔
2188
                }
2189
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
763,758✔
2190
                else                       mpf_add(sum,sum,jm);
751,218✔
2191
        }
2192
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
2193
}
3,606✔
2194

2195
/*
2196
                 #] EndTable : 
2197
                 #[ deltaMZV :
2198
*/
2199

2200
void deltaMZV(mpf_t result, WORD *indexes, int depth)
7,566✔
2201
{
2202
        GETIDENTITY
5,044✔
2203
/*
2204
        Because all sums go roughly like 1/2^j we need about depth steps.
2205
*/
2206
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
2207
        if ( depth == 1 ) {
7,566✔
2208
                if ( indexes[0] == 1 ) {
3,804✔
2209
                        mpf_set(result,mpfdelta1);
1,650✔
2210
                        return;
1,650✔
2211
                }
2212
                SimpleDelta(result,indexes[0]);
2,154✔
2213
        }
2214
        else if ( depth == 2 ) {
3,762✔
2215
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
1,470✔
2216
                        mpf_pow_ui(result,mpfdelta1,2);
486✔
2217
                        mpf_div_2exp(result,result,1);
486✔
2218
                }
2219
                else {
2220
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
984✔
2221
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
984✔
2222
                };
2223
        }
2224
        else if ( depth > 2 ) {
2,292✔
2225
                mpf_t *mpftab3;
2226
                int d;
2227
/*
2228
                Check first whether this is a power of delta1 = ln(2)
2229
*/
2230
                for ( d = 0; d < depth; d++ ) {
7,548✔
2231
                        if ( indexes[d] != 1 ) break;
6,678✔
2232
                }
2233
                if ( d == depth ) {        /* divide by fac_(depth) */
2,292✔
2234
                        mpf_pow_ui(result,mpfdelta1,depth);
870✔
2235
                        for ( d = 2; d <= depth; d++ ) {
5,196✔
2236
                                mpf_div_ui(result,result,(unsigned long)d);
3,456✔
2237
                        }
2238
                }
2239
                else {
2240
                        d = depth-1;
1,422✔
2241
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
1,422✔
2242
                        d--; indexes++;
1,422✔
2243
                        for(;;) {
6,726✔
2244
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
4,074✔
2245
                                d--; indexes++;
4,074✔
2246
                                if ( d == 0 ) {
4,074✔
2247
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
1,422✔
2248
                                        break;
1,422✔
2249
                                }
2250
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
2,652✔
2251
                                AT.mpf_tab2 = (void *)mpftab3;
2,652✔
2252
                        }
2253
                }
2254
        }
2255
        else if ( depth == 0 ) {
×
2256
                mpf_set_ui(result,1L);
×
2257
        }
2258
}
2259

2260
/*
2261
                 #] deltaMZV : 
2262
                 #[ deltaEuler :
2263

2264
                Regular Euler delta with - signs, but everywhere 1/2^j
2265
*/
2266

2267
void deltaEuler(mpf_t result, WORD *indexes, int depth)
990✔
2268
{
2269
        GETIDENTITY
660✔
2270
        int m;
990✔
2271
#ifdef DEBUG
2272
        int i;
2273
        printf(" deltaEuler(");
2274
        for ( i = 0; i < depth; i++ ) {
2275
                if ( i != 0 ) printf(",");
2276
                printf("%d",indexes[i]);
2277
        }
2278
        printf(") = ");
2279
#endif
2280
        if ( depth == 1 ) {
990✔
2281
                SimpleDelta(result,indexes[0]);
390✔
2282
        }
2283
        else if ( depth == 2 ) {
600✔
2284
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
348✔
2285
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
348✔
2286
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,0);
348✔
2287
        }
2288
        else if ( depth > 2 ) {
252✔
2289
                int d;
252✔
2290
                mpf_t *mpftab3;
252✔
2291
                d = depth-1;
252✔
2292
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
252✔
2293
                d--; indexes++;
252✔
2294
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
252✔
2295
                for(;;) {
348✔
2296
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
300✔
2297
                        d--; indexes++;
300✔
2298
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
300✔
2299
                        if ( d == 0 ) {
300✔
2300
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
252✔
2301
                                break;
252✔
2302
                        }
2303
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2304
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2305
                }
2306
        }
2307
        else if ( depth == 0 ) {
×
2308
                mpf_set_ui(result,1L);
×
2309
        }
2310
#ifdef DEBUG
2311
        gmp_printf("%.*Fe\n",40,result);
2312
#endif
2313
}
990✔
2314

2315
/*
2316
                 #] deltaEuler : 
2317
                 #[ deltaEulerC :
2318

2319
                Conjugate Euler delta without - signs, but possibly 1/4^j
2320
                When there is a - in the string we have 1/4.
2321
*/
2322

2323
void deltaEulerC(mpf_t result, WORD *indexes, int depth)
990✔
2324
{
2325
        GETIDENTITY
660✔
2326
        int m;
990✔
2327
#ifdef DEBUG
2328
        int i;
2329
        printf(" deltaEulerC(");
2330
        for ( i = 0; i < depth; i++ ) {
2331
                if ( i != 0 ) printf(",");
2332
                printf("%d",indexes[i]);
2333
        }
2334
        printf(") = ");
2335
#endif
2336
        mpf_set_ui(result,0);
990✔
2337
        if ( depth == 1 ) {
990✔
2338
                if ( indexes[0] == 0 ) {
390✔
2339
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2340
                }
2341
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
390✔
2342
                else                  SimpleDelta(result,indexes[0]);
150✔
2343
        }
2344
        else if ( depth == 2 ) {
600✔
2345
                int par;
348✔
2346
                m = indexes[0];
348✔
2347
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth,-m,2);
348✔
2348
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth, m,1);
132✔
2349
                m = indexes[1];
348✔
2350
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
348✔
2351
                else { par = indexes[0] < 0 ? -1: 0; }
150✔
2352
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
348✔
2353
        }
2354
        else if ( depth > 2 ) {
252✔
2355
                int d, par;
252✔
2356
                mpf_t *mpftab3;
252✔
2357
                d = depth-1;
252✔
2358
                m = indexes[0];
252✔
2359
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
252✔
2360
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
252✔
2361
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
60✔
2362
                d--; indexes++; m = indexes[0];
252✔
2363
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
252✔
2364
                else { par = indexes[-1] < 0 ? -1: 0; }
120✔
2365
                for(;;) {
348✔
2366
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
300✔
2367
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
300✔
2368
                        d--; indexes++; m = indexes[0];
300✔
2369
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
300✔
2370
                        else { par = indexes[-1] < 0 ? -1: 0; }
144✔
2371
                        if ( d == 0 ) {
300✔
2372
                                mpf_set_ui(result,0);
252✔
2373
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
252✔
2374
                                break;
252✔
2375
                        }
2376
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2377
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2378
                }
2379
        }
2380
        else if ( depth == 0 ) {
×
2381
                mpf_set_ui(result,1L);
×
2382
        }
2383
#ifdef DEBUG
2384
        gmp_printf("%.*Fe\n",40,result);
2385
#endif
2386
}
990✔
2387

2388
/*
2389
                 #] deltaEulerC : 
2390
                 #[ CalculateMZVhalf :
2391

2392
                 This routine is mainly for support when large numbers of
2393
                MZV's have to be calculated at the same time.
2394
*/
2395

2396
void CalculateMZVhalf(mpf_t result, WORD *indexes, int depth)
378✔
2397
{
2398
        int i;
378✔
2399
        if ( depth < 0 ) {
378✔
2400
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
2401
                exit(-1);
×
2402
        }
2403
        for ( i = 0; i < depth; i++ ) {
1,530✔
2404
                if ( indexes[i] <= 0 ) {
1,152✔
2405
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2406
                        exit(-1);
×
2407
                }
2408
        }
2409
        deltaMZV(result,indexes,depth);
378✔
2410
}
378✔
2411

2412
/*
2413
                 #] CalculateMZVhalf : 
2414
                 #[ CalculateMZV :
2415
*/
2416

2417
void CalculateMZV(mpf_t result, WORD *indexes, int depth)
822✔
2418
{
2419
        GETIDENTITY
548✔
2420
        int num1, num2 = 0, i, j = 0;
822✔
2421
        if ( depth < 0 ) {
822✔
2422
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
2423
                exit(-1);
×
2424
        }
2425
        if ( indexes[0] == 1 ) {
822✔
2426
                printf("Divergent MZV in CalculateMZV\n");
×
2427
                exit(-1);
×
2428
        }
2429
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2430
        for ( i = 0; i < depth; i++ ) {
2,076✔
2431
                if ( indexes[i] <= 0 ) {
1,254✔
2432
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
2433
                        exit(-1);
×
2434
                }
2435
                AT.indi1[i] = indexes[i];
1,254✔
2436
        }
2437
        num1 = depth; i = 0;
822✔
2438
        deltaMZV(result,indexes,depth);
822✔
2439
        for(;;) {
6,366✔
2440
                if ( AT.indi1[0] > 1 ) {
3,594✔
2441
                        AT.indi1[0] -= 1;
2,340✔
2442
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
7,794✔
2443
                        AT.indi2[0] = 1; num2++;
2,340✔
2444
                }
2445
                else {
2446
                        AT.indi2[0] += 1;
1,254✔
2447
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,926✔
2448
                        num1--;
1,254✔
2449
                        if ( num1 == 0 ) break;
1,254✔
2450
                }
2451
                deltaMZV(aux1,AT.indi1,num1);
2,772✔
2452
                deltaMZV(aux2,AT.indi2,num2);
2,772✔
2453
                mpf_mul(aux3,aux1,aux2);
2,772✔
2454
                mpf_add(result,result,aux3);
2,772✔
2455
        }
2456
        deltaMZV(aux3,AT.indi2,num2);
822✔
2457
        mpf_add(result,result,aux3);
822✔
2458
}
822✔
2459

2460
/*
2461
                 #] CalculateMZV : 
2462
                 #[ CalculateEuler :
2463

2464
                There is a problem of notation here.
2465
                Basically there are two notations.
2466
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2467
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2468
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2469
                   See Broadhurst,1996
2470
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2471
                                 sum_(j2,1,inf,sign_(m2)*
2472
                                 sum_(j3,1,inf,sign_(m3)
2473
                                                        /j3^abs_(m3)
2474
                                                        /(j2+j3)^abs_(m2)
2475
                                                        /(j1+j2+j3)^abs_(m1) )))
2476
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2477
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2478
                The algorithm follows 2, but the more common notation is 1.
2479
                Hence we start with a conversion.
2480
*/
2481

2482
void CalculateEuler(mpf_t result, WORD *Zindexes, int depth)
318✔
2483
{
2484
        GETIDENTITY
212✔
2485
        int s1, num1, num2, i, j;
318✔
2486

2487
        WORD *indexes = AT.WorkPointer;
318✔
2488
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
1,128✔
2489
        for ( i = 0; i < depth-1; i++ ) {
810✔
2490
                if ( Zindexes[i] < 0 ) {
492✔
2491
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
864✔
2492
                }
2493
        }
2494

2495
        if ( depth < 0 ) {
318✔
2496
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
2497
                exit(-1);
×
2498
        }
2499
        if ( indexes[0] == 1 ) {
318✔
2500
                printf("Divergent Euler sum in CalculateEuler\n");
×
2501
                exit(-1);
×
2502
        }
2503
        for ( i = 0, j = 0; i < depth; i++ ) {
1,128✔
2504
                if ( indexes[i] == 0 ) {
810✔
2505
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2506
                        exit(-1);
×
2507
                }
2508
                if ( indexes[i] < 0 ) j = 1;
810✔
2509
                AT.indi1[i] = indexes[i];
810✔
2510
        }
2511
        if ( j == 0 ) {
318✔
2512
                CalculateMZV(result,indexes,depth);
42✔
2513
                return;
42✔
2514
        }
2515
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
276✔
2516
        deltaEuler(result,AT.indi1,depth);
276✔
2517
        s1 = 0;
276✔
2518
        for(;;) {
990✔
2519
                s1++;
990✔
2520
                if ( AT.indi1[0] > 1 ) {
990✔
2521
                        AT.indi1[0] -= 1;
90✔
2522
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
162✔
2523
                        AT.indi2[0] = 1; num2++;
90✔
2524
                }
2525
                else if ( AT.indi1[0] < -1 ) {
900✔
2526
                        AT.indi1[0] += 1;
162✔
2527
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
270✔
2528
                        AT.indi2[0] = 1; num2++;
162✔
2529
                }
2530
                else if ( AT.indi1[0] == -1 ) {
738✔
2531
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
1,026✔
2532
                        AT.indi2[0] = -1; num2++;
486✔
2533
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,026✔
2534
                        num1--;
486✔
2535
                }
2536
                else {
2537
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
252✔
2538
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
432✔
2539
                        num1--;
252✔
2540
                }
2541
                if ( num1 == 0 ) break;
990✔
2542
                deltaEuler(aux1,AT.indi1,num1);
714✔
2543
                deltaEulerC(aux2,AT.indi2,num2);
714✔
2544
                mpf_mul(aux3,aux1,aux2);
714✔
2545
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
714✔
2546
                else                               mpf_sub(result,result,aux3);
408✔
2547
        }
2548
        deltaEulerC(aux3,AT.indi2,num2);
276✔
2549
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
276✔
2550
        else                          mpf_sub(result,result,aux3);
162✔
2551
}
2552

2553
/*
2554
                 #] CalculateEuler : 
2555
                 #[ ExpandMZV :
2556
*/
2557

2558
int ExpandMZV(WORD *term, WORD level)
×
2559
{
2560
        DUMMYUSE(term);
×
2561
        DUMMYUSE(level);
×
2562
        return(0);
×
2563
}
2564

2565
/*
2566
                 #] ExpandMZV : 
2567
                 #[ ExpandEuler :
2568
*/
2569

2570
int ExpandEuler(WORD *term, WORD level)
×
2571
{
2572
        DUMMYUSE(term);
×
2573
        DUMMYUSE(level);
×
2574
        return(0);
×
2575
}
2576

2577
/*
2578
                 #] ExpandEuler : 
2579
                 #[ EvaluateEuler :
2580

2581
        There are various steps here:
2582
        1: locate an Euler function.
2583
        2: evaluate it into a float.
2584
        3: convert the coefficient to a float and multiply.
2585
        4: Put the new term together.
2586
        5: Restart to see whether there are more Euler functions.
2587
        The compiler should check that there is no conflict between
2588
        the evaluate command and a potential polyfun or polyratfun.
2589
        Yet, when reading in expressions there can be a conflict.
2590
        Hence the Normalize routine should check as well.
2591

2592
        par == MZV: MZV
2593
        par == EULER: Euler
2594
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2595
        par == ALLMZVFUNCTIONS: all of the above.
2596
*/
2597

2598
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
1,350✔
2599
{
2600
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
1,350✔
2601
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
1,350✔
2602
        int retval;
1,350✔
2603
        tstop = term + *term; tstop -= ABS(tstop[-1]);
1,350✔
2604
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
1,350✔
2605
/*
2606
        Step 1. We also need to verify that the argument we find is legal
2607
*/
2608
        t = term+1;
1,350✔
2609
        while ( t < tstop ) {
3,972✔
2610
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
2,622✔
2611
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
264✔
2612
        /* all arguments should be small integers */
2613
                        indexes = AT.WorkPointer;
1,494✔
2614
                        sumweight = 0; depth = 0;
1,494✔
2615
                        tnext = t + t[1]; tt = t + FUNHEAD;
1,494✔
2616
                        while ( tt < tnext ) {
4,638✔
2617
                                if ( *tt != -SNUMBER ) goto nextfun;
3,144✔
2618
                                if ( tt[1] == 0 ) goto nextfun;
3,144✔
2619
                                indexes[depth] = tt[1];
3,144✔
2620
                                sumweight += ABS(tt[1]); depth++;
3,144✔
2621
                                tt += 2;
3,144✔
2622
                        }
2623
                        /* euler sum without arguments, i.e. mzv_(), euler_() or mzvhalf_() */
2624
                        if ( depth == 0) goto nextfun;
1,494✔
2625
                        if ( sumweight > AC.MaxWeight ) {
1,476✔
2626
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
2627
                                MesPrint("Please increase MaxWeight in form.set.");
×
2628
                                Terminate(-1);
×
2629
                        }
2630
/*
2631
                        Step 2: evaluate:
2632
*/
2633
                        AT.WorkPointer += depth;
1,476✔
2634
                        if ( first ) {
1,476✔
2635
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
1,152✔
2636
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
696✔
2637
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
378✔
2638
                                first = 0;
2639
                        }
2640
                        else {
2641
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
324✔
2642
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
2643
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2644
                                mpf_mul(aux4,aux4,aux5);
324✔
2645
                        }
2646
                        *t = 0;
1,476✔
2647
                }
2648
nextfun:
1,128✔
2649
                t += t[1];
2,622✔
2650
        }
2651
        if ( first == 1 ) return(Generator(BHEAD term,level));
1,350✔
2652
/*
2653
        Step 3:
2654
        Now the regular coefficient, if it is not 1/1.
2655
        We have two cases: size +- 3, or bigger.
2656
*/
2657
        nsize = term[*term-1];
1,152✔
2658
        if ( nsize < 0 ) {
1,152✔
2659
                mpf_neg(aux4,aux4);
72✔
2660
                nsize = -nsize;
72✔
2661
        }
2662
        if ( nsize == 3 ) {
1,152✔
2663
                if ( tstop[0] != 1 ) {
1,152✔
2664
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
132✔
2665
                }
2666
                if ( tstop[1] != 1 ) {
1,152✔
2667
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
132✔
2668
                }
2669
        }
2670
        else {
2671
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2672
                mpf_mul(aux4,aux4,aux5);
×
2673
        }
2674
/*
2675
        Now we have to locate possible other float_ functions.
2676
*/
2677
        t = term+1;
2678
        while ( t < tstop ) {
3,510✔
2679
                if ( *t == FLOATFUN ) {
2,358✔
2680
                        UnpackFloat(aux5,t);
×
2681
                        mpf_mul(aux4,aux4,aux5);
×
2682
                }
2683
                t += t[1];
2,358✔
2684
        }
2685
/*
2686
        Now we should compose the new term in the WorkSpace.
2687
*/
2688
        t = term+1;
1,152✔
2689
        newterm = AT.WorkPointer;
1,152✔
2690
        tt = newterm+1;
1,152✔
2691
        while ( t < tstop ) {
1,152✔
2692
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
2,358✔
2693
                else {
2694
                        i = t[1]; NCOPY(tt,t,i);
11,922✔
2695
                }
2696
        }
2697
        PackFloat(tt,aux4);
1,152✔
2698
        tt += tt[1];
1,152✔
2699
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
1,152✔
2700
        *newterm = tt-newterm;
1,152✔
2701
        AT.WorkPointer = tt;
1,152✔
2702
        retval = Generator(BHEAD newterm,level);
1,152✔
2703
        AT.WorkPointer = oldworkpointer;
1,152✔
2704
        return(retval);
1,152✔
2705
}
2706

2707
/*
2708
                 #] EvaluateEuler : 
2709
          #] MZV : 
2710
          #[ Functions :
2711
                 #[ CoEvaluate :
2712

2713
                Current subkeys: mzv_, euler_ and sqrt_.
2714
*/
2715

2716
int CoEvaluate(UBYTE *s)
390✔
2717
{
2718
        GETIDENTITY
260✔
2719
        UBYTE *subkey, c;
390✔
2720
        WORD numfun, type;
390✔
2721
        int error = 0;
390✔
2722
        if ( AT.aux_ == 0 ) {
390✔
2723
                MesPrint("&Illegal attempt to evaluate a function without activating floating point numbers.");
6✔
2724
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
2725
                return(1);
6✔
2726
        }
2727
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
384✔
2728
        if ( *s == 0 ) {
384✔
2729
/*
2730
                No subkey, which means all functions.
2731
*/
2732
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
42✔
2733
/*
2734
                The MZV, EULER and MZVHALF are done separately
2735
*/
2736
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
42✔
2737
                return(0);        
42✔
2738
        }
2739
        while ( *s ) {
660✔
2740
        subkey = s;
2741
        while ( FG.cTable[*s] == 0 ) s++;
1,656✔
2742
          if ( *s == '2' ) s++; /* cases li2_ and atan2_ */
360✔
2743
          if ( *s == '_' ) s++;
360✔
2744
          c = *s; *s = 0;
360✔
2745
/*
2746
                We still need provisions for pi_ and possibly other constants.
2747
*/
2748
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
360✔
2749
                        || ( functions[numfun].spec != 0 ) ) {
318✔
2750

2751
                if ( type == CSYMBOL ) {
42✔
2752
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
36✔
2753
                        break;
36✔
2754
                }
2755
/*
2756
                        This cannot work.
2757
*/
2758
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
6✔
2759
                return(1);
6✔
2760
          }
2761
          else {
2762
                switch ( numfun+FUNCTION ) {
318✔
2763
                        case MZV:
318✔
2764
                        case EULER:
2765
                        case MZVHALF:
2766
/*
2767
                        The following functions are treated in evaluate.c
2768
*/
2769
                        case SQRTFUNCTION:
2770
                        case LNFUNCTION:
2771
                        case EXPFUNCTION:
2772
                        case SINFUNCTION:
2773
                        case COSFUNCTION:
2774
                        case TANFUNCTION:
2775
                        case ASINFUNCTION:
2776
                        case ACOSFUNCTION:
2777
                        case ATANFUNCTION:
2778
                        case ATAN2FUNCTION:
2779
                        case SINHFUNCTION:
2780
                        case COSHFUNCTION:
2781
                        case TANHFUNCTION:
2782
                        case ASINHFUNCTION:
2783
                        case ACOSHFUNCTION:
2784
                        case ATANHFUNCTION:
2785
                        case LI2FUNCTION:
2786
                        case LINFUNCTION:
2787
                        case AGMFUNCTION:
2788
                        case GAMMAFUN:
2789
/*
2790
                        At a later stage we can add more functions from mpfr here
2791
                                mpfr_(number,arg(s))
2792
*/
2793
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
318✔
2794
                                break;
318✔
2795
                        default:
×
2796
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2797
                                error = 1;
×
2798
                                break;
×
2799
                }
2800
          }
2801
          *s = c;
318✔
2802
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
336✔
2803
        }
2804
        return(error);
2805
}
2806

2807
/*
2808
                 #] CoEvaluate : 
2809
          #] Functions : 
2810
*/
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