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

form-dev / form / 15701338753

17 Jun 2025 07:49AM UTC coverage: 50.382% (-0.004%) from 50.386%
15701338753

Pull #662

github

web-flow
Merge f1f68c050 into 207386593
Pull Request #662: Cleanup: change VOID into void

178 of 245 new or added lines in 34 files covered. (72.65%)

2 existing lines in 1 file now uncovered.

41784 of 82935 relevant lines covered (50.38%)

2640008.85 hits per line

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

30.76
/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 SetFloatPrecision(WORD prec);
58
int AddFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
59
int MulFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
60
int DivFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
61
int AddRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
62
int MulRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
63
void SimpleDelta(mpf_t sum, int m);
64
void SimpleDeltaC(mpf_t sum, int m);
65
void SingleTable(mpf_t *tabl, int N, int m, int pow);
66
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow);
67
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow);
68
void deltaMZV(mpf_t, int *, int);
69
void deltaEuler(mpf_t, int *, int);
70
void deltaEulerC(mpf_t, int *, int);
71
void CalculateMZVhalf(mpf_t, int *, int);
72
void CalculateMZV(mpf_t, int *, int);
73
void CalculateEuler(mpf_t, int *, int);
74
int ExpandMZV(WORD *term, WORD level);
75
int ExpandEuler(WORD *term, WORD level);
76
int PackFloat(WORD *,mpf_t);
77
int UnpackFloat(mpf_t, WORD *);
78
void RatToFloat(mpf_t result, UWORD *formrat, int ratsize);
79
 
80
/*
81
          #] Includes : 
82
          #[ Some GMP float info :
83

84
        From gmp.h:
85

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

99
        typedef __mpf_struct mpf_t[1];
100

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

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

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

122
        From mpfr.h
123

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

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

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

141
                 #[ Explanations :
142

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

849
UBYTE *CheckFloat(UBYTE *ss, int *spec)
2,516,574✔
850
{
851
        GETIDENTITY
1,677,708✔
852
        UBYTE *s = ss;
2,516,574✔
853
        int zero = 1, gotdot = 0;
2,516,574✔
854
        while ( FG.cTable[s[-1]] == 1 ) s--;
7,380,024✔
855
        *spec = 0;
2,516,574✔
856
        if ( FG.cTable[*s] == 1 ) {
2,516,574✔
857
                while ( *s == '0' ) s++;
2,709,960✔
858
                if ( FG.cTable[*s] == 1 ) {
2,516,574✔
859
                        s++;
2,323,266✔
860
                        while ( FG.cTable[*s] == 1 ) s++;
4,670,106✔
861
                        zero = 0;
862
                }
863
                if ( *s == '.' ) { goto dot; }
2,516,574✔
864
        }
865
        else if ( *s == '.' ) {
×
866
dot:
×
867
                gotdot = 1;
×
868
                s++;
×
869
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
×
870
                while ( *s == '0' ) s++;
×
871
                if ( FG.cTable[*s] == 1 ) {
×
872
                        s++;
×
873
                        while ( FG.cTable[*s] == 1 ) s++;
×
874
                        zero = 0;
875
                }
876
        }
877
        else return(ss);
878
/*
879
        Now we have had the mantissa part, which may be zero.
880
        Check for an exponent.
881
*/
882
        if ( *s == 'e' || *s == 'E' ) {
2,516,574✔
883
                s++;
×
884
                if ( *s == '-' || *s == '+' ) s++;
×
885
                if ( FG.cTable[*s] == 1 ) {
×
886
                        s++;
×
887
                        while ( FG.cTable[*s] == 1 ) s++;
×
888
                }
889
                else { return(ss); }
890
        }
891
        else if ( gotdot == 0 ) return(ss);
2,516,574✔
892
        if ( AT.aux_ == 0 ) { /* no floating point system */
×
893
                *spec = -1;
×
894
                return(s);
×
895
        }
896
        if ( zero ) *spec = 1;
×
897
        return(s);
898
}
899

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

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

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

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

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

941
int PrintFloat(WORD *fun,int numdigits)
114✔
942
{
943
        GETIDENTITY
76✔
944
        int n = 0;
114✔
945
        int prec = (AC.DefaultPrecision-AC.MaxWeight-1)*log10(2.0);
114✔
946
        if ( numdigits > prec || numdigits == 0 ) {
114✔
947
                numdigits = prec;
114✔
948
        }
949
        if ( UnpackFloat(aux4,fun) == 0 )
114✔
950
                n = gmp_snprintf((char *)(AO.floatspace),AO.floatsize,"%.*Fe",numdigits,aux4);
114✔
951
        if ( numdigits == prec ) {
114✔
952
                UBYTE *s1, *s2;
114✔
953
                int n1, n2 = n;
114✔
954
                s1 = AO.floatspace+n;
114✔
955
                while ( s1 > AO.floatspace && s1[-1] != 'e'
570✔
956
                 && s1[-1] != 'E' && s1[-1] != '.' ) { s1--; n2--; }
456✔
957
                if ( s1 > AO.floatspace && s1[-1] != '.' ) {
114✔
958
                        s1--; n2--;
114✔
959
                        s2 = s1; n1 = n2;
114✔
960
                        while ( s1[-1] == '0' ) { s1--; n1--; }
3,216✔
961
                        if ( s1[-1] == '.' ) { s1++; n1++; }
114✔
962
                        while ( n2 < n ) { *s1++ = *s2++; n2++; }
570✔
963
                        n -= (n2-n1);
114✔
964
                        *s1 = 0;
114✔
965
                }
966
        }
967
        return(n);
114✔
968
}
969

970
/*
971
                 #] PrintFloat : 
972
                 #[ AddFloats :
973
*/
974

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

986
/*
987
                 #] AddFloats : 
988
                 #[ MulFloats :
989
*/
990

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

1002
/*
1003
                 #] MulFloats : 
1004
                 #[ DivFloats :
1005
*/
1006

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

1018
/*
1019
                 #] DivFloats : 
1020
                 #[ AddRatToFloat :
1021

1022
                Note: this can be optimized, because often the rat is rather simple.
1023
*/
1024

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

1037
/*
1038
                 #] AddRatToFloat : 
1039
                 #[ MulRatToFloat :
1040

1041
                Note: this can be optimized, because often the rat is rather simple.
1042
*/
1043

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

1056
/*
1057
                 #] MulRatToFloat : 
1058
                 #[ SetupMZVTables :
1059
*/
1060

