Mercurial > dropbear
comparison libtommath/bn_s_mp_mul_high_digs_fast.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" | |
2 #ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C | |
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */ | |
4 /* SPDX-License-Identifier: Unlicense */ | |
5 | |
6 /* this is a modified version of fast_s_mul_digs that only produces | |
7 * output digits *above* digs. See the comments for fast_s_mul_digs | |
8 * to see how it works. | |
9 * | |
10 * This is used in the Barrett reduction since for one of the multiplications | |
11 * only the higher digits were needed. This essentially halves the work. | |
12 * | |
13 * Based on Algorithm 14.12 on pp.595 of HAC. | |
14 */ | |
15 mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) | |
16 { | |
17 int olduse, pa, ix, iz; | |
18 mp_err err; | |
19 mp_digit W[MP_WARRAY]; | |
20 mp_word _W; | |
21 | |
22 /* grow the destination as required */ | |
23 pa = a->used + b->used; | |
24 if (c->alloc < pa) { | |
25 if ((err = mp_grow(c, pa)) != MP_OKAY) { | |
26 return err; | |
27 } | |
28 } | |
29 | |
30 /* number of output digits to produce */ | |
31 pa = a->used + b->used; | |
32 _W = 0; | |
33 for (ix = digs; ix < pa; ix++) { | |
34 int tx, ty, iy; | |
35 mp_digit *tmpx, *tmpy; | |
36 | |
37 /* get offsets into the two bignums */ | |
38 ty = MP_MIN(b->used-1, ix); | |
39 tx = ix - ty; | |
40 | |
41 /* setup temp aliases */ | |
42 tmpx = a->dp + tx; | |
43 tmpy = b->dp + ty; | |
44 | |
45 /* this is the number of times the loop will iterrate, essentially its | |
46 while (tx++ < a->used && ty-- >= 0) { ... } | |
47 */ | |
48 iy = MP_MIN(a->used-tx, ty+1); | |
49 | |
50 /* execute loop */ | |
51 for (iz = 0; iz < iy; iz++) { | |
52 _W += (mp_word)*tmpx++ * (mp_word)*tmpy--; | |
53 } | |
54 | |
55 /* store term */ | |
56 W[ix] = (mp_digit)_W & MP_MASK; | |
57 | |
58 /* make next carry */ | |
59 _W = _W >> (mp_word)MP_DIGIT_BIT; | |
60 } | |
61 | |
62 /* setup dest */ | |
63 olduse = c->used; | |
64 c->used = pa; | |
65 | |
66 { | |
67 mp_digit *tmpc; | |
68 | |
69 tmpc = c->dp + digs; | |
70 for (ix = digs; ix < pa; ix++) { | |
71 /* now extract the previous digit [below the carry] */ | |
72 *tmpc++ = W[ix]; | |
73 } | |
74 | |
75 /* clear unused digits [that existed in the old copy of c] */ | |
76 MP_ZERO_DIGITS(tmpc, olduse - ix); | |
77 } | |
78 mp_clamp(c); | |
79 return MP_OKAY; | |
80 } | |
81 #endif |