1
- #include <linux/kernel .h>
1
+ #include <linux/slab .h>
2
2
#include <linux/string.h>
3
3
4
- #define BIGNSIZE 12
4
+ static inline int estimate_size (long long k )
5
+ {
6
+ if (k <= 93 )
7
+ return 1 ;
8
+ unsigned long long n = (k * 20899 - 34950 ) / 1926610 ;
9
+ return (int ) n + 1 ;
10
+ }
5
11
6
12
typedef struct BigN {
7
- unsigned long long cell [BIGNSIZE ];
13
+ int size ;
14
+ unsigned long long * cell ;
8
15
} ubig ;
9
16
10
- static inline void init_ubig ( ubig * x )
17
+ ubig * new_ubig ( int size )
11
18
{
12
- for (int i = 0 ; i < BIGNSIZE ; x -> cell [i ++ ] = 0 )
13
- ;
19
+ ubig * ptr = (ubig * ) kmalloc (sizeof (ubig ), GFP_KERNEL );
20
+ if (!ptr )
21
+ return (ubig * ) NULL ;
22
+
23
+ unsigned long long * ullptr = (unsigned long long * ) kmalloc (
24
+ size * sizeof (unsigned long long ), GFP_KERNEL );
25
+ if (!ullptr ) {
26
+ kfree (ptr );
27
+ return (ubig * ) NULL ;
28
+ }
29
+ memset (ullptr , 0 , size * sizeof (unsigned long long ));
30
+
31
+ ptr -> size = size ;
32
+ ptr -> cell = ullptr ;
33
+ return ptr ;
34
+ }
35
+
36
+ static inline void destroy_ubig (ubig * ptr )
37
+ {
38
+ if (ptr ) {
39
+ if (ptr -> cell )
40
+ kfree (ptr -> cell );
41
+ kfree (ptr );
42
+ }
43
+ }
44
+
45
+ static inline void zero_ubig (ubig * x )
46
+ {
47
+ memset (x -> cell , 0 , x -> size * sizeof (unsigned long long ));
48
+ }
49
+
50
+ static inline void ubig_assign (ubig * dest , ubig * src )
51
+ {
52
+ memcpy (dest -> cell , src -> cell , dest -> size * sizeof (unsigned long long ));
14
53
}
15
54
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
55
static inline void ubig_add (ubig * dest , ubig * a , ubig * b )
27
56
{
28
- for (int i = 0 ; i < BIGNSIZE ; i ++ )
57
+ for (int i = 0 ; i < a -> size ; i ++ )
29
58
dest -> cell [i ] = a -> cell [i ] + b -> cell [i ];
30
59
31
- for (int i = 0 ; i < BIGNSIZE - 1 ; i ++ )
60
+ for (int i = 0 ; i < a -> size - 1 ; i ++ )
32
61
dest -> cell [i + 1 ] += (dest -> cell [i ] < a -> cell [i ]);
33
62
}
34
63
64
+ static inline void ubig_sub (ubig * dest , ubig * a , ubig * b )
65
+ {
66
+ for (int i = 0 ; i < a -> size ; i ++ )
67
+ dest -> cell [i ] = a -> cell [i ] - b -> cell [i ];
68
+
69
+ for (int i = 0 ; i < a -> size - 1 ; i ++ )
70
+ dest -> cell [i + 1 ] -= (dest -> cell [i ] > a -> cell [i ]);
71
+ }
72
+
35
73
/**
36
74
* fib_sequence() - Calculate the k-th Fibonacci number.
37
75
* @k: Index of the Fibonacci number to calculate.
38
76
*
39
77
* Return: The k-th Fibonacci number on success.
40
78
*/
41
- static ubig fib_sequence (long long k )
79
+ static ubig * fib_sequence (long long k )
42
80
{
43
81
if (k <= 1LL ) {
44
- ubig result ;
45
- init_ubig (& result );
46
- result .cell [0 ] = (unsigned long long ) k ;
47
- return result ;
82
+ ubig * ret = new_ubig (1 );
83
+ if (!ret )
84
+ return (ubig * ) NULL ;
85
+ ret -> cell [0 ] = (unsigned long long ) k ;
86
+ return ret ;
48
87
}
49
88
50
- ubig a , b , c ;
51
- init_ubig (& a );
52
- init_ubig (& b );
53
- b .cell [0 ] = 1ULL ;
89
+ int sz = estimate_size (k );
90
+ ubig * a = new_ubig (sz );
91
+ ubig * b = new_ubig (sz );
92
+ ubig * c = new_ubig (sz );
93
+ if (!a || !b || !c ) {
94
+ destroy_ubig (a );
95
+ destroy_ubig (b );
96
+ destroy_ubig (c );
97
+ return (ubig * ) NULL ;
98
+ }
54
99
100
+ b -> cell [0 ] = 1ULL ;
55
101
for (int i = 2 ; i <= k ; i ++ ) {
56
- ubig_add (& c , & a , & b );
57
- a = b ;
58
- b = c ;
102
+ ubig_add (c , a , b );
103
+ ubig_assign ( a , b ) ;
104
+ ubig_assign ( b , c ) ;
59
105
}
60
106
107
+ destroy_ubig (a );
108
+ destroy_ubig (b );
61
109
return c ;
62
110
}
111
+
112
+ /**
113
+ * fib_to_string() - Convert the k-th Fibonacci number into string.
114
+ * @buf: Buffer where the resulting string will be stored.
115
+ * @buf_sz: Size of the buffer.
116
+ * @fib: Pointer to the Fibonacci number data.
117
+ *
118
+ * Return: The start position (offset) of the @fib string.
119
+ */
120
+ int fib_to_string (char * buf , int buf_sz , ubig * fib )
121
+ {
122
+ memset (buf , '0' , buf_sz );
123
+ buf [buf_sz - 1 ] = '\0' ;
124
+ int index = fib -> size - 1 ;
125
+ while (index >= 0 && !fib -> cell [index ])
126
+ index -- ;
127
+ if (index == -1 ) {
128
+ return buf_sz - 2 ;
129
+ }
130
+
131
+ for (int i = index ; i >= 0 ; i -- ) {
132
+ for (unsigned long long mask = 0x8000000000000000ULL ; mask ;
133
+ mask >>= 1 ) {
134
+ int carry = ((fib -> cell [i ] & mask ) != 0 );
135
+ for (int j = buf_sz - 2 ; j >= 0 ; j -- ) {
136
+ buf [j ] += buf [j ] - '0' + carry ;
137
+ carry = (buf [j ] > '9' );
138
+ if (carry )
139
+ buf [j ] -= 10 ;
140
+ }
141
+ }
142
+ }
143
+
144
+ int offset = 0 ;
145
+ while (buf [offset ] == '0' )
146
+ offset ++ ;
147
+ return (buf [offset ] == '\0' ) ? (offset - 1 ) : offset ;
148
+ }
0 commit comments