1061
void SetupMZVTables(void)
24✔
1062
{
1063
/*
1064
        Sets up a table of N+1 mpf_t floats with variable precision.
1065
        It assumes that each next element needs one bit less.
1066
        Initializes all of them.
1067
        We take some extra space, to have one limb overflow everywhere.
1068
        Because the depth of the MZV's can get close to the weight
1069
        and each deeper sum goes one higher, we make the tablesize a bit bigger.
1070
        This may not be needed if we fiddle with the sum boundaries.
1071
*/
1072
        size_t nt = sizeof(mp_limb_t);
24✔
1073
        int prec;
24✔
1074
#ifdef WITHPTHREADS
1075
        int i, Nw, id, totnum;
16✔
1076
        size_t fullsize, N, sumsize, j;
16✔
1077
        mp_limb_t *d;
16✔
1078
        Nw = AC.DefaultPrecision+AC.MaxWeight+1;
16✔
1079
        SetFloatPrecision(Nw);
16✔
1080
/*        prec = (AC.DefaultPrecision + 8*nt-1)/(8*nt); */
1081
        N = (size_t)Nw;
16✔
1082
        for ( i = 0, sumsize = 0; i <= Nw+1; i++ ) sumsize += (Nw-i+8*nt)/(8*nt)+1;
3,536✔
1083
        fullsize = (N+2)*sizeof(mpf_t)+sumsize*nt;
16✔
1084
        totnum = AM.totalnumberofthreads;
16✔
1085
    for ( id = 0; id < totnum; id++ ) {
80✔
1086
          if ( AB[id]->T.mpf_tab1 ) M_free(AB[id]->T.mpf_tab1,"mpftab1");
64✔
1087
          AB[id]->T.mpf_tab1 = (void *)Malloc1(fullsize,"mpftab1");
64✔
1088
          d = (mp_limb_t *)(((mpf_t *)(AB[id]->T.mpf_tab1))+N+2);
64✔
1089
          for ( j = 0; j < sumsize; j++ ) d[j] = 0;
46,656✔
1090
          for ( i = 0; i <= Nw; i++ ) {
14,080✔
1091
                ((mpf_t *)(AB[id]->T.mpf_tab1))[i]->_mp_prec = (Nw-i+8*nt)/(8*nt);
14,016✔
1092
                ((mpf_t *)(AB[id]->T.mpf_tab1))[i]->_mp_size = 0;
14,016✔
1093
                ((mpf_t *)(AB[id]->T.mpf_tab1))[i]->_mp_exp = 0;
14,016✔
1094
                ((mpf_t *)(AB[id]->T.mpf_tab1))[i]->_mp_d = d;
14,016✔
1095
                d += (Nw-i+8*nt)/(8*nt)+1;
14,016✔
1096
          }
1097
          if ( AB[id]->T.mpf_tab2 ) M_free(AB[id]->T.mpf_tab2,"mpftab2");
64✔
1098
          AB[id]->T.mpf_tab2 = (void *)Malloc1(fullsize,"mpftab2");
64✔
1099
          d = (mp_limb_t *)(((mpf_t *)(AB[id]->T.mpf_tab2))+N+1);
64✔
1100
          for ( j = 0; j < sumsize; j++ ) d[j] = 0;
46,656✔
1101
          for ( i = 0; i <= Nw; i++ ) {
14,080✔
1102
                ((mpf_t *)(AB[id]->T.mpf_tab2))[i]->_mp_prec = (Nw-i+8*nt)/(8*nt);
14,016✔
1103
                ((mpf_t *)(AB[id]->T.mpf_tab2))[i]->_mp_size = 0;
14,016✔
1104
                ((mpf_t *)(AB[id]->T.mpf_tab2))[i]->_mp_exp = 0;
14,016✔
1105
                ((mpf_t *)(AB[id]->T.mpf_tab2))[i]->_mp_d = d;
14,016✔
1106
                d += (Nw-i+8*nt)/(8*nt)+1;
14,016✔
1107
          }
1108
        }
1109
#else
1110
        int i, Nw;
8✔
1111
        size_t fullsize, N, sumsize, j;
8✔
1112
        mp_limb_t *d;
8✔
1113
/*        Nw = AC.DefaultPrecision+AC.MaxWeight+sizeof(mp_limb_t); */
1114
        Nw = AC.DefaultPrecision+AC.MaxWeight+1;
8✔
1115
        SetFloatPrecision(Nw);
8✔
1116
/*        prec = (AC.DefaultPrecision + 8*nt-1)/(8*nt); */
1117
        N = (size_t)Nw;
8✔
1118
        for ( i = 0, sumsize = 0; i <= Nw+1; i++ ) sumsize += (Nw-i+8*nt)/(8*nt)+1;
1,768✔
1119
        fullsize = (N+2)*sizeof(mpf_t)+sumsize*nt;
8✔
1120
        if ( mpftab1 ) M_free(mpftab1,"mpftab1");
8✔
1121
        AT.mpf_tab1 = (void *)Malloc1(fullsize,"mpftab1");
8✔
1122
        d = (mp_limb_t *)(((mpf_t *)(AT.mpf_tab1))+N+1);
8✔
1123
        for ( j = 0; j < sumsize; j++ ) d[j] = 0;
5,832✔
1124
        for ( i = 0; i <= Nw; i++ ) {
1,760✔
1125
                mpftab1[i]->_mp_prec = (Nw-i+8*nt)/(8*nt);
1,752✔
1126
                mpftab1[i]->_mp_size = 0;
1,752✔
1127
                mpftab1[i]->_mp_exp = 0;
1,752✔
1128
                mpftab1[i]->_mp_d = d;
1,752✔
1129
                d += (Nw-i+8*nt)/(8*nt)+1;
1,752✔
1130
        }
1131
        if ( mpftab2 ) M_free(mpftab2,"mpftab2");
8✔
1132
        AT.mpf_tab2 = (void *)Malloc1(fullsize,"mpftab2");
8✔
1133
        d = (mp_limb_t *)(((mpf_t *)(AT.mpf_tab2))+N+1);
8✔
1134
        for ( j = 0; j < sumsize; j++ ) d[j] = 0;
5,832✔
1135
        for ( i = 0; i <= Nw; i++ ) {
1,760✔
1136
                mpftab2[i]->_mp_prec = (Nw-i+8*nt)/(8*nt);
1,752✔
1137
                mpftab2[i]->_mp_size = 0;
1,752✔
1138
                mpftab2[i]->_mp_exp = 0;
1,752✔
1139
                mpftab2[i]->_mp_d = d;
1,752✔
1140
                d += (Nw-i+8*nt)/(8*nt)+1;
1,752✔
1141
        }
1142
#endif
1143
        if ( AS.delta_1 ) M_free(AS.delta_1,"delta1");
24✔
1144
        prec = (AC.DefaultPrecision + 8*nt-1)/(8*nt);
24✔
1145
        AS.delta_1 = (void *)Malloc1((prec+1)*sizeof(mp_limb_t)+sizeof(mpf_t),"delta1");
24✔
1146
        d = (mp_limb_t *)(((mpf_t *)(AS.delta_1))+1);
24✔
1147
        mpfdelta1->_mp_prec = prec;
24✔
1148
        mpfdelta1->_mp_size = 0;
24✔
1149
        mpfdelta1->_mp_exp = 0;
24✔
1150
        mpfdelta1->_mp_d = d;
24✔
1151
        SimpleDelta(mpfdelta1,1); /* this can speed up things. delta1 = ln(2) */
24✔
1152
/*
1153
        Finally the character buffer for printing
1154
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1155
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1156
*/
1157
}
24✔
1158

1159
/*
1160
                 #] SetupMZVTables : 
1161
                 #[ SetupMPFTables :
1162
*/
1163

