|
NAMEbcl - library of arbitrary precision decimal arithmeticSYNOPSISUse#include <bcl.h>Link with -lbcl. SignalsThis procedure will allow clients to use signals to interrupt computations running in bcl(3).void bcl_handleSignal(void); bool bcl_running(void); SetupThese items allow clients to set up bcl(3).BclError bcl_init(void); void bcl_free(void); bool bcl_abortOnFatalError(void); void bcl_setAbortOnFatalError(bool abrt); bool bcl_leadingZeroes(void); void bcl_setLeadingZeroes(bool leadingZeroes); void bcl_gc(void); ContextsThese items will allow clients to handle contexts, which are isolated from each other. This allows more than one client to use bcl(3) in the same program.struct BclCtxt; typedef struct BclCtxt* BclContext; BclContext bcl_ctxt_create(void); void bcl_ctxt_free(BclContext ctxt); BclError bcl_pushContext(BclContext ctxt); void bcl_popContext(void); BclContext bcl_context(void); void bcl_ctxt_freeNums(BclContext ctxt); size_t bcl_ctxt_scale(BclContext ctxt); void bcl_ctxt_setScale(BclContext ctxt, size_t scale); size_t bcl_ctxt_ibase(BclContext ctxt); void bcl_ctxt_setIbase(BclContext ctxt, size_t ibase); size_t bcl_ctxt_obase(BclContext ctxt); void bcl_ctxt_setObase(BclContext ctxt, size_t obase); ErrorsThese items allow clients to handle errors.typedef enum BclError BclError; BclError bcl_err(BclNumber n); NumbersThese items allow clients to manipulate and query the arbitrary-precision numbers managed by bcl(3).typedef struct { size_t i; } BclNumber; BclNumber bcl_num_create(void); void bcl_num_free(BclNumber n); bool bcl_num_neg(BclNumber n); void bcl_num_setNeg(BclNumber n, bool neg); size_t bcl_num_scale(BclNumber n); BclError bcl_num_setScale(BclNumber n, size_t scale); size_t bcl_num_len(BclNumber n); ConversionThese items allow clients to convert numbers into and from strings and integers.BclNumber bcl_parse(const char *restrict val); char* bcl_string(BclNumber n); BclError bcl_bigdig(BclNumber n, BclBigDig *result); BclNumber bcl_bigdig2num(BclBigDig val); MathThese items allow clients to run math on numbers.BclNumber bcl_add(BclNumber a, BclNumber b); BclNumber bcl_sub(BclNumber a, BclNumber b); BclNumber bcl_mul(BclNumber a, BclNumber b); BclNumber bcl_div(BclNumber a, BclNumber b); BclNumber bcl_mod(BclNumber a, BclNumber b); BclNumber bcl_pow(BclNumber a, BclNumber b); BclNumber bcl_lshift(BclNumber a, BclNumber b); BclNumber bcl_rshift(BclNumber a, BclNumber b); BclNumber bcl_sqrt(BclNumber a); BclError bcl_divmod(BclNumber a, BclNumber b, BclNumber *c, BclNumber *d); BclNumber bcl_modexp(BclNumber a, BclNumber b, BclNumber c); MiscellaneousThese items are miscellaneous.void bcl_zero(BclNumber n); void bcl_one(BclNumber n); ssize_t bcl_cmp(BclNumber a, BclNumber b); BclError bcl_copy(BclNumber d, BclNumber s); BclNumber bcl_dup(BclNumber s); Pseudo-Random Number GeneratorThese items allow clients to manipulate the seeded pseudo-random number generator in bcl(3).#define BCL_SEED_ULONGS #define BCL_SEED_SIZE typedef unsigned long BclBigDig; typedef unsigned long BclRandInt; BclNumber bcl_irand(BclNumber a); BclNumber bcl_frand(size_t places); BclNumber bcl_ifrand(BclNumber a, size_t places); BclError bcl_rand_seedWithNum(BclNumber n); BclError bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE]); void bcl_rand_reseed(void); BclNumber bcl_rand_seed2num(void); BclRandInt bcl_rand_int(void); BclRandInt bcl_rand_bounded(BclRandInt bound); DESCRIPTIONbcl(3) is a library that implements arbitrary-precision decimal math, as standardized by POSIX (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) in bc(1).bcl(3) is async-signal-safe if bcl_handleSignal(void) is used properly. (See the SIGNAL HANDLING section.) bcl(3) assumes that it is allowed to use the bcl, Bcl, bc, and Bc prefixes for symbol names without collision. All of the items in its interface are described below. See the documentation for each function for what each function can return. Signals
If execution is interrupted, bcl_handleSignal(void) does not return to its caller. See the SIGNAL HANDLING section.
See the SIGNAL HANDLING section. Setup
If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
This function must be the first one clients call. Calling any other function without calling this one first is undefined behavior.
This function must be the last one clients call. Calling this function before calling any other function is undefined behavior.
If activated, clients do not need to check for fatal errors. The default is false.
If activated, clients do not need to check for fatal errors.
The default is false.
ContextsAll procedures that take a BclContext parameter a require a valid context as an argument.
A BclContext contains the values scale, ibase, and obase, as well as a list of numbers. scale is a value used to control how many decimal places calculations should use. A value of 0 means that calculations are done on integers only, where applicable, and a value of 20, for example, means that all applicable calculations return results with 20 decimal places. The default is 0. ibase is a value used to control the input base. The minimum ibase is 2, and the maximum is 36. If ibase is 2, numbers are parsed as though they are in binary, and any digits larger than 1 are clamped. Likewise, a value of 10 means that numbers are parsed as though they are decimal, and any larger digits are clamped. The default is 10. obase is a value used to control the output base. The minimum obase is 0 and the maximum is BC_BASE_MAX (see the LIMITS section). Numbers created in one context are not valid in another context. It is undefined behavior to use a number created in a different context. Contexts are meant to isolate the numbers used by different clients in the same application.
If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
There must be a valid context to do any arithmetic.
Errors
There must be a valid current context. NumbersAll procedures in this section require a valid current context.
bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
The scale of a number is the number of decimal places it has after the radix (decimal point).
If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
ConversionAll procedures in this section require a valid current context.All procedures in this section consume the given BclNumber arguments that are not given to pointer arguments. See the Consumption and Propagation subsection below.
val must be non-NULL and a valid string. See BCL_ERROR_PARSE_INVALID_STR in the ERRORS section for more information. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
n is consumed; it cannot be used after the call. See the Consumption and Propagation subsection below.
a must be smaller than BC_OVERFLOW_MAX. See the LIMITS section. If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
n is consumed; it cannot be used after the call. See the Consumption and Propagation subsection below.
bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
MathAll procedures in this section require a valid current context.All procedures in this section can return the following errors:
a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b cannot be 0. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b cannot be 0. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b must be an integer. If b is negative, a must not be 0. a must be smaller than BC_OVERFLOW_MAX. See the LIMITS section. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b must be an integer. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b must be an integer. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. a and b can be the same number. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
a cannot be negative. a is consumed; it cannot be used after the call. See the Consumption and Propagation subsection below. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
b cannot be 0. a and b are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. c and d cannot point to the same place, nor can they point to the space occupied by a or b. If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
a, b, and c must be integers. c must not be 0. b must not be negative. a, b, and c are consumed; they cannot be used after the call. See the Consumption and Propagation subsection below. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
Miscellaneous
If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
Pseudo-Random Number GeneratorThe pseudo-random number generator in bcl(3) is a seeded PRNG. Given the same seed twice, it will produce the same sequence of pseudo-random numbers twice.By default, bcl(3) attempts to seed the PRNG with data from /dev/urandom. If that fails, it seeds itself with by calling libc’s srand(time(NULL)) and then calling rand() for each byte, since rand() is only guaranteed to return 15 bits. This should provide fairly good seeding in the standard case while also remaining fairly portable. If necessary, the PRNG can be reseeded with one of the following functions:
The following items allow clients to use the pseudo-random number generator. All procedures require a valid current context.
a must be an integer and non-negative. a is consumed; it cannot be used after the call. See the Consumption and Propagation subsection below. This procedure requires a valid current context. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
This procedure requires a valid current context. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
a must be an integer and non-negative. a is consumed; it cannot be used after the call. See the Consumption and Propagation subsection below. This procedure requires a valid current context. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
n is not consumed. This procedure requires a valid current context. If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
Note that if bcl_rand_seed2num(void) or bcl_rand_seed2num_err(BclNumber) are called right after this function, they are not guaranteed to return a number equal to n.
If there was no error, BCL_ERROR_NONE is returned. Otherwise, this function can return:
This procedure cannot fail.
This procedure requires a valid current context. bcl(3) will encode an error in the return value, if there was one. The error can be queried with bcl_err(BclNumber). Possible errors include:
This procedure cannot fail.
This procedure cannot fail. Consumption and PropagationSome functions are listed as consuming some or all of their arguments. This means that the arguments are freed, regardless of if there were errors or not.This is to enable compact code like the following:
If arguments to those functions were not consumed, memory would be leaked until reclaimed with bcl_ctxt_freeNums(BclContext). When errors occur, they are propagated through. The result should always be checked with bcl_err(BclNumber), so the example above should properly be:
ERRORSMost functions in bcl(3) return, directly or indirectly, any one of the error codes defined in BclError. The complete list of codes is the following:
A valid number string can only be one radix (period). In addition, any lowercase ASCII letters, symbols, or non-ASCII characters are invalid. It is allowed for the first character to be a dash. In that case, the number is considered to be negative. There is one exception to the above: one lowercase e is allowed in the number, after the radix, if it exists. If the letter e exists, the number is considered to be in scientific notation, where the part before the e is the number, and the part after, which must be an integer, is the exponent. There can be a dash right after the e to indicate a negative exponent. WARNING: Both the number and the exponent in scientific notation are interpreted according to the current ibase, but the number is still multiplied by 10^exponent regardless of the current ibase. For example, if ibase is 16 and bcl(3) is given the number string FFeA, the resulting decimal number will be 2550000000000, and if bcl(3) is given the number string 10e-4, the resulting decimal number will be 0.0016.
If clients call bcl_setAbortOnFatalError() with an true argument, this error will cause bcl(3) to throw a SIGABRT. This behavior can also be turned off later by calling that same function with a false argument. By default, this behavior is off. It is highly recommended that client libraries do not activate this behavior.
If clients call bcl_setAbortOnFatalError() with an true argument, this error will cause bcl(3) to throw a SIGABRT. This behavior can also be turned off later by calling that same function with a false argument. By default, this behavior is off. It is highly recommended that client libraries do not activate this behavior. ATTRIBUTESWhen bcl_handleSignal(void) is used properly, bcl(3) is async-signal-safe.bcl(3) is MT-Unsafe: it is unsafe to call any functions from more than one thread. PERFORMANCEMost bc(1) implementations use char types to calculate the value of 1 decimal digit at a time, but that can be slow. bcl(3) does something different.It uses large integers to calculate more than 1 decimal digit at a time. If built in a environment where BC_LONG_BIT (see the LIMITS section) is 64, then each integer has 9 decimal digits. If built in an environment where BC_LONG_BIT is 32 then each integer has 4 decimal digits. This value (the number of decimal digits per large integer) is called BC_BASE_DIGS. In addition, this bcl(3) uses an even larger integer for overflow checking. This integer type depends on the value of BC_LONG_BIT, but is always at least twice as large as the integer type used to store digits. LIMITSThe following are the limits on bcl(3):
These limits are meant to be effectively non-existent; the limits are so large (at least on 64-bit machines) that there should not be any point at which they become a problem. In fact, memory should be exhausted before these limits should be hit. SIGNAL HANDLINGIf a signal handler calls bcl_handleSignal(void) from the same thread that there are bcl(3) functions executing in, it will cause all execution to stop as soon as possible, interrupting long-running calculations, if necessary and cause the function that was executing to return. If possible, the error code BC_ERROR_SIGNAL is returned.If execution is interrupted, bcl_handleSignal(void) does not return to its caller. It is undefined behavior if bcl_handleSignal(void) is called from a thread that is not executing bcl(3) functions, if bcl(3) functions are executing. SEE ALSObc(1) and dc(1)STANDARDSbcl(3) is compliant with the arithmetic defined in the IEEE Std 1003.1-2017 (“POSIX.1-2017”) (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) specification for bc(1).Note that the specification explicitly says that bc(1) only accepts numbers that use a period (.) as a radix point, regardless of the value of LC_NUMERIC. This is also true of bcl(3). BUGSNone are known. Report bugs at https://git.yzena.com/gavin/bc.AUTHORSGavin D. Howard <gavin@yzena.com> and contributors.
Visit the GSP FreeBSD Man Page Interface. |