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

tueda / form / 18125652002

30 Sep 2025 09:38AM UTC coverage: 54.367% (+0.3%) from 54.112%
18125652002

push

github

tueda
refactor: remove workaround for FLINT >= 3.0.0 and < 3.2.0

We now require FLINT >= 3.2.0. The workaround is no longer necessary.

44447 of 81754 relevant lines covered (54.37%)

2275204.07 hits per line

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

75.81
/sources/float.c
1
/** @file float.c
2
 * 
3
 *  This file contains numerical routines that deal with floating point numbers.
4
 *        We use the GMP for arbitrary precision floating point arithmetic.
5
 *        The functions of the type sin, cos, ln, sqrt etc are handled by the
6
 *        mpfr library. The reason that for MZV's and the general notation we use
7
 *        the GMP (mpf_) is because the contents of the structs have been frozen
8
 *        and can be used for storage in a Form function float_. With mpfr_ this
9
 *        is not safely possible. All mpfr_ related code is in the file evaluate.c.
10
 */
11
/* #[ License : */
12
/*
13
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
14
 *   When using this file you are requested to refer to the publication
15
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
16
 *   This is considered a matter of courtesy as the development was paid
17
 *   for by FOM the Dutch physics granting agency and we would like to
18
 *   be able to track its scientific use to convince FOM of its value
19
 *   for the community.
20
 *
21
 *   This file is part of FORM.
22
 *
23
 *   FORM is free software: you can redistribute it and/or modify it under the
24
 *   terms of the GNU General Public License as published by the Free Software
25
 *   Foundation, either version 3 of the License, or (at your option) any later
26
 *   version.
27
 *
28
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
29
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
31
 *   details.
32
 *
33
 *   You should have received a copy of the GNU General Public License along
34
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
35
 */
36
/* #] License : */ 
37
/*
38
          #[ Includes : float.c
39
*/
40

41
#include "form3.h"
42
#include <math.h>
43
#include <gmp.h>
44

45
#define WITHCUTOFF
46

47
#define GMPSPREAD (GMP_LIMB_BITS/BITSINWORD)
48

49
void Form_mpf_init(mpf_t t);
50
void Form_mpf_clear(mpf_t t);
51
void Form_mpf_set_prec_raw(mpf_t t,ULONG newprec);
52
void FormtoZ(mpz_t z,UWORD *a,WORD na);
53
void ZtoForm(UWORD *a,WORD *na,mpz_t z);
54
long FloatToInteger(UWORD *out, mpf_t floatin, long *bitsused);
55
void IntegerToFloat(mpf_t result, UWORD *formlong, int longsize);
56
int FloatToRat(UWORD *ratout, WORD *nratout, mpf_t floatin);
57
int AddFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
58
int MulFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
59
int DivFloats(PHEAD WORD *fun3, WORD *fun1, WORD *fun2);
60
int AddRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
61
int MulRatToFloat(PHEAD WORD *outfun, WORD *infun, UWORD *formrat, WORD nrat);
62
void SimpleDelta(mpf_t sum, int m);
63
void SimpleDeltaC(mpf_t sum, int m);
64
void SingleTable(mpf_t *tabl, int N, int m, int pow);
65
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow);
66
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow);
67
void deltaMZV(mpf_t, int *, int);
68
void deltaEuler(mpf_t, int *, int);
69
void deltaEulerC(mpf_t, int *, int);
70
void CalculateMZVhalf(mpf_t, int *, int);
71
void CalculateMZV(mpf_t, int *, int);
72
void CalculateEuler(mpf_t, int *, int);
73
int ExpandMZV(WORD *term, WORD level);
74
int ExpandEuler(WORD *term, WORD level);
75
int PackFloat(WORD *,mpf_t);
76
int UnpackFloat(mpf_t, WORD *);
77
void RatToFloat(mpf_t result, UWORD *formrat, int ratsize);
78
 
79
/*
80
          #] Includes : 
81
          #[ Some GMP float info :
82

83
        From gmp.h:
84

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

98
        typedef __mpf_struct mpf_t[1];
99

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

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

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

121
        From mpfr.h
122

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

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

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

140
                 #[ Explanations :
141

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

687
        Form_mpf_empty(aux1);
6✔
688
        Form_mpf_empty(aux2);
6✔
689
        Form_mpf_empty(aux3);
6✔
690

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

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

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

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

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

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

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

848
UBYTE *CheckFloat(UBYTE *ss, int *spec)
2,270,438✔
849
{
850
        GETIDENTITY
1,513,628✔
851
        UBYTE *s = ss;
2,270,438✔
852
        int zero = 1, gotdot = 0;
2,270,438✔
853
        while ( FG.cTable[s[-1]] == 1 ) s--;
6,445,948✔
854
        *spec = 0;
2,270,438✔
855
        if ( FG.cTable[*s] == 1 ) {
2,270,438✔
856
                while ( *s == '0' ) s++;
2,405,006✔
857
                if ( FG.cTable[*s] == 1 ) {
2,270,426✔
858
                        s++;
2,135,924✔
859
                        while ( FG.cTable[*s] == 1 ) s++;
4,080,986✔
860
                        zero = 0;
861
                }
862
                if ( *s == '.' ) { goto dot; }
2,270,426✔
863
        }
864
        else if ( *s == '.' ) {
12✔
865
dot:
12✔
866
                gotdot = 1;
342✔
867
                s++;
342✔
868
                if ( FG.cTable[*s] != 1 && zero == 1 ) return(ss);
342✔
869
                while ( *s == '0' ) s++;
540✔
870
                if ( FG.cTable[*s] == 1 ) {
342✔
871
                        s++;
144✔
872
                        while ( FG.cTable[*s] == 1 ) s++;
432✔
873
                        zero = 0;
874
                }
875
        }
876
        else return(ss);
877
/*
878
        Now we have had the mantissa part, which may be zero.
879
        Check for an exponent.
880
*/
881
        if ( *s == 'e' || *s == 'E' ) {
2,270,438✔
882
                s++;
×
883
                if ( *s == '-' || *s == '+' ) s++;
×
884
                if ( FG.cTable[*s] == 1 ) {
×
885
                        s++;
×
886
                        while ( FG.cTable[*s] == 1 ) s++;
×
887
                }
888
                else { return(ss); }
889
        }
890
        else if ( gotdot == 0 ) return(ss);
2,270,438✔
891
        if ( AT.aux_ == 0 ) { /* no floating point system */
342✔
892
                *spec = -1;
×
893
                return(s);
×
894
        }
895
        if ( zero ) *spec = 1;
342✔
896
        return(s);
897
}
898

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

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

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

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

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

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

991
/*
992
                 #] PrintFloat : 
993
                 #[ AddFloats :
994
*/
995

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

1007
/*
1008
                 #] AddFloats : 
1009
                 #[ MulFloats :
1010
*/
1011

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

1023
/*
1024
                 #] MulFloats : 
1025
                 #[ DivFloats :
1026
*/
1027

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

1039
/*
1040
                 #] DivFloats : 
1041
                 #[ AddRatToFloat :
1042

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

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

1058
/*
1059
                 #] AddRatToFloat : 
1060
                 #[ MulRatToFloat :
1061

1062
                Note: this can be optimized, because often the rat is rather simple.
1063
*/
1064

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

1077
/*
1078
                 #] MulRatToFloat : 
1079
                 #[ SetupMZVTables :
1080
*/
1081

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

1174
/*
1175
                 #] SetupMZVTables : 
1176
                 #[ SetupMPFTables :
1177
*/
1178

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

