Line data Source code
1 : #include "tommath_private.h" 2 : #ifdef BN_S_MP_MUL_HIGH_DIGS_C 3 : /* LibTomMath, multiple-precision integer library -- Tom St Denis */ 4 : /* SPDX-License-Identifier: Unlicense */ 5 : 6 : /* multiplies |a| * |b| and does not compute the lower digs digits 7 : * [meant to get the higher part of the product] 8 : */ 9 0 : mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) 10 : { 11 0 : mp_int t; 12 0 : int pa, pb, ix, iy; 13 0 : mp_err err; 14 0 : mp_digit u; 15 0 : mp_word r; 16 0 : mp_digit tmpx, *tmpt, *tmpy; 17 : 18 : /* can we use the fast multiplier? */ 19 0 : if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) 20 0 : && ((a->used + b->used + 1) < MP_WARRAY) 21 0 : && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { 22 0 : return s_mp_mul_high_digs_fast(a, b, c, digs); 23 : } 24 : 25 0 : if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { 26 0 : return err; 27 : } 28 0 : t.used = a->used + b->used + 1; 29 : 30 0 : pa = a->used; 31 0 : pb = b->used; 32 0 : for (ix = 0; ix < pa; ix++) { 33 : /* clear the carry */ 34 0 : u = 0; 35 : 36 : /* left hand side of A[ix] * B[iy] */ 37 0 : tmpx = a->dp[ix]; 38 : 39 : /* alias to the address of where the digits will be stored */ 40 0 : tmpt = &(t.dp[digs]); 41 : 42 : /* alias for where to read the right hand side from */ 43 0 : tmpy = b->dp + (digs - ix); 44 : 45 0 : for (iy = digs - ix; iy < pb; iy++) { 46 : /* calculate the double precision result */ 47 0 : r = (mp_word)*tmpt + 48 0 : ((mp_word)tmpx * (mp_word)*tmpy++) + 49 0 : (mp_word)u; 50 : 51 : /* get the lower part */ 52 0 : *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK); 53 : 54 : /* carry the carry */ 55 0 : u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); 56 : } 57 0 : *tmpt = u; 58 : } 59 0 : mp_clamp(&t); 60 0 : mp_exch(&t, c); 61 0 : mp_clear(&t); 62 0 : return MP_OKAY; 63 : } 64 : #endif