From: Mark Wooding Date: Tue, 7 Feb 2006 19:32:47 +0000 (+0000) Subject: gcd: General tidying up. X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/commitdiff_plain/cf76bcbb2097c36912fae1c8a6cc77f0ce4bfafd gcd: General tidying up. * Implement a GCD algorithm in calc/gfx.cal (partly to help with testing the Python bindings). * Clean up the MP and GF implementations: expunge incorrect commentary and redundant code. --- diff --git a/calc/gfx.cal b/calc/gfx.cal index 45f534b..e38f4b7 100644 --- a/calc/gfx.cal +++ b/calc/gfx.cal @@ -97,24 +97,36 @@ define gf_mod(x, y) return gf(l[[1]]); } -define gf_inv(a, b) +define gf_gcd(a, b) { - local g, x, y, X, Y, u, v, t, q, r; - x = gf(1); X = gf(0); - y = gf(0); Y = gf(1); - - if (b == gf(0)) { g = a; } else if (a == gf(0)) { g = b; } + local swap = 0; + local g, x = 1, X = 0, y = 0, Y = 1, q, r, t; + if (a.x < b.x) { + t = a; a = b; b = t; + swap = 1; + } + if (b == gf(0)) + g = a; else { while (b != gf(0)) { - q = gf_div(b, a); r = gf_mod(b, a); + q = gf_div(a, b); r = gf_mod(a, b); t = X * q + x; x = X; X = t; t = Y * q + y; y = Y; Y = t; - b = a; a = r; + a = b; b = r; } g = a; } - if (g != gf(1)) quit "not coprime in gf_inv"; - return Y; + if (swap) { + t = x; x = y; y = t; + } + return list(g, x, y); +} + +define gf_inv(a, b) +{ + local l = gf_gcd(b, a); + if (l[[0]] != gf(1)) quit "not coprime in gf_inv"; + return l[[2]]; } /*----- That's all, folks -------------------------------------------------*/ diff --git a/gf-gcd.c b/gf-gcd.c index 622679a..048d29d 100644 --- a/gf-gcd.c +++ b/gf-gcd.c @@ -106,15 +106,7 @@ void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) return; } - /* --- Take a reference to the arguments --- */ - - a = MP_COPY(a); - b = MP_COPY(b); - - /* --- Make sure @a@ and @b@ are not both even --- */ - - MP_SPLIT(a); a->f &= ~MP_NEG; - MP_SPLIT(b); b->f &= ~MP_NEG; + /* --- Main extended Euclidean algorithm --- */ u = MP_COPY(a); v = MP_COPY(b); @@ -124,10 +116,10 @@ void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) gf_div(&q, &u, u, v); if (f & f_ext) { t = gf_mul(MP_NEW, X, q); - t = gf_add(t, x, t); + t = gf_add(t, t, x); MP_DROP(x); x = X; X = t; t = gf_mul(MP_NEW, Y, q); - t = gf_add(t, y, t); + t = gf_add(t, t, y); MP_DROP(y); y = Y; Y = t; } t = u; u = v; v = t; @@ -172,7 +164,6 @@ void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) MP_DROP(v); MP_DROP(X); MP_DROP(Y); - MP_DROP(a); MP_DROP(b); } /* -- @gf_modinv@ --- * diff --git a/mp-gcd.c b/mp-gcd.c index 5312400..c78181f 100644 --- a/mp-gcd.c +++ b/mp-gcd.c @@ -118,19 +118,19 @@ void mp_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b) return; } - /* --- Take a reference to the arguments --- */ + /* --- Force the signs on the arguments and take copies --- */ a = MP_COPY(a); b = MP_COPY(b); - /* --- Make sure @a@ and @b@ are not both even --- */ - MP_SPLIT(a); a->f &= ~MP_NEG; MP_SPLIT(b); b->f &= ~MP_NEG; u = MP_COPY(a); v = MP_COPY(b); + /* --- Main extended Euclidean algorithm --- */ + while (!MP_ZEROP(v)) { mp *t; mp_div(&q, &u, u, v);