diff options
author | Kevin B Kenny <kennykb@acm.org> | 2005-01-19 22:41:26 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2005-01-19 22:41:26 (GMT) |
commit | ef78ca64ce6ba6a8786f083318fe536f2bd52925 (patch) | |
tree | 47f8ad0d7291237c7f9af988c5e05275ed9286ee /libtommath/bn_s_mp_sub.c | |
parent | b23d942a1e86ddee18c2309afd7fa7e9afa79ef8 (diff) | |
download | tcl-ef78ca64ce6ba6a8786f083318fe536f2bd52925.zip tcl-ef78ca64ce6ba6a8786f083318fe536f2bd52925.tar.gz tcl-ef78ca64ce6ba6a8786f083318fe536f2bd52925.tar.bz2 |
Import of libtommath 0.33
Diffstat (limited to 'libtommath/bn_s_mp_sub.c')
-rw-r--r-- | libtommath/bn_s_mp_sub.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/libtommath/bn_s_mp_sub.c b/libtommath/bn_s_mp_sub.c new file mode 100644 index 0000000..5b7aef9 --- /dev/null +++ b/libtommath/bn_s_mp_sub.c @@ -0,0 +1,85 @@ +#include <tommath.h> +#ifdef BN_S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int +s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +#endif |