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

form-dev / form / 16168567412

09 Jul 2025 11:52AM UTC coverage: 50.85% (+0.2%) from 50.603%
16168567412

push

github

cbmarini
fix: make float printing consistend and independent of MZV weight

- Removed double SetFloatPrecision call. Now only called once from DoStartFloat.
- Fixed precision handling in SimpleDelta and SimpleDeltaC.
- Adjusted printed digits to avoid overprinting from gmp_snprintf.

test: adjusted the test evaluate_symbol accordingly and added two tests for the evaluation of MZV's.

8 of 11 new or added lines in 2 files covered. (72.73%)

204 existing lines in 1 file now uncovered.

42194 of 82978 relevant lines covered (50.85%)

2136103.55 hits per line

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

44.02
/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, int *, int);
68
void deltaEuler(mpf_t, int *, int);
69
void deltaEulerC(mpf_t, int *, int);
70
void CalculateMZVhalf(mpf_t, int *, int);
71
void CalculateMZV(mpf_t, int *, int);
72
void CalculateEuler(mpf_t, int *, 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)
×
214
{
215
        int i;
×
216
        for ( i = 0; i < t->_mp_prec; i++ ) t->_mp_d[i] = 0;
×
217
        t->_mp_size = 0;
×
218
        t->_mp_exp = 0;
×
219
}
×
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)
540✔
271
{
272
        WORD *t, nlimbs, num, nnum;
540✔
273
        mp_limb_t *d = infloat->_mp_d; /* Pointer to the limbs.  */
540✔
274
        int i;
540✔
275
        long e = infloat->_mp_exp;
540✔
276
        
277
        t = fun;
540✔
278
        *t++ = FLOATFUN;
540✔
279
        t++;
540✔
280
        FILLFUN(t);
540✔
281
        *t++ = -SNUMBER;
540✔
282
        *t++ = infloat->_mp_prec;
540✔
283
        *t++ = -SNUMBER;
540✔
284
        *t++ = infloat->_mp_size;
540✔
285
/*
286
        Now the exponent which is a signed long
287
*/
288
        if ( e < 0 ) {
540✔
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 ) {
540✔
303
                        *t++ = -SNUMBER; *t++ = e;
540✔
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;
540✔
318
        if ( nlimbs == 0 ) {
540✔
319
        }
320
        else if ( nlimbs == 1 && (ULONG)(*d) < ((ULONG)1)<<(BITSINWORD-1) ) {
540✔
321
                *t++ = -SNUMBER;
×
322
                *t++ = (UWORD)(*d);
×
323
        }
324
        else {
325
          if ( d[nlimbs-1] < ((ULONG)1)<<BITSINWORD ) {
540✔
326
                num = 2*nlimbs-1; /* number of UWORDS needed */
396✔
327
          }
328
          else {
329
                num = 2*nlimbs;   /* number of UWORDS needed */
144✔
330
          }
331
          nnum = num;
540✔
332
          *t++ = 2*num+2+ARGHEAD;
540✔
333
          *t++ = 0;
540✔
334
          FILLARG(t);
540✔
335
          *t++ = 2*num+2;
540✔
336
          while ( num > 1 ) {
2,046✔
337
                *t++ = (UWORD)(*d); *t++ = (UWORD)(((ULONG)(*d))>>BITSINWORD); d++;
1,506✔
338
                num -= 2;
1,506✔
339
          }
340
          if ( num == 1 ) { *t++ = (UWORD)(*d); }
540✔
341
          *t++ = 1;
540✔
342
          for ( i = 1; i < nnum; i++ ) *t++ = 0;
3,408✔
343
          *t++ = 2*nnum+1; /* the sign is hidden in infloat->_mp_size */
540✔
344
        }
345
        fun[1] = t-fun;
540✔
346
        return(fun[1]);
540✔
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)
540✔
365
{
366
        UWORD *t;
540✔
367
        WORD *f;
540✔
368
        int num, i;
540✔
369
        mp_limb_t *d;
540✔
370
/*
371
        Very first step: check whether we can use float_:
372
*/
373
        GETIDENTITY
360✔
374
        if ( AT.aux_ == 0 ) {
540✔
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;
540✔
385
        f = fun + FUNHEAD + 2;
540✔
386
        if ( ABS(f[1]) > f[-1]+1 ) goto Incorrect;
540✔
387
        if ( f[1] > outfloat->_mp_prec+1
540✔
388
          || outfloat->_mp_d == 0 ) {
540✔
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];
540✔
400
        outfloat->_mp_size = num;
540✔
401
        if ( num < 0 ) { num = -num; }
540✔
402
        f += 2;
540✔
403
        if ( *f == -SNUMBER ) {
540✔
404
                outfloat->_mp_exp = (mp_exp_t)(f[1]);
540✔
405
                f += 2;
540✔
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;
540✔
422
        if ( outfloat->_mp_size == 0 ) {
540✔
423
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
×
424
                return(0);
425
        }
426
        else if ( *f == -SNUMBER ) {
540✔
427
                *d++ = (mp_limb_t)f[1];
×
428
                for ( i = 0; i < outfloat->_mp_prec; i++ ) *d++ = 0;
×
429
                return(0);
430
        }
431
        num = (*f-ARGHEAD-2)/2; /* 2*number of limbs in the argument */
540✔
432
        t = (UWORD *)(f+ARGHEAD+1);
540✔
433
        while ( num > 1 ) {
2,046✔
434
                *d++ = (mp_limb_t)((((ULONG)(t[1]))<<BITSINWORD)+t[0]);
1,506✔
435
                t += 2; num -= 2;
1,506✔
436
        }
437
        if ( num == 1 ) *d++ = (mp_limb_t)((UWORD)(*t));
540✔
438
        for ( i = d-outfloat->_mp_d; i <= outfloat->_mp_prec; i++ ) *d++ = 0;
828✔
439
        return(0);
440
Incorrect:
540✔
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)
1,140✔
453
{
454
        WORD *fstop, *f, num, nnum, i;
1,140✔
455
        fstop = fun+fun[1];
1,140✔
456
        f = fun + FUNHEAD;
1,140✔
457
        num = 0;
1,140✔
458
/*
459
        Count arguments
460
*/
461
        while ( f < fstop ) { num++; NEXTARG(f); }
5,700✔
462
        if ( num != 4 ) return(0);
1,140✔
463
        f = fun + FUNHEAD;
1,140✔
464
        if ( *f != -SNUMBER ) return(0);
1,140✔
465
        if ( f[1] < 0 ) return(0);
1,140✔
466
        f += 2;
1,140✔
467
        if ( *f != -SNUMBER ) return(0);
1,140✔
468
        num = ABS(f[1]); /* number of limbs */
1,140✔
469
        f += 2;
1,140✔
470
        if ( *f == -SNUMBER ) { f += 2; }
1,140✔
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);
1,140✔
479
        if ( *f == -SNUMBER ) { if ( num != 1 ) return(0); }
1,140✔
480
        else {
481
                nnum = (ABS(f[*f-1])-1)/2;
1,140✔
482
                if ( ( *f != 4*num+2+ARGHEAD ) && ( *f != 4*num+ARGHEAD ) ) return(0);
1,140✔
483
                if ( ( nnum != 2*num ) && ( nnum != 2*num-1 ) ) return(0);
1,140✔
484
                f += ARGHEAD+nnum+1;
1,140✔
485
                if ( f[0] != 1 ) return(0);
1,140✔
486
                for ( i = 1; i < nnum; i++ ) {
7,242✔
487
                        if ( f[i] != 0 ) return(0);
6,102✔
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)
228✔
512
{
513
        int nlimbs, sgn = 1;
228✔
514
        mp_limb_t *d;
228✔
515
        UWORD *b = a;
228✔
516
        WORD nb = na;
228✔
517

518
        if ( nb == 0 ) {
228✔
519
                z->_mp_size = 0;
×
520
                z->_mp_d[0] = 0;
×
521
                return;
×
522
        }
523
        if ( nb < 0 ) { sgn = -1; nb = -nb; }
228✔
524
        nlimbs = (nb+1)/2;
228✔
525
        if ( mpz_cmp_si(z,0L) <= 1 ) {
228✔
526
                mpz_set_ui(z,10000000);
228✔
527
        }
528
        if ( z->_mp_alloc <= nlimbs ) {
228✔
529
                mpz_t zz;
228✔
530
                mpz_init(zz);
228✔
531
                while ( z->_mp_alloc <= nlimbs ) {
684✔
532
                        mpz_mul(zz,z,z);
456✔
533
                        mpz_set(z,zz);
456✔
534
                }
535
                mpz_clear(zz);
228✔
536
        }
537
        z->_mp_size = sgn*nlimbs;
228✔
538
        d = z->_mp_d;
228✔
539
        while ( nb > 1 ) {
228✔
540
                *d++ = (((mp_limb_t)(b[1]))<<BITSINWORD)+(mp_limb_t)(b[0]);
×
541
                b += 2; nb -= 2;
×
542
        }
543
        if ( nb == 1 ) { *d = (mp_limb_t)(*b); }
228✔
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)
×
556
{
557
        mp_limb_t *d = z->_mp_d;
×
558
        int nlimbs = ABS(z->_mp_size), i;
×
559
        UWORD j;
×
560
        if ( nlimbs == 0 ) { *na = 0; return; }
×
561
        *na = 0;
×
562
        for ( i = 0; i < nlimbs-1; i++ ) {
×
563
                *a++ = (UWORD)(*d);
×
564
                *a++ = (UWORD)((*d++)>>BITSINWORD);
×
565
                *na += 2;
×
566
        }
567
        *na += 1;
×
568
        *a++ = (UWORD)(*d);
×
569
        j = (UWORD)((*d)>>BITSINWORD);
×
570
        if ( j != 0 ) { *a = j; *na += 1; }
×
571
        if ( z->_mp_size < 0 ) *na = -*na;
×
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)
×
582
{
583
        mpz_t z;
×
584
        WORD nout, nx;
×
585
        UWORD x;
×
586
        mpz_init(z);
×
587
        mpz_set_f(z,floatin);
×
588
        ZtoForm(out,&nout,z);
×
589
        mpz_clear(z);
×
590
        x = out[0]; nx = 0;
×
591
        while ( x ) { nx++; x >>= 1; }
×
592
        *bitsused = (nout-1)*BITSINWORD + nx;
×
593
        return(nout);
×
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)
228✔
605
{
606
        mpz_t z;
228✔
607
        mpz_init(z);
228✔
608
        FormtoZ(z,formlong,longsize);
228✔
609
        mpf_set_z(result,z);
228✔
610
        mpz_clear(z);
228✔
611
}
228✔
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)
114✔
621
{
622
        GETIDENTITY
76✔
623
        int nnum, nden;
114✔
624
        UWORD *num, *den;
114✔
625
        int sgn = 0;
114✔
626
        if ( ratsize < 0 ) { ratsize = -ratsize; sgn = 1; }
114✔
627
        nnum = nden = (ratsize-1)/2;
114✔
628
        num = formrat; den = formrat+nnum;
114✔
629
        while ( num[nnum-1] == 0 ) { nnum--; }
114✔
630
        while ( den[nden-1] == 0 ) { nden--; }
114✔
631
        IntegerToFloat(aux2,num,nnum);
114✔
632
        IntegerToFloat(aux3,den,nden);
114✔
633
        mpf_div(result,aux2,aux3);
114✔
634
        if ( sgn > 0 ) mpf_neg(result,result);
114✔
635
}
114✔
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)
×
669
{
670
        GETIDENTITY
671
        WORD *out = AT.WorkPointer;
×
672
        WORD s; /* the sign. */
×
673
        UWORD *a, *b, *c, *d, *mc;
×
674
        WORD na, nb, nc, nd, i;
×
675
        int nout;
×
676
        LONG oldpWorkPointer = AT.pWorkPointer;
×
677
        long bitsused = 0, totalbitsused = 0, totalbits = AC.DefaultPrecision;
×
678
        int retval = 0, startnul;
×
679
        WantAddPointers(AC.DefaultPrecision);  /* Horrible overkill */
×
680
        AT.pWorkSpace[AT.pWorkPointer++] = out;
×
681
        a = NumberMalloc("FloatToRat");
×
682
        b = NumberMalloc("FloatToRat");
×
683

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

687
        Form_mpf_empty(aux1);
×
688
        Form_mpf_empty(aux2);
×
689
        Form_mpf_empty(aux3);
×
690

691
        mpf_trunc(aux1,floatin);     /* This should now be an integer */
×
692
        mpf_sub(aux2,floatin,aux1);  /* and this >= 0 */
×
693
        if ( mpf_sgn(aux1) == 0 ) { *out++ = 0; startnul = 1; }
×
694
        else {
695
                nout = FloatToInteger((UWORD *)out,aux1,&totalbitsused);
×
696
                out += nout;
×
697
                startnul = 0;
×
698
        }
699
        AT.pWorkSpace[AT.pWorkPointer++] = out;
×
700
        if ( mpf_sgn(aux2) ) {
×
701
          for(;;) {
×
702
                mpf_ui_div(aux3,1,aux2);
×
703
                mpf_trunc(aux1,aux3);
×
704
                mpf_sub(aux2,aux3,aux1);
×
705
                if ( mpf_sgn(aux1) == 0 ) { *out++ = 0; }
×
706
                else {
707
                        nout = FloatToInteger((UWORD *)out,aux1,&bitsused);
×
708
                        out += nout;
×
709
                        totalbitsused += bitsused;
×
710
                }
711
                if ( bitsused > (totalbits-totalbitsused)/2 ) { break; }
×
712
                if ( mpf_sgn(aux2) == 0 ) {
×
713
                        /*if ( startnul == 1 )*/ AT.pWorkSpace[AT.pWorkPointer++] = out;
×
714
                        break;
×
715
                }
716
                AT.pWorkSpace[AT.pWorkPointer++] = out;
×
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]);
×
730
          na = 1; a[0] = 1;
×
731
          c = (UWORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
×
732
          nc = nb = ((UWORD *)out)-c;
×
733
          if ( nc > 10 ) {
×
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];
×
739
          mc = c = NumberMalloc("FloatToRat");
×
740
          while ( AT.pWorkPointer > oldpWorkPointer ) {
×
741
                d = (UWORD *)(AT.pWorkSpace[--AT.pWorkPointer]);
×
742
                nd = (UWORD *)(AT.pWorkSpace[AT.pWorkPointer+1])-d; /* This is the x1 in the formula */
×
743
                if ( nd == 1 && *d == 0 ) break;
×
744
                c = a; a = b; b = c; nc = na; na = nb; nb = nc; /* 1/x2 */
×
745
                MulLong(d,nd,a,na,mc,&nc);
×
746
                AddLong(mc,nc,b,nb,b,&nb);
×
747
          }
748
          NumberFree(mc,"FloatToRat");
×
749
          if ( startnul == 0 ) {
×
750
                c = a; a = b; b = c; nc = na; na = nb; nb = nc;
×
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;
×
763
        if ( na == nb ) {
×
764
                *nratout = (2*na+1)*s;
×
765
                for ( i = 0; i < na; i++ ) *d++ = a[i];
×
766
                for ( i = 0; i < nb; i++ ) *d++ = b[i];
×
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);
×
781
        NumberFree(b,"FloatToRat");
×
782
        NumberFree(a,"FloatToRat");
×
783
        AT.pWorkPointer = oldpWorkPointer;
×
784
/*
785
        Just for check we go back to float
786
*/
787
        if ( s < 0 ) mpf_neg(floatin,floatin);
×
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);
×
797
}
798

799
/*
800
                 #] FloatToRat : 
801
                 #[ ZeroTable :
802
*/
803
        
804
void ZeroTable(mpf_t *tab, int N)
×
805
{
806
        int i, j;
×
807
        for ( i = 0; i < N; i++ ) {
×
808
                for ( j = 0; j < tab[i]->_mp_prec; j++ ) tab[i]->_mp_d[j] = 0;
×
809
        }
810
}
×
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)
×
823
{
824
        GETIDENTITY
825
        SBYTE *ss, c;
×
826
        ss = s;
×
827
        while ( *ss > 0 ) ss++;
×
828
        c = *ss; *ss = 0;
×
829
        gmp_sscanf((char *)s,"%Ff",aux1);
×
830
        if ( AT.WorkPointer > AT.WorkTop ) {
×
831
                MLOCK(ErrorMessageLock);
×
832
                MesWork();
×
833
                MUNLOCK(ErrorMessageLock);
×
834
                Terminate(-1);
×
835
        }
836
        PackFloat(AT.WorkPointer,aux1);
×
837
        *ss = c;
×
838
        return(ss);
×
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)
2,009,184✔
849
{
850
        GETIDENTITY
1,339,448✔
851
        UBYTE *s = ss;
2,009,184✔
852
        int zero = 1, gotdot = 0;
2,009,184✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
5,922,426✔
854
        *spec = 0;
2,009,184✔
855
        if ( FG.cTable[*s] == 1 ) {
2,009,184✔
856
                while ( *s == '0' ) s++;
2,105,310✔
857
                if ( FG.cTable[*s] == 1 ) {
2,009,184✔
858
                        s++;
1,913,136✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
3,817,158✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
2,009,184✔
863
        }
864
        else if ( *s == '.' ) {
×
865
dot:
×
866
                gotdot = 1;
×
867
                s++;
×
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
×
869
                while ( *s == '0' ) s++;
×
870
                if ( FG.cTable[*s] == 1 ) {
×
871
                        s++;
×
872
                        while ( FG.cTable[*s] == 1 ) s++;
×
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' ) {
2,009,184✔
882
                s++;
×
883
                if ( *s == '-' || *s == '+' ) s++;
×
884
                if ( FG.cTable[*s] == 1 ) {
×
885
                        s++;
×
886
                        while ( FG.cTable[*s] == 1 ) s++;
×
887
                }
888
                else { return(ss); }
889
        }
890
        else if ( gotdot == 0 ) return(ss);
2,009,184✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
×
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
×
896
        return(s);
897
}
898

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

905
                We set the default precision of the floats and allocate
906
                space for an output string if we want to write the float.
907
                Space needed: exponent: up to 12 chars.
908
                mantissa 2+10*prec/33 + a little bit extra.
909
*/
910

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

927
/*
928
                 #] SetFloatPrecision : 
929
                 #[ PrintFloat :
930

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

940
int PrintFloat(WORD *fun,int numdigits)
426✔
941
{
942
        GETIDENTITY
284✔
943
        int n = 0;
426✔
944
        int prec = (AC.DefaultPrecision-AC.MaxWeight-1)*log10(2.0);
426✔
945
        if ( numdigits > prec || numdigits == 0 ) {
426✔
946
                numdigits = prec;
426✔
947
        }
948
/* 
949
        GMP's gmp_snprintf always prints a non-zero number before the decimal point, so we 
950
        ask for one digit less. 
951
*/
952
        if ( UnpackFloat(aux4,fun) == 0 )
426✔
953
                n = gmp_snprintf((char *)(AO.floatspace),AO.floatsize,"%.*Fe",numdigits-1,aux4);
426✔
954
        if ( numdigits == prec ) {
426✔
955
                UBYTE *s1, *s2;
426✔
956
                int n1, n2 = n;
426✔
957
                s1 = AO.floatspace+n;
426✔
958
                while ( s1 > AO.floatspace && s1[-1] != 'e'
2,130✔
959
                 && s1[-1] != 'E' && s1[-1] != '.' ) { s1--; n2--; }
1,704✔
960
                if ( s1 > AO.floatspace && s1[-1] != '.' ) {
426✔
961
                        s1--; n2--;
426✔
962
                        s2 = s1; n1 = n2;
426✔
963
                        while ( s1[-1] == '0' ) { s1--; n1--; }
2,268✔
964
                        if ( s1[-1] == '.' ) { s1++; n1++; }
426✔
965
                        while ( n2 < n ) { *s1++ = *s2++; n2++; }
2,130✔
966
                        n -= (n2-n1);
426✔
967
                        *s1 = 0;
426✔
968
                }
969
        }
970
        return(n);
426✔
971
}
972

973
/*
974
                 #] PrintFloat : 
975
                 #[ AddFloats :
976
*/
977

978
int AddFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
979
{
980
        int retval = 0;
×
981
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
982
                mpf_add(aux1,aux1,aux2);
×
983
                PackFloat(fun3,aux1);
×
984
        }
985
        else { retval = -1; }
986
        return(retval);
×
987
}
988

989
/*
990
                 #] AddFloats : 
991
                 #[ MulFloats :
992
*/
993

994
int MulFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
995
{
996
        int retval = 0;
×
997
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
998
                mpf_mul(aux1,aux1,aux2);
×
999
                PackFloat(fun3,aux1);
×
1000
        }
1001
        else { retval = -1; }
1002
        return(retval);
×
1003
}
1004

1005
/*
1006
                 #] MulFloats : 
1007
                 #[ DivFloats :
1008
*/
1009

1010
int DivFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2)
×
1011
{
1012
        int retval = 0;
×
1013
        if ( UnpackFloat(aux1,fun1) == 0 && UnpackFloat(aux2,fun2) == 0 ) {
×
1014
                mpf_div(aux1,aux1,aux2);
×
1015
                PackFloat(fun3,aux1);
×
1016
        }
1017
        else { retval = -1; }
1018
        return(retval);
×
1019
}
1020

