Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
#line 2 "../src/kernel/none/invmod.c"1/* Copyright (C) 2003 The PARI group.23This file is part of the PARI/GP package.45PARI/GP is free software; you can redistribute it and/or modify it under the6terms of the GNU General Public License as published by the Free Software7Foundation; either version 2 of the License, or (at your option) any later8version. It is distributed in the hope that it will be useful, but WITHOUT9ANY WARRANTY WHATSOEVER.1011Check the License for details. You should have received a copy of it, along12with the package; see the file 'COPYING'. If not, write to the Free Software13Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1415/*==================================16* invmod(a,b,res)17*==================================18* If a is invertible, return 1, and set res = a^{ -1 }19* Otherwise, return 0, and set res = gcd(a,b)20*21* This is sufficiently different from bezout() to be implemented separately22* instead of having a bunch of extra conditionals in a single function body23* to meet both purposes.24*/2526#ifdef INVMOD_PARI27INLINE int28invmod_pari(GEN a, GEN b, GEN *res)29#else30int31invmod(GEN a, GEN b, GEN *res)32#endif33{34GEN v,v1,d,d1,q,r;35pari_sp av, av1;36long s;37ulong g;38ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */39int lhmres; /* Lehmer stage return value */4041if (!signe(b)) { *res=absi(a); return 0; }42av = avma;43if (lgefint(b) == 3) /* single-word affair */44{45ulong d1 = umodiu(a, uel(b,2));46if (d1 == 0)47{48if (b[2] == 1L)49{ *res = gen_0; return 1; }50else51{ *res = absi(b); return 0; }52}53g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s);54set_avma(av);55if (g != 1UL) { *res = utoipos(g); return 0; }56xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv;57*res = utoipos(xv); return 1;58}5960(void)new_chunk(lgefint(b));61d = absi_shallow(b); d1 = modii(a,d);6263v=gen_0; v1=gen_1; /* general case */64av1 = avma;6566while (lgefint(d) > 3 && signe(d1))67{68lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX);69if (lhmres != 0) /* check progress */70{ /* apply matrix */71if (lhmres == 1 || lhmres == -1)72{73if (xv1 == 1)74{75r = subii(d,d1); d=d1; d1=r;76a = subii(v,v1); v=v1; v1=a;77}78else79{80r = subii(d, mului(xv1,d1)); d=d1; d1=r;81a = subii(v, mului(xv1,v1)); v=v1; v1=a;82}83}84else85{86r = subii(muliu(d,xu), muliu(d1,xv));87a = subii(muliu(v,xu), muliu(v1,xv));88d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;89v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a;90if (lhmres&1) { togglesign(d); togglesign(v); }91else { togglesign(d1); togglesign(v1); }92}93}9495if (lhmres <= 0 && signe(d1))96{97q = dvmdii(d,d1,&r);98a = subii(v,mulii(q,v1));99v=v1; v1=a;100d=d1; d1=r;101}102if (gc_needed(av,1))103{104if(DEBUGMEM>1) pari_warn(warnmem,"invmod");105gerepileall(av1, 4, &d,&d1,&v,&v1);106}107} /* end while */108109/* Postprocessing - final sprint */110if (signe(d1))111{112/* Assertions: lgefint(d)==lgefint(d1)==3, and113* gcd(d,d1) is nonzero and fits into one word114*/115g = xxgcduu(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s);116if (g != 1UL) { set_avma(av); *res = utoipos(g); return 0; }117/* (From the xgcduu() blurb:)118* For finishing the multiword modinv, we now have to multiply the119* returned matrix (with properly adjusted signs) onto the values120* v' and v1' previously obtained from the multiword division steps.121* Actually, it is sufficient to take the scalar product of [v',v1']122* with [u1,-v1], and change the sign if s==1.123*/124v = subii(muliu(v,xu1),muliu(v1,xv1));125if (s > 0) setsigne(v,-signe(v));126set_avma(av); *res = modii(v,b); return 1;127}128/* get here when the final sprint was skipped (d1 was zero already) */129set_avma(av);130if (!equalii(d,gen_1)) { *res = icopy(d); return 0; }131*res = modii(v,b); return 1;132}133134135