Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
#line 2 "../src/kernel/none/gcd.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/* assume y > x > 0. return y mod x */16static ulong17resiu(GEN y, ulong x)18{19long i, ly = lgefint(y);20ulong xi = get_Fl_red(x);21LOCAL_HIREMAINDER;2223hiremainder = 0;24for (i=2; i<ly; i++) (void)divll_pre(y[i],x,xi);25return hiremainder;26}2728/* Assume x>y>0, both of them odd. return x-y if x=y mod 4, x+y otherwise */29static void30gcd_plus_minus(GEN x, GEN y, GEN res)31{32pari_sp av = avma;33long lx = lgefint(x)-1;34long ly = lgefint(y)-1, lt,m,i;35GEN t;3637if ((x[lx]^y[ly]) & 3) /* x != y mod 4*/38t = addiispec(x+2,y+2,lx-1,ly-1);39else40t = subiispec(x+2,y+2,lx-1,ly-1);4142lt = lgefint(t)-1; while (!t[lt]) lt--;43m = vals(t[lt]); lt++;44if (m == 0) /* 2^32 | t */45{46for (i = 2; i < lt; i++) res[i] = t[i];47}48else if (t[2] >> m)49{50shift_right(res,t, 2,lt, 0,m);51}52else53{54lt--; t++;55shift_right(res,t, 2,lt, t[1],m);56}57res[1] = evalsigne(1)|evallgefint(lt);58set_avma(av);59}6061/* uses modified right-shift binary algorithm now --GN 1998Jul23 */62static GEN63gcdii_basecase(GEN a, GEN b)64{65long v, w;66pari_sp av;67GEN t, p1;6869switch (abscmpii(a,b))70{71case 0: return absi(a);72case -1: swap(a,b);73}74if (!signe(b)) return absi(a);75/* here |a|>|b|>0. Try single precision first */76if (lgefint(a)==3)77return igcduu((ulong)a[2], (ulong)b[2]);78if (lgefint(b)==3)79{80ulong u = resiu(a,(ulong)b[2]);81if (!u) return absi(b);82return igcduu((ulong)b[2], u);83}8485/* larger than gcd: "set_avma(av)" gerepile (erasing t) is valid */86av = avma; (void)new_chunk(lgefint(b)); /* HACK */87t = remii(a,b);88if (!signe(t)) { set_avma(av); return absi(b); }8990a = b; b = t;91v = vali(a); a = shifti(a,-v); setabssign(a);92w = vali(b); b = shifti(b,-w); setabssign(b);93if (w < v) v = w;94switch(abscmpii(a,b))95{96case 0: set_avma(av); a = shifti(a,v); return a;97case -1: swap(a,b);98}99if (is_pm1(b)) { set_avma(av); return int2n(v); }100101/* we have three consecutive memory locations: a,b,t.102* All computations are done in place */103104/* a and b are odd now, and a>b>1 */105while (lgefint(a) > 3)106{107/* if a=b mod 4 set t=a-b, otherwise t=a+b, then strip powers of 2 */108/* so that t <= (a+b)/4 < a/2 */109gcd_plus_minus(a,b, t);110if (is_pm1(t)) { set_avma(av); return int2n(v); }111switch(abscmpii(t,b))112{113case -1: p1 = a; a = b; b = t; t = p1; break;114case 1: swap(a,t); break;115case 0: set_avma(av); b = shifti(b,v); return b;116}117}118{119long r[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0};120r[2] = (long) gcduodd((ulong)b[2], (ulong)a[2]);121set_avma(av); return shifti(r,v);122}123}124125GEN126gcdii(GEN x, GEN y)127{128pari_sp av=avma;129while (lgefint(y)-2 >= GCD_HALFGCD_LIMIT)130{131GEN M = HGCD0(x,y);132x = gel(M,2); y = gel(M,3);133if (signe(y) && expi(y)<magic_threshold(x))134{135swap(x,y);136y = remii(y,x);137}138if (gc_needed(av, 1)) gerepileall(av,2,&x,&y);139}140return gerepileuptoint(av, gcdii_basecase(x,y));141}142143144