1021
/*
1022
                 #] DivFloats : 
1023
                 #[ AddRatToFloat :
1024

1025
                Note: this can be optimized, because often the rat is rather simple.
1026
*/
1027

1028
int AddRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat)
×
1029
{
1030
        int retval = 0;
×
1031
        if ( UnpackFloat(aux2,infun) == 0 ) {
×
1032
                RatToFloat(aux1,formrat,nrat);
×
1033
                mpf_add(aux2,aux2,aux1);
×
1034
                PackFloat(outfun,aux2);
×
1035
        }
1036
        else retval = -1;
1037
        return(retval);
×
1038
}
1039

1040
/*
1041
                 #] AddRatToFloat : 
1042
                 #[ MulRatToFloat :
1043

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

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

1059
/*
1060
                 #] MulRatToFloat : 
1061
                 #[ SetupMZVTables :
1062
*/
1063

1064
void SetupMZVTables(void)
156✔
1065
{
1066
/*
1067
        Sets up a table of N+1 mpf_t floats with variable precision.
1068
        It assumes that each next element needs one bit less.
1069
        Initializes all of them.
1070
        We take some extra space, to have one limb overflow everywhere.
1071
        Because the depth of the MZV's can get close to the weight
1072
        and each deeper sum goes one higher, we make the tablesize a bit bigger.
1073
        This may not be needed if we fiddle with the sum boundaries.
1074
*/
1075
#ifdef WITHPTHREADS
1076
        int i, Nw, id, totnum;
104✔
1077
        size_t N;
104✔
1078
        mpf_t *a;
104✔
1079
        Nw = AC.DefaultPrecision;
104✔
1080
        N = (size_t)Nw;
104✔
1081
        totnum = AM.totalnumberofthreads;
104✔
1082
    for ( id = 0; id < totnum; id++ ) {
520✔
1083
                if ( AB[id]->T.mpf_tab1 ) {
416✔
1084
                        a = (mpf_t *)AB[id]->T.mpf_tab1;
1085
                        for ( i = 0; i <=Nw; i++ ) {
1086
                                mpf_clear(a[i]);
1087
                        }
1088
                        M_free(AB[id]->T.mpf_tab1,"mpftab1");
1089
                }
1090
                AB[id]->T.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
416✔
1091
                a = (mpf_t *)AB[id]->T.mpf_tab1;
416✔
1092
                for ( i = 0; i <=Nw; i++ ) {
19,920✔
1093
/*
1094
        As explained in the comment above, we could make this variable precision
1095
        using mpf_init2.
1096
*/
1097
                        mpf_init(a[i]);
19,504✔
1098
                }
1099
                if ( AB[id]->T.mpf_tab2 ) {
416✔
1100
                        a = (mpf_t *)AB[id]->T.mpf_tab2;
1101
                        for ( i = 0; i <=Nw; i++ ) {
1102
                                mpf_clear(a[i]);
1103
                        }
1104
                        M_free(AB[id]->T.mpf_tab2,"mpftab2");
1105
                }
1106
                AB[id]->T.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
416✔
1107
                a = (mpf_t *)AB[id]->T.mpf_tab2;
416✔
1108
                for ( i = 0; i <=Nw; i++ ) {
19,920✔
1109
                        mpf_init(a[i]);
19,504✔
1110
                }
1111
        }
1112
#else
1113
        int i, Nw;
52✔
1114
        size_t N;
52✔
1115
        Nw = AC.DefaultPrecision;
52✔
1116
        N = (size_t)Nw;
52✔
1117
        if ( AT.mpf_tab1 ) {
52✔
1118
                for ( i = 0; i <= Nw; i++ ) {
1119
                        mpf_clear(mpftab1[i]);
1120
                }
1121
                M_free(AT.mpf_tab1,"mpftab1");
1122
        }
1123
        AT.mpf_tab1 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab1");
52✔
1124
        for ( i = 0; i <= Nw; i++ ) {
2,490✔
1125
/*
1126
        As explained in the comment above, we could make this variable precision
1127
        using mpf_init2.
1128
*/
1129
                mpf_init(mpftab1[i]);
2,438✔
1130
        }
1131
        if ( AT.mpf_tab2 ) {
52✔
1132
                for ( i = 0; i <= Nw; i++ ) {
1133
                        mpf_clear(mpftab2[i]);
1134
                }
1135
                M_free(AT.mpf_tab2,"mpftab2");
1136
        }
1137
        AT.mpf_tab2 = (void *)Malloc1((N+2)*sizeof(mpf_t),"mpftab2");
52✔
1138
        for ( i = 0; i <= Nw; i++ ) {
2,490✔
1139
                mpf_init(mpftab2[i]);
2,438✔
1140
        }
1141
#endif
1142
        if ( AS.delta_1 ) {
156✔
UNCOV
1143
                mpf_clear(mpfdelta1);
×
UNCOV
1144
                M_free(AS.delta_1,"delta1");
×
1145
        }
1146
        AS.delta_1 = (void *)Malloc1(sizeof(mpf_t),"delta1");
156✔
1147
        mpf_init(mpfdelta1);
156✔
1148
        SimpleDelta(mpfdelta1,1); /* this can speed up things. delta1 = ln(2) */
156✔
1149
/*
1150
        Finally the character buffer for printing
1151
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1152
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1153
*/
1154
}
156✔
1155

