Mercurial > dropbear
comparison libtommath/bn_mp_div_d.c @ 1739:13d834efc376 fuzz
merge from main
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 15 Oct 2020 19:55:15 +0800 |
parents | 1051e4eea25a |
children |
comparison
equal
deleted
inserted
replaced
1562:768ebf737aa0 | 1739:13d834efc376 |
---|---|
1 #include <tommath_private.h> | 1 #include "tommath_private.h" |
2 #ifdef BN_MP_DIV_D_C | 2 #ifdef BN_MP_DIV_D_C |
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis | 3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 * | 4 /* SPDX-License-Identifier: Unlicense */ |
5 * LibTomMath is a library that provides multiple-precision | |
6 * integer arithmetic as well as number theoretic functionality. | |
7 * | |
8 * The library was designed directly after the MPI library by | |
9 * Michael Fromberger but has been written from scratch with | |
10 * additional optimizations in place. | |
11 * | |
12 * The library is free for all purposes without any express | |
13 * guarantee it works. | |
14 * | |
15 * Tom St Denis, [email protected], http://libtom.org | |
16 */ | |
17 | 5 |
18 static int s_is_power_of_two(mp_digit b, int *p) | 6 /* single digit division (based on routine from MPI) */ |
7 mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) | |
19 { | 8 { |
20 int x; | 9 mp_int q; |
10 mp_word w; | |
11 mp_digit t; | |
12 mp_err err; | |
13 int ix; | |
21 | 14 |
22 /* fast return if no power of two */ | 15 /* cannot divide by zero */ |
23 if ((b == 0) || ((b & (b-1)) != 0)) { | 16 if (b == 0u) { |
24 return 0; | 17 return MP_VAL; |
25 } | 18 } |
26 | 19 |
27 for (x = 0; x < DIGIT_BIT; x++) { | 20 /* quick outs */ |
28 if (b == (((mp_digit)1)<<x)) { | 21 if ((b == 1u) || MP_IS_ZERO(a)) { |
29 *p = x; | 22 if (d != NULL) { |
30 return 1; | 23 *d = 0; |
31 } | 24 } |
25 if (c != NULL) { | |
26 return mp_copy(a, c); | |
27 } | |
28 return MP_OKAY; | |
32 } | 29 } |
33 return 0; | |
34 } | |
35 | 30 |
36 /* single digit division (based on routine from MPI) */ | 31 /* power of two ? */ |
37 int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) | 32 if ((b & (b - 1u)) == 0u) { |
38 { | 33 ix = 1; |
39 mp_int q; | 34 while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<<ix))) { |
40 mp_word w; | 35 ix++; |
41 mp_digit t; | 36 } |
42 int res, ix; | 37 if (d != NULL) { |
38 *d = a->dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL); | |
39 } | |
40 if (c != NULL) { | |
41 return mp_div_2d(a, ix, c, NULL); | |
42 } | |
43 return MP_OKAY; | |
44 } | |
43 | 45 |
44 /* cannot divide by zero */ | 46 /* three? */ |
45 if (b == 0) { | 47 if (MP_HAS(MP_DIV_3) && (b == 3u)) { |
46 return MP_VAL; | 48 return mp_div_3(a, c, d); |
47 } | 49 } |
48 | 50 |
49 /* quick outs */ | 51 /* no easy answer [c'est la vie]. Just division */ |
50 if ((b == 1) || (mp_iszero(a) == MP_YES)) { | 52 if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { |
51 if (d != NULL) { | 53 return err; |
52 *d = 0; | 54 } |
53 } | |
54 if (c != NULL) { | |
55 return mp_copy(a, c); | |
56 } | |
57 return MP_OKAY; | |
58 } | |
59 | 55 |
60 /* power of two ? */ | 56 q.used = a->used; |
61 if (s_is_power_of_two(b, &ix) == 1) { | 57 q.sign = a->sign; |
62 if (d != NULL) { | 58 w = 0; |
63 *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1); | 59 for (ix = a->used - 1; ix >= 0; ix--) { |
64 } | 60 w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; |
65 if (c != NULL) { | |
66 return mp_div_2d(a, ix, c, NULL); | |
67 } | |
68 return MP_OKAY; | |
69 } | |
70 | 61 |
71 #ifdef BN_MP_DIV_3_C | 62 if (w >= b) { |
72 /* three? */ | 63 t = (mp_digit)(w / b); |
73 if (b == 3) { | 64 w -= (mp_word)t * (mp_word)b; |
74 return mp_div_3(a, c, d); | 65 } else { |
75 } | 66 t = 0; |
76 #endif | 67 } |
68 q.dp[ix] = t; | |
69 } | |
77 | 70 |
78 /* no easy answer [c'est la vie]. Just division */ | 71 if (d != NULL) { |
79 if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { | 72 *d = (mp_digit)w; |
80 return res; | 73 } |
81 } | 74 |
82 | 75 if (c != NULL) { |
83 q.used = a->used; | 76 mp_clamp(&q); |
84 q.sign = a->sign; | 77 mp_exch(&q, c); |
85 w = 0; | 78 } |
86 for (ix = a->used - 1; ix >= 0; ix--) { | 79 mp_clear(&q); |
87 w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); | 80 |
88 | 81 return err; |
89 if (w >= b) { | |
90 t = (mp_digit)(w / b); | |
91 w -= ((mp_word)t) * ((mp_word)b); | |
92 } else { | |
93 t = 0; | |
94 } | |
95 q.dp[ix] = (mp_digit)t; | |
96 } | |
97 | |
98 if (d != NULL) { | |
99 *d = (mp_digit)w; | |
100 } | |
101 | |
102 if (c != NULL) { | |
103 mp_clamp(&q); | |
104 mp_exch(&q, c); | |
105 } | |
106 mp_clear(&q); | |
107 | |
108 return res; | |
109 } | 82 } |
110 | 83 |
111 #endif | 84 #endif |
112 | |
113 /* ref: $Format:%D$ */ | |
114 /* git commit: $Format:%H$ */ | |
115 /* commit time: $Format:%ai$ */ |