PRCYCoin  2.0.0.7rc1
P2P Digital Currency
num_gmp_impl.h
Go to the documentation of this file.
1 /**********************************************************************
2  * Copyright (c) 2013, 2014 Pieter Wuille *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5  **********************************************************************/
6 
7 #ifndef _SECP256K1_NUM_REPR_IMPL_H_
8 #define _SECP256K1_NUM_REPR_IMPL_H_
9 
10 #include <string.h>
11 #include <stdlib.h>
12 #include <gmp.h>
13 
14 #include "util.h"
15 #include "num.h"
16 
17 #ifdef VERIFY
18 static void secp256k1_num_sanity(const secp256k1_num_t *a) {
19  VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0));
20 }
21 #else
22 #define secp256k1_num_sanity(a) do { } while(0)
23 #endif
24 
25 static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
26  *r = *a;
27 }
28 
29 static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
30  unsigned char tmp[65];
31  int len = 0;
32  if (a->limbs>1 || a->data[0] != 0) {
33  len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
34  }
35  int shift = 0;
36  while (shift < len && tmp[shift] == 0) shift++;
37  VERIFY_CHECK(len-shift <= (int)rlen);
38  memset(r, 0, rlen - len + shift);
39  if (len > shift) {
40  memcpy(r + rlen - len + shift, tmp + shift, len - shift);
41  }
42  memset(tmp, 0, sizeof(tmp));
43 }
44 
45 static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
46  VERIFY_CHECK(alen > 0);
47  VERIFY_CHECK(alen <= 64);
48  int len = mpn_set_str(r->data, a, alen, 256);
49  if (len == 0) {
50  r->data[0] = 0;
51  len = 1;
52  }
53  VERIFY_CHECK(len <= NUM_LIMBS*2);
54  r->limbs = len;
55  r->neg = 0;
56  while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
57 }
58 
59 static void secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
60  mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
61  r->limbs = a->limbs;
62  if (c != 0) {
63  VERIFY_CHECK(r->limbs < 2*NUM_LIMBS);
64  r->data[r->limbs++] = c;
65  }
66 }
67 
68 static void secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
69  mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
70  VERIFY_CHECK(c == 0);
71  r->limbs = a->limbs;
72  while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
73 }
74 
75 static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
78 
79  if (r->limbs >= m->limbs) {
80  mp_limb_t t[2*NUM_LIMBS];
81  mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
82  memset(t, 0, sizeof(t));
83  r->limbs = m->limbs;
84  while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
85  }
86 
87  if (r->neg && (r->limbs > 1 || r->data[0] != 0)) {
88  secp256k1_num_sub_abs(r, m, r);
89  r->neg = 0;
90  }
91 }
92 
93 static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
96 
108  VERIFY_CHECK(m->data[m->limbs-1] != 0);
109  mp_limb_t g[NUM_LIMBS+1];
110  mp_limb_t u[NUM_LIMBS+1];
111  mp_limb_t v[NUM_LIMBS+1];
112  for (int i=0; i < m->limbs; i++) {
113  u[i] = (i < a->limbs) ? a->data[i] : 0;
114  v[i] = m->data[i];
115  }
116  mp_size_t sn = NUM_LIMBS+1;
117  mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
118  VERIFY_CHECK(gn == 1);
119  VERIFY_CHECK(g[0] == 1);
120  r->neg = a->neg ^ m->neg;
121  if (sn < 0) {
122  mpn_sub(r->data, m->data, m->limbs, r->data, -sn);
123  r->limbs = m->limbs;
124  while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
125  } else {
126  r->limbs = sn;
127  }
128  memset(g, 0, sizeof(g));
129  memset(u, 0, sizeof(u));
130  memset(v, 0, sizeof(v));
131 }
132 
133 static int secp256k1_num_is_zero(const secp256k1_num_t *a) {
134  return (a->limbs == 1 && a->data[0] == 0);
135 }
136 
137 static int secp256k1_num_is_neg(const secp256k1_num_t *a) {
138  return (a->limbs > 1 || a->data[0] != 0) && a->neg;
139 }
140 
141 static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
142  if (a->limbs > b->limbs) return 1;
143  if (a->limbs < b->limbs) return -1;
144  return mpn_cmp(a->data, b->data, a->limbs);
145 }
146 
147 static int secp256k1_num_eq(const secp256k1_num_t *a, const secp256k1_num_t *b) {
148  if (a->limbs > b->limbs) return 0;
149  if (a->limbs < b->limbs) return 0;
150  if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) return 0;
151  return mpn_cmp(a->data, b->data, a->limbs) == 0;
152 }
153 
154 static void secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) {
155  if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */
156  r->neg = a->neg;
157  if (a->limbs >= b->limbs) {
158  secp256k1_num_add_abs(r, a, b);
159  } else {
160  secp256k1_num_add_abs(r, b, a);
161  }
162  } else {
163  if (secp256k1_num_cmp(a, b) > 0) {
164  r->neg = a->neg;
165  secp256k1_num_sub_abs(r, a, b);
166  } else {
167  r->neg = b->neg ^ bneg;
168  secp256k1_num_sub_abs(r, b, a);
169  }
170  }
171 }
172 
173 static void secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
176  secp256k1_num_subadd(r, a, b, 0);
177 }
178 
179 static void secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
182  secp256k1_num_subadd(r, a, b, 1);
183 }
184 
185 static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
188 
189  mp_limb_t tmp[2*NUM_LIMBS+1];
190  VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
191  if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
192  r->limbs = 1;
193  r->neg = 0;
194  r->data[0] = 0;
195  return;
196  }
197  if (a->limbs >= b->limbs)
198  mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs);
199  else
200  mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs);
201  r->limbs = a->limbs + b->limbs;
202  if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--;
203  VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS);
204  mpn_copyi(r->data, tmp, r->limbs);
205  r->neg = a->neg ^ b->neg;
206  memset(tmp, 0, sizeof(tmp));
207 }
208 
209 static void secp256k1_num_shift(secp256k1_num_t *r, int bits) {
210  if (bits % GMP_NUMB_BITS) {
211  // Shift within limbs.
212  mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS);
213  }
214  if (bits >= GMP_NUMB_BITS) {
215  // Shift full limbs.
216  for (int i = 0; i < r->limbs; i++) {
217  int index = i + (bits / GMP_NUMB_BITS);
218  if (index < r->limbs && index < 2*NUM_LIMBS) {
219  r->data[i] = r->data[index];
220  } else {
221  r->data[i] = 0;
222  }
223  }
224  }
225  while (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--;
226 }
227 
228 static void secp256k1_num_negate(secp256k1_num_t *r) {
229  r->neg ^= 1;
230 }
231 
232 #endif
VERIFY_CHECK
#define VERIFY_CHECK(cond)
Definition: util.h:61
secp256k1_num_t::neg
int neg
Definition: num_gmp.h:16
b
void const uint64_t * b
Definition: field_5x52_asm_impl.h:10
secp256k1_num_sanity
#define secp256k1_num_sanity(a)
Definition: num_gmp_impl.h:22
secp256k1_num_t::limbs
int limbs
Definition: num_gmp.h:17
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:15
util.h
secp256k1_num_t
Definition: num_gmp.h:14
r
void const uint64_t uint64_t * r
Definition: field_5x52_asm_impl.h:10
secp256k1_num_t::data
mp_limb_t data[2 *NUM_LIMBS]
Definition: num_gmp.h:15
NUM_LIMBS
#define NUM_LIMBS
Definition: num_gmp.h:12
num.h