1156
/*
1157
                 #] SetupMZVTables : 
1158
                 #[ SetupMPFTables :
1159
*/
1160

1161
void SetupMPFTables(void)
180✔
1162
{
1163
#ifdef WITHPTHREADS
1164
        int id, totnum;
120✔
1165
        mpf_t *a;
120✔
1166
/*
1167
        Now the aux variables
1168
*/
1169
#ifdef WITHSORTBOTS
1170
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
120✔
1171
#endif
1172
    for ( id = 0; id < totnum; id++ ) {
720✔
1173
                if ( AB[id]->T.aux_ ) {
600✔
1174
/*
1175
                        We work here with a[0] etc because the aux1 etc contain B which
1176
                        in the current routine would be AB[0] only
1177
*/
1178
                        a = (mpf_t *)AB[id]->T.aux_;
1179
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
1180
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
1181
                }
1182
                AB[id]->T.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AB[id]->T.aux_");
600✔
1183
                a = (mpf_t *)AB[id]->T.aux_;
600✔
1184
                mpf_inits(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
600✔
1185
                if ( AB[id]->T.indi1 ) M_free(AB[id]->T.indi1,"indi1");
600✔
1186
                AB[id]->T.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
600✔
1187
                AB[id]->T.indi2 = AB[id]->T.indi1 + AC.MaxWeight;
600✔
1188
        }
1189
#else
1190
/*
1191
        Now the aux variables
1192
*/
1193
        if ( AT.aux_ ) {
60✔
1194
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
1195
                M_free(AT.aux_,"AT.aux");
1196
        }
1197
        AT.aux_ = (void *)Malloc1(sizeof(mpf_t)*8,"AT.aux_");
60✔
1198
        mpf_inits(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
60✔
1199
        if ( AT.indi1 ) M_free(AT.indi1,"indi1");
60✔
1200
        AT.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
60✔
1201
        AT.indi2 = AT.indi1 + AC.MaxWeight;
60✔
1202
#endif
1203
/*
1204
        Finally the character buffer for printing
1205
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1206
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1207
*/
1208
}
180✔
1209

1210
/*
1211
                 #] SetupMPFTables : 
1212
                 #[ ClearMZVTables :
1213
*/
1214

1215
void ClearMZVTables(void)
156✔
1216
{
1217
#ifdef WITHPTHREADS
1218
        int i, id, totnum;
104✔
1219
        mpf_t *a;
104✔
1220
        totnum = AM.totalnumberofthreads;
104✔
1221
    for ( id = 0; id < totnum; id++ ) {
520✔
1222
                if ( AB[id]->T.mpf_tab1 ) { 
416✔
1223
/*
1224
                        We work here with a[0] etc because the aux1, mpftab1 etc contain B 
1225
                        which in the current routine would be AB[0] only
1226
*/
1227
                        a = (mpf_t *)AB[id]->T.mpf_tab1;
19,920✔
1228
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
19,920✔
1229
                                mpf_clear(a[i]);
19,504✔
1230
                        }
1231
                        M_free(AB[id]->T.mpf_tab1,"mpftab1"); 
416✔
1232
                        AB[id]->T.mpf_tab1 = 0; 
416✔
1233
                }
1234
                if ( AB[id]->T.mpf_tab2 ) { 
416✔
1235
                        a = (mpf_t *)AB[id]->T.mpf_tab2;
19,920✔
1236
                        for ( i = 0; i <=AC.DefaultPrecision; i++ ) {
19,920✔
1237
                                mpf_clear(a[i]);
19,504✔
1238
                        }
1239
                        M_free(AB[id]->T.mpf_tab2,"mpftab2"); 
416✔
1240
                        AB[id]->T.mpf_tab2 = 0; 
416✔
1241
                }
1242
        }
1243
#ifdef WITHSORTBOTS
1244
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
104✔
1245
#endif
1246
    for ( id = 0; id < totnum; id++ ) {
624✔
1247
                if ( AB[id]->T.aux_ ) { 
520✔
1248
                        a = (mpf_t *)AB[id]->T.aux_;
520✔
1249
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
520✔
1250
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
520✔
1251
                        AB[id]->T.aux_ = 0; 
520✔
1252
                }
1253
                if ( AB[id]->T.indi1 ) { M_free(AB[id]->T.indi1,"indi1"); AB[id]->T.indi1 = 0; }
520✔
1254
        }
1255
#else
1256
        int i;
52✔
1257
        if ( AT.mpf_tab1 ) { 
52✔
1258
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
2,490✔
1259
                        mpf_clear(mpftab1[i]);
2,438✔
1260
                }
1261
                M_free(AT.mpf_tab1,"mpftab1"); 
52✔
1262
                AT.mpf_tab1 = 0; 
52✔
1263
        }
1264
        if ( AT.mpf_tab2 ) { 
52✔
1265
                for ( i = 0; i <= AC.DefaultPrecision; i++ ) {
2,490✔
1266
                        mpf_clear(mpftab2[i]);
2,438✔
1267
                }
1268
                M_free(AT.mpf_tab2,"mpftab2"); 
52✔
1269
                AT.mpf_tab2 = 0; 
52✔
1270
        }
1271
        if ( AT.aux_ ) { 
52✔
1272
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
52✔
1273
                M_free(AT.aux_,"AT.aux_"); 
52✔
1274
                AT.aux_ = 0; 
52✔
1275
        }
1276
        if ( AT.indi1 ) { M_free(AT.indi1,"indi1"); AT.indi1 = 0; }
52✔
1277
#endif
1278
        if ( AO.floatspace ) { M_free(AO.floatspace,"floatspace"); AO.floatspace = 0;
156✔
1279
                AO.floatsize = 0; }
156✔
1280
        if ( AS.delta_1 ) { 
156✔
1281
                mpf_clear(mpfdelta1);
156✔
1282
                M_free(AS.delta_1,"delta1"); 
156✔
1283
                AS.delta_1 = 0; 
156✔
1284
        }
1285
}
156✔
1286

1287
/*
1288
                 #] ClearMZVTables : 
1289
                 #[ CoToFloat :
1290
*/
1291

1292
int CoToFloat(UBYTE *s)
24✔
1293
{
1294
        GETIDENTITY
16✔
1295
        if ( AT.aux_ == 0 ) {
24✔
1296
                MesPrint("&Illegal attempt to convert to float_ without activating floating point numbers.");
×
1297
                MesPrint("&Forgotten %#startfloat instruction?");
×
1298
                return(1);
×
1299
        }
1300
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
24✔
1301
        if ( *s ) {
24✔
UNCOV
1302
                MesPrint("&Illegal argument(s) in ToFloat statement: '%s'",s);
×
UNCOV
1303
                return(1);
×
1304
        }
1305
        Add2Com(TYPETOFLOAT);
24✔
1306
        return(0);
24✔
1307
}
1308

1309
/*
1310
                 #] CoToFloat : 
1311
                 #[ CoToRat :
1312
*/
1313

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

1331
/*
1332
                 #] CoToRat : 
1333
                 #[ ToFloat :
1334

1335
                Converts the coefficient to floating point if it is still a rat.
1336
*/
1337

1338
int ToFloat(PHEAD WORD *term, WORD level)
114✔
1339
{
1340
        WORD *t, *tstop, nsize, nsign = 3;
114✔
1341
        t = term+*term;
114✔
1342
        nsize = ABS(t[-1]);
114✔
1343
        tstop = t - nsize;
114✔
1344
        if ( t[-1] < 0 ) { nsign = -nsign; }
114✔
1345
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
114✔
1346
                t = term + 1;
108✔
1347
                while ( t < tstop ) {
222✔
1348
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
114✔
1349
                                return(Generator(BHEAD term,level));
×
1350
                        }
1351
                        t += t[1];
114✔
1352
                }
1353
        }
1354
        RatToFloat(aux4,(UWORD *)tstop,nsize);
114✔
1355
        PackFloat(tstop,aux4);
114✔
1356
        tstop += tstop[1];
114✔
1357
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
114✔
1358
        *term = tstop - term;
114✔
1359
        AT.WorkPointer = tstop;
114✔
1360
        return(Generator(BHEAD term,level));
114✔
1361
}
1362

1363
/*
1364
                 #] ToFloat : 
1365
                 #[ ToRat :
1366

1367
                Tries to convert the coefficient to rational if it is still a float.
1368
*/
1369

UNCOV
1370
int ToRat(PHEAD WORD *term, WORD level)
×
1371
{
UNCOV
1372
        WORD *tstop, *t, nsize, nsign, ncoef;
×
1373
/*
1374
        1: find the float which should be at the end.
1375
*/
UNCOV
1376
        tstop = term + *term; nsize = ABS(tstop[-1]);
×
UNCOV
1377
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
×
UNCOV
1378
        t = term+1;
×
UNCOV
1379
        while ( t < tstop ) {
×
UNCOV
1380
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
×
UNCOV
1381
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
×
UNCOV
1382
                t += t[1];
×
1383
        }
UNCOV
1384
        if ( t < tstop ) {
×
1385
/*
1386
                Now t points at the float_ function and everything is correct.
1387
                The result can go straight over the float_ function.
1388
*/
UNCOV
1389
                UnpackFloat(aux4,t);
×
UNCOV
1390
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
×
UNCOV
1391
                        t += ABS(ncoef);
×
UNCOV
1392
                        t[-1] = ncoef*nsign;
×
UNCOV
1393
                        *term = t - term;
×
1394
                }
1395
        }
UNCOV
1396
        return(Generator(BHEAD term,level));
×
1397
}
1398

1399
/*
1400
                 #] ToRat : 
1401
          #] Float Routines : 
1402
          #[ Sorting :
1403

1404
                We need a method to see whether two terms need addition that could
1405
                involve floating point numbers.
1406
                1: if PolyWise is active, we do not need anything, because
1407
                   Poly(Rat)Fun and floating point are mutually exclusive.
1408
                2: This means that there should be only interference in AddCoef.
1409
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1410
                   and PF_GetLoser.
1411
                The compare routine(s) should recognise the float_ and give off
1412
                a code (SortFloatMode) inside the AT struct:
1413
                0: no float_
1414
                1: float_ in term1 only
1415
                2: float_ in term2 only
1416
                3: float_ in both terms
1417
                Be careful: we have several compare routines, because various codes
1418
                use their own routines and we just set a variable with its address.
1419
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1420
                Only Compare1 should be active for this. The others should make sure
1421
                that the proper variable is always zero.
1422
                Remember: the sign of the coefficient is in the last word of the term.
1423

1424
                We need two routines:
1425
                1: AddWithFloat for SplitMerge which sorts by pointer.
1426
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1427
                   as possible in their location.
1428
                The routines start out the same, because AT.SortFloatMode, set in
1429
                Compare1, tells more or less what should be done.
1430
                The difference is in where we leave the result.
1431

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

1436
                 #[ AddWithFloat :
1437
*/
1438

1439
WORD AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
×
1440
{
1441
        GETBIDENTITY
1442
        SORTING *S = AT.SS;
×
UNCOV
1443
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
×
UNCOV
1444
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
×
1445
        s1 = *ps1;
×
1446
        s2 = *ps2;
×
1447
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
×
1448
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
×
1449
        if ( AT.SortFloatMode == 3 ) {
×
UNCOV
1450
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1451
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1452
                UnpackFloat(aux1,fun1);
×
1453
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1454
                UnpackFloat(aux2,fun2);
×
UNCOV
1455
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1456
        }
1457
        else if ( AT.SortFloatMode == 1 ) {
×
1458
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
UNCOV
1459
                UnpackFloat(aux1,fun1);
×
UNCOV
1460
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
UNCOV
1461
                fun2 = coef2;
×
UNCOV
1462
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1463
        }
UNCOV
1464
        else if ( AT.SortFloatMode == 2 ) {
×
UNCOV
1465
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
UNCOV
1466
                fun1 = coef1;
×
UNCOV
1467
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
UNCOV
1468
                UnpackFloat(aux2,fun2);
×
1469
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1470
        }
1471
        else {
1472
                MLOCK(ErrorMessageLock);
×
1473
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1474
                MUNLOCK(ErrorMessageLock);
×
UNCOV
1475
                Terminate(-1);
×
1476
                return(0);
×
1477
        }
1478
        mpf_add(aux3,aux1,aux2);
×
1479
        sign3 = mpf_sgn(aux3);
×
1480
        if ( sign3 == 0 ) {        /* May be rare! */
×
UNCOV
1481
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1482
        }
1483
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
UNCOV
1484
        fun3 = TermMalloc("AddWithFloat");
×
1485
        PackFloat(fun3,aux3);
×
1486
/*
1487
        Now we have to calculate where the sumterm fits.
1488
        If we are sloppy, we can be faster, but run the risk to need the
1489
        extension space, even when it is not needed. At slightly lower speed
1490
        (ie first creating the result in scribble space) we are better off.
1491
        This is why we use TermMalloc.
1492

1493
        The new term will have a rational coefficient of 1,1,+-3.
1494
        The size will be (fun1 or fun2 - term) + fun3 +3;
1495
*/
1496
        if ( AT.SortFloatMode == 3 ) {
×
1497
                if ( fun1[1] == fun3[1]  ) {
×
1498
Over1:
×
1499
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
×
1500
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1501
                        *s1 = t1-s1; goto Finished;
×
1502
                }
1503
                else if ( fun2[1] == fun3[1]  ) {
×
1504
Over2:
×
1505
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
×
1506
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1507
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
×
1508
                }
1509
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1510
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
×
1511
        }
1512
        else if ( AT.SortFloatMode == 1 ) {
×
1513
                if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1514
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1515
        }
1516
        else if ( AT.SortFloatMode == 2 ) {
×
1517
                if ( fun2[1] >= fun3[1]  ) goto Over2;
×
1518
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1519
        }
1520
/*
1521
        Does not fit. Go to extension space.
1522
*/
UNCOV
1523
        jj = fun1-s1;
×
UNCOV
1524
        j = jj+fun3[1]+3; /* space needed */
×
UNCOV
1525
        if ( (S->sFill + j) >= S->sTop2 ) {
×
UNCOV
1526
                GarbHand();
×
UNCOV
1527
                s1 = *ps1; /* new position of the term after the garbage collection */
×
UNCOV
1528
                fun1 = s1+jj;
×
1529
        }
UNCOV
1530
        t1 = S->sFill;
×
UNCOV
1531
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
×
UNCOV
1532
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
×
1533
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
UNCOV
1534
        *ps1 = S->sFill;
×
UNCOV
1535
        **ps1 = t1-*ps1;
×
1536
        S->sFill = t1;
×
1537
Finished:
×
1538
        *ps2 = 0;
×
1539
        TermFree(fun3,"AddWithFloat");
×
1540
        AT.SortFloatMode = 0;
×
1541
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
×
1542
                MLOCK(ErrorMessageLock);
×
1543
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1544
                AM.MaxTer/sizeof(WORD));
