forked from resilar/crchack
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbigint.h
197 lines (171 loc) · 4.48 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
/**
* Big integers for crchack.
*/
#ifndef BIGINT_H
#define BIGINT_H
#include <assert.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef uint32_t word;
#define WORD_BIT (sizeof(word)*8)
struct bigint {
word *buf;
size_t bits; /* size */
};
/**
* Bigint size in bytes and words.
*/
static inline size_t bigint_sizeof(const struct bigint *dest)
{
return 1 + (dest->bits-1)/8; /* ceil() */
}
static inline size_t bigint_words(const struct bigint *dest)
{
return 1 + (dest->bits-1)/WORD_BIT;
}
/**
* (De)initialize a bigint structure.
*/
static inline struct bigint *bigint_init(struct bigint *dest, size_t bits)
{
dest->bits = bits;
dest->buf = (bits) ? calloc(bigint_words(dest), sizeof(word)) : NULL;
return (dest->buf) ? dest : NULL;
}
static inline void bigint_destroy(struct bigint *dest)
{
if (dest) {
free(dest->buf);
dest->buf = NULL;
}
}
/**
* Functions declared below expect the passed in bigint structures to be
* properly initialized.
*/
/**
* Print bigint as a hex value to the stream.
*/
void bigint_fprint(FILE *stream, const struct bigint *dest);
#define bigint_print(x) (bigint_fprint(stdout, (x)))
/**
* Initialize all bits of a bigint to 0/1.
*/
static inline void bigint_load_zeros(struct bigint *dest)
{
memset(dest->buf, 0, bigint_sizeof(dest));
}
static inline void bigint_load_ones(struct bigint *dest)
{
memset(dest->buf, -1, bigint_sizeof(dest));
}
/**
* Check whether bigint is zero.
*/
static inline int bigint_is_zero(const struct bigint *dest)
{
size_t i, j = bigint_words(dest);
for (i = 0; i < j; i++) {
if (dest->buf[i])
return 0;
}
return 1;
}
/**
* Load bigint value from an ASCII representation of a hexadecimal value.
*
* The function fails if the passed in string does not represent a valid
* hexadecimal value, or if the destination bigint is too small to hold the
* value.
*/
int bigint_from_string(struct bigint *dest, const char *hex_string);
/**
* Get/set the value of the nth least significant bit (n = 0, 1, 2, ...)
*/
static inline int bigint_get_bit(const struct bigint *dest, size_t n)
{
return !!(dest->buf[n / WORD_BIT] & ((word)1 << (n % WORD_BIT)));
}
#define bigint_lsb(x) ((x)->buf[0] & 1)
#define bigint_msb(x) (bigint_get_bit((x), (x)->bits-1))
static inline void bigint_set_bit(const struct bigint *dest, size_t n)
{
dest->buf[n / WORD_BIT] |= ((word)1 << (n % WORD_BIT));
}
#define bigint_set_lsb(x) ((x)->buf[0] |= 1)
#define bigint_set_msb(x) (bigint_set_bit((x), (x)->bits-1))
static inline void bigint_clear_bit(const struct bigint *dest, size_t n)
{
dest->buf[n / WORD_BIT] &= ~((word)1 << (n % WORD_BIT));
}
#define bigint_clear_lsb(x) ((x)->buf[0] &= ~(word)1)
#define bigint_clear_msb(x) (bigint_clear_bit((x), (x)->bits-1))
static inline void bigint_flip_bit(const struct bigint *dest, size_t n)
{
dest->buf[n / WORD_BIT] ^= ((word)1 << (n % WORD_BIT));
}
#define bigint_flip_lsb(x) ((x)->buf[0] ^= 1)
#define bigint_flip_msb(x) (bigint_flip_bit((x), (x)->bits-1))
/**
* Move (copy) the source value to the destination.
*/
static inline void bigint_mov(struct bigint *dest, const struct bigint *src)
{
assert(dest->bits == src->bits);
memcpy(dest->buf, src->buf, bigint_sizeof(dest));
}
/**
* Bitwise NOT operation.
*/
static inline void bigint_not(struct bigint *dest)
{
size_t i, j = bigint_words(dest);
for (i = 0; i < j; i++)
dest->buf[i] = ~dest->buf[i];
}
/**
* Exclusive-OR.
*/
static inline void bigint_xor(struct bigint *dest, const struct bigint *src)
{
size_t i, j = bigint_words(dest);
assert(dest->bits == src->bits);
for (i = 0; i < j; i++)
dest->buf[i] ^= src->buf[i];
}
/**
* Bitwise AND.
*/
static inline void bigint_and(struct bigint *dest, const struct bigint *src)
{
size_t i, j = bigint_words(dest);
assert(dest->bits == src->bits);
for (i = 0; i < j; i++)
dest->buf[i] &= src->buf[i];
}
/**
* Swap the values of two bigints.
*/
static inline void bigint_swap(struct bigint *a, struct bigint *b) {
word *buf;
assert(a->bits == b->bits);
buf = a->buf;
a->buf = b->buf;
b->buf = buf;
}
/**
* Shift bigint value to the left or right by 1 bit.
*/
void bigint_shl_1(struct bigint *dest);
void bigint_shr_1(struct bigint *dest);
/**
* Reverse the bits in bigint.
*/
void bigint_reflect(struct bigint *dest);
/**
* Population count (Hamming weight of bits).
*/
size_t bigint_popcount(struct bigint *dest);
#endif