[BACK]Return to jacbase.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / generic

Annotation of OpenXM_contrib/gmp/mpn/generic/jacbase.c, Revision 1.1.1.2

1.1       maekawa     1: /* mpn_jacobi_base -- limb/limb Jacobi symbol with restricted arguments.
                      2:
                      3:    THIS INTERFACE IS PRELIMINARY AND MIGHT DISAPPEAR OR BE SUBJECT TO
1.1.1.2 ! ohara       4:    INCOMPATIBLE CHANGES IN A FUTURE RELEASE OF GMP.
1.1       maekawa     5:
1.1.1.2 ! ohara       6: Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1.1       maekawa     7:
                      8: This file is part of the GNU MP Library.
                      9:
                     10: The GNU MP Library is free software; you can redistribute it and/or modify
                     11: it under the terms of the GNU Lesser General Public License as published by
                     12: the Free Software Foundation; either version 2.1 of the License, or (at your
                     13: option) any later version.
                     14:
                     15: The GNU MP Library is distributed in the hope that it will be useful, but
                     16: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     17: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     18: License for more details.
                     19:
                     20: You should have received a copy of the GNU Lesser General Public License
                     21: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     22: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
1.1.1.2 ! ohara      23: MA 02111-1307, USA. */
1.1       maekawa    24:
                     25: #include "gmp.h"
                     26: #include "gmp-impl.h"
                     27: #include "longlong.h"
                     28:
                     29:
1.1.1.2 ! ohara      30: /* Use the simple loop by default.  The generic count_trailing_zeros is not
        !            31:    very fast, and the extra trickery of method 3 has proven to be less use
        !            32:    than might have been though.  */
        !            33: #ifndef JACOBI_BASE_METHOD
        !            34: #define JACOBI_BASE_METHOD  2
        !            35: #endif
        !            36:
1.1       maekawa    37:
1.1.1.2 ! ohara      38: /* Use count_trailing_zeros.  */
        !            39: #if JACOBI_BASE_METHOD == 1
1.1       maekawa    40: #define PROCESS_TWOS_ANY                                \
                     41:   {                                                     \
                     42:     mp_limb_t  twos;                                    \
                     43:     count_trailing_zeros (twos, a);                     \
                     44:     result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b);        \
                     45:     a >>= twos;                                         \
                     46:   }
                     47: #define PROCESS_TWOS_EVEN  PROCESS_TWOS_ANY
1.1.1.2 ! ohara      48: #endif
1.1       maekawa    49:
1.1.1.2 ! ohara      50: /* Use a simple loop.  A disadvantage of this is that there's a branch on a
        !            51:    50/50 chance of a 0 or 1 low bit.  */
        !            52: #if JACOBI_BASE_METHOD == 2
1.1       maekawa    53: #define PROCESS_TWOS_EVEN               \
                     54:   {                                     \
                     55:     int  two;                           \
                     56:     two = JACOBI_TWO_U_BIT1 (b);        \
                     57:     do                                  \
                     58:       {                                 \
1.1.1.2 ! ohara      59:        a >>= 1;                        \
        !            60:        result_bit1 ^= two;             \
        !            61:        ASSERT (a != 0);                \
1.1       maekawa    62:       }                                 \
                     63:     while ((a & 1) == 0);               \
                     64:   }
                     65: #define PROCESS_TWOS_ANY        \
                     66:   if ((a & 1) == 0)             \
                     67:     PROCESS_TWOS_EVEN;
