ajout du dossier code
This commit is contained in:
17
code/Makefile
Normal file
17
code/Makefile
Normal file
@@ -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
|
||||
737
code/big.c
Normal file
737
code/big.c
Normal file
@@ -0,0 +1,737 @@
|
||||
#include "big.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;i<self->size;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'<str[index]<'9'
|
||||
if(val>='0' && val<='9'){
|
||||
return (int)(val-'0');
|
||||
|
||||
//case 'A'<str[index]<'Z'
|
||||
} else if(val>='A' && val<='Z'){
|
||||
return (int)(val-'0'-('A'-'9'-1));
|
||||
|
||||
//case 'a'<str[index]<'z'
|
||||
} else if(val>='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'&& i<length-1){
|
||||
i++;
|
||||
}
|
||||
size_t first_digit=i;
|
||||
|
||||
//initializing the bign
|
||||
self->size=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;i<self->size;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->size<rhs->size){
|
||||
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]<rhs->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(i<self->size){
|
||||
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<n;i++){
|
||||
|
||||
//cases when i is higher than the size of one of the numbers
|
||||
if(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<n;i++){
|
||||
|
||||
// case when the size of rhs is smaller than lhs's
|
||||
if(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) {
|
||||
}
|
||||
BIN
code/big.gcda
Normal file
BIN
code/big.gcda
Normal file
Binary file not shown.
BIN
code/big.gcno
Normal file
BIN
code/big.gcno
Normal file
Binary file not shown.
79
code/big.h
Normal file
79
code/big.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef BIG_H
|
||||
#define BIG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
BIN
code/big.o
Normal file
BIN
code/big.o
Normal file
Binary file not shown.
BIN
code/testbig
Normal file
BIN
code/testbig
Normal file
Binary file not shown.
3182
code/testbig.cc
Normal file
3182
code/testbig.cc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
code/testbig.gcda
Normal file
BIN
code/testbig.gcda
Normal file
Binary file not shown.
Reference in New Issue
Block a user