×
1545
                MUNLOCK(ErrorMessageLock);
×
1546
                Terminate(-1);
×
1547
        }
1548
        return(1);
1549
}
1550

1551
/*
1552
                 #] AddWithFloat : 
1553
                 #[ MergeWithFloat :
1554

1555
                Note that we always park the result on top of term1.
1556
                This makes life easier, because the original AddRat in MergePatches
1557
                does this as well.
1558
*/
1559

1560
WORD MergeWithFloat(PHEAD WORD **interm1, WORD **interm2)
×
1561
{
1562
        GETBIDENTITY
1563
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3, *tt;
×
1564
        WORD sign3,j,jj, *t1, *t2, i, *term1 = *interm1, *term2 = *interm2, retval = 0;
×
1565
        coef1 = term1+*term1; size1 = coef1[-1]; coef1 -= ABS(size1);
×
1566
        coef2 = term2+*term2; size2 = coef2[-1]; coef2 -= ABS(size2);
×
1567
        if ( AT.SortFloatMode == 3 ) {
×
UNCOV
1568
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1569
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1570
                UnpackFloat(aux1,fun1);
×
1571
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1572
                UnpackFloat(aux2,fun2);
×
UNCOV
1573
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1574
        }
UNCOV
1575
        else if ( AT.SortFloatMode == 1 ) {
×
UNCOV
1576
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1577
                UnpackFloat(aux1,fun1);
×
1578
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1579
                fun2 = coef2;
×
1580
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1581
        }
1582
        else if ( AT.SortFloatMode == 2 ) {
×
1583
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1584
                fun1 = coef1;
×
1585
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
UNCOV
1586
                UnpackFloat(aux2,fun2);
×
1587
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1588
        }
1589
        else {
1590
                MLOCK(ErrorMessageLock);
×
UNCOV
1591
                MesPrint("Illegal value %d for AT.SortFloatMode in MergeWithFloat.",AT.SortFloatMode);
×
1592
                MUNLOCK(ErrorMessageLock);
×
1593
                Terminate(-1);
×
1594
                return(0);
×
1595
        }
UNCOV
1596
        mpf_add(aux3,aux1,aux2);
×
1597
        sign3 = mpf_sgn(aux3);
×
1598
        if ( sign3 == 0 ) {        /* May be very rare! */
×
1599
                AT.SortFloatMode = 0; return(0);
×
1600
        }
1601
/*
1602
        Now check whether we can park the result on top of one of the input terms.
1603
*/
1604
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
UNCOV
1605
        fun3 = TermMalloc("MergeWithFloat");
×
UNCOV
1606
        PackFloat(fun3,aux3);
×
1607
        if ( AT.SortFloatMode == 3 ) {
×
1608
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) {
×
1609
OnTopOf1:        t1 = fun3; t2 = fun1;
×
1610
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
UNCOV
1611
                        *t2++ = 1; *t2++ = 1; *t2++ = sign3 < 0 ? -3: 3;
×
UNCOV
1612
                        retval = 1;
×
1613
                }
UNCOV
1614
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) {
×
1615
Shift1:                t2 = term1 + *term1; tt = t2;
×
1616
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1617
                        t1 = fun3 + fun3[1]; for ( i = 0; i < fun3[1]; i++ ) *--t2 = *--t1;
×
1618
                        t1 = fun1;
1619
                        while ( t1 > term1 ) *--t2 = *--t1;
×
1620
                        *t2 = tt-t2; term1 = t2;
×
1621
                        retval = 1;
×
1622
                }
1623
                else { /* Here we have to move term1 to the left to make room. */
1624
Over1:                jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
×
1625
                        t2 = term1-jj; t1 = term1;
×
1626
                        while ( t1 < fun1 ) *t2++ = *t1++;
×
UNCOV
1627
                        term1 -= jj;
×
1628
                        *term1 += jj;
×
UNCOV
1629
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = fun3[i];
×
1630
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1631
                        retval = 1;
×
1632
                }
1633
        }
UNCOV
1634
        else if ( AT.SortFloatMode == 1 ) {
×
UNCOV
1635
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) goto OnTopOf1;
×
UNCOV
1636
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) goto Shift1;
×
UNCOV
1637
                else goto Over1;
×
1638
        }
1639
        else { /* Can only be 2, based on previous tests */
UNCOV
1640
                if ( fun3[1] + 3 == ABS(size1) ) {
×
1641
                        t2 = coef1; t1 = fun3;
UNCOV
1642
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
UNCOV
1643
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
UNCOV
1644
                        retval = 1;
×
1645
                }
UNCOV
1646
                else if ( fun3[1] + 3 < ABS(size1) ) {
×
UNCOV
1647
                        j = ABS(size1) - fun3[1] - 3;
×
UNCOV
1648
                        t2 = term1 + *term1; tt = t2;
×
UNCOV
1649
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
UNCOV
1650
                        t2 -= fun3[1]; t1 = t2-j;
×
UNCOV
1651
                        while ( t2 > term1 ) *--t2 = *--t1;
×
UNCOV
1652
                        *t2 = tt-t2; term1 = t2;
×
UNCOV
1653
                        retval = 1;
×
1654
                }
UNCOV
1655
                else goto Over1;
×
1656
        }
UNCOV
1657
        *interm1 = term1;
×
UNCOV
1658
        TermFree(fun3,"MergeWithFloat");
×
UNCOV
1659
        AT.SortFloatMode = 0;
×
UNCOV
1660
        return(retval);
×
1661
}
1662

1663
/*
1664
                 #] MergeWithFloat : 
1665
          #] Sorting : 
1666
          #[ MZV :
1667

1668
                The functions here allow the arbitrary precision calculation
1669
                of MZV's and Euler sums.
1670
                They are called when the functions mzv_ and/or euler_ are used
1671
                and the evaluate statement is applied.
1672
                The output is in a float_ function.
1673
                The expand statement tries to express the functions in terms of a basis.
1674
                The bases are the 'standard basis for the euler sums and the
1675
                pushdown bases from the datamine, unless otherwise specified.
1676

1677
                 #[ SimpleDelta :
1678
*/
1679

1680
void SimpleDelta(mpf_t sum, int m)
780✔
1681
{
1682
        long s = 1;
780✔
1683
        long prec = AC.DefaultPrecision;
780✔
1684
        unsigned long xprec = (unsigned long)prec, x;
780✔
1685
        int j, jmax, n;
780✔
1686
        mpf_t jm,jjm;
780✔
1687
        mpf_init(jm); mpf_init(jjm);
780✔
1688
        if ( m < 0 ) { s = -1; m = -m; }
780✔
1689

1690
/*
1691
        We will loop until 1/2^j/j^m is smaller than the default precision.
1692
        Just running to prec is however overkill, specially when m is large.
1693
        We try to estimate a better value.
1694
        jmax = prec - ((log2(prec)-1)*m).
1695
        Hence we need the leading bit of prec.
1696
        We are still overshooting a bit.
1697
*/
1698
        n = 0; x = xprec;
780✔
1699
        while ( x ) { x >>= 1; n++; }
5,700✔
1700
/* 
1701
        We have now n = floor(log2(x))+1. 
1702
*/
1703
        n--;
780✔
1704
        jmax = (int)((int)xprec - (n-1)*m);
780✔
1705
        mpf_set_ui(sum,0);
780✔
1706
        for ( j = 1; j <= jmax; j++ ) {
40,434✔
1707
#ifdef WITHCUTOFF
1708
                xprec--;
38,874✔
1709
                mpf_set_prec_raw(jm,xprec);
38,874✔
1710
                mpf_set_prec_raw(jjm,xprec);
38,874✔
1711
#endif
1712
                mpf_set_ui(jm,1L);
38,874✔
1713
                mpf_div_ui(jjm,jm,(unsigned long)j);
38,874✔
1714
                mpf_pow_ui(jm,jjm,(unsigned long)m);
38,874✔
1715
                mpf_div_2exp(jjm,jm,(unsigned long)j);
38,874✔
1716
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
38,874✔
1717
                else                       mpf_add(sum,sum,jjm);
38,874✔
1718
        }
1719
        mpf_clear(jjm); mpf_clear(jm);
780✔
1720
}
780✔
1721

1722
/*
1723
                 #] SimpleDelta : 
1724
                 #[ SimpleDeltaC :
1725
*/
1726