1164
void SetupMPFTables(void)
24✔
1165
{
1166
        size_t nt = sizeof(mp_limb_t);
24✔
1167
        int prec, prec1, i;
24✔
1168
#ifdef WITHPTHREADS
1169
        int Nw, id, totnum;
16✔
1170
        size_t j;
16✔
1171
        mp_limb_t *d;
16✔
1172
        Nw = AC.DefaultPrecision+AC.MaxWeight+1;
16✔
1173
        SetFloatPrecision(Nw);
16✔
1174
        prec = (AC.DefaultPrecision + 8*nt-1)/(8*nt);
16✔
1175
        prec1 = prec+1;
16✔
1176
/*
1177
        Now the aux variables
1178
*/
1179
#ifdef WITHSORTBOTS
1180
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
16✔
1181
#endif
1182
    for ( id = 0; id < totnum; id++ ) {
96✔
1183
                if ( AB[id]->T.aux_ ) M_free(AB[id]->T.aux_,"aux_");
80✔
1184
                AB[id]->T.aux_ = (void *)Malloc1(8*(prec1*sizeof(mp_limb_t)+sizeof(mpf_t)),"aux-mp");
80✔
1185
                d = (mp_limb_t *)(((mpf_t *)(AB[id]->T.aux_))+8);
80✔
1186
                for ( j = 0; j < (size_t)(8*prec); j++ ) d[j] = 0;
2,160✔
1187
                for ( i = 0; i < 8; i++ ) {
720✔
1188
                        ((mpf_t *)(AB[id]->T.aux_))[i]->_mp_prec = prec;
640✔
1189
                        ((mpf_t *)(AB[id]->T.aux_))[i]->_mp_size = 0;
640✔
1190
                        ((mpf_t *)(AB[id]->T.aux_))[i]->_mp_exp = 0;
640✔
1191
                        ((mpf_t *)(AB[id]->T.aux_))[i]->_mp_d = d;
640✔
1192
                        d += prec1;
640✔
1193
                }
1194
                if ( AB[id]->T.indi1 ) M_free(AB[id]->T.indi1,"indi1");
80✔
1195
                AB[id]->T.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
80✔
1196
                AB[id]->T.indi2 = AB[id]->T.indi1 + AC.MaxWeight;
80✔
1197
        }
1198
#else
1199
        int Nw;
8✔
1200
        size_t j;
8✔
1201
        mp_limb_t *d;
8✔
1202
/*        Nw = AC.DefaultPrecision+AC.MaxWeight+sizeof(mp_limb_t); */
1203
        Nw = AC.DefaultPrecision+AC.MaxWeight+1;
8✔
1204
        SetFloatPrecision(Nw);
8✔
1205
        prec = (AC.DefaultPrecision + 8*nt-1)/(8*nt);
8✔
1206
        prec1 = prec+1;
8✔
1207
/*
1208
        Now the aux variables
1209
*/
1210
        if ( mpfaux_ ) M_free(mpfaux_,"aux_");
8✔
1211
        AT.aux_ = (void *)Malloc1(8*(prec1*sizeof(mp_limb_t)+sizeof(mpf_t)),"aux_");
8✔
1212
        d = (mp_limb_t *)(((mpf_t *)(AT.aux_))+8);
8✔
1213
        for ( j = 0; j < (size_t)(8*prec); j++ ) d[j] = 0;
216✔
1214
        for ( i = 0; i < 8; i++ ) {
72✔
1215
                ((mpf_t *)(AT.aux_))[i]->_mp_prec = prec;
64✔
1216
                ((mpf_t *)(AT.aux_))[i]->_mp_size = 0;
64✔
1217
                ((mpf_t *)(AT.aux_))[i]->_mp_exp = 0;
64✔
1218
                ((mpf_t *)(AT.aux_))[i]->_mp_d = d;
64✔
1219
                d += prec1;
64✔
1220
        }
1221
        if ( AT.indi1 ) M_free(AT.indi1,"indi1");
8✔
1222
        AT.indi1 = (int *)Malloc1(sizeof(int)*AC.MaxWeight*2,"indi1");
8✔
1223
        AT.indi2 = AT.indi1 + AC.MaxWeight;
8✔
1224
#endif
1225
/*
1226
        Finally the character buffer for printing
1227
        if ( AO.floatspace ) M_free(AO.floatspace,"floatspace");
1228
        AO.floatspace = (UBYTE *)Malloc1(((10*AC.DefaultPrecision)/33+40)*sizeof(UBYTE),"floatspace");
1229
*/
1230
}
24✔
1231

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

NEW
1237
void ClearMZVTables(void)
×
1238
{
1239
#ifdef WITHPTHREADS
1240
        int id, totnum;
1241
        totnum = AM.totalnumberofthreads;
1242
    for ( id = 0; id < totnum; id++ ) {
1243
                if ( AB[id]->T.mpf_tab1 ) { M_free(AB[id]->T.mpf_tab1,"mpftab1"); AB[id]->T.mpf_tab1 = 0; }
1244
                if ( AB[id]->T.mpf_tab2 ) { M_free(AB[id]->T.mpf_tab2,"mpftab2"); AB[id]->T.mpf_tab2 = 0; }
1245
        }
1246
#ifdef WITHSORTBOTS
1247
        totnum = MaX(2*AM.totalnumberofthreads-3,AM.totalnumberofthreads);
1248
#endif
1249
    for ( id = 0; id < totnum; id++ ) {
1250
                if ( AB[id]->T.aux_ ) { M_free(AB[id]->T.aux_,"aux-mp"); AB[id]->T.aux_ = 0; }
1251
                if ( AB[id]->T.indi1 ) { M_free(AB[id]->T.indi1,"indi1"); AB[id]->T.indi1 = 0; }
1252
        }
1253
#else
1254
        if ( AT.mpf_tab1 ) { M_free(AT.mpf_tab1,"mpftab1"); AT.mpf_tab1 = 0; }
1255
        if ( AT.mpf_tab2 ) { M_free(AT.mpf_tab2,"mpftab2"); AT.mpf_tab2 = 0; }
1256
        if ( AT.aux_ ) { M_free(AT.aux_,"aux-mp"); AT.aux_ = 0; }
1257
        if ( AT.indi1 ) { M_free(AT.indi1,"indi1"); AT.indi1 = 0; }
1258
#endif
1259
        if ( AO.floatspace ) { M_free(AO.floatspace,"floatspace"); AO.floatspace = 0;
×
1260
                AO.floatsize = 0; }
×
1261
        if ( AS.delta_1 ) { mpfdelta1->_mp_d = 0; M_free(AS.delta_1,"delta1"); }
×
1262
}
×
1263

1264
/*
1265
                 #] ClearMZVTables : 
1266
                 #[ CoToFloat :
1267
*/
1268

1269
int CoToFloat(UBYTE *s)
24✔
1270
{
1271
        GETIDENTITY
16✔
1272
        if ( AT.aux_ == 0 ) {
24✔
1273
                MesPrint("&Illegal attempt to convert to float_ without activating floating point numbers.");
×
1274
                MesPrint("&Forgotten %#startfloat instruction?");
×
1275
                return(1);
×
1276
        }
1277
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
24✔
1278
        if ( *s ) {
24✔
1279
                MesPrint("&Illegal argument(s) in ToFloat statement: '%s'",s);
×
1280
                return(1);
×
1281
        }
1282
        Add2Com(TYPETOFLOAT);
24✔
1283
        return(0);
24✔
1284
}
1285

1286
/*
1287
                 #] CoToFloat : 
1288
                 #[ CoToRat :
1289
*/
1290

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

1308
/*
1309
                 #] CoToRat : 
1310
                 #[ ToFloat :
1311

1312
                Converts the coefficient to floating point if it is still a rat.
1313
*/
1314

1315
int ToFloat(PHEAD WORD *term, WORD level)
114✔
1316
{
1317
        WORD *t, *tstop, nsize, nsign = 3;
114✔
1318
        t = term+*term;
114✔
1319
        nsize = ABS(t[-1]);
114✔
1320
        tstop = t - nsize;
114✔
1321
        if ( t[-1] < 0 ) { nsign = -nsign; }
114✔
1322
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
114✔
1323
                t = term + 1;
108✔
1324
                while ( t < tstop ) {
222✔
1325
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
114✔
1326
                                return(Generator(BHEAD term,level));
×
1327
                        }
1328
                        t += t[1];
114✔
1329
                }
1330
        }
1331
        RatToFloat(aux4,(UWORD *)tstop,nsize);
