Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28485 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2000 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
#include "pari.h"
16
#include "paripriv.h"
17
#include "anal.h"
18
#include "parse.h"
19
20
/***************************************************************************
21
** **
22
** Mnemonic codes parser **
23
** **
24
***************************************************************************/
25
26
/* TEMPLATE is assumed to be ";"-separated list of items. Each item
27
* may have one of the following forms: id=value id==value id|value id&~value.
28
* Each id consists of alphanum characters, dashes and underscores.
29
* IDs are case-sensitive.
30
31
* ARG consists of several IDs separated by punctuation (and optional
32
* whitespace). Each modifies the return value in a "natural" way: an
33
* ID from id=value should be the first in the sequence and sets RETVAL to
34
* VALUE (and cannot be negated), ID from id|value bit-ORs RETVAL with
35
* VALUE (and bit-ANDs RETVAL with ~VALUE if negated), ID from
36
* id&~value behaves as if it were noid|value, ID from
37
* id==value behaves the same as id=value, but should come alone.
38
39
* For items of the form id|value and id&~value negated forms are
40
* allowed: either when arg looks like no[-_]id, or when id looks like
41
* this, and arg is not-negated. */
42
43
static int
44
IS_ID(char c) { return isalnum((int)c) || c == '_'; }
45
long
46
eval_mnemonic(GEN str, const char *tmplate)
47
{
48
const char *arg, *etmplate;
49
ulong retval = 0;
50
51
if (typ(str)==t_INT) return itos(str);
52
if (typ(str)!=t_STR) pari_err_TYPE("eval_mnemonic",str);
53
54
arg = GSTR(str);
55
etmplate = strchr(tmplate, '\n');
56
if (!etmplate) etmplate = tmplate + strlen(tmplate);
57
58
while (1)
59
{
60
long numarg;
61
const char *e, *id, *negated = NULL;
62
int negate = 0; /* Arg has 'no' prefix removed */
63
ulong l;
64
char *buf;
65
static char b[80];
66
67
while (isspace((int)*arg)) arg++;
68
if (!*arg) break;
69
e = arg; while (IS_ID(*e)) e++;
70
/* Now the ID is whatever is between arg and e. */
71
l = e - arg;
72
if (l >= sizeof(b)) pari_err(e_MISC,"id too long in a mnemonic");
73
if (!l) pari_err(e_MISC,"mnemonic does not start with an id");
74
strncpy(b, arg, l); b[l] = 0;
75
arg = e; e = buf = b;
76
while ('0' <= *e && *e <= '9') e++;
77
if (*e == 0) pari_err(e_MISC,"numeric id in a mnemonic");
78
FIND:
79
id = tmplate;
80
while ((id = strstr(id, buf)) && id < etmplate)
81
{
82
const char *s = id;
83
id += l; if (s[l] != '|') continue; /* False positive */
84
if (s == tmplate || !IS_ID(s[-1])) break; /* Found as is */
85
/* If we found "no_ID", negate */
86
if (!negate && s >= tmplate+3 && (s == tmplate+3 || !IS_ID(s[-4]))
87
&& s[-3] == 'n' && s[-2] == 'o' && s[-1] == '_')
88
{ negated = id; break; }
89
}
90
if (!id && !negated && !negate && l > 3
91
&& buf[0] == 'n' && buf[1] == 'o' && buf[2] == '_')
92
{ /* Try to find the flag without the prefix "no_". */
93
buf += 3; l -= 3; negate = 1;
94
if (buf[0]) goto FIND;
95
}
96
/* Negated and AS_IS forms, prefer AS_IS otherwise use negated form */
97
if (!id)
98
{
99
if (!negated) pari_err(e_MISC,"Unrecognized id '%s' in mnemonic", b);
100
id = negated; negate = 1;
101
}
102
if (*id++ != '|') pari_err(e_MISC,"Missing | in mnemonic template");
103
e = id;
104
while (*e >= '0' && *e <= '9') e++;
105
while (isspace((int)*e)) e++;
106
if (*e && *e != ';' && *e != ',')
107
pari_err(e_MISC, "Non-numeric argument in mnemonic template");
108
numarg = atol(id);
109
if (negate) retval &= ~numarg; else retval |= numarg;
110
while (isspace((int)*arg)) arg++;
111
if (*arg && !ispunct((int)*arg++)) /* skip punctuation */
112
pari_err(e_MISC,"Junk after id in mnemonic");
113
}
114
return retval;
115
}
116
117
/********************************************************************/
118
/** **/
119
/** HASH TABLE MANIPULATIONS **/
120
/** **/
121
/********************************************************************/
122
static void
123
insertep(entree *ep, entree **table, ulong hash)
124
{
125
ep->hash = hash;
126
hash %= functions_tblsz;
127
ep->next = table[hash];
128
table[hash] = ep;
129
}
130
131
static entree *
132
initep(const char *name, long len)
133
{
134
const long add = 4*sizeof(long);
135
entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
136
entree *ep1 = initial_value(ep);
137
char *u = (char *) ep1 + add;
138
ep->name = u; memcpy(u, name,len); u[len]=0;
139
ep->valence = EpNEW;
140
ep->value = NULL;
141
ep->menu = 0;
142
ep->code = NULL;
143
ep->help = NULL;
144
ep->pvalue = NULL;
145
ep->arity = 0;
146
return ep;
147
}
148
149
/* Look for s of length len in T; if 'insert', insert if missing */
150
static entree *
151
findentry(const char *s, long len, entree **T, int insert)
152
{
153
ulong hash = hash_str_len(s, len);
154
entree *ep;
155
for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
156
if (ep->hash == hash)
157
{
158
const char *t = ep->name;
159
if (!strncmp(t, s, len) && !t[len]) return ep;
160
}
161
/* not found */
162
if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
163
return ep;
164
}
165
entree *
166
pari_is_default(const char *s)
167
{ return findentry(s, strlen(s), defaults_hash, 0); }
168
entree *
169
is_entry(const char *s)
170
{ return findentry(s, strlen(s), functions_hash, 0); }
171
entree *
172
fetch_entry_raw(const char *s, long len)
173
{ return findentry(s, len, functions_hash, 1); }
174
entree *
175
fetch_entry(const char *s) { return fetch_entry_raw(s, strlen(s)); }
176
177
/*******************************************************************/
178
/* */
179
/* SYNTACTICAL ANALYZER FOR GP */
180
/* */
181
/*******************************************************************/
182
static GEN
183
readseq_i(char *t)
184
{
185
if (gp_meta(t,0)) return gnil;
186
return closure_evalres(pari_compile_str(t));
187
}
188
GEN
189
readseq(char *t)
190
{ pari_sp av = avma; return gerepileupto(av, readseq_i(t)); }
191
192
/* filtered readseq = remove blanks and comments */
193
GEN
194
gp_read_str(const char *s)
195
{ pari_sp av = avma; return gerepileupto(av, readseq_i(gp_filter(s))); }
196
197
GEN
198
compile_str(const char *s) { return pari_compile_str(gp_filter(s)); }
199
200
GEN
201
gp_read_str_bitprec(const char *s, long bitprec)
202
{
203
GEN x;
204
push_localbitprec(bitprec);
205
x = gp_read_str(s);
206
pop_localprec();
207
return x;
208
}
209
210
GEN
211
gp_read_str_prec(const char *s, long prec)
212
{ return gp_read_str_bitprec(s, prec2nbits(prec)); }
213
214
/* valid return type */
215
static int
216
isreturn(char c)
217
{ return c == 'l' || c == 'v' || c == 'i' || c == 'm' || c == 'u'; }
218
219
/* if is known that 2 commas follow s; base-10 signed integer followed
220
* by comma? */
221
static int
222
is_long(const char *s)
223
{
224
while (isspace(*s)) s++;
225
if (*s == '+' || *s == '-') s++;
226
while (isdigit(*s)) s++;
227
return *s == ',';
228
}
229
/* if is known that 2 commas follow s; base-10 unsigned integer followed
230
* by comma? */
231
static int
232
is_ulong(const char *s)
233
{
234
while (isspace(*s)) s++;
235
if (*s == '+') s++;
236
while (isdigit(*s)) s++;
237
return *s == ',';
238
}
239
static long
240
check_proto(const char *code)
241
{
242
long arity = 0;
243
const char *s = code;
244
if (isreturn(*s)) s++;
245
while (*s && *s != '\n') switch (*s++)
246
{
247
case '&':
248
case 'C':
249
case 'G':
250
case 'I':
251
case 'J':
252
case 'U':
253
case 'L':
254
case 'M':
255
case 'P':
256
case 'W':
257
case 'f':
258
case 'n':
259
case 'p':
260
case 'b':
261
case 'r':
262
arity++; break;
263
case 'E':
264
case 's':
265
if (*s == '*') s++;
266
arity++; break;
267
case 'D':
268
switch(*s)
269
{
270
case 'G': case '&': case 'n': case 'I': case 'E':
271
case 'P': case 's': case 'r': s++; arity++; break;
272
case 'V': s++; break;
273
case 0:
274
pari_err(e_SYNTAX,"function has incomplete prototype", s,code);
275
break;
276
default:
277
{
278
const char *p;
279
long i;
280
for(i = 0, p = s; *p && i < 2; p++) i += *p==','; /* skip 2 commas */
281
if (i < 2) pari_err(e_SYNTAX,"missing comma",s,code);
282
arity++;
283
switch(p[-2])
284
{
285
case 'L':
286
if (!is_long(s)) pari_err(e_SYNTAX,"not a long",s,code);
287
break;
288
case 'U':
289
if (!is_ulong(s)) pari_err(e_SYNTAX,"not an ulong",s,code);
290
break;
291
case 'G': case 'r': case 's': case 'M':
292
break;
293
default: pari_err(e_SYNTAX,"incorrect type",s-2,code);
294
}
295
s = p;
296
}
297
}
298
break;
299
case 'V':
300
case '=':
301
case ',': break;
302
case '\n': break; /* Before the mnemonic */
303
default:
304
if (isreturn(s[-1]))
305
pari_err(e_SYNTAX, "this code has to come first", s-1, code);
306
pari_err(e_SYNTAX, "unknown parser code", s-1, code);
307
}
308
if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
309
return arity;
310
}
311
static void
312
check_name(const char *name)
313
{
314
const char *s = name;
315
if (isalpha((int)*s))
316
while (is_keyword_char(*++s)) /* empty */;
317
if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
318
}
319
320
entree *
321
install(void *f, const char *name, const char *code)
322
{
323
long arity = check_proto(code);
324
entree *ep;
325
326
check_name(name);
327
ep = fetch_entry(name);
328
if (ep->valence != EpNEW)
329
{
330
if (ep->valence != EpINSTALL)
331
pari_err(e_MISC,"[install] identifier '%s' already in use", name);
332
pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name);
333
if (ep->code) pari_free((void*)ep->code);
334
}
335
else
336
{
337
ep->value = f;
338
ep->valence = EpINSTALL;
339
}
340
ep->code = pari_strdup(code);
341
ep->arity = arity; return ep;
342
}
343
344
static void
345
killep(entree *ep)
346
{
347
GEN p = (GEN)initial_value(ep);
348
freeep(ep);
349
*p = 0; /* otherwise pari_var_create won't regenerate it */
350
ep->valence = EpNEW;
351
ep->value = NULL;
352
ep->pvalue = NULL;
353
}
354
/* Kill ep, i.e free all memory it references, and reset to initial value */
355
void
356
kill0(const char *e)
357
{
358
entree *ep = is_entry(e);
359
if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
360
killep(ep);
361
}
362
363
void
364
addhelp(const char *e, char *s)
365
{
366
entree *ep = fetch_entry(e);
367
void *f = (void *) ep->help;
368
ep->help = pari_strdup(s);
369
if (f && !EpSTATIC(ep)) pari_free(f);
370
}
371
372
/*******************************************************************/
373
/* */
374
/* PARSER */
375
/* */
376
/*******************************************************************/
377
378
#ifdef LONG_IS_64BIT
379
static const long MAX_DIGITS = 19;
380
#else
381
static const long MAX_DIGITS = 9;
382
#endif
383
384
static const long MAX_XDIGITS = BITS_IN_LONG>>2;
385
static const long MAX_BDIGITS = BITS_IN_LONG;
386
387
static int
388
ishex(const char **s)
389
{
390
if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' ))
391
{
392
*s += 2;
393
return 1;
394
}
395
else
396
return 0;
397
}
398
399
static int
400
isbin(const char **s)
401
{
402
if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' ))
403
{
404
*s += 2;
405
return 1;
406
}
407
else
408
return 0;
409
}
410
411
static ulong
412
bin_number_len(const char *s, long n)
413
{
414
ulong m = 0;
415
long i;
416
for (i = 0; i < n; i++,s++)
417
m = 2*m + (*s - '0');
418
return m;
419
}
420
421
static int
422
pari_isbdigit(int c)
423
{
424
return c=='0' || c=='1';
425
}
426
427
static ulong
428
hex_number_len(const char *s, long n)
429
{
430
ulong m = 0;
431
long i;
432
for(i = 0; i < n; i++, s++)
433
{
434
ulong c;
435
if( *s >= '0' && *s <= '9')
436
c = *s - '0';
437
else if( *s >= 'A' && *s <= 'F')
438
c = *s - 'A' + 10;
439
else
440
c = *s - 'a' + 10;
441
m = 16*m + c;
442
}
443
return m;
444
}
445
446
static GEN
447
strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n))
448
{
449
long i, l = (n+B-1)/B;
450
GEN N, Np;
451
N = cgetipos(l+2);
452
Np = int_LSW(N);
453
for (i=1; i<l; i++, Np = int_nextW(Np))
454
uel(Np, 0) = num(s+n-i*B, B);
455
uel(Np, 0) = num(s, n-(i-1)*B);
456
return int_normalize(N, 0);
457
}
458
459
static GEN
460
binary_read(const char **ps, long B, int is(int), ulong num(const char *s, long n))
461
{
462
const char *s = *ps;
463
while (is((int)**ps)) (*ps)++;
464
return strtobin_len(s, *ps-s, B, num);
465
}
466
467
static GEN
468
bin_read(const char **ps)
469
{
470
return binary_read(ps, MAX_BDIGITS, pari_isbdigit, bin_number_len);
471
}
472
473
static GEN
474
hex_read(const char **ps)
475
{
476
return binary_read(ps, MAX_XDIGITS, isxdigit, hex_number_len);
477
}
478
479
static ulong
480
dec_number_len(const char *s, long B)
481
{
482
ulong m = 0;
483
long n;
484
for (n = 0; n < B; n++,s++)
485
m = 10*m + (*s - '0');
486
return m;
487
}
488
489
static GEN
490
dec_strtoi_len(const char *s, long n)
491
{
492
const long B = MAX_DIGITS;
493
long i, l = (n+B-1)/B;
494
GEN V = cgetg(l+1, t_VECSMALL);
495
for (i=1; i<l; i++)
496
uel(V,i) = dec_number_len(s+n-i*B, B);
497
uel(V, i) = dec_number_len(s, n-(i-1)*B);
498
return fromdigitsu(V, powuu(10, B));
499
}
500
501
static GEN
502
dec_read_more(const char **ps)
503
{
504
pari_sp av = avma;
505
const char *s = *ps;
506
while (isdigit((int)**ps)) (*ps)++;
507
return gerepileuptoint(av, dec_strtoi_len(s, *ps-s));
508
}
509
510
static ulong
511
number(int *n, const char **s)
512
{
513
ulong m = 0;
514
for (*n = 0; *n < MAX_DIGITS && isdigit((int)**s); (*n)++,(*s)++)
515
m = 10*m + (**s - '0');
516
return m;
517
}
518
519
static GEN
520
dec_read(const char **s)
521
{
522
int nb;
523
ulong y = number(&nb, s);
524
if (nb < MAX_DIGITS)
525
return utoi(y);
526
*s -= MAX_DIGITS;
527
return dec_read_more(s);
528
}
529
530
static GEN
531
real_read_more(GEN y, const char **ps)
532
{
533
pari_sp av = avma;
534
const char *s = *ps;
535
GEN z = dec_read(ps);
536
long e = *ps-s;
537
return gerepileuptoint(av, addmulii(z, powuu(10, e), y));
538
}
539
540
static long
541
exponent(const char **pts)
542
{
543
const char *s = *pts;
544
long n;
545
int nb;
546
switch(*++s)
547
{
548
case '-': s++; n = -(long)number(&nb, &s); break;
549
case '+': s++; /* Fall through */
550
default: n = (long)number(&nb, &s);
551
}
552
*pts = s; return n;
553
}
554
555
static GEN
556
real_0_digits(long n) {
557
long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1);
558
return real_0_bit(b);
559
}
560
561
static GEN
562
real_read(pari_sp av, const char **s, GEN y, long prec)
563
{
564
long l, n = 0;
565
switch(**s)
566
{
567
default: return y; /* integer */
568
case '.':
569
{
570
const char *old = ++*s;
571
if (isalpha((int)**s) || **s=='.')
572
{
573
if (**s == 'E' || **s == 'e') {
574
n = exponent(s);
575
if (!signe(y)) { set_avma(av); return real_0_digits(n); }
576
break;
577
}
578
--*s; return y; /* member */
579
}
580
if (isdigit((int)**s)) y = real_read_more(y, s);
581
n = old - *s;
582
if (**s != 'E' && **s != 'e')
583
{
584
if (!signe(y)) { set_avma(av); return real_0(prec); }
585
break;
586
}
587
}
588
/* Fall through */
589
case 'E': case 'e':
590
n += exponent(s);
591
if (!signe(y)) { set_avma(av); return real_0_digits(n); }
592
}
593
l = nbits2prec(bit_accuracy(lgefint(y)));
594
if (l < prec) l = prec; else prec = l;
595
if (!n) return itor(y, prec);
596
incrprec(l);
597
y = itor(y, l);
598
if (n > 0)
599
y = mulrr(y, rpowuu(10UL, (ulong)n, l));
600
else
601
y = divrr(y, rpowuu(10UL, (ulong)-n, l));
602
return gerepileuptoleaf(av, rtor(y, prec));
603
}
604
605
static GEN
606
int_read(const char **s)
607
{
608
GEN y;
609
if (isbin(s))
610
y = bin_read(s);
611
else if (ishex(s))
612
y = hex_read(s);
613
else
614
y = dec_read(s);
615
return y;
616
}
617
618
GEN
619
strtoi(const char *s) { return int_read(&s); }
620
621
GEN
622
strtor(const char *s, long prec)
623
{
624
pari_sp av = avma;
625
GEN y = dec_read(&s);
626
y = real_read(av, &s, y, prec);
627
if (typ(y) == t_REAL) return y;
628
return gerepileuptoleaf(av, itor(y, prec));
629
}
630
631
static void
632
skipdigits(char **lex) {
633
while (isdigit((int)**lex)) ++*lex;
634
}
635
636
static int
637
skipexponent(char **lex)
638
{
639
char *old=*lex;
640
if ((**lex=='e' || **lex=='E'))
641
{
642
++*lex;
643
if ( **lex=='+' || **lex=='-' ) ++*lex;
644
if (!isdigit((int)**lex))
645
{
646
*lex=old;
647
return KINTEGER;
648
}
649
skipdigits(lex);
650
return KREAL;
651
}
652
return KINTEGER;
653
}
654
655
static int
656
skipconstante(char **lex)
657
{
658
skipdigits(lex);
659
if (**lex=='.')
660
{
661
char *old = ++*lex;
662
if (**lex == '.') { --*lex; return KINTEGER; }
663
if (isalpha((int)**lex))
664
{
665
skipexponent(lex);
666
if (*lex == old)
667
{
668
--*lex; /* member */
669
return KINTEGER;
670
}
671
return KREAL;
672
}
673
skipdigits(lex);
674
skipexponent(lex);
675
return KREAL;
676
}
677
return skipexponent(lex);
678
}
679
680
static void
681
skipstring(char **lex)
682
{
683
while (**lex)
684
{
685
while (**lex == '\\') *lex+=2;
686
if (**lex == '"')
687
{
688
if ((*lex)[1] != '"') break;
689
*lex += 2; continue;
690
}
691
(*lex)++;
692
}
693
}
694
695
int
696
pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
697
{
698
(void) yylval;
699
yylloc->start=*lex;
700
if (!**lex)
701
{
702
yylloc->end=*lex;
703
return 0;
704
}
705
if (isalpha((int)**lex))
706
{
707
while (is_keyword_char(**lex)) ++*lex;
708
yylloc->end=*lex;
709
return KENTRY;
710
}
711
if (**lex=='"')
712
{
713
++*lex;
714
skipstring(lex);
715
if (!**lex)
716
compile_err("run-away string",*lex-1);
717
++*lex;
718
yylloc->end=*lex;
719
return KSTRING;
720
}
721
if (**lex == '.')
722
{
723
int token;
724
if ((*lex)[1]== '.')
725
{
726
*lex+=2; yylloc->end = *lex; return KDOTDOT;
727
}
728
token=skipconstante(lex);
729
if (token==KREAL)
730
{
731
yylloc->end = *lex;
732
return token;
733
}
734
++*lex;
735
yylloc->end=*lex;
736
return '.';
737
}
738
if (isbin((const char**)lex))
739
{
740
while (**lex=='0' || **lex=='1') ++*lex;
741
return KINTEGER;
742
}
743
if (ishex((const char**)lex))
744
{
745
while (isxdigit((int)**lex)) ++*lex;
746
return KINTEGER;
747
}
748
if (isdigit((int)**lex))
749
{
750
int token=skipconstante(lex);
751
yylloc->end = *lex;
752
return token;
753
}
754
if ((*lex)[1]=='=')
755
switch (**lex)
756
{
757
case '=':
758
if ((*lex)[2]=='=')
759
{ *lex+=3; yylloc->end = *lex; return KID; }
760
else
761
{ *lex+=2; yylloc->end = *lex; return KEQ; }
762
case '>':
763
*lex+=2; yylloc->end = *lex; return KGE;
764
case '<':
765
*lex+=2; yylloc->end = *lex; return KLE;
766
case '*':
767
*lex+=2; yylloc->end = *lex; return KME;
768
case '/':
769
*lex+=2; yylloc->end = *lex; return KDE;
770
case '%':
771
if ((*lex)[2]=='=') break;
772
*lex+=2; yylloc->end = *lex; return KMODE;
773
case '!':
774
if ((*lex)[2]=='=') break;
775
*lex+=2; yylloc->end = *lex; return KNE;
776
case '\\':
777
*lex+=2; yylloc->end = *lex; return KEUCE;
778
case '+':
779
*lex+=2; yylloc->end = *lex; return KPE;
780
case '-':
781
*lex+=2; yylloc->end = *lex; return KSE;
782
}
783
if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>')
784
{
785
*lex+=3; yylloc->end = *lex; return KPARROW;
786
}
787
if (**lex=='-' && (*lex)[1]=='>')
788
{
789
*lex+=2; yylloc->end = *lex; return KARROW;
790
}
791
if (**lex=='<' && (*lex)[1]=='>')
792
{
793
*lex+=2; yylloc->end = *lex; return KNE;
794
}
795
if (**lex=='\\' && (*lex)[1]=='/')
796
switch((*lex)[2])
797
{
798
case '=':
799
*lex+=3; yylloc->end = *lex; return KDRE;
800
default:
801
*lex+=2; yylloc->end = *lex; return KDR;
802
}
803
if ((*lex)[1]==**lex)
804
switch (**lex)
805
{
806
case '&':
807
*lex+=2; yylloc->end = *lex; return KAND;
808
case '|':
809
*lex+=2; yylloc->end = *lex; return KOR;
810
case '+':
811
*lex+=2; yylloc->end = *lex; return KPP;
812
case '-':
813
*lex+=2; yylloc->end = *lex; return KSS;
814
case '>':
815
if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;}
816
*lex+=2; yylloc->end = *lex; return KSR;
817
case '<':
818
if ((*lex)[2]=='=')
819
{ *lex+=3; yylloc->end = *lex; return KSLE; }
820
*lex+=2; yylloc->end = *lex; return KSL;
821
}
822
yylloc->end = *lex+1;
823
return (unsigned char) *(*lex)++;
824
}
825
826
/********************************************************************/
827
/* */
828
/* Formal variables management */
829
/* */
830
/********************************************************************/
831
static THREAD long max_priority, min_priority;
832
static THREAD long max_avail; /* max variable not yet used */
833
static THREAD long nvar; /* first GP free variable */
834
static hashtable *h_polvar;
835
836
void
837
varstate_save(struct pari_varstate *s)
838
{
839
s->nvar = nvar;
840
s->max_avail = max_avail;
841
s->max_priority = max_priority;
842
s->min_priority = min_priority;
843
}
844
845
static void
846
varentries_set(long v, entree *ep)
847
{
848
hash_insert(h_polvar, (void*)ep->name, (void*)v);
849
varentries[v] = ep;
850
}
851
static int
852
_given_value(void *E, hashentry *e) { return e->val == E; }
853
854
static void
855
varentries_unset(long v)
856
{
857
entree *ep = varentries[v];
858
if (ep)
859
{
860
hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
861
_given_value);
862
if (!e) pari_err_BUG("varentries_unset [unknown var]");
863
varentries[v] = NULL;
864
pari_free(e);
865
if (v <= nvar && ep == is_entry(ep->name))
866
{ /* known to the GP interpreter; entree in functions_hash is permanent */
867
GEN p = (GEN)initial_value(ep);
868
if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; }
869
*p = 0;
870
}
871
else /* from name_var() or a direct pari_var_create() */
872
pari_free(ep);
873
}
874
}
875
static void
876
varentries_reset(long v, entree *ep)
877
{
878
varentries_unset(v);
879
varentries_set(v, ep);
880
}
881
882
static void
883
var_restore(struct pari_varstate *s)
884
{
885
nvar = s->nvar;
886
max_avail = s->max_avail;
887
max_priority = s->max_priority;
888
min_priority = s->min_priority;
889
}
890
891
void
892
varstate_restore(struct pari_varstate *s)
893
{
894
long i;
895
for (i = nvar; i >= s->nvar; i--)
896
{
897
varentries_unset(i);
898
varpriority[i] = -i;
899
}
900
for (i = max_avail+1; i <= s->max_avail; i++)
901
{
902
varentries_unset(i);
903
varpriority[i] = -i;
904
}
905
var_restore(s);
906
}
907
908
void
909
pari_set_varstate(long *vp, struct pari_varstate *vs)
910
{
911
var_restore(vs);
912
varpriority = (long*)newblock(MAXVARN+2) + 1;
913
memcpy(varpriority-1,vp-1,(MAXVARN+2)*sizeof(long));
914
}
915
916
/* must come before destruction of functions_hash */
917
void
918
pari_var_close(void)
919
{
920
GEN h = hash_values(h_polvar);
921
long i, l = lg(h);
922
for (i = 1; i < l; i++)
923
{
924
long v = h[i];
925
entree *ep = varentries[v];
926
if (ep && ep != is_entry(ep->name)) pari_free(ep);
927
}
928
free((void*)varentries);
929
free((void*)(varpriority-1));
930
hash_destroy(h_polvar);
931
}
932
933
void
934
pari_var_init(void)
935
{
936
long i;
937
varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
938
varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
939
varpriority[-1] = 1-LONG_MAX;
940
h_polvar = hash_create_str(100, 0);
941
nvar = 0; max_avail = MAXVARN;
942
max_priority = min_priority = 0;
943
(void)fetch_user_var("x");
944
(void)fetch_user_var("y");
945
/* initialize so that people can use pol_x(i) directly */
946
for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
947
/* reserve varnum 1..9 for static temps with predictable priority wrt x */
948
nvar = 10;
949
min_priority = -MAXVARN;
950
}
951
long pari_var_next(void) { return nvar; }
952
long pari_var_next_temp(void) { return max_avail; }
953
long
954
pari_var_create(entree *ep)
955
{
956
GEN p = (GEN)initial_value(ep);
957
long v;
958
if (*p) return varn(p);
959
if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
960
v = nvar++;
961
/* set p = pol_x(v) */
962
p[0] = evaltyp(t_POL) | _evallg(4);
963
p[1] = evalsigne(1) | evalvarn(v);
964
gel(p,2) = gen_0;
965
gel(p,3) = gen_1;
966
varentries_set(v, ep);
967
varpriority[v]= min_priority--;
968
return v;
969
}
970
971
long
972
delete_var(void)
973
{ /* user wants to delete one of his/her/its variables */
974
if (max_avail == MAXVARN) return 0; /* nothing to delete */
975
max_avail++;
976
if (varpriority[max_avail] == min_priority) min_priority++;
977
else if (varpriority[max_avail] == max_priority) max_priority--;
978
return max_avail+1;
979
}
980
long
981
fetch_var(void)
982
{
983
if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
984
varpriority[max_avail] = min_priority--;
985
return max_avail--;
986
}
987
long
988
fetch_var_higher(void)
989
{
990
if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
991
varpriority[max_avail] = ++max_priority;
992
return max_avail--;
993
}
994
995
static int
996
_higher(void *E, hashentry *e)
997
{ long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
998
static int
999
_lower(void *E, hashentry *e)
1000
{ long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
1001
1002
static GEN
1003
var_register(long v, const char *s)
1004
{
1005
varentries_reset(v, initep(s, strlen(s)));
1006
return pol_x(v);
1007
}
1008
GEN
1009
varhigher(const char *s, long w)
1010
{
1011
long v;
1012
if (w >= 0)
1013
{
1014
hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
1015
if (e) return pol_x((long)e->val);
1016
}
1017
/* no luck: need to create */
1018
if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
1019
v = nvar++;
1020
varpriority[v]= ++max_priority;
1021
return var_register(v, s);
1022
}
1023
GEN
1024
varlower(const char *s, long w)
1025
{
1026
long v;
1027
if (w >= 0)
1028
{
1029
hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
1030
if (e) return pol_x((long)e->val);
1031
}
1032
/* no luck: need to create */
1033
v = fetch_var();
1034
return var_register(v, s);
1035
}
1036
1037
long
1038
fetch_user_var(const char *s)
1039
{
1040
entree *ep = fetch_entry(s);
1041
long v;
1042
switch (EpVALENCE(ep))
1043
{
1044
case EpVAR: return varn((GEN)initial_value(ep));
1045
case EpNEW: break;
1046
default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
1047
}
1048
v = pari_var_create(ep);
1049
ep->valence = EpVAR;
1050
ep->value = initial_value(ep);
1051
return v;
1052
}
1053
1054
GEN
1055
fetch_var_value(long v, GEN t)
1056
{
1057
entree *ep = varentries[v];
1058
if (!ep) return NULL;
1059
if (t)
1060
{
1061
long vn = localvars_find(t,ep);
1062
if (vn) return get_lex(vn);
1063
}
1064
return (GEN)ep->value;
1065
}
1066
1067
void
1068
name_var(long n, const char *s)
1069
{
1070
entree *ep;
1071
char *u;
1072
1073
if (n < pari_var_next())
1074
pari_err(e_MISC, "renaming a GP variable is forbidden");
1075
if (n > (long)MAXVARN)
1076
pari_err_OVERFLOW("variable number");
1077
1078
ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1);
1079
u = (char *)initial_value(ep);
1080
ep->valence = EpVAR;
1081
ep->name = u; strcpy(u,s);
1082
ep->value = gen_0; /* in case geval is called */
1083
varentries_reset(n, ep);
1084
}
1085
1086
static int
1087
cmp_by_var(void *E,GEN x, GEN y)
1088
{ (void)E; return varncmp((long)x,(long)y); }
1089
GEN
1090
vars_sort_inplace(GEN z)
1091
{ gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
1092
GEN
1093
vars_to_RgXV(GEN h)
1094
{
1095
long i, l = lg(h);
1096
GEN z = cgetg(l, t_VEC);
1097
for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
1098
return z;
1099
}
1100
GEN
1101
gpolvar(GEN x)
1102
{
1103
long v;
1104
if (!x) {
1105
GEN h = hash_values(h_polvar);
1106
return vars_to_RgXV(vars_sort_inplace(h));
1107
}
1108
if (typ(x)==t_PADIC) return gcopy( gel(x,2) );
1109
v = gvar(x);
1110
if (v==NO_VARIABLE) return gen_0;
1111
return pol_x(v);
1112
}
1113
1114
static void
1115
fill_hashtable_single(entree **table, entree *ep)
1116
{
1117
EpSETSTATIC(ep);
1118
insertep(ep, table, hash_str(ep->name));
1119
if (ep->code) ep->arity = check_proto(ep->code);
1120
ep->pvalue = NULL;
1121
}
1122
1123
void
1124
pari_fill_hashtable(entree **table, entree *ep)
1125
{
1126
for ( ; ep->name; ep++) fill_hashtable_single(table, ep);
1127
}
1128
1129
void
1130
pari_add_function(entree *ep)
1131
{
1132
fill_hashtable_single(functions_hash, ep);
1133
}
1134
1135
/********************************************************************/
1136
/** **/
1137
/** SIMPLE GP FUNCTIONS **/
1138
/** **/
1139
/********************************************************************/
1140
1141
GEN
1142
arity0(GEN C)
1143
{
1144
if (typ(C)!=t_CLOSURE) pari_err_TYPE("arity", C);
1145
return utoi(closure_arity(C));
1146
}
1147
1148
#define ALIAS(ep) (entree *) ((GEN)ep->value)[1]
1149
1150
entree *
1151
do_alias(entree *ep)
1152
{
1153
while (ep->valence == EpALIAS) ep = ALIAS(ep);
1154
return ep;
1155
}
1156
1157
void
1158
alias0(const char *s, const char *old)
1159
{
1160
entree *ep, *e;
1161
GEN x;
1162
1163
ep = fetch_entry(old);
1164
e = fetch_entry(s);
1165
if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
1166
pari_err(e_MISC,"can't replace an existing symbol by an alias");
1167
freeep(e);
1168
x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep;
1169
e->value=x; e->valence=EpALIAS;
1170
}
1171
1172
GEN
1173
ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/)
1174
{
1175
if (gequal0(g)) /* false */
1176
return b? closure_evalgen(b): gnil;
1177
else /* true */
1178
return a? closure_evalgen(a): gnil;
1179
}
1180
1181
void
1182
ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/)
1183
{
1184
if (gequal0(g)) /* false */
1185
{ if (b) closure_evalvoid(b); }
1186
else /* true */
1187
{ if (a) closure_evalvoid(a); }
1188
}
1189
1190
GEN
1191
ifpari_multi(GEN g, GEN a/*closure*/)
1192
{
1193
long i, nb = lg(a)-1;
1194
if (!gequal0(g)) /* false */
1195
return closure_evalgen(gel(a,1));
1196
for(i=2;i<nb;i+=2)
1197
{
1198
GEN g = closure_evalgen(gel(a,i));
1199
if (!g) return g;
1200
if (!gequal0(g))
1201
return closure_evalgen(gel(a,i+1));
1202
}
1203
return i<=nb? closure_evalgen(gel(a,i)): gnil;
1204
}
1205
1206
GEN
1207
andpari(GEN a, GEN b/*closure*/)
1208
{
1209
GEN g;
1210
if (gequal0(a))
1211
return gen_0;
1212
g=closure_evalgen(b);
1213
if (!g) return g;
1214
return gequal0(g)?gen_0:gen_1;
1215
}
1216
1217
GEN
1218
orpari(GEN a, GEN b/*closure*/)
1219
{
1220
GEN g;
1221
if (!gequal0(a))
1222
return gen_1;
1223
g=closure_evalgen(b);
1224
if (!g) return g;
1225
return gequal0(g)?gen_0:gen_1;
1226
}
1227
1228
GEN gmule(GEN *x, GEN y) { *x = gmul(*x,y); return *x; }
1229
GEN gdive(GEN *x, GEN y) { *x = gdiv(*x,y); return *x; }
1230
GEN gdivente(GEN *x, GEN y) { *x = gdivent(*x,y); return *x; }
1231
GEN gdivrounde(GEN *x, GEN y) { *x = gdivround(*x,y); return *x; }
1232
GEN gmode(GEN *x, GEN y) { *x = gmod(*x,y); return *x; }
1233
GEN gshiftle(GEN *x, long n) { *x = gshift(*x,n); return *x; }
1234
GEN gshiftre(GEN *x, long n) { *x = gshift(*x,-n); return *x; }
1235
GEN gadde(GEN *x, GEN y) { *x = gadd(*x,y); return *x; }
1236
GEN gadd1e(GEN *x) { *x = typ(*x)==t_INT?addiu(*x,1):gaddgs(*x,1); return *x; }
1237
GEN gsube(GEN *x, GEN y) { *x = gsub(*x,y); return *x; }
1238
GEN gsub1e(GEN *x) { *x = typ(*x)==t_INT?subiu(*x,1):gsubgs(*x,1); return *x; }
1239
1240
GEN gshift_right(GEN x, long n) { return gshift(x,-n); }
1241
1242