1.1.1.2 ! ohara      68: #endif
1.1       maekawa    69:
1.1.1.2 ! ohara      70: /* Process one bit arithmetically, then a simple loop.  This cuts the loop
        !            71:    condition down to a 25/75 chance, which should branch predict better.
        !            72:    The CPU will need a reasonable variable left shift.  */
        !            73: #if JACOBI_BASE_METHOD == 3
        !            74: #define PROCESS_TWOS_EVEN               \
        !            75:   {                                     \
        !            76:     int  two, mask, shift;              \
        !            77:                                         \
        !            78:     two = JACOBI_TWO_U_BIT1 (b);        \
        !            79:     mask = (~a & 2);                    \
        !            80:     a >>= 1;                            \
        !            81:                                         \
        !            82:     shift = (~a & 1);                   \
        !            83:     a >>= shift;                        \
        !            84:     result_bit1 ^= two ^ (two & mask);  \
        !            85:                                         \
        !            86:     while ((a & 1) == 0)                \
        !            87:       {                                 \
        !            88:        a >>= 1;                        \
        !            89:        result_bit1 ^= two;             \
        !            90:        ASSERT (a != 0);                \
        !            91:       }                                 \
        !            92:   }
        !            93: #define PROCESS_TWOS_ANY                \
        !            94:   {                                     \
        !            95:     int  two, mask, shift;              \
        !            96:                                         \
        !            97:     two = JACOBI_TWO_U_BIT1 (b);        \
        !            98:     shift = (~a & 1);                   \
        !            99:     a >>= shift;                        \
        !           100:                                         \
        !           101:     mask = shift << 1;                  \
        !           102:     result_bit1 ^= (two & mask);        \
        !           103:                                         \
        !           104:     while ((a & 1) == 0)                \
        !           105:       {                                 \
        !           106:        a >>= 1;                        \
        !           107:        result_bit1 ^= two;             \
        !           108:        ASSERT (a != 0);                \
        !           109:       }                                 \
        !           110:   }
1.1       maekawa   111: #endif
                    112:
                    113:
                    114: /* Calculate the value of the Jacobi symbol (a/b) of two mp_limb_t's, but
                    115:    with a restricted range of inputs accepted, namely b>1, b odd, and a<=b.
                    116:
                    117:    The initial result_bit1 is taken as a parameter for the convenience of
1.1.1.2 ! ohara     118:    mpz_kronecker_ui() et al.  The sign changes both here and in those
1.1       maekawa   119:    routines accumulate nicely in bit 1, see the JACOBI macros.
                    120:
                    121:    The return value here is the normal +1, 0, or -1.  Note that +1 and -1
                    122:    have bit 1 in the "BIT1" sense, which could be useful if the caller is
                    123:    accumulating it into some extended calculation.
                    124:
                    125:    Duplicating the loop body to avoid the MP_LIMB_T_SWAP(a,b) would be
                    126:    possible, but a couple of tests suggest it's not a significant speedup,
                    127:    and may even be a slowdown, so what's here is good enough for now.
                    128:
                    129:    Future: The code doesn't demand a<=b actually, so maybe this could be
                    130:    relaxed.  All the places this is used currently call with a<=b though.  */
                    131:
                    132: int
                    133: mpn_jacobi_base (mp_limb_t a, mp_limb_t b, int result_bit1)
                    134: {
                    135:   ASSERT (b & 1);  /* b odd */
                    136:   ASSERT (b != 1);
                    137:   ASSERT (a <= b);
                    138:
                    139:   if (a == 0)
                    140:     return 0;
                    141:
                    142:   PROCESS_TWOS_ANY;
                    143:   if (a == 1)
                    144:     goto done;
                    145:
                    146:   for (;;)
                    147:     {
                    148:       result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a, b);
                    149:       MP_LIMB_T_SWAP (a, b);
                    150:
                    151:       do
                    152:        {
1.1.1.2 ! ohara     153:          /* working on (a/b), a,b odd, a>=b */
        !           154:          ASSERT (a & 1);
        !           155:          ASSERT (b & 1);
        !           156:          ASSERT (a >= b);
1.1       maekawa   157:
                    158:          if ((a -= b) == 0)
                    159:            return 0;
                    160:
1.1.1.2 ! ohara     161:          PROCESS_TWOS_EVEN;
1.1       maekawa   162:          if (a == 1)
                    163:            goto done;
                    164:        }
                    165:       while (a >= b);
                    166:     }
                    167:
                    168:  done:
                    169:   return JACOBI_BIT1_TO_PN (result_bit1);
                    170: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>