-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
10f9bd8
commit 4c684ff
Showing
2 changed files
with
233 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#ifndef SECP256K1_INT128_H | ||
#define SECP256K1_INT128_H | ||
|
||
#include <stdint.h> | ||
|
||
/* | ||
#ifdef UINT128_MAX | ||
#undef UINT128_MAX | ||
*/ | ||
|
||
#if defined(UINT128_MAX) | ||
typedef uint128_t secp256k1_uint128; | ||
typedef int128_t secp256k1_int128; | ||
#else | ||
typedef struct { | ||
uint64_t lo; | ||
uint64_t hi; | ||
} secp256k1_uint128; | ||
|
||
typedef secp256k1_uint128 secp256k1_int128; | ||
#endif | ||
|
||
/* Low 32 bits of a (u)int64_t as an uint64_t. */ | ||
#define LO32(x) ((uint64_t)(x) & 0xffffffff) | ||
#define HI32(x) ((x) >> 32) | ||
|
||
#if defined(_M_X64) | defined(_M_ARM64) | defined(_WIN64) /* MSVC */ | ||
#include <intrin.h> | ||
#define secp256k1_umulh __umulh | ||
#define secp256k1_mulh __mulh | ||
#else | ||
static SECP256K1_INLINE uint64_t secp256k1_umulh(uint64_t a, uint64_t b) { | ||
#if defined(UINT128_MAX) | ||
return (uint64_t)(((uint128_t)a * b) >> 64); | ||
#else | ||
uint64_t t1 = LO32(a)*LO32(b); | ||
uint64_t t2 = HI32(a)*LO32(b); | ||
uint64_t t3 = LO32(a)*HI32(b) + HI32(t1) + LO32(t2); | ||
return HI32(a)*HI32(b) + HI32(t2) + HI32(t3); | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE int64_t secp256k1_mulh(int64_t a, int64_t b) { | ||
#if defined(UINT128_MAX) | ||
return (int64_t)(((int128_t)a * b) >> 64); | ||
#else | ||
uint64_t t1 = (uint64_t)(uint32_t)a * (uint32_t)b; | ||
int64_t t2 = (a >> 32) * (uint32_t)b; | ||
int64_t t3 = (uint32_t)a * (b >> 32); | ||
uint64_t t4 = (t1 >> 32) + (uint32_t)t2 + (uint32_t)t3; | ||
return (a >> 32) * (b >> 32) + (t2 >> 32) + (t3 >> 32) + (int64_t)(t4 >> 32); | ||
#endif | ||
} | ||
#endif | ||
|
||
static SECP256K1_INLINE void secp256k1_umul128(secp256k1_int128 *r, uint64_t a, uint64_t b) { | ||
#if defined(UINT128_MAX) | ||
*r = (uint128_t)a * b; | ||
#else | ||
r->hi = secp256k1_umulh(a, b); | ||
r->lo += a * b; | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) { | ||
#if defined(UINT128_MAX) | ||
*r = (int128_t)a * b; | ||
#else | ||
r->hi = (uint64_t)secp256k1_mulh(a, b); | ||
r->lo = (uint64_t)a * (uint64_t)b; | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) { | ||
#if defined(UINT128_MAX) | ||
*r += (int128_t)a * b; | ||
#else | ||
uint64_t lo = (uint64_t)a * (uint64_t)b; | ||
r->hi += (uint64_t)secp256k1_mulh(a, b) + (r->lo > ~lo); | ||
r->lo += lo; | ||
#endif | ||
} | ||
|
||
/* Signed (arithmetic) right shift. | ||
* Non-constant time in b. | ||
*/ | ||
static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b) { | ||
#if defined(UINT128_MAX) | ||
*r >>= b; | ||
#else | ||
if (b >= 64) { | ||
r->lo = (uint64_t)((int64_t)(r->hi) >> (b-64)); | ||
r->hi = (uint64_t)((int64_t)(r->hi) >> 63); | ||
} else if (b > 0) { | ||
r->lo = ((r->hi & (((uint64_t)1<<b)-1)) << (64-b)) | r->lo >> b; | ||
r->hi = (uint64_t)((int64_t)(r->hi) >> b); | ||
} | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) { | ||
#if defined(UINT128_MAX) | ||
return (int64_t)(uint64_t)(*a); | ||
#else | ||
return (int64_t)a->lo; | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) { | ||
#if defined(UINT128_MAX) | ||
*r = a; | ||
#else | ||
r->hi = (uint64_t)(a >> 63); | ||
r->lo = (uint64_t)a; | ||
#endif | ||
} | ||
|
||
static SECP256K1_INLINE int secp256k1_i128_eq(const secp256k1_int128 *a, const secp256k1_int128 *b) { | ||
#if defined(UINT128_MAX) | ||
return *a == *b; | ||
#else | ||
return a->hi == b->hi && a->lo == b->lo; | ||
#endif | ||
} | ||
|
||
/* | ||
#endif | ||
#define UINT128_MAX ((uint128_t)(int128_t)(-1)) | ||
*/ | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters