#Multi-Precision Math
#define FIO_MATH
#include "fio-stl.h"Extra multi-precision operations on little-endian uint64_t arrays: division, shifts, two's-complement inverse, and bit-index queries. The core add/sub/mul helpers (fio_math_add, fio_math_sub, fio_math_mul, fio_math_addc64, etc.) and the wide union types (fio_u128, fio_u256, …) live in 000 core.h and do not require FIO_MATH.
Note: this module assumes the CPU performs 64-bit multiply in constant time, which is not guaranteed on all hardware.
#API Functions
#fio_math_div
FIO_IFUNC void fio_math_div(uint64_t *dest,
uint64_t *reminder,
const uint64_t *a,
const uint64_t *b,
const size_t number_array_length);Divides the number_array_length-word number a by b, storing the quotient in dest and the remainder in reminder. Either output may be NULL if you only need the other one.
Note: not constant time. Uses binary long division, which is simple but not the fastest algorithm on earth.
If b is zero, logs an error and fills both outputs with 0xFF.
#fio_math_shr
FIO_IFUNC void fio_math_shr(uint64_t *dest,
uint64_t *n,
const size_t right_shift_bits,
size_t number_array_length);Shifts n right by right_shift_bits and stores the result in dest.
#fio_math_shl
FIO_IFUNC void fio_math_shl(uint64_t *dest,
uint64_t *n,
const size_t left_shift_bits,
const size_t number_array_length);Shifts n left by left_shift_bits and stores the result in dest.
#fio_math_inv
FIO_IFUNC void fio_math_inv(uint64_t *dest, uint64_t *n, size_t len);Two's-complement negation of the len-word number n.
#fio_math_msb_index
FIO_MIFN size_t fio_math_msb_index(uint64_t *n, const size_t len);Returns the zero-based index of the most significant set bit, or (size_t)-1 if the number is zero. Useful for measuring bit length.
#fio_math_lsb_index
FIO_MIFN size_t fio_math_lsb_index(uint64_t *n, const size_t len);Returns the zero-based index of the least significant set bit, or (size_t)-1 if the number is zero.
#Example
#define FIO_MATH
#include "fio-stl.h"
int main(void) {
uint64_t a[2] = {0, 1}; /* 2^64 */
uint64_t b[2] = {3, 0}; /* 3 */
uint64_t q[2] = {0};
uint64_t r[2] = {0};
fio_math_div(q, r, a, b, 2);
printf("quot: %016llX%016llX\n",
(unsigned long long)q[1], (unsigned long long)q[0]);
printf("rem: %016llX%016llX\n",
(unsigned long long)r[1], (unsigned long long)r[0]);
return 0;
}