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

form-dev / form / 16800283938

07 Aug 2025 09:14AM UTC coverage: 52.867% (+0.01%) from 52.854%
16800283938

push

github

jodavies
Simplify 32-bit detection using stdint.h

43936 of 83106 relevant lines covered (52.87%)

2237251.77 hits per line

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

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

518
        if ( nb == 0 ) {
252✔
519
                z->_mp_size = 0;
×
520
                z->_mp_d[0] = 0;
×
521
                return;
×
522
        }
523
        if ( nb < 0 ) { sgn = -1; nb = -nb; }
252✔
524
        nlimbs = (nb+1)/2;
252✔
525
        if ( mpz_cmp_si(z,0L) <= 1 ) {
252✔
526
                mpz_set_ui(z,10000000);
252✔
527
        }
528
        if ( z->_mp_alloc <= nlimbs ) {
252✔
529
                mpz_t zz;
252✔
530
                mpz_init(zz);
252✔
531
                while ( z->_mp_alloc <= nlimbs ) {
756✔
532
                        mpz_mul(zz,z,z);
504✔
533
                        mpz_set(z,zz);
504✔
534
                }
535
                mpz_clear(zz);
252✔
536
        }
537
        z->_mp_size = sgn*nlimbs;
252✔
538
        d = z->_mp_d;
