add mp_complement, mp_tc_div_2d, mp_tc_and, mp_tc_or, mp_tc_xor

This commit is contained in:
Daniel Mendler 2018-09-10 18:48:58 +02:00
parent bc685fd4a5
commit eebbcf0644
No known key found for this signature in database
GPG Key ID: D88ADB2A2693CA43
7 changed files with 468 additions and 0 deletions

26
bn_mp_complement.c Normal file
View File

@ -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$ */

90
bn_mp_tc_and.c Normal file
View File

@ -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$ */

36
bn_mp_tc_div_2d.c Normal file
View File

@ -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$ */

90
bn_mp_tc_or.c Normal file
View File

@ -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$ */

90
bn_mp_tc_xor.c Normal file
View File

@ -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$ */

View File

@ -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 // test mp_get_int
printf("\n\nTesting: mp_get_int"); printf("\n\nTesting: mp_get_int");
for (i = 0; i < 1000; ++i) { for (i = 0; i < 1000; ++i) {

View File

@ -292,8 +292,23 @@ int mp_or(const mp_int *a, const mp_int *b, mp_int *c);
/* c = a AND b */ /* c = a AND b */
int mp_and(const mp_int *a, const mp_int *b, mp_int *c); 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 <--- */ /* ---> Basic arithmetic <--- */
/* b = ~a */
int mp_complement(const mp_int *a, mp_int *b);
/* b = -a */ /* b = -a */
int mp_neg(const mp_int *a, mp_int *b); int mp_neg(const mp_int *a, mp_int *b);