summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2001-01-07 01:19:12 +0100
committerKevin Ryde <user42@zip.com.au>2001-01-07 01:19:12 +0100
commitccc0c6f8739e3ce30e252de080bec00367bf8ed6 (patch)
treeaab64756f37f39015d01d8f602ec9fd2529e8690
parente9545f777eb657335eaae0aabdc639b125f82ffe (diff)
downloadgmp-ccc0c6f8739e3ce30e252de080bec00367bf8ed6.tar.gz
* mpz/kronzu.c, mpz/kronzs.c, mpz/kronuz.c, mpz/kronsz.c: Use
mpn_modexact_1_odd and new JACOBI macros, various rearrangements in support of this.
-rw-r--r--mpz/kronsz.c126
-rw-r--r--mpz/kronzs.c66
-rw-r--r--mpz/kronzu.c53
3 files changed, 135 insertions, 110 deletions
diff --git a/mpz/kronsz.c b/mpz/kronsz.c
index cf58a6d60..892ed2763 100644
--- a/mpz/kronsz.c
+++ b/mpz/kronsz.c
@@ -1,4 +1,4 @@
-/* mpz_si_kronecker -- Kronecker/Jacobi symbol. */
+/* mpz_si_kronecker -- long+mpz Kronecker/Jacobi symbol. */
/*
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
@@ -26,95 +26,89 @@ MA 02111-1307, USA.
#include "longlong.h"
+/* This implementation depends on BITS_PER_MP_LIMB being even, so that
+ (a/2)^BITS_PER_MP_LIMB = 1 and so there's no need to pay attention to how
+ many low zero limbs are stripped. */
+#if BITS_PER_MP_LIMB % 2 != 0
+Error, error, unsupported BITS_PER_MP_LIMB
+#endif
+
+
int
mpz_si_kronecker (long a, mpz_srcptr b)
{
- int b_abs_size;
- mp_srcptr b_ptr;
- mp_limb_t b_low;
+ mp_srcptr b_ptr = PTR(b);
+ mp_limb_t b_low = b_ptr[0];
+ int b_size = SIZ (b);
+ int b_abs_size = ABS (b_size);
+ mp_limb_t b_rem;
int twos;
int result_bit1;
- b_abs_size = ABSIZ (b);
if (b_abs_size == 0)
return JACOBI_S0 (a); /* (a/0) */
- b_ptr = PTR(b);
- b_low = b_ptr[0];
-
- /* (0/b) = 1 if b=+/-1, 0 otherwise */
- if (a == 0)
- return (b_abs_size == 1) & (b_low == 1);
+ /* account for the effect of the sign of b, then ignore it */
+ result_bit1 = JACOBI_BSGN_SS_BIT1 (a, b_size);
- /* account for the effect of the sign of b, so can then ignore it */
- result_bit1 = JACOBI_BSGN_SZ_BIT1 (a, b);
-
- if ((b_low & 1) == 0)
+ if (! (b_low & 1))
{
- /* b even */
-
- if ((a & 1) == 0)
- return 0; /* (a/b)=0 if both a,b even */
+ /* (even/even)=0, and (0/b)=0 for b!=+/-1 */
+ if (! (a & 1))
+ return 0;
- /* Require MP_BITS_PER_LIMB even, so that (a/2)^MP_BITS_PER_LIMB = 1,
- and so that therefore there's no need to account for how many zero
- limbs are stripped. */
- ASSERT ((BITS_PER_MP_LIMB & 1) == 0);
+ /* a odd, b even */
- MPN_STRIP_LOW_ZEROS_NOT_ZERO (b_ptr, b_abs_size);
- b_low = b_ptr[0];
-
- if ((b_low & 1) == 0)
+ /* establish shifted b_low for use with reciprocity below */
+ MPN_STRIP_LOW_ZEROS_NOT_ZERO (b_ptr, b_abs_size, b_low);
+ if (! (b_low & 1))
{
- /* odd a, even b */
-
- mp_limb_t b_shl_bit1;
-
- count_trailing_zeros (twos, b_low);
-
- /* b_shl_bit1 is b>>twos, but with only bit 1 guaranteed */
- if (twos == BITS_PER_MP_LIMB-1)
- b_shl_bit1 = (b_abs_size == 1) ? 0 : (b_ptr[1] << 1);
+ if (b_low == MP_LIMB_T_HIGHBIT)
+ {
+ if (b_abs_size == 1)
+ {
+ /* (a/0x80000000) = (a/2)^(BPML-1) */
+ result_bit1 ^= JACOBI_TWOS_U_BIT1 (BITS_PER_MP_LIMB-1, a);
+ return JACOBI_BIT1_TO_PN (result_bit1);
+ }
+
+ /* b_abs_size > 1 */
+ b_low = b_ptr[1] << 1;
+ }
else
- b_shl_bit1 = (b_low >> twos);
-
- result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_shl_bit1);
- a = ABS(a);
+ {
+ count_trailing_zeros (twos, b_low);
+ b_low >>= twos;
+ }
+ }
+ }
+ else
+ {
+ /* b odd */
- if (a == 1)
- return JACOBI_BIT1_TO_PN (result_bit1); /* (1/b)=1 */
+ /* (0/b)=1 for b=+/-1, 0 otherwise */
+ if (a == 0)
+ return (b_abs_size == 1 && b_low == 1);
- /* twos (a/2), reciprocity to (b/a), and (b/a) = (b mod a / b) */
- return mpn_jacobi_base (mpn_mod_1_rshift (b_ptr, b_abs_size,
- twos, a),
- a,
- result_bit1
- ^ JACOBI_TWOS_U_BIT1 (twos, a)
- ^ JACOBI_RECIP_UU_BIT1 (a, b_shl_bit1));
+ if (! (a & 1))
+ {
+ /* a even, b odd */
+ count_trailing_zeros (twos, a);
+ a >>= twos;
+ /* (a*2^n/b) = (a/b) * twos(n,a) */
+ result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b_low);
}
}
- /* b odd */
-
result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_low);
a = ABS(a);
- /* (a/1) = 1 for any a */
- if (b_abs_size == 1 && b_low == 1)
- return JACOBI_BIT1_TO_PN (result_bit1);
-
- /* Note a is cast to unsigned because 0x80..00 doesn't fit in a signed. */
- if ((a & 1) == 0)
- {
- count_trailing_zeros (twos, a);
- a = ((unsigned long) a) >> twos;
- result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b_low);
- }
-
if (a == 1)
return JACOBI_BIT1_TO_PN (result_bit1); /* (1/b)=1 */
- /* reciprocity to (b/a), and (b/a) == (b mod a / a) */
- return mpn_jacobi_base (mpn_mod_1 (b_ptr, b_abs_size, a), a,
- result_bit1 ^ JACOBI_RECIP_UU_BIT1 (a, b_low));
+ /* (a/b*2^n) = (b*2^n mod a / a) * recip(a,b) */
+ JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, b_rem, b_ptr, b_abs_size,
+ (unsigned long) a);
+ result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a, b_low);
+ return mpn_jacobi_base (b_rem, (mp_limb_t) (unsigned long) a, result_bit1);
}
diff --git a/mpz/kronzs.c b/mpz/kronzs.c
index 6bd7ef441..6089cd0c8 100644
--- a/mpz/kronzs.c
+++ b/mpz/kronzs.c
@@ -1,4 +1,4 @@
-/* mpz_kronecker_si -- Kronecker/Jacobi symbol. */
+/* mpz_kronecker_si -- mpz+long Kronecker/Jacobi symbol. */
/*
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
@@ -26,43 +26,59 @@ MA 02111-1307, USA.
#include "longlong.h"
-/* This function is expected to be often used with b odd, so there's a test
- for this before invoking count_trailing_zeros().
+/* This implementation depends on BITS_PER_MP_LIMB being even, so that
+ (a/2)^BITS_PER_MP_LIMB = 1 and so there's no need to pay attention to how
+ many low zero limbs are stripped. */
+#if BITS_PER_MP_LIMB % 2 != 0
+Error, error, unsupported BITS_PER_MP_LIMB
+#endif
- After the absolute value of b is established it's treated as an unsigned
+
+/* After the absolute value of b is established it's treated as an unsigned
long, because 0x80..00 doesn't fit in a signed long. */
int
mpz_kronecker_si (mpz_srcptr a, long b)
{
- int result_bit1;
- int twos;
+ mp_srcptr a_ptr = PTR(a);
+ int a_size = SIZ(a);
+ mp_limb_t a_rem;
+ int result_bit1;
+
+ if (b & 1)
+ {
+ result_bit1 = JACOBI_BSGN_SS_BIT1 (a_size, b);
+ }
+ else
+ {
+ mp_limb_t a_low = a_ptr[0];
+ int twos;
+
+ if (b == 0)
+ return JACOBI_LS0 (a_low, a_size); /* (a/0) */
+
+ if (! (a_low & 1))
+ return 0; /* (even/even)=0 */
- if (b == 0)
- return JACOBI_Z0 (a);
+ /* (a/2)=(2/a) for a odd */
+ count_trailing_zeros (twos, b);
+ b >>= twos;
+ result_bit1 = (JACOBI_TWOS_U_BIT1 (twos, a_low)
+ ^ JACOBI_BSGN_SS_BIT1 (a_size, b));
+ }
- result_bit1 = JACOBI_BSGN_ZS_BIT1(a, b);
b = ABS (b);
if (b == 1)
- return JACOBI_BIT1_TO_PN (result_bit1); /* (a/1) = 1 for any a */
+ return JACOBI_BIT1_TO_PN (result_bit1); /* (a/1)=1 for any a */
- if (b & 1)
- return mpn_jacobi_base (mpz_fdiv_ui (a, b), b, result_bit1);
-
- /* result 0 if both a,b even */
- if (mpz_even_p (a))
- return 0;
+ result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a_size, b);
+ a_size = ABS(a_size);
- /* (a/2)=(2/a) when a odd */
- count_trailing_zeros (twos, b);
- result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, PTR(a)[0]);
-
- b = ((unsigned long) b) >> twos;
- if (b == 1)
- return JACOBI_BIT1_TO_PN (result_bit1);
- else
- return mpn_jacobi_base (mpz_fdiv_ui (a, b), b, result_bit1);
+ /* (a/b) = (a mod b / b) */
+ JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, a_rem, a_ptr, a_size,
+ (unsigned long) b);
+ return mpn_jacobi_base (a_rem, (mp_limb_t) (unsigned long) b, result_bit1);
}
diff --git a/mpz/kronzu.c b/mpz/kronzu.c
index b6681fec8..11e552f91 100644
--- a/mpz/kronzu.c
+++ b/mpz/kronzu.c
@@ -1,4 +1,4 @@
-/* mpz_kronecker_ui -- Kronecker/Jacobi symbol. */
+/* mpz_kronecker_ui -- mpz+ulong Kronecker/Jacobi symbol. */
/*
Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
@@ -26,35 +26,50 @@ MA 02111-1307, USA.
#include "longlong.h"
-/* This function is expected to be often used with b an odd prime, so the
- code for odd b is nice and short. */
+/* This implementation depends on BITS_PER_MP_LIMB being even, so that
+ (a/2)^BITS_PER_MP_LIMB = 1 and so there's no need to pay attention to how
+ many low zero limbs are stripped. */
+#if BITS_PER_MP_LIMB % 2 != 0
+Error, error, unsupported BITS_PER_MP_LIMB
+#endif
+
int
mpz_kronecker_ui (mpz_srcptr a, unsigned long b)
{
- int twos;
+ mp_srcptr a_ptr = PTR(a);
+ int a_size = SIZ(a);
+ mp_limb_t a_rem;
+ int result_bit1;
if (b & 1)
{
- if (b != 1)
- return mpn_jacobi_base (mpz_fdiv_ui (a, b), b, 0);
- else
- return 1; /* (a/1)=1 for any a */
+ result_bit1 = JACOBI_ASGN_SU_BIT1 (a_size, b);
}
+ else
+ {
+ mp_limb_t a_low = a_ptr[0];
+ int twos;
- if (b == 0)
- return JACOBI_Z0 (a);
+ if (b == 0)
+ return JACOBI_LS0 (a_low, a_size); /* (a/0) */
- /* (a/2)=0 if a even */
- if (mpz_even_p (a))
- return 0;
+ if (! (a_low & 1))
+ return 0; /* (even/even)=0 */
+
+ /* (a/2)=(2/a) for a odd */
+ count_trailing_zeros (twos, b);
+ b >>= twos;
+ result_bit1 = (JACOBI_TWOS_U_BIT1 (twos, a_low)
+ ^ JACOBI_ASGN_SU_BIT1 (a_size, b));
+ }
- /* (a/2)=(2/a) when a odd */
- count_trailing_zeros (twos, b);
- b >>= twos;
if (b == 1)
- return JACOBI_TWOS_U (twos, PTR(a)[0]);
+ return JACOBI_BIT1_TO_PN (result_bit1); /* (a/1)=1 for any a */
+
+ a_size = ABS(a_size);
- return mpn_jacobi_base (mpz_fdiv_ui (a, b), b,
- JACOBI_TWOS_U_BIT1(twos, PTR(a)[0]));
+ /* (a/b) = (a mod b / b) */
+ JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, a_rem, a_ptr, a_size, b);
+ return mpn_jacobi_base (a_rem, (mp_limb_t) b, result_bit1);
}