diff options
author | dgp <dgp@users.sourceforge.net> | 2005-09-16 16:13:16 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2005-09-16 16:13:16 (GMT) |
commit | c054dac446c3c39b715702d64d8408b7d93a2c69 (patch) | |
tree | 32cec51236751a7139721123ce45239d912a89eb | |
parent | 82c1f95070e323d171a08ba2459e352484beaba5 (diff) | |
download | tcl-c054dac446c3c39b715702d64d8408b7d93a2c69.zip tcl-c054dac446c3c39b715702d64d8408b7d93a2c69.tar.gz tcl-c054dac446c3c39b715702d64d8408b7d93a2c69.tar.bz2 |
* libtommath/bn_mp_add_d.c: Bug fix. For mp_add_d(&a, d, &c),
when &a has the value -d, then the value &c computed should be zero,
but mp_add_d was producing an inconsistent zero value with a sign
field of MP_NEG, something like a value of -0, which other routines
in libtommath can't handle.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | libtommath/bn_mp_add_d.c | 106 |
2 files changed, 112 insertions, 0 deletions
@@ -7,6 +7,12 @@ * win/Makefile.in: * win/makefile.vc: + * libtommath/bn_mp_add_d.c: Bug fix. For mp_add_d(&a, d, &c), + when &a has the value -d, then the value &c computed should be zero, + but mp_add_d was producing an inconsistent zero value with a sign + field of MP_NEG, something like a value of -0, which other routines + in libtommath can't handle. + * generic/tclExecute.c: Dropped all creation of "bigOne" values and just use tommath routines that accept the value "1" directly. diff --git a/libtommath/bn_mp_add_d.c b/libtommath/bn_mp_add_d.c new file mode 100644 index 0000000..bf9f4bc --- /dev/null +++ b/libtommath/bn_mp_add_d.c @@ -0,0 +1,106 @@ +#include <tommath.h> +#ifdef BN_MP_ADD_D_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 + */ + +/* single digit addition */ +int +mp_add_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix signs */ + a->sign = MP_NEG; + c->sign = (c->used) ? MP_NEG : MP_ZPOS; + + return res; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; +} + +#endif |