aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2023-04-12 17:28:46 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-04-12 17:28:46 +0000
commit211da69ae75405023c29340e4e45b7c3fcccc2af (patch)
tree87ec1db1aaae068d23b200dbc19802402d6ca470
parent175888b8d57a2bdeb3f87034cc40f5619d7ff79c (diff)
parent214eb3eb45cb03d03a6d0809bf79f49ad9ac0767 (diff)
downloadbc-211da69ae75405023c29340e4e45b7c3fcccc2af.tar.gz
Original change: https://android-review.googlesource.com/c/platform/external/bc/+/2530973 Change-Id: I92f7e5699b972d22976cfd7cccecd4eb3b4af202 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--METADATA6
-rw-r--r--Makefile.in2
-rw-r--r--NEWS.md44
-rwxr-xr-xconfigure.sh2
-rw-r--r--gen/lib2.bc28
-rw-r--r--include/bcl.h51
-rw-r--r--include/lang.h3
-rw-r--r--include/lex.h3
-rw-r--r--include/library.h210
-rw-r--r--include/program.h210
-rw-r--r--include/version.h2
-rw-r--r--include/vm.h4
-rw-r--r--manuals/bc.1.md.in6
-rw-r--r--manuals/bc/A.16
-rw-r--r--manuals/bc/A.1.md2
-rw-r--r--manuals/bc/E.16
-rw-r--r--manuals/bc/E.1.md2
-rw-r--r--manuals/bc/EH.16
-rw-r--r--manuals/bc/EH.1.md2
-rw-r--r--manuals/bc/EHN.16
-rw-r--r--manuals/bc/EHN.1.md2
-rw-r--r--manuals/bc/EN.16
-rw-r--r--manuals/bc/EN.1.md2
-rw-r--r--manuals/bc/H.16
-rw-r--r--manuals/bc/H.1.md2
-rw-r--r--manuals/bc/HN.16
-rw-r--r--manuals/bc/HN.1.md2
-rw-r--r--manuals/bc/N.16
-rw-r--r--manuals/bc/N.1.md2
-rw-r--r--manuals/bcl.3424
-rw-r--r--manuals/bcl.3.md320
-rw-r--r--manuals/dc.1.md.in10
-rw-r--r--manuals/dc/A.112
-rw-r--r--manuals/dc/A.1.md10
-rw-r--r--manuals/dc/E.112
-rw-r--r--manuals/dc/E.1.md10
-rw-r--r--manuals/dc/EH.112
-rw-r--r--manuals/dc/EH.1.md10
-rw-r--r--manuals/dc/EHN.112
-rw-r--r--manuals/dc/EHN.1.md10
-rw-r--r--manuals/dc/EN.112
-rw-r--r--manuals/dc/EN.1.md10
-rw-r--r--manuals/dc/H.112
-rw-r--r--manuals/dc/H.1.md10
-rw-r--r--manuals/dc/HN.112
-rw-r--r--manuals/dc/HN.1.md10
-rw-r--r--manuals/dc/N.112
-rw-r--r--manuals/dc/N.1.md10
-rw-r--r--manuals/development.md28
-rw-r--r--manuals/header_bc.txt2
-rw-r--r--manuals/header_bcl.txt2
-rw-r--r--manuals/header_dc.txt2
-rwxr-xr-xscripts/exec-install.sh6
-rwxr-xr-xscripts/fuzz_prep.sh9
-rwxr-xr-xscripts/locale_install.sh3
-rwxr-xr-xscripts/safe-install.sh12
-rw-r--r--src/bc_parse.c2
-rw-r--r--src/data.c73
-rw-r--r--src/dc_lex.c1
-rw-r--r--src/dc_parse.c1
-rw-r--r--src/library.c739
-rw-r--r--src/program.c24
-rw-r--r--src/vm.c10
-rwxr-xr-xtests/all.sh3
-rw-r--r--tests/bc/all.txt1
-rw-r--r--tests/bc/fib.txt31
-rw-r--r--tests/bc/fib_results.txt31
-rw-r--r--tests/bc/scripts/all.txt1
-rw-r--r--tests/bc/scripts/cbrt.txt100
-rw-r--r--tests/bc/scripts/root.bc19
-rw-r--r--tests/bc/scripts/root.txt255
-rw-r--r--tests/bcl.c52
-rw-r--r--tests/extra_required.txt1
-rwxr-xr-xtests/other.sh36
-rwxr-xr-xtests/read.sh13
-rwxr-xr-xtests/script.sh2
-rwxr-xr-xtests/scripts.sh3
77 files changed, 2440 insertions, 587 deletions
diff --git a/METADATA b/METADATA
index bd4d6568..9356878b 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/gavinhoward/bc"
}
- version: "6.2.5"
+ version: "6.5.0"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 2
- day: 14
+ month: 4
+ day: 11
}
}
diff --git a/Makefile.in b/Makefile.in
index 89ddb758..f936fc2c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -536,7 +536,6 @@ clean:%%CLEAN_PREREQS%%
@$(RM) -f $(BC_HELP_C) $(BC_HELP_O)
@$(RM) -f $(DC_HELP_C) $(DC_HELP_O)
@$(RM) -fr vs/bin/ vs/lib/
- @$(RM) -f $(BCL_PC)
clean_benchmarks:
@printf 'Cleaning benchmarks...\n'
@@ -550,6 +549,7 @@ clean_config: clean clean_benchmarks
@$(RM) -f $(BC_MD) $(BC_MANPAGE)
@$(RM) -f $(DC_MD) $(DC_MANPAGE)
@$(RM) -f compile_commands.json
+ @$(RM) -f $(BCL_PC)
clean_coverage:
@printf 'Cleaning coverage files...\n'
diff --git a/NEWS.md b/NEWS.md
index bf4aae40..44b17b06 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,49 @@
# News
+## 6.5.0
+
+This is a production release that fixes an infinite loop bug in `root()` and
+`cbrt()`, fixes a bug with `BC_LINE_LENGTH=0`, and adds the `fib()` function to
+the extended math library to calculate Fibonacci numbers.
+
+## 6.4.0
+
+This is a production release that fixes a `read()`/`?` bug and adds features to
+`bcl`.
+
+The bug was that multiple read calls could repeat old data.
+
+The new features in `bcl` are functions to preserve `BclNumber` arguments and
+not free them.
+
+***WARNING for `bcl` Users***: The `bcl_rand_seedWithNum()` function used to not
+consume its arguments. Now it does. This change could have made this version
+`7.0.0`, but I'm 99.9% confident that there are no `bcl` users, or if there are,
+they probably don't use the PRNG. So I took a risk and didn't update the major
+version.
+
+`bcl` now includes more capacity to check for invalid numbers when built to run
+under Valgrind.
+
+## 6.3.1
+
+This is a production release that fixes a `bc` dependency loop for minimal
+environments and Linux from Scratch.
+
+## 6.3.0
+
+This is a production release with a couple of fixes for manuals and a new
+feature for `dc`: there is now a command to query whether extended registers are
+enabled or not.
+
+Users who don't care do not need to upgrade.
+
+## 6.2.6
+
+This is a production release that fixes an install bug that affected locale
+installation of all locales when using `mksh`. Users do ***NOT*** need to
+upgrade if they don't use `mksh` and/or don't need to install all locales.
+
## 6.2.5
This is a production release that fixes a test bug that affected Android and
diff --git a/configure.sh b/configure.sh
index 3ada5298..021d3080 100755
--- a/configure.sh
+++ b/configure.sh
@@ -1801,7 +1801,7 @@ if [ "$library" -ne 0 ]; then
contents=$(replace "$contents" "LIBDIR" "$LIBDIR")
contents=$(replace "$contents" "VERSION" "$version")
- printf '%s\n' "$contents" > "./bcl.pc"
+ printf '%s\n' "$contents" > "$scriptdir/bcl.pc"
pkg_config_install="\$(SAFE_INSTALL) \$(PC_INSTALL_ARGS) \"\$(BCL_PC)\" \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
pkg_config_uninstall="\$(RM) -f \"\$(DESTDIR)\$(PC_PATH)/\$(BCL_PC)\""
diff --git a/gen/lib2.bc b/gen/lib2.bc
index 826f8a43..ba3f76b1 100644
--- a/gen/lib2.bc
+++ b/gen/lib2.bc
@@ -36,7 +36,7 @@
define p(x,y){
auto a
a=y$
- if(y==a)return (x^a)@scale
+ if(y==a)return(x^a)@scale
return e(y*l(x))
}
define r(x,p){
@@ -93,6 +93,18 @@ define comb(n,r){
scale=s
return f
}
+define fib(n){
+ auto i,t,p,r
+ if(!n)return 0
+ n=abs(n)$
+ t=1
+ for (i=1;i<n;++i){
+ r=p
+ p=t
+ t+=r
+ }
+ return t
+}
define log(x,b){
auto p,s
s=scale
@@ -106,7 +118,7 @@ define log(x,b){
define l2(x){return log(x,2)}
define l10(x){return log(x,A)}
define root(x,n){
- auto s,m,r,q,p
+ auto s,t,m,r,q,p
if(n<0)sqrt(n)
n=n$
if(n==0)x/n
@@ -114,13 +126,17 @@ define root(x,n){
if(n==2)return sqrt(x)
s=scale
scale=0
- if(x<0&&n%2==0)sqrt(x)
- scale=s+2
+ if(x<0&&n%2==0){
+ scale=s
+ sqrt(x)
+ }
+ scale=s+scale(x)+5
+ t=s+5
m=(x<0)
x=abs(x)
p=n-1
q=A^ceil((length(x$)/n)$,0)
- while(r!=q){
+ while(r@t!=q@t){
r=q
q=(p*r+x/r^p)/n
}
@@ -474,7 +490,7 @@ define bxor(a,b){
return bunrev(t)
}
define bshl(a,b){return abs(a)$*2^abs(b)$}
-define bshr(a,b){return (abs(a)$/2^abs(b)$)$}
+define bshr(a,b){return(abs(a)$/2^abs(b)$)$}
define bnotn(x,n){
auto s,t,m[]
s=scale
diff --git a/include/bcl.h b/include/bcl.h
index 25313823..0908e215 100644
--- a/include/bcl.h
+++ b/include/bcl.h
@@ -36,6 +36,9 @@
#ifndef BC_BCL_H
#define BC_BCL_H
+// TODO: Add a generation index when building with Valgrind to check for
+// use-after-free's or double frees.
+
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>
@@ -238,6 +241,9 @@ bcl_dup(BclNumber s);
BclError
bcl_bigdig(BclNumber n, BclBigDig* result);
+BclError
+bcl_bigdig_keep(BclNumber n, BclBigDig* result);
+
BclNumber
bcl_bigdig2num(BclBigDig val);
@@ -245,35 +251,68 @@ 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);
+
ssize_t
bcl_cmp(BclNumber a, BclNumber b);
@@ -289,19 +328,31 @@ bcl_parse(const char* restrict val);
char*
bcl_string(BclNumber n);
+char*
+bcl_string_keep(BclNumber n);
+
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
diff --git a/include/lang.h b/include/lang.h
index 9eee3279..97aeeaa9 100644
--- a/include/lang.h
+++ b/include/lang.h
@@ -277,6 +277,9 @@ typedef enum BcInst
#if DC_ENABLED
+ /// dc extended registers command.
+ BC_INST_EXTENDED_REGISTERS,
+
/// dc's return; it pops an executing string off of the stack.
BC_INST_POP_EXEC,
diff --git a/include/lex.h b/include/lex.h
index 060f5bea..ac9b7b6e 100644
--- a/include/lex.h
+++ b/include/lex.h
@@ -409,6 +409,9 @@ typedef enum BcLexType
#if DC_ENABLED
+ /// dc extended registers keyword.
+ BC_LEX_EXTENDED_REGISTERS,
+
/// A special token for dc to calculate equal without a register.
BC_LEX_EQ_NO_REG,
diff --git a/include/library.h b/include/library.h
index 76df9139..1edd3757 100644
--- a/include/library.h
+++ b/include/library.h
@@ -47,6 +47,145 @@
#include <num.h>
#include <vm.h>
+#if BC_ENABLE_MEMCHECK
+
+/**
+ * A typedef for Valgrind builds. This is to add a generation index for error
+ * checking.
+ */
+typedef struct BclNum
+{
+ /// The number.
+ BcNum n;
+
+ /// The generation index.
+ size_t gen_idx;
+
+} BclNum;
+
+/**
+ * Clears the generation byte in a BclNumber and returns the value.
+ * @param n The BclNumber.
+ * @return The value of the index.
+ */
+#define BCL_NO_GEN(n) \
+ ((n).i & ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT)))
+
+/**
+ * Gets the generation index in a BclNumber.
+ * @param n The BclNumber.
+ * @return The generation index.
+ */
+#define BCL_GET_GEN(n) ((n).i >> ((sizeof(size_t) - 1) * CHAR_BIT))
+
+/**
+ * Turns a BclNumber into a BcNum.
+ * @param c The context.
+ * @param n The BclNumber.
+ */
+#define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, BCL_NO_GEN(n)))
+
+/**
+ * Clears the generation index top byte in the BclNumber.
+ * @param n The BclNumber.
+ */
+#define BCL_CLEAR_GEN(n) \
+ do \
+ { \
+ (n).i &= ~(((size_t) UCHAR_MAX) << ((sizeof(size_t) - 1) * CHAR_BIT)); \
+ } \
+ while (0)
+
+#define BCL_CHECK_NUM_GEN(c, bn) \
+ do \
+ { \
+ size_t gen_ = BCL_GET_GEN(bn); \
+ BclNum* ptr_ = BCL_NUM(c, bn); \
+ if (BCL_NUM_ARRAY(ptr_) == NULL) \
+ { \
+ bcl_nonexistentNum(); \
+ } \
+ if (gen_ != ptr_->gen_idx) \
+ { \
+ bcl_invalidGeneration(); \
+ } \
+ } \
+ while (0)
+
+#define BCL_CHECK_NUM_VALID(c, bn) \
+ do \
+ { \
+ size_t idx_ = BCL_NO_GEN(bn); \
+ if ((c)->nums.len <= idx_) \
+ { \
+ bcl_numIdxOutOfRange(); \
+ } \
+ BCL_CHECK_NUM_GEN(c, bn); \
+ } \
+ while (0)
+
+/**
+ * Returns the limb array of the number.
+ * @param bn The number.
+ * @return The limb array.
+ */
+#define BCL_NUM_ARRAY(bn) ((bn)->n.num)
+
+/**
+ * Returns the limb array of the number for a non-pointer.
+ * @param bn The number.
+ * @return The limb array.
+ */
+#define BCL_NUM_ARRAY_NP(bn) ((bn).n.num)
+
+/**
+ * Returns the BcNum pointer.
+ * @param bn The number.
+ * @return The BcNum pointer.
+ */
+#define BCL_NUM_NUM(bn) (&(bn)->n)
+
+/**
+ * Returns the BcNum pointer for a non-pointer.
+ * @param bn The number.
+ * @return The BcNum pointer.
+ */
+#define BCL_NUM_NUM_NP(bn) (&(bn).n)
+
+// These functions only abort. They exist to give developers some idea of what
+// went wrong when bugs are found, if they look at the Valgrind stack trace.
+
+BC_NORETURN void
+bcl_invalidGeneration(void);
+
+BC_NORETURN void
+bcl_nonexistentNum(void);
+
+BC_NORETURN void
+bcl_numIdxOutOfRange(void);
+
+#else // BC_ENABLE_MEMCHECK
+
+/**
+ * A typedef for non-Valgrind builds.
+ */
+typedef BcNum BclNum;
+
+#define BCL_NO_GEN(n) ((n).i)
+#define BCL_NUM(c, n) ((BclNum*) bc_vec_item(&(c)->nums, (n).i))
+#define BCL_CLEAR_GEN(n) ((void) (n))
+
+#define BCL_CHECK_NUM_GEN(c, bn)
+#define BCL_CHECK_NUM_VALID(c, n)
+
+#define BCL_NUM_ARRAY(bn) ((bn)->num)
+#define BCL_NUM_ARRAY_NP(bn) ((bn).num)
+
+#define BCL_NUM_NUM(bn) (bn)
+#define BCL_NUM_NUM_NP(bn) (&(bn))
+
+#endif // BC_ENABLE_MEMCHECK
+
/**
* A header that sets a jump.
* @param vm The thread data.
@@ -88,19 +227,19 @@
* idx.
* @param c The context.
* @param e The error.
- * @param n The number.
+ * @param bn The number.
* @param idx The idx to set as the return value.
*/
-#define BC_MAYBE_SETUP(c, e, n, idx) \
- do \
- { \
- if (BC_ERR((e) != BCL_ERROR_NONE)) \
- { \
- if ((n).num != NULL) bc_num_free(&(n)); \
- idx.i = 0 - (size_t) (e); \
- } \
- else idx = bcl_num_insert(c, &(n)); \
- } \
+#define BC_MAYBE_SETUP(c, e, bn, idx) \
+ do \
+ { \
+ if (BC_ERR((e) != BCL_ERROR_NONE)) \
+ { \
+ if (BCL_NUM_ARRAY_NP(bn) != NULL) bc_num_free(BCL_NUM_NUM_NP(bn)); \
+ idx.i = 0 - (size_t) (e); \
+ } \
+ else idx = bcl_num_insert(c, &(bn)); \
+ } \
while (0)
/**
@@ -108,17 +247,17 @@
* is bad.
* @param c The context.
*/
-#define BC_CHECK_CTXT(vm, c) \
- do \
- { \
- c = bcl_contextHelper(vm); \
- if (BC_ERR(c == NULL)) \
- { \
- BclNumber n_num; \
- n_num.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \
- return n_num; \
- } \
- } \
+#define BC_CHECK_CTXT(vm, c) \
+ do \
+ { \
+ c = bcl_contextHelper(vm); \
+ if (BC_ERR(c == NULL)) \
+ { \
+ BclNumber n_num_; \
+ n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_CONTEXT; \
+ return n_num_; \
+ } \
+ } \
while (0)
/**
@@ -157,16 +296,18 @@
#define BC_CHECK_NUM(c, n) \
do \
{ \
- if (BC_ERR((n).i >= (c)->nums.len)) \
+ size_t no_gen_ = BCL_NO_GEN(n); \
+ if (BC_ERR(no_gen_ >= (c)->nums.len)) \
{ \
if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) return (n); \
else \
{ \
- BclNumber n_num; \
- n_num.i = 0 - (size_t) BCL_ERROR_INVALID_NUM; \
- return n_num; \
+ BclNumber n_num_; \
+ n_num_.i = 0 - (size_t) BCL_ERROR_INVALID_NUM; \
+ return n_num_; \
} \
} \
+ BCL_CHECK_NUM_GEN(c, n); \
} \
while (0)
@@ -181,7 +322,8 @@
#define BC_CHECK_NUM_ERR(c, n) \
do \
{ \
- if (BC_ERR((n).i >= (c)->nums.len)) \
+ size_t no_gen_ = BCL_NO_GEN(n); \
+ if (BC_ERR(no_gen_ >= (c)->nums.len)) \
{ \
if ((n).i > 0 - (size_t) BCL_ERROR_NELEMS) \
{ \
@@ -189,17 +331,25 @@
} \
else return BCL_ERROR_INVALID_NUM; \
} \
+ BCL_CHECK_NUM_GEN(c, n); \
} \
while (0)
//clang-format on
/**
- * Turns a BclNumber into a BcNum.
+ * Grows the context's nums array if necessary.
* @param c The context.
- * @param n The BclNumber.
*/
-#define BC_NUM(c, n) ((BcNum*) bc_vec_item(&(c)->nums, (n).i))
+#define BCL_GROW_NUMS(c) \
+ do \
+ { \
+ if ((c)->free_nums.len == 0) \
+ { \
+ bc_vec_grow(&((c)->nums), 1); \
+ } \
+ } \
+ while (0)
/**
* Frees a BcNum for bcl. This is a destructor.
diff --git a/include/program.h b/include/program.h
index 93621d4d..1df753af 100644
--- a/include/program.h
+++ b/include/program.h
@@ -608,6 +608,7 @@ extern const char bc_program_esc_seqs[];
&&lbl_BC_INST_MODEXP, \
&&lbl_BC_INST_DIVMOD, \
&&lbl_BC_INST_PRINT_STREAM, \
+ &&lbl_BC_INST_EXTENDED_REGISTERS, \
&&lbl_BC_INST_POP_EXEC, \
&&lbl_BC_INST_EXECUTE, \
&&lbl_BC_INST_EXEC_COND, \
@@ -701,6 +702,7 @@ extern const char bc_program_esc_seqs[];
&&lbl_BC_INST_MODEXP, \
&&lbl_BC_INST_DIVMOD, \
&&lbl_BC_INST_PRINT_STREAM, \
+ &&lbl_BC_INST_EXTENDED_REGISTERS, \
&&lbl_BC_INST_POP_EXEC, \
&&lbl_BC_INST_EXECUTE, \
&&lbl_BC_INST_EXEC_COND, \
@@ -902,146 +904,82 @@ extern const char bc_program_esc_seqs[];
#if BC_ENABLE_EXTRA_MATH
-#define BC_PROG_LBLS \
- static const void* const bc_program_inst_lbls[] = { \
- &&lbl_BC_INST_NEG, \
- &&lbl_BC_INST_BOOL_NOT, \
- &&lbl_BC_INST_TRUNC, \
- &&lbl_BC_INST_POWER, \
- &&lbl_BC_INST_MULTIPLY, \
- &&lbl_BC_INST_DIVIDE, \
- &&lbl_BC_INST_MODULUS, \
- &&lbl_BC_INST_PLUS, \
- &&lbl_BC_INST_MINUS, \
- &&lbl_BC_INST_PLACES, \
- &&lbl_BC_INST_LSHIFT, \
- &&lbl_BC_INST_RSHIFT, \
- &&lbl_BC_INST_REL_EQ, \
- &&lbl_BC_INST_REL_LE, \
- &&lbl_BC_INST_REL_GE, \
- &&lbl_BC_INST_REL_NE, \
- &&lbl_BC_INST_REL_LT, \
- &&lbl_BC_INST_REL_GT, \
- &&lbl_BC_INST_BOOL_OR, \
- &&lbl_BC_INST_BOOL_AND, \
- &&lbl_BC_INST_ASSIGN_NO_VAL, \
- &&lbl_BC_INST_NUM, \
- &&lbl_BC_INST_VAR, \
- &&lbl_BC_INST_ARRAY_ELEM, \
- &&lbl_BC_INST_ARRAY, \
- &&lbl_BC_INST_ZERO, \
- &&lbl_BC_INST_ONE, \
- &&lbl_BC_INST_IBASE, \
- &&lbl_BC_INST_OBASE, \
- &&lbl_BC_INST_SCALE, \
- &&lbl_BC_INST_SEED, \
- &&lbl_BC_INST_LENGTH, \
- &&lbl_BC_INST_SCALE_FUNC, \
- &&lbl_BC_INST_SQRT, \
- &&lbl_BC_INST_ABS, \
- &&lbl_BC_INST_IS_NUMBER, \
- &&lbl_BC_INST_IS_STRING, \
- &&lbl_BC_INST_IRAND, \
- &&lbl_BC_INST_ASCIIFY, \
- &&lbl_BC_INST_READ, \
- &&lbl_BC_INST_RAND, \
- &&lbl_BC_INST_MAXIBASE, \
- &&lbl_BC_INST_MAXOBASE, \
- &&lbl_BC_INST_MAXSCALE, \
- &&lbl_BC_INST_MAXRAND, \
- &&lbl_BC_INST_LINE_LENGTH, \
- &&lbl_BC_INST_LEADING_ZERO, \
- &&lbl_BC_INST_PRINT, \
- &&lbl_BC_INST_PRINT_POP, \
- &&lbl_BC_INST_STR, \
- &&lbl_BC_INST_POP, \
- &&lbl_BC_INST_SWAP, \
- &&lbl_BC_INST_MODEXP, \
- &&lbl_BC_INST_DIVMOD, \
- &&lbl_BC_INST_PRINT_STREAM, \
- &&lbl_BC_INST_POP_EXEC, \
- &&lbl_BC_INST_EXECUTE, \
- &&lbl_BC_INST_EXEC_COND, \
- &&lbl_BC_INST_PRINT_STACK, \
- &&lbl_BC_INST_CLEAR_STACK, \
- &&lbl_BC_INST_REG_STACK_LEN, \
- &&lbl_BC_INST_STACK_LEN, \
- &&lbl_BC_INST_DUPLICATE, \
- &&lbl_BC_INST_LOAD, \
- &&lbl_BC_INST_PUSH_VAR, \
- &&lbl_BC_INST_PUSH_TO_VAR, \
- &&lbl_BC_INST_QUIT, \
- &&lbl_BC_INST_NQUIT, \
- &&lbl_BC_INST_EXEC_STACK_LEN, \
- &&lbl_BC_INST_INVALID, \
+#define BC_PROG_LBLS \
+ static const void* const bc_program_inst_lbls[] = { \
+ &&lbl_BC_INST_NEG, &&lbl_BC_INST_BOOL_NOT, \
+ &&lbl_BC_INST_TRUNC, &&lbl_BC_INST_POWER, \
+ &&lbl_BC_INST_MULTIPLY, &&lbl_BC_INST_DIVIDE, \
+ &&lbl_BC_INST_MODULUS, &&lbl_BC_INST_PLUS, \
+ &&lbl_BC_INST_MINUS, &&lbl_BC_INST_PLACES, \
+ &&lbl_BC_INST_LSHIFT, &&lbl_BC_INST_RSHIFT, \
+ &&lbl_BC_INST_REL_EQ, &&lbl_BC_INST_REL_LE, \
+ &&lbl_BC_INST_REL_GE, &&lbl_BC_INST_REL_NE, \
+ &&lbl_BC_INST_REL_LT, &&lbl_BC_INST_REL_GT, \
+ &&lbl_BC_INST_BOOL_OR, &&lbl_BC_INST_BOOL_AND, \
+ &&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM, \
+ &&lbl_BC_INST_VAR, &&lbl_BC_INST_ARRAY_ELEM, \
+ &&lbl_BC_INST_ARRAY, &&lbl_BC_INST_ZERO, \
+ &&lbl_BC_INST_ONE, &&lbl_BC_INST_IBASE, \
+ &&lbl_BC_INST_OBASE, &&lbl_BC_INST_SCALE, \
+ &&lbl_BC_INST_SEED, &&lbl_BC_INST_LENGTH, \
+ &&lbl_BC_INST_SCALE_FUNC, &&lbl_BC_INST_SQRT, \
+ &&lbl_BC_INST_ABS, &&lbl_BC_INST_IS_NUMBER, \
+ &&lbl_BC_INST_IS_STRING, &&lbl_BC_INST_IRAND, \
+ &&lbl_BC_INST_ASCIIFY, &&lbl_BC_INST_READ, \
+ &&lbl_BC_INST_RAND, &&lbl_BC_INST_MAXIBASE, \
+ &&lbl_BC_INST_MAXOBASE, &&lbl_BC_INST_MAXSCALE, \
+ &&lbl_BC_INST_MAXRAND, &&lbl_BC_INST_LINE_LENGTH, \
+ &&lbl_BC_INST_LEADING_ZERO, &&lbl_BC_INST_PRINT, \
+ &&lbl_BC_INST_PRINT_POP, &&lbl_BC_INST_STR, \
+ &&lbl_BC_INST_POP, &&lbl_BC_INST_SWAP, \
+ &&lbl_BC_INST_MODEXP, &&lbl_BC_INST_DIVMOD, \
+ &&lbl_BC_INST_PRINT_STREAM, &&lbl_BC_INST_EXTENDED_REGISTERS, \
+ &&lbl_BC_INST_POP_EXEC, &&lbl_BC_INST_EXECUTE, \
+ &&lbl_BC_INST_EXEC_COND, &&lbl_BC_INST_PRINT_STACK, \
+ &&lbl_BC_INST_CLEAR_STACK, &&lbl_BC_INST_REG_STACK_LEN, \
+ &&lbl_BC_INST_STACK_LEN, &&lbl_BC_INST_DUPLICATE, \
+ &&lbl_BC_INST_LOAD, &&lbl_BC_INST_PUSH_VAR, \
+ &&lbl_BC_INST_PUSH_TO_VAR, &&lbl_BC_INST_QUIT, \
+ &&lbl_BC_INST_NQUIT, &&lbl_BC_INST_EXEC_STACK_LEN, \
+ &&lbl_BC_INST_INVALID, \
}
#else // BC_ENABLE_EXTRA_MATH
-#define BC_PROG_LBLS \
- static const void* const bc_program_inst_lbls[] = { \
- &&lbl_BC_INST_NEG, \
- &&lbl_BC_INST_BOOL_NOT, \
- &&lbl_BC_INST_POWER, \
- &&lbl_BC_INST_MULTIPLY, \
- &&lbl_BC_INST_DIVIDE, \
- &&lbl_BC_INST_MODULUS, \
- &&lbl_BC_INST_PLUS, \
- &&lbl_BC_INST_MINUS, \
- &&lbl_BC_INST_REL_EQ, \
- &&lbl_BC_INST_REL_LE, \
- &&lbl_BC_INST_REL_GE, \
- &&lbl_BC_INST_REL_NE, \
- &&lbl_BC_INST_REL_LT, \
- &&lbl_BC_INST_REL_GT, \
- &&lbl_BC_INST_BOOL_OR, \
- &&lbl_BC_INST_BOOL_AND, \
- &&lbl_BC_INST_ASSIGN_NO_VAL, \
- &&lbl_BC_INST_NUM, \
- &&lbl_BC_INST_VAR, \
- &&lbl_BC_INST_ARRAY_ELEM, \
- &&lbl_BC_INST_ARRAY, \
- &&lbl_BC_INST_ZERO, \
- &&lbl_BC_INST_ONE, \
- &&lbl_BC_INST_IBASE, \
- &&lbl_BC_INST_OBASE, \
- &&lbl_BC_INST_SCALE, \
- &&lbl_BC_INST_LENGTH, \
- &&lbl_BC_INST_SCALE_FUNC, \
- &&lbl_BC_INST_SQRT, \
- &&lbl_BC_INST_ABS, \
- &&lbl_BC_INST_IS_NUMBER, \
- &&lbl_BC_INST_IS_STRING, \
- &&lbl_BC_INST_ASCIIFY, \
- &&lbl_BC_INST_READ, \
- &&lbl_BC_INST_MAXIBASE, \
- &&lbl_BC_INST_MAXOBASE, \
- &&lbl_BC_INST_MAXSCALE, \
- &&lbl_BC_INST_LINE_LENGTH, \
- &&lbl_BC_INST_LEADING_ZERO, \
- &&lbl_BC_INST_PRINT, \
- &&lbl_BC_INST_PRINT_POP, \
- &&lbl_BC_INST_STR, \
- &&lbl_BC_INST_POP, \
- &&lbl_BC_INST_SWAP, \
- &&lbl_BC_INST_MODEXP, \
- &&lbl_BC_INST_DIVMOD, \
- &&lbl_BC_INST_PRINT_STREAM, \
- &&lbl_BC_INST_POP_EXEC, \
- &&lbl_BC_INST_EXECUTE, \
- &&lbl_BC_INST_EXEC_COND, \
- &&lbl_BC_INST_PRINT_STACK, \
- &&lbl_BC_INST_CLEAR_STACK, \
- &&lbl_BC_INST_REG_STACK_LEN, \
- &&lbl_BC_INST_STACK_LEN, \
- &&lbl_BC_INST_DUPLICATE, \
- &&lbl_BC_INST_LOAD, \
- &&lbl_BC_INST_PUSH_VAR, \
- &&lbl_BC_INST_PUSH_TO_VAR, \
- &&lbl_BC_INST_QUIT, \
- &&lbl_BC_INST_NQUIT, \
- &&lbl_BC_INST_EXEC_STACK_LEN, \
- &&lbl_BC_INST_INVALID, \
+#define BC_PROG_LBLS \
+ static const void* const bc_program_inst_lbls[] = { \
+ &&lbl_BC_INST_NEG, &&lbl_BC_INST_BOOL_NOT, \
+ &&lbl_BC_INST_POWER, &&lbl_BC_INST_MULTIPLY, \
+ &&lbl_BC_INST_DIVIDE, &&lbl_BC_INST_MODULUS, \
+ &&lbl_BC_INST_PLUS, &&lbl_BC_INST_MINUS, \
+ &&lbl_BC_INST_REL_EQ, &&lbl_BC_INST_REL_LE, \
+ &&lbl_BC_INST_REL_GE, &&lbl_BC_INST_REL_NE, \
+ &&lbl_BC_INST_REL_LT, &&lbl_BC_INST_REL_GT, \
+ &&lbl_BC_INST_BOOL_OR, &&lbl_BC_INST_BOOL_AND, \
+ &&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM, \
+ &&lbl_BC_INST_VAR, &&lbl_BC_INST_ARRAY_ELEM, \
+ &&lbl_BC_INST_ARRAY, &&lbl_BC_INST_ZERO, \
+ &&lbl_BC_INST_ONE, &&lbl_BC_INST_IBASE, \
+ &&lbl_BC_INST_OBASE, &&lbl_BC_INST_SCALE, \
+ &&lbl_BC_INST_LENGTH, &&lbl_BC_INST_SCALE_FUNC, \
+ &&lbl_BC_INST_SQRT, &&lbl_BC_INST_ABS, \
+ &&lbl_BC_INST_IS_NUMBER, &&lbl_BC_INST_IS_STRING, \
+ &&lbl_BC_INST_ASCIIFY, &&lbl_BC_INST_READ, \
+ &&lbl_BC_INST_MAXIBASE, &&lbl_BC_INST_MAXOBASE, \
+ &&lbl_BC_INST_MAXSCALE, &&lbl_BC_INST_LINE_LENGTH, \
+ &&lbl_BC_INST_LEADING_ZERO, &&lbl_BC_INST_PRINT, \
+ &&lbl_BC_INST_PRINT_POP, &&lbl_BC_INST_STR, \
+ &&lbl_BC_INST_POP, &&lbl_BC_INST_SWAP, \
+ &&lbl_BC_INST_MODEXP, &&lbl_BC_INST_DIVMOD, \
+ &&lbl_BC_INST_PRINT_STREAM, &&lbl_BC_INST_EXTENDED_REGISTERS, \
+ &&lbl_BC_INST_POP_EXEC, &&lbl_BC_INST_EXECUTE, \
+ &&lbl_BC_INST_EXEC_COND, &&lbl_BC_INST_PRINT_STACK, \
+ &&lbl_BC_INST_CLEAR_STACK, &&lbl_BC_INST_REG_STACK_LEN, \
+ &&lbl_BC_INST_STACK_LEN, &&lbl_BC_INST_DUPLICATE, \
+ &&lbl_BC_INST_LOAD, &&lbl_BC_INST_PUSH_VAR, \
+ &&lbl_BC_INST_PUSH_TO_VAR, &&lbl_BC_INST_QUIT, \
+ &&lbl_BC_INST_NQUIT, &&lbl_BC_INST_EXEC_STACK_LEN, \
+ &&lbl_BC_INST_INVALID, \
}
#endif // BC_ENABLE_EXTRA_MATH
diff --git a/include/version.h b/include/version.h
index a443280c..daa1977c 100644
--- a/include/version.h
+++ b/include/version.h
@@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
-#define VERSION 6.2.5
+#define VERSION 6.5.0
#endif // BC_VERSION_H
diff --git a/include/vm.h b/include/vm.h
index dd21d43f..c56cc8e7 100644
--- a/include/vm.h
+++ b/include/vm.h
@@ -560,9 +560,13 @@ typedef struct BcVm
/// The vector for creating strings to pass to the client.
BcVec out;
+#if BC_ENABLE_EXTRA_MATH
+
/// The PRNG.
BcRNG rng;
+#endif // BC_ENABLE_EXTRA_MATH
+
/// The current error.
BclError err;
diff --git a/manuals/bc.1.md.in b/manuals/bc.1.md.in
index a2e6d086..a4bea761 100644
--- a/manuals/bc.1.md.in
+++ b/manuals/bc.1.md.in
@@ -418,7 +418,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
@@ -1359,6 +1359,10 @@ The extended library is a **non-portable extension**.
: Returns the combination of the truncated absolute value of **n** of the
truncated absolute value of **k**, if **k \<= n**. If not, it returns **0**.
+**fib(n)**
+
+: Returns the Fibonacci number of the truncated absolute value of **n**.
+
**l2(x)**
: Returns the logarithm base **2** of **x**.
diff --git a/manuals/bc/A.1 b/manuals/bc/A.1
index b1996a1f..5de2d352 100644
--- a/manuals/bc/A.1
+++ b/manuals/bc/A.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -477,8 +477,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/A.1.md b/manuals/bc/A.1.md
index e7b4c821..3f34f451 100644
--- a/manuals/bc/A.1.md
+++ b/manuals/bc/A.1.md
@@ -372,7 +372,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/E.1 b/manuals/bc/E.1
index fea1cecd..ecb8b128 100644
--- a/manuals/bc/E.1
+++ b/manuals/bc/E.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -433,8 +433,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/E.1.md b/manuals/bc/E.1.md
index 3631267f..5411dcf6 100644
--- a/manuals/bc/E.1.md
+++ b/manuals/bc/E.1.md
@@ -344,7 +344,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/EH.1 b/manuals/bc/EH.1
index 2a36cab7..507e7f4a 100644
--- a/manuals/bc/EH.1
+++ b/manuals/bc/EH.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -433,8 +433,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/EH.1.md b/manuals/bc/EH.1.md
index f2f49ea7..6f4c4326 100644
--- a/manuals/bc/EH.1.md
+++ b/manuals/bc/EH.1.md
@@ -344,7 +344,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/EHN.1 b/manuals/bc/EHN.1
index 75768a03..e00fcd57 100644
--- a/manuals/bc/EHN.1
+++ b/manuals/bc/EHN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -433,8 +433,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/EHN.1.md b/manuals/bc/EHN.1.md
index a38503cc..6f7a3321 100644
--- a/manuals/bc/EHN.1.md
+++ b/manuals/bc/EHN.1.md
@@ -344,7 +344,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/EN.1 b/manuals/bc/EN.1
index 9c015858..ea842eac 100644
--- a/manuals/bc/EN.1
+++ b/manuals/bc/EN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -433,8 +433,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/EN.1.md b/manuals/bc/EN.1.md
index 28b558d8..189193bf 100644
--- a/manuals/bc/EN.1.md
+++ b/manuals/bc/EN.1.md
@@ -344,7 +344,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/H.1 b/manuals/bc/H.1
index cbd93da0..d477dc8a 100644
--- a/manuals/bc/H.1
+++ b/manuals/bc/H.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -477,8 +477,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/H.1.md b/manuals/bc/H.1.md
index ac35def9..2cb0b4eb 100644
--- a/manuals/bc/H.1.md
+++ b/manuals/bc/H.1.md
@@ -372,7 +372,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/HN.1 b/manuals/bc/HN.1
index 5893d2a7..10d9621c 100644
--- a/manuals/bc/HN.1
+++ b/manuals/bc/HN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -477,8 +477,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/HN.1.md b/manuals/bc/HN.1.md
index 82a99add..25f136a2 100644
--- a/manuals/bc/HN.1.md
+++ b/manuals/bc/HN.1.md
@@ -372,7 +372,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bc/N.1 b/manuals/bc/N.1
index 791f4740..f39e5127 100644
--- a/manuals/bc/N.1
+++ b/manuals/bc/N.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH NAME
@@ -477,8 +477,8 @@ Makes bc(1) print all numbers greater than \f[B]-1\f[R] and less than
.RS
.PP
This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
+\f[B]plznl(x)\f[R], \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions
+in the extended math library (see the \f[B]LIBRARY\f[R] section).
.PP
This is a \f[B]non-portable extension\f[R].
.RE
diff --git a/manuals/bc/N.1.md b/manuals/bc/N.1.md
index b8339ea3..56a4b227 100644
--- a/manuals/bc/N.1.md
+++ b/manuals/bc/N.1.md
@@ -372,7 +372,7 @@ The following are the options that bc(1) accepts.
: Makes bc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
+ This can be set for individual numbers with the **plz(x)**, **plznl(x)**,
**pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
the **LIBRARY** section).
diff --git a/manuals/bcl.3 b/manuals/bcl.3
index 6bebaa8f..cb65a2b8 100644
--- a/manuals/bcl.3
+++ b/manuals/bcl.3
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "BCL" "3" "October 2022" "Gavin D. Howard" "Libraries Manual"
+.TH "BCL" "3" "February 2023" "Gavin D. Howard" "Libraries Manual"
.nh
.ad l
.SH NAME
@@ -139,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
@@ -150,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.
@@ -209,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
@@ -608,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]
@@ -644,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].
@@ -665,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
@@ -681,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]
@@ -712,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
@@ -735,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
@@ -761,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
@@ -788,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
@@ -815,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.
@@ -851,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.
@@ -879,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.
@@ -907,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
@@ -931,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
@@ -959,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
@@ -991,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]
@@ -1060,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.
@@ -1112,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
@@ -1158,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
@@ -1253,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]
diff --git a/manuals/bcl.3.md b/manuals/bcl.3.md
index 6c6967b4..fa566d16 100644
--- a/manuals/bcl.3.md
+++ b/manuals/bcl.3.md
@@ -136,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
@@ -146,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.
@@ -195,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_**);**
@@ -548,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_**)**
@@ -578,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
@@ -595,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*.
@@ -609,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**
@@ -632,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
@@ -649,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
@@ -668,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
@@ -688,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
@@ -708,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.
@@ -733,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
@@ -753,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
@@ -773,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
@@ -791,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
@@ -813,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
@@ -835,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_**)**
@@ -891,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.
@@ -921,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.
@@ -956,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.
@@ -974,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.
@@ -1046,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.
}
diff --git a/manuals/dc.1.md.in b/manuals/dc.1.md.in
index fc02e9d3..9e1e6ccf 100644
--- a/manuals/dc.1.md.in
+++ b/manuals/dc.1.md.in
@@ -231,10 +231,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -1127,6 +1123,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/A.1 b/manuals/dc/A.1
index 13ed8c4c..bef54876 100644
--- a/manuals/dc/A.1
+++ b/manuals/dc/A.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -271,10 +271,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1255,6 +1251,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/A.1.md b/manuals/dc/A.1.md
index b656650c..44b1578b 100644
--- a/manuals/dc/A.1.md
+++ b/manuals/dc/A.1.md
@@ -224,10 +224,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -1087,6 +1083,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/E.1 b/manuals/dc/E.1
index 3fb69dfe..41de5e08 100644
--- a/manuals/dc/E.1
+++ b/manuals/dc/E.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -256,10 +256,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1040,6 +1036,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/E.1.md b/manuals/dc/E.1.md
index 0bbe9761..8a172d8a 100644
--- a/manuals/dc/E.1.md
+++ b/manuals/dc/E.1.md
@@ -215,10 +215,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -918,6 +914,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/EH.1 b/manuals/dc/EH.1
index da7776ed..08cb483d 100644
--- a/manuals/dc/EH.1
+++ b/manuals/dc/EH.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -256,10 +256,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1040,6 +1036,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/EH.1.md b/manuals/dc/EH.1.md
index 0751d3f7..1c5b6f56 100644
--- a/manuals/dc/EH.1.md
+++ b/manuals/dc/EH.1.md
@@ -215,10 +215,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -918,6 +914,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/EHN.1 b/manuals/dc/EHN.1
index 10ef283e..efeb0bba 100644
--- a/manuals/dc/EHN.1
+++ b/manuals/dc/EHN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -256,10 +256,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1040,6 +1036,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/EHN.1.md b/manuals/dc/EHN.1.md
index 9ba7fe13..8a3c6d2b 100644
--- a/manuals/dc/EHN.1.md
+++ b/manuals/dc/EHN.1.md
@@ -215,10 +215,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -918,6 +914,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/EN.1 b/manuals/dc/EN.1
index abdcbe8c..ce1e6b9b 100644
--- a/manuals/dc/EN.1
+++ b/manuals/dc/EN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -256,10 +256,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1040,6 +1036,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/EN.1.md b/manuals/dc/EN.1.md
index 5c0590c5..f8deee53 100644
--- a/manuals/dc/EN.1.md
+++ b/manuals/dc/EN.1.md
@@ -215,10 +215,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -918,6 +914,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/H.1 b/manuals/dc/H.1
index c96100e5..8baa0b74 100644
--- a/manuals/dc/H.1
+++ b/manuals/dc/H.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -271,10 +271,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1255,6 +1251,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/H.1.md b/manuals/dc/H.1.md
index 0dddf66d..7166c155 100644
--- a/manuals/dc/H.1.md
+++ b/manuals/dc/H.1.md
@@ -224,10 +224,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -1087,6 +1083,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/HN.1 b/manuals/dc/HN.1
index a6644ecd..2a392630 100644
--- a/manuals/dc/HN.1
+++ b/manuals/dc/HN.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -271,10 +271,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1255,6 +1251,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/HN.1.md b/manuals/dc/HN.1.md
index d39a7497..6239a12b 100644
--- a/manuals/dc/HN.1.md
+++ b/manuals/dc/HN.1.md
@@ -224,10 +224,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -1087,6 +1083,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/dc/N.1 b/manuals/dc/N.1
index f9aeb1ac..b7b501fb 100644
--- a/manuals/dc/N.1
+++ b/manuals/dc/N.1
@@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
.SH Name
@@ -271,10 +271,6 @@ Makes dc(1) print all numbers greater than \f[B]-1\f[R] and less than
\f[B]1\f[R], and not equal to \f[B]0\f[R], with a leading zero.
.RS
.PP
-This can be set for individual numbers with the \f[B]plz(x)\f[R],
-plznl(x)**, \f[B]pnlz(x)\f[R], and \f[B]pnlznl(x)\f[R] functions in the
-extended math library (see the \f[B]LIBRARY\f[R] section).
-.PP
This is a \f[B]non-portable extension\f[R].
.RE
.PP
@@ -1255,6 +1251,12 @@ section).
Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the
\f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack.
.TP
+\f[B]gx\f[R]
+Pushes \f[B]1\f[R] onto the stack if extended register mode is on,
+\f[B]0\f[R] otherwise.
+See the \f[I]Extended Register Mode\f[R] subsection of the
+\f[B]REGISTERS\f[R] section for more information.
+.TP
\f[B]gz\f[R]
Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not
been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options
diff --git a/manuals/dc/N.1.md b/manuals/dc/N.1.md
index 3c36661d..8795d947 100644
--- a/manuals/dc/N.1.md
+++ b/manuals/dc/N.1.md
@@ -224,10 +224,6 @@ The following are the options that dc(1) accepts.
: Makes dc(1) print all numbers greater than **-1** and less than **1**, and
not equal to **0**, with a leading zero.
- This can be set for individual numbers with the **plz(x)**, plznl(x)**,
- **pnlz(x)**, and **pnlznl(x)** functions in the extended math library (see
- the **LIBRARY** section).
-
This is a **non-portable extension**.
All long options are **non-portable extensions**.
@@ -1087,6 +1083,12 @@ other character produces a parse error (see the **ERRORS** section).
: Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT
VARIABLES** section) onto the stack.
+**gx**
+
+: Pushes **1** onto the stack if extended register mode is on, **0**
+ otherwise. See the *Extended Register Mode* subsection of the **REGISTERS**
+ section for more information.
+
**gz**
: Pushes **0** onto the stack if the leading zero setting has not been enabled
diff --git a/manuals/development.md b/manuals/development.md
index 297fbd89..333538df 100644
--- a/manuals/development.md
+++ b/manuals/development.md
@@ -1,6 +1,6 @@
# Development
-Updated: 13 Feb 2023
+Updated: 13 Mar 2023
This document is meant for the day when I (Gavin D. Howard) get [hit by a
bus][1]. In other words, it's meant to make the [bus factor][1] a non-issue.
@@ -65,6 +65,8 @@ about things like fuzzing, [`scan-build`][19], [valgrind][20],
[AddressSanitizer][21] (and the other sanitizers), and many other things.
One of my happiest moments was when my `bc` was made the default in FreeBSD.
+Another happiest moment was when I found out that my `bc` had shipped with Mac
+OSX Ventura, without my knowledge.
But since I believe in [finishing the software I write][22], I have done less
work on `bc` over time, though there are still times when I put a lot of effort
@@ -894,6 +896,8 @@ data structures.
Vectors are what do the heavy lifting in almost all of `bc`'s data structures.
Even the maps of identifiers and arrays use vectors.
+The code associated with this header is in [`src/vector.c`][228].
+
#### `version.h`
This header defines the version of `bc`.
@@ -1057,7 +1061,9 @@ template, and the manpage generated from the markdown version.
### `scripts/`
This folder contains helper scripts. Most of them are written in pure [POSIX
-`sh`][72], but one ([`karatsuba.py`][78]) is written in Python 3.
+`sh`][72], but three ([`afl.py`][94], [`karatsuba.py`][78], and
+[`randmath.py`][95]) are written in Python 3, and one ([`ministat.c`][223]) is
+written in C. [`ministat.c`][223] in particular is copied from elsewhere.
For more information about the shell scripts, see [POSIX Shell Scripts][76].
@@ -2051,7 +2057,7 @@ directory of all other test directories for each calculator.
#### `bc` Standard Tests
-The list of current (17 July 2022) standard tests for `bc` is below:
+The list of current (27 February 2023) standard tests for `bc` is below:
decimal
@@ -2205,6 +2211,10 @@ bessel
: Tests the `j()` function in the math library.
+fib
+
+: Tests the `fib()` Fibonacci function in the extended math library.
+
arrays
: Test arrays.
@@ -2305,7 +2315,7 @@ line_loop_quit2
#### `dc` Standard Tests
-The list of current (17 July 2022) standard tests for `dc` is below:
+The list of current (27 February 2023) standard tests for `dc` is below:
decimal
@@ -2465,7 +2475,7 @@ to put it on the same line as others.
#### `bc` Script Tests
-The list of current (17 July 2022) script tests for `bc` is below:
+The list of current (27 February 2023) script tests for `bc` is below:
print.bc
@@ -2491,6 +2501,11 @@ parse.bc
: Tests parsing even harder than the parse standard test.
+root.bc
+
+: Tests that `root()` and `cbrt()` do not go into an infinite loop on a
+ pathological case found by a user.
+
array.bc
: Tests arrays even harder than the arrays standard test.
@@ -2549,7 +2564,7 @@ ifs2.bc
#### `dc` Script Tests
-The list of current (17 July 2022) script tests for `dc` is below:
+The list of current (27 February 2023) script tests for `dc` is below:
prime.dc
@@ -5207,3 +5222,4 @@ However, where possible, errors are returned directly.
[225]: #allsh
[226]: #errorssh
[227]: #errorsh
+[228]: #vectorc
diff --git a/manuals/header_bc.txt b/manuals/header_bc.txt
index c50a8619..1f69d328 100644
--- a/manuals/header_bc.txt
+++ b/manuals/header_bc.txt
@@ -1,3 +1,3 @@
-.TH "BC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "BC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
diff --git a/manuals/header_bcl.txt b/manuals/header_bcl.txt
index 72b8dc7e..3b436817 100644
--- a/manuals/header_bcl.txt
+++ b/manuals/header_bcl.txt
@@ -1,3 +1,3 @@
-.TH "BCL" "3" "October 2022" "Gavin D. Howard" "Libraries Manual"
+.TH "BCL" "3" "February 2023" "Gavin D. Howard" "Libraries Manual"
.nh
.ad l
diff --git a/manuals/header_dc.txt b/manuals/header_dc.txt
index 311b9cb3..db82bfb6 100644
--- a/manuals/header_dc.txt
+++ b/manuals/header_dc.txt
@@ -1,3 +1,3 @@
-.TH "DC" "1" "October 2022" "Gavin D. Howard" "General Commands Manual"
+.TH "DC" "1" "February 2023" "Gavin D. Howard" "General Commands Manual"
.nh
.ad l
diff --git a/scripts/exec-install.sh b/scripts/exec-install.sh
index 3b9375af..8180b29c 100755
--- a/scripts/exec-install.sh
+++ b/scripts/exec-install.sh
@@ -60,6 +60,12 @@ fi
# If it's a symlink, create an equivalent in the install directory.
for exe in $bindir/*; do
+ # Skip any directories in case the bin/ directory is also used as the
+ # prefix.
+ if [ -d "$exe" ]; then
+ continue
+ fi
+
base=$(basename "$exe")
if [ -L "$exe" ]; then
diff --git a/scripts/fuzz_prep.sh b/scripts/fuzz_prep.sh
index 107cf4cf..2c57d94a 100755
--- a/scripts/fuzz_prep.sh
+++ b/scripts/fuzz_prep.sh
@@ -57,11 +57,12 @@ asan=0
while getopts "a" opt; do
case "$opt" in
- a) asan=1 ; shift ;;
+ a) asan=1 ;;
?) usage "Invalid option: $opt" ;;
esac
done
+shift $(($OPTIND - 1))
if [ $# -lt 1 ]; then
CC=afl-clang-lto
@@ -76,10 +77,10 @@ cd "$scriptdir/.."
set -e
+CFLAGS="-flto -fstack-protector-all -fsanitize=shadow-call-stack -ffixed-x18 -fsanitize=cfi -fvisibility=hidden"
+
if [ "$asan" -ne 0 ]; then
- CFLAGS="-flto -fsanitize=address"
-else
- CFLAGS="-flto"
+ CFLAGS="$CFLAGS -fsanitize=address"
fi
# We want a debug build because asserts are counted as crashes too.
diff --git a/scripts/locale_install.sh b/scripts/locale_install.sh
index 75534a73..3816f54e 100755
--- a/scripts/locale_install.sh
+++ b/scripts/locale_install.sh
@@ -184,11 +184,12 @@ all_locales=0
while getopts "l" opt; do
case "$opt" in
- l) all_locales=1 ; shift ;;
+ l) all_locales=1 ;;
?) usage "Invalid option: $opt" ;;
esac
done
+shift $(($OPTIND - 1))
test "$#" -ge 2 || usage "Must have at least two arguments"
diff --git a/scripts/safe-install.sh b/scripts/safe-install.sh
index 04108838..5774a17e 100755
--- a/scripts/safe-install.sh
+++ b/scripts/safe-install.sh
@@ -41,7 +41,7 @@ set -e
if test "$mkdirp" ; then
umask 022
-case "$2" in
+case "$dst" in
*/*) mkdir -p "${dst%/*}" ;;
esac
fi
@@ -51,15 +51,15 @@ trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP
umask 077
if test "$symlink" ; then
-ln -s "$1" "$tmp"
+ln -s "$src" "$tmp"
else
-cat < "$1" > "$tmp"
+cat < "$src" > "$tmp"
chmod "$mode" "$tmp"
fi
-mv -f "$tmp" "$2"
-test -d "$2" && {
-rm -f "$2/$tmp"
+mv -f "$tmp" "$dst"
+test -d "$dst" && {
+rm -f "$dst/$tmp"
printf "%s: %s is a directory\n" "$0" "$dst" 1>&2
exit 1
}
diff --git a/src/bc_parse.c b/src/bc_parse.c
index 13e03a49..4cf886ef 100644
--- a/src/bc_parse.c
+++ b/src/bc_parse.c
@@ -1888,6 +1888,7 @@ bc_parse_stmt(BcParse* p)
case BC_LEX_KW_AUTO:
case BC_LEX_KW_DEFINE:
#if DC_ENABLED
+ case BC_LEX_EXTENDED_REGISTERS:
case BC_LEX_EQ_NO_REG:
case BC_LEX_COLON:
case BC_LEX_EXECUTE:
@@ -2436,6 +2437,7 @@ bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next)
case BC_LEX_KW_STREAM:
case BC_LEX_KW_ELSE:
#if DC_ENABLED
+ case BC_LEX_EXTENDED_REGISTERS:
case BC_LEX_EQ_NO_REG:
case BC_LEX_COLON:
case BC_LEX_EXECUTE:
diff --git a/src/data.c b/src/data.c
index 5eb34bdb..b57e1fc4 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1151,47 +1151,60 @@ const uchar dc_parse_insts[] = {
#if BC_ENABLE_EXTRA_MATH
BC_INST_TRUNC,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE,
- BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS,
+ BC_INST_POWER, BC_INST_MULTIPLY,
+ BC_INST_DIVIDE, BC_INST_MODULUS,
+ BC_INST_PLUS, BC_INST_MINUS,
#if BC_ENABLE_EXTRA_MATH
- BC_INST_PLACES, BC_INST_LSHIFT, BC_INST_RSHIFT,
+ BC_INST_PLACES, BC_INST_LSHIFT,
+ BC_INST_RSHIFT,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
BC_INST_BOOL_OR, BC_INST_BOOL_AND,
#if BC_ENABLED
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
#if BC_ENABLE_EXTRA_MATH
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID,
#endif // BC_ENABLE_EXTRA_MATH
#endif // BC_ENABLED
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_REL_GT, BC_INST_REL_LT, BC_INST_INVALID,
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
- BC_INST_INVALID, BC_INST_REL_LE, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_REL_GT,
+ BC_INST_REL_LT, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_REL_GE, BC_INST_INVALID,
+ BC_INST_REL_LE, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID,
#if BC_ENABLED
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID,
#endif // BC_ENABLED
- BC_INST_IBASE, BC_INST_OBASE, BC_INST_SCALE,
+ BC_INST_IBASE, BC_INST_OBASE,
+ BC_INST_SCALE,
#if BC_ENABLE_EXTRA_MATH
BC_INST_SEED,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_LENGTH, BC_INST_PRINT, BC_INST_SQRT,
- BC_INST_ABS, BC_INST_IS_NUMBER, BC_INST_IS_STRING,
+ BC_INST_LENGTH, BC_INST_PRINT,
+ BC_INST_SQRT, BC_INST_ABS,
+ BC_INST_IS_NUMBER, BC_INST_IS_STRING,
#if BC_ENABLE_EXTRA_MATH
BC_INST_IRAND,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_ASCIIFY, BC_INST_MODEXP, BC_INST_DIVMOD,
- BC_INST_QUIT, BC_INST_INVALID,
+ BC_INST_ASCIIFY, BC_INST_MODEXP,
+ BC_INST_DIVMOD, BC_INST_QUIT,
+ BC_INST_INVALID,
#if BC_ENABLE_EXTRA_MATH
BC_INST_RAND,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_MAXIBASE, BC_INST_MAXOBASE, BC_INST_MAXSCALE,
+ BC_INST_MAXIBASE, BC_INST_MAXOBASE,
+ BC_INST_MAXSCALE,
#if BC_ENABLE_EXTRA_MATH
BC_INST_MAXRAND,
#endif // BC_ENABLE_EXTRA_MATH
@@ -1199,17 +1212,21 @@ const uchar dc_parse_insts[] = {
#if BC_ENABLED
BC_INST_INVALID,
#endif // BC_ENABLED
- BC_INST_LEADING_ZERO, BC_INST_PRINT_STREAM, BC_INST_INVALID,
- BC_INST_REL_EQ, BC_INST_INVALID, BC_INST_EXECUTE,
- BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, BC_INST_INVALID,
- BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP,
- BC_INST_POP, BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_LEADING_ZERO, BC_INST_PRINT_STREAM,
+ BC_INST_INVALID, BC_INST_EXTENDED_REGISTERS,
+ BC_INST_REL_EQ, BC_INST_INVALID,
+ BC_INST_EXECUTE, BC_INST_PRINT_STACK,
+ BC_INST_CLEAR_STACK, BC_INST_INVALID,
+ BC_INST_STACK_LEN, BC_INST_DUPLICATE,
+ BC_INST_SWAP, BC_INST_POP,
+ BC_INST_INVALID, BC_INST_INVALID,
BC_INST_INVALID,
#if BC_ENABLE_EXTRA_MATH
BC_INST_INVALID,
#endif // BC_ENABLE_EXTRA_MATH
- BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
- BC_INST_PRINT_POP, BC_INST_NQUIT, BC_INST_EXEC_STACK_LEN,
+ BC_INST_INVALID, BC_INST_INVALID,
+ BC_INST_INVALID, BC_INST_PRINT_POP,
+ BC_INST_NQUIT, BC_INST_EXEC_STACK_LEN,
BC_INST_SCALE_FUNC, BC_INST_INVALID,
};
#endif // DC_ENABLED
diff --git a/src/dc_lex.c b/src/dc_lex.c
index cf737ea3..963e3f13 100644
--- a/src/dc_lex.c
+++ b/src/dc_lex.c
@@ -278,6 +278,7 @@ dc_lex_token(BcLex* l)
c2 = l->buf[l->i];
if (c2 == 'l') l->t = BC_LEX_KW_LINE_LENGTH;
+ else if (c2 == 'x') l->t = BC_LEX_EXTENDED_REGISTERS;
else if (c2 == 'z') l->t = BC_LEX_KW_LEADING_ZERO;
else bc_lex_invalidChar(l, c2);
diff --git a/src/dc_parse.c b/src/dc_parse.c
index 638ccfb7..2a6f387a 100644
--- a/src/dc_parse.c
+++ b/src/dc_parse.c
@@ -349,6 +349,7 @@ dc_parse_token(BcParse* p, BcLexType t, uint8_t flags)
case BC_LEX_KW_LEADING_ZERO:
case BC_LEX_KW_STREAM:
case BC_LEX_KW_ELSE:
+ case BC_LEX_EXTENDED_REGISTERS:
case BC_LEX_EQ_NO_REG:
case BC_LEX_EXECUTE:
case BC_LEX_PRINT_STACK:
diff --git a/src/library.c b/src/library.c
index 6283d198..cc32a3a3 100644
--- a/src/library.c
+++ b/src/library.c
@@ -60,6 +60,28 @@
// cannot assume that allocation failures are fatal. So we have to reset the
// jumps every time to ensure that the locals will be correct after jumping.
+#if BC_ENABLE_MEMCHECK
+
+BC_NORETURN void
+bcl_invalidGeneration(void)
+{
+ abort();
+}
+
+BC_NORETURN void
+bcl_nonexistentNum(void)
+{
+ abort();
+}
+
+BC_NORETURN void
+bcl_numIdxOutOfRange(void)
+{
+ abort();
+}
+
+#endif // BC_ENABLE_MEMCHECK
+
static BclTls* tls = NULL;
static BclTls tls_real;
@@ -195,10 +217,14 @@ bcl_init(void)
bc_vec_init(&vm->ctxts, sizeof(BclContext), BC_DTOR_NONE);
bc_vec_init(&vm->out, sizeof(uchar), BC_DTOR_NONE);
- // We need to seed this in case /dev/random and /dev/urandm don't work.
+#if BC_ENABLE_EXTRA_MATH
+
+ // We need to seed this in case /dev/random and /dev/urandom don't work.
srand((unsigned int) time(NULL));
bc_rand_init(&vm->rng);
+#endif // BC_ENABLE_EXTRA_MATH
+
err:
BC_FUNC_FOOTER(vm, e);
@@ -227,6 +253,7 @@ bcl_pushContext(BclContext ctxt)
bc_vec_push(&vm->ctxts, &ctxt);
err:
+
BC_FUNC_FOOTER(vm, e);
return e;
}
@@ -262,7 +289,9 @@ bcl_free(void)
vm->refs -= 1;
if (vm->refs) return;
+#if BC_ENABLE_EXTRA_MATH
bc_rand_free(&vm->rng);
+#endif // BC_ENABLE_EXTRA_MATH
bc_vec_free(&vm->out);
for (i = 0; i < vm->ctxts.len; ++i)
@@ -363,7 +392,7 @@ bcl_ctxt_create(void)
// malloc() is appropriate here.
ctxt = bc_vm_malloc(sizeof(BclCtxt));
- bc_vec_init(&ctxt->nums, sizeof(BcNum), BC_DTOR_BCL_NUM);
+ bc_vec_init(&ctxt->nums, sizeof(BclNum), BC_DTOR_BCL_NUM);
bc_vec_init(&ctxt->free_nums, sizeof(BclNumber), BC_DTOR_NONE);
ctxt->scale = 0;
@@ -445,6 +474,10 @@ bcl_err(BclNumber n)
BC_CHECK_CTXT_ERR(vm, ctxt);
+ // We need to clear the top byte in memcheck mode. We can do this because
+ // the parameter is a copy.
+ BCL_CLEAR_GEN(n);
+
// Errors are encoded as (0 - error_code). If the index is in that range, it
// is an encoded error.
if (n.i >= ctxt->nums.len)
@@ -462,14 +495,14 @@ bcl_err(BclNumber n)
* @return The resulting BclNumber from the insert.
*/
static BclNumber
-bcl_num_insert(BclContext ctxt, BcNum* restrict n)
+bcl_num_insert(BclContext ctxt, BclNum* restrict n)
{
BclNumber idx;
// If there is a free spot...
if (ctxt->free_nums.len)
{
- BcNum* ptr;
+ BclNum* ptr;
// Get the index of the free spot and remove it.
idx = *((BclNumber*) bc_vec_top(&ctxt->free_nums));
@@ -477,11 +510,30 @@ bcl_num_insert(BclContext ctxt, BcNum* restrict n)
// Copy the number into the spot.
ptr = bc_vec_item(&ctxt->nums, idx.i);
- memcpy(ptr, n, sizeof(BcNum));
+
+ memcpy(BCL_NUM_NUM(ptr), n, sizeof(BcNum));
+
+#if BC_ENABLE_MEMCHECK
+
+ ptr->gen_idx += 1;
+
+ if (ptr->gen_idx == UCHAR_MAX)
+ {
+ ptr->gen_idx = 0;
+ }
+
+ idx.i |= (ptr->gen_idx << ((sizeof(size_t) - 1) * CHAR_BIT));
+
+#endif // BC_ENABLE_MEMCHECK
}
else
{
- // Just push the number onto the vector.
+#if BC_ENABLE_MEMCHECK
+ n->gen_idx = 0;
+#endif // BC_ENABLE_MEMCHECK
+
+ // Just push the number onto the vector because the generation index is
+ // 0.
idx.i = ctxt->nums.len;
bc_vec_push(&ctxt->nums, n);
}
@@ -493,7 +545,7 @@ BclNumber
bcl_num_create(void)
{
BclError e = BCL_ERROR_NONE;
- BcNum n;
+ BclNum n;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -502,11 +554,12 @@ bcl_num_create(void)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- bc_num_init(&n, BC_NUM_DEF_SIZE);
+ bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
err:
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
@@ -520,26 +573,34 @@ err:
* @param num The number to destroy.
*/
static void
-bcl_num_dtor(BclContext ctxt, BclNumber n, BcNum* restrict num)
+bcl_num_dtor(BclContext ctxt, BclNumber n, BclNum* restrict num)
{
- assert(num != NULL && num->num != NULL);
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
+
+ BCL_CLEAR_GEN(n);
bcl_num_destruct(num);
bc_vec_push(&ctxt->free_nums, &n);
+
+#if BC_ENABLE_MEMCHECK
+ num->n.num = NULL;
+#endif // BC_ENABLE_MEMCHECK
}
void
bcl_num_free(BclNumber n)
{
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- num = BC_NUM(ctxt, n);
+ num = BCL_NUM(ctxt, n);
bcl_num_dtor(ctxt, n, num);
}
@@ -548,26 +609,31 @@ BclError
bcl_copy(BclNumber d, BclNumber s)
{
BclError e = BCL_ERROR_NONE;
- BcNum* dest;
- BcNum* src;
+ BclNum* dest;
+ BclNum* src;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ERR(vm, ctxt);
+ BCL_CHECK_NUM_VALID(ctxt, d);
+ BCL_CHECK_NUM_VALID(ctxt, s);
+
BC_FUNC_HEADER(vm, err);
- assert(d.i < ctxt->nums.len && s.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(d) < ctxt->nums.len);
+ assert(BCL_NO_GEN(s) < ctxt->nums.len);
- dest = BC_NUM(ctxt, d);
- src = BC_NUM(ctxt, s);
+ dest = BCL_NUM(ctxt, d);
+ src = BCL_NUM(ctxt, s);
assert(dest != NULL && src != NULL);
- assert(dest->num != NULL && src->num != NULL);
+ assert(BCL_NUM_ARRAY(dest) != NULL && BCL_NUM_ARRAY(src) != NULL);
- bc_num_copy(dest, src);
+ bc_num_copy(BCL_NUM_NUM(dest), BCL_NUM_NUM(src));
err:
+
BC_FUNC_FOOTER(vm, e);
return e;
@@ -577,28 +643,31 @@ BclNumber
bcl_dup(BclNumber s)
{
BclError e = BCL_ERROR_NONE;
- BcNum *src, dest;
+ BclNum *src, dest;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT(vm, ctxt);
+ BCL_CHECK_NUM_VALID(ctxt, s);
+
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(s.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(s) < ctxt->nums.len);
- src = BC_NUM(ctxt, s);
+ src = BCL_NUM(ctxt, s);
- assert(src != NULL && src->num != NULL);
+ assert(src != NULL && BCL_NUM_NUM(src) != NULL);
// Copy the number.
- bc_num_clear(&dest);
- bc_num_createCopy(&dest, src);
+ bc_num_clear(BCL_NUM_NUM(&dest));
+ bc_num_createCopy(BCL_NUM_NUM(&dest), BCL_NUM_NUM(src));
err:
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, dest, idx);
@@ -608,75 +677,81 @@ err:
void
bcl_num_destruct(void* num)
{
- BcNum* n = (BcNum*) num;
+ BclNum* n = (BclNum*) num;
assert(n != NULL);
- if (n->num == NULL) return;
+ if (BCL_NUM_ARRAY(n) == NULL) return;
- bc_num_free(num);
- bc_num_clear(num);
+ bc_num_free(BCL_NUM_NUM(n));
+ bc_num_clear(BCL_NUM_NUM(n));
}
bool
bcl_num_neg(BclNumber n)
{
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
- num = BC_NUM(ctxt, n);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- assert(num != NULL && num->num != NULL);
+ num = BCL_NUM(ctxt, n);
- return BC_NUM_NEG(num) != 0;
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
+
+ return BC_NUM_NEG(BCL_NUM_NUM(num)) != 0;
}
void
bcl_num_setNeg(BclNumber n, bool neg)
{
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- num = BC_NUM(ctxt, n);
+ num = BCL_NUM(ctxt, n);
- assert(num != NULL && num->num != NULL);
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
- num->rdx = BC_NUM_NEG_VAL(num, neg);
+ BCL_NUM_NUM(num)->rdx = BC_NUM_NEG_VAL(BCL_NUM_NUM(num), neg);
}
size_t
bcl_num_scale(BclNumber n)
{
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- num = BC_NUM(ctxt, n);
+ num = BCL_NUM(ctxt, n);
- assert(num != NULL && num->num != NULL);
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
- return bc_num_scale(num);
+ return bc_num_scale(BCL_NUM_NUM(num));
}
BclError
bcl_num_setScale(BclNumber n, size_t scale)
{
BclError e = BCL_ERROR_NONE;
- BcNum* nptr;
+ BclNum* nptr;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -684,18 +759,27 @@ bcl_num_setScale(BclNumber n, size_t scale)
BC_CHECK_NUM_ERR(ctxt, n);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
BC_FUNC_HEADER(vm, err);
- assert(n.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- nptr = BC_NUM(ctxt, n);
+ nptr = BCL_NUM(ctxt, n);
- assert(nptr != NULL && nptr->num != NULL);
+ assert(nptr != NULL && BCL_NUM_ARRAY(nptr) != NULL);
- if (scale > nptr->scale) bc_num_extend(nptr, scale - nptr->scale);
- else if (scale < nptr->scale) bc_num_truncate(nptr, nptr->scale - scale);
+ if (scale > BCL_NUM_NUM(nptr)->scale)
+ {
+ bc_num_extend(BCL_NUM_NUM(nptr), scale - BCL_NUM_NUM(nptr)->scale);
+ }
+ else if (scale < BCL_NUM_NUM(nptr)->scale)
+ {
+ bc_num_truncate(BCL_NUM_NUM(nptr), BCL_NUM_NUM(nptr)->scale - scale);
+ }
err:
+
BC_FUNC_FOOTER(vm, e);
return e;
@@ -704,54 +788,75 @@ err:
size_t
bcl_num_len(BclNumber n)
{
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
- num = BC_NUM(ctxt, n);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- assert(num != NULL && num->num != NULL);
+ num = BCL_NUM(ctxt, n);
- return bc_num_len(num);
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
+
+ return bc_num_len(BCL_NUM_NUM(num));
}
-BclError
-bcl_bigdig(BclNumber n, BclBigDig* result)
+static BclError
+bcl_bigdig_helper(BclNumber n, BclBigDig* result, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* num;
+ BclNum* num;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ERR(vm, ctxt);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
BC_FUNC_HEADER(vm, err);
- assert(n.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
assert(result != NULL);
- num = BC_NUM(ctxt, n);
+ num = BCL_NUM(ctxt, n);
- assert(num != NULL && num->num != NULL);
+ assert(num != NULL && BCL_NUM_ARRAY(num) != NULL);
- *result = bc_num_bigdig(num);
+ *result = bc_num_bigdig(BCL_NUM_NUM(num));
err:
- bcl_num_dtor(ctxt, n, num);
+
+ if (destruct)
+ {
+ bcl_num_dtor(ctxt, n, num);
+ }
+
BC_FUNC_FOOTER(vm, e);
return e;
}
+BclError
+bcl_bigdig(BclNumber n, BclBigDig* result)
+{
+ return bcl_bigdig_helper(n, result, true);
+}
+
+BclError
+bcl_bigdig_keep(BclNumber n, BclBigDig* result)
+{
+ return bcl_bigdig_helper(n, result, false);
+}
+
BclNumber
bcl_bigdig2num(BclBigDig val)
{
BclError e = BCL_ERROR_NONE;
- BcNum n;
+ BclNum n;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -760,11 +865,12 @@ bcl_bigdig2num(BclBigDig val)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- bc_num_createFromBigdig(&n, val);
+ bc_num_createFromBigdig(BCL_NUM_NUM_NP(n), val);
err:
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
@@ -773,20 +879,22 @@ err:
/**
* Sets up and executes a binary operator operation.
- * @param a The first operand.
- * @param b The second operand.
- * @param op The operation.
- * @param req The function to get the size of the result for preallocation.
- * @return The result of the operation.
+ * @param a The first operand.
+ * @param b The second operand.
+ * @param op The operation.
+ * @param req The function to get the size of the result for
+ * preallocation.
+ * @param destruct True if the parameters should be consumed, false otherwise.
+ * @return The result of the operation.
*/
static BclNumber
bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
- const BcNumBinaryOpReq req)
+ const BcNumBinaryOpReq req, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* aptr;
- BcNum* bptr;
- BcNum c;
+ BclNum* aptr;
+ BclNum* bptr;
+ BclNum c;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -798,27 +906,31 @@ bcl_binary(BclNumber a, BclNumber b, const BcNumBinaryOp op,
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
- bptr = BC_NUM(ctxt, b);
+ aptr = BCL_NUM(ctxt, a);
+ bptr = BCL_NUM(ctxt, b);
assert(aptr != NULL && bptr != NULL);
- assert(aptr->num != NULL && bptr->num != NULL);
+ assert(BCL_NUM_ARRAY(aptr) != NULL && BCL_NUM_ARRAY(bptr) != NULL);
// Clear and initialize the result.
- bc_num_clear(&c);
- bc_num_init(&c, req(aptr, bptr, ctxt->scale));
+ bc_num_clear(BCL_NUM_NUM_NP(c));
+ bc_num_init(BCL_NUM_NUM_NP(c),
+ req(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), ctxt->scale));
- op(aptr, bptr, &c, ctxt->scale);
+ op(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM_NP(c), ctxt->scale);
err:
- // Eat the operands.
- bcl_num_dtor(ctxt, a, aptr);
- if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ if (destruct)
+ {
+ // Eat the operands.
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ }
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, c, idx);
@@ -829,57 +941,105 @@ err:
BclNumber
bcl_add(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_add, bc_num_addReq);
+ return bcl_binary(a, b, bc_num_add, bc_num_addReq, true);
+}
+
+BclNumber
+bcl_add_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_add, bc_num_addReq, false);
}
BclNumber
bcl_sub(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_sub, bc_num_addReq);
+ return bcl_binary(a, b, bc_num_sub, bc_num_addReq, true);
+}
+
+BclNumber
+bcl_sub_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_sub, bc_num_addReq, false);
}
BclNumber
bcl_mul(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_mul, bc_num_mulReq);
+ return bcl_binary(a, b, bc_num_mul, bc_num_mulReq, true);
+}
+
+BclNumber
+bcl_mul_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_mul, bc_num_mulReq, false);
}
BclNumber
bcl_div(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_div, bc_num_divReq);
+ return bcl_binary(a, b, bc_num_div, bc_num_divReq, true);
+}
+
+BclNumber
+bcl_div_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_div, bc_num_divReq, false);
}
BclNumber
bcl_mod(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_mod, bc_num_divReq);
+ return bcl_binary(a, b, bc_num_mod, bc_num_divReq, true);
+}
+
+BclNumber
+bcl_mod_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_mod, bc_num_divReq, false);
}
BclNumber
bcl_pow(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_pow, bc_num_powReq);
+ return bcl_binary(a, b, bc_num_pow, bc_num_powReq, true);
+}
+
+BclNumber
+bcl_pow_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_pow, bc_num_powReq, false);
}
BclNumber
bcl_lshift(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq);
+ return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq, true);
+}
+
+BclNumber
+bcl_lshift_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq, false);
}
BclNumber
bcl_rshift(BclNumber a, BclNumber b)
{
- return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq);
+ return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq, true);
}
BclNumber
-bcl_sqrt(BclNumber a)
+bcl_rshift_keep(BclNumber a, BclNumber b)
+{
+ return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq, false);
+}
+
+static BclNumber
+bcl_sqrt_helper(BclNumber a, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* aptr;
- BcNum b;
+ BclNum* aptr;
+ BclNum b;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -890,30 +1050,48 @@ bcl_sqrt(BclNumber a)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(a.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(a) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
+ aptr = BCL_NUM(ctxt, a);
- bc_num_sqrt(aptr, &b, ctxt->scale);
+ bc_num_sqrt(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), ctxt->scale);
err:
- bcl_num_dtor(ctxt, a, aptr);
+
+ if (destruct)
+ {
+ bcl_num_dtor(ctxt, a, aptr);
+ }
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
return idx;
}
-BclError
-bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
+BclNumber
+bcl_sqrt(BclNumber a)
+{
+ return bcl_sqrt_helper(a, true);
+}
+
+BclNumber
+bcl_sqrt_keep(BclNumber a)
+{
+ return bcl_sqrt_helper(a, false);
+}
+
+static BclError
+bcl_divmod_helper(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d,
+ bool destruct)
{
BclError e = BCL_ERROR_NONE;
size_t req;
- BcNum* aptr;
- BcNum* bptr;
- BcNum cnum, dnum;
+ BclNum* aptr;
+ BclNum* bptr;
+ BclNum cnum, dnum;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -924,41 +1102,45 @@ bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 2);
+ BCL_GROW_NUMS(ctxt);
assert(c != NULL && d != NULL);
- aptr = BC_NUM(ctxt, a);
- bptr = BC_NUM(ctxt, b);
+ aptr = BCL_NUM(ctxt, a);
+ bptr = BCL_NUM(ctxt, b);
assert(aptr != NULL && bptr != NULL);
- assert(aptr->num != NULL && bptr->num != NULL);
+ assert(BCL_NUM_ARRAY(aptr) != NULL && BCL_NUM_ARRAY(bptr) != NULL);
- bc_num_clear(&cnum);
- bc_num_clear(&dnum);
+ bc_num_clear(BCL_NUM_NUM_NP(cnum));
+ bc_num_clear(BCL_NUM_NUM_NP(dnum));
- req = bc_num_divReq(aptr, bptr, ctxt->scale);
+ req = bc_num_divReq(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), ctxt->scale);
// Initialize the numbers.
- bc_num_init(&cnum, req);
+ bc_num_init(BCL_NUM_NUM_NP(cnum), req);
BC_UNSETJMP(vm);
BC_SETJMP(vm, err);
- bc_num_init(&dnum, req);
+ bc_num_init(BCL_NUM_NUM_NP(dnum), req);
- bc_num_divmod(aptr, bptr, &cnum, &dnum, ctxt->scale);
+ bc_num_divmod(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM_NP(cnum),
+ BCL_NUM_NUM_NP(dnum), ctxt->scale);
err:
- // Eat the operands.
- bcl_num_dtor(ctxt, a, aptr);
- if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ if (destruct)
+ {
+ // Eat the operands.
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ }
// If there was an error...
if (BC_ERR(vm->err))
{
// Free the results.
- if (cnum.num != NULL) bc_num_free(&cnum);
- if (dnum.num != NULL) bc_num_free(&dnum);
+ if (BCL_NUM_ARRAY_NP(cnum) != NULL) bc_num_free(&cnum);
+ if (BCL_NUM_ARRAY_NP(cnum) != NULL) bc_num_free(&dnum);
// Make sure the return values are invalid.
c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
@@ -978,15 +1160,27 @@ err:
return e;
}
-BclNumber
-bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
+BclError
+bcl_divmod(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
+{
+ return bcl_divmod_helper(a, b, c, d, true);
+}
+
+BclError
+bcl_divmod_keep(BclNumber a, BclNumber b, BclNumber* c, BclNumber* d)
+{
+ return bcl_divmod_helper(a, b, c, d, false);
+}
+
+static BclNumber
+bcl_modexp_helper(BclNumber a, BclNumber b, BclNumber c, bool destruct)
{
BclError e = BCL_ERROR_NONE;
size_t req;
- BcNum* aptr;
- BcNum* bptr;
- BcNum* cptr;
- BcNum d;
+ BclNum* aptr;
+ BclNum* bptr;
+ BclNum* cptr;
+ BclNum d;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -999,34 +1193,39 @@ bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
- assert(c.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
+ assert(BCL_NO_GEN(c) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
- bptr = BC_NUM(ctxt, b);
- cptr = BC_NUM(ctxt, c);
+ aptr = BCL_NUM(ctxt, a);
+ bptr = BCL_NUM(ctxt, b);
+ cptr = BCL_NUM(ctxt, c);
assert(aptr != NULL && bptr != NULL && cptr != NULL);
- assert(aptr->num != NULL && bptr->num != NULL && cptr->num != NULL);
+ assert(BCL_NUM_NUM(aptr) != NULL && BCL_NUM_NUM(bptr) != NULL &&
+ BCL_NUM_NUM(cptr) != NULL);
// Prepare the result.
- bc_num_clear(&d);
+ bc_num_clear(BCL_NUM_NUM_NP(d));
- req = bc_num_divReq(aptr, cptr, 0);
+ req = bc_num_divReq(BCL_NUM_NUM(aptr), BCL_NUM_NUM(cptr), 0);
// Initialize the result.
- bc_num_init(&d, req);
+ bc_num_init(BCL_NUM_NUM_NP(d), req);
- bc_num_modexp(aptr, bptr, cptr, &d);
+ bc_num_modexp(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr), BCL_NUM_NUM(cptr),
+ BCL_NUM_NUM_NP(d));
err:
- // Eat the operands.
- bcl_num_dtor(ctxt, a, aptr);
- if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
- if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
+ if (destruct)
+ {
+ // Eat the operands.
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
+ }
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, d, idx);
@@ -1034,68 +1233,87 @@ err:
return idx;
}
+BclNumber
+bcl_modexp(BclNumber a, BclNumber b, BclNumber c)
+{
+ return bcl_modexp_helper(a, b, c, true);
+}
+
+BclNumber
+bcl_modexp_keep(BclNumber a, BclNumber b, BclNumber c)
+{
+ return bcl_modexp_helper(a, b, c, false);
+}
+
ssize_t
bcl_cmp(BclNumber a, BclNumber b)
{
- BcNum* aptr;
- BcNum* bptr;
+ BclNum* aptr;
+ BclNum* bptr;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, a);
+ BCL_CHECK_NUM_VALID(ctxt, b);
+
+ assert(BCL_NO_GEN(a) < ctxt->nums.len && BCL_NO_GEN(b) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
- bptr = BC_NUM(ctxt, b);
+ aptr = BCL_NUM(ctxt, a);
+ bptr = BCL_NUM(ctxt, b);
assert(aptr != NULL && bptr != NULL);
- assert(aptr->num != NULL && bptr->num != NULL);
+ assert(BCL_NUM_NUM(aptr) != NULL && BCL_NUM_NUM(bptr));
- return bc_num_cmp(aptr, bptr);
+ return bc_num_cmp(BCL_NUM_NUM(aptr), BCL_NUM_NUM(bptr));
}
void
bcl_zero(BclNumber n)
{
- BcNum* nptr;
+ BclNum* nptr;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
- nptr = BC_NUM(ctxt, n);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- assert(nptr != NULL && nptr->num != NULL);
+ nptr = BCL_NUM(ctxt, n);
- bc_num_zero(nptr);
+ assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
+
+ bc_num_zero(BCL_NUM_NUM(nptr));
}
void
bcl_one(BclNumber n)
{
- BcNum* nptr;
+ BclNum* nptr;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- assert(n.i < ctxt->nums.len);
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- nptr = BC_NUM(ctxt, n);
+ nptr = BCL_NUM(ctxt, n);
- assert(nptr != NULL && nptr->num != NULL);
+ assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
- bc_num_one(nptr);
+ bc_num_one(BCL_NUM_NUM(nptr));
}
BclNumber
bcl_parse(const char* restrict val)
{
BclError e = BCL_ERROR_NONE;
- BcNum n;
+ BclNum n;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1105,7 +1323,7 @@ bcl_parse(const char* restrict val)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
assert(val != NULL);
@@ -1122,46 +1340,53 @@ bcl_parse(const char* restrict val)
}
// Clear and initialize the number.
- bc_num_clear(&n);
- bc_num_init(&n, BC_NUM_DEF_SIZE);
+ bc_num_clear(BCL_NUM_NUM_NP(n));
+ bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
- bc_num_parse(&n, val, (BcBigDig) ctxt->ibase);
+ bc_num_parse(BCL_NUM_NUM_NP(n), val, (BcBigDig) ctxt->ibase);
// Set the negative.
+#if BC_ENABLE_MEMCHECK
+ n.n.rdx = BC_NUM_NEG_VAL(BCL_NUM_NUM_NP(n), neg);
+#else // BC_ENABLE_MEMCHECK
n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
+#endif // BC_ENABLE_MEMCHECK
err:
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
return idx;
}
-char*
-bcl_string(BclNumber n)
+static char*
+bcl_string_helper(BclNumber n, bool destruct)
{
- BcNum* nptr;
+ BclNum* nptr;
char* str = NULL;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
BC_CHECK_CTXT_ASSERT(vm, ctxt);
- if (BC_ERR(n.i >= ctxt->nums.len)) return str;
+ BCL_CHECK_NUM_VALID(ctxt, n);
+
+ if (BC_ERR(BCL_NO_GEN(n) >= ctxt->nums.len)) return str;
BC_FUNC_HEADER(vm, err);
- assert(n.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- nptr = BC_NUM(ctxt, n);
+ nptr = BCL_NUM(ctxt, n);
- assert(nptr != NULL && nptr->num != NULL);
+ assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
// Clear the buffer.
bc_vec_popAll(&vm->out);
// Print to the buffer.
- bc_num_print(nptr, (BcBigDig) ctxt->obase, false);
+ bc_num_print(BCL_NUM_NUM(nptr), (BcBigDig) ctxt->obase, false);
bc_vec_pushByte(&vm->out, '\0');
// Just dup the string; the caller is responsible for it.
@@ -1169,20 +1394,37 @@ bcl_string(BclNumber n)
err:
- // Eat the operand.
- bcl_num_dtor(ctxt, n, nptr);
+ if (destruct)
+ {
+ // Eat the operand.
+ bcl_num_dtor(ctxt, n, nptr);
+ }
BC_FUNC_FOOTER_NO_ERR(vm);
return str;
}
-BclNumber
-bcl_irand(BclNumber a)
+char*
+bcl_string(BclNumber n)
+{
+ return bcl_string_helper(n, true);
+}
+
+char*
+bcl_string_keep(BclNumber n)
+{
+ return bcl_string_helper(n, false);
+}
+
+#if BC_ENABLE_EXTRA_MATH
+
+static BclNumber
+bcl_irand_helper(BclNumber a, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* aptr;
- BcNum b;
+ BclNum* aptr;
+ BclNum b;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1193,24 +1435,27 @@ bcl_irand(BclNumber a)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(a.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(a) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
+ aptr = BCL_NUM(ctxt, a);
- assert(aptr != NULL && aptr->num != NULL);
+ assert(aptr != NULL && BCL_NUM_NUM(aptr) != NULL);
// Clear and initialize the result.
- bc_num_clear(&b);
- bc_num_init(&b, BC_NUM_DEF_SIZE);
+ bc_num_clear(BCL_NUM_NUM_NP(b));
+ bc_num_init(BCL_NUM_NUM_NP(b), BC_NUM_DEF_SIZE);
- bc_num_irand(aptr, &b, &vm->rng);
+ bc_num_irand(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), &vm->rng);
err:
- // Eat the operand.
- bcl_num_dtor(ctxt, a, aptr);
+ if (destruct)
+ {
+ // Eat the operand.
+ bcl_num_dtor(ctxt, a, aptr);
+ }
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
@@ -1218,6 +1463,18 @@ err:
return idx;
}
+BclNumber
+bcl_irand(BclNumber a)
+{
+ return bcl_irand_helper(a, true);
+}
+
+BclNumber
+bcl_irand_keep(BclNumber a)
+{
+ return bcl_irand_helper(a, false);
+}
+
/**
* Helps bcl_frand(). This is separate because the error handling is easier that
* way. It is also easier to do ifrand that way.
@@ -1257,6 +1514,7 @@ bcl_frandHelper(BcNum* restrict b, size_t places)
bc_num_shiftRight(b, places);
err:
+
bc_num_free(&pow);
BC_LONGJMP_CONT(vm);
}
@@ -1265,7 +1523,7 @@ BclNumber
bcl_frand(size_t places)
{
BclError e = BCL_ERROR_NONE;
- BcNum n;
+ BclNum n;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1274,13 +1532,13 @@ bcl_frand(size_t places)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
// Clear and initialize the number.
- bc_num_clear(&n);
- bc_num_init(&n, BC_NUM_DEF_SIZE);
+ bc_num_clear(BCL_NUM_NUM_NP(n));
+ bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
- bcl_frandHelper(&n, places);
+ bcl_frandHelper(BCL_NUM_NUM_NP(n), places);
err:
@@ -1319,17 +1577,18 @@ bcl_ifrandHelper(BcNum* restrict a, BcNum* restrict b, size_t places)
bc_num_add(&ir, &fr, b, 0);
err:
+
bc_num_free(&fr);
bc_num_free(&ir);
BC_LONGJMP_CONT(vm);
}
-BclNumber
-bcl_ifrand(BclNumber a, size_t places)
+static BclNumber
+bcl_ifrand_helper(BclNumber a, size_t places, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* aptr;
- BcNum b;
+ BclNum* aptr;
+ BclNum b;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1339,24 +1598,27 @@ bcl_ifrand(BclNumber a, size_t places)
BC_FUNC_HEADER(vm, err);
- bc_vec_grow(&ctxt->nums, 1);
+ BCL_GROW_NUMS(ctxt);
- assert(a.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(a) < ctxt->nums.len);
- aptr = BC_NUM(ctxt, a);
+ aptr = BCL_NUM(ctxt, a);
- assert(aptr != NULL && aptr->num != NULL);
+ assert(aptr != NULL && BCL_NUM_NUM(aptr) != NULL);
// Clear and initialize the number.
- bc_num_clear(&b);
- bc_num_init(&b, BC_NUM_DEF_SIZE);
+ bc_num_clear(BCL_NUM_NUM_NP(b));
+ bc_num_init(BCL_NUM_NUM_NP(b), BC_NUM_DEF_SIZE);
- bcl_ifrandHelper(aptr, &b, places);
+ bcl_ifrandHelper(BCL_NUM_NUM(aptr), BCL_NUM_NUM_NP(b), places);
err:
- // Eat the oprand.
- bcl_num_dtor(ctxt, a, aptr);
+ if (destruct)
+ {
+ // Eat the oprand.
+ bcl_num_dtor(ctxt, a, aptr);
+ }
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, b, idx);
@@ -1364,11 +1626,23 @@ err:
return idx;
}
-BclError
-bcl_rand_seedWithNum(BclNumber n)
+BclNumber
+bcl_ifrand(BclNumber a, size_t places)
+{
+ return bcl_ifrand_helper(a, places, true);
+}
+
+BclNumber
+bcl_ifrand_keep(BclNumber a, size_t places)
+{
+ return bcl_ifrand_helper(a, places, false);
+}
+
+static BclError
+bcl_rand_seedWithNum_helper(BclNumber n, bool destruct)
{
BclError e = BCL_ERROR_NONE;
- BcNum* nptr;
+ BclNum* nptr;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1377,20 +1651,40 @@ bcl_rand_seedWithNum(BclNumber n)
BC_FUNC_HEADER(vm, err);
- assert(n.i < ctxt->nums.len);
+ assert(BCL_NO_GEN(n) < ctxt->nums.len);
- nptr = BC_NUM(ctxt, n);
+ nptr = BCL_NUM(ctxt, n);
- assert(nptr != NULL && nptr->num != NULL);
+ assert(nptr != NULL && BCL_NUM_NUM(nptr) != NULL);
- bc_num_rng(nptr, &vm->rng);
+ bc_num_rng(BCL_NUM_NUM(nptr), &vm->rng);
err:
+
+ if (destruct)
+ {
+ // Eat the oprand.
+ bcl_num_dtor(ctxt, n, nptr);
+ }
+
BC_FUNC_FOOTER(vm, e);
+
return e;
}
BclError
+bcl_rand_seedWithNum(BclNumber n)
+{
+ return bcl_rand_seedWithNum_helper(n, true);
+}
+
+BclError
+bcl_rand_seedWithNum_keep(BclNumber n)
+{
+ return bcl_rand_seedWithNum_helper(n, false);
+}
+
+BclError
bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])
{
BclError e = BCL_ERROR_NONE;
@@ -1411,7 +1705,9 @@ bcl_rand_seed(unsigned char seed[BCL_SEED_SIZE])
bc_rand_seed(&vm->rng, vals[0], vals[1], vals[2], vals[3]);
err:
+
BC_FUNC_FOOTER(vm, e);
+
return e;
}
@@ -1427,7 +1723,7 @@ BclNumber
bcl_rand_seed2num(void)
{
BclError e = BCL_ERROR_NONE;
- BcNum n;
+ BclNum n;
BclNumber idx;
BclContext ctxt;
BcVm* vm = bcl_getspecific();
@@ -1437,12 +1733,13 @@ bcl_rand_seed2num(void)
BC_FUNC_HEADER(vm, err);
// Clear and initialize the number.
- bc_num_clear(&n);
- bc_num_init(&n, BC_NUM_DEF_SIZE);
+ bc_num_clear(BCL_NUM_NUM_NP(n));
+ bc_num_init(BCL_NUM_NUM_NP(n), BC_NUM_DEF_SIZE);
- bc_num_createFromRNG(&n, &vm->rng);
+ bc_num_createFromRNG(BCL_NUM_NUM_NP(n), &vm->rng);
err:
+
BC_FUNC_FOOTER(vm, e);
BC_MAYBE_SETUP(ctxt, e, n, idx);
@@ -1466,4 +1763,6 @@ bcl_rand_bounded(BclRandInt bound)
return (BclRandInt) bc_rand_bounded(&vm->rng, (BcRand) bound);
}
+#endif // BC_ENABLE_EXTRA_MATH
+
#endif // BC_ENABLE_LIBRARY
diff --git a/src/program.c b/src/program.c
index 5ede93d5..243f827f 100644
--- a/src/program.c
+++ b/src/program.c
@@ -757,9 +757,16 @@ bc_program_read(BcProgram* p)
// struct.
bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
}
- // This needs to be updated because the parser could have been used
- // somewhere else
- else bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
+ else
+ {
+ // This needs to be updated because the parser could have been used
+ // somewhere else.
+ bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
+
+ // The read buffer also needs to be emptied or else it will still
+ // contain previous read expressions.
+ bc_vec_empty(&vm->read_buf);
+ }
BC_SETJMP_LOCKED(vm, exec_err);
@@ -2689,12 +2696,20 @@ bc_program_globalSetting(BcProgram* p, uchar inst)
BcBigDig val;
// Make sure the instruction is valid.
+#if DC_ENABLED
+ assert((inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO) ||
+ (BC_IS_DC && inst == BC_INST_EXTENDED_REGISTERS));
+#else // DC_ENABLED
assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
+#endif // DC_ENABLED
if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm->line_len;
#if BC_ENABLED
else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0);
#endif // BC_ENABLED
+#if DC_ENABLED
+ else if (inst == BC_INST_EXTENDED_REGISTERS) val = (DC_X != 0);
+#endif // DC_ENABLED
else val = (BC_Z != 0);
// Push the global.
@@ -3246,6 +3261,9 @@ bc_program_exec(BcProgram* p)
#if BC_ENABLED
BC_PROG_LBL(BC_INST_GLOBAL_STACKS):
#endif // BC_ENABLED
+#if DC_ENABLED
+ BC_PROG_LBL(BC_INST_EXTENDED_REGISTERS):
+#endif // DC_ENABLE
BC_PROG_LBL(BC_INST_LEADING_ZERO):
// clang-format on
{
diff --git a/src/vm.c b/src/vm.c
index 3a7913e3..41da0fd9 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -622,8 +622,12 @@ bc_vm_envLen(const char* var)
if (num)
{
// Parse it and clamp it if needed.
- len = (size_t) atoi(lenv) - 1;
- if (len == 1 || len >= UINT16_MAX) len = BC_NUM_PRINT_WIDTH;
+ len = (size_t) strtol(lenv, NULL, 10);
+ if (len != 0)
+ {
+ len -= 1;
+ if (len < 2 || len >= UINT16_MAX) len = BC_NUM_PRINT_WIDTH;
+ }
}
// Set the default.
else len = BC_NUM_PRINT_WIDTH;
@@ -643,12 +647,14 @@ bc_vm_shutdown(void)
if (vm->catalog != BC_VM_INVALID_CATALOG) catclose(vm->catalog);
#endif // BC_ENABLE_NLS
+#if !BC_ENABLE_LIBRARY
#if BC_ENABLE_HISTORY
// This must always run to ensure that the terminal is back to normal, i.e.,
// has raw mode disabled. But we should only do it if we did not have a bad
// terminal because history was not initialized if it is a bad terminal.
if (BC_TTY && !vm->history.badTerm) bc_history_free(&vm->history);
#endif // BC_ENABLE_HISTORY
+#endif // !BC_ENABLE_LIBRARY
#if BC_DEBUG
#if !BC_ENABLE_LIBRARY
diff --git a/tests/all.sh b/tests/all.sh
index 09980477..9174d398 100755
--- a/tests/all.sh
+++ b/tests/all.sh
@@ -50,11 +50,12 @@ pll=1
while getopts "n" opt; do
case "$opt" in
- n) pll=0 ; shift ; set -e ;;
+ n) pll=0 ; set -e ;;
?) usage "Invalid option: $opt" ;;
esac
done
+shift $(($OPTIND - 1))
# Command-line processing.
if [ "$#" -ge 1 ]; then
diff --git a/tests/bc/all.txt b/tests/bc/all.txt
index af5eaaa4..3d0ea05b 100644
--- a/tests/bc/all.txt
+++ b/tests/bc/all.txt
@@ -34,6 +34,7 @@ arctangent
sine
cosine
bessel
+fib
arrays
misc
misc1
diff --git a/tests/bc/fib.txt b/tests/bc/fib.txt
new file mode 100644
index 00000000..2fa2eea1
--- /dev/null
+++ b/tests/bc/fib.txt
@@ -0,0 +1,31 @@
+fib(0)
+fib(1)
+fib(2)
+fib(3)
+fib(4)
+fib(5)
+fib(6)
+fib(7)
+fib(8)
+fib(9)
+fib(10)
+fib(11)
+fib(12)
+fib(13)
+fib(14)
+fib(15)
+fib(16)
+fib(17)
+fib(18)
+fib(19)
+fib(20)
+fib(21)
+fib(22)
+fib(23)
+fib(24)
+fib(25)
+fib(26)
+fib(27)
+fib(28)
+fib(29)
+fib(30)
diff --git a/tests/bc/fib_results.txt b/tests/bc/fib_results.txt
new file mode 100644
index 00000000..1837f6b7
--- /dev/null
+++ b/tests/bc/fib_results.txt
@@ -0,0 +1,31 @@
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
diff --git a/tests/bc/scripts/all.txt b/tests/bc/scripts/all.txt
index e2d2aa32..a226bed5 100644
--- a/tests/bc/scripts/all.txt
+++ b/tests/bc/scripts/all.txt
@@ -4,6 +4,7 @@ subtract.bc
add.bc
print.bc
parse.bc
+root.bc
array.bc
array2.bc
atan.bc
diff --git a/tests/bc/scripts/cbrt.txt b/tests/bc/scripts/cbrt.txt
new file mode 100644
index 00000000..bae7f3af
--- /dev/null
+++ b/tests/bc/scripts/cbrt.txt
@@ -0,0 +1,100 @@
+.464158883361277889241007635091
+.215443469003188372175929356651
+.100000000000000000000000000000
+.046415888336127788924100763509
+.021544346900318837217592935665
+.010000000000000000000000000000
+.004641588833612778892410076350
+.002154434690031883721759293566
+.001000000000000000000000000000
+.000464158883361277889241007635
+.000215443469003188372175929356
+.000100000000000000000000000000
+.000046415888336127788924100763
+.000021544346900318837217592935
+.000010000000000000000000000000
+.000004641588833612778892410076
+.000002154434690031883721759293
+.000001000000000000000000000000
+.000000464158883361277889241007
+.000000215443469003188372175929
+.000000100000000000000000000000
+.000000046415888336127788924100
+.000000021544346900318837217592
+.000000010000000000000000000000
+.000000004641588833612778892410
+.000000002154434690031883721759
+.000000001000000000000000000000
+.000000000464158883361277889241
+.000000000215443469003188372175
+.000000000100000000000000000000
+.000000000046415888336127788924
+.000000000021544346900318837217
+.000000000010000000000000000000
+.000000000004641588833612778892
+.000000000002154434690031883721
+.000000000001000000000000000000
+.000000000000464158883361277889
+.000000000000215443469003188372
+.000000000000100000000000000000
+.000000000000046415888336127788
+.000000000000021544346900318837
+.000000000000010000000000000000
+.000000000000004641588833612778
+.000000000000002154434690031883
+.000000000000001000000000000000
+.000000000000000464158883361277
+.000000000000000215443469003188
+.000000000000000100000000000000
+.000000000000000046415888336127
+.000000000000000021544346900318
+.000000000000000010000000000000
+.000000000000000004641588833612
+.000000000000000002154434690031
+.000000000000000001000000000000
+.000000000000000000464158883361
+.000000000000000000215443469003
+.000000000000000000100000000000
+.000000000000000000046415888336
+.000000000000000000021544346900
+.000000000000000000010000000000
+.000000000000000000004641588833
+.000000000000000000002154434690
+.000000000000000000001000000000
+.000000000000000000000464158883
+.000000000000000000000215443469
+.000000000000000000000100000000
+.000000000000000000000046415888
+.000000000000000000000021544346
+.000000000000000000000010000000
+.000000000000000000000004641588
+.000000000000000000000002154434
+.000000000000000000000001000000
+.000000000000000000000000464158
+.000000000000000000000000215443
+.000000000000000000000000100000
+.000000000000000000000000046415
+.000000000000000000000000021544
+.000000000000000000000000010000
+.000000000000000000000000004641
+.000000000000000000000000002154
+.000000000000000000000000001000
+.000000000000000000000000000464
+.000000000000000000000000000215
+.000000000000000000000000000100
+.000000000000000000000000000046
+.000000000000000000000000000021
+.000000000000000000000000000010
+.000000000000000000000000000004
+.000000000000000000000000000002
+.000000000000000000000000000001
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
diff --git a/tests/bc/scripts/root.bc b/tests/bc/scripts/root.bc
new file mode 100644
index 00000000..95210fe2
--- /dev/null
+++ b/tests/bc/scripts/root.bc
@@ -0,0 +1,19 @@
+scale = 30
+
+s = 1 >> 1
+
+for (i = 0; i < 100; ++i)
+{
+ cbrt(s)
+ s >>= 1
+}
+
+s = 1 >> 1
+
+for (i = 0; i < 155; ++i)
+{
+ root(s, 5)
+ s >>= 1
+}
+
+halt
diff --git a/tests/bc/scripts/root.txt b/tests/bc/scripts/root.txt
new file mode 100644
index 00000000..b720eb5d
--- /dev/null
+++ b/tests/bc/scripts/root.txt
@@ -0,0 +1,255 @@
+.464158883361277889241007635091
+.215443469003188372175929356651
+.100000000000000000000000000000
+.046415888336127788924100763509
+.021544346900318837217592935665
+.010000000000000000000000000000
+.004641588833612778892410076350
+.002154434690031883721759293566
+.001000000000000000000000000000
+.000464158883361277889241007635
+.000215443469003188372175929356
+.000100000000000000000000000000
+.000046415888336127788924100763
+.000021544346900318837217592935
+.000010000000000000000000000000
+.000004641588833612778892410076
+.000002154434690031883721759293
+.000001000000000000000000000000
+.000000464158883361277889241007
+.000000215443469003188372175929
+.000000100000000000000000000000
+.000000046415888336127788924100
+.000000021544346900318837217592
+.000000010000000000000000000000
+.000000004641588833612778892410
+.000000002154434690031883721759
+.000000001000000000000000000000
+.000000000464158883361277889241
+.000000000215443469003188372175
+.000000000100000000000000000000
+.000000000046415888336127788924
+.000000000021544346900318837217
+.000000000010000000000000000000
+.000000000004641588833612778892
+.000000000002154434690031883721
+.000000000001000000000000000000
+.000000000000464158883361277889
+.000000000000215443469003188372
+.000000000000100000000000000000
+.000000000000046415888336127788
+.000000000000021544346900318837
+.000000000000010000000000000000
+.000000000000004641588833612778
+.000000000000002154434690031883
+.000000000000001000000000000000
+.000000000000000464158883361277
+.000000000000000215443469003188
+.000000000000000100000000000000
+.000000000000000046415888336127
+.000000000000000021544346900318
+.000000000000000010000000000000
+.000000000000000004641588833612
+.000000000000000002154434690031
+.000000000000000001000000000000
+.000000000000000000464158883361
+.000000000000000000215443469003
+.000000000000000000100000000000
+.000000000000000000046415888336
+.000000000000000000021544346900
+.000000000000000000010000000000
+.000000000000000000004641588833
+.000000000000000000002154434690
+.000000000000000000001000000000
+.000000000000000000000464158883
+.000000000000000000000215443469
+.000000000000000000000100000000
+.000000000000000000000046415888
+.000000000000000000000021544346
+.000000000000000000000010000000
+.000000000000000000000004641588
+.000000000000000000000002154434
+.000000000000000000000001000000
+.000000000000000000000000464158
+.000000000000000000000000215443
+.000000000000000000000000100000
+.000000000000000000000000046415
+.000000000000000000000000021544
+.000000000000000000000000010000
+.000000000000000000000000004641
+.000000000000000000000000002154
+.000000000000000000000000001000
+.000000000000000000000000000464
+.000000000000000000000000000215
+.000000000000000000000000000100
+.000000000000000000000000000046
+.000000000000000000000000000021
+.000000000000000000000000000010
+.000000000000000000000000000004
+.000000000000000000000000000002
+.000000000000000000000000000001
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+.630957344480193249434360136622
+.398107170553497250770252305087
+.251188643150958011108503206779
+.158489319246111348520210137339
+.100000000000000000000000000000
+.063095734448019324943436013662
+.039810717055349725077025230508
+.025118864315095801110850320677
+.015848931924611134852021013733
+.010000000000000000000000000000
+.006309573444801932494343601366
+.003981071705534972507702523050
+.002511886431509580111085032067
+.001584893192461113485202101373
+.001000000000000000000000000000
+.000630957344480193249434360136
+.000398107170553497250770252305
+.000251188643150958011108503206
+.000158489319246111348520210137
+.000100000000000000000000000000
+.000063095734448019324943436013
+.000039810717055349725077025230
+.000025118864315095801110850320
+.000015848931924611134852021013
+.000010000000000000000000000000
+.000006309573444801932494343601
+.000003981071705534972507702523
+.000002511886431509580111085032
+.000001584893192461113485202101
+.000001000000000000000000000000
+.000000630957344480193249434360
+.000000398107170553497250770252
+.000000251188643150958011108503
+.000000158489319246111348520210
+.000000100000000000000000000000
+.000000063095734448019324943436
+.000000039810717055349725077025
+.000000025118864315095801110850
+.000000015848931924611134852021
+.000000010000000000000000000000
+.000000006309573444801932494343
+.000000003981071705534972507702
+.000000002511886431509580111085
+.000000001584893192461113485202
+.000000001000000000000000000000
+.000000000630957344480193249434
+.000000000398107170553497250770
+.000000000251188643150958011108
+.000000000158489319246111348520
+.000000000100000000000000000000
+.000000000063095734448019324943
+.000000000039810717055349725077
+.000000000025118864315095801110
+.000000000015848931924611134852
+.000000000010000000000000000000
+.000000000006309573444801932494
+.000000000003981071705534972507
+.000000000002511886431509580111
+.000000000001584893192461113485
+.000000000001000000000000000000
+.000000000000630957344480193249
+.000000000000398107170553497250
+.000000000000251188643150958011
+.000000000000158489319246111348
+.000000000000100000000000000000
+.000000000000063095734448019324
+.000000000000039810717055349725
+.000000000000025118864315095801
+.000000000000015848931924611134
+.000000000000010000000000000000
+.000000000000006309573444801932
+.000000000000003981071705534972
+.000000000000002511886431509580
+.000000000000001584893192461113
+.000000000000001000000000000000
+.000000000000000630957344480193
+.000000000000000398107170553497
+.000000000000000251188643150958
+.000000000000000158489319246111
+.000000000000000100000000000000
+.000000000000000063095734448019
+.000000000000000039810717055349
+.000000000000000025118864315095
+.000000000000000015848931924611
+.000000000000000010000000000000
+.000000000000000006309573444801
+.000000000000000003981071705534
+.000000000000000002511886431509
+.000000000000000001584893192461
+.000000000000000001000000000000
+.000000000000000000630957344480
+.000000000000000000398107170553
+.000000000000000000251188643150
+.000000000000000000158489319246
+.000000000000000000100000000000
+.000000000000000000063095734448
+.000000000000000000039810717055
+.000000000000000000025118864315
+.000000000000000000015848931924
+.000000000000000000010000000000
+.000000000000000000006309573444
+.000000000000000000003981071705
+.000000000000000000002511886431
+.000000000000000000001584893192
+.000000000000000000001000000000
+.000000000000000000000630957344
+.000000000000000000000398107170
+.000000000000000000000251188643
+.000000000000000000000158489319
+.000000000000000000000100000000
+.000000000000000000000063095734
+.000000000000000000000039810717
+.000000000000000000000025118864
+.000000000000000000000015848931
+.000000000000000000000010000000
+.000000000000000000000006309573
+.000000000000000000000003981071
+.000000000000000000000002511886
+.000000000000000000000001584893
+.000000000000000000000001000000
+.000000000000000000000000630957
+.000000000000000000000000398107
+.000000000000000000000000251188
+.000000000000000000000000158489
+.000000000000000000000000100000
+.000000000000000000000000063095
+.000000000000000000000000039810
+.000000000000000000000000025118
+.000000000000000000000000015848
+.000000000000000000000000010000
+.000000000000000000000000006309
+.000000000000000000000000003981
+.000000000000000000000000002511
+.000000000000000000000000001584
+.000000000000000000000000001000
+.000000000000000000000000000630
+.000000000000000000000000000398
+.000000000000000000000000000251
+.000000000000000000000000000158
+.000000000000000000000000000100
+.000000000000000000000000000063
+.000000000000000000000000000039
+.000000000000000000000000000025
+.000000000000000000000000000015
+.000000000000000000000000000010
+.000000000000000000000000000006
+.000000000000000000000000000003
+.000000000000000000000000000002
+.000000000000000000000000000001
+.000000000000000000000000000001
+0
+0
+0
+0
+0
diff --git a/tests/bcl.c b/tests/bcl.c
index cea63f45..5bb50c29 100644
--- a/tests/bcl.c
+++ b/tests/bcl.c
@@ -55,7 +55,7 @@ main(void)
BclError e;
BclContext ctxt;
size_t scale;
- BclNumber n, n2, n3, n4, n5, n6;
+ BclNumber n, n2, n3, n4, n5, n6, n7;
char* res;
BclBigDig b = 0;
@@ -124,9 +124,21 @@ main(void)
if (!bcl_num_neg(n4)) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
// Add them and check the result.
+ n5 = bcl_add_keep(n3, n4);
+ err(bcl_err(n5));
+ res = bcl_string(n5);
+ if (res == NULL) err(BCL_ERROR_FATAL_ALLOC_ERR);
+ if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
+
+ // We want to ensure all memory gets freed because we run this under
+ // Valgrind.
+ free(res);
+
+ // Add them and check the result.
n3 = bcl_add(n3, n4);
err(bcl_err(n3));
- res = bcl_string(bcl_dup(n3));
+ res = bcl_string_keep(n3);
+ if (res == NULL) err(BCL_ERROR_FATAL_ALLOC_ERR);
if (strcmp(res, "-25452.9108273")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
// We want to ensure all memory gets freed because we run this under
@@ -136,19 +148,29 @@ main(void)
// Ensure that divmod, a special case, works.
n4 = bcl_parse("8937458902.2890347");
err(bcl_err(n4));
- e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6);
+ e = bcl_divmod_keep(n4, n3, &n5, &n6);
err(e);
res = bcl_string(n5);
-
if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
-
free(res);
res = bcl_string(n6);
-
if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
+ free(res);
+
+ // Ensure that divmod, a special case, works.
+ n4 = bcl_parse("8937458902.2890347");
+ err(bcl_err(n4));
+ e = bcl_divmod(bcl_dup(n4), n3, &n5, &n6);
+ err(e);
+
+ res = bcl_string(n5);
+ if (strcmp(res, "-351137.0060159482")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
+ free(res);
+ res = bcl_string(n6);
+ if (strcmp(res, ".00000152374405414")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
free(res);
// Ensure that sqrt works. This is also a special case. The reason is
@@ -214,10 +236,18 @@ main(void)
err(bcl_err(n3));
// Repeat.
+ n2 = bcl_ifrand_keep(n3, 10);
+ err(bcl_err(n2));
+
+ // Repeat.
n2 = bcl_ifrand(bcl_dup(n3), 10);
err(bcl_err(n2));
// Still checking asserts.
+ e = bcl_rand_seedWithNum_keep(n3);
+ err(e);
+
+ // Still checking asserts.
e = bcl_rand_seedWithNum(n3);
err(e);
@@ -229,9 +259,12 @@ main(void)
n5 = bcl_parse("10");
err(bcl_err(n5));
- n6 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5));
+ n6 = bcl_modexp_keep(n5, n5, n5);
err(bcl_err(n6));
+ n7 = bcl_modexp(bcl_dup(n5), bcl_dup(n5), bcl_dup(n5));
+ err(bcl_err(n7));
+
// Clean up.
bcl_num_free(n);
@@ -250,6 +283,11 @@ main(void)
n4 = bcl_parse("-1.01");
err(bcl_err(n4));
+ res = bcl_string_keep(n);
+ if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
+
+ free(res);
+
res = bcl_string(bcl_dup(n));
if (strcmp(res, ".01")) err(BCL_ERROR_FATAL_UNKNOWN_ERR);
diff --git a/tests/extra_required.txt b/tests/extra_required.txt
index e36d95a1..c498802f 100644
--- a/tests/extra_required.txt
+++ b/tests/extra_required.txt
@@ -1,5 +1,6 @@
engineering
lib2
+fib
places
rand
scientific
diff --git a/tests/other.sh b/tests/other.sh
index de4059b9..c3a739a3 100755
--- a/tests/other.sh
+++ b/tests/other.sh
@@ -273,8 +273,8 @@ else
printf 'Running dc Easter script...'
- easter_res="$outputdir/dc_outputs/easter.txt"
- easter_out="$outputdir/dc_outputs/easter_results.txt"
+ easter_out="$outputdir/dc_outputs/easter.txt"
+ easter_res="$outputdir/dc_outputs/easter_results.txt"
outdir=$(dirname "$easter_out")
@@ -287,11 +287,41 @@ else
"$testdir/dc/scripts/easter.sh" "$exe" 2021 "$@" 2> /dev/null | cut -c1-12 > "$easter_out"
err="$?"
- checktest "$d" "$err" "Easter script" "$easter_res" "$easter_out"
+ checktest "$d" "$err" "Easter script" "$easter_out" "$easter_res"
printf 'pass\n'
fi
+ unset DC_ENV_ARGS
+ unset DC_EXPR_EXIT
+
+ printf 'Running dc extended register command tests...'
+
+ ext_reg_out="$outputdir/dc_outputs/ext_reg.txt"
+ ext_reg_res="$outputdir/dc_outputs/ext_reg_results.txt"
+
+ outdir=$(dirname "$ext_reg_out")
+
+ if [ ! -d "$outdir" ]; then
+ mkdir -p "$outdir"
+ fi
+
+ printf '0\n' > "$ext_reg_res"
+
+ "$exe" "$@" -e "gxpR" 2> /dev/null > "$ext_reg_out"
+ err="$?"
+
+ checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res"
+
+ printf '1\n' > "$ext_reg_res"
+
+ "$exe" "$@" -x -e "gxpR" 2> /dev/null > "$ext_reg_out"
+ err="$?"
+
+ checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res"
+
+ printf 'pass\n'
+
fi
out1="$outputdir/${d}_outputs/${d}_other.txt"
diff --git a/tests/read.sh b/tests/read.sh
index d7be18fd..4881c10d 100755
--- a/tests/read.sh
+++ b/tests/read.sh
@@ -74,6 +74,7 @@ results="$testdir/$d/read_results.txt"
errors="$testdir/$d/read_errors.txt"
out="$outputdir/${d}_outputs/read_results.txt"
+multiple_res="$outputdir/${d}_outputs/read_multiple_results.txt"
outdir=$(dirname "$out")
# Make sure the directory exists.
@@ -89,11 +90,13 @@ if [ "$d" = "bc" ]; then
halt="halt"
read_call="read()"
read_expr="${read_call}\n5+5;"
+ read_multiple=$(printf '%s\n%s\n%s\n' "3" "2" "1")
else
options="-x"
halt="q"
read_call="?"
read_expr="${read_call}"
+ read_multiple=$(printf '%spR\n%spR\n%spR\n' "3" "2" "1")
fi
# I use these, so unset them to make the tests work.
@@ -116,6 +119,16 @@ done < "$name"
printf 'pass\n'
+printf 'Running %s read multiple...' "$d"
+
+printf '3\n2\n1\n' > "$multiple_res"
+
+# Run multiple read() calls.
+printf '%s\n' "$read_multiple" | "$exe" "$@" "$options" -e "$read_call" -e "$read_call" -e "$read_call" > "$out"
+checktest "$d" "$?" 'read multiple' "$multiple_res" "$out"
+
+printf 'pass\n'
+
printf 'Running %s read errors...' "$d"
# Run read on every line.
diff --git a/tests/script.sh b/tests/script.sh
index 438af17c..fef0c529 100755
--- a/tests/script.sh
+++ b/tests/script.sh
@@ -132,7 +132,7 @@ fi
# Skip the tests that require extra math if we don't have it.
if [ "$run_extra_tests" -eq 0 ]; then
- if [ "$f" = "rand.bc" ]; then
+ if [ "$f" = "rand.bc" ] || [ "$f" = "root.bc" ]; then
printf 'Skipping %s script: %s\n' "$d" "$f"
exit 0
fi
diff --git a/tests/scripts.sh b/tests/scripts.sh
index ef0e81ef..dda57e43 100755
--- a/tests/scripts.sh
+++ b/tests/scripts.sh
@@ -52,11 +52,12 @@ pll=1
while getopts "n" opt; do
case "$opt" in
- n) pll=0 ; shift ; set -e ;;
+ n) pll=0 ; set -e ;;
?) usage "Invalid option: $opt" ;;
esac
done
+shift $(($OPTIND - 1))
# Command-line processing.
if [ "$#" -eq 0 ]; then