diff --git a/bn_mp_complement.c b/bn_mp_complement.c new file mode 100644 index 0000000..256ddea --- /dev/null +++ b/bn_mp_complement.c @@ -0,0 +1,26 @@ +#include "tommath_private.h" +#ifdef BN_MP_COMPLEMENT_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. + */ + +/* b = ~a */ +int mp_complement(const mp_int *a, mp_int *b) +{ + int res = mp_neg(a, b); + return res == MP_OKAY ? mp_sub_d(b, 1, b) : res; +} +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/bn_mp_tc_and.c b/bn_mp_tc_and.c new file mode 100644 index 0000000..0e28ca8 --- /dev/null +++ b/bn_mp_tc_and.c @@ -0,0 +1,90 @@ +#include "tommath_private.h" +#ifdef BN_MP_TC_AND_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. + */ + +/* two complement and */ +int mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + int res = MP_OKAY, bits; + int as = mp_isneg(a), bs = mp_isneg(b), s = 0; + mp_int *mx = 0, _mx, acpy, bcpy; + + if (as || bs) { + bits = MAX(mp_count_bits(a), mp_count_bits(b)); + res = mp_init_set_int(&_mx, 1); + if (res != MP_OKAY) { + goto end; + } + + mx = &_mx; + res = mp_mul_2d(mx, bits + 1, mx); + if (res != MP_OKAY) { + goto end; + } + + if (as) { + res = mp_init(&acpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, a, &acpy); + if (res != MP_OKAY) { + mp_clear(&acpy); + goto end; + } + a = &acpy; + } + if (bs) { + res = mp_init(&bcpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, b, &bcpy); + if (res != MP_OKAY) { + mp_clear(&bcpy); + goto end; + } + b = &bcpy; + } + } + + res = mp_and(a, b, c); + s = as & bs; + + if (s && res == MP_OKAY) { + res = mp_sub(c, mx, c); + } + +end: + if (a == &acpy) { + mp_clear(&acpy); + } + + if (b == &bcpy) { + mp_clear(&bcpy); + } + + if (mx == &_mx) { + mp_clear(mx); + } + + return res; +} +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/bn_mp_tc_div_2d.c b/bn_mp_tc_div_2d.c new file mode 100644 index 0000000..5ea4e38 --- /dev/null +++ b/bn_mp_tc_div_2d.c @@ -0,0 +1,36 @@ +#include "tommath_private.h" +#ifdef BN_MP_TC_DIV_2D_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. + */ + +/* two complement right shift */ +int mp_tc_div_2d(const mp_int *a, int b, mp_int *c) +{ + int res; + if (!mp_isneg(a)) { + return mp_div_2d(a, b, c, 0); + } + + res = mp_add_d(a, 1, c); + if (res != MP_OKAY) { + return res; + } + + res = mp_div_2d(c, b, c, 0); + return res == MP_OKAY ? mp_sub_d(c, 1, c) : res; +} +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/bn_mp_tc_or.c b/bn_mp_tc_or.c new file mode 100644 index 0000000..1e7d583 --- /dev/null +++ b/bn_mp_tc_or.c @@ -0,0 +1,90 @@ +#include "tommath_private.h" +#ifdef BN_MP_TC_OR_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. + */ + +/* two complement or */ +int mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + int res = MP_OKAY, bits; + int as = mp_isneg(a), bs = mp_isneg(b), s = 0; + mp_int *mx = 0, _mx, acpy, bcpy; + + if (as || bs) { + bits = MAX(mp_count_bits(a), mp_count_bits(b)); + res = mp_init_set_int(&_mx, 1); + if (res != MP_OKAY) { + goto end; + } + + mx = &_mx; + res = mp_mul_2d(mx, bits + 1, mx); + if (res != MP_OKAY) { + goto end; + } + + if (as) { + res = mp_init(&acpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, a, &acpy); + if (res != MP_OKAY) { + mp_clear(&acpy); + goto end; + } + a = &acpy; + } + if (bs) { + res = mp_init(&bcpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, b, &bcpy); + if (res != MP_OKAY) { + mp_clear(&bcpy); + goto end; + } + b = &bcpy; + } + } + + res = mp_or(a, b, c); + s = as | bs; + + if (s && res == MP_OKAY) { + res = mp_sub(c, mx, c); + } + +end: + if (a == &acpy) { + mp_clear(&acpy); + } + + if (b == &bcpy) { + mp_clear(&bcpy); + } + + if (mx == &_mx) { + mp_clear(mx); + } + + return res; +} +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/bn_mp_tc_xor.c b/bn_mp_tc_xor.c new file mode 100644 index 0000000..be9b9d8 --- /dev/null +++ b/bn_mp_tc_xor.c @@ -0,0 +1,90 @@ +#include "tommath_private.h" +#ifdef BN_MP_TC_XOR_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. + */ + +/* two complement xor */ +int mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + int res = MP_OKAY, bits; + int as = mp_isneg(a), bs = mp_isneg(b), s = 0; + mp_int *mx = 0, _mx, acpy, bcpy; + + if (as || bs) { + bits = MAX(mp_count_bits(a), mp_count_bits(b)); + res = mp_init_set_int(&_mx, 1); + if (res != MP_OKAY) { + goto end; + } + + mx = &_mx; + res = mp_mul_2d(mx, bits + 1, mx); + if (res != MP_OKAY) { + goto end; + } + + if (as) { + res = mp_init(&acpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, a, &acpy); + if (res != MP_OKAY) { + mp_clear(&acpy); + goto end; + } + a = &acpy; + } + if (bs) { + res = mp_init(&bcpy); + if (res != MP_OKAY) { + goto end; + } + + res = mp_add(mx, b, &bcpy); + if (res != MP_OKAY) { + mp_clear(&bcpy); + goto end; + } + b = &bcpy; + } + } + + res = mp_xor(a, b, c); + s = as ^ bs; + + if (s && res == MP_OKAY) { + res = mp_sub(c, mx, c); + } + +end: + if (a == &acpy) { + mp_clear(&acpy); + } + + if (b == &bcpy) { + mp_clear(&bcpy); + } + + if (mx == &_mx) { + mp_clear(mx); + } + + return res; +} +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/demo/demo.c b/demo/demo.c index 4f32072..ff67fcc 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -261,6 +261,127 @@ int main(void) } } + // test mp_complement + printf("\n\nTesting: mp_complement"); + for (i = 0; i < 1000; ++i) { + int l = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&a, labs(l)); + if (l < 0) + mp_neg(&a, &a); + mp_complement(&a, &b); + + l = ~l; + mp_set_int(&c, labs(l)); + if (l < 0) + mp_neg(&c, &c); + + if (mp_cmp(&b, &c) != MP_EQ) { + printf("\nmp_complement() bad result!"); + return EXIT_FAILURE; + } + } + + // test mp_tc_div_2d + printf("\n\nTesting: mp_tc_div_2d"); + for (i = 0; i < 1000; ++i) { + int l, m; + + l = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&a, labs(l)); + if (l < 0) + mp_neg(&a, &a); + + m = rand() % 32; + + mp_set_int(&d, labs(l >> m)); + if ((l >> m) < 0) + mp_neg(&d, &d); + + mp_tc_div_2d(&a, m, &b); + if (mp_cmp(&b, &d) != MP_EQ) { + printf("\nmp_tc_div_2d() bad result!"); + return EXIT_FAILURE; + } + } + + // test mp_tc_xor + printf("\n\nTesting: mp_tc_or"); + for (i = 0; i < 1000; ++i) { + int l, m; + + l = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&a, labs(l)); + if (l < 0) + mp_neg(&a, &a); + + m = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&b, labs(m)); + if (m < 0) + mp_neg(&b, &b); + + mp_set_int(&d, labs(l ^ m)); + if ((l ^ m) < 0) + mp_neg(&d, &d); + + mp_tc_xor(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_tc_xor() bad result!"); + return EXIT_FAILURE; + } + } + + // test mp_tc_or + printf("\n\nTesting: mp_tc_or"); + for (i = 0; i < 1000; ++i) { + int l, m; + + l = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&a, labs(l)); + if (l < 0) + mp_neg(&a, &a); + + m = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&b, labs(m)); + if (m < 0) + mp_neg(&b, &b); + + mp_set_int(&d, labs(l | m)); + if ((l | m) < 0) + mp_neg(&d, &d); + + mp_tc_or(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_tc_or() bad result!"); + return EXIT_FAILURE; + } + } + + // test mp_tc_and + printf("\n\nTesting: mp_tc_and"); + for (i = 0; i < 1000; ++i) { + int l, m; + + l = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&a, labs(l)); + if (l < 0) + mp_neg(&a, &a); + + m = (rand() * rand() + 1) * (rand() % 1 ? -1 : 1); + mp_set_int(&b, labs(m)); + if (m < 0) + mp_neg(&b, &b); + + mp_set_int(&d, labs(l & m)); + if ((l & m) < 0) + mp_neg(&d, &d); + + mp_tc_and(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_tc_and() bad result!"); + return EXIT_FAILURE; + } + } + // test mp_get_int printf("\n\nTesting: mp_get_int"); for (i = 0; i < 1000; ++i) { diff --git a/tommath.h b/tommath.h index 795cf10..c048777 100644 --- a/tommath.h +++ b/tommath.h @@ -292,8 +292,23 @@ int mp_or(const mp_int *a, const mp_int *b, mp_int *c); /* c = a AND b */ int mp_and(const mp_int *a, const mp_int *b, mp_int *c); +/* c = a XOR b (two complement) */ +int mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a OR b (two complement) */ +int mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a AND b (two complement) */ +int mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c); + +/* right shift (two complement) */ +int mp_tc_div_2d(const mp_int *a, int b, mp_int *c); + /* ---> Basic arithmetic <--- */ +/* b = ~a */ +int mp_complement(const mp_int *a, mp_int *b); + /* b = -a */ int mp_neg(const mp_int *a, mp_int *b);