150696a6eSStefan Eßer /* 250696a6eSStefan Eßer * ***************************************************************************** 350696a6eSStefan Eßer * 450696a6eSStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 550696a6eSStefan Eßer * 6d101cdd6SStefan Eßer * Copyright (c) 2018-2023 Gavin D. Howard and contributors. 750696a6eSStefan Eßer * 850696a6eSStefan Eßer * Redistribution and use in source and binary forms, with or without 950696a6eSStefan Eßer * modification, are permitted provided that the following conditions are met: 1050696a6eSStefan Eßer * 1150696a6eSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 1250696a6eSStefan Eßer * list of conditions and the following disclaimer. 1350696a6eSStefan Eßer * 1450696a6eSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 1550696a6eSStefan Eßer * this list of conditions and the following disclaimer in the documentation 1650696a6eSStefan Eßer * and/or other materials provided with the distribution. 1750696a6eSStefan Eßer * 1850696a6eSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1950696a6eSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2050696a6eSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2150696a6eSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2250696a6eSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2350696a6eSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2450696a6eSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2550696a6eSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2650696a6eSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2750696a6eSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2850696a6eSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 2950696a6eSStefan Eßer * 3050696a6eSStefan Eßer * ***************************************************************************** 3150696a6eSStefan Eßer * 3250696a6eSStefan Eßer * The public header for the bc library. 3350696a6eSStefan Eßer * 3450696a6eSStefan Eßer */ 3550696a6eSStefan Eßer 3650696a6eSStefan Eßer #ifndef BC_BCL_H 3750696a6eSStefan Eßer #define BC_BCL_H 3850696a6eSStefan Eßer 39d101cdd6SStefan Eßer #include <stdbool.h> 40d101cdd6SStefan Eßer #include <stdlib.h> 41d101cdd6SStefan Eßer #include <limits.h> 42d101cdd6SStefan Eßer #include <stdint.h> 43d101cdd6SStefan Eßer 44103d7cdfSStefan Eßer #ifndef NDEBUG 45103d7cdfSStefan Eßer #define BC_DEBUG (1) 46103d7cdfSStefan Eßer #else // NDEBUG 47103d7cdfSStefan Eßer #define BC_DEBUG (0) 48103d7cdfSStefan Eßer #endif // NDEBUG 49103d7cdfSStefan Eßer 507e5c51e5SStefan Eßer #ifdef _WIN32 517e5c51e5SStefan Eßer #include <Windows.h> 527e5c51e5SStefan Eßer #include <BaseTsd.h> 537e5c51e5SStefan Eßer #include <stdio.h> 547e5c51e5SStefan Eßer #include <io.h> 557e5c51e5SStefan Eßer #endif // _WIN32 567e5c51e5SStefan Eßer 577e5c51e5SStefan Eßer #ifdef _WIN32 587e5c51e5SStefan Eßer #define ssize_t SSIZE_T 597e5c51e5SStefan Eßer #endif // _WIN32 607e5c51e5SStefan Eßer 6144d4804dSStefan Eßer #define BCL_SEED_ULONGS (4) 6244d4804dSStefan Eßer #define BCL_SEED_SIZE (sizeof(long) * BCL_SEED_ULONGS) 6344d4804dSStefan Eßer 6444d4804dSStefan Eßer // For some reason, LONG_BIT is not defined in some versions of gcc. 6544d4804dSStefan Eßer // I define it here to the minimum accepted value in the POSIX standard. 6644d4804dSStefan Eßer #ifndef LONG_BIT 6744d4804dSStefan Eßer #define LONG_BIT (32) 6844d4804dSStefan Eßer #endif // LONG_BIT 6944d4804dSStefan Eßer 7044d4804dSStefan Eßer #ifndef BC_LONG_BIT 7144d4804dSStefan Eßer #define BC_LONG_BIT LONG_BIT 7244d4804dSStefan Eßer #endif // BC_LONG_BIT 7344d4804dSStefan Eßer 7444d4804dSStefan Eßer #if BC_LONG_BIT > LONG_BIT 7544d4804dSStefan Eßer #error BC_LONG_BIT cannot be greater than LONG_BIT 7644d4804dSStefan Eßer #endif // BC_LONG_BIT > LONG_BIT 7744d4804dSStefan Eßer 7844d4804dSStefan Eßer // For more information about the items here, see the either the 7944d4804dSStefan Eßer // manuals/bcl.3.md or manuals/bcl.3 manuals. 8044d4804dSStefan Eßer 8144d4804dSStefan Eßer // BclBigDig is a fixed-size integer type that bcl can convert numbers to. 8244d4804dSStefan Eßer // 8344d4804dSStefan Eßer // BclRandInt is the type of fixed-size integer natively returned by the 8444d4804dSStefan Eßer // pseudo-random number generator. 8544d4804dSStefan Eßer #if BC_LONG_BIT >= 64 8644d4804dSStefan Eßer 8744d4804dSStefan Eßer typedef uint64_t BclBigDig; 8844d4804dSStefan Eßer typedef uint64_t BclRandInt; 8944d4804dSStefan Eßer 9044d4804dSStefan Eßer #elif BC_LONG_BIT >= 32 9144d4804dSStefan Eßer 9244d4804dSStefan Eßer typedef uint32_t BclBigDig; 9344d4804dSStefan Eßer typedef uint32_t BclRandInt; 9444d4804dSStefan Eßer 9544d4804dSStefan Eßer #else 9644d4804dSStefan Eßer 9744d4804dSStefan Eßer #error BC_LONG_BIT must be at least 32 9844d4804dSStefan Eßer 9944d4804dSStefan Eßer #endif // BC_LONG_BIT >= 64 10044d4804dSStefan Eßer 10144d4804dSStefan Eßer #ifndef BC_ENABLE_LIBRARY 10244d4804dSStefan Eßer #define BC_ENABLE_LIBRARY (1) 10344d4804dSStefan Eßer #endif // BC_ENABLE_LIBRARY 10444d4804dSStefan Eßer 1057e5c51e5SStefan Eßer #if BC_ENABLE_LIBRARY 10650696a6eSStefan Eßer 10778bc019dSStefan Eßer typedef enum BclError 10878bc019dSStefan Eßer { 10950696a6eSStefan Eßer BCL_ERROR_NONE, 11050696a6eSStefan Eßer 11150696a6eSStefan Eßer BCL_ERROR_INVALID_NUM, 11250696a6eSStefan Eßer BCL_ERROR_INVALID_CONTEXT, 11350696a6eSStefan Eßer BCL_ERROR_SIGNAL, 11450696a6eSStefan Eßer 11550696a6eSStefan Eßer BCL_ERROR_MATH_NEGATIVE, 11650696a6eSStefan Eßer BCL_ERROR_MATH_NON_INTEGER, 11750696a6eSStefan Eßer BCL_ERROR_MATH_OVERFLOW, 11850696a6eSStefan Eßer BCL_ERROR_MATH_DIVIDE_BY_ZERO, 11950696a6eSStefan Eßer 12050696a6eSStefan Eßer BCL_ERROR_PARSE_INVALID_STR, 12150696a6eSStefan Eßer 12250696a6eSStefan Eßer BCL_ERROR_FATAL_ALLOC_ERR, 12350696a6eSStefan Eßer BCL_ERROR_FATAL_UNKNOWN_ERR, 12450696a6eSStefan Eßer 12550696a6eSStefan Eßer BCL_ERROR_NELEMS, 12650696a6eSStefan Eßer 12750696a6eSStefan Eßer } BclError; 12850696a6eSStefan Eßer 12978bc019dSStefan Eßer typedef struct BclNumber 13078bc019dSStefan Eßer { 13150696a6eSStefan Eßer size_t i; 13250696a6eSStefan Eßer 13350696a6eSStefan Eßer } BclNumber; 13450696a6eSStefan Eßer 13550696a6eSStefan Eßer struct BclCtxt; 13650696a6eSStefan Eßer 13750696a6eSStefan Eßer typedef struct BclCtxt* BclContext; 13850696a6eSStefan Eßer 139d101cdd6SStefan Eßer BclError 140d101cdd6SStefan Eßer bcl_start(void); 14150696a6eSStefan Eßer 142d101cdd6SStefan Eßer void 143d101cdd6SStefan Eßer bcl_end(void); 14450696a6eSStefan Eßer 14578bc019dSStefan Eßer BclError 14678bc019dSStefan Eßer bcl_init(void); 14750696a6eSStefan Eßer 14878bc019dSStefan Eßer void 14978bc019dSStefan Eßer bcl_free(void); 15050696a6eSStefan Eßer 15178bc019dSStefan Eßer bool 15278bc019dSStefan Eßer bcl_abortOnFatalError(void); 15350696a6eSStefan Eßer 15478bc019dSStefan Eßer void 15578bc019dSStefan Eßer bcl_setAbortOnFatalError(bool abrt); 15650696a6eSStefan Eßer 15778bc019dSStefan Eßer bool 15878bc019dSStefan Eßer bcl_leadingZeroes(void); 15950696a6eSStefan Eßer 16078bc019dSStefan Eßer void 16178bc019dSStefan Eßer bcl_setLeadingZeroes(bool leadingZeroes); 16250696a6eSStefan Eßer 163d101cdd6SStefan Eßer bool 164d101cdd6SStefan Eßer bcl_digitClamp(void); 165d101cdd6SStefan Eßer 166d101cdd6SStefan Eßer void 167d101cdd6SStefan Eßer bcl_setDigitClamp(bool digitClamp); 168d101cdd6SStefan Eßer 16978bc019dSStefan Eßer void 17078bc019dSStefan Eßer bcl_gc(void); 17150696a6eSStefan Eßer 17278bc019dSStefan Eßer BclError 17378bc019dSStefan Eßer bcl_pushContext(BclContext ctxt); 17450696a6eSStefan Eßer 17578bc019dSStefan Eßer void 17678bc019dSStefan Eßer bcl_popContext(void); 17750696a6eSStefan Eßer 17878bc019dSStefan Eßer BclContext 17978bc019dSStefan Eßer bcl_context(void); 18050696a6eSStefan Eßer 18178bc019dSStefan Eßer BclContext 18278bc019dSStefan Eßer bcl_ctxt_create(void); 18350696a6eSStefan Eßer 18478bc019dSStefan Eßer void 18578bc019dSStefan Eßer bcl_ctxt_free(BclContext ctxt); 18650696a6eSStefan Eßer 18778bc019dSStefan Eßer void 18878bc019dSStefan Eßer bcl_ctxt_freeNums(BclContext ctxt); 18950696a6eSStefan Eßer 19078bc019dSStefan Eßer size_t 19178bc019dSStefan Eßer bcl_ctxt_scale(BclContext ctxt); 19250696a6eSStefan Eßer 19378bc019dSStefan Eßer void 19478bc019dSStefan Eßer bcl_ctxt_setScale(BclContext ctxt, size_t scale); 19550696a6eSStefan Eßer 19678bc019dSStefan Eßer size_t 19778bc019dSStefan Eßer bcl_ctxt_ibase(BclContext ctxt); 19878bc019dSStefan Eßer 19978bc019dSStefan Eßer void 20078bc019dSStefan Eßer bcl_ctxt_setIbase(BclContext ctxt, size_t ibase); 20178bc019dSStefan Eßer 20278bc019dSStefan Eßer size_t 20378bc019dSStefan Eßer bcl_ctxt_obase(BclContext ctxt); 20478bc019dSStefan Eßer 20578bc019dSStefan Eßer void 20678bc019dSStefan Eßer bcl_ctxt_setObase(BclContext ctxt, size_t obase); 20778bc019dSStefan Eßer 20878bc019dSStefan Eßer BclError 20978bc019dSStefan Eßer bcl_err(BclNumber n); 21078bc019dSStefan Eßer 21178bc019dSStefan Eßer BclNumber 21278bc019dSStefan Eßer bcl_num_create(void); 21378bc019dSStefan Eßer 21478bc019dSStefan Eßer void 21578bc019dSStefan Eßer bcl_num_free(BclNumber n); 21678bc019dSStefan Eßer 21778bc019dSStefan Eßer bool 21878bc019dSStefan Eßer bcl_num_neg(BclNumber n); 21978bc019dSStefan Eßer 22078bc019dSStefan Eßer void 22178bc019dSStefan Eßer bcl_num_setNeg(BclNumber n, bool neg); 22278bc019dSStefan Eßer 22378bc019dSStefan Eßer size_t 22478bc019dSStefan Eßer bcl_num_scale(BclNumber n); 22578bc019dSStefan Eßer 22678bc019dSStefan Eßer BclError 22778bc019dSStefan Eßer bcl_num_setScale(BclNumber n, size_t scale); 22878bc019dSStefan Eßer 22978bc019dSStefan Eßer size_t 23078bc019dSStefan Eßer bcl_num_len(BclNumber n); 23178bc019dSStefan Eßer 23278bc019dSStefan Eßer BclError 23378bc019dSStefan Eßer bcl_copy(BclNumber d, BclNumber s); 23478bc019dSStefan Eßer 23578bc019dSStefan Eßer BclNumber 23678bc019dSStefan Eßer bcl_dup(BclNumber s); 23778bc019dSStefan Eßer 23878bc019dSStefan Eßer BclError 23978bc019dSStefan Eßer bcl_bigdig(BclNumber n, BclBigDig* result); 24078bc019dSStefan Eßer 241175a4d10SStefan Eßer BclError 242175a4d10SStefan Eßer bcl_bigdig_keep(BclNumber n, BclBigDig* result); 243175a4d10SStefan Eßer 24478bc019dSStefan Eßer BclNumber 24578bc019dSStefan Eßer bcl_bigdig2num(BclBigDig val); 24678bc019dSStefan Eßer 24778bc019dSStefan Eßer BclNumber 24878bc019dSStefan Eßer bcl_add(BclNumber a, BclNumber b); 24978bc019dSStefan Eßer 25078bc019dSStefan Eßer BclNumber 251175a4d10SStefan Eßer bcl_add_keep(BclNumber a, BclNumber b); 252175a4d10SStefan Eßer 253175a4d10SStefan Eßer BclNumber 25478bc019dSStefan Eßer bcl_sub(BclNumber a, BclNumber b); 25578bc019dSStefan Eßer 25678bc019dSStefan Eßer BclNumber 257175a4d10SStefan Eßer bcl_sub_keep(BclNumber a, BclNumber b); 258175a4d10SStefan Eßer 259175a4d10SStefan Eßer BclNumber 26078bc019dSStefan Eßer bcl_mul(BclNumber a, BclNumber b); 26178bc019dSStefan Eßer 26278bc019dSStefan Eßer BclNumber 263175a4d10SStefan Eßer bcl_mul_keep(BclNumber a, BclNumber b); 264175a4d10SStefan Eßer 265175a4d10SStefan Eßer BclNumber 26678bc019dSStefan Eßer bcl_div(BclNumber a, BclNumber b); 26778bc019dSStefan Eßer 26878bc019dSStefan Eßer BclNumber 269175a4d10SStefan Eßer bcl_div_keep(BclNumber a, BclNumber b); 270175a4d10SStefan Eßer 271175a4d10SStefan Eßer BclNumber 27278bc019dSStefan Eßer bcl_mod(BclNumber a, BclNumber b); 27378bc019dSStefan Eßer 27478bc019dSStefan Eßer BclNumber 275175a4d10SStefan Eßer bcl_mod_keep(BclNumber a, BclNumber b); 276175a4d10SStefan Eßer 277175a4d10SStefan Eßer BclNumber 27878bc019dSStefan Eßer bcl_pow(BclNumber a, BclNumber b); 27978bc019dSStefan Eßer 28078bc019dSStefan Eßer BclNumber 281175a4d10SStefan Eßer bcl_pow_keep(BclNumber a, BclNumber b); 282175a4d10SStefan Eßer 283175a4d10SStefan Eßer BclNumber 28478bc019dSStefan Eßer bcl_lshift(BclNumber a, BclNumber b); 28578bc019dSStefan Eßer 28678bc019dSStefan Eßer BclNumber 287175a4d10SStefan Eßer bcl_lshift_keep(BclNumber a, BclNumber b); 288175a4d10SStefan Eßer 289175a4d10SStefan Eßer BclNumber 29078bc019dSStefan Eßer bcl_rshift(BclNumber a, BclNumber b); 29178bc019dSStefan Eßer 29278bc019dSStefan Eßer BclNumber 293175a4d10SStefan Eßer bcl_rshift_keep(BclNumber a, BclNumber b); 294175a4d10SStefan Eßer 295175a4d10SStefan Eßer BclNumber 29678bc019dSStefan Eßer bcl_sqrt(BclNumber a); 29778bc019dSStefan Eßer 298175a4d10SStefan Eßer BclNumber 299175a4d10SStefan Eßer bcl_sqrt_keep(BclNumber a); 300175a4d10SStefan Eßer 30178bc019dSStefan Eßer BclError 30278bc019dSStefan Eßer bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d); 30378bc019dSStefan Eßer 304175a4d10SStefan Eßer BclError 305175a4d10SStefan Eßer bcl_divmod_keep(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d); 306175a4d10SStefan Eßer 30778bc019dSStefan Eßer BclNumber 30878bc019dSStefan Eßer bcl_modexp(BclNumber a, BclNumber b, BclNumber c); 30978bc019dSStefan Eßer 310175a4d10SStefan Eßer BclNumber 311175a4d10SStefan Eßer bcl_modexp_keep(BclNumber a, BclNumber b, BclNumber c); 312175a4d10SStefan Eßer 31378bc019dSStefan Eßer ssize_t 31478bc019dSStefan Eßer bcl_cmp(BclNumber a, BclNumber b); 31578bc019dSStefan Eßer 31678bc019dSStefan Eßer void 31778bc019dSStefan Eßer bcl_zero(BclNumber n); 31878bc019dSStefan Eßer 31978bc019dSStefan Eßer void 32078bc019dSStefan Eßer bcl_one(BclNumber n); 32178bc019dSStefan Eßer 32278bc019dSStefan Eßer BclNumber 32378bc019dSStefan Eßer bcl_parse(const char* restrict val); 32478bc019dSStefan Eßer 32578bc019dSStefan Eßer char* 32678bc019dSStefan Eßer bcl_string(BclNumber n); 32778bc019dSStefan Eßer 328175a4d10SStefan Eßer char* 329175a4d10SStefan Eßer bcl_string_keep(BclNumber n); 330175a4d10SStefan Eßer 33178bc019dSStefan Eßer BclNumber 33278bc019dSStefan Eßer bcl_irand(BclNumber a); 33378bc019dSStefan Eßer 33478bc019dSStefan Eßer BclNumber 335175a4d10SStefan Eßer bcl_irand_keep(BclNumber a); 336175a4d10SStefan Eßer 337175a4d10SStefan Eßer BclNumber 33878bc019dSStefan Eßer bcl_frand(size_t places); 33978bc019dSStefan Eßer 34078bc019dSStefan Eßer BclNumber 34178bc019dSStefan Eßer bcl_ifrand(BclNumber a, size_t places); 34278bc019dSStefan Eßer 343175a4d10SStefan Eßer BclNumber 344175a4d10SStefan Eßer bcl_ifrand_keep(BclNumber a, size_t places); 345175a4d10SStefan Eßer 34678bc019dSStefan Eßer BclError 34778bc019dSStefan Eßer bcl_rand_seedWithNum(BclNumber n); 34878bc019dSStefan Eßer 34978bc019dSStefan Eßer BclError 350175a4d10SStefan Eßer bcl_rand_seedWithNum_keep(BclNumber n); 351175a4d10SStefan Eßer 352175a4d10SStefan Eßer BclError 35378bc019dSStefan Eßer bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE]); 35478bc019dSStefan Eßer 35578bc019dSStefan Eßer void 35678bc019dSStefan Eßer bcl_rand_reseed(void); 35778bc019dSStefan Eßer 35878bc019dSStefan Eßer BclNumber 35978bc019dSStefan Eßer bcl_rand_seed2num(void); 36078bc019dSStefan Eßer 36178bc019dSStefan Eßer BclRandInt 36278bc019dSStefan Eßer bcl_rand_int(void); 36378bc019dSStefan Eßer 36478bc019dSStefan Eßer BclRandInt 36578bc019dSStefan Eßer bcl_rand_bounded(BclRandInt bound); 36650696a6eSStefan Eßer 3677e5c51e5SStefan Eßer #endif // BC_ENABLE_LIBRARY 3687e5c51e5SStefan Eßer 36950696a6eSStefan Eßer #endif // BC_BCL_H 370