Skip to content

Commit fd26938

Browse files
authored
Merge pull request #294 from libtom/deprecate-ex-funs
deprecate mp_n_root_ex and mp_expt_d_ex
2 parents c58c7f6 + c7314fa commit fd26938

15 files changed

+251
-320
lines changed

bn_deprecated.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,18 @@ mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result)
191191
return s_mp_prime_is_divisible(a, result);
192192
}
193193
#endif
194+
#ifdef BN_MP_EXPT_D_EX_C
195+
mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
196+
{
197+
(void)fast;
198+
return mp_expt_d(a, b, c);
199+
}
200+
#endif
201+
#ifdef BN_MP_N_ROOT_EX_C
202+
mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
203+
{
204+
(void)fast;
205+
return mp_n_root(a, b, c);
206+
}
207+
#endif
194208
#endif

bn_mp_expt_d.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,43 @@
33
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
44
/* SPDX-License-Identifier: Unlicense */
55

6-
/* wrapper function for mp_expt_d_ex() */
6+
/* calculate c = a**b using a square-multiply algorithm */
77
mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c)
88
{
9-
return mp_expt_d_ex(a, b, c, 0);
9+
mp_err err;
10+
11+
mp_int g;
12+
13+
if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
14+
return err;
15+
}
16+
17+
/* set initial result */
18+
mp_set(c, 1uL);
19+
20+
while (b > 0u) {
21+
/* if the bit is set multiply */
22+
if ((b & 1u) != 0u) {
23+
if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
24+
mp_clear(&g);
25+
return err;
26+
}
27+
}
28+
29+
/* square */
30+
if (b > 1u) {
31+
if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
32+
mp_clear(&g);
33+
return err;
34+
}
35+
}
36+
37+
/* shift to next bit */
38+
b >>= 1;
39+
}
40+
41+
mp_clear(&g);
42+
return MP_OKAY;
1043
}
1144

1245
#endif

bn_mp_expt_d_ex.c

Lines changed: 0 additions & 66 deletions
This file was deleted.

bn_mp_n_root.c

Lines changed: 159 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,168 @@
33
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
44
/* SPDX-License-Identifier: Unlicense */
55