114✔
1332
        PackFloat(tstop,aux4);
114✔
1333
        tstop += tstop[1];
114✔
1334
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
114✔
1335
        *term = tstop - term;
114✔
1336
        AT.WorkPointer = tstop;
114✔
1337
        return(Generator(BHEAD term,level));
114✔
1338
}
1339

1340
/*
1341
                 #] ToFloat : 
1342
                 #[ ToRat :
1343

1344
                Tries to convert the coefficient to rational if it is still a float.
1345
*/
1346

1347
int ToRat(PHEAD WORD *term, WORD level)
×
1348
{
1349
        WORD *tstop, *t, nsize, nsign, ncoef;
×
1350
/*
1351
        1: find the float which should be at the end.
1352
*/
1353
        tstop = term + *term; nsize = ABS(tstop[-1]);
×
1354
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
×
1355
        t = term+1;
×
1356
        while ( t < tstop ) {
×
1357
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
×
1358
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
×
1359
                t += t[1];
×
1360
        }
1361
        if ( t < tstop ) {
×
1362
/*
1363
                Now t points at the float_ function and everything is correct.
1364
                The result can go straight over the float_ function.
1365
*/
1366
                UnpackFloat(aux4,t);
×
1367
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
×
1368
                        t += ABS(ncoef);
×
1369
                        t[-1] = ncoef*nsign;
×
1370
                        *term = t - term;
×
1371
                }
1372
        }
1373
        return(Generator(BHEAD term,level));
×
1374
}
1375

1376
/*
1377
                 #] ToRat : 
1378
          #] Float Routines : 
1379
          #[ Sorting :
1380

1381
                We need a method to see whether two terms need addition that could
1382
                involve floating point numbers.
1383
                1: if PolyWise is active, we do not need anything, because
1384
                   Poly(Rat)Fun and floating point are mutually exclusive.
1385
                2: This means that there should be only interference in AddCoef.
1386
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1387
                   and PF_GetLoser.
1388
                The compare routine(s) should recognise the float_ and give off
1389
                a code (SortFloatMode) inside the AT struct:
1390
                0: no float_
1391
                1: float_ in term1 only
1392
                2: float_ in term2 only
1393
                3: float_ in both terms
1394
                Be careful: we have several compare routines, because various codes
1395
                use their own routines and we just set a variable with its address.
1396
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1397
                Only Compare1 should be active for this. The others should make sure
1398
                that the proper variable is always zero.
1399
                Remember: the sign of the coefficient is in the last word of the term.
1400

1401
                We need two routines:
1402
                1: AddWithFloat for SplitMerge which sorts by pointer.
1403
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1404
                   as possible in their location.
1405
                The routines start out the same, because AT.SortFloatMode, set in
1406
                Compare1, tells more or less what should be done.
1407
                The difference is in where we leave the result.
1408

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

1413
                 #[ AddWithFloat :
1414
*/
1415

1416
WORD AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
×
1417
{
1418
        GETBIDENTITY
1419
        SORTING *S = AT.SS;
×
1420
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
×
1421
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
×
1422
        s1 = *ps1;
×
1423
        s2 = *ps2;
×
1424
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
×
1425
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
×
1426
        if ( AT.SortFloatMode == 3 ) {
×
1427
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1428
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1429
                UnpackFloat(aux1,fun1);
×
1430
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1431
                UnpackFloat(aux2,fun2);
×
1432
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1433
        }
1434
        else if ( AT.SortFloatMode == 1 ) {
×
1435
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1436
                UnpackFloat(aux1,fun1);
×
1437
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1438
                fun2 = coef2;
×
1439
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1440
        }
1441
        else if ( AT.SortFloatMode == 2 ) {
×
1442
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
×
1443
                fun1 = coef1;
×
1444
                RatToFloat(aux1,(UWORD *)coef1,size1);
×
1445
                UnpackFloat(aux2,fun2);
×
1446
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
×
1447
        }
1448
        else {
1449
                MLOCK(ErrorMessageLock);
×
1450
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1451
                MUNLOCK(ErrorMessageLock);
×
1452
                Terminate(-1);
×
1453
                return(0);
×
1454
        }
1455
        mpf_add(aux3,aux1,aux2);
×
1456
        sign3 = mpf_sgn(aux3);
×
1457
        if ( sign3 == 0 ) {        /* May be rare! */
×
1458
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1459
        }
1460
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
×
1461
        fun3 = TermMalloc("AddWithFloat");
×
1462
        PackFloat(fun3,aux3);
×
1463
/*
1464
        Now we have to calculate where the sumterm fits.
1465
        If we are sloppy, we can be faster, but run the risk to need the
1466
        extension space, even when it is not needed. At slightly lower speed
1467
        (ie first creating the result in scribble space) we are better off.
1468
        This is why we use TermMalloc.
1469

1470
        The new term will have a rational coefficient of 1,1,+-3.
1471
        The size will be (fun1 or fun2 - term) + fun3 +3;
1472
*/
1473
        if ( AT.SortFloatMode == 3 ) {
×
1474
                if ( fun1[1] == fun3[1]  ) {
×
1475
Over1:
×
1476
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
×
1477
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1478
                        *s1 = t1-s1; goto Finished;
×
1479
                }
1480
                else if ( fun2[1] == fun3[1]  ) {
×
1481
Over2:
×
1482
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
×
1483
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1484
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
×
1485
                }
1486
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1487
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
×
1488
        }
1489
        else if ( AT.SortFloatMode == 1 ) {
×
1490
                if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1491
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1492
        }
1493
        else if ( AT.SortFloatMode == 2 ) {
×
1494
                if ( fun2[1] >= fun3[1]  ) goto Over2;
×
1495
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1496
        }
1497
/*
1498
        Does not fit. Go to extension space.
1499
*/
1500
        jj = fun1-s1;
×
1501
        j = jj+fun3[1]+3; /* space needed */
×
1502
        if ( (S->sFill + j) >= S->sTop2 ) {
×
1503
                GarbHand();
×
1504
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1505
                fun1 = s1+jj;
×
1506
        }
1507
        t1 = S->sFill;
×
1508
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
×
1509
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
×
1510
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
×
1511
        *ps1 = S->sFill;
×
1512
        **ps1 = t1-*ps1;
×
1513
        S->sFill = t1;
×
1514
Finished:
×
1515
        *ps2 = 0;
×
1516
        TermFree(fun3,"AddWithFloat");
×
1517
        AT.SortFloatMode = 0;
×
1518
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
×
1519
                MLOCK(ErrorMessageLock);
×
1520
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1521
                AM.MaxTer/sizeof(WORD));
×
1522
                MUNLOCK(ErrorMessageLock);
×
1523
                Terminate(-1);
×
1524
        }
1525
        return(1);
1526
}
1527

1528
/*
1529
                 #] AddWithFloat : 
1530
                 #[ MergeWithFloat :
1531

1532
                Note that we always park the result on top of term1.
1533
                This makes life easier, because the original AddRat in MergePatches
1534
                does this as well.
1535
*/
1536

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

1640
/*
1641
                 #] MergeWithFloat : 
1642
          #] Sorting : 
1643
          #[ MZV :
1644

1645
                The functions here allow the arbitrary precision calculation
1646
                of MZV's and Euler sums.
1647
                They are called when the functions mzv_ and/or euler_ are used
1648
                and the evaluate statement is applied.
1649
                The output is in a float_ function.
1650
                The expand statement tries to express the functions in terms of a basis.
1651
                The bases are the 'standard basis for the euler sums and the
1652
                pushdown bases from the datamine, unless otherwise specified.
1653

1654
                 #[ SimpleDelta :
1655
*/
1656

