diff options
Diffstat (limited to 'ghc/runtime/gmp/mpz_gcdext.c')
-rw-r--r-- | ghc/runtime/gmp/mpz_gcdext.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/ghc/runtime/gmp/mpz_gcdext.c b/ghc/runtime/gmp/mpz_gcdext.c new file mode 100644 index 0000000000..183b9bd197 --- /dev/null +++ b/ghc/runtime/gmp/mpz_gcdext.c @@ -0,0 +1,80 @@ +/* mpz_gcdext(g, s, t, a, b) -- Set G to gcd(a, b), and S and T such that + g = as + bt. + +Copyright (C) 1991 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +The GNU MP Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU MP Library; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Botch: SLOW! */ + +void +#ifdef __STDC__ +mpz_gcdext (MP_INT *g, MP_INT *s, MP_INT *t, const MP_INT *a, const MP_INT *b) +#else +mpz_gcdext (g, s, t, a, b) + MP_INT *g; + MP_INT *s; + MP_INT *t; + const MP_INT *a; + const MP_INT *b; +#endif +{ + MP_INT s0, s1, q, r, x, d0, d1; + + mpz_init_set_ui (&s0, 1); + mpz_init_set_ui (&s1, 0); + mpz_init (&q); + mpz_init (&r); + mpz_init (&x); + mpz_init_set (&d0, a); + mpz_init_set (&d1, b); + + while (d1.size != 0) + { + mpz_divmod (&q, &r, &d0, &d1); + mpz_set (&d0, &d1); + mpz_set (&d1, &r); + + mpz_mul (&x, &s1, &q); + mpz_sub (&x, &s0, &x); + mpz_set (&s0, &s1); + mpz_set (&s1, &x); + } + + if (t != NULL) + { + mpz_mul (&x, &s0, a); + mpz_sub (&x, &d0, &x); + if (b->size == 0) + t->size = 0; + else + mpz_div (t, &x, b); + } + mpz_set (s, &s0); + mpz_set (g, &d0); + + mpz_clear (&s0); + mpz_clear (&s1); + mpz_clear (&q); + mpz_clear (&r); + mpz_clear (&x); + mpz_clear (&d0); + mpz_clear (&d1); +} |