From 9566ad747fe543bcdc7cf5f338d6133a5db9ba85 Mon Sep 17 00:00:00 2001 From: Janek Date: Mon, 19 Aug 2019 16:39:39 +0200 Subject: [PATCH 1/3] alternative multiplication --- bn.c | 39 +++++++++++++++++++++++++++++++++++++++ bn.h | 1 + 2 files changed, 40 insertions(+) diff --git a/bn.c b/bn.c index 7ec0895..40a5e9f 100644 --- a/bn.c +++ b/bn.c @@ -273,6 +273,45 @@ void bignum_mul(struct bn* a, struct bn* b, struct bn* c) } +void bignum_mul_alt(struct bn *a, struct bn *b, struct bn *c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + DTYPE_TMP tmp = 0; + DTYPE tmp_to_add = 0; + + int usable_len = BN_ARRAY_SIZE; + + /* this section speads up algorithm by "cutting" len of bignum*/ + for (int i = BN_ARRAY_SIZE - 1; i >= 0; --i) + { + if (a->array[i] != 0 || b->array[i] != 0) + { + usable_len = 2 * (i + 1); + break; + } + } + + usable_len = usable_len > BN_ARRAY_SIZE ? BN_ARRAY_SIZE : usable_len; + // + + for (int i = 0; i < usable_len; ++i) + { + c->array[i] += tmp_to_add; + tmp_to_add = tmp = 0; + for (int j = 0, k = i; j < i + 1 && j < usable_len; ++j, --k) + { + tmp = (DTYPE_TMP)a->array[j] * (DTYPE_TMP)b->array[k]; + tmp_to_add += tmp >> 32; + c->array[i] += tmp; + } + } +} + + void bignum_div(struct bn* a, struct bn* b, struct bn* c) { require(a, "a is null"); diff --git a/bn.h b/bn.h index f82676f..a2802e6 100644 --- a/bn.h +++ b/bn.h @@ -97,6 +97,7 @@ void bignum_to_string(struct bn* n, char* str, int maxsize); void bignum_add(struct bn* a, struct bn* b, struct bn* c); /* c = a + b */ void bignum_sub(struct bn* a, struct bn* b, struct bn* c); /* c = a - b */ void bignum_mul(struct bn* a, struct bn* b, struct bn* c); /* c = a * b */ +void bignum_mul_alt(struct bn* a, struct bn* b, struct bn* c); /* c = a * b alternative, much faster method*/ void bignum_div(struct bn* a, struct bn* b, struct bn* c); /* c = a / b */ void bignum_mod(struct bn* a, struct bn* b, struct bn* c); /* c = a % b */ void bignum_divmod(struct bn* a, struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ From e00f38c9f2c8548e21b0b7d9c950a3f29baaab74 Mon Sep 17 00:00:00 2001 From: Janek Date: Mon, 19 Aug 2019 16:44:44 +0200 Subject: [PATCH 2/3] alternative fast multiplication --- Makefile | 1 + bn.h | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 26e4dba..063f432 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ all: @$(CC) $(CFLAGS) bn.c ./tests/factorial.c -o ./build/test_factorial @$(CC) $(CFLAGS) bn.c ./tests/randomized.c -o ./build/test_random @#$(CC) $(CFLAGS) bn.c ./tests/rsa.c -o ./build/test_rsa + @$(CC) $(CFLAGS) bn.c ./tests/mul_test.c -o ./build/test_mul test: diff --git a/bn.h b/bn.h index a2802e6..b2e8723 100644 --- a/bn.h +++ b/bn.h @@ -29,8 +29,9 @@ There may well be room for performance-optimizations and improvements. #define WORD_SIZE 4 #endif -/* Size of big-numbers in bytes */ -#define BN_ARRAY_SIZE (128 / WORD_SIZE) +/* Size of big-numbers in WORDS */ // because you dividing by WORD size +// #define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 1024 /* Here comes the compile-time specialization for how large the underlying array size should be. */ From 68b1c866570c41cd311dbae943405017a02ab2f2 Mon Sep 17 00:00:00 2001 From: Janek Date: Mon, 19 Aug 2019 16:47:08 +0200 Subject: [PATCH 3/3] multiplication test added --- tests/mul_test.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 tests/mul_test.c diff --git a/tests/mul_test.c b/tests/mul_test.c new file mode 100644 index 0000000..a208fac --- /dev/null +++ b/tests/mul_test.c @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "bn.h" + +int mul_get_clocks(struct bn *a, struct bn *b, struct bn *c) +{ + int clocks = clock(); + bignum_mul(a, b, c); + return clock() - clocks; +} + +int mul_alt_get_clocks(struct bn *a, struct bn *b, struct bn *c) +{ + int clocks = clock(); + bignum_mul_alt(a, b, c); + return clock() - clocks; +} + +int int_test() +{ + struct bn a, b, c; + int clocks = 0, + clocks_alt = 0, + num1 = 0, + num2 = 0; + char res[17000] = {0}, + res_alt[17000] = {0}; + bignum_init(&a); + bignum_init(&b); + bignum_init(&c); + printf("method\tnum1\tnum2\tresult\tclocks\n"); + + for (int i = 0; i < 10; ++i) + { + num1 = rand(); + num2 = rand(); + + bignum_from_int(&a, num1); + bignum_from_int(&b, num2); + + clocks = mul_get_clocks(&a, &b, &c); + bignum_to_string(&c, res, 17000); + + clocks_alt = mul_alt_get_clocks(&a, &b, &c); + bignum_to_string(&c, res_alt, 17000); + + printf("normal\t%d\t%d\t%s\t%d\n", num1, num2, res, clocks); + printf("alter\t%d\t%d\t%s\t%d\n", num1, num2, res_alt, clocks_alt); + printf("\n"); + } + + return 0; +} + +int bigger_then_int_test() +{ + struct bn a, b, c; + int clocks = 0, + clocks_alt = 0; + char res[17000] = {0}, + res_alt[17000] = {0}, + num1[17000] = {0}, + num2[17000] = {0}; + + bignum_init(&a); + bignum_init(&b); + bignum_init(&c); + printf("method\tnum1\tnum2\tresult\tclocks\n"); + + for (int i = 0; i < 10; ++i) + { + a.array[0] = rand(); + a.array[1] = rand(); + a.array[2] = rand(); + a.array[3] = rand(); + + b.array[0] = rand(); + b.array[1] = rand(); + b.array[2] = rand(); + b.array[3] = rand(); + + bignum_to_string(&a, num1, 17000); + bignum_to_string(&b, num2, 17000); + + clocks = mul_get_clocks(&a, &b, &c); + bignum_to_string(&c, res, 17000); + + clocks_alt = mul_alt_get_clocks(&a, &b, &c); + bignum_to_string(&c, res_alt, 17000); + + printf("normal\t%s\t%s\t%s\t%d\n", num1, num2, res, clocks); + printf("alter\t%s\t%s\t%s\t%d\n", num1, num2, res_alt, clocks_alt); + printf("\n"); + } + + return 0; +} + +int main() +{ + srand(time(NULL)); + int_test(); + bigger_then_int_test(); + return 0; +}