Electroneum
Toggle main menu visibility
Loading...
Searching...
No Matches
int128_struct_impl.h
Go to the documentation of this file.
1
#ifndef SECP256K1_INT128_STRUCT_IMPL_H
2
#define SECP256K1_INT128_STRUCT_IMPL_H
3
4
#include "
int128.h
"
5
6
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
/* MSVC */
7
# include <intrin.h>
8
# if defined(_M_ARM64) || defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
9
/* On ARM64 MSVC, use __(u)mulh for the upper half of 64x64 multiplications.
10
(Define SECP256K1_MSVC_MULH_TEST_OVERRIDE to test this code path on X64,
11
which supports both __(u)mulh and _umul128.) */
12
# if defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
13
# pragma message(__FILE__ ": SECP256K1_MSVC_MULH_TEST_OVERRIDE is defined, forcing use of __(u)mulh.")
14
# endif
15
static
SECP256K1_INLINE
uint64_t
secp256k1_umul128(
uint64_t
a
,
uint64_t
b,
uint64_t
* hi) {
16
*hi = __umulh(
a
, b);
17
return
a
* b;
18
}
19
20
static
SECP256K1_INLINE
int64_t
secp256k1_mul128(
int64_t
a
,
int64_t
b,
int64_t
* hi) {
21
*hi = __mulh(
a
, b);
22
return
(
uint64_t
)
a
* (
uint64_t
)b;
23
}
24
# else
25
/* On x84_64 MSVC, use native _(u)mul128 for 64x64->128 multiplications. */
26
# define secp256k1_umul128 _umul128
27
# define secp256k1_mul128 _mul128
28
# endif
29
#else
30
/* On other systems, emulate 64x64->128 multiplications using 32x32->64 multiplications. */
31
static
SECP256K1_INLINE
uint64_t
secp256k1_umul128(
uint64_t
a
,
uint64_t
b,
uint64_t
* hi) {
32
uint64_t
ll = (
uint64_t
)(
uint32_t
)
a
* (
uint32_t
)b;
33
uint64_t
lh = (
uint32_t
)
a
* (b >> 32);
34
uint64_t
hl = (
a
>> 32) * (
uint32_t
)b;
35
uint64_t
hh = (
a
>> 32) * (b >> 32);
36
uint64_t
mid34 = (ll >> 32) + (
uint32_t
)lh + (
uint32_t
)hl;
37
*hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
38
return
(mid34 << 32) + (
uint32_t
)ll;
39
}
40
41
static
SECP256K1_INLINE
int64_t
secp256k1_mul128(
int64_t
a
,
int64_t
b,
int64_t
* hi) {
42
uint64_t
ll = (
uint64_t
)(
uint32_t
)
a
* (
uint32_t
)b;
43
int64_t
lh = (
uint32_t
)
a
* (b >> 32);
44
int64_t
hl = (
a
>> 32) * (
uint32_t
)b;
45
int64_t
hh = (
a
>> 32) * (b >> 32);
46
uint64_t
mid34 = (ll >> 32) + (
uint32_t
)lh + (
uint32_t
)hl;
47
*hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
48
return
(mid34 << 32) + (
uint32_t
)ll;
49
}
50
#endif
51
52
static
SECP256K1_INLINE
void
secp256k1_u128_load(
secp256k1_uint128
*r,
uint64_t
hi,
uint64_t
lo) {
53
r->
hi
= hi;
54
r->
lo
= lo;
55
}
56
57
static
SECP256K1_INLINE
void
secp256k1_u128_mul(
secp256k1_uint128
*r,
uint64_t
a
,
uint64_t
b) {
58
r->
lo
= secp256k1_umul128(
a
, b, &r->
hi
);
59
}
60
61
static
SECP256K1_INLINE
void
secp256k1_u128_accum_mul(
secp256k1_uint128
*r,
uint64_t
a
,
uint64_t
b) {
62
uint64_t
lo, hi;
63
lo = secp256k1_umul128(
a
, b, &hi);
64
r->
lo
+= lo;
65
r->
hi
+= hi + (r->
lo
< lo);
66
}
67
68
static
SECP256K1_INLINE
void
secp256k1_u128_accum_u64(
secp256k1_uint128
*r,
uint64_t
a
) {
69
r->
lo
+=
a
;
70
r->
hi
+= r->
lo
<
a
;
71
}
72
73
/* Unsigned (logical) right shift.
74
* Non-constant time in n.
75
*/
76
static
SECP256K1_INLINE
void
secp256k1_u128_rshift(
secp256k1_uint128
*r,
unsigned
int
n) {
77
VERIFY_CHECK
(n < 128);
78
if
(n >= 64) {
79
r->
lo
= r->
hi
>> (n-64);
80
r->
hi
= 0;
81
}
else
if
(n > 0) {
82
r->
lo
= ((1U * r->
hi
) << (64-n)) | r->
lo
>> n;
83
r->
hi
>>= n;
84
}
85
}
86
87
static
SECP256K1_INLINE
uint64_t
secp256k1_u128_to_u64(
const
secp256k1_uint128
*
a
) {
88
return
a
->lo;
89
}
90
91
static
SECP256K1_INLINE
uint64_t
secp256k1_u128_hi_u64(
const
secp256k1_uint128
*
a
) {
92
return
a
->hi;
93
}
94
95
static
SECP256K1_INLINE
void
secp256k1_u128_from_u64(
secp256k1_uint128
*r,
uint64_t
a
) {
96
r->
hi
= 0;
97
r->
lo
=
a
;
98
}
99
100
static
SECP256K1_INLINE
int
secp256k1_u128_check_bits(
const
secp256k1_uint128
*r,
unsigned
int
n) {
101
VERIFY_CHECK
(n < 128);
102
return
n >= 64 ? r->
hi
>> (n - 64) == 0
103
: r->hi == 0 && r->lo >> n == 0;
104
}
105
106
static
SECP256K1_INLINE
void
secp256k1_i128_load(
secp256k1_int128
*r,
int64_t
hi,
uint64_t
lo) {
107
r->hi = hi;
108
r->lo = lo;
109
}
110
111
static
SECP256K1_INLINE
void
secp256k1_i128_mul(
secp256k1_int128
*r,
int64_t
a
,
int64_t
b) {
112
int64_t
hi;
113
r->lo = (
uint64_t
)secp256k1_mul128(
a
, b, &hi);
114
r->hi = (
uint64_t
)hi;
115
}
116
117
static
SECP256K1_INLINE
void
secp256k1_i128_accum_mul(
secp256k1_int128
*r,
int64_t
a
,
int64_t
b) {
118
int64_t
hi;
119
uint64_t
lo = (
uint64_t
)secp256k1_mul128(
a
, b, &hi);
120
r->lo += lo;
121
hi += r->lo < lo;
122
/* Verify no overflow.
123
* If r represents a positive value (the sign bit is not set) and the value we are adding is a positive value (the sign bit is not set),
124
* then we require that the resulting value also be positive (the sign bit is not set).
125
* Note that (X <= Y) means (X implies Y) when X and Y are boolean values (i.e. 0 or 1).
126
*/
127
VERIFY_CHECK
((r->hi <= 0x7fffffffffffffffu && (
uint64_t
)hi <= 0x7fffffffffffffffu) <= (r->hi + (
uint64_t
)hi <= 0x7fffffffffffffffu));
128
/* Verify no underflow.
129
* If r represents a negative value (the sign bit is set) and the value we are adding is a negative value (the sign bit is set),
130
* then we require that the resulting value also be negative (the sign bit is set).
131
*/
132
VERIFY_CHECK
((r->hi > 0x7fffffffffffffffu && (
uint64_t
)hi > 0x7fffffffffffffffu) <= (r->hi + (
uint64_t
)hi > 0x7fffffffffffffffu));
133
r->hi += hi;
134
}
135
136
static
SECP256K1_INLINE
void
secp256k1_i128_dissip_mul(
secp256k1_int128
*r,
int64_t
a
,
int64_t
b) {
137
int64_t
hi;
138
uint64_t
lo = (
uint64_t
)secp256k1_mul128(
a
, b, &hi);
139
hi += r->lo < lo;
140
/* Verify no overflow.
141
* If r represents a positive value (the sign bit is not set) and the value we are subtracting is a negative value (the sign bit is set),
142
* then we require that the resulting value also be positive (the sign bit is not set).
143
*/
144
VERIFY_CHECK
((r->hi <= 0x7fffffffffffffffu && (
uint64_t
)hi > 0x7fffffffffffffffu) <= (r->hi - (
uint64_t
)hi <= 0x7fffffffffffffffu));
145
/* Verify no underflow.
146
* If r represents a negative value (the sign bit is set) and the value we are subtracting is a positive value (the sign sign bit is not set),
147
* then we require that the resulting value also be negative (the sign bit is set).
148
*/
149
VERIFY_CHECK
((r->hi > 0x7fffffffffffffffu && (
uint64_t
)hi <= 0x7fffffffffffffffu) <= (r->hi - (
uint64_t
)hi > 0x7fffffffffffffffu));
150
r->hi -= hi;
151
r->lo -= lo;
152
}
153
154
static
SECP256K1_INLINE
void
secp256k1_i128_det(
secp256k1_int128
*r,
int64_t
a
,
int64_t
b,
int64_t
c,
int64_t
d) {
155
secp256k1_i128_mul(r,
a
, d);
156
secp256k1_i128_dissip_mul(r, b, c);
157
}
158
159
/* Signed (arithmetic) right shift.
160
* Non-constant time in n.
161
*/
162
static
SECP256K1_INLINE
void
secp256k1_i128_rshift(
secp256k1_int128
*r,
unsigned
int
n) {
163
VERIFY_CHECK
(n < 128);
164
if
(n >= 64) {
165
r->lo = (
uint64_t
)((
int64_t
)(r->hi) >> (n-64));
166
r->hi = (
uint64_t
)((
int64_t
)(r->hi) >> 63);
167
}
else
if
(n > 0) {
168
r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
169
r->hi = (
uint64_t
)((
int64_t
)(r->hi) >> n);
170
}
171
}
172
173
static
SECP256K1_INLINE
uint64_t
secp256k1_i128_to_u64(
const
secp256k1_int128
*
a
) {
174
return
a
->lo;
175
}
176
177
static
SECP256K1_INLINE
int64_t
secp256k1_i128_to_i64(
const
secp256k1_int128
*
a
) {
178
/* Verify that a represents a 64 bit signed value by checking that the high bits are a sign extension of the low bits. */
179
VERIFY_CHECK
(
a
->hi == -(
a
->lo >> 63));
180
return
(
int64_t
)secp256k1_i128_to_u64(
a
);
181
}
182
183
static
SECP256K1_INLINE
void
secp256k1_i128_from_i64(
secp256k1_int128
*r,
int64_t
a
) {
184
r->hi = (
uint64_t
)(
a
>> 63);
185
r->lo = (
uint64_t
)
a
;
186
}
187
188
static
SECP256K1_INLINE
int
secp256k1_i128_eq_var(
const
secp256k1_int128
*
a
,
const
secp256k1_int128
*b) {
189
return
a
->hi == b->hi &&
a
->lo == b->lo;
190
}
191
192
static
SECP256K1_INLINE
int
secp256k1_i128_check_pow2(
const
secp256k1_int128
*r,
unsigned
int
n) {
193
VERIFY_CHECK
(n < 127);
194
return
n >= 64 ? r->hi == (
uint64_t
)1 << (n - 64) && r->lo == 0
195
: r->hi == 0 && r->lo == (
uint64_t
)1 << n;
196
}
197
198
#endif
VERIFY_CHECK
#define VERIFY_CHECK(cond)
Definition
util.h:96
int128.h
secp256k1_int128
int128_t secp256k1_int128
Definition
int128_native.h:17
a
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition
pointer.h:1124
SECP256K1_INLINE
#define SECP256K1_INLINE
Definition
secp256k1.h:131
int64_t
signed __int64 int64_t
Definition
stdint.h:135
uint32_t
unsigned int uint32_t
Definition
stdint.h:126
uint64_t
unsigned __int64 uint64_t
Definition
stdint.h:136
secp256k1_uint128
Definition
int128_struct.h:7
secp256k1_uint128::lo
uint64_t lo
Definition
int128_struct.h:8
secp256k1_uint128::hi
uint64_t hi
Definition
int128_struct.h:9
external
secp256k1
src
int128_struct_impl.h
Generated on
for Electroneum by
1.17.0