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 : mp_digit *tmpa, *tmpc;
10 : mp_err err;
11 : 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
|