Line data Source code
1 : #include "tommath_private.h" 2 : #ifdef BN_MP_SUB_D_C 3 : /* LibTomMath, multiple-precision integer library -- Tom St Denis */ 4 : /* SPDX-License-Identifier: Unlicense */ 5 : 6 : /* single digit subtraction */ 7 0 : mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) 8 : { 9 0 : mp_digit *tmpa, *tmpc; 10 0 : mp_err err; 11 0 : int ix, oldused; 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 just do an unsigned 21 : * addition [with fudged signs] 22 : */ 23 0 : if (a->sign == MP_NEG) { 24 0 : mp_int a_ = *a; 25 0 : a_.sign = MP_ZPOS; 26 0 : err = mp_add_d(&a_, b, c); 27 0 : c->sign = MP_NEG; 28 : 29 : /* clamp */ 30 0 : mp_clamp(c); 31 : 32 0 : return err; 33 : } 34 : 35 : /* setup regs */ 36 0 : oldused = c->used; 37 0 : tmpa = a->dp; 38 0 : tmpc = c->dp; 39 : 40 : /* if a <= b simply fix the single digit */ 41 0 : if (((a->used == 1) && (a->dp[0] <= b)) || (a->used == 0)) { 42 0 : if (a->used == 1) { 43 0 : *tmpc++ = b - *tmpa; 44 : } else { 45 0 : *tmpc++ = b; 46 : } 47 0 : ix = 1; 48 : 49 : /* negative/1digit */ 50 0 : c->sign = MP_NEG; 51 0 : c->used = 1; 52 : } else { 53 0 : mp_digit mu = b; 54 : 55 : /* positive/size */ 56 0 : c->sign = MP_ZPOS; 57 0 : c->used = a->used; 58 : 59 : /* subtract digits, mu is carry */ 60 0 : for (ix = 0; ix < a->used; ix++) { 61 0 : *tmpc = *tmpa++ - mu; 62 0 : mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u); 63 0 : *tmpc++ &= MP_MASK; 64 : } 65 : } 66 : 67 : /* zero excess digits */ 68 0 : MP_ZERO_DIGITS(tmpc, oldused - ix); 69 : 70 0 : mp_clamp(c); 71 0 : return MP_OKAY; 72 : } 73 : 74 : #endif