1228
/*
1229
                 #] SetupMPFTables : 
1230
                 #[ ClearMZVTables :
1231
*/
1232

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

1305
/*
1306
                 #] ClearMZVTables : 
1307
                 #[ CoToFloat :
1308
*/
1309

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

1327
/*
1328
                 #] CoToFloat : 
1329
                 #[ CoToRat :
1330
*/
1331

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

1349
/*
1350
                 #] CoToRat : 
1351
                 #[ ToFloat :
1352

1353
                Converts the coefficient to floating point if it is still a rat.
1354
*/
1355

1356
int ToFloat(PHEAD WORD *term, WORD level)
282✔
1357
{
1358
        WORD *t, *tstop, nsize, nsign = 3;
282✔
1359
        t = term+*term;
282✔
1360
        nsize = ABS(t[-1]);
282✔
1361
        tstop = t - nsize;
282✔
1362
        if ( t[-1] < 0 ) { nsign = -nsign; }
282✔
1363
        if ( nsize == 3 && t[-2] == 1 && t[-3] == 1 ) { /* Could be float */
282✔
1364
                t = term + 1;
144✔
1365
                while ( t < tstop ) {
282✔
1366
                        if ( ( *t == FLOATFUN ) && ( t+t[1] == tstop ) ) {
138✔
1367
                                return(Generator(BHEAD term,level));
×
1368
                        }
1369
                        t += t[1];
138✔
1370
                }
1371
        }
1372
        RatToFloat(aux4,(UWORD *)tstop,nsize);
282✔
1373
        PackFloat(tstop,aux4);
282✔
1374
        tstop += tstop[1];
282✔
1375
        *tstop++ = 1; *tstop++ = 1; *tstop++ = nsign;
282✔
1376
        *term = tstop - term;
282✔
1377
        AT.WorkPointer = tstop;
282✔
1378
        return(Generator(BHEAD term,level));
282✔
1379
}
1380

1381
/*
1382
                 #] ToFloat : 
1383
                 #[ ToRat :
1384

1385
                Tries to convert the coefficient to rational if it is still a float.
1386
*/
1387

1388
int ToRat(PHEAD WORD *term, WORD level)
6✔
1389
{
1390
        WORD *tstop, *t, nsize, nsign, ncoef;
6✔
1391
/*
1392
        1: find the float which should be at the end.
1393
*/
1394
        tstop = term + *term; nsize = ABS(tstop[-1]);
6✔
1395
        nsign = tstop[-1] < 0 ? -1: 1; tstop -= nsize;
6✔
1396
        t = term+1;
6✔
1397
        while ( t < tstop ) {
6✔
1398
                if ( *t == FLOATFUN && t + t[1] == tstop && TestFloat(t) &&
6✔
1399
                nsize == 3 && tstop[0] == 1 && tstop[1] == 1 ) break;
6✔
1400
                t += t[1];
×
1401
        }
1402
        if ( t < tstop ) {
6✔
1403
/*
1404
                Now t points at the float_ function and everything is correct.
1405
                The result can go straight over the float_ function.
1406
*/
1407
                UnpackFloat(aux4,t);
6✔
1408
                if ( FloatToRat((UWORD *)t,&ncoef,aux4) == 0 ) {
6✔
1409
                        t += ABS(ncoef);
6✔
1410
                        t[-1] = ncoef*nsign;
6✔
1411
                        *term = t - term;
6✔
1412
                }
1413
        }
1414
        return(Generator(BHEAD term,level));
6✔
1415
}
1416

1417
/*
1418
                 #] ToRat : 
1419
          #] Float Routines : 
1420
          #[ Sorting :
1421

1422
                We need a method to see whether two terms need addition that could
1423
                involve floating point numbers.
1424
                1: if PolyWise is active, we do not need anything, because
1425
                   Poly(Rat)Fun and floating point are mutually exclusive.
1426
                2: This means that there should be only interference in AddCoef.
1427
                   and the AddRat parts in MergePatches, MasterMerge, SortBotMerge
1428
                   and PF_GetLoser.
1429
                The compare routine(s) should recognise the float_ and give off
1430
                a code (SortFloatMode) inside the AT struct:
1431
                0: no float_
1432
                1: float_ in term1 only
1433
                2: float_ in term2 only
1434
                3: float_ in both terms
1435
                Be careful: we have several compare routines, because various codes
1436
                use their own routines and we just set a variable with its address.
1437
                Currently we have Compare1, CompareSymbols and CompareHSymbols.
1438
                Only Compare1 should be active for this. The others should make sure
1439
                that the proper variable is always zero.
1440
                Remember: the sign of the coefficient is in the last word of the term.
1441

1442
                We need two routines:
1443
                1: AddWithFloat for SplitMerge which sorts by pointer.
1444
                2: MergeWithFloat for MergePatches etc which keeps terms as much
1445
                   as possible in their location.
1446
                The routines start out the same, because AT.SortFloatMode, set in
1447
                Compare1, tells more or less what should be done.
1448
                The difference is in where we leave the result.
1449

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

1454
                 #[ AddWithFloat :
1455
*/
1456

