diff options
Diffstat (limited to 'third_party/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c')
-rw-r--r-- | third_party/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c new file mode 100644 index 0000000..3ebf9b4 --- /dev/null +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c @@ -0,0 +1,74 @@ +#include "tommath_private.h" +#ifdef BN_MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit subtraction */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_digit *tmpa, *tmpc; + mp_err err; + int ix, oldused; + + /* grow c as required */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + mp_int a_ = *a; + a_.sign = MP_ZPOS; + err = mp_add_d(&a_, b, c); + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if (((a->used == 1) && (a->dp[0] <= b)) || (a->used == 0)) { + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + mp_digit mu = b; + + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract digits, mu is carry */ + for (ix = 0; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + MP_ZERO_DIGITS(tmpc, oldused - ix); + + mp_clamp(c); + return MP_OKAY; +} + +#endif |