1657
void SimpleDelta(mpf_t sum, int m)
24✔
1658
{
1659
        long s = 1;
24✔
1660
        long prec = AC.DefaultPrecision;
24✔
1661
        unsigned long xprec = (unsigned long)prec, x;
24✔
1662
        int j, jmax, n;
24✔
1663
        mpf_t jm,jjm;
24✔
1664
        mpf_init(jm); mpf_init(jjm);
24✔
1665
        if ( m < 0 ) { s = -1; m = -m; }
24✔
1666

1667
/*
1668
        We will loop until 1/2^j/j^m is smaller than the default precision.
1669
        Just running to prec is however overkill, specially when m is large.
1670
        We try to estimate a better value.
1671
        jmax = prec - ((2log(prec)-1)*m).
1672
        Hence we need the leading bit of prec.
1673
        We are still overshooting a bit.
1674
*/
1675
        n = 0; x = xprec;
24✔
1676
        while ( x ) { x >>= 1; n++; }
222✔
1677
        jmax = (int)((int)xprec - n*m);
24✔
1678
        mpf_set_ui(sum,0);
24✔
1679
        for ( j = 1; j < jmax; j++ ) {
5,058✔
1680
#ifdef WITHCUTOFF
1681
                xprec--;
5,010✔
1682
                mpf_set_prec_raw(jm,xprec);
5,010✔
1683
                mpf_set_prec_raw(jjm,xprec);
5,010✔
1684
#endif
1685
                mpf_set_ui(jm,1L);
5,010✔
1686
                mpf_div_ui(jjm,jm,(unsigned long)j);
5,010✔
1687
                mpf_pow_ui(jm,jjm,(unsigned long)m);
5,010✔
1688
                mpf_div_2exp(jjm,jm,(unsigned long)j);
5,010✔
1689
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
5,010✔
1690
                else                       mpf_add(sum,sum,jjm);
5,010✔
1691
        }
1692
        mpf_clear(jjm); mpf_clear(jm);
24✔
1693
}
24✔
1694

1695
/*
1696
                 #] SimpleDelta : 
1697
                 #[ SimpleDeltaC :
1698
*/
1699

1700
void SimpleDeltaC(mpf_t sum, int m)
×
1701
{
1702
        long s = 1;
×
1703
        long prec = AC.DefaultPrecision;
×
1704
        unsigned long xprec = (unsigned long)prec, x;
×
1705
        int j, jmax, n;
×
1706
        mpf_t jm,jjm;
×
1707
        mpf_init(jm); mpf_init(jjm);
×
1708
        if ( m < 0 ) { s = -1; m = -m; }
×
1709
/*
1710
        We will loop until 1/2^j/j^m is smaller than the default precision.
1711
        Just running to prec is however overkill, specially when m is large.
1712
        We try to estimate a better value.
1713
        jmax = prec - ((2log(prec)-1)*m).
1714
        Hence we need the leading bit of prec.
1715
        We are still overshooting a bit.
1716
*/
1717
        n = 0; x = xprec;
×
1718
        while ( x ) { x >>= 1; n++; }
×
1719
        jmax = (int)((int)xprec - n*m);
×
1720
        if ( s < 0 ) jmax /= 2;
×
1721
        mpf_set_si(sum,0L);
×
1722
        for ( j = 1; j < jmax; j++ ) {
×
1723
#ifdef WITHCUTOFF
1724
                xprec--;
×
1725
                mpf_set_prec_raw(jm,xprec);
×
1726
                mpf_set_prec_raw(jjm,xprec);
×
1727
#endif
1728
                mpf_set_ui(jm,1L);
×
1729
                mpf_div_ui(jjm,jm,(unsigned long)j);
×
1730
                mpf_pow_ui(jm,jjm,(unsigned long)m);
×
1731
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
×
1732
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
1733
                mpf_add(sum,sum,jjm);
×
1734
        }
1735
        mpf_clear(jjm); mpf_clear(jm);
×
1736
}
×
1737

1738
/*
1739
                 #] SimpleDeltaC : 
1740
                 #[ SingleTable :
1741
*/
1742

1743
void SingleTable(mpf_t *tabl, int N, int m, int pow)
×
1744
{
1745
/*
1746
        Creates a table T(1,...,N) with
1747
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
1748
        To make this table we have two options:
1749
        1: run the sum backwards with the potential problem that the 
1750
           precision is difficult to manage.
1751
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
1752
        When doing Euler sums we may need also 1/4^j
1753
        pow: 1 -> 1/2^j
1754
             2 -> 1/4^j
1755
*/
1756
        GETIDENTITY
1757
        long s = 1;
×
1758
        int j;
×
1759
#ifdef WITHCUTOFF
1760
        long prec = mpf_get_default_prec();
×
1761
#endif
1762
        mpf_t jm,jjm;
×
1763
        mpf_init(jm); mpf_init(jjm);
×
1764
        if ( pow < 1 || pow > 2 ) {
×
1765
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1766
                exit(-1);
×
1767
        }
1768
        if ( m < 0 ) { m = -m; s = -1; }
×
1769
        mpf_set_si(auxsum,0L);
×
1770
        for ( j = N; j > 0; j-- ) {
×
1771
#ifdef WITHCUTOFF
1772
                mpf_set_prec_raw(jm,prec-j);
×
1773
                mpf_set_prec_raw(jjm,prec-j);
×
1774
#endif
1775
                mpf_set_ui(jm,1L);
×
1776
                mpf_div_ui(jjm,jm,(unsigned long)j);
×
1777
                mpf_pow_ui(jm,jjm,(unsigned long)m);
×
1778
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
×
1779
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
×
1780
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
×
1781
                else                       mpf_add(auxsum,auxsum,jjm);
×
1782
/*
1783
                And now copy auxsum to tablelement j
1784
*/
1785
                mpf_set(tabl[j],auxsum);
×
1786
        }
1787
        mpf_clear(jjm); mpf_clear(jm);
×
1788
}
×
1789

1790
/*
1791
                 #] SingleTable : 
1792
                 #[ DoubleTable :
1793
*/
1794

1795
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
×
1796
{
1797
        GETIDENTITY
1798
        long s = 1;
×
1799
#ifdef WITHCUTOFF
1800
        long prec = mpf_get_default_prec();
×
1801
#endif
1802
        int j;
×
1803
        mpf_t jm,jjm;
×
1804
        mpf_init(jm); mpf_init(jjm);
×
1805
        if ( pow < -1 || pow > 2 ) {
×
1806
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1807
                exit(-1);
×
1808
        }
1809
        if ( m < 0 ) { m = -m; s = -1; }
×
1810
        mpf_set_ui(auxsum,0L);
×
1811
        for ( j = N; j > 0; j-- ) {
×
1812
#ifdef WITHCUTOFF
1813
                mpf_set_prec_raw(jm,prec-j);
×
1814
                mpf_set_prec_raw(jjm,prec-j);
×
1815
#endif
1816
                mpf_set_ui(jm,1L);
×
1817
                mpf_div_ui(jjm,jm,(unsigned long)j);
×
1818
                mpf_pow_ui(jm,jjm,(unsigned long)m);
×
1819
                if ( pow == -1 ) {
×
1820
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
×
1821
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1822
                }
1823
                else if ( pow > 0 ) {
×
1824
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
×
1825
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1826
                }
1827
                else {
1828
                        mpf_mul(jm,jm,tabin[j+1]);
×
1829
                }
1830
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
×
1831
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
×
1832
                else                       mpf_add(auxsum,auxsum,jm);
×
1833
/*
1834
                And now copy auxsum to tablelement j
1835
*/
1836
                mpf_set(tabout[j],auxsum);
×
1837
        }
1838
        mpf_clear(jjm); mpf_clear(jm);
×
1839
}
×
1840