1457
int AddWithFloat(PHEAD WORD **ps1, WORD **ps2)
174✔
1458
{
1459
        GETBIDENTITY
1460
        SORTING *S = AT.SS;
174✔
1461
        WORD *coef1, *coef2, size1, size2, *fun1, *fun2, *fun3;
174✔
1462
        WORD *s1,*s2,sign3,j,jj, *t1, *t2, i;
174✔
1463
        s1 = *ps1;
174✔
1464
        s2 = *ps2;
174✔
1465
        coef1 = s1+*s1; size1 = coef1[-1]; coef1 -= ABS(coef1[-1]);
174✔
1466
        coef2 = s2+*s2; size2 = coef2[-1]; coef2 -= ABS(coef2[-1]);
174✔
1467
        if ( AT.SortFloatMode == 3 ) {
174✔
1468
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
198✔
1469
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
198✔
1470
                UnpackFloat(aux1,fun1);
168✔
1471
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
168✔
1472
                UnpackFloat(aux2,fun2);
168✔
1473
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
168✔
1474
        }
1475
        else if ( AT.SortFloatMode == 1 ) {
6✔
1476
                fun1 = s1+1; while ( fun1 < coef1 && fun1[0] != FLOATFUN ) fun1 += fun1[1];
×
1477
                UnpackFloat(aux1,fun1);
×
1478
                if ( size1 < 0 ) mpf_neg(aux1,aux1);
×
1479
                fun2 = coef2;
×
1480
                RatToFloat(aux2,(UWORD *)coef2,size2);
×
1481
        }
1482
        else if ( AT.SortFloatMode == 2 ) {
6✔
1483
                fun2 = s2+1; while ( fun2 < coef2 && fun2[0] != FLOATFUN ) fun2 += fun2[1];
12✔
1484
                fun1 = coef1;
6✔
1485
                RatToFloat(aux1,(UWORD *)coef1,size1);
6✔
1486
                UnpackFloat(aux2,fun2);
6✔
1487
                if ( size2 < 0 ) mpf_neg(aux2,aux2);
6✔
1488
        }
1489
        else {
1490
                MLOCK(ErrorMessageLock);
×
1491
                MesPrint("Illegal value %d for AT.SortFloatMode in AddWithFloat.",AT.SortFloatMode);
×
1492
                MUNLOCK(ErrorMessageLock);
×
1493
                Terminate(-1);
×
1494
                return(0);
×
1495
        }
1496
        mpf_add(aux3,aux1,aux2);
174✔
1497
        sign3 = mpf_sgn(aux3);
174✔
1498
        if ( sign3 == 0 ) {        /* May be rare! */
126✔
1499
                *ps1 = 0; *ps2 = 0; AT.SortFloatMode = 0; return(0);
×
1500
        }
1501
        if ( sign3 < 0 ) mpf_neg(aux3,aux3);
174✔
1502
        fun3 = TermMalloc("AddWithFloat");
174✔
1503
        PackFloat(fun3,aux3);
174✔
1504
/*
1505
        Now we have to calculate where the sumterm fits.
1506
        If we are sloppy, we can be faster, but run the risk to need the
1507
        extension space, even when it is not needed. At slightly lower speed
1508
        (ie first creating the result in scribble space) we are better off.
1509
        This is why we use TermMalloc.
1510

1511
        The new term will have a rational coefficient of 1,1,+-3.
1512
        The size will be (fun1 or fun2 - term) + fun3 +3;
1513
*/
1514
        if ( AT.SortFloatMode == 3 ) {
174✔
1515
                if ( fun1[1] == fun3[1]  ) {
168✔
1516
Over1:
42✔
1517
                        i = fun3[1]; t1 = fun1; t2 = fun3; NCOPY(t1,t2,i);
5,676✔
1518
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
126✔
1519
                        *s1 = t1-s1; goto Finished;
126✔
1520
                }
1521
                else if ( fun2[1] == fun3[1]  ) {
126✔
1522
Over2:
36✔
1523
                        i = fun3[1]; t1 = fun2; t2 = fun3; NCOPY(t1,t2,i);
2,052✔
1524
                        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
42✔
1525
                        *s2 = t1-s2; *ps1 = s2; goto Finished;
42✔
1526
                }
1527
                else if ( fun1[1] >= fun3[1]  ) goto Over1;
90✔
1528
                else if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1529
        }
1530
        else if ( AT.SortFloatMode == 1 ) {
6✔
1531
                if ( fun1[1] >= fun3[1]  ) goto Over1;
×
1532
                else if ( fun3[1]+3 <= ABS(size2) ) goto Over2;
×
1533
        }
1534
        else if ( AT.SortFloatMode == 2 ) {
6✔
1535
                if ( fun2[1] >= fun3[1]  ) goto Over2;
6✔
1536
                else if ( fun3[1]+3 <= ABS(size1) ) goto Over1;
×
1537
        }
1538
/*
1539
        Does not fit. Go to extension space.
1540
*/
1541
        jj = fun1-s1;
6✔
1542
        j = jj+fun3[1]+3; /* space needed */
6✔
1543
        if ( (S->sFill + j) >= S->sTop2 ) {
6✔
1544
                GarbHand();
×
1545
                s1 = *ps1; /* new position of the term after the garbage collection */
×
1546
                fun1 = s1+jj;
×
1547
        }
1548
        t1 = S->sFill;
6✔
1549
        for ( i = 0; i < jj; i++ ) *t1++ = s1[i];
12✔
1550
        i = fun3[1]; s1 = fun3; NCOPY(t1,s1,i);
336✔
1551
        *t1++ = 1; *t1++ = 1; *t1++ = sign3 < 0 ? -3: 3;
6✔
1552
        *ps1 = S->sFill;
6✔
1553
        **ps1 = t1-*ps1;
6✔
1554
        S->sFill = t1;
6✔
1555
Finished:
174✔
1556
        *ps2 = 0;
174✔
1557
        TermFree(fun3,"AddWithFloat");
174✔
1558
        AT.SortFloatMode = 0;
174✔
1559
        if ( **ps1 > AM.MaxTer/((LONG)(sizeof(WORD))) ) {
174✔
1560
                MLOCK(ErrorMessageLock);
×
1561
                MesPrint("Term too complex after addition in sort. MaxTermSize = %10l",
×
1562
                AM.MaxTer/sizeof(WORD));
×
1563
                MUNLOCK(ErrorMessageLock);
×
1564
                Terminate(-1);
×
1565
        }
1566
        return(1);
1567
}
1568

1569
/*
1570
                 #] AddWithFloat : 
1571
                 #[ MergeWithFloat :
1572

1573
                Note that we always park the result on top of term1.
1574
                This makes life easier, because the original AddRat in MergePatches
1575
                does this as well.
1576
*/
1577

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

1682
/*
1683
                 #] MergeWithFloat : 
1684
          #] Sorting : 
1685
          #[ MZV :
1686

1687
                The functions here allow the arbitrary precision calculation
1688
                of MZV's and Euler sums.
1689
                They are called when the functions mzv_ and/or euler_ are used
1690
                and the evaluate statement is applied.
1691
                The output is in a float_ function.
1692
                The expand statement tries to express the functions in terms of a basis.
1693
                The bases are the 'standard basis for the euler sums and the
1694
                pushdown bases from the datamine, unless otherwise specified.
1695

1696
                 #[ SimpleDelta :
1697
*/
1698

