Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28495 views
License: GPL3
ubuntu2004
1
#line 2 "../src/kernel/none/halfgcd.c"
2
/* Copyright (C) 2019 The PARI group.
3
4
This file is part of the PARI/GP package.
5
6
PARI/GP is free software; you can redistribute it and/or modify it under the
7
terms of the GNU General Public License as published by the Free Software
8
Foundation; either version 2 of the License, or (at your option) any later
9
version. It is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY WHATSOEVER.
11
12
Check the License for details. You should have received a copy of it, along
13
with the package; see the file 'COPYING'. If not, write to the Free Software
14
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16
GEN
17
ZM2_mul(GEN A, GEN B)
18
{
19
const long t = 52;
20
GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2);
21
GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2);
22
if (lgefint(A11) < t || lgefint(B11) < t || lgefint(A22) < t || lgefint(B22) < t
23
|| lgefint(A12) < t || lgefint(B12) < t || lgefint(A21) < t || lgefint(B21) < t)
24
{
25
GEN a = mulii(A11, B11), b = mulii(A12, B21);
26
GEN c = mulii(A11, B12), d = mulii(A12, B22);
27
GEN e = mulii(A21, B11), f = mulii(A22, B21);
28
GEN g = mulii(A21, B12), h = mulii(A22, B22);
29
retmkmat2(mkcol2(addii(a,b), addii(e,f)), mkcol2(addii(c,d), addii(g,h)));
30
} else
31
{
32
GEN M1 = mulii(addii(A11,A22), addii(B11,B22));
33
GEN M2 = mulii(addii(A21,A22), B11);
34
GEN M3 = mulii(A11, subii(B12,B22));
35
GEN M4 = mulii(A22, subii(B21,B11));
36
GEN M5 = mulii(addii(A11,A12), B22);
37
GEN M6 = mulii(subii(A21,A11), addii(B11,B12));
38
GEN M7 = mulii(subii(A12,A22), addii(B21,B22));
39
GEN T1 = addii(M1,M4), T2 = subii(M7,M5);
40
GEN T3 = subii(M1,M2), T4 = addii(M3,M6);
41
retmkmat2(mkcol2(addii(T1,T2), addii(M2,M4)),
42
mkcol2(addii(M3,M5), addii(T3,T4)));
43
}
44
}
45
46
static GEN
47
matid2(void)
48
{
49
retmkmat2(mkcol2(gen_1,gen_0),
50
mkcol2(gen_0,gen_1));
51
}
52
53
/* Return M*[q,1;1,0] */
54
static GEN
55
mulq(GEN M, GEN q)
56
{
57
GEN u, v, res = cgetg(3, t_MAT);
58
u = addii(mulii(gcoeff(M,1,1), q), gcoeff(M,1,2));
59
v = addii(mulii(gcoeff(M,2,1), q), gcoeff(M,2,2));
60
gel(res,1) = mkcol2(u, v);
61
gel(res,2) = gel(M,1);
62
return res;
63
}
64
static GEN
65
mulqab(GEN M, GEN q, GEN *ap, GEN *bp)
66
{
67
GEN b = subii(*ap, mulii(*bp, q));
68
*ap = *bp; *bp = b;
69
return mulq(M,q);
70
}
71
72
/* Return M*[q,1;1,0]^-1 */
73
74
static GEN
75
mulqi(GEN M, GEN q, GEN *ap, GEN *bp)
76
{
77
GEN u, v, res, a;
78
a = addii(mulii(*ap, q), *bp);
79
*bp = *ap; *ap = a;
80
res = cgetg(3, t_MAT);
81
u = subii(gcoeff(M,1,1),mulii(gcoeff(M,1,2), q));
82
v = subii(gcoeff(M,2,1),mulii(gcoeff(M,2,2), q));
83
gel(res,1) = gel(M,2);
84
gel(res,2) = mkcol2(u,v);
85
return res;
86
}
87
88
static long
89
uexpi(GEN a)
90
{ return expi(subiu(shifti(a,1),1)); }
91
92
static GEN
93
FIXUP0(GEN M, GEN *a, GEN *b, long m)
94
{
95
long cnt=0;
96
while (expi(*b) >= m)
97
{
98
GEN r, q = dvmdii(*a, *b, &r);
99
*a = *b; *b = r;
100
M = mulq(M, q);
101
cnt++;
102
};
103
if (cnt>6) pari_err_BUG("FIXUP0");
104
return M;
105
}
106
107
static long
108
signdet(GEN Q)
109
{
110
long a = Mod4(gcoeff(Q,1,1)), b = Mod4(gcoeff(Q,1,2));
111
long c = Mod4(gcoeff(Q,2,1)), d = Mod4(gcoeff(Q,2,2));
112
return ((a*d-b*c)&3)==1 ? 1 : -1;
113
}
114
115
static GEN
116
ZM_inv2(GEN M)
117
{
118
long e = signdet(M);
119
if (e==1) return mkmat22(gcoeff(M,2,2),negi(gcoeff(M,1,2)),
120
negi(gcoeff(M,2,1)),gcoeff(M,1,1));
121
else return mkmat22(negi(gcoeff(M,2,2)),gcoeff(M,1,2),
122
gcoeff(M,2,1),negi(gcoeff(M,1,1)));
123
}
124
125
static GEN
126
lastq(GEN Q)
127
{
128
GEN p = gcoeff(Q,1,1), q = gcoeff(Q,1,2), s = gcoeff(Q,2,2);
129
if (signe(q)==0) pari_err_BUG("halfgcd");
130
if (signe(s)==0) return p;
131
if (equali1(q)) return subiu(p,1);
132
return divii(p, q);
133
}
134
135
static GEN
136
mulT(GEN Q, GEN *ap, GEN *bp)
137
{
138
*ap = addii(*ap, *bp);
139
*bp = negi(*bp);
140
return mkmat2(gel(Q,1),
141
mkcol2(subii(gcoeff(Q,1,1), gcoeff(Q,1,2))
142
, subii(gcoeff(Q,2,1), gcoeff(Q,2,2))));
143
}
144
145
static GEN
146
FIXUP1(GEN M, GEN a, GEN b, long m, long t, GEN *ap, GEN *bp)
147
{
148
GEN Q = gel(M,1), a0 = gel(M,2), b0 = gel(M,3);
149
GEN q, am = remi2n(a, m), bm = remi2n(b, m);
150
if (signdet(Q)==-1)
151
{
152
*ap = subii(mulii(bm, gcoeff(Q,1,2)),mulii(am, gcoeff(Q,2,2)));
153
*bp = subii(mulii(am, gcoeff(Q,2,1)),mulii(bm, gcoeff(Q,1,1)));
154
*ap = addii(*ap, shifti(addii(a0, gcoeff(Q,2,2)), m));
155
*bp = addii(*bp, shifti(subii(b0, gcoeff(Q,2,1)), m));
156
if (signe(*bp) >= 0)
157
return Q;
158
if (expi(addii(*ap,*bp)) >= m+t)
159
return mulT(Q, ap ,bp);
160
q = lastq(Q);
161
Q = mulqi(Q, q, ap, bp);
162
if (cmpiu(q, 2)>=0)
163
return mulqab(Q, subiu(q,1), ap, bp);
164
else
165
return mulqi(Q, lastq(Q), ap, bp);
166
}
167
else
168
{
169
*ap = subii(mulii(am, gcoeff(Q,2,2)),mulii(bm, gcoeff(Q,1,2)));
170
*bp = subii(mulii(bm, gcoeff(Q,1,1)),mulii(am, gcoeff(Q,2,1)));
171
*ap = addii(*ap, shifti(subii(a0, gcoeff(Q,2,2)), m));
172
*bp = addii(*bp, shifti(addii(b0, gcoeff(Q,2,1)), m));
173
if (expi(*ap) >= m+t)
174
return FIXUP0(Q, ap, bp, m+t);
175
else
176
return signe(gcoeff(Q,1,2))==0? Q: mulqi(Q, lastq(Q), ap, bp);
177
}
178
}
179
180
static long
181
magic_threshold(GEN a)
182
{ return (3+uexpi(a))>>1; }
183
184
static GEN
185
HGCD_basecase(GEN a, GEN b)
186
{
187
pari_sp av=avma;
188
long m = magic_threshold(a);
189
GEN u,u1,v,v1;
190
u1 = v = gen_0;
191
u = v1 = gen_1;
192
while (expi(b) >= m)
193
{
194
GEN r, q = dvmdii(a,b, &r);
195
a = b; b = r; swap(u,u1); swap(v,v1);
196
u = addii(mulii(u1, q), u);
197
v = addii(mulii(v1, q), v);
198
if (gc_needed(av,2))
199
{
200
if (DEBUGMEM>1) pari_warn(warnmem,"halfgcd (d = %ld)",lgefint(b));
201
gerepileall(av,6, &a,&b,&u1,&v1,&u,&v);
202
}
203
}
204
return gerepilecopy(av, mkvec3(mkmat22(u,u1,v,v1), a, b));
205
}
206
207
static GEN HGCD(GEN x, GEN y);
208
209
/*
210
Based on
211
Klaus Thull and Chee K. Yap,
212
A unified approach to HGCD algorithms for polynomials andintegers,
213
1990, Manuscript.
214
URL: http://cs.nyu.edu/cs/faculty/yap/papers.
215
*/
216
217
static GEN
218
HGCD_split(GEN a, GEN b)
219
{
220
pari_sp av = avma;
221
long m = magic_threshold(a), t, l, k, tp;
222
GEN a0, b0, ap, bp, c, d, c0, d0, cp, dp, R, S, T, q, r;
223
if (signe(b) < 0 || cmpii(a,b)<0) pari_err_BUG("HGCD_split");
224
if (expi(b) < m)
225
return gerepilecopy(av, mkvec3(matid2(), a, b));
226
a0 = addiu(shifti(a, -m), 1);
227
if (cmpiu(a0,7) <= 0)
228
{
229
R = FIXUP0(matid2(), &a, &b, m);
230
return gerepilecopy(av, mkvec3(R, a, b));
231
}
232
b0 = shifti(b,-m);
233
t = magic_threshold(a0);
234
R = FIXUP1(HGCD(a0,b0),a, b, m, t, &ap, &bp);
235
if (expi(bp) < m)
236
return gerepilecopy(av, mkvec3(R, ap, bp));
237
q = dvmdii(ap, bp, &r);
238
c = bp; d = r;
239
if (cmpiu(shifti(c,-m),6) <= 0)
240
{
241
R = FIXUP0(mulq(R, q), &c, &d, m);
242
return gerepilecopy(av, mkvec3(R, c, d));
243
}
244
l = uexpi(c);
245
k = 2*m-l-1; if (k<0) pari_err_BUG("halfgcd");
246
c0 = addiu(shifti(c, -k), 1); if (cmpiu(c0,8)<0) pari_err_BUG("halfgcd");
247
d0 = shifti(d, -k);
248
tp = magic_threshold(c0);
249
S = FIXUP1(HGCD(c0,d0), c, d, k, tp, &cp, &dp);
250
if (!(expi(cp)>=m+1 && m+1 > expi(dp))) pari_err_BUG("halfgcd");
251
T = FIXUP0(ZM2_mul(mulq(R, q), S), &cp, &dp, m);
252
return gerepilecopy(av, mkvec3(T, cp, dp));
253
}
254
255
static GEN
256
HGCD(GEN x, GEN y)
257
{
258
if (lgefint(y)-2 < HALFGCD_LIMIT)
259
return HGCD_basecase(x, y);
260
else
261
return HGCD_split(x, y);
262
}
263
264
static GEN
265
HGCD0(GEN x, GEN y)
266
{
267
if (signe(y) >= 0 && cmpii(x, y) >= 0)
268
return HGCD(x, y);
269
if (cmpii(x, y) < 0)
270
{
271
GEN M = HGCD0(y, x), Q = gel(M,1);
272
return mkvec3(mkmat22(gcoeff(Q,2,1),gcoeff(Q,2,2),gcoeff(Q,1,1),gcoeff(Q,1,2)),
273
gel(M,2),gel(M,3));
274
} /* Now y <= x*/
275
if (signe(x) <= 0)
276
{ /* y <= x <=0 */
277
GEN M = HGCD(negi(y), negi(x)), Q = gel(M,1);
278
return mkvec3(mkmat22(negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2)),
279
negi(gcoeff(Q,1,1)),negi(gcoeff(Q,1,2))),
280
gel(M,2),gel(M,3));
281
}
282
else /* y <= 0 <=x */
283
{
284
GEN M = HGCD0(x, negi(y)), Q = gel(M,1);
285
return mkvec3(mkmat22(gcoeff(Q,1,1),gcoeff(Q,1,2),negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2))),
286
gel(M,2),gel(M,3));
287
}
288
}
289
290
GEN
291
halfgcdii(GEN A, GEN B)
292
{
293
pari_sp av = avma;
294
GEN M, Q, a, b, m = absi_shallow(abscmpii(A, B)>0 ? A: B);
295
M = HGCD0(A,B); Q = gel(M,1); a = gel(M,2); b = gel(M,3);
296
while (signe(b) && cmpii(sqri(b), m) >= 0)
297
{
298
GEN r, q = dvmdii(a, b, &r);
299
a = b; b = r;
300
Q = mulq(Q, q);
301
}
302
return gerepilecopy(av, mkvec2(ZM_inv2(Q),mkcol2(a,b)));
303
}
304
305