diff options
Diffstat (limited to 'manuals/bcl.3')
-rw-r--r-- | manuals/bcl.3 | 666 |
1 files changed, 582 insertions, 84 deletions
diff --git a/manuals/bcl.3 b/manuals/bcl.3 index c079a20c..cb65a2b8 100644 --- a/manuals/bcl.3 +++ b/manuals/bcl.3 @@ -1,7 +1,7 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.\" Copyright (c) 2018-2021 Gavin D. Howard and contributors. +.\" Copyright (c) 2018-2023 Gavin D. Howard and contributors. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions are met: @@ -25,7 +25,9 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.TH "BCL" "3" "June 2021" "Gavin D. Howard" "Libraries Manual" +.TH "BCL" "3" "February 2023" "Gavin D. Howard" "Libraries Manual" +.nh +.ad l .SH NAME .PP bcl - library of arbitrary precision decimal arithmetic @@ -34,19 +36,16 @@ bcl - library of arbitrary precision decimal arithmetic .PP \f[I]#include <bcl.h>\f[R] .PP -Link with \f[I]-lbcl\f[R]. -.SS Signals -.PP -This procedure will allow clients to use signals to interrupt -computations running in bcl(3). -.PP -\f[B]void bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B]);\f[R] -.PP -\f[B]bool bcl_running(\f[R]\f[I]void\f[R]\f[B]);\f[R] +Link with \f[I]-lbcl\f[R], and on POSIX systems, \f[I]-lpthread\f[R] is +also required. .SS Setup .PP These items allow clients to set up bcl(3). .PP +\f[B]BclError bcl_start(\f[R]\f[I]void\f[R]\f[B]);\f[R] +.PP +\f[B]void bcl_end(\f[R]\f[I]void\f[R]\f[B]);\f[R] +.PP \f[B]BclError bcl_init(\f[R]\f[I]void\f[R]\f[B]);\f[R] .PP \f[B]void bcl_free(\f[R]\f[I]void\f[R]\f[B]);\f[R] @@ -55,7 +54,16 @@ These items allow clients to set up bcl(3). .PP \f[B]void bcl_setAbortOnFatalError(bool\f[R] \f[I]abrt\f[R]\f[B]);\f[R] .PP +\f[B]bool bcl_leadingZeroes(\f[R]\f[I]void\f[R]\f[B]);\f[R] +.PP +\f[B]void bcl_setLeadingZeroes(bool\f[R] +\f[I]leadingZeroes\f[R]\f[B]);\f[R] +.PP \f[B]void bcl_gc(\f[R]\f[I]void\f[R]\f[B]);\f[R] +.PP +\f[B]bool bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B]);\f[R] +.PP +\f[B]void bcl_setDigitClamp(bool\f[R] \f[I]digitClamp\f[R]\f[B]);\f[R] .SS Contexts .PP These items will allow clients to handle contexts, which are isolated @@ -131,9 +139,14 @@ integers. .PP \f[B]char* bcl_string(BclNumber\f[R] \f[I]n\f[R]\f[B]);\f[R] .PP +\f[B]char* bcl_string_keep(BclNumber\f[R] \f[I]n\f[R]\f[B]);\f[R] +.PP \f[B]BclError bcl_bigdig(BclNumber\f[R] \f[I]n\f[R]\f[B], BclBigDig *\f[R]\f[I]result\f[R]\f[B]);\f[R] .PP +\f[B]BclError bcl_bigdig_keep(BclNumber\f[R] \f[I]n\f[R]\f[B], BclBigDig +*\f[R]\f[I]result\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_bigdig2num(BclBigDig\f[R] \f[I]val\f[R]\f[B]);\f[R] .SS Math .PP @@ -142,35 +155,68 @@ These items allow clients to run math on numbers. \f[B]BclNumber bcl_add(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_add_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_sub(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_sub_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_mul(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_mul_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_div(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_div_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_mod(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_mod_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_pow(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_pow_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_lshift(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_lshift_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_rshift(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_rshift_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_sqrt(BclNumber\f[R] \f[I]a\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_sqrt_keep(BclNumber\f[R] \f[I]a\f[R]\f[B]);\f[R] +.PP \f[B]BclError bcl_divmod(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber *\f[R]\f[I]c\f[R]\f[B], BclNumber *\f[R]\f[I]d\f[R]\f[B]);\f[R] .PP +\f[B]BclError bcl_divmod_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber *\f[R]\f[I]c\f[R]\f[B], +BclNumber *\f[R]\f[I]d\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_modexp(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber\f[R] \f[I]c\f[R]\f[B]);\f[R] +.PP +\f[B]BclNumber bcl_modexp_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber\f[R] \f[I]c\f[R]\f[B]);\f[R] .SS Miscellaneous .PP These items are miscellaneous. @@ -201,14 +247,22 @@ generator in bcl(3). .PP \f[B]BclNumber bcl_irand(BclNumber\f[R] \f[I]a\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_irand_keep(BclNumber\f[R] \f[I]a\f[R]\f[B]);\f[R] +.PP \f[B]BclNumber bcl_frand(size_t\f[R] \f[I]places\f[R]\f[B]);\f[R] .PP \f[B]BclNumber bcl_ifrand(BclNumber\f[R] \f[I]a\f[R]\f[B], size_t\f[R] \f[I]places\f[R]\f[B]);\f[R] .PP +\f[B]BclNumber bcl_ifrand_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], +size_t\f[R] \f[I]places\f[R]\f[B]);\f[R] +.PP \f[B]BclError bcl_rand_seedWithNum(BclNumber\f[R] \f[I]n\f[R]\f[B]);\f[R] .PP +\f[B]BclError bcl_rand_seedWithNum_keep(BclNumber\f[R] +\f[I]n\f[R]\f[B]);\f[R] +.PP \f[B]BclError bcl_rand_seed(unsigned char\f[R] \f[I]seed\f[R]\f[B][\f[R]\f[I]BCL_SEED_SIZE\f[R]\f[B]]);\f[R] .PP @@ -223,67 +277,77 @@ generator in bcl(3). .SH DESCRIPTION .PP bcl(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). -.PP -bcl(3) is async-signal-safe if -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is used properly. -(See the \f[B]SIGNAL HANDLING\f[R] section.) +standardized by POSIX +(https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) in +bc(1). .PP -bcl(3) assumes that it is allowed to use the \f[B]bcl_\f[R] and -\f[B]bc_\f[R] prefixes for symbol names without collision. +bcl(3) assumes that it is allowed to use the \f[B]bcl\f[R], +\f[B]Bcl\f[R], \f[B]bc\f[R], and \f[B]Bc\f[R] prefixes for symbol names +without collision. .PP All of the items in its interface are described below. See the documentation for each function for what each function can return. -.SS Signals -.TP -\f[B]void bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] -An async-signal-safe function that can be called from a signal handler. -If called from a signal handler on the same thread as any executing -bcl(3) functions, it will interrupt the functions and force them to -return early. -It is undefined behavior if this function is called from a thread that -is \f[I]not\f[R] executing any bcl(3) functions while any bcl(3) -functions are executing. +.SS Setup +.TP +\f[B]BclError bcl_start(\f[R]\f[I]void\f[R]\f[B])\f[R] +Initializes this library. +This function can be called multiple times, but \f[B]bcl_end()\f[R] must +only be called \f[I]once\f[R]. +This is to make it possible for multiple libraries and applications to +initialize bcl(3) without problem. .RS .PP -If execution \f[I]is\f[R] interrupted, -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] does \f[I]not\f[R] -return to its caller. +It is suggested that client libraries call this function, but do not +call \f[B]bcl_end()\f[R], and client applications should call both. .PP -See the \f[B]SIGNAL HANDLING\f[R] section. +If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned. +Otherwise, this function can return: +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.PP +This function must be the first one clients call. +Calling any other function without calling this one first is undefined +behavior. .RE .TP -\f[B]bool bcl_running(\f[R]\f[I]void\f[R]\f[B])\f[R] -An async-signal-safe function that can be called from a signal handler. -It will return \f[B]true\f[R] if any bcl(3) procedures are running, -which means it is safe to call -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R]. -Otherwise, it returns \f[B]false\f[R]. +\f[B]void bcl_end(\f[R]\f[I]void\f[R]\f[B])\f[R] +Deinitializes this library. +This function must only be called \f[I]once\f[R]. .RS .PP -See the \f[B]SIGNAL HANDLING\f[R] section. +All data must have been freed before calling this function. +.PP +This function must be the last one clients call. +Calling this function before calling any other function is undefined +behavior. .RE -.SS Setup .TP \f[B]BclError bcl_init(\f[R]\f[I]void\f[R]\f[B])\f[R] -Initializes this library. +Initializes the library for the current thread. This function can be called multiple times, but each call must be matched by a call to \f[B]bcl_free(\f[R]\f[I]void\f[R]\f[B])\f[R]. This is to make it possible for multiple libraries and applications to -initialize bcl(3) without problem. +initialize threads for bcl(3) without problem. .RS .PP +This function \f[I]must\f[R] be called from the thread that it is +supposed to initialize. +.PP If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned. Otherwise, this function can return: .IP \[bu] 2 \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .PP -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 second one clients call. +Calling any other function without calling \f[B]bcl_start()\f[R] and +then this one first is undefined behavior, except in the case of new +threads. +New threads can safely call this function without calling +\f[B]bcl_start()\f[R] if another thread has previously called +\f[B]bcl_start()\f[R]. +But this function must still be the first function in bcl(3) called by +that new thread. .RE .TP \f[B]void bcl_free(\f[R]\f[I]void\f[R]\f[B])\f[R] @@ -291,9 +355,12 @@ Decrements bcl(3)\[cq]s reference count and frees the data associated with it if the reference count is \f[B]0\f[R]. .RS .PP -This function must be the last one clients call. -Calling this function before calling any other function is undefined -behavior. +This function \f[I]must\f[R] be called from the thread that it is +supposed to deinitialize. +.PP +This function must be the second to last one clients call. +Calling this function before calling any other function besides +\f[B]bcl_end()\f[R] is undefined behavior. .RE .TP \f[B]bool bcl_abortOnFatalError(\f[R]\f[I]void\f[R]\f[B])\f[R] @@ -304,6 +371,11 @@ a fatal error occurs. .RS .PP If activated, clients do not need to check for fatal errors. +.PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is read on. +.PP +The default is \f[B]false\f[R]. .RE .TP \f[B]void bcl_setAbortOnFatalError(bool\f[R] \f[I]abrt\f[R]\f[B])\f[R] @@ -314,9 +386,74 @@ If \f[I]abrt\f[R] is \f[B]true\f[R], bcl(3) will cause a \f[B]SIGABRT\f[R] on fatal errors after the call. .RS .PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is set on. +.PP If activated, clients do not need to check for fatal errors. .RE .TP +\f[B]bool bcl_leadingZeroes(\f[R]\f[I]void\f[R]\f[B])\f[R] +Queries and returns the state of whether leading zeroes are added to +strings returned by \f[B]bcl_string()\f[R] when numbers are greater than +\f[B]-1\f[R], less than \f[B]1\f[R], and not equal to \f[B]0\f[R]. +If \f[B]true\f[R] is returned, then leading zeroes will be added. +.RS +.PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is read on. +.PP +The default is \f[B]false\f[R]. +.RE +.TP +\f[B]void bcl_setLeadingZeroes(bool\f[R] \f[I]leadingZeroes\f[R]\f[B])\f[R] +Sets the state of whether leading zeroes are added to strings returned +by \f[B]bcl_string()\f[R] when numbers are greater than \f[B]-1\f[R], +less than \f[B]1\f[R], and not equal to \f[B]0\f[R]. +If \f[I]leadingZeroes\f[R] is \f[B]true\f[R], leading zeroes will be +added to strings returned by \f[B]bcl_string()\f[R]. +.RS +.PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is set on. +.RE +.TP +\f[B]bool bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B])\f[R] +Queries and returns the state of whether digits in number strings that +are greater than or equal to the current \f[B]ibase\f[R] are clamped or +not. +.RS +.PP +If \f[B]true\f[R] is returned, then digits are treated as though they +are equal to the value of \f[B]ibase\f[R] minus \f[B]1\f[R]. +If this is \f[I]not\f[R] true, then digits are treated as though they +are equal to the value they would have if \f[B]ibase\f[R] was large +enough. +They are then multiplied by the appropriate power of \f[B]ibase\f[R]. +.PP +For example, with clamping off and an \f[B]ibase\f[R] of \f[B]3\f[R], +the string \[lq]AB\[rq] would equal \f[B]3\[ha]1*A+3\[ha]0*B\f[R], which +is \f[B]3\f[R] times \f[B]10\f[R] plus \f[B]11\f[R], or \f[B]41\f[R], +while with clamping on and an \f[B]ibase\f[R] of \f[B]3\f[R], the string +\[lq]AB\[rq] would be equal to \f[B]3\[ha]1*2+3\[ha]0*2\f[R], which is +\f[B]3\f[R] times \f[B]2\f[R] plus \f[B]2\f[R], or \f[B]8\f[R]. +.PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is read on. +.PP +The default is \f[B]true\f[R]. +.RE +.TP +\f[B]void bcl_setDigitClamp(bool\f[R] \f[I]digitClamp\f[R]\f[B])\f[R] +Sets the state of whether digits in number strings that are greater than +or equal to the current \f[B]ibase\f[R] are clamped or not. +For more information, see the +\f[B]bcl_digitClamp(\f[R]\f[I]void\f[R]\f[B])\f[R] function. +.RS +.PP +This value is \f[I]thread-local\f[R]; it applies to just the thread it +is set on. +.RE +.TP \f[B]void bcl_gc(\f[R]\f[I]void\f[R]\f[B])\f[R] Garbage collects cached instances of arbitrary-precision numbers. This only frees the memory of numbers that are \f[I]not\f[R] in use, so @@ -365,6 +502,15 @@ 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. +.PP +Different threads also have different contexts, so any numbers created +in one thread are not valid in another thread. +To pass values between contexts and threads, use \f[B]bcl_string()\f[R] +to produce a string to pass around, and use \f[B]bcl_parse()\f[R] to +parse the string. +It is suggested that the \f[B]obase\f[R] used to create the string be +passed around with the string and used as the \f[B]ibase\f[R] for +\f[B]bcl_parse()\f[R] to ensure that the number will be the same. .RE .TP \f[B]BclContext bcl_ctxt_create(\f[R]\f[I]void\f[R]\f[B])\f[R] @@ -508,8 +654,9 @@ Returns the number of \f[I]significant decimal digits\f[R] in .PP All procedures in this section require a valid current context. .PP -All procedures in this section consume the given \f[B]BclNumber\f[R] -arguments that are not given to pointer arguments. +All procedures in this section without the \f[B]_keep\f[R] suffix in +their name consume the given \f[B]BclNumber\f[R] arguments that are not +given to pointer arguments. See the \f[B]Consumption and Propagation\f[R] subsection below. .TP \f[B]BclNumber bcl_parse(const char *restrict\f[R] \f[I]val\f[R]\f[B])\f[R] @@ -544,6 +691,11 @@ The string is dynamically allocated and must be freed by the caller. See the \f[B]Consumption and Propagation\f[R] subsection below. .RE .TP +\f[B]char* bcl_string_keep(BclNumber\f[R] \f[I]n\f[R]\f[B])\f[R] +Returns a string representation of \f[I]n\f[R] according the the current +context\[cq]s \f[B]ibase\f[R]. +The string is dynamically allocated and must be freed by the caller. +.TP \f[B]BclError bcl_bigdig(BclNumber\f[R] \f[I]n\f[R]\f[B], BclBigDig *\f[R]\f[I]result\f[R]\f[B])\f[R] Converts \f[I]n\f[R] into a \f[B]BclBigDig\f[R] and returns the result in the space pointed to by \f[I]result\f[R]. @@ -565,6 +717,24 @@ Otherwise, this function can return: See the \f[B]Consumption and Propagation\f[R] subsection below. .RE .TP +\f[B]BclError bcl_bigdig_keep(BclNumber\f[R] \f[I]n\f[R]\f[B], BclBigDig *\f[R]\f[I]result\f[R]\f[B])\f[R] +Converts \f[I]n\f[R] into a \f[B]BclBigDig\f[R] and returns the result +in the space pointed to by \f[I]result\f[R]. +.RS +.PP +\f[I]a\f[R] must be smaller than \f[B]BC_OVERFLOW_MAX\f[R]. +See the \f[B]LIMITS\f[R] section. +.PP +If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned. +Otherwise, this function can return: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_OVERFLOW\f[R] +.RE +.TP \f[B]BclNumber bcl_bigdig2num(BclBigDig\f[R] \f[I]val\f[R]\f[B])\f[R] Creates a \f[B]BclNumber\f[R] from \f[I]val\f[R]. .RS @@ -581,6 +751,11 @@ Possible errors include: .PP All procedures in this section require a valid current context. .PP +All procedures in this section without the \f[B]_keep\f[R] suffix in +their name consume the given \f[B]BclNumber\f[R] arguments that are not +given to pointer arguments. +See the \f[B]Consumption and Propagation\f[R] subsection below. +.PP All procedures in this section can return the following errors: .IP \[bu] 2 \f[B]BCL_ERROR_INVALID_NUM\f[R] @@ -612,6 +787,25 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_add_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Adds \f[I]a\f[R] and \f[I]b\f[R] and returns the result. +The \f[I]scale\f[R] of the result is the max of the \f[I]scale\f[R]s of +\f[I]a\f[R] and \f[I]b\f[R]. +.RS +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_sub(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Subtracts \f[I]b\f[R] from \f[I]a\f[R] and returns the result. The \f[I]scale\f[R] of the result is the max of the \f[I]scale\f[R]s of @@ -635,6 +829,25 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_sub_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Subtracts \f[I]b\f[R] from \f[I]a\f[R] and returns the result. +The \f[I]scale\f[R] of the result is the max of the \f[I]scale\f[R]s of +\f[I]a\f[R] and \f[I]b\f[R]. +.RS +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_mul(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Multiplies \f[I]a\f[R] and \f[I]b\f[R] and returns the result. If \f[I]ascale\f[R] is the \f[I]scale\f[R] of \f[I]a\f[R] and @@ -661,6 +874,28 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_mul_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Multiplies \f[I]a\f[R] and \f[I]b\f[R] and returns the result. +If \f[I]ascale\f[R] is the \f[I]scale\f[R] of \f[I]a\f[R] and +\f[I]bscale\f[R] is the \f[I]scale\f[R] of \f[I]b\f[R], the +\f[I]scale\f[R] of the result is equal to +\f[B]min(ascale+bscale,max(scale,ascale,bscale))\f[R], where +\f[B]min()\f[R] and \f[B]max()\f[R] return the obvious values. +.RS +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_div(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Divides \f[I]a\f[R] by \f[I]b\f[R] and returns the result. The \f[I]scale\f[R] of the result is the \f[I]scale\f[R] of the current @@ -688,6 +923,29 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_div_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Divides \f[I]a\f[R] by \f[I]b\f[R] and returns the result. +The \f[I]scale\f[R] of the result is the \f[I]scale\f[R] of the current +context. +.RS +.PP +\f[I]b\f[R] cannot be \f[B]0\f[R]. +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_DIVIDE_BY_ZERO\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_mod(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Divides \f[I]a\f[R] by \f[I]b\f[R] to the \f[I]scale\f[R] of the current context, computes the modulus \f[B]a-(a/b)*b\f[R], and returns the @@ -715,6 +973,29 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_mod_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Divides \f[I]a\f[R] by \f[I]b\f[R] to the \f[I]scale\f[R] of the current +context, computes the modulus \f[B]a-(a/b)*b\f[R], and returns the +modulus. +.RS +.PP +\f[I]b\f[R] cannot be \f[B]0\f[R]. +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_DIVIDE_BY_ZERO\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_pow(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Calculates \f[I]a\f[R] to the power of \f[I]b\f[R] to the \f[I]scale\f[R] of the current context. @@ -751,6 +1032,38 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_pow_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Calculates \f[I]a\f[R] to the power of \f[I]b\f[R] to the +\f[I]scale\f[R] of the current context. +\f[I]b\f[R] must be an integer, but can be negative. +If it is negative, \f[I]a\f[R] must be non-zero. +.RS +.PP +\f[I]b\f[R] must be an integer. +If \f[I]b\f[R] is negative, \f[I]a\f[R] must not be \f[B]0\f[R]. +.PP +\f[I]a\f[R] must be smaller than \f[B]BC_OVERFLOW_MAX\f[R]. +See the \f[B]LIMITS\f[R] section. +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_OVERFLOW\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_DIVIDE_BY_ZERO\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_lshift(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Shifts \f[I]a\f[R] left (moves the radix right) by \f[I]b\f[R] places and returns the result. @@ -779,6 +1092,30 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_lshift_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Shifts \f[I]a\f[R] left (moves the radix right) by \f[I]b\f[R] places +and returns the result. +This is done in decimal. +\f[I]b\f[R] must be an integer. +.RS +.PP +\f[I]b\f[R] must be an integer. +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_rshift(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] Shifts \f[I]a\f[R] right (moves the radix left) by \f[I]b\f[R] places and returns the result. @@ -807,6 +1144,30 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_rshift_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B])\f[R] +Shifts \f[I]a\f[R] right (moves the radix left) by \f[I]b\f[R] places +and returns the result. +This is done in decimal. +\f[I]b\f[R] must be an integer. +.RS +.PP +\f[I]b\f[R] must be an integer. +.PP +\f[I]a\f[R] and \f[I]b\f[R] can be the same number. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_sqrt(BclNumber\f[R] \f[I]a\f[R]\f[B])\f[R] Calculates the square root of \f[I]a\f[R] and returns the result. The \f[I]scale\f[R] of the result is equal to the \f[B]scale\f[R] of the @@ -831,6 +1192,27 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_sqrt_keep(BclNumber\f[R] \f[I]a\f[R]\f[B])\f[R] +Calculates the square root of \f[I]a\f[R] and returns the result. +The \f[I]scale\f[R] of the result is equal to the \f[B]scale\f[R] of the +current context. +.RS +.PP +\f[I]a\f[R] cannot be negative. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NEGATIVE\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclError bcl_divmod(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber *\f[R]\f[I]c\f[R]\f[B], BclNumber *\f[R]\f[I]d\f[R]\f[B])\f[R] Divides \f[I]a\f[R] by \f[I]b\f[R] and returns the quotient in a new number which is put into the space pointed to by \f[I]c\f[R], and puts @@ -859,6 +1241,30 @@ Otherwise, this function can return: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclError bcl_divmod_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber *\f[R]\f[I]c\f[R]\f[B], BclNumber *\f[R]\f[I]d\f[R]\f[B])\f[R] +Divides \f[I]a\f[R] by \f[I]b\f[R] and returns the quotient in a new +number which is put into the space pointed to by \f[I]c\f[R], and puts +the modulus in a new number which is put into the space pointed to by +\f[I]d\f[R]. +.RS +.PP +\f[I]b\f[R] cannot be \f[B]0\f[R]. +.PP +\f[I]c\f[R] and \f[I]d\f[R] cannot point to the same place, nor can they +point to the space occupied by \f[I]a\f[R] or \f[I]b\f[R]. +.PP +If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned. +Otherwise, this function can return: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_DIVIDE_BY_ZERO\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_modexp(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber\f[R] \f[I]c\f[R]\f[B])\f[R] Computes a modular exponentiation where \f[I]a\f[R] is the base, \f[I]b\f[R] is the exponent, and \f[I]c\f[R] is the modulus, and returns @@ -891,6 +1297,35 @@ Possible errors include: .IP \[bu] 2 \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE +.TP +\f[B]BclNumber bcl_modexp_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], BclNumber\f[R] \f[I]b\f[R]\f[B], BclNumber\f[R] \f[I]c\f[R]\f[B])\f[R] +Computes a modular exponentiation where \f[I]a\f[R] is the base, +\f[I]b\f[R] is the exponent, and \f[I]c\f[R] is the modulus, and returns +the result. +The \f[I]scale\f[R] of the result is equal to the \f[B]scale\f[R] of the +current context. +.RS +.PP +\f[I]a\f[R], \f[I]b\f[R], and \f[I]c\f[R] must be integers. +\f[I]c\f[R] must not be \f[B]0\f[R]. +\f[I]b\f[R] must not be negative. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NEGATIVE\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_DIVIDE_BY_ZERO\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE .SS Miscellaneous .TP \f[B]void bcl_zero(BclNumber\f[R] \f[I]n\f[R]\f[B])\f[R] @@ -960,6 +1395,11 @@ char[\f[R]\f[I]BCL_SEED_SIZE\f[R]\f[B]])\f[R] .IP \[bu] 2 \f[B]bcl_rand_reseed(\f[R]\f[I]void\f[R]\f[B])\f[R] .PP +All procedures in this section without the \f[B]_keep\f[R] suffix in +their name consume the given \f[B]BclNumber\f[R] arguments that are not +given to pointer arguments. +See the \f[B]Consumption and Propagation\f[R] subsection below. +.PP The following items allow clients to use the pseudo-random number generator. All procedures require a valid current context. @@ -1012,6 +1452,36 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_irand_keep(BclNumber\f[R] \f[I]a\f[R]\f[B])\f[R] +Returns a random number that is not larger than \f[I]a\f[R] in a new +number. +If \f[I]a\f[R] is \f[B]0\f[R] or \f[B]1\f[R], the new number is equal to +\f[B]0\f[R]. +The bound is unlimited, so it is not bound to the size of +\f[B]BclRandInt\f[R]. +This is done by generating as many random numbers as necessary, +multiplying them by certain exponents, and adding them all together. +.RS +.PP +\f[I]a\f[R] must be an integer and non-negative. +.PP +This procedure requires a valid current context. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NEGATIVE\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclNumber bcl_frand(size_t\f[R] \f[I]places\f[R]\f[B])\f[R] Returns a random number between \f[B]0\f[R] (inclusive) and \f[B]1\f[R] (exclusive) that has \f[I]places\f[R] decimal digits after the radix @@ -1058,11 +1528,55 @@ Possible errors include: \f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] .RE .TP +\f[B]BclNumber bcl_ifrand_keep(BclNumber\f[R] \f[I]a\f[R]\f[B], size_t\f[R] \f[I]places\f[R]\f[B])\f[R] +Returns a random number less than \f[I]a\f[R] with \f[I]places\f[R] +decimal digits after the radix (decimal point). +There are no limits on \f[I]a\f[R] or \f[I]places\f[R]. +.RS +.PP +\f[I]a\f[R] must be an integer and non-negative. +.PP +This procedure requires a valid current context. +.PP +bcl(3) will encode an error in the return value, if there was one. +The error can be queried with \f[B]bcl_err(BclNumber)\f[R]. +Possible errors include: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NEGATIVE\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_MATH_NON_INTEGER\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_FATAL_ALLOC_ERR\f[R] +.RE +.TP \f[B]BclError bcl_rand_seedWithNum(BclNumber\f[R] \f[I]n\f[R]\f[B])\f[R] Seeds the PRNG with \f[I]n\f[R]. .RS .PP -\f[I]n\f[R] is \f[I]not\f[R] consumed. +\f[I]n\f[R] is consumed. +.PP +This procedure requires a valid current context. +.PP +If there was no error, \f[B]BCL_ERROR_NONE\f[R] is returned. +Otherwise, this function can return: +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_NUM\f[R] +.IP \[bu] 2 +\f[B]BCL_ERROR_INVALID_CONTEXT\f[R] +.PP +Note that if \f[B]bcl_rand_seed2num(\f[R]\f[I]void\f[R]\f[B])\f[R] or +\f[B]bcl_rand_seed2num_err(BclNumber)\f[R] are called right after this +function, they are not guaranteed to return a number equal to +\f[I]n\f[R]. +.RE +.TP +\f[B]BclError bcl_rand_seedWithNum_keep(BclNumber\f[R] \f[I]n\f[R]\f[B])\f[R] +Seeds the PRNG with \f[I]n\f[R]. +.RS .PP This procedure requires a valid current context. .PP @@ -1153,7 +1667,7 @@ so the example above should properly be: .nf \f[C] BclNumber n = bcl_num_add(bcl_num_mul(a, b), bcl_num_div(c, d)); -if (bc_num_err(n) != BCL_ERROR_NONE) { +if (bcl_err(n) != BCL_ERROR_NONE) { // Handle the error. } \f[R] @@ -1173,9 +1687,6 @@ An invalid \f[B]BclNumber\f[R] was given as a parameter. \f[B]BCL_ERROR_INVALID_CONTEXT\f[R] An invalid \f[B]BclContext\f[R] is being used. .TP -\f[B]BCL_ERROR_SIGNAL\f[R] -A signal interrupted execution. -.TP \f[B]BCL_ERROR_MATH_NEGATIVE\f[R] A negative number was given as an argument to a parameter that cannot accept negative numbers, such as for square roots. @@ -1251,11 +1762,16 @@ this behavior. .RE .SH ATTRIBUTES .PP -When \f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is used -properly, bcl(3) is async-signal-safe. +bcl(3) is \f[I]MT-Safe\f[R]: it is safe to call any functions from more +than one thread. +However, is is \f[I]not\f[R] safe to pass any data between threads +except for strings returned by \f[B]bcl_string()\f[R]. .PP -bcl(3) is \f[I]MT-Unsafe\f[R]: it is unsafe to call any functions from -more than one thread. +bcl(3) is not \f[I]async-signal-safe\f[R]. +It was not possible to make bcl(3) safe with signals and also make it +safe with multiple threads. +If it is necessary to be able to interrupt bcl(3), spawn a separate +thread to run the calculation. .SH PERFORMANCE .PP Most bc(1) implementations use \f[B]char\f[R] types to calculate the @@ -1327,33 +1843,15 @@ 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. -.SH SIGNAL HANDLING -.PP -If a signal handler calls -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] 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 \f[B]BC_ERROR_SIGNAL\f[R] is returned. -.PP -If execution \f[I]is\f[R] interrupted, -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] does \f[I]not\f[R] -return to its caller. -.PP -It is undefined behavior if -\f[B]bcl_handleSignal(\f[R]\f[I]void\f[R]\f[B])\f[R] is called from a -thread that is not executing bcl(3) functions, if bcl(3) functions are -executing. .SH SEE ALSO .PP bc(1) and dc(1) .SH STANDARDS .PP bcl(3) is compliant with the arithmetic defined in the IEEE Std -1003.1-2017 -(\[lq]POSIX.1-2017\[rq]) (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) -specification for bc(1). +1003.1-2017 (\[lq]POSIX.1-2017\[rq]) specification at +https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html for +bc(1). .PP Note that the specification explicitly says that bc(1) only accepts numbers that use a period (\f[B].\f[R]) as a radix point, regardless of @@ -1362,8 +1860,8 @@ This is also true of bcl(3). .SH BUGS .PP None are known. -Report bugs at https://git.yzena.com/gavin/bc. +Report bugs at https://git.gavinhoward.com/gavin/bc. .SH AUTHORS .PP Gavin D. -Howard <gavin@yzena.com> and contributors. +Howard <gavin@gavinhoward.com> and contributors. |