diff options
author | Elliott Hughes <enh@google.com> | 2023-04-12 17:28:46 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-04-12 17:28:46 +0000 |
commit | 211da69ae75405023c29340e4e45b7c3fcccc2af (patch) | |
tree | 87ec1db1aaae068d23b200dbc19802402d6ca470 | |
parent | 175888b8d57a2bdeb3f87034cc40f5619d7ff79c (diff) | |
parent | 214eb3eb45cb03d03a6d0809bf79f49ad9ac0767 (diff) | |
download | bc-211da69ae75405023c29340e4e45b7c3fcccc2af.tar.gz |
Upgrade gavinhoward/bc to 6.5.0 am: 6fba858a57 am: cd59192ae8 am: 81dcada73a am: 214eb3eb45android-14.0.0_r45android-14.0.0_r44android-14.0.0_r43android-14.0.0_r42android-14.0.0_r41android-14.0.0_r40android-14.0.0_r39android-14.0.0_r38android-14.0.0_r27android-14.0.0_r26android-14.0.0_r25android-14.0.0_r24android-14.0.0_r23android-14.0.0_r22android-14.0.0_r21android-14.0.0_r20android-14.0.0_r19android-14.0.0_r18android-14.0.0_r17android-14.0.0_r16android14-qpr1-s2-releaseandroid14-qpr1-releaseandroid14-d2-s5-releaseandroid14-d2-s4-releaseandroid14-d2-s3-releaseandroid14-d2-s2-releaseandroid14-d2-s1-releaseandroid14-d2-release
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>
77 files changed, 2440 insertions, 587 deletions
@@ -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' @@ -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: @@ -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 { @@ -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 |