Bitcoin ABC 0.33.6
P2P Digital Currency
field_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 https://www.opensource.org/licenses/mit-license.php.*
5 ***********************************************************************/
6
7#ifndef SECP256K1_FIELD_IMPL_H
8#define SECP256K1_FIELD_IMPL_H
9
10#include "field.h"
11#include "util.h"
12
13#if defined(SECP256K1_WIDEMUL_INT128)
14#include "field_5x52_impl.h"
15#elif defined(SECP256K1_WIDEMUL_INT64)
16#include "field_10x26_impl.h"
17#else
18#error "Please select wide multiplication implementation"
19#endif
20
22 secp256k1_fe na;
23#ifdef VERIFY
28#endif
29 secp256k1_fe_negate(&na, a, 1);
30 secp256k1_fe_add(&na, b);
32}
33
44 secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
45 int j, ret;
46
47#ifdef VERIFY
48 VERIFY_CHECK(r != a);
51#endif
52
58 secp256k1_fe_sqr(&x2, a);
59 secp256k1_fe_mul(&x2, &x2, a);
60
61 secp256k1_fe_sqr(&x3, &x2);
62 secp256k1_fe_mul(&x3, &x3, a);
63
64 x6 = x3;
65 for (j=0; j<3; j++) {
66 secp256k1_fe_sqr(&x6, &x6);
67 }
68 secp256k1_fe_mul(&x6, &x6, &x3);
69
70 x9 = x6;
71 for (j=0; j<3; j++) {
72 secp256k1_fe_sqr(&x9, &x9);
73 }
74 secp256k1_fe_mul(&x9, &x9, &x3);
75
76 x11 = x9;
77 for (j=0; j<2; j++) {
78 secp256k1_fe_sqr(&x11, &x11);
79 }
80 secp256k1_fe_mul(&x11, &x11, &x2);
81
82 x22 = x11;
83 for (j=0; j<11; j++) {
84 secp256k1_fe_sqr(&x22, &x22);
85 }
86 secp256k1_fe_mul(&x22, &x22, &x11);
87
88 x44 = x22;
89 for (j=0; j<22; j++) {
90 secp256k1_fe_sqr(&x44, &x44);
91 }
92 secp256k1_fe_mul(&x44, &x44, &x22);
93
94 x88 = x44;
95 for (j=0; j<44; j++) {
96 secp256k1_fe_sqr(&x88, &x88);
97 }
98 secp256k1_fe_mul(&x88, &x88, &x44);
99
100 x176 = x88;
101 for (j=0; j<88; j++) {
102 secp256k1_fe_sqr(&x176, &x176);
103 }
104 secp256k1_fe_mul(&x176, &x176, &x88);
105
106 x220 = x176;
107 for (j=0; j<44; j++) {
108 secp256k1_fe_sqr(&x220, &x220);
109 }
110 secp256k1_fe_mul(&x220, &x220, &x44);
111
112 x223 = x220;
113 for (j=0; j<3; j++) {
114 secp256k1_fe_sqr(&x223, &x223);
115 }
116 secp256k1_fe_mul(&x223, &x223, &x3);
117
118 /* The final result is then assembled using a sliding window over the blocks. */
119
120 t1 = x223;
121 for (j=0; j<23; j++) {
122 secp256k1_fe_sqr(&t1, &t1);
123 }
124 secp256k1_fe_mul(&t1, &t1, &x22);
125 for (j=0; j<6; j++) {
126 secp256k1_fe_sqr(&t1, &t1);
127 }
128 secp256k1_fe_mul(&t1, &t1, &x2);
129 secp256k1_fe_sqr(&t1, &t1);
130 secp256k1_fe_sqr(r, &t1);
131
132 /* Check that a square root was actually calculated */
133
134 secp256k1_fe_sqr(&t1, r);
135 ret = secp256k1_fe_equal(&t1, a);
136
137#ifdef VERIFY
138 if (!ret) {
139 secp256k1_fe_negate(&t1, &t1, 1);
142 }
143#endif
144 return ret;
145}
146
148 secp256k1_fe r;
149 return secp256k1_fe_sqrt(&r, a);
150}
151
152#ifndef VERIFY
153static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; }
154static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; }
155#else
156static void secp256k1_fe_verify(const secp256k1_fe *a) {
157 /* Magnitude between 0 and 32. */
159 /* Normalized is 0 or 1. */
160 VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1));
161 /* If normalized, magnitude must be 0 or 1. */
162 if (a->normalized) secp256k1_fe_verify_magnitude(a, 1);
163 /* Invoke implementation-specific checks. */
164 secp256k1_fe_impl_verify(a);
165}
166
167static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) {
168 VERIFY_CHECK(m >= 0);
169 VERIFY_CHECK(m <= 32);
170 VERIFY_CHECK(a->magnitude <= m);
171}
172
176 r->magnitude = 1;
177 r->normalized = 1;
179}
180
184 r->magnitude = 1;
186}
187
191 r->magnitude = 1;
192 r->normalized = 1;
194}
195
199}
200
204}
205
207 VERIFY_CHECK(0 <= a && a <= 0x7FFF);
209 r->magnitude = (a != 0);
210 r->normalized = 1;
212}
213
215 VERIFY_CHECK(0 <= a && a <= 0x7FFF);
218 r->magnitude += 1;
219 r->normalized = 0;
221}
222
224 a->magnitude = 0;
225 a->normalized = 1;
228}
229
232 VERIFY_CHECK(a->normalized);
234}
235
238 VERIFY_CHECK(a->normalized);
239 return secp256k1_fe_impl_is_odd(a);
240}
241
242SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
245 VERIFY_CHECK(a->normalized);
246 VERIFY_CHECK(b->normalized);
247 return secp256k1_fe_impl_cmp_var(a, b);
248}
249
250SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
252 r->magnitude = 1;
253 r->normalized = 0;
255}
256
257SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
259 r->magnitude = 1;
260 r->normalized = 1;
262 return 1;
263 } else {
264 /* Mark the output field element as invalid. */
265 r->magnitude = -1;
266 return 0;
267 }
268}
269
270SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
272 VERIFY_CHECK(a->normalized);
274}
275
278 VERIFY_CHECK(m >= 0 && m <= 31);
281 r->magnitude = m + 1;
282 r->normalized = 0;
284}
285
288 VERIFY_CHECK(a >= 0 && a <= 32);
289 VERIFY_CHECK(a*r->magnitude <= 32);
291 r->magnitude *= a;
292 r->normalized = 0;
294}
295
299 VERIFY_CHECK(r->magnitude + a->magnitude <= 32);
301 r->magnitude += a->magnitude;
302 r->normalized = 0;
304}
305
311 VERIFY_CHECK(r != b);
312 VERIFY_CHECK(a != b);
313 secp256k1_fe_impl_mul(r, a, b);
314 r->magnitude = 1;
315 r->normalized = 0;
317}
318
323 r->magnitude = 1;
324 r->normalized = 0;
326}
327
328SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
329 VERIFY_CHECK(flag == 0 || flag == 1);
332 secp256k1_fe_impl_cmov(r, a, flag);
333 if (a->magnitude > r->magnitude) r->magnitude = a->magnitude;
334 if (!a->normalized) r->normalized = 0;
336}
337
340 VERIFY_CHECK(a->normalized);
342}
343
346 r->magnitude = 1;
347 r->normalized = 1;
349}
350
352 int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
355 r->magnitude = x->magnitude > 0;
356 r->normalized = 1;
359}
360
362 int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
365 r->magnitude = x->magnitude > 0;
366 r->normalized = 1;
369}
370
372 int ret;
373 secp256k1_fe tmp = *x, sqrt;
377 VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp));
378 return ret;
379}
380
382 VERIFY_CHECK(m >= 0);
383 VERIFY_CHECK(m <= 32);
385 r->magnitude = m;
386 r->normalized = (m == 0);
388}
389
394 r->magnitude = (r->magnitude >> 1) + 1;
395 r->normalized = 0;
397}
398
399#endif /* defined(VERIFY) */
400
401#endif /* SECP256K1_FIELD_IMPL_H */
#define secp256k1_fe_cmov
Definition: field.h:96
#define secp256k1_fe_negate(r, a, m)
Negate a field element.
Definition: field.h:215
#define secp256k1_fe_normalizes_to_zero_var
Definition: field.h:82
#define secp256k1_fe_cmp_var
Definition: field.h:87
#define secp256k1_fe_normalize_weak
Definition: field.h:79
#define secp256k1_fe_is_odd
Definition: field.h:86
#define secp256k1_fe_mul
Definition: field.h:94
#define secp256k1_fe_add
Definition: field.h:93
#define secp256k1_fe_clear
Definition: field.h:84
#define secp256k1_fe_normalize_var
Definition: field.h:80
#define secp256k1_fe_half
Definition: field.h:102
#define secp256k1_fe_to_storage
Definition: field.h:97
#define secp256k1_fe_inv_var
Definition: field.h:100
#define secp256k1_fe_is_zero
Definition: field.h:85
#define secp256k1_fe_mul_int_unchecked
Definition: field.h:92
#define secp256k1_fe_set_b32_limit
Definition: field.h:89
#define secp256k1_fe_is_square_var
Definition: field.h:104
#define secp256k1_fe_get_bounds
Definition: field.h:101
#define secp256k1_fe_from_storage
Definition: field.h:98
#define secp256k1_fe_set_b32_mod
Definition: field.h:88
#define secp256k1_fe_negate_unchecked
Definition: field.h:91
#define secp256k1_fe_get_b32
Definition: field.h:90
#define secp256k1_fe_normalizes_to_zero
Definition: field.h:81
#define secp256k1_fe_inv
Definition: field.h:99
#define secp256k1_fe_sqr
Definition: field.h:95
#define secp256k1_fe_normalize
Definition: field.h:78
#define secp256k1_fe_add_int
Definition: field.h:103
#define secp256k1_fe_set_int
Definition: field.h:83
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r)
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a)
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r)
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x)
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a)
Convert a field element to a 32-byte big endian value.
static SECP256K1_INLINE void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a)
static SECP256K1_INLINE void secp256k1_fe_impl_clear(secp256k1_fe *a)
static SECP256K1_INLINE void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a)
static SECP256K1_INLINE int secp256k1_fe_impl_is_zero(const secp256k1_fe *a)
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m)
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a)
static SECP256K1_INLINE void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m)
static SECP256K1_INLINE void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a)
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b)
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r)
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x)
static SECP256K1_INLINE void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a)
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a)
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a)
static SECP256K1_INLINE void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a)
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r)
static void secp256k1_fe_impl_normalize(secp256k1_fe *r)
static SECP256K1_INLINE void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag)
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x)
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r)
static SECP256K1_INLINE int secp256k1_fe_impl_is_odd(const secp256k1_fe *a)
static SECP256K1_INLINE void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe *SECP256K1_RESTRICT b)
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a)
Definition: field_impl.h:147
static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m)
Definition: field_impl.h:154
static void secp256k1_fe_verify(const secp256k1_fe *a)
Definition: field_impl.h:153
static int secp256k1_fe_sqrt(secp256k1_fe *SECP256K1_RESTRICT r, const secp256k1_fe *SECP256K1_RESTRICT a)
Definition: field_impl.h:34
static SECP256K1_INLINE int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b)
Definition: field_impl.h:21
#define SECP256K1_INLINE
Definition: util.h:48
#define VERIFY_CHECK(cond)
Definition: util.h:143
#define SECP256K1_RESTRICT
Definition: util.h:176
This field implementation represents the value as 10 uint32_t limbs in base 2^26.
Definition: field_10x26.h:14