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 */
mp_sub_d(const mp_int * a,mp_digit b,mp_int * c)7 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 if (c->alloc < (a->used + 1)) {
15 if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
16 return err;
17 }
18 }
19
20 /* if a is negative just do an unsigned
21 * addition [with fudged signs]
22 */
23 if (a->sign == MP_NEG) {
24 mp_int a_ = *a;
25 a_.sign = MP_ZPOS;
26 err = mp_add_d(&a_, b, c);
27 c->sign = MP_NEG;
28
29 /* clamp */
30 mp_clamp(c);
31
32 return err;
33 }
34
35 /* setup regs */
36 oldused = c->used;
37 tmpa = a->dp;
38 tmpc = c->dp;
39
40 /* if a <= b simply fix the single digit */
41 if (((a->used == 1) && (a->dp[0] <= b)) || (a->used == 0)) {
42 if (a->used == 1) {
43 *tmpc++ = b - *tmpa;
44 } else {
45 *tmpc++ = b;
46 }
47 ix = 1;
48
49 /* negative/1digit */
50 c->sign = MP_NEG;
51 c->used = 1;
52 } else {
53 mp_digit mu = b;
54
55 /* positive/size */
56 c->sign = MP_ZPOS;
57 c->used = a->used;
58
59 /* subtract digits, mu is carry */
60 for (ix = 0; ix < a->used; ix++) {
61 *tmpc = *tmpa++ - mu;
62 mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
63 *tmpc++ &= MP_MASK;
64 }
65 }
66
67 /* zero excess digits */
68 MP_ZERO_DIGITS(tmpc, oldused - ix);
69
70 mp_clamp(c);
71 return MP_OKAY;
72 }
73
74 #endif
75