-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathnum_builtin.h
155 lines (141 loc) · 3.75 KB
/
num_builtin.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
#ifndef _SECP256K1_NUM_GMP_
#define _SECP256K1_NUM_GMP_
#include <assert.h>
#include <string>
#include <string.h>
#include <stdlib.h>
namespace secp256k1 {
class Number {
private:
uint64_t n[8]; // 512 bits ought to be enough for everyone
int top; // number of used entries in n
void FixTop() {
while (top > 0 && n[top-1] == 0)
top--;
}
int GetNumBytes() {
if (top==0)
return 0;
int ret = 8*(top-1);
uint64_t h = n[top-1];
while (h>0) {
ret++;
h >>= 8;
}
return ret;
}
Number(const Number &c) {}
public:
Number() {
top = 0;
}
Number(const unsigned char *bin, int len) {
top = 0;
SetBytes(bin, len);
}
Number &operator=(const Number &x) {
for (int pos = 0; pos < x.top; pos++)
n[pos] = x.n[pos];
top = x.top;
}
void SetNumber(const Number &x) {
*this = x;
}
void SetBytes(const unsigned char *bin, unsigned int len) {
n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = n[7] = 0;
assert(len<=64);
for (int pos = 0; pos < len; pos++)
n[(len-1-pos)/8] |= ((uint64_t)(bin[pos])) << (((len-1-pos)%8)*8);
top = 8;
FixTop();
}
void GetBytes(unsigned char *bin, unsigned int len) {
unsigned int size = GetNumBytes();
assert(size <= len);
memset(bin,0,len);
for (int i=0; i<size; i++)
bin[i] = (n[(size-i-1)/8] >> (((size-1-i)%8)*8)) & 0xFF;
}
void SetInt(int x) {
n[0] = x;
top = 1;
FixTop();
}
void SetModInverse(const Number &x, const Number &m) {
mpz_invert(bn, x.bn, m.bn);
}
void SetModMul(const Number &a, const Number &b, const Number &m) {
mpz_mul(bn, a.bn, b.bn);
mpz_mod(bn, bn, m.bn);
}
void SetAdd(const Number &a1, const Number &a2) {
mpz_add(bn, a1.bn, a2.bn);
}
void SetSub(const Number &a1, const Number &a2) {
mpz_sub(bn, a1.bn, a2.bn);
}
void SetMult(const Number &a1, const Number &a2) {
mpz_mul(bn, a1.bn, a2.bn);
}
void SetDiv(const Number &a1, const Number &a2) {
mpz_tdiv_q(bn, a1.bn, a2.bn);
}
void SetMod(const Number &a, const Number &m) {
mpz_mod(bn, a.bn, m.bn);
}
int Compare(const Number &a) const {
return mpz_cmp(bn, a.bn);
}
int GetBits() const {
return mpz_sizeinbase(bn,2);
}
// return the lowest (rightmost) bits bits, and rshift them away
int ShiftLowBits(int bits) {
int ret = mpz_get_ui(bn) & ((1 << bits) - 1);
mpz_fdiv_q_2exp(bn, bn, bits);
return ret;
}
// check whether number is 0,
bool IsZero() const {
return mpz_size(bn) == 0;
}
bool IsOdd() const {
return mpz_get_ui(bn) & 1;
}
bool IsNeg() const {
return mpz_sgn(bn) < 0;
}
void Negate() {
mpz_neg(bn, bn);
}
void Shift1() {
mpz_fdiv_q_2exp(bn, bn, 1);
}
void Inc() {
mpz_add_ui(bn, bn, 1);
}
void SetHex(const std::string &str) {
mpz_set_str(bn, str.c_str(), 16);
}
void SetPseudoRand(const Number &max) {
number_state.gen(bn, max.bn);
}
void SplitInto(int bits, Number &low, Number &high) const {
mpz_t tmp;
mpz_init_set_ui(tmp,1);
mpz_mul_2exp(tmp,tmp,bits);
mpz_sub_ui(tmp,tmp,1);
mpz_and(low.bn, bn, tmp);
mpz_clear(tmp);
mpz_fdiv_q_2exp(high.bn, bn, bits);
}
std::string ToString() const {
char *str = (char*)malloc(mpz_sizeinbase(bn,16) + 2);
mpz_get_str(str, 16, bn);
std::string ret(str);
free(str);
return ret;
}
};
}
#endif