commit edacf28b140bd16048db632ea0ed6f6cf4f19229 Author: robert_osada Date: Tue Jun 23 09:06:58 2026 +0200 ajout du dossier code diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 0000000..00131cf --- /dev/null +++ b/code/Makefile @@ -0,0 +1,17 @@ +GTEST_DIR = ./googletest/googletest + +CFLAGS = -Wall -Wextra -std=c99 -O2 -g -pedantic -fprofile-arcs -ftest-coverage +CXXFLAGS = -Wall -Wextra -std=c++11 -O2 -g -pedantic -I$(GTEST_DIR)/include -I$(GTEST_DIR) +LDFLAGS = -pthread -fprofile-arcs + + +TARGETS = testbig + +all: testbig + +clean: + rm -f *.o $(TARGETS) + rm -f *.gcda *.gcno *.gcov + +testbig: big.o ${GTEST_DIR}/src/gtest-all.o testbig.cc +big.o: big.c big.h diff --git a/code/big.c b/code/big.c new file mode 100644 index 0000000..5acc347 --- /dev/null +++ b/code/big.c @@ -0,0 +1,737 @@ +#include "big.h" + +#include +#include +#include +#include +#include + +#define CAPACITY 10 +#define BASE 0x100000000 + +void bign_create_empty(struct bign *self) { + //initializing an empty bign + self->data=NULL; + self->capacity= 0; + self->size=0; +} + + +void bign_create_from_value(struct bign *self, uint32_t val) { + //creating a bign out of a value + self->capacity=CAPACITY; + self->size=1; + self->data=malloc(self->capacity*sizeof(uint32_t)); + self->data[0]=val; + +} + + +//function that doubles the maximum capacity of a bign +void extend_capacity(struct bign *self){ + self->capacity=self->capacity*2; + //temp points to the curr array to keep the location + uint32_t *temp=self->data; + self->data=NULL; + + // allocating another mem segment to self->data + self->data=calloc(self->capacity,sizeof(uint32_t)); + for(size_t i=0;isize;i++){ + self->data[i]=temp[i]; + } + //freeing the previous array to avoid memory leaks + free(temp); +} + +//function that converts a hex char into an integer +uint32_t hex_char_to_int(char val){ + + //--------------------------------converting every char to an int + //case '0'='0' && val<='9'){ + return (int)(val-'0'); + + //case 'A'='A' && val<='Z'){ + return (int)(val-'0'-('A'-'9'-1)); + + //case 'a'='a' && val<='z'){ + return (int)(val-'0'-('a'-'9'-1)); + + } + return -1; +} + + + +void bign_create_from_string(struct bign *self, const char *str) { + //getting the index of the first digit that s not a 0 + size_t length=strlen(str); + size_t i=0; + while(str[i]=='0'&& isize=0; + self->capacity=CAPACITY; + self->data=calloc(self->capacity,sizeof(uint32_t)); + + int pow_16=1; + size_t index_curr=length-1; //index_curr is the index of the current char we re treating + size_t digit_bign=0; // index of the uint32_t we re working on + uint32_t tmp=0; //tmp is a temporary uint32_t used to add the char*pow16s together + size_t count=1; + + while(index_curr>first_digit ){ + + //ading up the hex digits with the powers of 16 + tmp+=hex_char_to_int(str[index_curr])*pow_16; + + pow_16=pow_16*16; //incrementing the power of 16 + index_curr--; + + //every 8 hex chars assining the uint32 digit the value of tmp and giving every variable their default value + if(count%8==0){ + self->size++; + //checking if we need to extend the capacity + if(self->size>=self->capacity){ + extend_capacity(self); + } + + self->data[digit_bign]=tmp; + digit_bign++; + pow_16=1; + tmp=0; + count=0; + } + count ++; + + } + // case when the initial str size%8!=0 or if the the size of the bign is still 0 + // which can occur if the index of the first non 0 diigt is 0 + if(count!=0 || self->size==0){ + self->size++; + self->data[digit_bign]=tmp+hex_char_to_int(str[index_curr])*pow_16; + } +} + + + +void bign_copy_from_other(struct bign *self, const struct bign *other) { + //if data was already allocated we re freeing it + if (self->data!=NULL){ + free(self->data); + } + + //allocating a new array to self->data + self->capacity=other->capacity; + self->data=calloc(self->capacity,sizeof(uint32_t)); + self->size=other->size; + + //copying every digit + for(size_t i=0;isize;i++){ + self->data[i]=other->data[i]; + } +} + +void bign_move_from_other(struct bign *self, struct bign *other) { + //if data was already allocated we re freeing it + if (self->data!=NULL){ + free(self->data); + } + //giving every value of other to self + self->capacity=other->capacity; + self->size=other->size; + self->data=other->data; + + //not freeing other->data cause it would erase the array that s also pointed by self->data + other->data=NULL; + other->capacity=0; + other->size=0; +} + +void bign_destroy(struct bign *self) { + //if data was already allocated we re freeing it + if(self->data!=NULL){ + free(self->data); + } + self->size=0; + self->capacity=0; + +} + +void bign_print(const struct bign *self) { + + if(self->size>0){ + //we re printing the number backwords + for(size_t i=self->size-1;i>0;i--){ + + printf("%08X_",self->data[i]); //%08x prints a uint32_t with the non significant 0s included + } + // and printing data[0] separately to avoid having an underscore after the number + printf("%08X",self->data[0]); + printf("\n"); + + } + + +} + +int bign_cmp(const struct bign *lhs, const struct bign *rhs) { + // comparing sizes + if(lhs->sizesize){ + return -1; + }else if(lhs->size>rhs->size){ + return 1; + } else { + + //if sizes are equal comparing every digit + for(size_t i =lhs->size;i>0;i--){ + if(lhs->data[i-1]>rhs->data[i-1]){ + return 1; + }else if(lhs->data[i-1]data[i-1]){ + return -1; + } + + } + + } + return 0; + + + +} + +int bign_cmp_zero(const struct bign *self) { + if(self->data[0]==0 && self->size==1){ + return 0; + } + return 1; +} +/* + *Les fonctions complémentaires + * + */ +uint32_t bign_get(const struct bign *self,size_t i){ + if(isize){ + return self->data[i]; + } + return 0; +} + +void bign_normalize(struct bign *self){ + size_t i = self->size-1; + while(self->data[i]==0 && i>0){ + self->size--; + i--; + } + +} + +//function that returns the bigger size out of 2 bigns +size_t max(size_t nb1, size_t nb2){ + if(nb1>nb2){ + return nb1; + } + return nb2; +} + + +void bign_add(struct bign *self, const struct bign *lhs, const struct bign *rhs) { + //if self is empty we create it from 0 + if(self->data==NULL){ + bign_create_from_value(self, 0); + } + + //initializing every local variable needed to calculate + size_t n = max(lhs->size,rhs->size); + uint64_t c=0; + uint64_t sum = 0; + + uint64_t digit1=0; + uint64_t digit2=0; + + //extending self's size/capacity to n+1 + size_t size=n+1; + while(size>self->capacity){ + extend_capacity(self); + } + self->size=size; + self->data[n]=0; //setting data[n]to 0 because it s the only value that we might not change (if c= 0 at the end) + + for(size_t i=0;i=lhs->size){ + digit1=0; + }else{digit1 = lhs->data[i]; } + + if(i>=rhs->size){ + digit2=0; + }else{ digit2 = rhs->data[i]; } + + //add algorithm application + sum = digit1+digit2+c; + self->data[i]=sum%BASE; + c=sum/BASE; + } + //adding c to data[n] + self->data[n]+=c; + + bign_normalize(self); + +} + + +void bign_sub(struct bign *self, const struct bign *lhs, const struct bign *rhs) { + //if self is empty we create it from 0 + if(self->data==NULL){ + bign_create_from_value(self, 0); + } + + //checking if the first number is bigger or equal to he second + if(bign_cmp(lhs,rhs)>=0){ + + uint32_t b=0; + uint64_t diff=0; + uint64_t digit2=0; + + //extending self's size/capacity to n+1 + size_t n = lhs->size; + size_t size=n+1; + while(size>self->capacity){ + extend_capacity(self); + } + self->size=size; + self->data[n]=0; + + for(size_t i=0;i=rhs->size){ + digit2=0; + }else{ digit2 = rhs->data[i]; } + + + //main algorithm + diff= lhs->data[i]-digit2-b; + self->data[i]=diff%BASE; + //making sure b(orrow) is [0;1] + if(diff/BASE>0){ + b=1; + } else { b=0; } + + } + + bign_normalize(self); + } + +} + +void bign_mul(struct bign *self, const struct bign *lhs, const struct bign *rhs) { + if(self->data==NULL){ + bign_create_from_value(self, 0); + } + + uint32_t c=0; + uint64_t tmp=0; + + size_t n = lhs->size; + size_t m = rhs->size; + size_t size=n+m+1; + //temporary array that holds the result + uint32_t *tmp_data=calloc(size+1,sizeof(uint32_t)); + + for (size_t i = 0; i < n; i++){ + + c=0; + for (size_t j = 0; j < m; j++){ + //casting the sum of uint32_t + tmp= (uint64_t)lhs->data[i]*rhs->data[j]+ tmp_data[i+j]+c; + + tmp_data[i+j]= tmp%BASE; + c= tmp/BASE; + } + if(c>0){ + tmp_data[i+m]=c; + } + } + //creating self out of the temporary array we allocated right above + free(self->data); + self->size=size; + self->data=tmp_data; + self->capacity=size+1; + bign_normalize(self); + +} + + +void bign_mul_karatsuba(struct bign *self, const struct bign *lhs, const struct bign *rhs) { +} + +void bign_mul_short(struct bign *self, const struct bign *lhs, uint32_t rhs) { + //making a bign out of the initial uint32_t to be able to use the mul functions + struct bign tmp_big; + bign_create_from_value(&tmp_big,rhs); + + bign_mul(self,lhs,&tmp_big); + bign_destroy(&tmp_big); +} + +// https://janmr.com/blog/2012/11/basic-multiple-precision-short-division/ +void bign_div_short(struct bign *quo, uint32_t *rem, const struct bign *lhs, uint32_t rhs) { + + if(rhs !=0){ + uint64_t temp=0; + + for(size_t k =lhs->size; k>0; k--){ + + temp=(uint64_t)(*rem*BASE+lhs->data[k-1]); + quo->data[k-1]=temp/rhs; + *rem=temp%rhs; + } + + } + +} + + +// https://janmr.com/blog/2014/04/basic-multiple-precision-long-division/ +void bign_div(struct bign *quo, struct bign *rem, const struct bign *lhs, const struct bign *rhs) { + //initializing quo and rem at 0x0 + if(quo->data!=NULL){ + bign_destroy(quo); + } + if(rem->data!=NULL){ + bign_destroy(rem); + } + bign_create_from_value(quo, 0); + bign_create_from_value(rem, 0); + + + //case when rhs is a one digit bign + if(rhs->size==1){ + while(lhs->size>=quo->capacity){ + extend_capacity(quo); + } + quo->size=lhs->size; + + bign_div_short(quo, rem->data, lhs, rhs->data[0]); + } + + //normalizing the bigns + bign_normalize(quo); + bign_normalize(rem); + +} + + +void expo(struct bign *lhs, struct bign *rhs, struct bign *self){ + //the bign that s going to be returned + struct bign tmp; + bign_create_from_value(&tmp, 1); + + uint32_t r=0; + + + //case when n = 0 + if(bign_cmp_zero(rhs)== 0){ + bign_move_from_other(self, &tmp); + + //case when n=1 + }else if(bign_cmp(rhs,&tmp)==0 ){ + bign_move_from_other(self, lhs); + }else{ + + //dividing the n by 2 + bign_div_short(&tmp, &r, rhs, 2); + + //n is even + if(r==0){ + // rhs = rhs/2 + bign_move_from_other(rhs, &tmp); + //lhs = lhs² + bign_mul(lhs,lhs,lhs); + + expo(lhs,rhs,self); + + //n is odd + } else { + + // rhs = (rhs-1)/2 + bign_move_from_other(rhs, &tmp); + + //keeping in memory the value of lhs + bign_copy_from_other(&tmp, lhs); + + //lhs = lhs² + bign_mul(lhs,lhs,lhs); + + expo(lhs,rhs,self); + + bign_mul(lhs, lhs, &tmp); //multiplication by lhs + } + + } + + bign_destroy(&tmp); + +} + + +void bign_exp(struct bign *self, const struct bign *lhs, const struct bign *rhs) { + + bign_destroy(self); + + //copies of lhs and rhs + struct bign big_l; + bign_create_empty(&big_l); + bign_copy_from_other(&big_l, lhs); + + struct bign big_r; + bign_create_empty(&big_r); + bign_copy_from_other(&big_r, rhs); + + + //isolating the case when lhs ==0 + if(bign_cmp_zero(lhs)==0){ + bign_create_from_value(self, 0); + } else { + expo(&big_l, &big_r, self); + } + + //destroying the copies + bign_destroy(&big_l); + bign_destroy(&big_r); + + bign_normalize(self); +} + + +/* + * + * bigz + * + */ + +void bigz_create_empty(struct bigz *self) { + self->positive=true; + bign_create_empty(&self->n); +} + +void bigz_create_from_value(struct bigz *self, int32_t val) { + if(val<0){ + self->positive=false; + val=-val; + }else{ + self->positive=true; + } + bign_create_from_value(&self->n,val); + +} + + + +void bigz_create_from_string(struct bigz *self, const char *str, unsigned base) { + size_t i=1; + //checking if the number is >=0 or <0 + if(str[0]=='-'){ + bigz_create_from_value(self,hex_char_to_int(str[1])); + self->positive=false; + i=2; + } else { + bigz_create_from_value(self,hex_char_to_int(str[0])); + } + + struct bign tmp_big; + //using the algorithm to transform a str to an int + while(str[i]!='\0'){ + bign_create_from_value(&tmp_big,hex_char_to_int(str[i])); + bign_mul_short(&self->n,&self->n,base); //multiply the number by base + bign_add(&self->n,&self->n,&tmp_big); //add the next digit + + bign_destroy(&tmp_big); + + i++; + } + +} + +void bigz_copy_from_other(struct bigz *self, const struct bigz *other) { + bigz_destroy(self); + //assigning the values of other to self + self->n.capacity=other->n.capacity; + self->n.size=other->n.size; + self->positive=other->positive; + + //copying every digit to self + self->n.data=calloc(self->n.capacity, sizeof(uint32_t)); + for (size_t i = 0; i < self->n.size; i++) + { + self->n.data[i]=other->n.data[i]; + } + + +} + +void bigz_move_from_other(struct bigz *self, struct bigz *other) { + bigz_destroy(self); + //assigning the values of other to self + self->n.capacity=other->n.capacity; + self->n.size=other->n.size; + self->positive=other->positive; + + //self->data points the same array as other->data + self->n.data=other->n.data; + //other points to NULL to make other destroyable + other->n.data=NULL; + bigz_destroy(other); + +} + +void bigz_destroy(struct bigz *self) { + bign_destroy(&self->n); + self->positive=true; + +} + +void bigz_print(const struct bigz *self) { + if(!self->positive){ + printf("-"); + } + bign_print(&self->n); +} + +int bigz_cmp(const struct bigz *lhs, const struct bigz *rhs) { + if(bigz_cmp_zero(lhs)==0 && bigz_cmp_zero(rhs)==0){ + return 0; + } + + if(lhs->positive && !rhs->positive){ + return 1; + } + if(!lhs->positive && rhs->positive){ + return -1; + } + if(!lhs->positive && !rhs->positive){ + return -bign_cmp(&lhs->n, &rhs->n); + } + return bign_cmp(&lhs->n, &rhs->n); + +} + +int bigz_cmp_zero(const struct bigz *self) { + if(self->n.size==1 && self->n.data[0]==0){ + return 0; + } + if(!self->positive){ + return -1; + } + return 1; +} + +void bigz_add(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs) { + if(self->n.data==NULL){ + bigz_create_from_value(self, 0); + } + + // if same sign + if(lhs->positive==rhs->positive){ + self->positive=lhs->positive; + bign_add(&self->n,&lhs->n,&rhs->n); + + // if rhs <0 + } else if(lhs->positive && !rhs->positive){ + //if lhs value greater than rhs value + if(bign_cmp(&lhs->n,&rhs->n)>=0){ + self->positive=true; + bign_sub(&self->n, &lhs->n, &rhs->n); + //if rhs value greater than lhs value + } else { + self->positive=false; + bign_sub (&self->n, &rhs->n, &lhs->n); + + } + + //if lhs<0 + }else { + //if lhs value greater than rhs value + if(bign_cmp(&lhs->n,&rhs->n)>=0){ + self->positive=false; + bign_sub(&self->n, &lhs->n, &rhs->n); + //if rhs value greater than lhs value + } else { + self->positive=true; + bign_sub (&self->n, &rhs->n, &lhs->n); + + } + } + + +} + +void bigz_sub(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs) { + if(self->n.data==NULL){ + bigz_create_from_value(self, 0); + } + + //lhs=>0 && rhs<0 + if(lhs->positive && !rhs->positive){ + self->positive=true; + bign_add(&self->n, &lhs->n, &rhs->n); + + //lhs<0 && rhs>=0 + } else if(!lhs->positive && rhs->positive){ + self->positive=false; + bign_add(&self->n, &lhs->n, &rhs->n); + + //lhs>=0 && rhs>=0 + } else if(lhs->positive && rhs->positive){ + if(bign_cmp(&lhs->n,&rhs->n)>=0){ + self->positive=true; + bign_sub(&self->n, &lhs->n, &rhs->n); + } else { + self->positive=false; + bign_sub(&self->n, &rhs->n, &lhs->n); + } + //lhs<0 && rhs<0 + } else { + if(bign_cmp(&lhs->n,&rhs->n)>=0){ + self->positive=false; + bign_sub(&self->n, &lhs->n, &rhs->n); + } else { + self->positive=true; + bign_sub(&self->n, &rhs->n, &lhs->n); + } + + } + + + +} + +void bigz_mul(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs) { + if(self->n.data==NULL){ + bigz_create_from_value(self, 0); + } + + bign_mul(&self->n, &lhs->n, &rhs->n); + //case when same sign + if(lhs->positive==rhs->positive){ + self->positive=true; + //case when different signs + } else { + self->positive=false; + } + + +} + +void bigz_div(struct bigz *quo, struct bigz *rem, const struct bigz *lhs, const struct bigz *rhs) { +} + +void bigz_gcd(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs) { +} diff --git a/code/big.gcda b/code/big.gcda new file mode 100644 index 0000000..8c01e77 Binary files /dev/null and b/code/big.gcda differ diff --git a/code/big.gcno b/code/big.gcno new file mode 100644 index 0000000..73dd241 Binary files /dev/null and b/code/big.gcno differ diff --git a/code/big.h b/code/big.h new file mode 100644 index 0000000..b91ade4 --- /dev/null +++ b/code/big.h @@ -0,0 +1,79 @@ +#ifndef BIG_H +#define BIG_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bign { + uint32_t *data; + size_t capacity; + size_t size; +}; + + +void bign_create_empty(struct bign *self); +void bign_create_from_value(struct bign *self, uint32_t val); +void bign_create_from_string(struct bign *self, const char *str); + +void bign_copy_from_other(struct bign *self, const struct bign *other); +void bign_move_from_other(struct bign *self, struct bign *other); + +void bign_destroy(struct bign *self); + +void bign_print(const struct bign *self); + +int bign_cmp(const struct bign *lhs, const struct bign *rhs); +int bign_cmp_zero(const struct bign *self); + +void bign_add(struct bign *self, const struct bign *lhs, const struct bign *rhs); +void bign_sub(struct bign *self, const struct bign *lhs, const struct bign *rhs); + +void bign_mul(struct bign *self, const struct bign *lhs, const struct bign *rhs); +void bign_mul_karatsuba(struct bign *self, const struct bign *lhs, const struct bign *rhs); +void bign_mul_short(struct bign *self, const struct bign *lhs, uint32_t rhs); + +void bign_div_short(struct bign *quo, uint32_t *rem, const struct bign *lhs, uint32_t rhs); +void bign_div(struct bign *quo, struct bign *rem, const struct bign *lhs, const struct bign *rhs); + +void bign_exp(struct bign *self, const struct bign *lhs, const struct bign *rhs); + + +struct bigz { + bool positive; + struct bign n; +}; + + +void bigz_create_empty(struct bigz *self); +void bigz_create_from_value(struct bigz *self, int32_t val); +void bigz_create_from_string(struct bigz *self, const char *str, unsigned base); + +void bigz_copy_from_other(struct bigz *self, const struct bigz *other); +void bigz_move_from_other(struct bigz *self, struct bigz *other); + +void bigz_destroy(struct bigz *self); + +void bigz_print(const struct bigz *self); + +int bigz_cmp(const struct bigz *lhs, const struct bigz *rhs); +int bigz_cmp_zero(const struct bigz *self); + +void bigz_add(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs); +void bigz_sub(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs); + +void bigz_mul(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs); +void bigz_div(struct bigz *quo, struct bigz *rem, const struct bigz *lhs, const struct bigz *rhs); + +void bigz_gcd(struct bigz *self, const struct bigz *lhs, const struct bigz *rhs); + +#ifdef __cplusplus +} +#endif + + +#endif // BIG_H diff --git a/code/big.o b/code/big.o new file mode 100644 index 0000000..dee0b4d Binary files /dev/null and b/code/big.o differ diff --git a/code/testbig b/code/testbig new file mode 100644 index 0000000..a563939 Binary files /dev/null and b/code/testbig differ diff --git a/code/testbig.cc b/code/testbig.cc new file mode 100644 index 0000000..d6159de --- /dev/null +++ b/code/testbig.cc @@ -0,0 +1,3182 @@ +#include "big.h" + +#include + +#include "gtest/gtest.h" + +static int bign_compare_to(const struct bign *b, const char *ref) { + if (b->data == nullptr) { + return 4242; + } + + struct bign bref; + bign_create_from_string(&bref, ref); + int cmp = bign_cmp(b, &bref); + bign_destroy(&bref); + return cmp; +} + +static void bign_create_random(struct bign *self) { + static const int SizeMin = 3; + static const int SizeMax = 50; + int size = SizeMin + std::rand() / (RAND_MAX / (SizeMax - SizeMin)); + assert(SizeMin <= size && size <= SizeMax); + + self->size = size; + self->capacity = size; + self->data = static_cast(std::calloc(size, sizeof(uint32_t))); + + for (int i = 0; i < size; ++i) { + self->data[i] = (rand() << 16) + rand(); + } + + if (self->data[size - 1] == 0) { + self->data[size - 1] = 1; + } +} + +static int bigz_compare_to(const struct bigz *b, const char *ref, unsigned base) { + if (b->n.data == nullptr) { + return 4242; + } + + struct bigz bref; + bigz_create_from_string(&bref, ref, base); + + int cmp = bigz_cmp(b, &bref); + bigz_destroy(&bref); + return cmp; +} + +TEST(BigN, CreateEmpty) { + struct bign b1; + bign_create_empty(&b1); + + EXPECT_EQ(b1.size, 0u); + EXPECT_EQ(b1.data, nullptr); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromValue) { + struct bign b1; + bign_create_from_value(&b1, UINT32_C(42)); + + EXPECT_EQ(b1.size, 1u); + EXPECT_EQ(b1.data[0], UINT32_C(42)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringZero) { + struct bign b1; + bign_create_from_string(&b1, "0"); + + EXPECT_EQ(b1.size, 1u); + EXPECT_EQ(b1.data[0], UINT32_C(0)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringZeroes) { + struct bign b1; + bign_create_from_string(&b1, "00000000"); + + EXPECT_EQ(b1.size, 1u); + EXPECT_EQ(b1.data[0], UINT32_C(0)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringDigit) { + struct bign b1; + bign_create_from_string(&b1, "29A"); + + EXPECT_EQ(b1.size, 1u); + EXPECT_EQ(b1.data[0], UINT32_C(0x29A)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringLong) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + EXPECT_EQ(b1.size, 6u); + EXPECT_EQ(b1.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b1.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b1.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b1.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b1.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b1.data[0], UINT32_C(0x32F1C3F2)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringAllDigit) { + struct bign b1; + bign_create_from_string(&b1, "0123456789ABCDEFabcdef"); + + EXPECT_EQ(b1.size, 3u); + EXPECT_EQ(b1.data[2], UINT32_C(0x012345)); + EXPECT_EQ(b1.data[1], UINT32_C(0x6789ABCD)); + EXPECT_EQ(b1.data[0], UINT32_C(0xEFABCDEF)); + + bign_destroy(&b1); +} + +TEST(BigN, CreateFromStringWithZero) { + struct bign b1; + bign_create_from_string(&b1, "0000000000000042"); + + EXPECT_EQ(b1.size, 1u); + EXPECT_EQ(b1.data[0], UINT32_C(0x42)); + + bign_destroy(&b1); +} + +TEST(BigN, CmpSame) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + int cmp = bign_cmp(&b1, &b1); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b1); +} + +TEST(BigN, CmpEqual) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + int cmp = bign_cmp(&b1, &b2); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CmpSameSizeGreater) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F1"); + + int cmp = bign_cmp(&b1, &b2); + EXPECT_GT(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CmpSameSizeLower) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F3"); + + int cmp = bign_cmp(&b1, &b2); + EXPECT_LT(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CmpDifferentSize) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_value(&b2, UINT32_C(42)); + + { + int cmp = bign_cmp(&b1, &b2); + EXPECT_GT(cmp, 0); + } + + { + int cmp = bign_cmp(&b2, &b1); + EXPECT_LT(cmp, 0); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CmpToZero) { + struct bign b1; + bign_create_from_string(&b1, "0000000000000000"); + + struct bign b2; + bign_create_from_string(&b2, "0000000100000000"); + + int cmp = bign_cmp(&b1, &b2); + EXPECT_LT(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CmpZeroEqual) { + struct bign b1; + bign_create_from_string(&b1, "0"); + + int cmp = bign_cmp_zero(&b1); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b1); +} + +TEST(BigN, CmpZeroZeroEqual) { + struct bign b1; + bign_create_from_string(&b1, "0000000000000000"); + + int cmp = bign_cmp_zero(&b1); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b1); +} + +TEST(BigN, CmpZeroDifferent) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + int cmp = bign_cmp_zero(&b1); + EXPECT_GT(cmp, 0); + + bign_destroy(&b1); +} + +TEST(BigN, Copy) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_empty(&b2); + + bign_copy_from_other(&b2, &b1); + + EXPECT_EQ(b2.size, 6u); + + if (b2.size == 6u) { + EXPECT_EQ(b2.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(bign_cmp(&b1, &b2), 0); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, CopyInNonEmpty) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "158EFA739BFA8362FBCD"); + + bign_copy_from_other(&b2, &b1); + + EXPECT_EQ(b2.size, 6u); + + if (b2.size == 6u) { + EXPECT_EQ(b2.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(bign_cmp(&b1, &b2), 0); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, Move) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + uint32_t *ptr = b1.data; + + struct bign b2; + bign_create_empty(&b2); + + bign_move_from_other(&b2, &b1); + + EXPECT_EQ(b2.size, 6u); + + if (b2.size == 6u) { + + EXPECT_EQ(b2.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(ptr, b2.data); + + EXPECT_EQ(b1.size, 0u); + EXPECT_EQ(b1.capacity, 0u); + EXPECT_EQ(b1.data, nullptr); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MoveInNonEmpty) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + uint32_t *ptr = b1.data; + + struct bign b2; + bign_create_from_string(&b2, "158EFA739BFA8362FBCD"); + + bign_move_from_other(&b2, &b1); + + EXPECT_EQ(b2.size, 6u); + + if (b2.size == 6u) { + + EXPECT_EQ(b2.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(ptr, b2.data); + + EXPECT_EQ(b1.size, 0u); + EXPECT_EQ(b1.capacity, 0u); + EXPECT_EQ(b1.data, nullptr); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, Print) { + struct bign b1; + bign_create_from_string(&b1, "0000000000000000A948CDEA56730000000BFF0782B30000000032F1C3F2"); + + bign_print(&b1); puts(""); + + bign_destroy(&b1); +} + +/* + * add + */ + +TEST(BigN, AddSingleDigit) { + struct bign b1; + bign_create_from_string(&b1, "12"); + + struct bign b2; + bign_create_from_string(&b2, "34"); + + struct bign b3; + bign_create_empty(&b3); + + bign_add(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "46"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddSingleDigitToSelf) { + struct bign b1; + bign_create_from_string(&b1, "12"); + + struct bign b2; + bign_create_from_string(&b2, "34"); + + bign_add(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "46"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddManyDigits) { + struct bign b1; + bign_create_from_string(&b1, "1212121212121212"); + + struct bign b2; + bign_create_from_string(&b2, "3434343434343434"); + + struct bign b3; + bign_create_empty(&b3); + + bign_add(&b3, &b1, &b2); + + + int cmp = bign_compare_to(&b3, "4646464646464646"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddManyDigitsToSelf) { + struct bign b1; + bign_create_from_string(&b1, "1212121212121212"); + + struct bign b2; + bign_create_from_string(&b2, "3434343434343434"); + + bign_add(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "4646464646464646"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddManyDigitsWithCarry) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "1"); + + struct bign b3; + bign_create_empty(&b3); + + bign_add(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "10000000000000000"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddManyDigitsWithCarryToSelf) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "1"); + + bign_add(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "10000000000000000"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, AddMax) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFFFFFFFFFF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_add(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1fffffffffffffffe"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +/* + * sub + */ + +TEST(BigN, SubSingleDigit) { + struct bign b1; + bign_create_from_string(&b1, "46"); + + struct bign b2; + bign_create_from_string(&b2, "34"); + + struct bign b3; + bign_create_empty(&b3); + + bign_sub(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubSingleDigitToSelf) { + struct bign b1; + bign_create_from_string(&b1, "46"); + + struct bign b2; + bign_create_from_string(&b2, "34"); + + bign_sub(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubManyDigits) { + struct bign b1; + bign_create_from_string(&b1, "4646464646464646"); + + struct bign b2; + bign_create_from_string(&b2, "3434343434343434"); + + struct bign b3; + bign_create_empty(&b3); + + bign_sub(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1212121212121212"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubManyDigitsToSelf) { + struct bign b1; + bign_create_from_string(&b1, "4646464646464646"); + + struct bign b2; + bign_create_from_string(&b2, "3434343434343434"); + + bign_sub(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "1212121212121212"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubManyDigitsWithCarry) { + struct bign b1; + bign_create_from_string(&b1, "10000000000000000"); + + struct bign b2; + bign_create_from_string(&b2, "1"); + + struct bign b3; + bign_create_empty(&b3); + + bign_sub(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "FFFFFFFFFFFFFFFF"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubManyDigitsWithCarryToSelf) { + struct bign b1; + bign_create_from_string(&b1, "10000000000000000"); + + struct bign b2; + bign_create_from_string(&b2, "1"); + + bign_sub(&b1, &b1, &b2); + int cmp = bign_compare_to(&b1, "FFFFFFFFFFFFFFFF"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, SubMax) { + struct bign b1; + bign_create_from_string(&b1, "10000000000000000"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFFFFFFFFFF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_sub(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + + +// TODO: X - 0 + +/* + * mul + */ + +TEST(BigN, MulSingleDigit) { + struct bign b1; + bign_create_from_string(&b1, "42"); + + struct bign b2; + bign_create_from_string(&b2, "69"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1b12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulSingleDigitToSelf) { + struct bign b1; + bign_create_from_string(&b1, "42"); + + struct bign b2; + bign_create_from_string(&b2, "69"); + + bign_mul(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "1b12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + + +TEST(BigN, MulManyDigits) { + struct bign b1; + bign_create_from_string(&b1, "69426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "12"); + + { + struct bign b3; + bign_create_empty(&b3); + bign_mul(&b3, &b1, &b2); + int cmp = bign_compare_to(&b3, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + bign_destroy(&b3); + } + + { + struct bign b3; + bign_create_empty(&b3); + bign_mul(&b3, &b2, &b1); + int cmp = bign_compare_to(&b3, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + bign_destroy(&b3); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulManyDigitsToSelf) { + struct bign b1; + bign_create_from_string(&b1, "69426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "12"); + + bign_mul(&b1, &b1, &b2); + int cmp = bign_compare_to(&b1, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + + +TEST(BigN, MulManyDigitsWithCarry) { + struct bign b1; + bign_create_from_string(&b1, "4269426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "1200000012"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul(&b3, &b1, &b2); + + + int cmp = bign_compare_to(&b3, "4ab66ab6b56cd56c8ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulManyDigitsWithCarryToSelf) { + struct bign b1; + bign_create_from_string(&b1, "4269426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "1200000012"); + + bign_mul(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "4ab66ab6b56cd56c8ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulMax) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFFFFFFFFFF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "fffffffffffffffe0000000000000001"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulRsa768) { + struct bign b1; + bign_create_from_string(&b1, "d982ec7b440e2869d2535e51f91bacc3eb6eba042e106e6f875c3d17e53db65fffd6e4e9a36084ce60f83d754dd7f701"); + + struct bign b2; + bign_create_from_string(&b2, "eebe6dd23ce7e99c0e2249fecc4418c34af74e418bfa714c3791828414ab18f32fd7e093062a49b030225cc845f99ab5"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "cad984557c97e039431a226ad727f0c6d43ef3d418469f1b375049b229843ee9f83b1f97738ac274f5f61f401f21f1913e4b64bb31b55a38d398c0dfed00b1392f0889711c44b359e7976c617fcc734f06e3e95c26476091b52f462e79413db5"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +/* + * mul short TODO + */ + + +/* + * mul karatsuba + */ + +TEST(BigN, MulKaratsubaSingleDigit) { + struct bign b1; + bign_create_from_string(&b1, "42"); + + struct bign b2; + bign_create_from_string(&b2, "69"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul_karatsuba(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1b12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulKaratsubaSingleDigitToSelf) { + struct bign b1; + bign_create_from_string(&b1, "42"); + + struct bign b2; + bign_create_from_string(&b2, "69"); + + bign_mul_karatsuba(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "1b12"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + + +TEST(BigN, MulKaratsubaManyDigits) { + struct bign b1; + bign_create_from_string(&b1, "69426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "12"); + + { + struct bign b3; + bign_create_empty(&b3); + bign_mul_karatsuba(&b3, &b1, &b2); + int cmp = bign_compare_to(&b3, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + bign_destroy(&b3); + } + + { + struct bign b3; + bign_create_empty(&b3); + bign_mul_karatsuba(&b3, &b2, &b1); + int cmp = bign_compare_to(&b3, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + bign_destroy(&b3); + } + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulKaratsubaManyDigitsToSelf) { + struct bign b1; + bign_create_from_string(&b1, "69426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "12"); + + bign_mul_karatsuba(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "766ab66ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + + +TEST(BigN, MulKaratsubaManyDigitsWithCarry) { + struct bign b1; + bign_create_from_string(&b1, "4269426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "1200000012"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul_karatsuba(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "4ab66ab6b56cd56c8ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulKaratsubaManyDigitsWithCarryToSelf) { + struct bign b1; + bign_create_from_string(&b1, "4269426942694269"); + + struct bign b2; + bign_create_from_string(&b2, "1200000012"); + + bign_mul_karatsuba(&b1, &b1, &b2); + + int cmp = bign_compare_to(&b1, "4ab66ab6b56cd56c8ab66ab62"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulKaratsubaMax) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFFFFFFFFFF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul_karatsuba(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "fffffffffffffffe0000000000000001"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, MulKaratsubaRsa768) { + struct bign b1; + bign_create_from_string(&b1, "d982ec7b440e2869d2535e51f91bacc3eb6eba042e106e6f875c3d17e53db65fffd6e4e9a36084ce60f83d754dd7f701"); + + struct bign b2; + bign_create_from_string(&b2, "eebe6dd23ce7e99c0e2249fecc4418c34af74e418bfa714c3791828414ab18f32fd7e093062a49b030225cc845f99ab5"); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul_karatsuba(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "cad984557c97e039431a226ad727f0c6d43ef3d418469f1b375049b229843ee9f83b1f97738ac274f5f61f401f21f1913e4b64bb31b55a38d398c0dfed00b1392f0889711c44b359e7976c617fcc734f06e3e95c26476091b52f462e79413db5"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +/* + * div + */ + +TEST(BigN, DivSingleDigit) { + struct bign b1; + bign_create_from_string(&b1, "69"); + + struct bign b2; + bign_create_from_string(&b2, "42"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + + int cmpq = bign_compare_to(&q, "1"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "27"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivSingleDigitReverse) { + struct bign b1; + bign_create_from_string(&b1, "69"); + + struct bign b2; + bign_create_from_string(&b2, "42"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b2, &b1); + + int cmpq = bign_compare_to(&q, "0"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "42"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivShort) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "4269"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + + + int cmpq = bign_compare_to(&q, "36d289377777bc42aa33c0180efb449c6ca5908b4dc2c"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "1de6"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivShortMax) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFF"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + + int cmpq = bign_compare_to(&q, "100000001"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "0"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivManyDigits) { + struct bign b1; + bign_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2"); + + struct bign b2; + bign_create_from_string(&b2, "426999FEAB350EB291B3F1098"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + + int cmpq = bign_compare_to(&q, "36d20a18b7884e2890017831"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "222ada30e45d62ecadb8056da"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivMax) { + struct bign b1; + bign_create_from_string(&b1, "FFFFFFFFFFFFFFFF"); + + struct bign b2; + bign_create_from_string(&b2, "FFFFFFFFFFFFFFFF"); + + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + + int cmpq = bign_compare_to(&q, "1"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "0"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + + +/* + * tests from http://www.hackersdelight.org/hdcodetxt/divmnu64.c.txt + * the first three tests are errors + */ + +TEST(BigN, DivCase3) { + // test #3 + struct bign b1; + bign_create_from_string(&b1, "00000003"); + struct bign b2; + bign_create_from_string(&b2, "00000002"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000001"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase4) { + // test #4 + struct bign b1; + bign_create_from_string(&b1, "00000003"); + struct bign b2; + bign_create_from_string(&b2, "00000003"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase5) { + // test #5 + struct bign b1; + bign_create_from_string(&b1, "00000003"); + struct bign b2; + bign_create_from_string(&b2, "00000004"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000003"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase6) { + // test #6 + struct bign b1; + bign_create_from_string(&b1, "00000000"); + struct bign b2; + bign_create_from_string(&b2, "ffffffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase7) { + // test #7 + struct bign b1; + bign_create_from_string(&b1, "ffffffff"); + struct bign b2; + bign_create_from_string(&b2, "00000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "ffffffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase8) { + // test #8 + struct bign b1; + bign_create_from_string(&b1, "ffffffff"); + struct bign b2; + bign_create_from_string(&b2, "ffffffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase9) { + // test #9 + struct bign b1; + bign_create_from_string(&b1, "ffffffff"); + struct bign b2; + bign_create_from_string(&b2, "00000003"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "55555555"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase10) { + // test #10 + struct bign b1; + bign_create_from_string(&b1, "ffffffffffffffff"); + struct bign b2; + bign_create_from_string(&b2, "00000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "ffffffffffffffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase11) { + // test #11 + struct bign b1; + bign_create_from_string(&b1, "ffffffffffffffff"); + struct bign b2; + bign_create_from_string(&b2, "ffffffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "0000000100000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase12) { + // test #12 + struct bign b1; + bign_create_from_string(&b1, "fffffffeffffffff"); + struct bign b2; + bign_create_from_string(&b2, "ffffffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000ffffffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "fffffffe"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase13) { + // test #13 + struct bign b1; + bign_create_from_string(&b1, "0000123400005678"); + struct bign b2; + bign_create_from_string(&b2, "00009abc"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "000000001e1dba76"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00006bd0"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase14) { + // test #14 + struct bign b1; + bign_create_from_string(&b1, "0000000000000000"); + struct bign b2; + bign_create_from_string(&b2, "0000000100000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase15) { + // test #15 + struct bign b1; + bign_create_from_string(&b1, "0000000700000000"); + struct bign b2; + bign_create_from_string(&b2, "0000000300000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000002"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000100000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase16) { + // test #16 + struct bign b1; + bign_create_from_string(&b1, "0000000700000005"); + struct bign b2; + bign_create_from_string(&b2, "0000000300000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000002"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000100000005"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase17) { + // test #17 + struct bign b1; + bign_create_from_string(&b1, "0000000600000000"); + struct bign b2; + bign_create_from_string(&b2, "0000000200000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000003"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase18) { + // test #18 + struct bign b1; + bign_create_from_string(&b1, "80000000"); + struct bign b2; + bign_create_from_string(&b2, "40000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "3fffffff"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase19) { + // test #19 + struct bign b1; + bign_create_from_string(&b1, "8000000000000000"); + struct bign b2; + bign_create_from_string(&b2, "40000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001fffffff8"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000008"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase20) { + // test #20 + struct bign b1; + bign_create_from_string(&b1, "8000000000000000"); + struct bign b2; + bign_create_from_string(&b2, "4000000000000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "3fffffffffffffff"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase21) { + // test #21 + struct bign b1; + bign_create_from_string(&b1, "0000bcde0000789a"); + struct bign b2; + bign_create_from_string(&b2, "0000bcde0000789a"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase22) { + // test #22 + struct bign b1; + bign_create_from_string(&b1, "0000bcde0000789b"); + struct bign b2; + bign_create_from_string(&b2, "0000bcde0000789a"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000000000001"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase23) { + // test #23 + struct bign b1; + bign_create_from_string(&b1, "0000bcde00007899"); + struct bign b2; + bign_create_from_string(&b2, "0000bcde0000789a"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000bcde00007899"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase24) { + // test #24 + struct bign b1; + bign_create_from_string(&b1, "0000ffff0000ffff"); + struct bign b2; + bign_create_from_string(&b2, "0000ffff0000ffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000001"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "0000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase25) { + // test #25 + struct bign b1; + bign_create_from_string(&b1, "0000ffff0000ffff"); + struct bign b2; + bign_create_from_string(&b2, "0000000100000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "0000ffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "000000000000ffff"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase26) { + // test #26 + struct bign b1; + bign_create_from_string(&b1, "0000012300004567000089ab"); + struct bign b2; + bign_create_from_string(&b2, "0000000100000000"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "0000012300004567"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000000089ab"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase27) { + // test #27 + // Shows that first qhat can = b + 1. + struct bign b1; + bign_create_from_string(&b1, "000080000000fffe00000000"); + + struct bign b2; + bign_create_from_string(&b2, "000080000000ffff"); + + struct bign q; + bign_create_empty(&q); + + struct bign r; + bign_create_empty(&r); + + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000ffffffff"); + EXPECT_EQ(cmpq, 0); + + int cmpr = bign_compare_to(&r, "00007fff0000ffff"); + EXPECT_EQ(cmpr, 0); + + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase28) { + // test #28 + // Adding back step req'd. + struct bign b1; + bign_create_from_string(&b1, "800000000000000000000003"); + struct bign b2; + bign_create_from_string(&b2, "200000000000000000000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000003"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "200000000000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase29) { + // test #29 + // Adding back step req'd. + struct bign b1; + bign_create_from_string(&b1, "000080000000000000000003"); + struct bign b2; + bign_create_from_string(&b2, "000020000000000000000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000003"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "000020000000000000000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase30) { + // test #30 + // Add back req'd. + struct bign b1; + bign_create_from_string(&b1, "00007fff000080000000000000000000"); + struct bign b2; + bign_create_from_string(&b2, "000080000000000000000001"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000fffe0000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00007fffffffffff00020000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase31) { + // test #31 + // Shows that mult-sub quantity cannot be treated as signed. + struct bign b1; + bign_create_from_string(&b1, "00008000000000000000fffe00000000"); + struct bign b2; + bign_create_from_string(&b2, "00008000000000000000ffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000ffffffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00007fffffffffff0000ffff"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase32) { + // test #32 + // Shows that mult-sub quantity cannot be treated as signed. + struct bign b1; + bign_create_from_string(&b1, "8000000000000000fffffffe00000000"); + struct bign b2; + bign_create_from_string(&b2, "80000000000000000000ffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "0000000100000000"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "00000000fffeffff00000000"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, DivCase33) { + // test #33 + // Shows that mult-sub quantity cannot be treated as signed. + struct bign b1; + bign_create_from_string(&b1, "8000000000000000fffffffe00000000"); + struct bign b2; + bign_create_from_string(&b2, "8000000000000000ffffffff"); + struct bign q; + bign_create_empty(&q); + struct bign r; + bign_create_empty(&r); + bign_div(&q, &r, &b1, &b2); + int cmpq = bign_compare_to(&q, "00000000ffffffff"); + EXPECT_EQ(cmpq, 0); + int cmpr = bign_compare_to(&r, "7fffffffffffffffffffffff"); + EXPECT_EQ(cmpr, 0); + bign_destroy(&r); + bign_destroy(&q); + bign_destroy(&b2); + bign_destroy(&b1); +} + + +/* + * exp + */ + +// exp( , 0) + +TEST(BigN, ExpXPowerZero) { + struct bign b1; + bign_create_from_string(&b1, "1234567890ABCDEF"); + + struct bign b2; + bign_create_from_string(&b2, "0"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp( , 1) + +TEST(BigN, ExpXPowerOne) { + struct bign b1; + bign_create_from_string(&b1, "1234567890ABCDEF"); + + struct bign b2; + bign_create_from_string(&b2, "1"); + + struct bign b3; + bign_create_empty(&b3); + + bign_print(&b3); + + bign_exp(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1234567890ABCDEF"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp(0, ) + +TEST(BigN, ExpZeroPowerN) { + struct bign b1; + bign_create_from_string(&b1, "0"); + + struct bign b2; + bign_create_from_string(&b2, "1234567890ABCDEF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "0"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp(1, ) + +TEST(BigN, ExpOnePowerN) { + struct bign b1; + bign_create_from_string(&b1, "1"); + + struct bign b2; + bign_create_from_string(&b2, "1234567890ABCDEF"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + int cmp = bign_compare_to(&b3, "1"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp(sm, sm) + +TEST(BigN, ExpSmallPowerSmall) { + struct bign b1; + bign_create_from_string(&b1, "31"); + + struct bign b2; + bign_create_from_string(&b2, "56"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + bign_print(&b3); + + int cmp = bign_compare_to(&b3, "7491caf9dd4e6cc7aa542df60f1437aad480c03e54f97e58230a7952097d3710e2c0af4562b67af9f8e46b8c40beaa50fadf46423471861e4efce4f21"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp(lg, sm) + +TEST(BigN, ExpLargePowerSmall) { + struct bign b1; + bign_create_from_string(&b1, "123456789"); + + struct bign b2; + bign_create_from_string(&b2, "13"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + bign_print(&b3); + + int cmp = bign_compare_to(&b3, "b9def572bcd526c6bc46607dde0446ad6da1f4c4302fd57a1bec55d6157b328aeabe4525706f87494c647dca5fd70e1c33bbc93a4291fcf0eb957d7262a84b96148baee40ed8836bbeef433d9"); + EXPECT_EQ(cmp, 0); + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +// exp(sm, lg) + +TEST(BigN, ExpSmallPowerLarge) { + struct bign b1; + bign_create_from_string(&b1, "2"); + + struct bign b2; + bign_create_from_string(&b2, "1000"); + + struct bign b3; + bign_create_empty(&b3); + + bign_exp(&b3, &b1, &b2); + + EXPECT_EQ(b3.size, 129u); + + if (b3.size == 129u) { + EXPECT_EQ(b3.data[128], UINT32_C(1)); + + for (int i = 0; i < 128; ++i) { + EXPECT_EQ(b3.data[i], UINT32_C(0)); + } + } + + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); +} + +TEST(BigN, RandomAddSub) { + static const int Iterations = 1000; + + for (int i = 0; i < Iterations; ++i) { + struct bign b1; + + bign_create_random(&b1); + + struct bign b2; + bign_create_random(&b2); + + struct bign b3; + bign_create_empty(&b3); + + + bign_add(&b3, &b1, &b2); + + struct bign b4; + bign_create_empty(&b4); + + + bign_sub(&b4, &b3, &b2); + + int cmp = bign_cmp(&b4, &b1); + + bign_destroy(&b4); + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); + + ASSERT_EQ(cmp, 0); + } + +} + +TEST(BigN, RandomMulMul) { + static const int Iterations = 100; + + for (int i = 0; i < Iterations; ++i) { + struct bign b1; + bign_create_random(&b1); + + struct bign b2; + bign_create_random(&b2); + + struct bign b3; + bign_create_empty(&b3); + + bign_mul(&b3, &b1, &b2); + + struct bign b4; + bign_create_empty(&b4); + + bign_mul_karatsuba(&b4, &b1, &b2); + + int cmp = bign_cmp(&b3, &b4); + + bign_destroy(&b4); + bign_destroy(&b3); + bign_destroy(&b2); + bign_destroy(&b1); + + ASSERT_EQ(cmp, 0); + } + +} + +TEST(BigN, RandomMulDiv) { + static const int Iterations = 1000; + + for (int i = 0; i < Iterations; ++i) { + struct bign b1; + bign_create_random(&b1); + + struct bign b2; + bign_create_random(&b2); + + struct bign quo; + bign_create_empty(&quo); + + struct bign rem; + bign_create_empty(&rem); + + bign_div(&quo, &rem, &b1, &b2); + + struct bign b3; + bign_create_random(&b3); + + bign_mul(&b3, &quo, &b2); + bign_add(&b3, &b3, &rem); + + int cmp = bign_cmp(&b3, &b1); + + bign_destroy(&b3); + bign_destroy(&rem); + bign_destroy(&quo); + bign_destroy(&b2); + bign_destroy(&b1); + + ASSERT_EQ(cmp, 0); + } + +} + +/* + * BigZ + */ + +TEST(BigZ, CreateEmpty) { + struct bigz b1; + bigz_create_empty(&b1); + + EXPECT_EQ(b1.n.size, 0u); + EXPECT_EQ(b1.n.data, nullptr); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromValuePositive) { + struct bigz b1; + bigz_create_from_value(&b1, INT32_C(42)); + + EXPECT_TRUE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], UINT32_C(42)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromValueNegative) { + struct bigz b1; + bigz_create_from_value(&b1, INT32_C(-42)); + + EXPECT_FALSE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], UINT32_C(42)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromValuePositiveMax) { + struct bigz b1; + bigz_create_from_value(&b1, INT32_MAX); + + uint32_t ref = INT32_MAX; + + EXPECT_TRUE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], ref); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromValueNegativeMin) { + struct bigz b1; + bigz_create_from_value(&b1, INT32_MIN); + + EXPECT_FALSE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], UINT32_C(2147483648)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromStringPositiveZero) { + struct bigz b1; + bigz_create_from_string(&b1, "0", 10); + + EXPECT_TRUE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], UINT32_C(0)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromStringNegativeZero) { + struct bigz b1; + bigz_create_from_string(&b1, "-0", 10); + + EXPECT_FALSE(b1.positive); + EXPECT_EQ(b1.n.size, 1u); + EXPECT_EQ(b1.n.data[0], UINT32_C(0)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromStringBinary) { + struct bigz b1; + bigz_create_from_string(&b1, "1001101101111010010010101101101011110110011100010001110111010001010001011110100010101010", 2); + + EXPECT_TRUE(b1.positive); + EXPECT_EQ(b1.n.size, 3u); + EXPECT_EQ(b1.n.data[0], UINT32_C(0xd145e8aa)); + EXPECT_EQ(b1.n.data[1], UINT32_C(0xdaf6711d)); + EXPECT_EQ(b1.n.data[2], UINT32_C(0x9b7a4a)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromStringDecimal) { + struct bigz b1; + bigz_create_from_string(&b1, "15497642151661527013020516797518124587412201", 10); + + EXPECT_TRUE(b1.positive); + EXPECT_EQ(b1.n.size, 5u); + EXPECT_EQ(b1.n.data[0], UINT32_C(0x1507eae9)); + EXPECT_EQ(b1.n.data[1], UINT32_C(0x7698c6e5)); + EXPECT_EQ(b1.n.data[2], UINT32_C(0x57589b7b)); + EXPECT_EQ(b1.n.data[3], UINT32_C(0x7a1cba70)); + EXPECT_EQ(b1.n.data[4], UINT32_C(0xb1e7)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CreateFromStringDecimalNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-15497642151661527013020516797518124587412201", 10); + + EXPECT_FALSE(b1.positive); + EXPECT_EQ(b1.n.size, 5u); + EXPECT_EQ(b1.n.data[0], UINT32_C(0x1507eae9)); + EXPECT_EQ(b1.n.data[1], UINT32_C(0x7698c6e5)); + EXPECT_EQ(b1.n.data[2], UINT32_C(0x57589b7b)); + EXPECT_EQ(b1.n.data[3], UINT32_C(0x7a1cba70)); + EXPECT_EQ(b1.n.data[4], UINT32_C(0xb1e7)); + + bigz_destroy(&b1); +} + +TEST(BigZ, CmpSame) { + struct bigz b1; + bigz_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + int cmp = bigz_cmp(&b1, &b1); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b1); +} + +TEST(BigZ, CmpEqualPositive) { + struct bigz b1; + bigz_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + struct bigz b2; + bigz_create_from_string(&b2, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + int cmp = bigz_cmp(&b1, &b2); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, CmpEqualNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + struct bigz b2; + bigz_create_from_string(&b2, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + int cmp = bigz_cmp(&b1, &b2); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, CmpDifferentSign) { + struct bigz b1; + bigz_create_from_string(&b1, "E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + struct bigz b2; + bigz_create_from_string(&b2, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + { + int cmp = bigz_cmp(&b1, &b2); + EXPECT_GT(cmp, 0); + } + + { + int cmp = bigz_cmp(&b2, &b1); + EXPECT_LT(cmp, 0); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +// TODO: negative negative + +TEST(BigZ, CmpPositiveNegativeZero) { + struct bigz b1; + bigz_create_from_string(&b1, "0", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-0", 10); + + { + int cmp = bigz_cmp(&b1, &b2); + EXPECT_EQ(cmp, 0); + } + + { + int cmp = bigz_cmp(&b2, &b1); + EXPECT_EQ(cmp, 0); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, CmpZeroEqualPositiveZero) { + struct bigz b1; + bigz_create_from_string(&b1, "0", 10); + + int cmp = bigz_cmp_zero(&b1); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b1); +} + +TEST(BigZ, CmpZeroEqualNegativeZero) { + struct bigz b1; + bigz_create_from_string(&b1, "-0", 10); + + int cmp = bigz_cmp_zero(&b1); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b1); +} + +TEST(BigZ, CmpZeroPositive) { + struct bigz b1; + bigz_create_from_string(&b1, "12345678987654321", 10); + + int cmp = bigz_cmp_zero(&b1); + EXPECT_GT(cmp, 0); + + bigz_destroy(&b1); +} + +TEST(BigZ, CmpZeroNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-12345678987654321", 10); + + int cmp = bigz_cmp_zero(&b1); + EXPECT_LT(cmp, 0); + + bigz_destroy(&b1); +} + + +TEST(BigZ, Copy) { + struct bigz b1; + bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + struct bigz b2; + bigz_create_empty(&b2); + + bigz_copy_from_other(&b2, &b1); + + EXPECT_FALSE(b2.positive); + EXPECT_EQ(b2.n.size, 6u); + + if (b2.n.size == 6u) { + EXPECT_EQ(b2.n.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.n.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.n.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.n.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.n.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.n.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(bigz_cmp(&b1, &b2), 0); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, CopyInNonEmpty) { + struct bigz b1; + bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + struct bigz b2; + bigz_create_from_string(&b2, "EF193C2DFAC33C2FF3D89274801", 16); + + bigz_copy_from_other(&b2, &b1); + + EXPECT_FALSE(b2.positive); + EXPECT_EQ(b2.n.size, 6u); + + if (b2.n.size == 6u) { + EXPECT_EQ(b2.n.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.n.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.n.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.n.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.n.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.n.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(bigz_cmp(&b1, &b2), 0); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, Move) { + struct bigz b1; + bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + uint32_t *ptr = b1.n.data; + + struct bigz b2; + bigz_create_empty(&b2); + + bigz_move_from_other(&b2, &b1); + + EXPECT_FALSE(b2.positive); + EXPECT_EQ(b2.n.size, 6u); + + if (b2.n.size == 6u) { + EXPECT_EQ(b2.n.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.n.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.n.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.n.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.n.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.n.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(ptr, b2.n.data); + + EXPECT_EQ(b1.n.size, 0u); + EXPECT_EQ(b1.n.capacity, 0u); + EXPECT_EQ(b1.n.data, nullptr); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, MoveInNonEmpty) { + struct bigz b1; + bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); + + uint32_t *ptr = b1.n.data; + + struct bigz b2; + bigz_create_from_string(&b2, "EF193C2DFAC33C2FF3D89274801", 16); + + bigz_move_from_other(&b2, &b1); + + EXPECT_FALSE(b2.positive); + EXPECT_EQ(b2.n.size, 6u); + + if (b2.n.size == 6u) { + EXPECT_EQ(b2.n.data[5], UINT32_C(0xE38C3BA9)); + EXPECT_EQ(b2.n.data[4], UINT32_C(0x48CDEA56)); + EXPECT_EQ(b2.n.data[3], UINT32_C(0x73926BFF)); + EXPECT_EQ(b2.n.data[2], UINT32_C(0xDBAECBF7)); + EXPECT_EQ(b2.n.data[1], UINT32_C(0x82B3F2C3)); + EXPECT_EQ(b2.n.data[0], UINT32_C(0x32F1C3F2)); + + EXPECT_EQ(ptr, b2.n.data); + + EXPECT_EQ(b1.n.size, 0u); + EXPECT_EQ(b1.n.capacity, 0u); + EXPECT_EQ(b1.n.data, nullptr); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +// TEST(BigZ, Print) { +// struct bigz b1; +// bigz_create_from_string(&b1, "-E38C3BA948CDEA5673926BFFDBAECBF782B3F2C332F1C3F2", 16); +// +// bigz_print(&b1); puts(""); +// +// bigz_destroy(&b1); +// } + +TEST(BigZ, AddPositivePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, AddPositiveNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-46578458745802102102145458458245485441416", 10); + + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, AddNegativePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, AddNegativeNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_add(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + + + + +TEST(BigZ, SubPositivePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, SubPositiveNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-46578458745802102102145458458245485441416", 10); + + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, SubNegativePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "324808583067597272281203376099393387231117", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, SubNegativeNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-46578458745802102102145458458245485441416", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_sub(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "231651665575993068076912459182902416348285", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + + +TEST(BigZ, MulPositivePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, MulPositiveNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, MulNegativePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "-1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "-1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, MulNegativeNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + { + struct bigz b3; + bigz_create_empty(&b3); + + bigz_mul(&b3, &b2, &b1); + + int cmp = bigz_compare_to(&b3, "1295953036756212640552727646158429498971649147282135793047210", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + } + + bigz_destroy(&b2); + bigz_destroy(&b1); +} + + +TEST(BigZ, DivPositivePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "2948551563409199521", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivPositiveNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "-59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "2948551563409199521", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivNegativePositive) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + // int cmpq = bigz_compare_to(&q, "-59733647658934344963858", 10); + int cmpq = bigz_compare_to(&q, "-59733647658934344963859", 10); + EXPECT_EQ(cmpq, 0); + + // int cmpr = bigz_compare_to(&r, "-2948551563409199521", 10); + int cmpr = bigz_compare_to(&r, "1709294311171010689", 10); + + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivNegativeNegative) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179057917641147901789701", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + // int cmpq = bigz_compare_to(&q, "59733647658934344963858", 10); + int cmpq = bigz_compare_to(&q, "59733647658934344963859", 10); + EXPECT_EQ(cmpq, 0); + + // int cmpr = bigz_compare_to(&r, "-2948551563409199521", 10); + int cmpr = bigz_compare_to(&r, "1709294311171010689", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + + + +TEST(BigZ, DivPositivePositiveZeroRemainder) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179054969089584492590180", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "0", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivPositiveNegativeZeroRemainder) { + struct bigz b1; + bigz_create_from_string(&b1, "278230124321795170179054969089584492590180", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "-59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "0", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivNegativePositiveZeroRemainder) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179054969089584492590180", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "-59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "0", 10); + + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, DivNegativeNegativeZeroRemainder) { + struct bigz b1; + bigz_create_from_string(&b1, "-278230124321795170179054969089584492590180", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "-4657845874580210210", 10); + + struct bigz q; + bigz_create_empty(&q); + + struct bigz r; + bigz_create_empty(&r); + + bigz_div(&q, &r, &b1, &b2); + + int cmpq = bigz_compare_to(&q, "59733647658934344963858", 10); + EXPECT_EQ(cmpq, 0); + + int cmpr = bigz_compare_to(&r, "0", 10); + EXPECT_EQ(cmpr, 0); + + bigz_destroy(&r); + bigz_destroy(&q); + bigz_destroy(&b2); + bigz_destroy(&b1); +} + +TEST(BigZ, GcdCoprime) { + struct bigz b1; + bigz_create_from_string(&b1, "1533918542734615245164352154619195752815244561235899341531", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "1533918542734615245164352154619195752815244561235899341532", 10); + + struct bigz b3; + bigz_create_empty(&b3); + + bigz_gcd(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "1", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + bigz_destroy(&b2); + bigz_destroy(&b1); + +} + +TEST(BigZ, GcdRsa768) { + struct bigz b1; + bigz_create_from_string(&b1, "d982ec7b440e2869d2535e51f91bacc3eb6eba042e106e6f875c3d17e53db65fffd6e4e9a36084ce60f83d754dd7f701", 16); + + struct bigz b2; + bigz_create_from_string(&b2, "eebe6dd23ce7e99c0e2249fecc4418c34af74e418bfa714c3791828414ab18f32fd7e093062a49b030225cc845f99ab5", 16); + + struct bigz b3; + bigz_create_empty(&b3); + + bigz_gcd(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "1", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + bigz_destroy(&b2); + bigz_destroy(&b1); + +} + +TEST(BigZ, GcdNotCoprime) { + struct bigz b1; + bigz_create_from_string(&b1, "829029200588685010168228367991253899050528829049", 10); + + struct bigz b2; + bigz_create_from_string(&b2, "92196793900174799975899442851691027900097961", 10); + + struct bigz b3; + bigz_create_empty(&b3); + + bigz_gcd(&b3, &b1, &b2); + + int cmp = bigz_compare_to(&b3, "97713221", 10); + EXPECT_EQ(cmp, 0); + + bigz_destroy(&b3); + bigz_destroy(&b2); + bigz_destroy(&b1); + +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/code/testbig.gcda b/code/testbig.gcda new file mode 100644 index 0000000..044aab5 Binary files /dev/null and b/code/testbig.gcda differ