1841
/*
1842
                 #] DoubleTable : 
1843
                 #[ EndTable :
1844
*/
1845

1846
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
×
1847
{
1848
        long s = 1;
×
1849
#ifdef WITHCUTOFF
1850
        long prec = mpf_get_default_prec();
×
1851
#endif
1852
        int j;
×
1853
        mpf_t jm,jjm;
×
1854
        mpf_init(jm); mpf_init(jjm);
×
1855
        if ( pow < -1 || pow > 2 ) {
×
1856
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1857
                exit(-1);
×
1858
        }
1859
        if ( m < 0 ) { m = -m; s = -1; }
×
1860
        mpf_set_si(sum,0L);
×
1861
        for ( j = N; j > 0; j-- ) {
×
1862
#ifdef WITHCUTOFF
1863
                mpf_set_prec_raw(jm,prec-j);
×
1864
                mpf_set_prec_raw(jjm,prec-j);
×
1865
#endif
1866
                mpf_set_ui(jm,1L);
×
1867
                mpf_div_ui(jjm,jm,(unsigned long)j);
×
1868
                mpf_pow_ui(jm,jjm,(unsigned long)m);
×
1869
                if ( pow == -1 ) {
×
1870
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
×
1871
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1872
                }
1873
                else if ( pow > 0 ) {
×
1874
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
×
1875
                        mpf_mul(jm,jjm,tabin[j+1]);
×
1876
                }
1877
                else {
1878
                        mpf_mul(jm,jm,tabin[j+1]);
×
1879
                }
1880
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
×
1881
                else                       mpf_add(sum,sum,jm);
×
1882
        }
1883
        mpf_clear(jjm); mpf_clear(jm);
×
1884
}
×
1885

1886
/*
1887
                 #] EndTable : 
1888
                 #[ deltaMZV :
1889
*/
1890

1891
void deltaMZV(mpf_t result, int *indexes, int depth)
×
1892
{
1893
        GETIDENTITY
1894
/*
1895
        Because all sums go roughly like 1/2^j we need about depth steps.
1896
*/
1897
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
1898
        if ( depth == 1 ) {
×
1899
                if ( indexes[0] == 1 ) {
×
1900
                        mpf_set(result,mpfdelta1);
×
1901
                        return;
×
1902
                }
1903
                SimpleDelta(result,indexes[0]);
×
1904
        }
1905
        else if ( depth == 2 ) {
×
1906
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
×
1907
                        mpf_pow_ui(result,mpfdelta1,2);
×
1908
                        mpf_div_2exp(result,result,1);
×
1909
                }
1910
                else {
1911
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
×
1912
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
×
1913
                };
1914
        }
1915
        else if ( depth > 2 ) {
×
1916
                mpf_t *mpftab3;
1917
                int d;
1918
/*
1919
                Check first whether this is a power of delta1 = ln(2)
1920
*/
1921
                for ( d = 0; d < depth; d++ ) {
×
1922
                        if ( indexes[d] != 1 ) break;
×
1923
                }
1924
                if ( d == depth ) {        /* divide by fac_(depth) */
×
1925
                        mpf_pow_ui(result,mpfdelta1,depth);
×
1926
                        for ( d = 2; d <= depth; d++ ) {
×
1927
                                mpf_div_ui(result,result,(unsigned long)d);
×
1928
                        }
1929
                }
1930
                else {
1931
                        d = depth-1;
×
1932
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
×
1933
                        d--; indexes++;
×
1934
                        for(;;) {
×
1935
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
×
1936
                                d--; indexes++;
×
1937
                                if ( d == 0 ) {
×
1938
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
×
1939
                                        break;
×
1940
                                }
1941
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
×
1942
                                AT.mpf_tab2 = (void *)mpftab3;
×
1943
                        }
1944
                }
1945
        }
1946
        else if ( depth == 0 ) {
×
1947
                mpf_set_ui(result,1L);
×
1948
        }
1949
}
1950

1951
/*
1952
                 #] deltaMZV : 
1953
                 #[ deltaEuler :
1954

1955
                Regular Euler delta with - signs, but everywhere 1/2^j
1956
*/
1957

1958
void deltaEuler(mpf_t result, int *indexes, int depth)
×
1959
{
1960
        GETIDENTITY
1961
        int m;
×
1962
#ifdef DEBUG
1963
        int i;
1964
        printf(" deltaEuler(");
1965
        for ( i = 0; i < depth; i++ ) {
1966
                if ( i != 0 ) printf(",");
1967
                printf("%d",indexes[i]);
1968
        }
1969
        printf(") = ");
1970
#endif
1971
        if ( depth == 1 ) {
×
1972
                SimpleDelta(result,indexes[0]);
×
1973
        }
1974
        else if ( depth == 2 ) {
×
1975
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
×
1976
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
×
1977
                EndTable(result,mpftab1,AC.DefaultPrecision,m,0);
×
1978
        }
1979
        else if ( depth > 2 ) {
×
1980
                int d;
×
1981
                mpf_t *mpftab3;
×
1982
                d = depth-1;
×
1983
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
×
1984
                d--; indexes++;
×
1985
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
×
1986
                for(;;) {
×
1987
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
×
1988
                        d--; indexes++;
×
1989
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
×
1990
                        if ( d == 0 ) {
×
1991
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
×
1992
                                break;
×
1993
                        }
1994
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
×
1995
                        AT.mpf_tab2 = (void *)mpftab3;
×
1996
                }
1997
        }
1998
        else if ( depth == 0 ) {
×
1999
                mpf_set_ui(result,1L);
×
2000
        }
2001
#ifdef DEBUG
2002
        gmp_printf("%.*Fe\n",40,result);
2003
#endif
2004
}
×
2005

2006
/*
2007
                 #] deltaEuler : 
2008
                 #[ deltaEulerC :
2009

2010
                Conjugate Euler delta without - signs, but possibly 1/4^j
2011
                When there is a - in the string we have 1/4.
2012
*/
2013

2014
void deltaEulerC(mpf_t result, int *indexes, int depth)
×
2015
{
2016
        GETIDENTITY
2017
        int m;
×
2018
#ifdef DEBUG
2019
        int i;
2020
        printf(" deltaEulerC(");
2021
        for ( i = 0; i < depth; i++ ) {
2022
                if ( i != 0 ) printf(",");
2023
                printf("%d",indexes[i]);
2024
        }
2025
        printf(") = ");
2026
#endif
2027
        mpf_set_ui(result,0);
×
2028
        if ( depth == 1 ) {
×
2029
                if ( indexes[0] == 0 ) {
×
2030
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2031
                }
2032
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
×
2033
                else                  SimpleDelta(result,indexes[0]);
×
2034
        }
2035
        else if ( depth == 2 ) {
×
2036
                int par;
×
2037
                m = indexes[0];
×
2038
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth+1,-m,2);
×
2039
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth+1, m,1);
×
2040
                m = indexes[1];
×
2041
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
×
2042
                else { par = indexes[0] < 0 ? -1: 0; }
×
2043
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
×
2044
        }
2045
        else if ( depth > 2 ) {
×
2046
                int d, par;
×
2047
                mpf_t *mpftab3;
×
2048
                d = depth-1;
×
2049
                m = indexes[0];
×
2050
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
×
2051
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
×
2052
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
×
2053
                d--; indexes++; m = indexes[0];
×
2054
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
×
2055
                else { par = indexes[-1] < 0 ? -1: 0; }
×
2056
                for(;;) {
×
2057
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
×
2058
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
×
2059
                        d--; indexes++; m = indexes[0];
×
2060
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
×
2061
                        else { par = indexes[-1] < 0 ? -1: 0; }
×
2062
                        if ( d == 0 ) {
×
2063
                                mpf_set_ui(result,0);
×
2064
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
×
2065
                                break;
×
2066
                        }
2067
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
×
2068
                        AT.mpf_tab2 = (void *)mpftab3;
×
2069
                }
2070
        }
2071
        else if ( depth == 0 ) {
×
2072
                mpf_set_ui(result,1L);
×
2073
        }
2074
#ifdef DEBUG
2075
        gmp_printf("%.*Fe\n",40,result);
2076
#endif
2077
}
×
2078

2079
/*
2080
                 #] deltaEulerC : 
2081
                 #[ CalculateMZVhalf :
2082

2083
                 This routine is mainly for support when large numbers of
2084
                MZV's have to be calculated at the same time.
2085
*/
2086

2087
void CalculateMZVhalf(mpf_t result, int *indexes, int depth)
×
2088
{
2089
        int i;
×
2090
        if ( depth < 0 ) {
×
2091
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
2092
                exit(-1);
×
2093
        }
2094
        for ( i = 0; i < depth; i++ ) {
×
2095
                if ( indexes[i] <= 0 ) {
×
2096
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2097
                        exit(-1);
×
2098
                }
2099
        }
2100
        deltaMZV(result,indexes,depth);
×
2101
}
×
2102

2103
/*
2104
                 #] CalculateMZVhalf : 
2105
                 #[ CalculateMZV :
2106
*/
2107

2108
void CalculateMZV(mpf_t result, int *indexes, int depth)
×
2109
{
2110
        GETIDENTITY
2111
        int num1, num2 = 0, i, j = 0;
×
2112
        if ( depth < 0 ) {
×
2113
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
2114
                exit(-1);
×
2115
        }
2116
        if ( indexes[0] == 1 ) {
×
2117
                printf("Divergent MZV in CalculateMZV\n");
×
2118
                exit(-1);
×
2119
        }
2120
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2121
        for ( i = 0; i < depth; i++ ) {
×
2122
                if ( indexes[i] <= 0 ) {
×
2123
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
2124
                        exit(-1);
×
2125
                }
2126
                AT.indi1[i] = indexes[i];
×
2127
        }
2128
        num1 = depth; i = 0;
×
2129
        deltaMZV(result,indexes,depth);
×
2130
        for(;;) {
×
2131
                if ( AT.indi1[0] > 1 ) {
×
2132
                        AT.indi1[0] -= 1;
×
2133
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
2134
                        AT.indi2[0] = 1; num2++;
×
2135
                }
2136
                else {
2137
                        AT.indi2[0] += 1;
×
2138
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
×
2139
                        num1--;
×
2140
                        if ( num1 == 0 ) break;
×
2141
                }
2142
                deltaMZV(aux1,AT.indi1,num1);
×
2143
                deltaMZV(aux2,AT.indi2,num2);
×
2144
                mpf_mul(aux3,aux1,aux2);
×
2145
                mpf_add(result,result,aux3);
×
2146
        }
2147
        deltaMZV(aux3,AT.indi2,num2);
×
2148
        mpf_add(result,result,aux3);
×
2149
}
×
2150

2151
/*
2152
                 #] CalculateMZV : 
2153
                 #[ CalculateEuler :
2154

2155
                There is a problem of notation here.
2156
                Basically there are two notations.
2157
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2158
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2159
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2160
                   See Broadhurst,1996
2161
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2162
                                 sum_(j2,1,inf,sign_(m2)*
2163
                                 sum_(j3,1,inf,sign_(m3)
2164
                                                        /j3^abs_(m3)
2165
                                                        /(j2+j3)^abs_(m2)
2166
                                                        /(j1+j2+j3)^abs_(m1) )))
2167
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2168
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2169
                The algorithm follows 2, but the more common notation is 1.
2170
                Hence we start with a conversion.
2171
*/
2172

2173
void CalculateEuler(mpf_t result, int *Zindexes, int depth)
×
2174
{
2175
        GETIDENTITY
2176
        int s1, num1, num2, i, j;
×
2177

2178
        int *indexes = (int *)(AT.WorkPointer);
×
2179
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
×
2180
        for ( i = 0; i < depth-1; i++ ) {
×
2181
                if ( Zindexes[i] < 0 ) {
×
2182
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
×
2183
                }
2184
        }
2185

2186
        if ( depth < 0 ) {
×
2187
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
2188
                exit(-1);
×
2189
        }
2190
        if ( indexes[0] == 1 ) {
×
2191
                printf("Divergent Euler sum in CalculateEuler\n");
×
2192
                exit(-1);
×
2193
        }
2194
        for ( i = 0, j = 0; i < depth; i++ ) {
×
2195
                if ( indexes[i] == 0 ) {
×
2196
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2197
                        exit(-1);
×
2198
                }
2199
                if ( indexes[i] < 0 ) j = 1;
×
2200
                AT.indi1[i] = indexes[i];
×
2201
        }
2202
        if ( j == 0 ) {
×
2203
                CalculateMZV(result,indexes,depth);
×
2204
                return;
×
2205
        }
2206
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
×
2207
        deltaEuler(result,AT.indi1,depth);
×
2208
        s1 = 0;
×
2209
        for(;;) {
×
2210
                s1++;
×
2211
                if ( AT.indi1[0] > 1 ) {
×
2212
                        AT.indi1[0] -= 1;
×
2213
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
2214
                        AT.indi2[0] = 1; num2++;
×
2215
                }
2216
                else if ( AT.indi1[0] < -1 ) {
×
2217
                        AT.indi1[0] += 1;
×
2218
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
2219
                        AT.indi2[0] = 1; num2++;
×
2220
                }
2221
                else if ( AT.indi1[0] == -1 ) {
×
2222
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
×
2223
                        AT.indi2[0] = -1; num2++;
×
2224
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
×
2225
                        num1--;
×
2226
                }
2227
                else {
2228
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
×
2229
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
×
2230
                        num1--;
×
2231
                }
2232
                if ( num1 == 0 ) break;
×
2233
                deltaEuler(aux1,AT.indi1,num1);
×
2234
                deltaEulerC(aux2,AT.indi2,num2);
×
2235
                mpf_mul(aux3,aux1,aux2);
×
2236
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
×
2237
                else                               mpf_sub(result,result,aux3);
×
2238
        }
2239
        deltaEulerC(aux3,AT.indi2,num2);
×
2240
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
×
2241
        else                          mpf_sub(result,result,aux3);
×
2242
}
2243

2244
/*
2245
                 #] CalculateEuler : 
2246
                 #[ ExpandMZV :
2247
*/
2248

2249
int ExpandMZV(WORD *term, WORD level)
×
2250
{
2251
        DUMMYUSE(term);
×
2252
        DUMMYUSE(level);
×
2253
        return(0);
×
2254
}
2255

2256
/*
2257
                 #] ExpandMZV : 
2258
                 #[ ExpandEuler :
2259
*/
2260

2261
int ExpandEuler(WORD *term, WORD level)
×
2262
{
2263
        DUMMYUSE(term);
×
2264
        DUMMYUSE(level);
×
2265
        return(0);
×
2266
}
2267