UNCOV
1727
void SimpleDeltaC(mpf_t sum, int m)
×
1728
{
1729
        long s = 1;
×
1730
        long prec = AC.DefaultPrecision;
×
1731
        unsigned long xprec = (unsigned long)prec, x;
×
1732
        int j, jmax, n;
×
1733
        mpf_t jm,jjm;
×
UNCOV
1734
        mpf_init(jm); mpf_init(jjm);
×
1735
        if ( m < 0 ) { s = -1; m = -m; }
×
1736
/*
1737
        We will loop until 1/2^j/j^m is smaller than the default precision.
1738
        Just running to prec is however overkill, specially when m is large.
1739
        We try to estimate a better value.
1740
        jmax = prec - ((log2(prec)-1)*m).
1741
        Hence we need the leading bit of prec.
1742
        We are still overshooting a bit.
1743
*/
UNCOV
1744
        n = 0; x = xprec;
×
UNCOV
1745
        while ( x ) { x >>= 1; n++; }
×
1746
/* 
1747
        We have now n = floor(log2(x))+1. 
1748
*/
NEW
1749
        n--;
×
NEW
1750
        jmax = (int)((int)xprec - (n-1)*m);
×
UNCOV
1751
        if ( s < 0 ) jmax /= 2;
×
UNCOV
1752
        mpf_set_si(sum,0L);
×
NEW
1753
        for ( j = 1; j <= jmax; j++ ) {
×
1754
#ifdef WITHCUTOFF
UNCOV
1755
                xprec--;
×
UNCOV
1756
                mpf_set_prec_raw(jm,xprec);
×
UNCOV
1757
                mpf_set_prec_raw(jjm,xprec);
×
1758
#endif
UNCOV
1759
                mpf_set_ui(jm,1L);
×
UNCOV
1760
                mpf_div_ui(jjm,jm,(unsigned long)j);
×
1761
                mpf_pow_ui(jm,jjm,(unsigned long)m);
×
1762
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
×
UNCOV
1763
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
1764
                mpf_add(sum,sum,jjm);
×
1765
        }
1766
        mpf_clear(jjm); mpf_clear(jm);
×
1767
}
×
1768

1769
/*
1770
                 #] SimpleDeltaC : 
1771
                 #[ SingleTable :
1772
*/
1773

1774
void SingleTable(mpf_t *tabl, int N, int m, int pow)
864✔
1775
{
1776
/*
1777
        Creates a table T(1,...,N) with
1778
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
1779
        To make this table we have two options:
1780
        1: run the sum backwards with the potential problem that the 
1781
           precision is difficult to manage.
1782
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
1783
        When doing Euler sums we may need also 1/4^j
1784
        pow: 1 -> 1/2^j
1785
             2 -> 1/4^j
1786
*/
1787
        GETIDENTITY
576✔
1788
        long s = 1;
864✔
1789
        int j;
864✔
1790
#ifdef WITHCUTOFF
1791
        long prec = mpf_get_default_prec();
864✔
1792
#endif
1793
        mpf_t jm,jjm;
864✔
1794
        mpf_init(jm); mpf_init(jjm);
864✔
1795
        if ( pow < 1 || pow > 2 ) {
864✔
UNCOV
1796
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
UNCOV
1797
                exit(-1);
×
1798
        }
1799
        if ( m < 0 ) { m = -m; s = -1; }
864✔
1800
        mpf_set_si(auxsum,0L);
864✔
1801
        for ( j = N; j > 0; j-- ) {
67,944✔
1802
#ifdef WITHCUTOFF
1803
                mpf_set_prec_raw(jm,prec-j);
66,216✔
1804
                mpf_set_prec_raw(jjm,prec-j);
66,216✔
1805
#endif
1806
                mpf_set_ui(jm,1L);
66,216✔
1807
                mpf_div_ui(jjm,jm,(unsigned long)j);
66,216✔
1808
                mpf_pow_ui(jm,jjm,(unsigned long)m);
66,216✔
1809
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
66,216✔
1810
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
66,216✔
1811
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
66,216✔
1812
                else                       mpf_add(auxsum,auxsum,jjm);
66,216✔
1813
/*
1814
                And now copy auxsum to tablelement j
1815
*/
1816
                mpf_set(tabl[j],auxsum);
66,216✔
1817
        }
1818
        mpf_clear(jjm); mpf_clear(jm);
864✔
1819
}
864✔
1820

1821
/*
1822
                 #] SingleTable : 
1823
                 #[ DoubleTable :
1824
*/
1825

1826
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
552✔
1827
{
1828
        GETIDENTITY
368✔
1829
        long s = 1;
552✔
1830
#ifdef WITHCUTOFF
1831
        long prec = mpf_get_default_prec();
552✔
1832
#endif
1833
        int j;
552✔
1834
        mpf_t jm,jjm;
552✔
1835
        mpf_init(jm); mpf_init(jjm);
552✔
1836
        if ( pow < -1 || pow > 2 ) {
552✔
UNCOV
1837
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
UNCOV
1838
                exit(-1);
×
1839
        }
1840
        if ( m < 0 ) { m = -m; s = -1; }
552✔
1841
        mpf_set_ui(auxsum,0L);
552✔
1842
        for ( j = N; j > 0; j-- ) {
43,200✔
1843
#ifdef WITHCUTOFF
1844
                mpf_set_prec_raw(jm,prec-j);
42,096✔
1845
                mpf_set_prec_raw(jjm,prec-j);
42,096✔
1846
#endif
1847
                mpf_set_ui(jm,1L);
42,096✔
1848
                mpf_div_ui(jjm,jm,(unsigned long)j);
42,096✔
1849
                mpf_pow_ui(jm,jjm,(unsigned long)m);
42,096✔
1850
                if ( pow == -1 ) {
42,096✔
UNCOV
1851
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
×
1852
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1853
                }
1854
                else if ( pow > 0 ) {
42,096✔
UNCOV
1855
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
×
1856
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1857
                }
1858
                else {
1859
                        mpf_mul(jm,jm,tabin[j+1]);
42,096✔
1860
                }
1861
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
42,096✔
1862
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
42,096✔
1863
                else                       mpf_add(auxsum,auxsum,jm);
42,096✔
1864
/*
1865
                And now copy auxsum to tablelement j
1866
*/
1867
                mpf_set(tabout[j],auxsum);
42,096✔
1868
        }
1869
        mpf_clear(jjm); mpf_clear(jm);
552✔
1870
}
552✔
1871

1872
/*
1873
                 #] DoubleTable : 
1874
                 #[ EndTable :
1875
*/
1876

1877
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
864✔
1878
{
1879
        long s = 1;
864✔
1880
#ifdef WITHCUTOFF
1881
        long prec = mpf_get_default_prec();
864✔
1882
#endif
1883
        int j;
864✔
1884
        mpf_t jm,jjm;
864✔
1885
        mpf_init(jm); mpf_init(jjm);
864✔
1886
        if ( pow < -1 || pow > 2 ) {
864✔
1887
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1888
                exit(-1);
×
1889
        }
1890
        if ( m < 0 ) { m = -m; s = -1; }
864✔
1891
        mpf_set_si(sum,0L);
864✔
1892
        for ( j = N; j > 0; j-- ) {
66,528✔
1893
#ifdef WITHCUTOFF
1894
                mpf_set_prec_raw(jm,prec-j);
64,800✔
1895
                mpf_set_prec_raw(jjm,prec-j);
64,800✔
1896
#endif
1897
                mpf_set_ui(jm,1L);
64,800✔
1898
                mpf_div_ui(jjm,jm,(unsigned long)j);
64,800✔
1899
                mpf_pow_ui(jm,jjm,(unsigned long)m);
64,800✔
1900
                if ( pow == -1 ) {
64,800✔
UNCOV
1901
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
×
1902
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1903
                }
1904
                else if ( pow > 0 ) {
64,800✔
1905
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
×
UNCOV
1906
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1907
                }
1908
                else {
1909
                        mpf_mul(jm,jm,tabin[j+1]);
64,800✔
1910
                }
1911
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
64,800✔
1912
                else                       mpf_add(sum,sum,jm);
64,800✔
1913
        }
1914
        mpf_clear(jjm); mpf_clear(jm);
864✔
1915
}
864✔
1916

1917
/*
1918
                 #] EndTable : 
1919
                 #[ deltaMZV :
1920
*/
1921

1922
void deltaMZV(mpf_t result, int *indexes, int depth)
2,424✔
1923
{
1924
        GETIDENTITY
1,616✔
1925
/*
1926
        Because all sums go roughly like 1/2^j we need about depth steps.
1927
*/
1928
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
1929
        if ( depth == 1 ) {
2,424✔
1930
                if ( indexes[0] == 1 ) {
1,248✔
1931
                        mpf_set(result,mpfdelta1);
624✔
1932
                        return;
624✔
1933
                }
1934
                SimpleDelta(result,indexes[0]);
624✔
1935
        }
1936
        else if ( depth == 2 ) {
1,176✔
1937
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
624✔
1938
                        mpf_pow_ui(result,mpfdelta1,2);
180✔
1939
                        mpf_div_2exp(result,result,1);
180✔
1940
                }
1941
                else {
1942
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
444✔
1943
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
444✔
1944
                };
1945
        }
1946
        else if ( depth > 2 ) {
552✔
1947
                mpf_t *mpftab3;
1948
                int d;
1949
/*
1950
                Check first whether this is a power of delta1 = ln(2)
1951
*/
1952
                for ( d = 0; d < depth; d++ ) {
1,236✔
1953
                        if ( indexes[d] != 1 ) break;
1,104✔
1954
                }
1955
                if ( d == depth ) {        /* divide by fac_(depth) */
552✔
1956
                        mpf_pow_ui(result,mpfdelta1,depth);
132✔
1957
                        for ( d = 2; d <= depth; d++ ) {
588✔
1958
                                mpf_div_ui(result,result,(unsigned long)d);
324✔
1959
                        }
1960
                }
1961
                else {
1962
                        d = depth-1;
420✔
1963
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
420✔
1964
                        d--; indexes++;
420✔
1965
                        for(;;) {
684✔
1966
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
552✔
1967
                                d--; indexes++;
552✔
1968
                                if ( d == 0 ) {
552✔
1969
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
420✔
1970
                                        break;
420✔
1971
                                }
1972
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
132✔
1973
                                AT.mpf_tab2 = (void *)mpftab3;
132✔
1974
                        }
1975
                }
1976
        }
UNCOV
1977
        else if ( depth == 0 ) {
×
1978
                mpf_set_ui(result,1L);
×
1979
        }
1980
}
1981

1982
/*
1983
                 #] deltaMZV : 
1984
                 #[ deltaEuler :
1985

1986
                Regular Euler delta with - signs, but everywhere 1/2^j
1987
*/
1988

1989
void deltaEuler(mpf_t result, int *indexes, int depth)
×
1990
{
1991
        GETIDENTITY
1992
        int m;
×
1993
#ifdef DEBUG
1994
        int i;
1995
        printf(" deltaEuler(");
1996
        for ( i = 0; i < depth; i++ ) {
1997
                if ( i != 0 ) printf(",");
1998
                printf("%d",indexes[i]);
1999
        }
2000
        printf(") = ");
2001
#endif
2002
        if ( depth == 1 ) {
×
2003
                SimpleDelta(result,indexes[0]);
×
2004
        }
UNCOV
2005
        else if ( depth == 2 ) {
×
UNCOV
2006
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
×
UNCOV
2007
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
×
2008
                EndTable(result,mpftab1,AC.DefaultPrecision,m,0);
×
2009
        }
UNCOV
2010
        else if ( depth > 2 ) {
×
UNCOV
2011
                int d;
×
UNCOV
2012
                mpf_t *mpftab3;
×
UNCOV
2013
                d = depth-1;
×
UNCOV
2014
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
×
UNCOV
2015
                d--; indexes++;
×
UNCOV
2016
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
×
UNCOV
2017
                for(;;) {
×
2018
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
×
UNCOV
2019
                        d--; indexes++;
×
UNCOV
2020
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
×
2021
                        if ( d == 0 ) {
×
UNCOV
2022
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
×
UNCOV
2023
                                break;
×
2024
                        }
UNCOV
2025
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
×
UNCOV
2026
                        AT.mpf_tab2 = (void *)mpftab3;
×
2027
                }
2028
        }
UNCOV
2029
        else if ( depth == 0 ) {
×
UNCOV
2030
                mpf_set_ui(result,1L);
×
2031
        }
2032
#ifdef DEBUG
2033
        gmp_printf("%.*Fe\n",40,result);
2034
#endif
UNCOV
2035
}
×
2036

2037
/*
2038
                 #] deltaEuler : 
2039
                 #[ deltaEulerC :
2040

2041
                Conjugate Euler delta without - signs, but possibly 1/4^j
2042
                When there is a - in the string we have 1/4.
2043
*/
2044

2045
void deltaEulerC(mpf_t result, int *indexes, int depth)
×
2046
{
2047
        GETIDENTITY
UNCOV
2048
        int m;
×
2049
#ifdef DEBUG
2050
        int i;
2051
        printf(" deltaEulerC(");
2052
        for ( i = 0; i < depth; i++ ) {
2053
                if ( i != 0 ) printf(",");
2054
                printf("%d",indexes[i]);
2055
        }
2056
        printf(") = ");
2057
#endif
2058
        mpf_set_ui(result,0);
×
2059
        if ( depth == 1 ) {
×
2060
                if ( indexes[0] == 0 ) {
×
2061
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2062
                }
2063
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
×
2064
                else                  SimpleDelta(result,indexes[0]);
×
2065
        }
2066
        else if ( depth == 2 ) {
×
2067
                int par;
×
2068
                m = indexes[0];
×
2069
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth+1,-m,2);
×
UNCOV
2070
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth+1, m,1);
×
2071
                m = indexes[1];
×
2072
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
×
UNCOV
2073
                else { par = indexes[0] < 0 ? -1: 0; }
×
UNCOV
2074
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
×
2075
        }
2076
        else if ( depth > 2 ) {
×
UNCOV
2077
                int d, par;
×
UNCOV
2078
                mpf_t *mpftab3;
×
UNCOV
2079
                d = depth-1;
×
UNCOV
2080
                m = indexes[0];
×
2081
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
×
UNCOV
2082
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
×
UNCOV
2083
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
×
UNCOV
2084
                d--; indexes++; m = indexes[0];
×
UNCOV
2085
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
×
UNCOV
2086
                else { par = indexes[-1] < 0 ? -1: 0; }
×
UNCOV
2087
                for(;;) {
×
UNCOV
2088
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
×
UNCOV
2089
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
×
UNCOV
2090
                        d--; indexes++; m = indexes[0];
×
2091
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
×
UNCOV
2092
                        else { par = indexes[-1] < 0 ? -1: 0; }
×
2093
                        if ( d == 0 ) {
×
2094
                                mpf_set_ui(result,0);
×
2095
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
×
2096
                                break;
×
2097
                        }
2098
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
×
2099
                        AT.mpf_tab2 = (void *)mpftab3;
×
2100
                }
2101
        }
UNCOV
2102
        else if ( depth == 0 ) {
×
UNCOV
2103
                mpf_set_ui(result,1L);
×
2104
        }
2105
#ifdef DEBUG
2106
        gmp_printf("%.*Fe\n",40,result);
2107
#endif
UNCOV
2108
}
×
2109

2110
/*
2111
                 #] deltaEulerC : 
2112
                 #[ CalculateMZVhalf :
2113

2114
                 This routine is mainly for support when large numbers of
2115
                MZV's have to be calculated at the same time.
2116
*/
2117

2118
void CalculateMZVhalf(mpf_t result, int *indexes, int depth)
×
2119
{
2120
        int i;
×
2121
        if ( depth < 0 ) {
×
2122
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
UNCOV
2123
                exit(-1);
×
2124
        }
2125
        for ( i = 0; i < depth; i++ ) {
×
2126
                if ( indexes[i] <= 0 ) {
×
2127
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2128
                        exit(-1);
×
2129
                }
2130
        }
UNCOV
2131
        deltaMZV(result,indexes,depth);
×
2132
}
×
2133

2134
/*
2135
                 #] CalculateMZVhalf : 
2136
                 #[ CalculateMZV :
2137
*/
2138

2139
void CalculateMZV(mpf_t result, int *indexes, int depth)
312✔
2140
{
2141
        GETIDENTITY
208✔
2142
        int num1, num2 = 0, i, j = 0;
312✔
2143
        if ( depth < 0 ) {
312✔
2144
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
UNCOV
2145
                exit(-1);
×
2146
        }
2147
        if ( indexes[0] == 1 ) {
312✔
2148
                printf("Divergent MZV in CalculateMZV\n");
×
2149
                exit(-1);
×
2150
        }
2151
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2152
        for ( i = 0; i < depth; i++ ) {
918✔
2153
                if ( indexes[i] <= 0 ) {
606✔
UNCOV
2154
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
UNCOV
2155
                        exit(-1);
×
2156
                }
2157
                AT.indi1[i] = indexes[i];
606✔
2158
        }
2159
        num1 = depth; i = 0;
312✔
2160
        deltaMZV(result,indexes,depth);
312✔
2161
        for(;;) {
2,112✔
2162
                if ( AT.indi1[0] > 1 ) {
1,212✔
2163
                        AT.indi1[0] -= 1;
606✔
2164
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
1,086✔
2165
                        AT.indi2[0] = 1; num2++;
606✔
2166
                }
2167
                else {
2168
                        AT.indi2[0] += 1;
606✔
2169
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,086✔
2170
                        num1--;
606✔
2171
                        if ( num1 == 0 ) break;
606✔
2172
                }
2173
                deltaMZV(aux1,AT.indi1,num1);
900✔
2174
                deltaMZV(aux2,AT.indi2,num2);
900✔
2175
                mpf_mul(aux3,aux1,aux2);
900✔
2176
                mpf_add(result,result,aux3);
900✔
2177
        }
2178
        deltaMZV(aux3,AT.indi2,num2);
312✔
2179
        mpf_add(result,result,aux3);
312✔
2180
}
312✔
2181

2182
/*
2183
                 #] CalculateMZV : 
2184
                 #[ CalculateEuler :
2185

2186
                There is a problem of notation here.
2187
                Basically there are two notations.
2188
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2189
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2190
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2191
                   See Broadhurst,1996
2192
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2193
                                 sum_(j2,1,inf,sign_(m2)*
2194
                                 sum_(j3,1,inf,sign_(m3)
2195
                                                        /j3^abs_(m3)
2196
                                                        /(j2+j3)^abs_(m2)
2197
                                                        /(j1+j2+j3)^abs_(m1) )))
2198
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2199
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2200
                The algorithm follows 2, but the more common notation is 1.
2201
                Hence we start with a conversion.
2202
*/
2203

2204
void CalculateEuler(mpf_t result, int *Zindexes, int depth)
×
2205
{
2206
        GETIDENTITY
2207
        int s1, num1, num2, i, j;
×
2208

UNCOV
2209
        int *indexes = (int *)(AT.WorkPointer);
×
2210
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
×
2211
        for ( i = 0; i < depth-1; i++ ) {
×
2212
                if ( Zindexes[i] < 0 ) {
×
2213
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
×
2214
                }
2215
        }
2216

2217
        if ( depth < 0 ) {
×
2218
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
UNCOV
2219
                exit(-1);
×
2220
        }
2221
        if ( indexes[0] == 1 ) {
×
2222
                printf("Divergent Euler sum in CalculateEuler\n");
×
2223
                exit(-1);
×
2224
        }
2225
        for ( i = 0, j = 0; i < depth; i++ ) {
×
2226
                if ( indexes[i] == 0 ) {
×
2227
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2228
                        exit(-1);
×
2229
                }
UNCOV
2230
                if ( indexes[i] < 0 ) j = 1;
×
UNCOV
2231
                AT.indi1[i] = indexes[i];
×
2232
        }
2233
        if ( j == 0 ) {
×
2234
                CalculateMZV(result,indexes,depth);
×
UNCOV
2235
                return;
×
2236
        }
2237
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
×
2238
        deltaEuler(result,AT.indi1,depth);
×
2239
        s1 = 0;
×
2240
        for(;;) {
×
2241
                s1++;
×
UNCOV
2242
                if ( AT.indi1[0] > 1 ) {
×
2243
                        AT.indi1[0] -= 1;
×
2244
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
2245
                        AT.indi2[0] = 1; num2++;
×
2246
                }
UNCOV
2247
                else if ( AT.indi1[0] < -1 ) {
×
UNCOV
2248
                        AT.indi1[0] += 1;
×
UNCOV
2249
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
UNCOV
2250
                        AT.indi2[0] = 1; num2++;
×
2251
                }
UNCOV
2252
                else if ( AT.indi1[0] == -1 ) {
×
2253
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
UNCOV
2254
                        AT.indi2[0] = -1; num2++;
×
2255
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
×
2256
                        num1--;
×
2257
                }
2258
                else {
UNCOV
2259
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
×
UNCOV
2260
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
×
UNCOV
2261
                        num1--;
×
2262
                }
UNCOV
2263
                if ( num1 == 0 ) break;
×
UNCOV
2264
                deltaEuler(aux1,AT.indi1,num1);
×
2265
                deltaEulerC(aux2,AT.indi2,num2);
×
UNCOV
2266
                mpf_mul(aux3,aux1,aux2);
×
2267
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
×
2268
                else                               mpf_sub(result,result,aux3);
×
2269
        }
UNCOV
2270
        deltaEulerC(aux3,AT.indi2,num2);
×
UNCOV
2271
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
×
UNCOV
2272
        else                          mpf_sub(result,result,aux3);
×
2273
}
2274

