-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbignum.c
114 lines (82 loc) · 2.67 KB
/
bignum.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "bignum.h"
long_number_t *new_number() {
long_number_t *number =(long_number_t*) malloc(sizeof(long_number_t));
number->count = 2;
number->values = (uint64_t *) malloc(sizeof(uint64_t) * number->count);
zero_number(number);
return number;
}
void zero_number(long_number_t *number) {
memset(number->values, 0, number->count*sizeof(uint64_t));
}
void add_digits (long_number_t *number) {
number->count *= 2;
uint64_t * old = number->values;
number->values = (uint64_t *) malloc(number->count*sizeof(uint64_t));
memset(number->values, 0, number->count*sizeof(uint64_t));
memcpy(number->values, old, number->count*sizeof(uint64_t)/2);
free(old);
}
void add_long_number(long_number_t *to, long_number_t *what) {
int posA = 0;
int carry = 0;
while (posA < what->count || carry) {
carry = 0;
if (posA < what->count) {
if (to->count <= posA) {
add_digits(to);
}
*(to->values + posA ) += *( what->values + posA );
}
if (*( to->values + posA ) >= BASE) {
if (to->count == posA+1 ) {
add_digits(to);
}
*( to->values + posA + 1 ) += *( to->values + posA ) / BASE;
*( to->values + posA ) = *( to->values + posA ) % BASE;
carry = 1;
}
posA++;
}
}
void print_long_number(long_number_t * ln) {
int offt = ln->count - 1 ;
while(ln->values[offt] == 0 && offt > 0)
offt--;
printf("%llu", ln->values[offt]);
int posA = offt -1;
while (posA >= 0) {
printf("%09llu", *(ln->values + posA));
posA--;
}
}
/*
abcde
efghk
---------
k(abcde)
h(abcde)
....
e(abcde)
*/
long_number_t *multiply_long_numbers(long_number_t *first, long_number_t *second) {
long_number_t *tmp = new_number();
for (int i = 0; i < second->count; i++) {
for (int j = 0; j < first->count; j++) {
if (tmp->count <= j + i) {
add_digits(tmp);
}
*(tmp->values + j + i) += *(second->values + i) * *(first->values + j);
//printf("%lu - %d %d\n", *(tmp->values + j + k), i, j);
if (*(tmp->values + j + i) >= BASE) {
if (tmp->count <= j + i +1 ) {
add_digits(tmp);
}
*(tmp->values + j + i + 1) += *(tmp->values + j + i) / BASE;
*(tmp->values + j + i) = *(tmp->values + j + i) % BASE;
}
}
}
//XXX normalize tmp caaried digits
return tmp;
}