xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/libtommath/bn_mp_add_d.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: bn_mp_add_d.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2 
3 #include <tommath.h>
4 #ifdef BN_MP_ADD_D_C
5 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6  *
7  * LibTomMath is a library that provides multiple-precision
8  * integer arithmetic as well as number theoretic functionality.
9  *
10  * The library was designed directly after the MPI library by
11  * Michael Fromberger but has been written from scratch with
12  * additional optimizations in place.
13  *
14  * The library is free for all purposes without any express
15  * guarantee it works.
16  *
17  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
18  */
19 
20 /* single digit addition */
21 int
mp_add_d(mp_int * a,mp_digit b,mp_int * c)22 mp_add_d (mp_int * a, mp_digit b, mp_int * c)
23 {
24   int     res, ix, oldused;
25   mp_digit *tmpa, *tmpc, mu;
26 
27   /* grow c as required */
28   if (c->alloc < a->used + 1) {
29      if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
30         return res;
31      }
32   }
33 
34   /* if a is negative and |a| >= b, call c = |a| - b */
35   if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
36      /* temporarily fix sign of a */
37      a->sign = MP_ZPOS;
38 
39      /* c = |a| - b */
40      res = mp_sub_d(a, b, c);
41 
42      /* fix sign  */
43      a->sign = c->sign = MP_NEG;
44 
45      /* clamp */
46      mp_clamp(c);
47 
48      return res;
49   }
50 
51   /* old number of used digits in c */
52   oldused = c->used;
53 
54   /* sign always positive */
55   c->sign = MP_ZPOS;
56 
57   /* source alias */
58   tmpa    = a->dp;
59 
60   /* destination alias */
61   tmpc    = c->dp;
62 
63   /* if a is positive */
64   if (a->sign == MP_ZPOS) {
65      /* add digit, after this we're propagating
66       * the carry.
67       */
68      *tmpc   = *tmpa++ + b;
69      mu      = *tmpc >> DIGIT_BIT;
70      *tmpc++ &= MP_MASK;
71 
72      /* now handle rest of the digits */
73      for (ix = 1; ix < a->used; ix++) {
74         *tmpc   = *tmpa++ + mu;
75         mu      = *tmpc >> DIGIT_BIT;
76         *tmpc++ &= MP_MASK;
77      }
78      /* set final carry */
79      ix++;
80      *tmpc++  = mu;
81 
82      /* setup size */
83      c->used = a->used + 1;
84   } else {
85      /* a was negative and |a| < b */
86      c->used  = 1;
87 
88      /* the result is a single digit */
89      if (a->used == 1) {
90         *tmpc++  =  b - a->dp[0];
91      } else {
92         *tmpc++  =  b;
93      }
94 
95      /* setup count so the clearing of oldused
96       * can fall through correctly
97       */
98      ix       = 1;
99   }
100 
101   /* now zero to oldused */
102   while (ix++ < oldused) {
103      *tmpc++ = 0;
104   }
105   mp_clamp(c);
106 
107   return MP_OKAY;
108 }
109 
110 #endif
111 
112 /* Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v  */
113 /* Revision: 1.5  */
114 /* Date: 2006/12/28 01:25:13  */
115