xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/libtommath/bn_s_mp_sub.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: bn_s_mp_sub.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2 
3 #include <tommath.h>
4 #ifdef BN_S_MP_SUB_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 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
21 int
s_mp_sub(mp_int * a,mp_int * b,mp_int * c)22 s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
23 {
24   int     olduse, res, min, max;
25 
26   /* find sizes */
27   min = b->used;
28   max = a->used;
29 
30   /* init result */
31   if (c->alloc < max) {
32     if ((res = mp_grow (c, max)) != MP_OKAY) {
33       return res;
34     }
35   }
36   olduse = c->used;
37   c->used = max;
38 
39   {
40     register mp_digit u, *tmpa, *tmpb, *tmpc;
41     register int i;
42 
43     /* alias for digit pointers */
44     tmpa = a->dp;
45     tmpb = b->dp;
46     tmpc = c->dp;
47 
48     /* set carry to zero */
49     u = 0;
50     for (i = 0; i < min; i++) {
51       /* T[i] = A[i] - B[i] - U */
52       *tmpc = *tmpa++ - *tmpb++ - u;
53 
54       /* U = carry bit of T[i]
55        * Note this saves performing an AND operation since
56        * if a carry does occur it will propagate all the way to the
57        * MSB.  As a result a single shift is enough to get the carry
58        */
59       u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
60 
61       /* Clear carry from T[i] */
62       *tmpc++ &= MP_MASK;
63     }
64 
65     /* now copy higher words if any, e.g. if A has more digits than B  */
66     for (; i < max; i++) {
67       /* T[i] = A[i] - U */
68       *tmpc = *tmpa++ - u;
69 
70       /* U = carry bit of T[i] */
71       u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
72 
73       /* Clear carry from T[i] */
74       *tmpc++ &= MP_MASK;
75     }
76 
77     /* clear digits above used (since we may not have grown result above) */
78     for (i = c->used; i < olduse; i++) {
79       *tmpc++ = 0;
80     }
81   }
82 
83   mp_clamp (c);
84   return MP_OKAY;
85 }
86 
87 #endif
88 
89 /* Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v  */
90 /* Revision: 1.4  */
91 /* Date: 2006/12/28 01:25:13  */
92