Skip to content

Commit 3bf06c3

Browse files
WIP: Simulated int128 type.
1 parent 10f9bd8 commit 3bf06c3

File tree

3 files changed

+369
-142
lines changed

3 files changed

+369
-142
lines changed

src/int128.h

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#ifndef SECP256K1_INT128_H
2+
#define SECP256K1_INT128_H
3+
4+
#include <stdint.h>
5+
#include "util.h"
6+
7+
/*
8+
#ifdef UINT128_MAX
9+
#undef UINT128_MAX
10+
*/
11+
12+
#if defined(UINT128_MAX)
13+
typedef uint128_t secp256k1_uint128;
14+
typedef int128_t secp256k1_int128;
15+
#else
16+
typedef struct {
17+
uint64_t lo;
18+
uint64_t hi;
19+
} secp256k1_uint128;
20+
21+
typedef secp256k1_uint128 secp256k1_int128;
22+
#endif
23+
24+
#if defined(_M_X64) | defined(_M_ARM64) | defined(_WIN64) /* MSVC */
25+
#include <intrin.h>
26+
#define secp256k1_umulh __umulh
27+
#define secp256k1_mulh __mulh
28+
#else
29+
static SECP256K1_INLINE uint64_t secp256k1_umulh(uint64_t a, uint64_t b) {
30+
#if defined(UINT128_MAX)
31+
return (uint64_t)(((uint128_t)a * b) >> 64);
32+
#else
33+
uint64_t t1 = (uint64_t)(uint32_t)a * (uint32_t)b;
34+
uint64_t t2 = (a >> 32) * (uint32_t)b;
35+
uint64_t t3 = (uint32_t)a*(b >> 32) + (t1 >> 32) + (uint32_t)t2;
36+
return (a >> 32)*(b >> 32) + (t2 >> 32) + (t3 >> 32);
37+
#endif
38+
}
39+
40+
static SECP256K1_INLINE int64_t secp256k1_mulh(int64_t a, int64_t b) {
41+
#if defined(UINT128_MAX)
42+
return (int64_t)(((int128_t)a * b) >> 64);
43+
#else
44+
uint64_t t1 = (uint64_t)(uint32_t)a * (uint32_t)b;
45+
int64_t t2 = (a >> 32) * (uint32_t)b;
46+
int64_t t3 = (uint32_t)a * (b >> 32);
47+
uint64_t t4 = (t1 >> 32) + (uint32_t)t2 + (uint32_t)t3;
48+
return (a >> 32) * (b >> 32) + (t2 >> 32) + (t3 >> 32) + (int64_t)(t4 >> 32);
49+
#endif
50+
}
51+
#endif
52+
53+
static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
54+
#if defined(UINT128_MAX)
55+
*r = (uint128_t)a * b;
56+
#else
57+
r->hi = secp256k1_umulh(a, b);
58+
r->lo += a * b;
59+
#endif
60+
}
61+
62+
static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
63+
#if defined(UINT128_MAX)
64+
*r += (uint128_t)a * b;
65+
#else
66+
uint64_t lo = a * b;
67+
r->hi += secp256k1_umulh(a, b) + (r->lo > ~lo);
68+
r->lo += lo;
69+
#endif
70+
}
71+
72+
static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) {
73+
#if defined(UINT128_MAX)
74+
*r += a;
75+
#else
76+
r->hi += (r->lo > ~a);
77+
r->lo += a;
78+
#endif
79+
}
80+
81+
/* Unsigned (logical) right shift.
82+
* Non-constant time in b.
83+
*/
84+
static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int b) {
85+
#if defined(UINT128_MAX)
86+
*r >>= b;
87+
#else
88+
if (b >= 64) {
89+
r->lo = (r->hi) >> (b-64);
90+
r->hi = 0;
91+
} else if (b > 0) {
92+
r->lo = ((r->hi & (((uint64_t)1<<b)-1)) << (64-b)) | r->lo >> b;
93+
r->hi >>= b;
94+
}
95+
#endif
96+
}
97+
98+
static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) {
99+
#if defined(UINT128_MAX)
100+
return (uint64_t)(*a);
101+
#else
102+
return a->lo;
103+
#endif
104+
}
105+
106+
static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) {
107+
#if defined(UINT128_MAX)
108+
*r = a;
109+
#else
110+
r->hi = 0;
111+
r->lo = a;
112+
#endif
113+
}
114+
115+
116+
static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
117+
#if defined(UINT128_MAX)
118+
*r = (int128_t)a * b;
119+
#else
120+
r->hi = (uint64_t)secp256k1_mulh(a, b);
121+
r->lo = (uint64_t)a * (uint64_t)b;
122+
#endif
123+
}
124+
125+
static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
126+
#if defined(UINT128_MAX)
127+
*r += (int128_t)a * b;
128+
#else
129+
uint64_t lo = (uint64_t)a * (uint64_t)b;
130+
r->hi += (uint64_t)secp256k1_mulh(a, b) + (r->lo > ~lo);
131+
r->lo += lo;
132+
#endif
133+
}
134+
135+
/* Signed (arithmetic) right shift.
136+
* Non-constant time in b.
137+
*/
138+
static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b) {
139+
#if defined(UINT128_MAX)
140+
*r >>= b;
141+
#else
142+
if (b >= 64) {
143+
r->lo = (uint64_t)((int64_t)(r->hi) >> (b-64));
144+
r->hi = (uint64_t)((int64_t)(r->hi) >> 63);
145+
} else if (b > 0) {
146+
r->lo = ((r->hi & (((uint64_t)1<<b)-1)) << (64-b)) | r->lo >> b;
147+
r->hi = (uint64_t)((int64_t)(r->hi) >> b);
148+
}
149+
#endif
150+
}
151+
152+
static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) {
153+
#if defined(UINT128_MAX)
154+
return (int64_t)(uint64_t)(*a);
155+
#else
156+
return (int64_t)a->lo;
157+
#endif
158+
}
159+
160+
static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) {
161+
#if defined(UINT128_MAX)
162+
*r = a;
163+
#else
164+
r->hi = (uint64_t)(a >> 63);
165+
r->lo = (uint64_t)a;
166+
#endif
167+
}
168+
169+
static SECP256K1_INLINE int secp256k1_i128_eq(const secp256k1_int128 *a, const secp256k1_int128 *b) {
170+
#if defined(UINT128_MAX)
171+
return *a == *b;
172+
#else
173+
return a->hi == b->hi && a->lo == b->lo;
174+
#endif
175+
}
176+
177+
/*
178+
#endif
179+
#define UINT128_MAX ((uint128_t)(int128_t)(-1))
180+
*/
181+
182+
#endif

0 commit comments

Comments
 (0)