Line data Source code
1 : #include "tommath_private.h" 2 : #ifdef BN_MP_ADD_D_C 3 : /* LibTomMath, multiple-precision integer library -- Tom St Denis */ 4 : /* SPDX-License-Identifier: Unlicense */ 5 : 6 : /* single digit addition */ 7 0 : mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) 8 : { 9 0 : mp_err err; 10 0 : int ix, oldused; 11 0 : mp_digit *tmpa, *tmpc; 12 : 13 : /* grow c as required */ 14 0 : if (c->alloc < (a->used + 1)) { 15 0 : if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { 16 0 : return err; 17 : } 18 : } 19 : 20 : /* if a is negative and |a| >= b, call c = |a| - b */ 21 0 : if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) { 22 0 : mp_int a_ = *a; 23 : /* temporarily fix sign of a */ 24 0 : a_.sign = MP_ZPOS; 25 : 26 : /* c = |a| - b */ 27 0 : err = mp_sub_d(&a_, b, c); 28 : 29 : /* fix sign */ 30 0 : c->sign = MP_NEG; 31 : 32 : /* clamp */ 33 0 : mp_clamp(c); 34 : 35 0 : return err; 36 : } 37 : 38 : /* old number of used digits in c */ 39 0 : oldused = c->used; 40 : 41 : /* source alias */ 42 0 : tmpa = a->dp; 43 : 44 : /* destination alias */ 45 0 : tmpc = c->dp; 46 : 47 : /* if a is positive */ 48 0 : if (a->sign == MP_ZPOS) { 49 : /* add digits, mu is carry */ 50 0 : mp_digit mu = b; 51 0 : for (ix = 0; ix < a->used; ix++) { 52 0 : *tmpc = *tmpa++ + mu; 53 0 : mu = *tmpc >> MP_DIGIT_BIT; 54 0 : *tmpc++ &= MP_MASK; 55 : } 56 : /* set final carry */ 57 0 : ix++; 58 0 : *tmpc++ = mu; 59 : 60 : /* setup size */ 61 0 : c->used = a->used + 1; 62 : } else { 63 : /* a was negative and |a| < b */ 64 0 : c->used = 1; 65 : 66 : /* the result is a single digit */ 67 0 : if (a->used == 1) { 68 0 : *tmpc++ = b - a->dp[0]; 69 : } else { 70 0 : *tmpc++ = b; 71 : } 72 : 73 : /* setup count so the clearing of oldused 74 : * can fall through correctly 75 : */ 76 0 : ix = 1; 77 : } 78 : 79 : /* sign always positive */ 80 0 : c->sign = MP_ZPOS; 81 : 82 : /* now zero to oldused */ 83 0 : MP_ZERO_DIGITS(tmpc, oldused - ix); 84 0 : mp_clamp(c); 85 : 86 0 : return MP_OKAY; 87 : } 88 : 89 : #endif