source: trunk/third/gmp/tune/modlinv.c @ 18191

Revision 18191, 7.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18190, which included commits to RCS files with non-trunk default branches.
Line 
1/* Alternate implementations of modlimb_invert to compare speeds. */
2
3/*
4Copyright 2000, 2002 Free Software Foundation, Inc.
5
6This file is part of the GNU MP Library.
7
8The GNU MP Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 2.1 of the License, or (at your
11option) any later version.
12
13The GNU MP Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
20the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21MA 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
151double
152speed_modlimb_invert_mul1 (struct speed_params *s)
153{
154  SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_mul1);
155}
156double
157speed_modlimb_invert_loop (struct speed_params *s)
158{
159  SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_loop);
160}
161double
162speed_modlimb_invert_cond (struct speed_params *s)
163{
164  SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_cond);
165}
166double
167speed_modlimb_invert_arith (struct speed_params *s)
168{
169  SPEED_ROUTINE_MODLIMB_INVERT (modlimb_invert_arith);
170}
Note: See TracBrowser for help on using the repository browser.