[BACK]Return to modlinv.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / tune

Annotation of OpenXM_contrib/gmp/tune/modlinv.c, Revision 1.1.1.1

1.1       ohara       1: /* Alternate implementations of modlimb_invert to compare speeds. */
                      2:
                      3: /*
                      4: Copyright 2000, 2002 Free Software Foundation, Inc.
                      5:
                      6: This file is part of the GNU MP Library.
                      7:
                      8: The GNU MP Library is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU Lesser General Public License as published by
                     10: the Free Software Foundation; either version 2.1 of the License, or (at your
                     11: option) any later version.
                     12:
                     13: The GNU MP Library is distributed in the hope that it will be useful, but
                     14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     16: License for more details.
                     17:
                     18: You should have received a copy of the GNU Lesser General Public License
                     19: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     21: MA 02111-1307, USA.
                     22: */
                     23:
                     24: #include <stdio.h>
                     25: #include "gmp.h"
                     26: #include "gmp-impl.h"
                     27: #include "longlong.h"
                     28: #include "speed.h"
                     29:
                     30:
                     31: /* Like the standard version in gmp-impl.h, but with the expressions using a
                     32:    "1-" form.  This has the same number of steps, but "1-" is on the
                     33:    dependent chain, whereas the "2*" in the standard version isn't.
                     34:    Depending on the CPU this should be the same or a touch slower.  */
                     35:
                     36: #if BITS_PER_MP_LIMB <= 32
                     37: #define modlimb_invert_mul1(inv,n)                              \
                     38:   do {                                                          \
                     39:     mp_limb_t  __n = (n);                                       \
                     40:     mp_limb_t  __inv;                                           \
                     41:     ASSERT ((__n & 1) == 1);                                    \
                     42:     __inv = modlimb_invert_table[(__n&0xFF)/2]; /*  8 */        \
                     43:     __inv = (1 - __n * __inv) * __inv + __inv;  /* 16 */        \
                     44:     __inv = (1 - __n * __inv) * __inv + __inv;  /* 32 */        \
                     45:     ASSERT (__inv * __n == 1);                                  \
                     46:     (inv) = __inv;                                              \
                     47:   } while (0)
                     48: #endif
                     49:
                     50: #if BITS_PER_MP_LIMB > 32 && BITS_PER_MP_LIMB <= 64
                     51: #define modlimb_invert_mul1(inv,n)                              \
                     52:   do {                                                          \
                     53:     mp_limb_t  __n = (n);                                       \
                     54:     mp_limb_t  __inv;                                           \
                     55:     ASSERT ((__n & 1) == 1);                                    \
                     56:     __inv = modlimb_invert_table[(__n&0xFF)/2]; /*  8 */        \
                     57:     __inv = (1 - __n * __inv) * __inv + __inv;  /* 16 */        \
                     58:     __inv = (1 - __n * __inv) * __inv + __inv;  /* 32 */        \
                     59:     __inv = (1 - __n * __inv) * __inv + __inv;  /* 64 */        \
                     60:     ASSERT (__inv * __n == 1);                                  \
                     61:     (inv) = __inv;                                              \
                     62:   } while (0)
                     63: #endif
                     64:
                     65:
                     66: /* The loop based version used in GMP 3.0 and earlier.  Usually slower than
                     67:    multiplying, due to the number of steps that must be performed.  Much
                     68:    slower when the processor has a good multiply.  */
                     69:
                     70: #define modlimb_invert_loop(inv,n)              \
                     71:   do {                                          \
                     72:     mp_limb_t  __v = (n);                       \
                     73:     mp_limb_t  __v_orig = __v;                  \
                     74:     mp_limb_t  __make_zero = 1;                 \
                     75:     mp_limb_t  __two_i = 1;                     \
                     76:     mp_limb_t  __v_inv = 0;                     \
                     77:                                                 \
                     78:     ASSERT ((__v & 1) == 1);                    \
                     79:                                                 \
                     80:     do                                          \
                     81:       {                                         \
                     82:         while ((__two_i & __make_zero) == 0)    \
                     83:           __two_i <<= 1, __v <<= 1;             \
                     84:         __v_inv += __two_i;                     \
                     85:         __make_zero -= __v;                     \
                     86:       }                                         \
                     87:     while (__make_zero);                        \
                     88:                                                 \
                     89:     ASSERT (__v_orig * __v_inv == 1);           \
                     90:     (inv) = __v_inv;                            \
                     91:   } while (0)
                     92:
                     93:
                     94: /* Another loop based version with conditionals, but doing a fixed number of
                     95:    steps. */
                     96:
                     97: #define modlimb_invert_cond(inv,n)              \
                     98:   do {                                          \
                     99:     mp_limb_t  __n = (n);                       \
                    100:     mp_limb_t  __rem = (1 - __n) >> 1;          \
                    101:     mp_limb_t  __inv = GMP_LIMB_HIGHBIT;       \
                    102:     int        __count;                         \
                    103:                                                 \
                    104:     ASSERT ((__n & 1) == 1);                    \
                    105:                                                 \
                    106:     __count = BITS_PER_MP_LIMB-1;               \
                    107:     do                                          \
                    108:       {                                         \
                    109:         __inv >>= 1;                            \
                    110:         if (__rem & 1)                          \
                    111:           {                                     \
                    112:             __inv |= GMP_LIMB_HIGHBIT;         \
                    113:             __rem -= __n;                       \
                    114:           }                                     \
                    115:         __rem >>= 1;                            \
                    116:       }                                         \
                    117:     while (-- __count);                         \
                    118:                                                 \
                    119:     ASSERT (__inv * __n == 1);                  \
                    120:     (inv) = __inv;                              \
                    121:   } while (0)
                    122:
                    123:
                    124: /* Another loop based bitwise version, but purely arithmetic, no
                    125:    conditionals. */
                    126:
                    127: #define modlimb_invert_arith(inv,n)                                     \
                    128:   do {                                                                  \
                    129:     mp_limb_t  __n = (n);                                               \
                    130:     mp_limb_t  __rem = (1 - __n) >> 1;                                  \
                    131:     mp_limb_t  __inv = GMP_LIMB_HIGHBIT;                               \
                    132:     mp_limb_t  __lowbit;                                                \
                    133:     int        __count;                                                 \
                    134:                                                                         \
                    135:     ASSERT ((__n & 1) == 1);                                            \
                    136:                                                                         \
                    137:     __count = BITS_PER_MP_LIMB-1;                                       \
                    138:     do                                                                  \
                    139:       {                                                                 \
                    140:         __lowbit = __rem & 1;                                           \
                    141:         __inv = (__inv >> 1) | (__lowbit << (BITS_PER_MP_LIMB-1));      \
                    142:         __rem = (__rem - (__n & -__lowbit)) >> 1;                       \
                    143:       }                                                                 \
                    144:     while (-- __count);                                                 \
                    145:                                                                         \
                    146:     ASSERT (__inv * __n == 1);                                          \
                    147:     (inv) = __inv;                                                      \
                    148:   } while (0)
                    149:
                    150:
                    151: double
                    152: speed_modlimb_invert_mul1 (struct speed_params *s)
                    153: {
                    154:   SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_mul1);
                    155: }
                    156: double
                    157: speed_modlimb_invert_loop (struct speed_params *s)
                    158: {
                    159:   SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_loop);
                    160: }
                    161: double
                    162: speed_modlimb_invert_cond (struct speed_params *s)
                    163: {
                    164:   SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_cond);
                    165: }
                    166: double
                    167: speed_modlimb_invert_arith (struct speed_params *s)
                    168: {
                    169:   SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_arith);
                    170: }

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