1699
void SimpleDelta(mpf_t sum, int m)
2,910✔
1700
{
1701
        long s = 1;
2,910✔
1702
        long prec = AC.DefaultPrecision;
2,910✔
1703
        unsigned long xprec = (unsigned long)prec, x;
2,910✔
1704
        int j, jmax, n;
2,910✔
1705
        mpf_t jm,jjm;
2,910✔
1706
        mpf_init(jm); mpf_init(jjm);
2,910✔
1707
        if ( m < 0 ) { s = -1; m = -m; }
2,910✔
1708

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 - ((log2(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;
2,910✔
1718
        while ( x ) { x >>= 1; n++; }
27,042✔
1719
/* 
1720
        We have now n = floor(log2(x))+1. 
1721
*/
1722
        n--;
2,910✔
1723
        jmax = (int)((int)xprec - (n-1)*m);
2,910✔
1724
        mpf_set_ui(sum,0);
2,910✔
1725
        for ( j = 1; j <= jmax; j++ ) {
792,222✔
1726
#ifdef WITHCUTOFF
1727
                xprec--;
786,402✔
1728
                mpf_set_prec_raw(jm,xprec);
786,402✔
1729
                mpf_set_prec_raw(jjm,xprec);
786,402✔
1730
#endif
1731
                mpf_set_ui(jm,1L);
786,402✔
1732
                mpf_div_ui(jjm,jm,(unsigned long)j);
786,402✔
1733
                mpf_pow_ui(jm,jjm,(unsigned long)m);
786,402✔
1734
                mpf_div_2exp(jjm,jm,(unsigned long)j);
786,402✔
1735
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jjm);
786,402✔
1736
                else                       mpf_add(sum,sum,jjm);
777,798✔
1737
        }
1738
        mpf_clear(jjm); mpf_clear(jm);
2,910✔
1739
}
2,910✔
1740

1741
/*
1742
                 #] SimpleDelta : 
1743
                 #[ SimpleDeltaC :
1744
*/
1745

1746
void SimpleDeltaC(mpf_t sum, int m)
240✔
1747
{
1748
        long s = 1;
240✔
1749
        long prec = AC.DefaultPrecision;
240✔
1750
        unsigned long xprec = (unsigned long)prec, x;
240✔
1751
        int j, jmax, n;
240✔
1752
        mpf_t jm,jjm;
240✔
1753
        mpf_init(jm); mpf_init(jjm);
240✔
1754
        if ( m < 0 ) { s = -1; m = -m; }
240✔
1755
/*
1756
        We will loop until 1/2^j/j^m is smaller than the default precision.
1757
        Just running to prec is however overkill, specially when m is large.
1758
        We try to estimate a better value.
1759
        jmax = prec - ((log2(prec)-1)*m).
1760
        Hence we need the leading bit of prec.
1761
        We are still overshooting a bit.
1762
*/
1763
        n = 0; x = xprec;
240✔
1764
        while ( x ) { x >>= 1; n++; }
1,920✔
1765
/* 
1766
        We have now n = floor(log2(x))+1. 
1767
*/
1768
        n--;
240✔
1769
        jmax = (int)((int)xprec - (n-1)*m);
240✔
1770
        if ( s < 0 ) jmax /= 2;
240✔
1771
        mpf_set_si(sum,0L);
240✔
1772
        for ( j = 1; j <= jmax; j++ ) {
8,988✔
1773
#ifdef WITHCUTOFF
1774
                xprec--;
8,508✔
1775
                mpf_set_prec_raw(jm,xprec);
8,508✔
1776
                mpf_set_prec_raw(jjm,xprec);
8,508✔
1777
#endif
1778
                mpf_set_ui(jm,1L);
8,508✔
1779
                mpf_div_ui(jjm,jm,(unsigned long)j);
8,508✔
1780
                mpf_pow_ui(jm,jjm,(unsigned long)m);
8,508✔
1781
                if ( s == -1 ) mpf_div_2exp(jjm,jm,2*(unsigned long)j);
8,508✔
1782
                else           mpf_div_2exp(jjm,jm,(unsigned long)j);
×
1783
                mpf_add(sum,sum,jjm);
8,508✔
1784
        }
1785
        mpf_clear(jjm); mpf_clear(jm);
240✔
1786
}
240✔
1787

1788
/*
1789
                 #] SimpleDeltaC : 
1790
                 #[ SingleTable :
1791
*/
1792

1793
void SingleTable(mpf_t *tabl, int N, int m, int pow)
3,606✔
1794
{
1795
/*
1796
        Creates a table T(1,...,N) with
1797
                T(i) = sum_(j,i,N,[sign_(j)]/2^j/j^m)
1798
        To make this table we have two options:
1799
        1: run the sum backwards with the potential problem that the 
1800
           precision is difficult to manage.
1801
        2: run the sum forwards. Take sum_(j,1,i-1,...) and later subtract.
1802
        When doing Euler sums we may need also 1/4^j
1803
        pow: 1 -> 1/2^j
1804
             2 -> 1/4^j
1805
*/
1806
        GETIDENTITY
2,404✔
1807
        long s = 1;
3,606✔
1808
        int j;
3,606✔
1809
#ifdef WITHCUTOFF
1810
        long prec = mpf_get_default_prec();
3,606✔
1811
#endif
1812
        mpf_t jm,jjm;
3,606✔
1813
        mpf_init(jm); mpf_init(jjm);
3,606✔
1814
        if ( pow < 1 || pow > 2 ) {
3,606✔
1815
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1816
                exit(-1);
×
1817
        }
1818
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
1819
        mpf_set_si(auxsum,0L);
3,606✔
1820
        for ( j = N; j > 0; j-- ) {
779,850✔
1821
#ifdef WITHCUTOFF
1822
                mpf_set_prec_raw(jm,prec-j);
772,638✔
1823
                mpf_set_prec_raw(jjm,prec-j);
772,638✔
1824
#endif
1825
                mpf_set_ui(jm,1L);
772,638✔
1826
                mpf_div_ui(jjm,jm,(unsigned long)j);
772,638✔
1827
                mpf_pow_ui(jm,jjm,(unsigned long)m);
772,638✔
1828
                mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
772,638✔
1829
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jjm);
772,638✔
1830
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jjm);
740,982✔
1831
                else                       mpf_add(auxsum,auxsum,jjm);
725,286✔
1832
/*
1833
                And now copy auxsum to tablelement j
1834
*/
1835
                mpf_set(tabl[j],auxsum);
772,638✔
1836
        }
1837
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
1838
}
3,606✔
1839

1840
/*
1841
                 #] SingleTable : 
1842
                 #[ DoubleTable :
1843
*/
1844

1845
void DoubleTable(mpf_t *tabout, mpf_t *tabin, int N, int m, int pow)
4,674✔
1846
{
1847
        GETIDENTITY
3,116✔
1848
        long s = 1;
4,674✔
1849
#ifdef WITHCUTOFF
1850
        long prec = mpf_get_default_prec();
4,674✔
1851
#endif
1852
        int j;
4,674✔
1853
        mpf_t jm,jjm;
4,674✔
1854
        mpf_init(jm); mpf_init(jjm);
4,674✔
1855
        if ( pow < -1 || pow > 2 ) {
4,674✔
1856
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1857
                exit(-1);
×
1858
        }
1859
        if ( m < 0 ) { m = -m; s = -1; }
4,674✔
1860
        mpf_set_ui(auxsum,0L);
4,674✔
1861
        for ( j = N; j > 0; j-- ) {
1,709,796✔
1862
#ifdef WITHCUTOFF
1863
                mpf_set_prec_raw(jm,prec-j);
1,700,448✔
1864
                mpf_set_prec_raw(jjm,prec-j);
1,700,448✔
1865
#endif
1866
                mpf_set_ui(jm,1L);
1,700,448✔
1867
                mpf_div_ui(jjm,jm,(unsigned long)j);
1,700,448✔
1868
                mpf_pow_ui(jm,jjm,(unsigned long)m);
1,700,448✔
1869
                if ( pow == -1 ) {
1,700,448✔
1870
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
8,232✔
1871
                        mpf_mul(jm,jjm,tabin[j+1]);
8,232✔
1872
                }
1873
                else if ( pow > 0 ) {
1,692,216✔
1874
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
3,648✔
1875
                        mpf_mul(jm,jjm,tabin[j+1]);
3,648✔
1876
                }
1877
                else {
1878
                        mpf_mul(jm,jm,tabin[j+1]);
1,688,568✔
1879
                }
1880
                if ( pow == 2 ) mpf_add(auxsum,auxsum,jm);
1,700,448✔
1881
                else if ( s == -1 && j%2 == 1 ) mpf_sub(auxsum,auxsum,jm);
1,700,448✔
1882
                else                       mpf_add(auxsum,auxsum,jm);
1,694,496✔
1883
/*
1884
                And now copy auxsum to tablelement j
1885
*/
1886
                mpf_set(tabout[j],auxsum);
1,700,448✔
1887
        }
1888
        mpf_clear(jjm); mpf_clear(jm);
4,674✔
1889
}
4,674✔
1890

1891
/*
1892
                 #] DoubleTable : 
1893
                 #[ EndTable :
1894
*/
1895

