diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-08-05 16:54:41 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-08-05 16:54:41 -0700 |
commit | 905a08374e2901e97b18e58d970f95a25ec6fc10 (patch) | |
tree | 5ec8498b29b05908c3d46da92d9f387cc7037350 | |
parent | d6ba8dd31733e6f3b455a8f746087b33066fef81 (diff) | |
download | txr-905a08374e2901e97b18e58d970f95a25ec6fc10.tar.gz txr-905a08374e2901e97b18e58d970f95a25ec6fc10.tar.bz2 txr-905a08374e2901e97b18e58d970f95a25ec6fc10.zip |
New functions digpow and digits.
* arith.c (digcommon): New static function.
(digpow, digits): New functions.
(arith_init): New digpow and digits intrinsic functions
registered.
* arith.h (digpow, digits): Declared.
* txr.1: New functions documented.
-rw-r--r-- | arith.c | 50 | ||||
-rw-r--r-- | arith.h | 3 | ||||
-rw-r--r-- | txr.1 | 90 |
3 files changed, 143 insertions, 0 deletions
@@ -2848,6 +2848,54 @@ val bits(val obj) return normalize(bignum_from_uintptr(coerce(uint_ptr_t, obj))); } +static val digcommon(int pow, val self, val n, val base_in) +{ + val r = default_arg_strict(base_in, num_fast(10)); + + if (!integerp(n) || minusp(n)) + uw_throwf(error_s, lit("~a: value ~s must be positive integer"), + self, n, nao); + if (!integerp(r) || lt(r, one)) + uw_throwf(error_s, lit("~a: base ~s must be positive integer"), + self, r, nao); + + { + val k = r; + val p = nil, p0; + list_collect_decl (out, ptail); + + while (lt(k, n)) { + push(k, &p); + k = mul(k, r); + } + + while ((p0 = pop(&p))) { + cnum i = 0; + while (ge(n, p0)) { + i++; + n = minus(n, p0); + } + ptail = list_collect(ptail, if3(pow, + mul(num_fast(i), p0), + num_fast(i))); + } + + list_collect(ptail, n); + + return out; + } +} + +val digpow(val n, val base) +{ + return digcommon(1, lit("digpow"), n, base); +} + +val digits(val n, val base) +{ + return digcommon(0, lit("digits"), n, base); +} + void arith_init(void) { mp_init(&NUM_MAX_MP); @@ -2882,6 +2930,8 @@ void arith_init(void) reg_varl(intern(lit("%e%"), user_package), flo(M_E)); reg_fun(intern(lit("bits"), system_package), func_n1(bits)); + reg_fun(intern(lit("digpow"), user_package), func_n2o(digpow, 1)); + reg_fun(intern(lit("digits"), user_package), func_n2o(digits, 1)); } void arith_free_all(void) @@ -45,6 +45,9 @@ val tofloatz(val obj); val tointz(val obj, val base); val width(val num); val bits(val obj); +val digpow(val n, val base); +val digits(val n, val base); + noreturn void do_mp_error(val self, mp_err code); void arith_init(void); void arith_free_all(void); @@ -34532,6 +34532,96 @@ approximations are accurate to .code flo-dig decimal digits. +.coNP Function @ digits +.synb +.mets (digits < number <> [ radix ]) +.syne +.desc +The +.code digits +function returns a list of the digits of +.meta number +represented in the base given by +.metn radix . + +The +.meta number +argument must be a non-negative integer, and +.meta radix +must be an integer greater than one. + +If +.meta radix +is omitted, it defaults to 10. + +The return value is a list of the digits in descending order of significance: +most significant to least significant. +The digits are integers. For instance, if +.meta radix +is 42, then the digits are integer values in the range 0 to 41. + +The returned list always contains at least one element, and +includes no leading zeros, except when +.meta number +is zero. In that case, a one-element list containing zero is returned. + +.TP* Examples: + +.cblk + (digits 1234) -> (1 2 3 4) + (digits 1234567 1000) -> (1 234 567) + (digits 30 2) -> (1 1 1 1 0) + (digits 0) -> (0) +.cble + +.coNP Function @ digpow +.synb +.mets (digpow < number <> [ radix ]) +.syne +.desc +The +.code digpow +function decomposes the +.meta number +argument into a power series whose terms add up to +.metn number . + +The +.meta number +argument must be a non-negative integer, and +.meta radix +must be an integer greater than one. + +The returned power series consists of a list of nonnegative +integers. It is formed from the digits of +.meta number +in the given +.metn radix , +which serve as coefficients which multiply successive +powers of the +.metn radix , +starting at the zeroth power (one). + +The terms are given in decreasing order of significance: +the term corresponding to the most significant digit of +.metn number , +multiplying the highest power of +.metn radix , +is listed first. + +The returned list always contains at least one element, and +includes no leading zeros, except when +.meta number +is zero. In that case, a one-element list containing zero is returned. + +.cblk + (digpow 1234) -> (1000 200 30 4) + (digpow 1234567 1000) -> (1000000 234000 567) + (digpow 30 2) -> (16 8 4 2 0) + (digpow 0) -> (0) +.cble + + .SS* Bit Operations In \*(TL, similarly to Common Lisp, bit operations on integers are based on a concept that might be called "infinite two's-complement". |