6-
/* wrapper function for mp_n_root_ex()
7-
* computes c = (a)**(1/b) such that (c)**b <= a and (c+1)**b > a
6+
/* find the n'th root of an integer
7+
*
8+
* Result found such that (c)**b <= a and (c+1)**b > a
9+
*
10+
* This algorithm uses Newton's approximation
11+
* x[i+1] = x[i] - f(x[i])/f'(x[i])
12+
* which will find the root in log(N) time where
13+
* each step involves a fair bit.
814
*/
915
mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c)
1016
{
11-
return mp_n_root_ex(a, b, c, 0);
17+
mp_int t1, t2, t3, a_;
18+
mp_ord cmp;
19+
int ilog2;
20+
mp_err err;
21+
22+
/* input must be positive if b is even */
23+
if (((b & 1u) == 0u) && (a->sign == MP_NEG)) {
24+
return MP_VAL;
25+
}
26+
27+
if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) {
28+
return err;
29+
}
30+
31+
/* if a is negative fudge the sign but keep track */
32+
a_ = *a;
33+
a_.sign = MP_ZPOS;
34+
35+
/* Compute seed: 2^(log_2(n)/b + 2)*/
36+
ilog2 = mp_count_bits(a);
37+
38+
/*
39+
GCC and clang do not understand the sizeof tests and complain,
40+
icc (the Intel compiler) seems to understand, at least it doesn't complain.
41+
2 of 3 say these macros are necessary, so there they are.
42+
*/
43+
#if ( !(defined MP_8BIT) && !(defined MP_16BIT) )
44+
/*
45+
The type of mp_digit might be larger than an int.
46+
If "b" is larger than INT_MAX it is also larger than
47+
log_2(n) because the bit-length of the "n" is measured
48+
with an int and hence the root is always < 2 (two).
49+
*/
50+
if (sizeof(mp_digit) >= sizeof(int)) {
51+
if (b > (mp_digit)(INT_MAX/2)) {
52+
mp_set(c, 1uL);
53+
c->sign = a->sign;
54+
err = MP_OKAY;
55+
goto LBL_ERR;
56+
}
57+
}
58+
#endif
59+
/* "b" is smaller than INT_MAX, we can cast safely */
60+
if (ilog2 < (int)b) {
61+
mp_set(c, 1uL);
62+
c->sign = a->sign;
63+
err = MP_OKAY;
64+
goto LBL_ERR;
65+
}
66+
ilog2 = ilog2 / ((int)b);
67+
if (ilog2 == 0) {
68+
mp_set(c, 1uL);
69+
c->sign = a->sign;
70+
err = MP_OKAY;
71+
goto LBL_ERR;
72+
}
73+
/* Start value must be larger than root */
74+
ilog2 += 2;
75+
if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) {
76+
goto LBL_ERR;
77+
}
78+
do {
79+
/* t1 = t2 */
80+
if ((err = mp_copy(&t2, &t1)) != MP_OKAY) {
81+
goto LBL_ERR;
82+
}
83+
84+
/* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
85+
86+
/* t3 = t1**(b-1) */
87+
if ((err = mp_expt_d(&t1, b - 1u, &t3)) != MP_OKAY) {
88+
goto LBL_ERR;
89+
}
90+
/* numerator */
91+
/* t2 = t1**b */
92+
if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) {
93+
goto LBL_ERR;
94+
}
95+
96+
/* t2 = t1**b - a */
97+
if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) {
98+
goto LBL_ERR;
99+
}
100+
101+
/* denominator */
102+
/* t3 = t1**(b-1) * b */
103+
if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY) {
104+
goto LBL_ERR;
105+
}
106+
107+
/* t3 = (t1**b - a)/(b * t1**(b-1)) */
108+
if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) {
109+
goto LBL_ERR;
110+
}
111+
112+
if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) {
113+
goto LBL_ERR;
114+
}
115+
/*
116+
Number of rounds is at most log_2(root). If it is more it
117+
got stuck, so break out of the loop and do the rest manually.
118+
*/
119+
if (ilog2-- == 0) {
120+
break;
121+
}
122+
} while (mp_cmp(&t1, &t2) != MP_EQ);
123+
124+
/* result can be off by a few so check */
125+
/* Loop beneath can overshoot by one if found root is smaller than actual root */
126+
for (;;) {
127+
if ((err = mp_expt_d(&t1, b, &t2)) != MP_OKAY) {
128+
goto LBL_ERR;
129+
}
130+
cmp = mp_cmp(&t2, &a_);
131+
if (cmp == MP_EQ) {
132+
err = MP_OKAY;
133+
goto LBL_ERR;
134+
}
135+
if (cmp == MP_LT) {
136+
if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) {
137+
goto LBL_ERR;
138+
}
139+
} else {
140+
break;
141+
}
142+
}
143+
/* correct overshoot from above or from recurrence */
144+
for (;;) {
145+
if ((err = mp_expt_d(&t1, b, &t2)) != MP_OKAY) {
146+
goto LBL_ERR;
147+
}
148+
if (mp_cmp(&t2, &a_) == MP_GT) {
149+
if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) {
150+
goto LBL_ERR;
151+
}
152+
} else {
153+
break;
154+
}
155+
}
156+
157+
/* set the result */
158+
mp_exch(&t1, c);
159+
160+
/* set the sign of the result */
161+
c->sign = a->sign;
162+
163+
err = MP_OKAY;
164+
165+
LBL_ERR:
166+
mp_clear_multi(&t1, &t2, &t3, NULL);
167+
return err;
12168
}
13169

14170
#endif

0 commit comments

Comments
 (0)