1896
void EndTable(mpf_t sum, mpf_t *tabin, int N, int m, int pow)
3,606✔
1897
{
1898
        long s = 1;
3,606✔
1899
#ifdef WITHCUTOFF
1900
        long prec = mpf_get_default_prec();
3,606✔
1901
#endif
1902
        int j;
3,606✔
1903
        mpf_t jm,jjm;
3,606✔
1904
        mpf_init(jm); mpf_init(jjm);
3,606✔
1905
        if ( pow < -1 || pow > 2 ) {
3,606✔
1906
                printf("Wrong parameter pow in SingleTable: %d\n",pow);
×
1907
                exit(-1);
×
1908
        }
1909
        if ( m < 0 ) { m = -m; s = -1; }
3,606✔
1910
        mpf_set_si(sum,0L);
3,606✔
1911
        for ( j = N; j > 0; j-- ) {
770,970✔
1912
#ifdef WITHCUTOFF
1913
                mpf_set_prec_raw(jm,prec-j);
763,758✔
1914
                mpf_set_prec_raw(jjm,prec-j);
763,758✔
1915
#endif
1916
                mpf_set_ui(jm,1L);
763,758✔
1917
                mpf_div_ui(jjm,jm,(unsigned long)j);
763,758✔
1918
                mpf_pow_ui(jm,jjm,(unsigned long)m);
763,758✔
1919
                if ( pow == -1 ) {
763,758✔
1920
                        mpf_mul_2exp(jjm,jm,(unsigned long)j);
13,050✔
1921
                        mpf_mul(jm,jjm,tabin[j+1]);
13,050✔
1922
                }
1923
                else if ( pow > 0 ) {
750,708✔
1924
                        mpf_div_2exp(jjm,jm,pow*(unsigned long)j);
11,700✔
1925
                        mpf_mul(jm,jjm,tabin[j+1]);
11,700✔
1926
                }
1927
                else {
1928
                        mpf_mul(jm,jm,tabin[j+1]);
739,008✔
1929
                }
1930
                if ( s == -1 && j%2 == 1 ) mpf_sub(sum,sum,jm);
763,758✔
1931
                else                       mpf_add(sum,sum,jm);
751,218✔
1932
        }
1933
        mpf_clear(jjm); mpf_clear(jm);
3,606✔
1934
}
3,606✔
1935

1936
/*
1937
                 #] EndTable : 
1938
                 #[ deltaMZV :
1939
*/
1940

1941
void deltaMZV(mpf_t result, int *indexes, int depth)
7,566✔
1942
{
1943
        GETIDENTITY
5,044✔
1944
/*
1945
        Because all sums go roughly like 1/2^j we need about depth steps.
1946
*/
1947
/*        MesPrint("deltaMZV(%a)",depth,indexes); */
1948
        if ( depth == 1 ) {
7,566✔
1949
                if ( indexes[0] == 1 ) {
3,804✔
1950
                        mpf_set(result,mpfdelta1);
1,650✔
1951
                        return;
1,650✔
1952
                }
1953
                SimpleDelta(result,indexes[0]);
2,154✔
1954
        }
1955
        else if ( depth == 2 ) {
3,762✔
1956
                if ( indexes[0] == 1 && indexes[1] == 1 ) {
1,470✔
1957
                        mpf_pow_ui(result,mpfdelta1,2);
486✔
1958
                        mpf_div_2exp(result,result,1);
486✔
1959
                }
1960
                else {
1961
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
984✔
1962
                        EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,indexes[1],0);
984✔
1963
                };
1964
        }
1965
        else if ( depth > 2 ) {
2,292✔
1966
                mpf_t *mpftab3;
1967
                int d;
1968
/*
1969
                Check first whether this is a power of delta1 = ln(2)
1970
*/
1971
                for ( d = 0; d < depth; d++ ) {
7,548✔
1972
                        if ( indexes[d] != 1 ) break;
6,678✔
1973
                }
1974
                if ( d == depth ) {        /* divide by fac_(depth) */
2,292✔
1975
                        mpf_pow_ui(result,mpfdelta1,depth);
870✔
1976
                        for ( d = 2; d <= depth; d++ ) {
5,196✔
1977
                                mpf_div_ui(result,result,(unsigned long)d);
3,456✔
1978
                        }
1979
                }
1980
                else {
1981
                        d = depth-1;
1,422✔
1982
                        SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
1,422✔
1983
                        d--; indexes++;
1,422✔
1984
                        for(;;) {
6,726✔
1985
                                DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,0);
4,074✔
1986
                                d--; indexes++;
4,074✔
1987
                                if ( d == 0 ) {
4,074✔
1988
                                        EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,*indexes,0);
1,422✔
1989
                                        break;
1,422✔
1990
                                }
1991
                                mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
2,652✔
1992
                                AT.mpf_tab2 = (void *)mpftab3;
2,652✔
1993
                        }
1994
                }
1995
        }
1996
        else if ( depth == 0 ) {
×
1997
                mpf_set_ui(result,1L);
×
1998
        }
1999
}
2000

2001
/*
2002
                 #] deltaMZV : 
2003
                 #[ deltaEuler :
2004

2005
                Regular Euler delta with - signs, but everywhere 1/2^j
2006
*/
2007

2008
void deltaEuler(mpf_t result, int *indexes, int depth)
990✔
2009
{
2010
        GETIDENTITY
660✔
2011
        int m;
990✔
2012
#ifdef DEBUG
2013
        int i;
2014
        printf(" deltaEuler(");
2015
        for ( i = 0; i < depth; i++ ) {
2016
                if ( i != 0 ) printf(",");
2017
                printf("%d",indexes[i]);
2018
        }
2019
        printf(") = ");
2020
#endif
2021
        if ( depth == 1 ) {
990✔
2022
                SimpleDelta(result,indexes[0]);
390✔
2023
        }
2024
        else if ( depth == 2 ) {
600✔
2025
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+1,indexes[0],1);
348✔
2026
                m = indexes[1]; if ( indexes[0] < 0 ) m = -m;
348✔
2027
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,0);
348✔
2028
        }
2029
        else if ( depth > 2 ) {
252✔
2030
                int d;
252✔
2031
                mpf_t *mpftab3;
252✔
2032
                d = depth-1;
252✔
2033
                SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,*indexes,1);
252✔
2034
                d--; indexes++;
252✔
2035
                m = *indexes; if ( indexes[-1] < 0 ) m = -m;
252✔
2036
                for(;;) {
348✔
2037
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,0);
300✔
2038
                        d--; indexes++;
300✔
2039
                        m = *indexes; if ( indexes[-1] < 0 ) m = -m;
300✔
2040
                        if ( d == 0 ) {
300✔
2041
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,0);
252✔
2042
                                break;
252✔
2043
                        }
2044
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2045
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2046
                }
2047
        }
2048
        else if ( depth == 0 ) {
×
2049
                mpf_set_ui(result,1L);
×
2050
        }
2051
#ifdef DEBUG
2052
        gmp_printf("%.*Fe\n",40,result);
2053
#endif
2054
}
990✔
2055

2056
/*
2057
                 #] deltaEuler : 
2058
                 #[ deltaEulerC :
2059

2060
                Conjugate Euler delta without - signs, but possibly 1/4^j
2061
                When there is a - in the string we have 1/4.
2062
*/
2063

2064
void deltaEulerC(mpf_t result, int *indexes, int depth)
990✔
2065
{
2066
        GETIDENTITY
660✔
2067
        int m;
990✔
2068
#ifdef DEBUG
2069
        int i;
2070
        printf(" deltaEulerC(");
2071
        for ( i = 0; i < depth; i++ ) {
2072
                if ( i != 0 ) printf(",");
2073
                printf("%d",indexes[i]);
2074
        }
2075
        printf(") = ");
2076
#endif
2077
        mpf_set_ui(result,0);
990✔
2078
        if ( depth == 1 ) {
990✔
2079
                if ( indexes[0] == 0 ) {
390✔
2080
                        printf("Illegal index in depth=1 deltaEulerC: %d\n",indexes[0]);
×
2081
                }
2082
                if ( indexes[0] < 0 ) SimpleDeltaC(result,indexes[0]);
390✔
2083
                else                  SimpleDelta(result,indexes[0]);
150✔
2084
        }
2085
        else if ( depth == 2 ) {
600✔
2086
                int par;
348✔
2087
                m = indexes[0];
348✔
2088
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth,-m,2);
348✔
2089
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+depth, m,1);
132✔
2090
                m = indexes[1];
