Skip to content

Commit 1623320

Browse files
committed
Improve Big Number implementation
1 parent dcd6937 commit 1623320

File tree

1 file changed

+47
-28
lines changed

1 file changed

+47
-28
lines changed

lib/unsigned_bignum.h

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,30 @@ typedef struct BigN {
77
unsigned long long cell[BIGNSIZE];
88
} ubig;
99

10-
#define init_ubig(x) for (int i = 0; i < BIGNSIZE; x.cell[i++] = 0)
10+
static inline void init_ubig(ubig *x)
11+
{
12+
for (int i = 0; i < BIGNSIZE; x->cell[i++] = 0)
13+
;
14+
}
15+
16+
/**
17+
* ubig_add() - Add two large unsigned integers.
18+
* @dest: Pointer to the destination ubig where the result will be stored.
19+
* @a: Pointer to the first ubig.
20+
* @b: Pointer to the second ubig.
21+
*
22+
* This function performs addition of two large unsigned integers represented by
23+
* the `ubig` structures pointed to by @a and @b. The result of the addition is
24+
* stored in the `ubig` structure pointed to by @dest.
25+
*/
26+
static inline void ubig_add(ubig *dest, ubig *a, ubig *b)
27+
{
28+
for (int i = 0; i < BIGNSIZE; i++)
29+
dest->cell[i] = a->cell[i] + b->cell[i];
1130

12-
#define P10_UINT64 10000000000000000000ULL
31+
for (int i = 0; i < BIGNSIZE - 1; i++)
32+
dest->cell[i + 1] += (dest->cell[i] < a->cell[i]);
33+
}
1334

1435
/**
1536
* fib_sequence() - Calculate the k-th Fibonacci number.
@@ -21,28 +42,18 @@ static ubig fib_sequence(long long k)
2142
{
2243
if (k <= 1LL) {
2344
ubig result;
24-
init_ubig(result);
45+
init_ubig(&result);
2546
result.cell[0] = (unsigned long long) k;
2647
return result;
2748
}
2849

2950
ubig a, b, c;
30-
init_ubig(a);
31-
init_ubig(b);
32-
b.cell[0] = 1;
51+
init_ubig(&a);
52+
init_ubig(&b);
53+
b.cell[0] = 1ULL;
3354

3455
for (int i = 2; i <= k; i++) {
35-
for (int j = 0; j < BIGNSIZE; j++)
36-
c.cell[j] = a.cell[j] + b.cell[j];
37-
38-
for (int j = 0; j < BIGNSIZE - 1; j++) {
39-
// if lower overflows or lower >= 10^9, add a carry to upper
40-
if ((c.cell[j] < a.cell[j]) || (c.cell[j] >= P10_UINT64)) {
41-
c.cell[j] -= P10_UINT64;
42-
c.cell[j + 1] += 1;
43-
}
44-
}
45-
56+
ubig_add(&c, &a, &b);
4657
a = b;
4758
b = c;
4859
}
@@ -64,22 +75,30 @@ int fib_to_string(char *buf, int buf_sz, void *fib, int fib_sz)
6475
{
6576
const ubig *f = (ubig *) fib;
6677

67-
memset(buf, '\0', buf_sz);
78+
memset(buf, '0', buf_sz);
79+
buf[buf_sz - 1] = '\0';
6880
int index = BIGNSIZE - 1;
6981
while (index >= 0 && !f->cell[index])
7082
index--;
7183
if (index == -1) {
72-
buf[0] = '0';
73-
buf[1] = '\0';
74-
return 0;
84+
return buf_sz - 2;
7585
}
7686

77-
char buf2[22];
78-
snprintf(buf2, 22, "%llu", f->cell[index--]);
79-
strcat(buf, buf2);
80-
while (index >= 0) {
81-
snprintf(buf2, 22, "%019llu", f->cell[index--]);
82-
strcat(buf, buf2);
87+
for (int i = index; i >= 0; i--) {
88+
for (unsigned long long mask = 0x8000000000000000ULL; mask;
89+
mask >>= 1) {
90+
int carry = ((f->cell[i] & mask) != 0);
91+
for (int j = buf_sz - 2; j >= 0; j--) {
92+
buf[j] += buf[j] - '0' + carry;
93+
carry = (buf[j] > '9');
94+
if (carry)
95+
buf[j] -= 10;
96+
}
97+
}
8398
}
84-
return 0;
99+
100+
int offset = 0;
101+
while (buf[offset] == '0')
102+
offset++;
103+
return (buf[offset] == '\0') ? (offset - 1) : offset;
85104
}

0 commit comments

Comments
 (0)