summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-02-25 22:00:50 -0800
committerKaz Kylheku <kaz@kylheku.com>2017-02-25 22:00:50 -0800
commit0f32fe85728e4ee35a25094d99bdf7b3ff1630a7 (patch)
tree568160ac3679e3cc202b28bf2fd262786187871f
parent56f0df1ea9282f1c050e23c78fed47f321ff8d06 (diff)
downloadtxr-0f32fe85728e4ee35a25094d99bdf7b3ff1630a7.tar.gz
txr-0f32fe85728e4ee35a25094d99bdf7b3ff1630a7.tar.bz2
txr-0f32fe85728e4ee35a25094d99bdf7b3ff1630a7.zip
Second argument optional in trunc.
* arith.c (trunc1): New static function. (trunc): Detect a missing second argument and call func1. * eval.c (eval_init): Update registration of trunc intrinsic to make second arg optional. * txr.1: Describe optional argument of trunc. Trunc documentation is merged with the floor, ceil and round section. The mod and trunc-rem functions are split off into their own sections, leaving the / function described by itself. The documentation of / is substantially revised.
-rw-r--r--arith.c21
-rw-r--r--eval.c2
-rw-r--r--txr.1158
3 files changed, 106 insertions, 75 deletions
diff --git a/arith.c b/arith.c
index 36ecad20..483efa15 100644
--- a/arith.c
+++ b/arith.c
@@ -803,8 +803,29 @@ tail:
uw_throwf(error_s, lit("*: invalid operands ~s ~s"), anum, bnum, nao);
}
+static val trunc1(val num)
+{
+ switch (type(num)) {
+ case NUM:
+ case BGNUM:
+ return num;
+ case FLNUM:
+ {
+ double n = c_flo(num);
+ return flo(n - fmod(n, 1.0));
+ }
+ case RNG:
+ return rcons(trunc1(from(num)), trunc1(to(num)));
+ default:
+ break;
+ }
+ uw_throwf(error_s, lit("trunc: invalid operand ~s"), num);
+}
+
val trunc(val anum, val bnum)
{
+ if (missingp(bnum))
+ return trunc1(anum);
tail:
switch (TAG_PAIR(tag(anum), tag(bnum))) {
case TAG_PAIR(TAG_NUM, TAG_NUM):
diff --git a/eval.c b/eval.c
index 0312292a..bc58d303 100644
--- a/eval.c
+++ b/eval.c
@@ -5691,7 +5691,7 @@ void eval_init(void)
reg_fun(intern(lit("-"), user_package), func_n1v(minusv));
reg_fun(intern(lit("*"), user_package), func_n0v(mulv));
reg_fun(intern(lit("abs"), user_package), func_n1(abso));
- reg_fun(intern(lit("trunc"), user_package), func_n2(trunc));
+ reg_fun(intern(lit("trunc"), user_package), func_n2o(trunc, 1));
reg_fun(intern(lit("mod"), user_package), func_n2(mod));
reg_fun(intern(lit("trunc-rem"), user_package), func_n2(trunc_rem));
reg_fun(intern(lit("wrap"), user_package), func_n3(wrap));
diff --git a/txr.1 b/txr.1
index b53e763b..2045cf21 100644
--- a/txr.1
+++ b/txr.1
@@ -31617,87 +31617,35 @@ A character may not be an operand of multiplication.
.PP
-.coNP Functions @, / @ trunc, @ mod and @ trunc-rem
+.coNP Function @ /
.synb
-.mets (/ <> [ dividend ] << divisor *)
-.mets (trunc < dividend << divisor )
-.mets (mod < dividend << divisor )
-.mets (trunc-rem < dividend << divisor )
+.mets (/ << divisor )
+.mets (/ < dividend << divisor *)
.syne
.desc
-The arguments to these functions are numbers. Characters are not permitted.
-
The
.code /
function performs floating-point division. Each operands is first
-converted to floating-point type, if necessary. If
-.meta dividend
-is omitted,
-then it is taken to be
-.code 1.0
-and the function calculates the reciprocal. Of these division functions,
-only this one may be called with just one argument, or with more than two
-arguments. If there are more than two arguments, then each additional argument
-is treated as an additional divisor which further divides the result of the
-division by the previous divisors.
-
-The
-.code trunc
-function performs a division of
+converted to floating-point type, if necessary. In the one-argument
+form, the
.meta dividend
-by
-.meta divisor
-whose result
-is truncated to integer toward zero. If both operands are integers, then an
-integer division is performed and the result is an integer. If either operand
-is a floating point value, a floating point division occurs, and the result is
-truncated toward zero to a floating-point integral value.
-
-The
-.code mod
-function performs a modulus operation. Firstly, the absolute value
-of
+argument is omitted. An implicit dividend is present, whose value is
+.codn 1.0 ,
+such that the one-argument form
+.code "(/ x)"
+is equivalent to the two-argument form
+.codn "(/ 1.0 x)" .
+
+If there are two or more arguments, explicitly or by the above equivalence,
+then a cumulative division is performed. The
.meta divisor
-is taken to be a modulus. Then a residue of
-.meta dividend
-with respect to
-.meta modulus
-is calculated. The residue's sign follows
-that of the sign of
-.metn divisor .
-That is, it is the smallest magnitude
-(closest to zero) residue of
-.meta dividend
-with respect to the absolute
-value of
-.metn divisor ,
-having the same sign as
-.metn divisor .
-If the operands are integer, the result is an integer. If either operand
-is of type float, then the result is a float. The modulus operation is
-then generalized into the floating point domain. For instance the expression
-.code "(mod 0.75 0.5)"
-yields a residue of 0.25 because 0.5 "goes into" 0.75 only
-once, with a "remainder" of 0.25.
-
-The
-.code trunc-rem
-function returns a list of two values: a
-.meta quotient
-and a
-.metn remainder .
-The
-.meta quotient
-is exactly the same value as what
-.code trunc
-would return for the same inputs.
-The
-.meta remainder
-obeys the following identity:
-
-.cblk
-.mets (eql < remainder (- < dividend >> (* divisor << quotient )))
-.cble
+value is taken into consideration, and divided by the first
+.codn divisor .
+If another
+.code divisor
+follows, then that value is divided by that subsequent divisor.
+This process repeats until all divisors are exhausted, and the
+value of the last division is returned.
.coNP Functions @ wrap and @ wrap*
.synb
@@ -31838,14 +31786,16 @@ is positive, it is returned. If
is negative, its additive inverse is
returned: a positive number of the same type with exactly the same magnitude.
-.coNP Functions @, floor @ ceil and @ round
+.coNP Functions @, trunc @, floor @ ceil and @ round
.synb
+.mets (trunc < dividend <> [ divisor ])
.mets (floor < dividend <> [ divisor ])
.mets (ceil < dividend <> [ divisor ])
.mets (round < dividend <> [ divisor ])
.syne
.desc
The
+.codn trunc ,
.codn floor ,
.code ceiling
and
@@ -31880,6 +31830,10 @@ and the result is a range composed of these two individual
quotients.
When the quotient is a scalar value,
+.code trunc
+returns the closest integer, in the zero direction,
+from the value of the quotient.
+The
.code floor
function returns the highest integer which does not exceed
the value of the quotient. That is to say, the division is
@@ -31916,6 +31870,62 @@ harmonizes with the semantics of the
.code round
function in the C language.
+.coNP Function @ mod
+.synb
+.mets (mod < dividend << divisor )
+.syne
+.desc
+The
+.code mod
+function performs a modulus operation. Firstly, the absolute value
+of
+.meta divisor
+is taken to be a modulus. Then a residue of
+.meta dividend
+with respect to
+.meta modulus
+is calculated. The residue's sign follows
+that of the sign of
+.metn divisor .
+That is, it is the smallest magnitude
+(closest to zero) residue of
+.meta dividend
+with respect to the absolute
+value of
+.metn divisor ,
+having the same sign as
+.metn divisor .
+If the operands are integer, the result is an integer. If either operand
+is of type float, then the result is a float. The modulus operation is
+then generalized into the floating point domain. For instance the expression
+.code "(mod 0.75 0.5)"
+yields a residue of 0.25 because 0.5 "goes into" 0.75 only
+once, with a "remainder" of 0.25.
+
+.coNP Function @ trunc-rem
+.synb
+.mets (trunc-rem < dividend << divisor )
+.syne
+.desc
+The
+.code trunc-rem
+function returns a list of two values: a
+.meta quotient
+and a
+.metn remainder .
+The
+.meta quotient
+is exactly the same value as what
+.code trunc
+would return for the same inputs.
+The
+.meta remainder
+obeys the following identity:
+
+.cblk
+.mets (eql < remainder (- < dividend >> (* divisor << quotient )))
+.cble
+
.coNP Functions @, sin @, cos @, tan @, asin @, acos @ atan and @ atan2
.synb
.mets (sin << radians )