=================================================================== RCS file: /home/cvs/OpenXM_contrib/gmp/mpn/generic/Attic/jacbase.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -p -r1.1.1.1 -r1.1.1.2 --- OpenXM_contrib/gmp/mpn/generic/Attic/jacbase.c 2000/09/09 14:12:25 1.1.1.1 +++ OpenXM_contrib/gmp/mpn/generic/Attic/jacbase.c 2003/08/25 16:06:20 1.1.1.2 @@ -1,10 +1,9 @@ /* mpn_jacobi_base -- limb/limb Jacobi symbol with restricted arguments. THIS INTERFACE IS PRELIMINARY AND MIGHT DISAPPEAR OR BE SUBJECT TO - INCOMPATIBLE CHANGES IN A FUTURE RELEASE OF GMP. */ + INCOMPATIBLE CHANGES IN A FUTURE RELEASE OF GMP. -/* -Copyright (C) 1999, 2000 Free Software Foundation, Inc. +Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU MP Library. @@ -21,18 +20,23 @@ License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -MA 02111-1307, USA. */ +MA 02111-1307, USA. */ #include "gmp.h" #include "gmp-impl.h" #include "longlong.h" -#if COUNT_TRAILING_ZEROS_TIME <= 7 -/* If count_trailing_zeros is fast, use it. - K7 at 7 cycles and P6 at 2 are good here. K6 at 12-27 and P5 at 18-42 - are not. The default 15 in longlong.h is meant to mean not good here. */ +/* Use the simple loop by default. The generic count_trailing_zeros is not + very fast, and the extra trickery of method 3 has proven to be less use + than might have been though. */ +#ifndef JACOBI_BASE_METHOD +#define JACOBI_BASE_METHOD 2 +#endif + +/* Use count_trailing_zeros. */ +#if JACOBI_BASE_METHOD == 1 #define PROCESS_TWOS_ANY \ { \ mp_limb_t twos; \ @@ -40,33 +44,70 @@ MA 02111-1307, USA. */ result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b); \ a >>= twos; \ } - #define PROCESS_TWOS_EVEN PROCESS_TWOS_ANY +#endif -#else -/* Use a loop instead. With "a" uniformly distributed there will usually be - only a few trailing zeros. - - Unfortunately the branch for the while loop here will be on a 50/50 - chance of a 1 or 0, which is bad for branch prediction. */ - +/* Use a simple loop. A disadvantage of this is that there's a branch on a + 50/50 chance of a 0 or 1 low bit. */ +#if JACOBI_BASE_METHOD == 2 #define PROCESS_TWOS_EVEN \ { \ int two; \ two = JACOBI_TWO_U_BIT1 (b); \ do \ { \ - a >>= 1; \ - result_bit1 ^= two; \ - ASSERT (a != 0); \ + a >>= 1; \ + result_bit1 ^= two; \ + ASSERT (a != 0); \ } \ while ((a & 1) == 0); \ } - #define PROCESS_TWOS_ANY \ if ((a & 1) == 0) \ PROCESS_TWOS_EVEN; +#endif +/* Process one bit arithmetically, then a simple loop. This cuts the loop + condition down to a 25/75 chance, which should branch predict better. + The CPU will need a reasonable variable left shift. */ +#if JACOBI_BASE_METHOD == 3 +#define PROCESS_TWOS_EVEN \ + { \ + int two, mask, shift; \ + \ + two = JACOBI_TWO_U_BIT1 (b); \ + mask = (~a & 2); \ + a >>= 1; \ + \ + shift = (~a & 1); \ + a >>= shift; \ + result_bit1 ^= two ^ (two & mask); \ + \ + while ((a & 1) == 0) \ + { \ + a >>= 1; \ + result_bit1 ^= two; \ + ASSERT (a != 0); \ + } \ + } +#define PROCESS_TWOS_ANY \ + { \ + int two, mask, shift; \ + \ + two = JACOBI_TWO_U_BIT1 (b); \ + shift = (~a & 1); \ + a >>= shift; \ + \ + mask = shift << 1; \ + result_bit1 ^= (two & mask); \ + \ + while ((a & 1) == 0) \ + { \ + a >>= 1; \ + result_bit1 ^= two; \ + ASSERT (a != 0); \ + } \ + } #endif @@ -74,7 +115,7 @@ MA 02111-1307, USA. */ with a restricted range of inputs accepted, namely b>1, b odd, and a<=b. The initial result_bit1 is taken as a parameter for the convenience of - mpz_kronecker_zi_ui() et al. The sign changes both here and in those + mpz_kronecker_ui() et al. The sign changes both here and in those routines accumulate nicely in bit 1, see the JACOBI macros. The return value here is the normal +1, 0, or -1. Note that +1 and -1 @@ -89,14 +130,7 @@ MA 02111-1307, USA. */ relaxed. All the places this is used currently call with a<=b though. */ int -#if __STDC__ mpn_jacobi_base (mp_limb_t a, mp_limb_t b, int result_bit1) -#else -mpn_jacobi_base (a, b, result_bit1) - mp_limb_t a; - mp_limb_t b; - int result_bit1; -#endif { ASSERT (b & 1); /* b odd */ ASSERT (b != 1); @@ -116,15 +150,15 @@ mpn_jacobi_base (a, b, result_bit1) do { - /* working on (a/b), a,b odd, a>=b */ - ASSERT (a & 1); - ASSERT (b & 1); - ASSERT (a >= b); + /* working on (a/b), a,b odd, a>=b */ + ASSERT (a & 1); + ASSERT (b & 1); + ASSERT (a >= b); if ((a -= b) == 0) return 0; - PROCESS_TWOS_EVEN; + PROCESS_TWOS_EVEN; if (a == 1) goto done; }