/* Copyright 2019-2021 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef EXESS_BIGINT_H #define EXESS_BIGINT_H #include "attributes.h" #include #include #include typedef uint32_t Bigit; /* We need enough precision for any double, the "largest" of which (using absolute exponents) is the smallest subnormal ~= 5e-324. This is 1076 bits long, but we need a bit more space for arithmetic. This is absurd, but such is decimal. These are only used on the stack so it doesn't hurt too much. */ #define BIGINT_MAX_SIGNIFICANT_BITS 1280u #define BIGINT_BIGIT_BITS 32u #define BIGINT_MAX_BIGITS (BIGINT_MAX_SIGNIFICANT_BITS / BIGINT_BIGIT_BITS) typedef struct { Bigit bigits[BIGINT_MAX_BIGITS]; unsigned n_bigits; } ExessBigint; void exess_bigint_zero(ExessBigint* num); size_t exess_bigint_print_hex(FILE* stream, const ExessBigint* num); void exess_bigint_clamp(ExessBigint* num); void exess_bigint_shift_left(ExessBigint* num, unsigned amount); void exess_bigint_set(ExessBigint* num, const ExessBigint* value); void exess_bigint_set_u32(ExessBigint* num, uint32_t value); void exess_bigint_set_u64(ExessBigint* num, uint64_t value); void exess_bigint_set_pow10(ExessBigint* num, unsigned exponent); void exess_bigint_set_decimal_string(ExessBigint* num, const char* str); void exess_bigint_set_hex_string(ExessBigint* num, const char* str); void exess_bigint_multiply_u32(ExessBigint* num, uint32_t factor); void exess_bigint_multiply_u64(ExessBigint* num, uint64_t factor); void exess_bigint_multiply_pow10(ExessBigint* num, unsigned exponent); EXESS_I_PURE_FUNC int exess_bigint_compare(const ExessBigint* lhs, const ExessBigint* rhs); void exess_bigint_add_u32(ExessBigint* lhs, uint32_t rhs); void exess_bigint_add(ExessBigint* lhs, const ExessBigint* rhs); void exess_bigint_subtract(ExessBigint* lhs, const ExessBigint* rhs); EXESS_I_PURE_FUNC Bigit exess_bigint_left_shifted_bigit(const ExessBigint* num, unsigned amount, unsigned index); /// Faster implementation of exess_bigint_subtract(lhs, rhs << amount) void exess_bigint_subtract_left_shifted(ExessBigint* lhs, const ExessBigint* rhs, unsigned amount); /// Faster implementation of exess_bigint_compare(l + p, c) EXESS_I_PURE_FUNC int exess_bigint_plus_compare(const ExessBigint* l, const ExessBigint* p, const ExessBigint* c); /// Divide and set `lhs` to modulo uint32_t exess_bigint_divmod(ExessBigint* lhs, const ExessBigint* rhs); #endif // EXESS_BIGINT_H