348✔
2091
                if ( m < 0 ) { m = -m; par = indexes[0] < 0 ? 0: 1; }
348✔
2092
                else { par = indexes[0] < 0 ? -1: 0; }
150✔
2093
                EndTable(result,mpftab1,AC.DefaultPrecision-AC.MaxWeight,m,par);
348✔
2094
        }
2095
        else if ( depth > 2 ) {
252✔
2096
                int d, par;
252✔
2097
                mpf_t *mpftab3;
252✔
2098
                d = depth-1;
252✔
2099
                m = indexes[0];
252✔
2100
        ZeroTable(mpftab1,AC.DefaultPrecision+1);
252✔
2101
                if ( m < 0 ) SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1,-m,2);
252✔
2102
                else         SingleTable(mpftab1,AC.DefaultPrecision-AC.MaxWeight+d+1, m,1);
60✔
2103
                d--; indexes++; m = indexes[0];
252✔
2104
                if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
252✔
2105
                else { par = indexes[-1] < 0 ? -1: 0; }
120✔
2106
                for(;;) {
348✔
2107
                ZeroTable(mpftab2,AC.DefaultPrecision-AC.MaxWeight+d);
300✔
2108
                        DoubleTable(mpftab2,mpftab1,AC.DefaultPrecision-AC.MaxWeight+d,m,par);
300✔
2109
                        d--; indexes++; m = indexes[0];
300✔
2110
                        if ( m < 0 ) { m = -m; par = indexes[-1] < 0 ? 0: 1; }
300✔
2111
                        else { par = indexes[-1] < 0 ? -1: 0; }
144✔
2112
                        if ( d == 0 ) {
300✔
2113
                                mpf_set_ui(result,0);
252✔
2114
                                EndTable(result,mpftab2,AC.DefaultPrecision-AC.MaxWeight,m,par);
252✔
2115
                                break;
252✔
2116
                        }
2117
                        mpftab3 = (mpf_t *)AT.mpf_tab1; AT.mpf_tab1 = AT.mpf_tab2;
48✔
2118
                        AT.mpf_tab2 = (void *)mpftab3;
48✔
2119
                }
2120
        }
2121
        else if ( depth == 0 ) {
×
2122
                mpf_set_ui(result,1L);
×
2123
        }
2124
#ifdef DEBUG
2125
        gmp_printf("%.*Fe\n",40,result);
2126
#endif
2127
}
990✔
2128

2129
/*
2130
                 #] deltaEulerC : 
2131
                 #[ CalculateMZVhalf :
2132

2133
                 This routine is mainly for support when large numbers of
2134
                MZV's have to be calculated at the same time.
2135
*/
2136

2137
void CalculateMZVhalf(mpf_t result, int *indexes, int depth)
378✔
2138
{
2139
        int i;
378✔
2140
        if ( depth < 0 ) {
378✔
2141
                printf("Illegal depth in CalculateMZVhalf: %d\n",depth);
×
2142
                exit(-1);
×
2143
        }
2144
        for ( i = 0; i < depth; i++ ) {
1,530✔
2145
                if ( indexes[i] <= 0 ) {
1,152✔
2146
                        printf("Illegal index[%d] in CalculateMZVhalf: %d\n",i,indexes[i]);
×
2147
                        exit(-1);
×
2148
                }
2149
        }
2150
        deltaMZV(result,indexes,depth);
378✔
2151
}
378✔
2152

2153
/*
2154
                 #] CalculateMZVhalf : 
2155
                 #[ CalculateMZV :
2156
*/
2157

2158
void CalculateMZV(mpf_t result, int *indexes, int depth)
822✔
2159
{
2160
        GETIDENTITY
548✔
2161
        int num1, num2 = 0, i, j = 0;
822✔
2162
        if ( depth < 0 ) {
822✔
2163
                printf("Illegal depth in CalculateMZV: %d\n",depth);
×
2164
                exit(-1);
×
2165
        }
2166
        if ( indexes[0] == 1 ) {
822✔
2167
                printf("Divergent MZV in CalculateMZV\n");
×
2168
                exit(-1);
×
2169
        }
2170
/*        MesPrint("calculateMZV(%a)",depth,indexes); */
2171
        for ( i = 0; i < depth; i++ ) {
2,076✔
2172
                if ( indexes[i] <= 0 ) {
1,254✔
2173
                        printf("Illegal index[%d] in CalculateMZV: %d\n",i,indexes[i]);
×
2174
                        exit(-1);
×
2175
                }
2176
                AT.indi1[i] = indexes[i];
1,254✔
2177
        }
2178
        num1 = depth; i = 0;
822✔
2179
        deltaMZV(result,indexes,depth);
822✔
2180
        for(;;) {
6,366✔
2181
                if ( AT.indi1[0] > 1 ) {
3,594✔
2182
                        AT.indi1[0] -= 1;
2,340✔
2183
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
7,794✔
2184
                        AT.indi2[0] = 1; num2++;
2,340✔
2185
                }
2186
                else {
2187
                        AT.indi2[0] += 1;
1,254✔
2188
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,926✔
2189
                        num1--;
1,254✔
2190
                        if ( num1 == 0 ) break;
1,254✔
2191
                }
2192
                deltaMZV(aux1,AT.indi1,num1);
2,772✔
2193
                deltaMZV(aux2,AT.indi2,num2);
2,772✔
2194
                mpf_mul(aux3,aux1,aux2);
2,772✔
2195
                mpf_add(result,result,aux3);
2,772✔
2196
        }
2197
        deltaMZV(aux3,AT.indi2,num2);
822✔
2198
        mpf_add(result,result,aux3);
822✔
2199
}
822✔
2200

2201
/*
2202
                 #] CalculateMZV : 
2203
                 #[ CalculateEuler :
2204

2205
                There is a problem of notation here.
2206
                Basically there are two notations.
2207
                1: Z(m1,m2,m3) = sum_(j3,1,inf,sign_(m3)/j3^abs_(m3)*
2208
                                 sum_(j2,j3+1,inf,sign_(m2)/j2^abs_(m2)*
2209
                                 sum_(j1,j2+1,inf,sign_(m1)/j1^abs_(m1))))
2210
                   See Broadhurst,1996
2211
                2: L(m1,m2,m3) = sum_(j1,1,inf,sign_(m1)*
2212
                                 sum_(j2,1,inf,sign_(m2)*
2213
                                 sum_(j3,1,inf,sign_(m3)
2214
                                                        /j3^abs_(m3)
2215
                                                        /(j2+j3)^abs_(m2)
2216
                                                        /(j1+j2+j3)^abs_(m1) )))
2217
                   See Borwein, Bradley, Broadhurst and Lisonek, 1999
2218
                The L corresponds with the H of the datamine up to sign_(m1*m2*m3)
2219
                The algorithm follows 2, but the more common notation is 1.
2220
                Hence we start with a conversion.
2221
*/
2222