2268
/*
2269
                 #] ExpandEuler : 
2270
                 #[ EvaluateEuler :
2271

2272
        There are various steps here:
2273
        1: locate an Euler function.
2274
        2: evaluate it into a float.
2275
        3: convert the coefficient to a float and multiply.
2276
        4: Put the new term together.
2277
        5: Restart to see whether there are more Euler functions.
2278
        The compiler should check that there is no conflict between
2279
        the evaluate command and a potential polyfun or polyratfun.
2280
        Yet, when reading in expressions there can be a conflict.
2281
        Hence the Normalize routine should check as well.
2282

2283
        par == MZV: MZV
2284
        par == EULER: Euler
2285
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2286
        par == ALLMZVFUNCTIONS: all of the above.
2287
*/
2288

2289
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
60✔
2290
{
2291
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
60✔
2292
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
60✔
2293
        int retval;
60✔
2294
        tstop = term + *term; tstop -= ABS(tstop[-1]);
60✔
2295
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
60✔
2296
/*
2297
        Step 1. We also need to verify that the argument we find is legal
2298
*/
2299
        t = term+1;
60✔
2300
        while ( t < tstop ) {
132✔
2301
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
72✔
2302
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
72✔
2303
        /* all arguments should be small integers */
2304
                        indexes = AT.WorkPointer;
×
2305
                        sumweight = 0; depth = 0;
×
2306
                        tnext = t + t[1]; tt = t + FUNHEAD;
×
2307
                        while ( tt < tnext ) {
×
2308
                                if ( *tt != -SNUMBER ) goto nextfun;
×
2309
                                if ( tt[1] == 0 ) goto nextfun;
×
2310
                                indexes[depth] = tt[1];
×
2311
                                sumweight += ABS(tt[1]); depth++;
×
2312
                                tt += 2;
×
2313
                        }
2314
                        if ( sumweight > AC.MaxWeight ) {
×
2315
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
2316
                                MesPrint("Please increase MaxWeight in form.set.");
×
2317
                                Terminate(-1);
×
2318
                        }
2319
/*
2320
                        Step 2: evaluate:
2321
*/
2322
                        AT.WorkPointer += depth;
×
2323
                        if ( first ) {
×
2324
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
×
2325
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
×
2326
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
×
2327
                                first = 0;
2328
                        }
2329
                        else {
2330
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
×
2331
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
2332
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2333
                                mpf_mul(aux4,aux4,aux5);
×
2334
                        }
2335
                        *t = 0;
×
2336
                }
2337
nextfun:
72✔
2338
                t += t[1];
72✔
2339
        }
2340
        if ( first == 1 ) return(Generator(BHEAD term,level));
60✔
2341
/*
2342
        Step 3:
2343
        Now the regular coefficient, if it is not 1/1.
2344
        We have two cases: size +- 3, or bigger.
2345
*/
2346
        nsize = term[*term-1];
×
2347
        if ( nsize < 0 ) {
×
2348
                mpf_neg(aux4,aux4);
×
2349
                nsize = -nsize;
×
2350
        }
2351
        if ( nsize == 3 ) {
×
2352
                if ( tstop[0] != 1 ) {
×
2353
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
×
2354
                }
2355
                if ( tstop[1] != 1 ) {
×
2356
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
×
2357
                }
2358
        }
2359
        else {
2360
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2361
                mpf_mul(aux4,aux4,aux5);
×
2362
        }
2363
/*
2364
        Now we have to locate possible other float_ functions.
2365
*/
2366
        t = term+1;
2367
        while ( t < tstop ) {
×
2368
                if ( *t == FLOATFUN ) {
×
2369
                        UnpackFloat(aux5,t);
×
2370
                        mpf_mul(aux4,aux4,aux5);
×
2371
                }
2372
                t += t[1];
×
2373
        }
2374
/*
2375
        Now we should compose the new term in the WorkSpace.
2376
*/
2377
        t = term+1;
×
2378
        newterm = AT.WorkPointer;
×
2379
        tt = newterm+1;
×
2380
        while ( t < tstop ) {
×
2381
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
×
2382
                else {
2383
                        i = t[1]; NCOPY(tt,t,i);
×
2384
                }
2385
        }
2386
        PackFloat(tt,aux4);
×
2387
        tt += tt[1];
×
2388
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
×
2389
        *newterm = tt-newterm;
×
2390
        AT.WorkPointer = tt;
×
2391
        retval = Generator(BHEAD newterm,level);
×
2392
        AT.WorkPointer = oldworkpointer;
×
2393
        return(retval);
×
2394
}
2395

2396
/*
2397
                 #] EvaluateEuler : 
2398
          #] MZV : 
2399
          #[ Functions :
2400
                 #[ CoEvaluate :
2401

2402
                Current subkeys: mzv_, euler_ and sqrt_.
2403
*/
2404

2405
int CoEvaluate(UBYTE *s)
24✔
2406
{
2407
        UBYTE *subkey, c;
24✔
2408
        WORD numfun, type;
24✔
2409
        int error = 0;
24✔
2410
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
24✔
2411
        if ( *s == 0 ) {
24✔
2412
/*
2413
                No subkey, which means all functions.
2414
*/
2415
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
6✔
2416
/*
2417
                The MZV, EULER and MZVHALF are done separately
2418
*/
2419
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
6✔
2420
                return(0);        
6✔
2421
        }
2422
        while ( *s ) {
18✔
2423
        subkey = s;
2424
        while ( FG.cTable[*s] == 0 ) s++;
54✔
2425
          if ( *s == '_' ) s++;
18✔
2426
          c = *s; *s++ = 0;
18✔
2427
/*
2428
                We still need provisions for pi_ and possibly other constants.
2429
*/
2430
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
18✔
2431
                        || ( functions[numfun].spec != 0 ) ) {
×
2432

2433
                if ( type == CSYMBOL ) {
18✔
2434
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
18✔
2435
                        break;
18✔
2436
                }
2437
/*
2438
                        This cannot work.
2439
*/
2440
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2441
                error = 1;
×
2442
          }
2443
          else {
2444
                switch ( numfun+FUNCTION ) {
×
2445
                        case MZV:
×
2446
                        case EULER:
2447
                        case MZVHALF:
2448
                        case SQRTFUNCTION:
2449
/*
2450
                        The following functions are treated in evaluate.c
2451

2452
                        case LNFUNCTION:
2453
                        case SINFUNCTION:
2454
                        case COSFUNCTION:
2455
                        case TANFUNCTION:
2456
                        case ASINFUNCTION:
2457
                        case ACOSFUNCTION:
2458
                        case ATANFUNCTION:
2459
                        case ATAN2FUNCTION:
2460
                        case SINHFUNCTION:
2461
                        case COSHFUNCTION:
2462
                        case TANHFUNCTION:
2463
                        case ASINHFUNCTION:
2464
                        case ACOSHFUNCTION:
2465
                        case ATANHFUNCTION:
2466
                        case LI2HFUNCTION:
2467
                        case LINHFUNCTION:
2468
                        case AGMFUNCTION:
2469
                        case GAMMAFUN:
2470

2471
                        At a later stage we can add more functions from mpfr here
2472
                                mpfr_(number,arg(s))
2473
*/
2474
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
×
2475
                                break;
×
2476
                        default:
×
2477
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2478
                                error = 1;
×
2479
                                break;
×
2480
                }
2481
          }
2482
          *s = c;
×
2483
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
×
2484
        }
2485
        return(error);
2486
}
2487

2488
/*
2489
                 #] CoEvaluate : 
2490
          #] Functions : 
2491
*/
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

© 2025 Coveralls, Inc