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/invmod.c"
2
/* Copyright (C) 2003 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
/*==================================
17
* invmod(a,b,res)
18
*==================================
19
* If a is invertible, return 1, and set res = a^{ -1 }
20
* Otherwise, return 0, and set res = gcd(a,b)
21
*
22
* This is sufficiently different from bezout() to be implemented separately
23
* instead of having a bunch of extra conditionals in a single function body
24
* to meet both purposes.
25
*/
26
27
#ifdef INVMOD_PARI
28
INLINE int
29
invmod_pari(GEN a, GEN b, GEN *res)
30
#else
31
int
32
invmod(GEN a, GEN b, GEN *res)
33
#endif
34
{
35
GEN v,v1,d,d1,q,r;
36
pari_sp av, av1;
37
long s;
38
ulong g;
39
ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */
40
int lhmres; /* Lehmer stage return value */
41
42
if (!signe(b)) { *res=absi(a); return 0; }
43
av = avma;
44
if (lgefint(b) == 3) /* single-word affair */
45
{
46
ulong d1 = umodiu(a, uel(b,2));
47
if (d1 == 0)
48
{
49
if (b[2] == 1L)
50
{ *res = gen_0; return 1; }
51
else
52
{ *res = absi(b); return 0; }
53
}
54
g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s);
55
set_avma(av);
56
if (g != 1UL) { *res = utoipos(g); return 0; }
57
xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv;
58
*res = utoipos(xv); return 1;
59
}
60
61
(void)new_chunk(lgefint(b));
62
d = absi_shallow(b); d1 = modii(a,d);
63
64
v=gen_0; v1=gen_1; /* general case */
65
av1 = avma;
66
67
while (lgefint(d) > 3 && signe(d1))
68
{
69
lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX);
70
if (lhmres != 0) /* check progress */
71
{ /* apply matrix */
72
if (lhmres == 1 || lhmres == -1)
73
{
74
if (xv1 == 1)
75
{
76
r = subii(d,d1); d=d1; d1=r;
77
a = subii(v,v1); v=v1; v1=a;
78
}
79
else
80
{
81
r = subii(d, mului(xv1,d1)); d=d1; d1=r;
82
a = subii(v, mului(xv1,v1)); v=v1; v1=a;
83
}
84
}
85
else
86
{
87
r = subii(muliu(d,xu), muliu(d1,xv));
88
a = subii(muliu(v,xu), muliu(v1,xv));
89
d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
90
v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a;
91
if (lhmres&1) { togglesign(d); togglesign(v); }
92
else { togglesign(d1); togglesign(v1); }
93
}
94
}
95
96
if (lhmres <= 0 && signe(d1))
97
{
98
q = dvmdii(d,d1,&r);
99
a = subii(v,mulii(q,v1));
100
v=v1; v1=a;
101
d=d1; d1=r;
102
}
103
if (gc_needed(av,1))
104
{
105
if(DEBUGMEM>1) pari_warn(warnmem,"invmod");
106
gerepileall(av1, 4, &d,&d1,&v,&v1);
107
}
108
} /* end while */
109
110
/* Postprocessing - final sprint */
111
if (signe(d1))
112
{
113
/* Assertions: lgefint(d)==lgefint(d1)==3, and
114
* gcd(d,d1) is nonzero and fits into one word
115
*/
116
g = xxgcduu(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s);
117
if (g != 1UL) { set_avma(av); *res = utoipos(g); return 0; }
118
/* (From the xgcduu() blurb:)
119
* For finishing the multiword modinv, we now have to multiply the
120
* returned matrix (with properly adjusted signs) onto the values
121
* v' and v1' previously obtained from the multiword division steps.
122
* Actually, it is sufficient to take the scalar product of [v',v1']
123
* with [u1,-v1], and change the sign if s==1.
124
*/
125
v = subii(muliu(v,xu1),muliu(v1,xv1));
126
if (s > 0) setsigne(v,-signe(v));
127
set_avma(av); *res = modii(v,b); return 1;
128
}
129
/* get here when the final sprint was skipped (d1 was zero already) */
130
set_avma(av);
131
if (!equalii(d,gen_1)) { *res = icopy(d); return 0; }
132
*res = modii(v,b); return 1;
133
}
134
135