aboutsummaryrefslogtreecommitdiff
path: root/manuals/bcl.3.md
diff options
context:
space:
mode:
Diffstat (limited to 'manuals/bcl.3.md')
-rw-r--r--manuals/bcl.3.md521
1 files changed, 440 insertions, 81 deletions
diff --git a/manuals/bcl.3.md b/manuals/bcl.3.md
index daf5f461..fa566d16 100644
--- a/manuals/bcl.3.md
+++ b/manuals/bcl.3.md
@@ -2,7 +2,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:
@@ -38,21 +38,16 @@ bcl - library of arbitrary precision decimal arithmetic
*#include <bcl.h>*
-Link with *-lbcl*.
-
-## Signals
-
-This procedure will allow clients to use signals to interrupt computations
-running in bcl(3).
-
-**void bcl_handleSignal(**_void_**);**
-
-**bool bcl_running(**_void_**);**
+Link with *-lbcl*, and on POSIX systems, *-lpthread* is also required.
## Setup
These items allow clients to set up bcl(3).
+**BclError bcl_start(**_void_**);**
+
+**void bcl_end(**_void_**);**
+
**BclError bcl_init(**_void_**);**
**void bcl_free(**_void_**);**
@@ -61,8 +56,16 @@ These items allow clients to set up bcl(3).
**void bcl_setAbortOnFatalError(bool** _abrt_**);**
+**bool bcl_leadingZeroes(**_void_**);**
+
+**void bcl_setLeadingZeroes(bool** _leadingZeroes_**);**
+
**void bcl_gc(**_void_**);**
+**bool bcl_digitClamp(**_void_**);**
+
+**void bcl_setDigitClamp(bool** _digitClamp_**);**
+
## Contexts
These items will allow clients to handle contexts, which are isolated from each
@@ -133,8 +136,12 @@ These items allow clients to convert numbers into and from strings and integers.
**char\* bcl_string(BclNumber** _n_**);**
+**char\* bcl_string_keep(BclNumber** _n_**);**
+
**BclError bcl_bigdig(BclNumber** _n_**, BclBigDig \***_result_**);**
+**BclError bcl_bigdig_keep(BclNumber** _n_**, BclBigDig \***_result_**);**
+
**BclNumber bcl_bigdig2num(BclBigDig** _val_**);**
## Math
@@ -143,26 +150,48 @@ These items allow clients to run math on numbers.
**BclNumber bcl_add(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_add_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_sub(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_sub_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_mul(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_mul_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_div(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_div_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_mod(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_mod_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_pow(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_pow_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_lshift(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_lshift_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_rshift(BclNumber** _a_**, BclNumber** _b_**);**
+**BclNumber bcl_rshift_keep(BclNumber** _a_**, BclNumber** _b_**);**
+
**BclNumber bcl_sqrt(BclNumber** _a_**);**
+**BclNumber bcl_sqrt_keep(BclNumber** _a_**);**
+
**BclError bcl_divmod(BclNumber** _a_**, BclNumber** _b_**, BclNumber \***_c_**, BclNumber \***_d_**);**
+**BclError bcl_divmod_keep(BclNumber** _a_**, BclNumber** _b_**, BclNumber \***_c_**, BclNumber \***_d_**);**
+
**BclNumber bcl_modexp(BclNumber** _a_**, BclNumber** _b_**, BclNumber** _c_**);**
+**BclNumber bcl_modexp_keep(BclNumber** _a_**, BclNumber** _b_**, BclNumber** _c_**);**
+
## Miscellaneous
These items are miscellaneous.
@@ -192,12 +221,18 @@ generator in bcl(3).
**BclNumber bcl_irand(BclNumber** _a_**);**
+**BclNumber bcl_irand_keep(BclNumber** _a_**);**
+
**BclNumber bcl_frand(size_t** _places_**);**
**BclNumber bcl_ifrand(BclNumber** _a_**, size_t** _places_**);**
+**BclNumber bcl_ifrand_keep(BclNumber** _a_**, size_t** _places_**);**
+
**BclError bcl_rand_seedWithNum(BclNumber** _n_**);**
+**BclError bcl_rand_seedWithNum_keep(BclNumber** _n_**);**
+
**BclError bcl_rand_seed(unsigned char** _seed_**[**_BCL_SEED_SIZE_**]);**
**void bcl_rand_reseed(**_void_**);**
@@ -211,66 +246,76 @@ generator in bcl(3).
# DESCRIPTION
bcl(3) is a library that implements arbitrary-precision decimal math, as
-[standardized by POSIX][1] in bc(1).
+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_** and **bc_** prefixes for
-symbol names without collision.
+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
+## Setup
+
+**BclError bcl_start(**_void_**)**
+
+: Initializes this library. This function can be called multiple times, but
+ **bcl_end()** must only be called *once*. This is to make it possible for
+ multiple libraries and applications to initialize bcl(3) without problem.
-**void bcl_handleSignal(**_void_**)**
+ It is suggested that client libraries call this function, but do not call
+ **bcl_end()**, and client applications should call both.
-: 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
- *not* executing any bcl(3) functions while any bcl(3) functions are
- executing.
+ If there was no error, **BCL_ERROR_NONE** is returned. Otherwise, this
+ function can return:
- If execution *is* interrupted, **bcl_handleSignal(**_void_**)** does *not*
- return to its caller.
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
- See the **SIGNAL HANDLING** section.
+ This function must be the first one clients call. Calling any other
+ function without calling this one first is undefined behavior.
-**bool bcl_running(**_void_**)**
+**void bcl_end(**_void_**)**
-: An async-signal-safe function that can be called from a signal handler. It
- will return **true** if any bcl(3) procedures are running, which means it is
- safe to call **bcl_handleSignal(**_void_**)**. Otherwise, it returns
- **false**.
+: Deinitializes this library. This function must only be called *once*.
- See the **SIGNAL HANDLING** section.
+ All data must have been freed before calling this function.
-## Setup
+ This function must be the last one clients call. Calling this function
+ before calling any other function is undefined behavior.
**BclError bcl_init(**_void_**)**
-: Initializes this library. This function can be called multiple times, but
- each call must be matched by a call to **bcl_free(**_void_**)**. This is to
- make it possible for multiple libraries and applications to initialize
- bcl(3) without problem.
+: Initializes the library for the current thread. This function can be called
+ multiple times, but each call must be matched by a call to
+ **bcl_free(**_void_**)**. This is to make it possible for multiple libraries
+ and applications to initialize threads for bcl(3) without problem.
+
+ This function *must* be called from the thread that it is supposed to
+ initialize.
If there was no error, **BCL_ERROR_NONE** is returned. Otherwise, this
function can return:
* **BCL_ERROR_FATAL_ALLOC_ERR**
- 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 **bcl_start()** and then this one first is
+ undefined behavior, except in the case of new threads. New threads can
+ safely call this function without calling **bcl_start()** if another thread
+ has previously called **bcl_start()**. But this function must still be the
+ first function in bcl(3) called by that new thread.
**void bcl_free(**_void_**)**
: Decrements bcl(3)'s reference count and frees the data associated with it if
the reference count is **0**.
- This function must be the last one clients call. Calling this function
- before calling any other function is undefined behavior.
+ This function *must* be called from the thread that it is supposed to
+ deinitialize.
+
+ This function must be the second to last one clients call. Calling this
+ function before calling any other function besides **bcl_end()** is
+ undefined behavior.
**bool bcl_abortOnFatalError(**_void_**)**
@@ -280,6 +325,10 @@ each function for what each function can return.
If activated, clients do not need to check for fatal errors.
+ This value is *thread-local*; it applies to just the thread it is read on.
+
+ The default is **false**.
+
**void bcl_setAbortOnFatalError(bool** _abrt_**)**
: Sets the state of calling **abort()** on fatal errors. If *abrt* is
@@ -287,8 +336,59 @@ each function for what each function can return.
call. If *abrt* is **true**, bcl(3) will cause a **SIGABRT** on fatal errors
after the call.
+ This value is *thread-local*; it applies to just the thread it is set on.
+
If activated, clients do not need to check for fatal errors.
+**bool bcl_leadingZeroes(**_void_**)**
+
+: Queries and returns the state of whether leading zeroes are added to strings
+ returned by **bcl_string()** when numbers are greater than **-1**, less than
+ **1**, and not equal to **0**. If **true** is returned, then leading zeroes
+ will be added.
+
+ This value is *thread-local*; it applies to just the thread it is read on.
+
+ The default is **false**.
+
+**void bcl_setLeadingZeroes(bool** _leadingZeroes_**)**
+
+: Sets the state of whether leading zeroes are added to strings returned by
+ **bcl_string()** when numbers are greater than **-1**, less than **1**, and
+ not equal to **0**. If *leadingZeroes* is **true**, leading zeroes will be
+ added to strings returned by **bcl_string()**.
+
+ This value is *thread-local*; it applies to just the thread it is set on.
+
+**bool bcl_digitClamp(**_void_**)**
+
+: Queries and returns the state of whether digits in number strings that are
+ greater than or equal to the current **ibase** are clamped or not.
+
+ If **true** is returned, then digits are treated as though they are equal to
+ the value of **ibase** minus **1**. If this is *not* true, then digits are
+ treated as though they are equal to the value they would have if **ibase**
+ was large enough. They are then multiplied by the appropriate power of
+ **ibase**.
+
+ For example, with clamping off and an **ibase** of **3**, the string "AB"
+ would equal **3\^1\*A+3\^0\*B**, which is **3** times **10** plus **11**, or
+ **41**, while with clamping on and an **ibase** of **3**, the string "AB"
+ would be equal to **3\^1\*2+3\^0\*2**, which is **3** times **2** plus
+ **2**, or **8**.
+
+ This value is *thread-local*; it applies to just the thread it is read on.
+
+ The default is **true**.
+
+**void bcl_setDigitClamp(bool** _digitClamp_**)**
+
+: Sets the state of whether digits in number strings that are greater than or
+ equal to the current **ibase** are clamped or not. For more information, see
+ the **bcl_digitClamp(**_void_**)** function.
+
+ This value is *thread-local*; it applies to just the thread it is set on.
+
**void bcl_gc(**_void_**)**
: Garbage collects cached instances of arbitrary-precision numbers. This only
@@ -334,6 +434,13 @@ an argument.
are meant to isolate the numbers used by different clients in the same
application.
+ 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 **bcl_string()** to produce a string to pass around, and
+ use **bcl_parse()** to parse the string. It is suggested that the **obase**
+ used to create the string be passed around with the string and used as the
+ **ibase** for **bcl_parse()** to ensure that the number will be the same.
+
**BclContext bcl_ctxt_create(**_void_**)**
: Creates a context and returns it. Returns **NULL** if there was an error.
@@ -473,9 +580,9 @@ All procedures in this section require a valid current context.
All 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.
+All procedures in this section without the **_keep** suffix in their name
+consume the given **BclNumber** arguments that are not given to pointer
+arguments. See the **Consumption and Propagation** subsection below.
**BclNumber bcl_parse(const char \*restrict** _val_**)**
@@ -503,6 +610,12 @@ subsection below.
*n* is consumed; it cannot be used after the call. See the
**Consumption and Propagation** subsection below.
+**char\* bcl_string_keep(BclNumber** _n_**)**
+
+: Returns a string representation of *n* according the the current context's
+ **ibase**. The string is dynamically allocated and must be freed by the
+ caller.
+
**BclError bcl_bigdig(BclNumber** _n_**, BclBigDig \***_result_**)**
: Converts *n* into a **BclBigDig** and returns the result in the space
@@ -520,6 +633,20 @@ subsection below.
*n* is consumed; it cannot be used after the call. See the
**Consumption and Propagation** subsection below.
+**BclError bcl_bigdig_keep(BclNumber** _n_**, BclBigDig \***_result_**)**
+
+: Converts *n* into a **BclBigDig** and returns the result in the space
+ pointed to by *result*.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_OVERFLOW**
+
**BclNumber bcl_bigdig2num(BclBigDig** _val_**)**
: Creates a **BclNumber** from *val*.
@@ -534,6 +661,10 @@ subsection below.
All procedures in this section require a valid current context.
+All procedures in this section without the **_keep** suffix in their name
+consume the given **BclNumber** arguments that are not given to pointer
+arguments. See the **Consumption and Propagation** subsection below.
+
All procedures in this section can return the following errors:
* **BCL_ERROR_INVALID_NUM**
@@ -557,6 +688,20 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_INVALID_CONTEXT**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_add_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Adds *a* and *b* and returns the result. The *scale* of the result is the
+ max of the *scale*s of *a* and *b*.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_sub(BclNumber** _a_**, BclNumber** _b_**)**
: Subtracts *b* from *a* and returns the result. The *scale* of the result is
@@ -574,6 +719,20 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_INVALID_CONTEXT**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_sub_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Subtracts *b* from *a* and returns the result. The *scale* of the result is
+ the max of the *scale*s of *a* and *b*.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_mul(BclNumber** _a_**, BclNumber** _b_**)**
: Multiplies *a* and *b* and returns the result. If *ascale* is the *scale* of
@@ -593,6 +752,22 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_INVALID_CONTEXT**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_mul_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Multiplies *a* and *b* and returns the result. If *ascale* is the *scale* of
+ *a* and *bscale* is the *scale* of *b*, the *scale* of the result is equal
+ to **min(ascale+bscale,max(scale,ascale,bscale))**, where **min()** and
+ **max()** return the obvious values.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_div(BclNumber** _a_**, BclNumber** _b_**)**
: Divides *a* by *b* and returns the result. The *scale* of the result is the
@@ -613,6 +788,23 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_div_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Divides *a* by *b* and returns the result. The *scale* of the result is the
+ *scale* of the current context.
+
+ *b* cannot be **0**.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_mod(BclNumber** _a_**, BclNumber** _b_**)**
: Divides *a* by *b* to the *scale* of the current context, computes the
@@ -633,6 +825,23 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_mod_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Divides *a* by *b* to the *scale* of the current context, computes the
+ modulus **a-(a/b)\*b**, and returns the modulus.
+
+ *b* cannot be **0**.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_pow(BclNumber** _a_**, BclNumber** _b_**)**
: Calculates *a* to the power of *b* to the *scale* of the current context.
@@ -658,6 +867,28 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_pow_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Calculates *a* to the power of *b* to the *scale* of the current context.
+ *b* must be an integer, but can be negative. If it is negative, *a* must
+ be non-zero.
+
+ *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* 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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_MATH_OVERFLOW**
+ * **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_lshift(BclNumber** _a_**, BclNumber** _b_**)**
: Shifts *a* left (moves the radix right) by *b* places and returns the
@@ -678,6 +909,23 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_NON_INTEGER**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_lshift_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Shifts *a* left (moves the radix right) by *b* places and returns the
+ result. This is done in decimal. *b* must be an integer.
+
+ *b* must be an integer.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_rshift(BclNumber** _a_**, BclNumber** _b_**)**
: Shifts *a* right (moves the radix left) by *b* places and returns the
@@ -698,6 +946,23 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_NON_INTEGER**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_rshift_keep(BclNumber** _a_**, BclNumber** _b_**)**
+
+: Shifts *a* right (moves the radix left) by *b* places and returns the
+ result. This is done in decimal. *b* must be an integer.
+
+ *b* must be an integer.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_sqrt(BclNumber** _a_**)**
: Calculates the square root of *a* and returns the result. The *scale* of the
@@ -716,6 +981,21 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_NEGATIVE**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_sqrt_keep(BclNumber** _a_**)**
+
+: Calculates the square root of *a* and returns the result. The *scale* of the
+ result is equal to the **scale** of the current context.
+
+ *a* cannot be negative.
+
+ 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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NEGATIVE**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclError bcl_divmod(BclNumber** _a_**, BclNumber** _b_**, BclNumber \***_c_**, BclNumber \***_d_**)**
: Divides *a* by *b* and returns the quotient in a new number which is put
@@ -738,6 +1018,25 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclError bcl_divmod_keep(BclNumber** _a_**, BclNumber** _b_**, BclNumber \***_c_**, BclNumber \***_d_**)**
+
+: Divides *a* by *b* and returns the quotient in a new number which is put
+ into the space pointed to by *c*, and puts the modulus in a new number which
+ is put into the space pointed to by *d*.
+
+ *b* cannot be **0**.
+
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
**BclNumber bcl_modexp(BclNumber** _a_**, BclNumber** _b_**, BclNumber** _c_**)**
: Computes a modular exponentiation where *a* is the base, *b* is the
@@ -760,6 +1059,25 @@ All procedures in this section can return the following errors:
* **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
* **BCL_ERROR_FATAL_ALLOC_ERR**
+**BclNumber bcl_modexp_keep(BclNumber** _a_**, BclNumber** _b_**, BclNumber** _c_**)**
+
+: Computes a modular exponentiation where *a* is the base, *b* is the
+ exponent, and *c* is the modulus, and returns the result. The *scale* of the
+ result is equal to the **scale** of the current context.
+
+ *a*, *b*, and *c* must be integers. *c* must not be **0**. *b* must not be
+ negative.
+
+ 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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NEGATIVE**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_MATH_DIVIDE_BY_ZERO**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
## Miscellaneous
**void bcl_zero(BclNumber** _n_**)**
@@ -816,6 +1134,10 @@ If necessary, the PRNG can be reseeded with one of the following functions:
* **bcl_rand_seed(unsigned char[**_BCL_SEED_SIZE_**])**
* **bcl_rand_reseed(**_void_**)**
+All procedures in this section without the **_keep** suffix in their name
+consume the given **BclNumber** arguments that are not given to pointer
+arguments. See the **Consumption and Propagation** subsection below.
+
The following items allow clients to use the pseudo-random number generator. All
procedures require a valid current context.
@@ -846,8 +1168,29 @@ 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.
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NEGATIVE**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
+**BclNumber bcl_irand_keep(BclNumber** _a_**)**
+
+: Returns a random number that is not larger than *a* in a new number. If *a*
+ is **0** or **1**, the new number is equal to **0**. The bound is unlimited,
+ so it is not bound to the size of **BclRandInt**. This is done by generating
+ as many random numbers as necessary, multiplying them by certain exponents,
+ and adding them all together.
+
+ *a* must be an integer and non-negative.
This procedure requires a valid current context.
@@ -881,8 +1224,26 @@ 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.
+ *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:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+ * **BCL_ERROR_MATH_NEGATIVE**
+ * **BCL_ERROR_MATH_NON_INTEGER**
+ * **BCL_ERROR_FATAL_ALLOC_ERR**
+
+**BclNumber bcl_ifrand_keep(BclNumber** _a_**, size_t** _places_**)**
+
+: Returns a random number less than *a* with *places* decimal digits after the
+ radix (decimal point). There are no limits on *a* or *places*.
+
+ *a* must be an integer and non-negative.
This procedure requires a valid current context.
@@ -899,7 +1260,23 @@ procedures require a valid current context.
: Seeds the PRNG with *n*.
- *n* is *not* consumed.
+ *n* is consumed.
+
+ This procedure requires a valid current context.
+
+ If there was no error, **BCL_ERROR_NONE** is returned. Otherwise, this
+ function can return:
+
+ * **BCL_ERROR_INVALID_NUM**
+ * **BCL_ERROR_INVALID_CONTEXT**
+
+ 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*.
+
+**BclError bcl_rand_seedWithNum_keep(BclNumber** _n_**)**
+
+: Seeds the PRNG with *n*.
This procedure requires a valid current context.
@@ -971,7 +1348,7 @@ checked with **bcl_err(BclNumber)**, so the example above should properly
be:
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.
}
@@ -992,10 +1369,6 @@ codes defined in **BclError**. The complete list of codes is the following:
: An invalid **BclContext** is being used.
-**BCL_ERROR_SIGNAL**
-
-: A signal interrupted execution.
-
**BCL_ERROR_MATH_NEGATIVE**
: A negative number was given as an argument to a parameter that cannot accept
@@ -1065,11 +1438,13 @@ codes defined in **BclError**. The complete list of codes is the following:
# ATTRIBUTES
-When **bcl_handleSignal(**_void_**)** is used properly, bcl(3) is
-async-signal-safe.
+bcl(3) is *MT-Safe*: it is safe to call any functions from more than one thread.
+However, is is *not* safe to pass any data between threads except for strings
+returned by **bcl_string()**.
-bcl(3) is *MT-Unsafe*: it is unsafe to call any functions from more than one
-thread.
+bcl(3) is not *async-signal-safe*. 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.
# PERFORMANCE
@@ -1141,29 +1516,15 @@ These limits are meant to be effectively non-existent; the limits are so large
become a problem. In fact, memory should be exhausted before these limits should
be hit.
-# SIGNAL HANDLING
-
-If 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 ALSO
bc(1) and dc(1)
# STANDARDS
-bcl(3) is compliant with the arithmetic defined in the
-[IEEE Std 1003.1-2017 (“POSIX.1-2017”)][1] specification for bc(1).
+bcl(3) is compliant with the arithmetic defined in the IEEE Std 1003.1-2017
+(“POSIX.1-2017”) specification at
+https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html 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
@@ -1171,10 +1532,8 @@ use a period (**.**) as a radix point, regardless of the value of
# BUGS
-None are known. Report bugs at https://git.yzena.com/gavin/bc.
+None are known. Report bugs at https://git.gavinhoward.com/gavin/bc.
# AUTHORS
-Gavin D. Howard <gavin@yzena.com> and contributors.
-
-[1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
+Gavin D. Howard <gavin@gavinhoward.com> and contributors.