252✔
539
        while ( nb > 1 ) {
252✔
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); }
252✔
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)
252✔
605
{
606
        mpz_t z;
252✔
607
        mpz_init(z);
252✔
608
        FormtoZ(z,formlong,longsize);
252✔
609
        mpf_set_z(result,z);
252✔
610
        mpz_clear(z);
252✔
611
}
252✔
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)
126✔
621
{
622
        GETIDENTITY
84✔
623
        int nnum, nden;
126✔
624
        UWORD *num, *den;
126✔
625
        int sgn = 0;
126✔
626
        if ( ratsize < 0 ) { ratsize = -ratsize; sgn = 1; }
126✔
627
        nnum = nden = (ratsize-1)/2;
126✔
628
        num = formrat; den = formrat+nnum;
126✔
629
        while ( num[nnum-1] == 0 ) { nnum--; }
126✔
630
        while ( den[nden-1] == 0 ) { nden--; }
126✔
631
        IntegerToFloat(aux2,num,nnum);
126✔
632
        IntegerToFloat(aux3,den,nden);
126✔
633
        mpf_div(result,aux2,aux3);
126✔
634
        if ( sgn > 0 ) mpf_neg(result,result);
126✔
635
}
126✔
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)
78✔
823
{
824
        GETIDENTITY
52✔
825
        SBYTE *ss, c;
78✔
826
        ss = s;
78✔
827
        while ( *ss > 0 ) ss++;
312✔
828
        c = *ss; *ss = 0;
78✔
829
        gmp_sscanf((char *)s,"%Ff",aux1);
78✔
830
        if ( AT.WorkPointer > AT.WorkTop ) {
78✔
831
                MLOCK(ErrorMessageLock);
×
832
                MesWork();
×
833
                MUNLOCK(ErrorMessageLock);
×
834
                Terminate(-1);
×
835
        }
836
        PackFloat(AT.WorkPointer,aux1);
78✔
837
        *ss = c;
78✔
838
        return(ss);
78✔
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,267,750✔
849
{
850
        GETIDENTITY
1,511,836✔
851
        UBYTE *s = ss;
2,267,750✔
852
        int zero = 1, gotdot = 0;
2,267,750✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
6,439,618✔
854
        *spec = 0;
2,267,750✔
855
        if ( FG.cTable[*s] == 1 ) {
2,267,750✔
856
                while ( *s == '0' ) s++;
2,402,084✔
857
                if ( FG.cTable[*s] == 1 ) {
2,267,750✔
858
                        s++;
2,133,494✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
4,077,590✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
2,267,750✔
863
        }
864
        else if ( *s == '.' ) {
×
865
dot:
×
866
                gotdot = 1;
78✔
867
                s++;
78✔
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
78✔
869
                while ( *s == '0' ) s++;
144✔
870
                if ( FG.cTable[*s] == 1 ) {
78✔
871
                        s++;
12✔
872
                        while ( FG.cTable[*s] == 1 ) s++;
12✔
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,267,750✔
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,267,750✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
78✔
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
78✔
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)
192✔
912
{
913
        if ( prec <= 0 ) {
192✔
914
                MesPrint("&Illegal value for number of bits for floating point constants: %d",prec);
×
915
                return(-1);
×
916
        }
917
        else {
918
                AC.DefaultPrecision = prec;
192✔
919
                if ( AO.floatspace != 0 ) M_free(AO.floatspace,"floatspace");
192✔
920
                AO.floatsize = ((10*prec)/33+20)*sizeof(char);
192✔
921
                AO.floatspace = (UBYTE *)Malloc1(AO.floatsize,"floatspace");
192✔
922
                mpf_set_default_prec(prec);
192✔
923
                return(0);
192✔
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)
474✔
941
{
942
        GETIDENTITY
316✔
943
        int n = 0;
474✔
944
        int prec = (AC.DefaultPrecision-AC.MaxWeight-1)*log10(2.0);
474✔
945
        if ( numdigits > prec || numdigits == 0 ) {
474✔
946
                numdigits = prec;
474✔
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 )
474✔
953
                n = gmp_snprintf((char *)(AO.floatspace),AO.floatsize,"%.*Fe",numdigits-1,aux4);
474✔
954
        if ( numdigits == prec ) {
474✔
955
                UBYTE *s1, *s2;
474✔
956
                int n1, n2 = n;
474✔
957
                s1 = AO.floatspace+n;
474✔
958
                while ( s1 > AO.floatspace && s1[-1] != 'e'
2,370✔
959
                 && s1[-1] != 'E' && s1[-1] != '.' ) { s1--; n2--; }
1,896✔
960
                if ( s1 > AO.floatspace && s1[-1] != '.' ) {
474✔
961
                        s1--; n2--;
474✔
962
                        s2 = s1; n1 = n2;
474✔
963
                        while ( s1[-1] == '0' ) { s1--; n1--; }
2,490✔
964
                        if ( s1[-1] == '.' ) { s1++; n1++; }
474✔
965
                        while ( n2 < n ) { *s1++ = *s2++; n2++; }
2,370✔
966
                        n -= (n2-n1);
474✔
967
                        *s1 = 0;
474✔
968
                }
969
        }
970
        return(n);
474✔
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✔
1143
                mpf_clear(mpfdelta1);
×
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)
192✔
1162
{
1163
#ifdef WITHPTHREADS
1164
        int id, totnum;
128✔
1165
        mpf_t *a;
128✔
1166
/*
1167
        Now the aux variables
1168
*/
1169
#ifdef WITHSORTBOTS
1170
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
128✔
1171
#endif
1172
    for ( id = 0; id < totnum; id++ ) {
768✔
1173
                if ( AB[id]->T.aux_ ) {
640✔
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_");
640✔
1183
                a = (mpf_t *)AB[id]->T.aux_;
640✔
1184
                mpf_inits(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
640✔
1185
                if ( AB[id]->T.indi1 ) M_free(AB[id]->T.indi1,"indi1");
640✔
1186
                AB[id]->T.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
640✔
1187
                AB[id]->T.indi2 = AB[id]->T.indi1 + AC.MaxWeight;
640✔
1188
        }
1189
#else
1190
/*
1191
        Now the aux variables
1192
*/
1193
        if ( AT.aux_ ) {
64✔
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_");
64✔
1198
        mpf_inits(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
64✔
1199
        if ( AT.indi1 ) M_free(AT.indi1,"indi1");
64✔
1200
        AT.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
64✔
1201
        AT.indi2 = AT.indi1 + AC.MaxWeight;
64✔
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
}
192✔
1209

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

1215
void ClearMZVTables(void)
162✔
1216
{
1217
#ifdef WITHPTHREADS
1218
        int i, id, totnum;
108✔
1219
        mpf_t *a;
108✔
1220
        totnum = AM.totalnumberofthreads;
108✔
1221
    for ( id = 0; id < totnum; id++ ) {
540✔
1222
                if ( AB[id]->T.mpf_tab1 ) { 
432✔
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 ) { 
432✔
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);
108✔
1245
#endif
1246
    for ( id = 0; id < totnum; id++ ) {
648✔
1247
                if ( AB[id]->T.aux_ ) { 
540✔
1248
                        a = (mpf_t *)AB[id]->T.aux_;
540✔
1249
                        mpf_clears(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],(mpf_ptr)0);
540✔
1250
                        M_free(AB[id]->T.aux_,"AB[id]->T.aux_");
540✔
1251
                        AB[id]->T.aux_ = 0; 
540✔
1252
                }
1253
                if ( AB[id]->T.indi1 ) { M_free(AB[id]->T.indi1,"indi1"); AB[id]->T.indi1 = 0; }
540✔
1254
        }
1255
#else
1256
        int i;
54✔
1257
        if ( AT.mpf_tab1 ) { 
54✔
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 ) { 
54✔
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_ ) { 
54✔
1272
                mpf_clears(aux1,aux2,aux3,aux4,aux5,auxjm,auxjjm,auxsum,(mpf_ptr)0);
54✔
1273
                M_free(AT.aux_,"AT.aux_"); 
54✔
1274
                AT.aux_ = 0; 
54✔
1275
        }
1276
        if ( AT.indi1 ) { M_free(AT.indi1,"indi1"); AT.indi1 = 0; }
54✔
1277
#endif
1278
        if ( AO.floatspace ) { M_free(AO.floatspace,"floatspace"); AO.floatspace = 0;
162✔
1279
                AO.floatsize = 0; }
162✔
1280
        if ( AS.delta_1 ) { 
162✔
1281
                mpf_clear(mpfdelta1);
156✔
1282
                M_free(AS.delta_1,"delta1"); 
156✔
1283
                AS.delta_1 = 0; 
156✔
1284
        }
1285
}
162✔
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✔
1302
                MesPrint("&Illegal argument(s) in ToFloat statement: '%s'",s);
×
1303
                return(1);
×
1304
        }
1305
        Add2Com(TYPETOFLOAT);
24✔
1306
        return(0);
24✔
1307
}
1308

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

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

1370
int ToRat(PHEAD WORD *term, WORD level)
×
1371
{
1372
        WORD *tstop, *t, nsize, nsign, ncoef;
×
1373
/*
1374
        1: find the float which should be at the end.
1375
*/
1376
        tstop = term + *term; nsize = ABS(tstop[-1]);
×
1377
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
×
1378
        t = term+1;
×
1379
        while ( t < tstop ) {
×
1380
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
×
1381
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
×
1382
                t += t[1];
×
1383
        }
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
*/
1389
                UnpackFloat(aux4,t);
×
1390
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
×
1391
                        t += ABS(ncoef);
×
1392
                        t[-1] = ncoef*nsign;
×
1393
                        *term = t - term;
×
1394
                }
1395
        }
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
int AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
12✔
1440
{
1441
        GETBIDENTITY
1442
        SORTING *S = AT.SS;
12✔
1443
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
12✔
1444
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
12✔
1445
        s1 = *ps1;
12✔
1446
        s2 = *ps2;
12✔
1447
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
12✔
1448
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
12✔
1449
        if ( AT.SortFloatMode == 3 ) {
12✔
1450
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
12✔
1451
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
12✔
1452
                UnpackFloat(aux1,fun1);
6✔
1453
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
6✔
1454
                UnpackFloat(aux2,fun2);
6✔
1455
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
6✔
1456
        }
1457
        else if ( AT.SortFloatMode == 1 ) {
6✔
1458
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1459
                UnpackFloat(aux1,fun1);
×
1460
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1461
                fun2 = coef2;
×
1462
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1463
        }
1464
        else if ( AT.SortFloatMode == 2 ) {
6✔
1465
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
12✔
1466
                fun1 = coef1;
6✔
1467
                RatToFloat(aux1,(UWORD *)coef1,size1);
6✔
1468
                UnpackFloat(aux2,fun2);
6✔
1469
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
6✔
1470
        }
1471
        else {
1472
                MLOCK(ErrorMessageLock);
×
1473
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1474
                MUNLOCK(ErrorMessageLock);
×
1475
                Terminate(-1);
×
1476
                return(0);
×
1477
        }
1478
        mpf_add(aux3,aux1,aux2);
12✔
1479
        sign3 = mpf_sgn(aux3);
12✔
1480
        if ( sign3 == 0 ) {        /* May be rare! */
12✔
1481
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1482
        }
1483
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
12✔
1484
        fun3 = TermMalloc("AddWithFloat");
12✔
1485
        PackFloat(fun3,aux3);
12✔
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 ) {
12✔
1497
                if ( fun1[1] == fun3[1]  ) {
6✔
1498
Over1:
×
1499
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
120✔
1500
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
6✔
1501
                        *s1 = t1-s1; goto Finished;
6✔
1502
                }
1503
                else if ( fun2[1] == fun3[1]  ) {
6✔
1504
Over2:
×
1505
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
120✔
1506
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
6✔
1507
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
6✔
1508
                }
1509
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
6✔
1510
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
×
1511
        }
1512
        else if ( AT.SortFloatMode == 1 ) {
6✔
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 ) {
6✔
1517
                if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1518
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1519
        }
1520
/*
1521
        Does not fit. Go to extension space.
1522
*/
1523
        jj = fun1-s1;
×
1524
        j = jj+fun3[1]+3; /* space needed */
×
1525
        if ( (S->sFill + j) >= S->sTop2 ) {
×
1526
                GarbHand();
×
1527
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1528
                fun1 = s1+jj;
×
1529
        }
1530
        t1 = S->sFill;
×
1531
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
×
1532
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
×
1533
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1534
        *ps1 = S->sFill;
×
1535
        **ps1 = t1-*ps1;
×
1536
        S->sFill = t1;
×
1537
Finished:
12✔
1538
        *ps2 = 0;
12✔
1539
        TermFree(fun3,"AddWithFloat");
12✔
1540
        AT.SortFloatMode = 0;
12✔
1541
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
12✔
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
int 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;
×
1565
        int retval = 0;
×
1566
        coef1 = term1+*term1; size1 = coef1[-1]; coef1 -= ABS(size1);
×
1567
        coef2 = term2+*term2; size2 = coef2[-1]; coef2 -= ABS(size2);
×
1568
        if ( AT.SortFloatMode == 3 ) {
×
1569
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1570
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1571
                UnpackFloat(aux1,fun1);
×
1572
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1573
                UnpackFloat(aux2,fun2);
×
1574
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1575
        }
1576
        else if ( AT.SortFloatMode == 1 ) {
×
1577
                fun1 = term1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1578
                UnpackFloat(aux1,fun1);
×
1579
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1580
                fun2 = coef2;
×
1581
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1582
        }
1583
        else if ( AT.SortFloatMode == 2 ) {
×
1584
                fun2 = term2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1585
                fun1 = coef1;
×
1586
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
1587
                UnpackFloat(aux2,fun2);
×
1588
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1589
        }
1590
        else {
1591
                MLOCK(ErrorMessageLock);
×
1592
                MesPrint("Illegal value %d for AT.SortFloatMode in MergeWithFloat.",AT.SortFloatMode);
×
1593
                MUNLOCK(ErrorMessageLock);
×
1594
                Terminate(-1);
×
1595
                return(0);
×
1596
        }
1597
        mpf_add(aux3,aux1,aux2);
×
1598
        sign3 = mpf_sgn(aux3);
×
1599
        if ( sign3 == 0 ) {        /* May be very rare! */
×
1600
                AT.SortFloatMode = 0; return(0);
×
1601
        }
1602
/*
1603
        Now check whether we can park the result on top of one of the input terms.
1604
*/
1605
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
1606
        fun3 = TermMalloc("MergeWithFloat");
×
1607
        PackFloat(fun3,aux3);
×
1608
        if ( AT.SortFloatMode == 3 ) {
×
1609
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) {
×
1610
OnTopOf1:        t1 = fun3; t2 = fun1;
×
1611
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1612
                        *t2++ = 1; *t2++ = 1; *t2++ = sign3 < 0 ? -3: 3;
×
1613
                        retval = 1;
×
1614
                }
1615
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) {
×
1616
Shift1:                t2 = term1 + *term1; tt = t2;
×
1617
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1618
                        t1 = fun3 + fun3[1]; for ( i = 0; i < fun3[1]; i++ ) *--t2 = *--t1;
×
1619
                        t1 = fun1;
1620
                        while ( t1 > term1 ) *--t2 = *--t1;
×
1621
                        *t2 = tt-t2; term1 = t2;
×
1622
                        retval = 1;
×
1623
                }
1624
                else { /* Here we have to move term1 to the left to make room. */
1625
Over1:                jj = fun3[1]-fun1[1]+3-ABS(size1); /* This is positive */
×
1626
                        t2 = term1-jj; t1 = term1;
×
1627
                        while ( t1 < fun1 ) *t2++ = *t1++;
×
1628
                        term1 -= jj;
×
1629
                        *term1 += jj;
×
1630
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = fun3[i];
×
1631
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1632
                        retval = 1;
×
1633
                }
1634
        }
1635
        else if ( AT.SortFloatMode == 1 ) {
×
1636
                if ( fun1[1] + ABS(size1) == fun3[1] + 3 ) goto OnTopOf1;
×
1637
                else if ( fun1[1] + ABS(size1) > fun3[1] + 3 ) goto Shift1;
×
1638
                else goto Over1;
×
1639
        }
1640
        else { /* Can only be 2, based on previous tests */
1641
                if ( fun3[1] + 3 == ABS(size1) ) {
×
1642
                        t2 = coef1; t1 = fun3;
1643
                        for ( i = 0; i < fun3[1]; i++ ) *t2++ = *t1++;
×
1644
                        *t2++ = 1; *t2++ = 1;  *t2++ = sign3 < 0 ? -3: 3;
×
1645
                        retval = 1;
×
1646
                }
1647
                else if ( fun3[1] + 3 < ABS(size1) ) {
×
1648
                        j = ABS(size1) - fun3[1] - 3;
×
1649
                        t2 = term1 + *term1; tt = t2;
×
1650
                        *--t2 = sign3 < 0 ? -3: 3; *--t2 = 1; *--t2 = 1;
×
1651
                        t2 -= fun3[1]; t1 = t2-j;
×
1652
                        while ( t2 > term1 ) *--t2 = *--t1;
×
1653
                        *t2 = tt-t2; term1 = t2;
×
1654
                        retval = 1;
×
1655
                }
1656
                else goto Over1;
×
1657
        }
1658
        *interm1 = term1;
×
1659
        TermFree(fun3,"MergeWithFloat");
×
1660
        AT.SortFloatMode = 0;
×
1661
        return(retval);
×
1662
}
1663

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

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

1678
                 #[ SimpleDelta :
1679
*/
1680

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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