summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arith.c50
-rw-r--r--arith.h3
-rw-r--r--txr.190
3 files changed, 143 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index 5e7c1b33..80405e85 100644
--- a/arith.c
+++ b/arith.c
@@ -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)
diff --git a/arith.h b/arith.h
index 1fa4e6c4..29e65706 100644
--- a/arith.h
+++ b/arith.h
@@ -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);
diff --git a/txr.1 b/txr.1
index 8d88ff38..3c2937e0 100644
--- a/txr.1
+++ b/txr.1
@@ -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".