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 : mp_err err;
10 : int ix, oldused;
11 : 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
|