1 #ifndef _SECP256K1_NUM_REPR_IMPL_H_
2 #define _SECP256K1_NUM_REPR_IMPL_H_
12 void static secp256k1_num_sanity(const secp256k1_num_t *a) {
13 assert(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0));
16 #define secp256k1_num_sanity(a) do { } while(0)
19 void static secp256k1_num_init(secp256k1_num_t *r) {
25 void static secp256k1_num_free(secp256k1_num_t *r) {
28 void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
32 int static secp256k1_num_bits(const secp256k1_num_t *a) {
33 int ret=(a->limbs-1)*GMP_NUMB_BITS;
34 mp_limb_t x=a->data[a->limbs-1];
43 void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
44 unsigned char tmp[65];
45 int len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
47 memset(r, 0, rlen - len);
48 memcpy(r + rlen - len, tmp, len);
51 void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
54 int len = mpn_set_str(r->data, a, alen, 256);
55 assert(len <= NUM_LIMBS*2);
58 while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
61 void static secp256k1_num_set_int(secp256k1_num_t *r, int a) {
64 r->data[0] = (a < 0) ? -a : a;
67 void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
68 secp256k1_num_sanity(r);
69 secp256k1_num_sanity(m);
71 if (r->limbs >= m->limbs) {
72 mp_limb_t t[2*NUM_LIMBS];
73 mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
75 while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
80 void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
81 secp256k1_num_sanity(a);
82 secp256k1_num_sanity(m);
85 secp256k1_num_t a2 = *a;
86 secp256k1_num_t m2 = *m;
89 // mpn_gcdext computes: (G,S) = gcdext(U,V), where
92 // * U has equal or more limbs than V, and V has no padding
93 // If we set U to be (a padded version of) a, and V = m:
98 assert(m->limbs <= NUM_LIMBS);
99 assert(m->data[m->limbs-1] != 0);
100 mp_limb_t g[NUM_LIMBS+1];
101 mp_limb_t u[NUM_LIMBS+1];
102 mp_limb_t v[NUM_LIMBS+1];
103 for (int i=0; i < m->limbs; i++) {
104 u[i] = (i < a->limbs) ? a->data[i] : 0;
107 mp_size_t sn = NUM_LIMBS+1;
108 mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
111 r->neg = a->neg ^ m->neg;
113 mpn_sub(r->data, m->data, m->limbs, r->data, -sn);
115 while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
122 secp256k1_num_mod_mul(&c, &a2, r, m);
123 assert(c.limbs == 1 && c.data[0] == 1);
127 int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
128 return (a->limbs == 1 && a->data[0] == 0);
131 int static secp256k1_num_is_odd(const secp256k1_num_t *a) {
132 return a->data[0] & 1;
135 int static secp256k1_num_is_neg(const secp256k1_num_t *a) {
136 return (a->limbs > 1 || a->data[0] != 0) && a->neg;
139 int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
140 if (a->limbs > b->limbs) return 1;
141 if (a->limbs < b->limbs) return -1;
142 return mpn_cmp(a->data, b->data, a->limbs);
145 void static secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
146 mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
149 assert(r->limbs < 2*NUM_LIMBS);
150 r->data[r->limbs++] = c;
154 void static secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
155 mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
158 while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
161 void static secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) {
162 if (!(b->neg ^ bneg ^ a->neg)) { // a and b have the same sign
164 if (a->limbs >= b->limbs) {
165 secp256k1_num_add_abs(r, a, b);
167 secp256k1_num_add_abs(r, b, a);
170 if (secp256k1_num_cmp(a, b) > 0) {
172 secp256k1_num_sub_abs(r, a, b);
174 r->neg = b->neg ^ bneg;
175 secp256k1_num_sub_abs(r, b, a);
180 void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
181 secp256k1_num_sanity(a);
182 secp256k1_num_sanity(b);
185 secp256k1_num_t a2 = *a;
186 secp256k1_num_t b2 = *b;
189 secp256k1_num_subadd(r, a, b, 0);
192 secp256k1_num_t c = *r;
193 secp256k1_num_subadd(&c, &c, &b2, 1);
194 assert(secp256k1_num_cmp(&c, &a2) == 0);
198 void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
200 secp256k1_num_t a2 = *a;
201 secp256k1_num_t b2 = *b;
203 secp256k1_num_sanity(a);
204 secp256k1_num_sanity(b);
206 secp256k1_num_subadd(r, a, b, 1);
210 secp256k1_num_subadd(&c, r, &b2, 0);
211 assert(secp256k1_num_cmp(&c, &a2) == 0);
215 void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
217 secp256k1_num_t a2 = *a;
218 secp256k1_num_t b2 = *b;
221 secp256k1_num_sanity(a);
222 secp256k1_num_sanity(b);
224 mp_limb_t tmp[2*NUM_LIMBS+1];
225 assert(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
226 if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
232 if (a->limbs >= b->limbs)
233 mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs);
235 mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs);
236 r->limbs = a->limbs + b->limbs;
237 if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--;
238 assert(r->limbs <= 2*NUM_LIMBS);
239 mpn_copyi(r->data, tmp, r->limbs);
240 r->neg = a->neg ^ b->neg;
242 secp256k1_num_sanity(&a2);
243 secp256k1_num_sanity(&b2);
247 secp256k1_num_div(&c, r, &b2);
248 assert(secp256k1_num_cmp(&a2, &c) == 0);
249 secp256k1_num_div(&c, r, &a2);
250 assert(secp256k1_num_cmp(&b2, &c) == 0);
254 void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
255 secp256k1_num_sanity(a);
256 secp256k1_num_sanity(b);
257 if (b->limbs > a->limbs) {
264 mp_limb_t quo[2*NUM_LIMBS+1];
265 mp_limb_t rem[2*NUM_LIMBS+1];
266 mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs);
267 mpn_copyi(r->data, quo, a->limbs - b->limbs + 1);
268 r->limbs = a->limbs - b->limbs + 1;
269 while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--;
270 r->neg = a->neg ^ b->neg;
273 void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) {
274 secp256k1_num_mul(r, a, b);
275 secp256k1_num_mod(r, m);
279 int static secp256k1_num_shift(secp256k1_num_t *r, int bits) {
280 assert(bits <= GMP_NUMB_BITS);
281 mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits);
282 if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--;
283 ret >>= (GMP_NUMB_BITS - bits);
287 int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
288 return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1);
291 void static secp256k1_num_inc(secp256k1_num_t *r) {
292 mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1);
294 assert(r->limbs < 2*NUM_LIMBS);
295 r->data[r->limbs++] = ret;
299 void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) {
300 static const unsigned char cvt[256] = {
301 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
302 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
303 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
304 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
305 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
306 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
307 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
308 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
309 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
310 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
311 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
312 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
313 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
314 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
315 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
316 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0
319 for (int i=0; i<alen; i++) {
322 r->limbs = mpn_set_str(r->data, num, alen, 16);
323 while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--;
326 void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) {
327 static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
328 unsigned char *tmp = malloc(257);
329 mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs);
331 for (int i=0; i<len; i++) {
332 assert(rlen-len+i >= 0);
333 assert(rlen-len+i < rlen);
336 r[rlen-len+i] = cvt[tmp[i]];
338 for (int i=0; i<rlen-len; i++) {
346 void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
349 if (bits >= a->limbs * GMP_NUMB_BITS) {
358 while (left >= GMP_NUMB_BITS) {
359 rl->data[rl->limbs] = a->data[rl->limbs];
361 left -= GMP_NUMB_BITS;
364 mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs);
365 rh->limbs = a->limbs - rl->limbs;
367 mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left);
368 rh->limbs = a->limbs - rl->limbs;
369 while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--;
372 rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1);
375 while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--;
378 void static secp256k1_num_negate(secp256k1_num_t *r) {