2223
void CalculateEuler(mpf_t result, int *Zindexes, int depth)
318✔
2224
{
2225
        GETIDENTITY
212✔
2226
        int s1, num1, num2, i, j;
318✔
2227

2228
        int *indexes = (int *)(AT.WorkPointer);
318✔
2229
        for ( i = 0; i < depth; i++ ) indexes[i] = Zindexes[i];
1,128✔
2230
        for ( i = 0; i < depth-1; i++ ) {
810✔
2231
                if ( Zindexes[i] < 0 ) {
492✔
2232
                        for ( j = i+1; j < depth; j++ ) indexes[j] = -indexes[j];
864✔
2233
                }
2234
        }
2235

2236
        if ( depth < 0 ) {
318✔
2237
                printf("Illegal depth in CalculateEuler: %d\n",depth);
×
2238
                exit(-1);
×
2239
        }
2240
        if ( indexes[0] == 1 ) {
318✔
2241
                printf("Divergent Euler sum in CalculateEuler\n");
×
2242
                exit(-1);
×
2243
        }
2244
        for ( i = 0, j = 0; i < depth; i++ ) {
1,128✔
2245
                if ( indexes[i] == 0 ) {
810✔
2246
                        printf("Illegal index[%d] in CalculateEuler: %d\n",i,indexes[i]);
×
2247
                        exit(-1);
×
2248
                }
2249
                if ( indexes[i] < 0 ) j = 1;
810✔
2250
                AT.indi1[i] = indexes[i];
810✔
2251
        }
2252
        if ( j == 0 ) {
318✔
2253
                CalculateMZV(result,indexes,depth);
42✔
2254
                return;
42✔
2255
        }
2256
        num1 = depth; AT.indi2[0] = 0; num2 = 0;
276✔
2257
        deltaEuler(result,AT.indi1,depth);
276✔
2258
        s1 = 0;
276✔
2259
        for(;;) {
990✔
2260
                s1++;
990✔
2261
                if ( AT.indi1[0] > 1 ) {
990✔
2262
                        AT.indi1[0] -= 1;
90✔
2263
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
162✔
2264
                        AT.indi2[0] = 1; num2++;
90✔
2265
                }
2266
                else if ( AT.indi1[0] < -1 ) {
900✔
2267
                        AT.indi1[0] += 1;
162✔
2268
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
270✔
2269
                        AT.indi2[0] = 1; num2++;
162✔
2270
                }
2271
                else if ( AT.indi1[0] == -1 ) {
738✔
2272
                        for ( j = num2; j > 0; j-- ) AT.indi2[j] = AT.indi2[j-1];
1,026✔
2273
                        AT.indi2[0] = -1; num2++;
486✔
2274
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
1,026✔
2275
                        num1--;
486✔
2276
                }
2277
                else {
2278
                        AT.indi2[0] = AT.indi2[0] < 0 ? AT.indi2[0]-1: AT.indi2[0]+1;
252✔
2279
                        for ( j = 1; j < num1; j++ ) AT.indi1[j-1] = AT.indi1[j];
432✔
2280
                        num1--;
252✔
2281
                }
2282
                if ( num1 == 0 ) break;
990✔
2283
                deltaEuler(aux1,AT.indi1,num1);
714✔
2284
                deltaEulerC(aux2,AT.indi2,num2);
714✔
2285
                mpf_mul(aux3,aux1,aux2);
714✔
2286
                if ( (depth+num1+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
714✔
2287
                else                               mpf_sub(result,result,aux3);
408✔
2288
        }
2289
        deltaEulerC(aux3,AT.indi2,num2);
276✔
2290
        if ( (depth+num2+s1)%2 == 0 ) mpf_add(result,result,aux3);
276✔
2291
        else                          mpf_sub(result,result,aux3);
162✔
2292
}
2293

2294
/*
2295
                 #] CalculateEuler : 
2296
                 #[ ExpandMZV :
2297
*/
2298

2299
int ExpandMZV(WORD *term, WORD level)
×
2300
{
2301
        DUMMYUSE(term);
×
2302
        DUMMYUSE(level);
×
2303
        return(0);
×
2304
}
2305

2306
/*
2307
                 #] ExpandMZV : 
2308
                 #[ ExpandEuler :
2309
*/
2310

2311
int ExpandEuler(WORD *term, WORD level)
×
2312
{
2313
        DUMMYUSE(term);
×
2314
        DUMMYUSE(level);
×
2315
        return(0);
×
2316
}
2317

2318
/*
2319
                 #] ExpandEuler : 
2320
                 #[ EvaluateEuler :
2321

2322
        There are various steps here:
2323
        1: locate an Euler function.
2324
        2: evaluate it into a float.
2325
        3: convert the coefficient to a float and multiply.
2326
        4: Put the new term together.
2327
        5: Restart to see whether there are more Euler functions.
2328
        The compiler should check that there is no conflict between
2329
        the evaluate command and a potential polyfun or polyratfun.
2330
        Yet, when reading in expressions there can be a conflict.
2331
        Hence the Normalize routine should check as well.
2332

2333
        par == MZV: MZV
2334
        par == EULER: Euler
2335
        par == MZVHALF: MZV sums in 1/2 rather than 1. -> deltaMZV.
2336
        par == ALLMZVFUNCTIONS: all of the above.
2337
*/
2338

2339
int EvaluateEuler(PHEAD WORD *term, WORD level, WORD par)
1,296✔
2340
{
2341
        WORD *t, *tstop, *tt, *tnext, sumweight, depth, first = 1, *newterm, i;
1,296✔
2342
        WORD *oldworkpointer = AT.WorkPointer, nsize, *indexes;
1,296✔
2343
        int retval;
1,296✔
2344
        tstop = term + *term; tstop -= ABS(tstop[-1]);
1,296✔
2345
        if ( AT.WorkPointer < term+*term ) AT.WorkPointer = term + *term;
1,296✔
2346
/*
2347
        Step 1. We also need to verify that the argument we find is legal
2348
*/
2349
        t = term+1;
1,296✔
2350
        while ( t < tstop ) {
3,810✔
2351
                if ( ( *t == par ) || ( ( par == ALLMZVFUNCTIONS ) && (
2,514✔
2352
                        *t == MZV || *t == EULER || *t == MZVHALF ) ) ) {
156✔
2353
        /* all arguments should be small integers */
2354
                        indexes = AT.WorkPointer;
1,494✔
2355
                        sumweight = 0; depth = 0;
1,494✔
2356
                        tnext = t + t[1]; tt = t + FUNHEAD;
1,494✔
2357
                        while ( tt < tnext ) {
4,638✔
2358
                                if ( *tt != -SNUMBER ) goto nextfun;
3,144✔
2359
                                if ( tt[1] == 0 ) goto nextfun;
3,144✔
2360
                                indexes[depth] = tt[1];
3,144✔
2361
                                sumweight += ABS(tt[1]); depth++;
3,144✔
2362
                                tt += 2;
3,144✔
2363
                        }
2364
                        /* euler sum without arguments, i.e. mzv_(), euler_() or mzvhalf_() */
2365
                        if ( depth == 0) goto nextfun;
1,494✔
2366
                        if ( sumweight > AC.MaxWeight ) {
1,476✔
2367
                                MesPrint("Error: Weight of Euler/MZV sum greater than %d",sumweight);
×
2368
                                MesPrint("Please increase MaxWeight in form.set.");
×
2369
                                Terminate(-1);
×
2370
                        }
2371
/*
2372
                        Step 2: evaluate:
2373
*/
2374
                        AT.WorkPointer += depth;
1,476✔
2375
                        if ( first ) {
1,476✔
2376
                                if ( *t == MZV ) CalculateMZV(aux4,indexes,depth);
1,152✔
2377
                                else if ( *t == EULER ) CalculateEuler(aux4,indexes,depth);
696✔
2378
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux4,indexes,depth);
378✔
2379
                                first = 0;
2380
                        }
2381
                        else {
2382
                                if ( *t == MZV ) CalculateMZV(aux5,indexes,depth);
324✔
2383
                                else if ( *t == EULER ) CalculateEuler(aux5,indexes,depth);
×
2384
                                else if ( *t == MZVHALF ) CalculateMZVhalf(aux5,indexes,depth);
×
2385
                                mpf_mul(aux4,aux4,aux5);
324✔
2386
                        }
2387
                        *t = 0;
1,476✔
2388
                }
2389
nextfun:
1,020✔
2390
                t += t[1];
2,514✔
2391
        }
2392
        if ( first == 1 ) return(Generator(BHEAD term,level));
1,296✔
2393
/*
2394
        Step 3:
2395
        Now the regular coefficient, if it is not 1/1.
2396
        We have two cases: size +- 3, or bigger.
2397
*/
2398
        nsize = term[*term-1];
1,152✔
2399
        if ( nsize < 0 ) {
1,152✔
2400
                mpf_neg(aux4,aux4);
72✔
2401
                nsize = -nsize;
72✔
2402
        }
2403
        if ( nsize == 3 ) {
1,152✔
2404
                if ( tstop[0] != 1 ) {
1,152✔
2405
                        mpf_mul_ui(aux4,aux4,(ULONG)((UWORD)tstop[0]));
132✔
2406
                }
2407
                if ( tstop[1] != 1 ) {
1,152✔
2408
                        mpf_div_ui(aux4,aux4,(ULONG)((UWORD)tstop[1]));
132✔
2409
                }
2410
        }
2411
        else {
2412
                RatToFloat(aux5,(UWORD *)tstop,nsize);
×
2413
                mpf_mul(aux4,aux4,aux5);
×
2414
        }
2415
/*
2416
        Now we have to locate possible other float_ functions.
2417
*/
2418
        t = term+1;
2419
        while ( t < tstop ) {
3,510✔
2420
                if ( *t == FLOATFUN ) {
2,358✔
2421
                        UnpackFloat(aux5,t);
×
2422
                        mpf_mul(aux4,aux4,aux5);
×
2423
                }
2424
                t += t[1];
2,358✔
2425
        }
2426
/*
2427
        Now we should compose the new term in the WorkSpace.
2428
*/
2429
        t = term+1;
1,152✔
2430
        newterm = AT.WorkPointer;
1,152✔
2431
        tt = newterm+1;
1,152✔
2432
        while ( t < tstop ) {
1,152✔
2433
                if ( *t == 0 || *t == FLOATFUN ) t += t[1];
2,358✔
2434
                else {
2435
                        i = t[1]; NCOPY(tt,t,i);
11,922✔
2436
                }
2437
        }
2438
        PackFloat(tt,aux4);
1,152✔
2439
        tt += tt[1];
1,152✔
2440
        *tt++ = 1; *tt++ = 1; *tt++ = 3;
1,152✔
2441
        *newterm = tt-newterm;
1,152✔
2442
        AT.WorkPointer = tt;
1,152✔
2443
        retval = Generator(BHEAD newterm,level);
1,152✔
2444
        AT.WorkPointer = oldworkpointer;
1,152✔
2445
        return(retval);
1,152✔
2446
}
2447

2448
/*
2449
                 #] EvaluateEuler : 
2450
          #] MZV : 
2451
          #[ Functions :
2452
                 #[ CoEvaluate :
2453

2454
                Current subkeys: mzv_, euler_ and sqrt_.
2455
*/
2456

2457
int CoEvaluate(UBYTE *s)
378✔
2458
{
2459
        GETIDENTITY
252✔
2460
        UBYTE *subkey, c;
378✔
2461
        WORD numfun, type;
378✔
2462
        int error = 0;
378✔
2463
        if ( AT.aux_ == 0 ) {
378✔
2464
                MesPrint("&Illegal attempt to evaluate a function without activating floating point numbers.");
6✔
2465
                MesPrint("&Forgotten %#startfloat instruction?");
6✔
2466
                return(1);
6✔
2467
        }
2468
        while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
372✔
2469
        if ( *s == 0 ) {
372✔
2470
/*
2471
                No subkey, which means all functions.
2472
*/
2473
                Add3Com(TYPEEVALUATE,ALLFUNCTIONS);
30✔
2474
/*
2475
                The MZV, EULER and MZVHALF are done separately
2476
*/
2477
                Add3Com(TYPEEVALUATE,ALLMZVFUNCTIONS);
30✔
2478
                return(0);        
30✔
2479
        }
2480
        while ( *s ) {
660✔
2481
        subkey = s;
2482
        while ( FG.cTable[*s] == 0 ) s++;
1,656✔
2483
          if ( *s == '2' ) s++; /* cases li2_ and atan2_ */
360✔
2484
          if ( *s == '_' ) s++;
360✔
2485
          c = *s; *s = 0;
360✔
2486
/*
2487
                We still need provisions for pi_ and possibly other constants.
2488
*/
2489
          if ( ( ( type = GetName(AC.varnames,subkey,&numfun,NOAUTO) ) != CFUNCTION )
360✔
2490
                        || ( functions[numfun].spec != 0 ) ) {
318✔
2491

2492
                if ( type == CSYMBOL ) {
42✔
2493
                        Add4Com(TYPEEVALUATE,SYMBOL,numfun);
36✔
2494
                        break;
36✔
2495
                }
2496
/*
2497
                        This cannot work.
2498
*/
2499
                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
6✔
2500
                return(1);
6✔
2501
          }
2502
          else {
2503
                switch ( numfun+FUNCTION ) {
318✔
2504
                        case MZV:
318✔
2505
                        case EULER:
2506
                        case MZVHALF:
2507
/*
2508
                        The following functions are treated in evaluate.c
2509
*/
2510
                        case SQRTFUNCTION:
2511
                        case LNFUNCTION:
2512
                        case SINFUNCTION:
2513
                        case COSFUNCTION:
2514
                        case TANFUNCTION:
2515
                        case ASINFUNCTION:
2516
                        case ACOSFUNCTION:
2517
                        case ATANFUNCTION:
2518
                        case ATAN2FUNCTION:
2519
                        case SINHFUNCTION:
2520
                        case COSHFUNCTION:
2521
                        case TANHFUNCTION:
2522
                        case ASINHFUNCTION:
2523
                        case ACOSHFUNCTION:
2524
                        case ATANHFUNCTION:
2525
                        case LI2FUNCTION:
2526
                        case LINFUNCTION:
2527
                        case AGMFUNCTION:
2528
                        case GAMMAFUN:
2529
/*
2530
                        At a later stage we can add more functions from mpfr here
2531
                                mpfr_(number,arg(s))
2532
*/
2533
                                Add3Com(TYPEEVALUATE,numfun+FUNCTION);
318✔
2534
                                break;
318✔
2535
                        default:
×
2536
                                MesPrint("&%s should be a built in function that can be evaluated numerically.",s);
×
2537
                                error = 1;
×
2538
                                break;
×
2539
                }
2540
          }
2541
          *s = c;
318✔
2542
          while ( *s == ' ' || *s == ',' || *s == '\t' ) s++;
336✔
2543
        }
2544
        return(error);
2545
}
2546

2547
/*
2548
                 #] CoEvaluate : 
2549
          #] Functions : 
2550
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc