Created
July 24, 2018 16:21
-
-
Save catid/c9f330994e25f8f23b96d9ffeb8e8d4f to your computer and use it in GitHub Desktop.
Fast 64-bit almost-finite field
This file contains hidden or 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
#include <stdint.h> | |
/* | |
65-bit multiplication of two 64-bit values a, b | |
with low bits set to 1 (implicitly): | |
(2a + 1)(2b + 1) | |
= 4ab + 2a + 2b + 1 | |
Stuffing it back into a 64-bit value: | |
= 2ab + a + b | |
*/ | |
// Product of a and b | |
static uint64_t mul65(uint64_t a, uint64_t b) | |
{ | |
return ((a * b) << 1) + (a + b); | |
} | |
// Multiplicative inverse of a | |
static uint64_t inv65(uint64_t a) | |
{ | |
uint64_t x = mul65(1, a) ^ 1; // 5 bit accurate guess | |
x = mul65(x, 1 + ~mul65(a, x)); // 10 bits | |
x = mul65(x, 1 + ~mul65(a, x)); // 20 bits | |
x = mul65(x, 1 + ~mul65(a, x)); // 40 bits | |
x = mul65(x, 1 + ~mul65(a, x)); // 80 bits | |
return x; | |
} | |
// Sum of a, b, c | |
static uint64_t add65(uint64_t a, uint64_t b, uint64_t c) | |
{ | |
return a + b + c + 1; | |
} | |
// = a + b - c | |
static uint64_t sub65(uint64_t a, uint64_t b, uint64_t c) | |
{ | |
return a + b - c; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment