forked from resilar/crchack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbigint.h
229 lines (203 loc) · 6.17 KB
/
bigint.h
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
* Rudimentary big integers for crchack.
*/
#ifndef BIGINT_H
#define BIGINT_H
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned long limb_t;
struct bigint {
limb_t *limb;
size_t bits;
};
#define LIMB_BITS (sizeof(limb_t)*8)
#define BITS_TO_LIMBS(bits) ((bits) ? (1 + ((bits) - 1) / LIMB_BITS) : 0)
/* Size of bigint in bits */
static inline size_t bigint_bits(const struct bigint *dest)
{
return dest->bits;
}
/* Number of bigint limbs */
static inline size_t bigint_limbs(const struct bigint *dest)
{
return BITS_TO_LIMBS(bigint_bits(dest));
}
/* Initialize bigint structure */
static inline struct bigint *bigint_init(struct bigint *dest, size_t bits)
{
if (bits && (dest->limb = calloc(BITS_TO_LIMBS(bits), sizeof(limb_t)))) {
dest->bits = bits;
return dest;
}
dest->limb = NULL;
dest->bits = 0;
return NULL;
}
/* Destroy bigint */
static inline void bigint_destroy(struct bigint *dest)
{
free(dest->limb);
dest->limb = NULL;
dest->bits = 0;
}
/* Allocate and initialize array of n bigint structures */
static inline struct bigint *bigint_array_new(size_t n, size_t bits)
{
struct bigint *arr;
size_t limbs = BITS_TO_LIMBS(bits);
if ((arr = malloc(n * sizeof(struct bigint) + n * limbs*sizeof(limb_t)))) {
size_t i;
limb_t *limb = (limb_t *)&arr[n];
memset(limb, 0, n * sizeof(limb_t));
for (i = 0; i < n; i++) {
arr[i].bits = bits;
arr[i].limb = limb;
limb += limbs;
}
}
return arr;
}
/* Delete n-length bigint array */
static inline void bigint_array_delete(struct bigint *arr)
{
free(arr);
}
/* Print hexadecimal representation of a bigint to stream */
void bigint_fprint(FILE *stream, const struct bigint *dest);
#define bigint_print(x) (bigint_fprint(stdout, (x)))
/* Set all bits to zero */
static inline void bigint_load_zeros(struct bigint *dest)
{
memset(dest->limb, 0, bigint_limbs(dest) * sizeof(limb_t));
}
/* Set all bits to one */
static inline void bigint_load_ones(struct bigint *dest)
{
memset(dest->limb, -1, bigint_limbs(dest) * sizeof(limb_t));
}
/* Test for zero value */
static inline int bigint_is_zero(const struct bigint *dest)
{
size_t i, j = bigint_limbs(dest);
for (i = 0; i < j; i++) {
if (dest->limb[i])
return 0;
}
return 1;
}
/**
* Load bigint from a hex string.
*
* Fails if the input string is an invalid hexadecimal number, or if destination
* bigint is too small to hold the value. Returns dest (or NULL on failure).
*/
struct bigint *bigint_from_string(struct bigint *dest, const char *hex);
/* Get/set the nth least significant bit (n = 0, 1, 2, ..., dest->bits - 1) */
static inline int bigint_get_bit(const struct bigint *dest, size_t n)
{
return (dest->limb[n / LIMB_BITS] >> (n % LIMB_BITS)) & 1;
}
#define bigint_lsb(x) ((x)->limb[0] & 1)
#define bigint_msb(x) (bigint_get_bit((x), (x)->bits-1))
static inline void bigint_set_bit(struct bigint *dest, size_t n)
{
dest->limb[n / LIMB_BITS] |= ((limb_t)1 << (n % LIMB_BITS));
}
#define bigint_set_lsb(x) ((x)->limb[0] |= 1)
#define bigint_set_msb(x) (bigint_set_bit((x), (x)->bits-1))
static inline void bigint_clear_bit(struct bigint *dest, size_t n)
{
dest->limb[n / LIMB_BITS] &= ~((limb_t)1 << (n % LIMB_BITS));
}
#define bigint_clear_lsb(x) ((x)->limb[0] &= ~(limb_t)1)
#define bigint_clear_msb(x) (bigint_clear_bit((x), (x)->bits-1))
static inline void bigint_flip_bit(struct bigint *dest, size_t n)
{
dest->limb[n / LIMB_BITS] ^= ((limb_t)1 << (n % LIMB_BITS));
}
#define bigint_flip_lsb(x) ((x)->limb[0] ^= 1)
#define bigint_flip_msb(x) (bigint_flip_bit((x), (x)->bits-1))
/* Move (copy) source bigint to destination */
static inline struct bigint *bigint_mov(struct bigint *dest,
const struct bigint *src)
{
memcpy(dest->limb, src->limb, bigint_limbs(dest) * sizeof(limb_t));
return dest;
}
/* Bitwise NOT */
static inline struct bigint *bigint_not(struct bigint *dest)
{
size_t i, j = bigint_limbs(dest);
for (i = 0; i < j; i++)
dest->limb[i] = ~dest->limb[i];
return dest;
}
/* Bitwise XOR */
static inline struct bigint *bigint_xor(struct bigint *dest,
const struct bigint *src)
{
size_t i, j;
for (i = 0, j = bigint_limbs(dest); i < j; i++)
dest->limb[i] ^= src->limb[i];
return dest;
}
/* Bitwise AND */
static inline struct bigint *bigint_and(struct bigint *dest,
const struct bigint *src)
{
size_t i, j = bigint_limbs(dest);
for (i = 0; i < j; i++)
dest->limb[i] &= src->limb[i];
return dest;
}
/* Swap the values of two bigints */
static inline void bigint_swap(struct bigint *a, struct bigint *b) {
limb_t *limb = a->limb;
a->limb = b->limb;
b->limb = limb;
}
/* Bit-shift to the left by 1 */
static inline struct bigint *bigint_shl_1(struct bigint *dest)
{
size_t i, j;
limb_t carry = 0;
for (i = 0, j = bigint_limbs(dest) - 1; i < j; i++) {
const limb_t c = (dest->limb[i] >> (LIMB_BITS - 1)) & 1;
dest->limb[i] = (dest->limb[i] << 1) | carry;
carry = c;
}
dest->limb[i] &= ((limb_t)1 << ((dest->bits - 1) % LIMB_BITS)) - 1;
dest->limb[i] = (dest->limb[i] << 1) | carry;
return dest;
}
/* Bit-shift to the right by 1 */
static inline struct bigint *bigint_shr_1(struct bigint *dest)
{
size_t i, j;
for (i = 0, j = bigint_limbs(dest) - 1; i < j; i++) {
const limb_t c = dest->limb[i+1] << (LIMB_BITS-1);
dest->limb[i] = (dest->limb[i] >> 1) | c;
}
dest->limb[i] >>= 1;
return dest;
}
/* Reverse the bits in a bigint (LSB becomes MSB and vice versa and so on) */
static inline struct bigint *bigint_reflect(struct bigint *dest)
{
struct bigint acc;
if (bigint_init(&acc, dest->bits)) {
size_t i;
bigint_mov(&acc, dest);
bigint_load_zeros(dest);
for (i = 0; i < dest->bits; i++) {
bigint_shl_1(dest);
if (bigint_lsb(&acc))
bigint_set_lsb(dest);
bigint_shr_1(&acc);
}
bigint_destroy(&acc);
}
return dest;
}
#endif