@@ -7,9 +7,30 @@ typedef struct BigN {
7
7
unsigned long long cell [BIGNSIZE ];
8
8
} ubig ;
9
9
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 ];
11
30
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
+ }
13
34
14
35
/**
15
36
* fib_sequence() - Calculate the k-th Fibonacci number.
@@ -21,28 +42,18 @@ static ubig fib_sequence(long long k)
21
42
{
22
43
if (k <= 1LL ) {
23
44
ubig result ;
24
- init_ubig (result );
45
+ init_ubig (& result );
25
46
result .cell [0 ] = (unsigned long long ) k ;
26
47
return result ;
27
48
}
28
49
29
50
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 ;
33
54
34
55
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 );
46
57
a = b ;
47
58
b = c ;
48
59
}
@@ -64,22 +75,30 @@ int fib_to_string(char *buf, int buf_sz, void *fib, int fib_sz)
64
75
{
65
76
const ubig * f = (ubig * ) fib ;
66
77
67
- memset (buf , '\0' , buf_sz );
78
+ memset (buf , '0' , buf_sz );
79
+ buf [buf_sz - 1 ] = '\0' ;
68
80
int index = BIGNSIZE - 1 ;
69
81
while (index >= 0 && !f -> cell [index ])
70
82
index -- ;
71
83
if (index == -1 ) {
72
- buf [0 ] = '0' ;
73
- buf [1 ] = '\0' ;
74
- return 0 ;
84
+ return buf_sz - 2 ;
75
85
}
76
86
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
+ }
83
98
}
84
- return 0 ;
99
+
100
+ int offset = 0 ;
101
+ while (buf [offset ] == '0' )
102
+ offset ++ ;
103
+ return (buf [offset ] == '\0' ) ? (offset - 1 ) : offset ;
85
104
}
0 commit comments