2275
/*
2276
                 #] CalculateEuler : 
2277
                 #[ ExpandMZV :
2278
*/
2279

UNCOV
2280
int ExpandMZV(WORD *term, WORD level)
×
2281
{
UNCOV
2282
        DUMMYUSE(term);
×
UNCOV
2283
        DUMMYUSE(level);
×
UNCOV
2284
        return(0);
×
2285
}
2286

2287
/*
2288
                 #] ExpandMZV : 
2289
                 #[ ExpandEuler :
2290
*/
2291

UNCOV
2292
int ExpandEuler(WORD *term, WORD level)
×
2293
{
UNCOV
2294
        DUMMYUSE(term);
×
UNCOV
2295
        DUMMYUSE(level);
×
UNCOV
2296
        return(0);
×
2297
}
2298

2299
/*
2300
                 #] ExpandEuler : 
2301
                 #[ EvaluateEuler :
2302

2303
        There are various steps here:
2304
        1: locate an Euler function.
2305
        2: evaluate it into a float.
2306
        3: convert the coefficient to a float and multiply.
2307
        4: Put the new term together.
2308
        5: Restart to see whether there are more Euler functions.
2309
        The compiler should check that there is no conflict between
2310
        the evaluate command and a potential polyfun or polyratfun.
2311
        Yet, when reading in expressions there can be a conflict.
2312
        Hence the Normalize routine should check as well.
2313

2314
        par == MZV: MZV
2315
        par == EULER: Euler
2316
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2317
        par == ALLMZVFUNCTIONS: all of the above.
2318
*/
2319

2320
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
372✔
2321
{
2322
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
372✔
2323
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
372✔
2324
        int retval;
372✔
2325
        tstop = term + *term; tstop -= ABS(tstop[-1]);
372✔
2326
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
372✔
2327
/*
2328
        Step 1. We also need to verify that the argument we find is legal
2329
*/
2330
        t = term+1;
372✔
2331
        while ( t < tstop ) {
942✔
2332
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
570✔
2333
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
72✔
2334
        /* all arguments should be small integers */
2335
                        indexes = AT.WorkPointer;
312✔
2336
                        sumweight = 0; depth = 0;
312✔
2337
                        tnext = t + t[1]; tt = t + FUNHEAD;
312✔
2338
                        while ( tt < tnext ) {
918✔
2339
                                if ( *tt != -SNUMBER ) goto nextfun;
606✔
2340
                                if ( tt[1] == 0 ) goto nextfun;
606✔
2341
                                indexes[depth] = tt[1];
606✔
2342
                                sumweight += ABS(tt[1]); depth++;
606✔
2343
                                tt += 2;
606✔
2344
                        }
2345
                        if ( sumweight > AC.MaxWeight ) {
312✔
UNCOV
2346
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
UNCOV
2347
                                MesPrint("Please increase MaxWeight in form.set.");
×
UNCOV
2348
                                Terminate(-1);
×
2349
                        }
2350
/*
2351
                        Step 2: evaluate:
2352
*/
2353
                        AT.WorkPointer += depth;
312✔
2354
                        if ( first ) {
312✔
2355
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
312✔
2356
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
×
2357
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
×
2358
                                first = 0;
2359
                        }
2360
                        else {
UNCOV
2361
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
×
UNCOV
2362
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
UNCOV
2363
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2364
                                mpf_mul(aux4,aux4,aux5);
×
2365
                        }
2366
                        *t = 0;
312✔
2367
                }
2368
nextfun:
258✔
2369
                t += t[1];
570✔
2370
        }
2371
        if ( first == 1 ) return(Generator(BHEAD term,level));
372✔
2372
/*
2373
        Step 3:
2374
        Now the regular coefficient, if it is not 1/1.
2375
        We have two cases: size +- 3, or bigger.
2376
*/
2377
        nsize = term[*term-1];
312✔
2378
        if ( nsize < 0 ) {
312✔
UNCOV
2379
                mpf_neg(aux4,aux4);
×
UNCOV
2380
                nsize = -nsize;
×
2381
        }
2382
        if ( nsize == 3 ) {
312✔
2383
                if ( tstop[0] != 1 ) {
312✔
2384
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
×
2385
                }
2386
                if ( tstop[1] != 1 ) {
312✔
2387
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
×
2388
                }
2389
        }
2390
        else {
2391
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2392
                mpf_mul(aux4,aux4,aux5);
×
2393
        }
2394
/*
2395
        Now we have to locate possible other float_ functions.
2396
*/
2397
        t = term+1;
2398
        while ( t < tstop ) {
810✔
2399
                if ( *t == FLOATFUN ) {
498✔
UNCOV
2400
                        UnpackFloat(aux5,t);
×
UNCOV
2401
                        mpf_mul(aux4,aux4,aux5);
×
2402
                }
2403
                t += t[1];
498✔
2404
        }
2405
/*
2406
        Now we should compose the new term in the WorkSpace.
2407
*/
2408
        t = term+1;
312✔
2409
        newterm = AT.WorkPointer;
312✔
2410
        tt = newterm+1;
312✔
2411
        while ( t < tstop ) {
312✔
2412
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
498✔
2413
                else {
2414
                        i = t[1]; NCOPY(tt,t,i);
2,514✔
2415
                }
2416
        }
2417
        PackFloat(tt,aux4);
312✔
2418
        tt += tt[1];
312✔
2419
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
312✔
2420
        *newterm = tt-newterm;
312✔
2421
        AT.WorkPointer = tt;
312✔
2422
        retval = Generator(BHEAD newterm,level);
312✔
2423
        AT.WorkPointer = oldworkpointer;
312✔
2424
        return(retval);
312✔
2425
}
2426

2427
/*
2428
                 #] EvaluateEuler : 
2429
          #] MZV : 
2430
          #[ Functions :
2431
                 #[ CoEvaluate :
2432

2433
                Current subkeys: mzv_, euler_ and sqrt_.
2434
*/
2435

2436
int CoEvaluate(UBYTE *s)
180✔
2437
{
2438
        UBYTE *subkey, c;
180✔
2439
        WORD numfun, type;
180✔
2440
        int error = 0;
180✔
2441
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
180✔
2442
        if ( *s == 0 ) {
180✔
2443
/*
2444
                No subkey, which means all functions.
2445
*/
2446
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
6✔
2447
/*
2448
                The MZV, EULER and MZVHALF are done separately
2449
*/
2450
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
6✔
2451
                return(0);        
6✔
2452
        }
2453
        while ( *s ) {
330✔
2454
        subkey = s;
2455
        while ( FG.cTable[*s] == 0 ) s++;
678✔
2456
          if ( *s == '_' ) s++;
174✔
2457
          c = *s; *s++ = 0;
174✔
2458
/*
2459
                We still need provisions for pi_ and possibly other constants.
2460
*/
2461
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
174✔
2462
                        || ( functions[numfun].spec != 0 ) ) {
156✔
2463

2464
                if ( type == CSYMBOL ) {
18✔
2465
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
18✔
2466
                        break;
18✔
2467
                }
2468
/*
2469
                        This cannot work.
2470
*/
UNCOV
2471
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
UNCOV
2472
                error = 1;
×
2473
          }
2474
          else {
2475
                switch ( numfun+FUNCTION ) {
156✔
2476
                        case MZV:
156✔
2477
                        case EULER:
2478
                        case MZVHALF:
2479
                        case SQRTFUNCTION:
2480
/*
2481
                        The following functions are treated in evaluate.c
2482

2483
                        case LNFUNCTION:
2484
                        case SINFUNCTION:
2485
                        case COSFUNCTION:
2486
                        case TANFUNCTION:
2487
                        case ASINFUNCTION:
2488
                        case ACOSFUNCTION:
2489
                        case ATANFUNCTION:
2490
                        case ATAN2FUNCTION:
2491
                        case SINHFUNCTION:
2492
                        case COSHFUNCTION:
2493
                        case TANHFUNCTION:
2494
                        case ASINHFUNCTION:
2495
                        case ACOSHFUNCTION:
2496
                        case ATANHFUNCTION:
2497
                        case LI2HFUNCTION:
2498
                        case LINHFUNCTION:
2499
                        case AGMFUNCTION:
2500
                        case GAMMAFUN:
2501

2502
                        At a later stage we can add more functions from mpfr here
2503
                                mpfr_(number,arg(s))
2504
*/
2505
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
156✔
2506
                                break;
156✔
UNCOV
2507
                        default:
×
UNCOV
2508
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
UNCOV
2509
                                error = 1;
×
UNCOV
2510
                                break;
×
2511
                }
2512
          }
2513
          *s = c;
156✔
2514
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
156✔
2515
        }
2516
        return(error);
2517
}
2518

2519
/*
2520
                 #] CoEvaluate : 
2521
          #] Functions : 
2522
*/
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