summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2012-03-29 10:14:08 -0700
committerKaz Kylheku <kaz@kylheku.com>2012-03-29 10:14:08 -0700
commit9e60a829fdd3874f510ebc57d1a378d020a55fb9 (patch)
tree5b62dfc5b71484eedaa6932a08df1217ecbe1def
parent6363875356bc050ef81d40553e573fc47aca2e28 (diff)
downloadtxr-9e60a829fdd3874f510ebc57d1a378d020a55fb9.tar.gz
txr-9e60a829fdd3874f510ebc57d1a378d020a55fb9.tar.bz2
txr-9e60a829fdd3874f510ebc57d1a378d020a55fb9.zip
* arith.c (dmod): New static function.
(mod): Use dmod instead of fmod directly, to calculate the correct semantics for combinations of negative operands in the floating point domain also. * txr.1: Documented /, trunc and mod.
-rw-r--r--ChangeLog9
-rw-r--r--arith.c17
-rw-r--r--txr.138
3 files changed, 57 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 7bbaa80c..82e41883 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2012-03-29 Kaz Kylheku <kaz@kylheku.com>
+ * arith.c (dmod): New static function.
+ (mod): Use dmod instead of fmod directly, to calculate
+ the correct semantics for combinations of
+ negative operands in the floating point domain also.
+
+ * txr.1: Documented /, trunc and mod.
+
+2012-03-29 Kaz Kylheku <kaz@kylheku.com>
+
* txr.1: Documented +, - and *.
2012-03-29 Kaz Kylheku <kaz@kylheku.com>
diff --git a/arith.c b/arith.c
index 5dd42347..a8cfb578 100644
--- a/arith.c
+++ b/arith.c
@@ -737,6 +737,17 @@ divzero:
uw_throw(numeric_error_s, lit("trunc: division by zero"));
}
+static double dmod(double a, double b)
+{
+ if (b < 0.0) {
+ double m = fmod(-a, -b);
+ return - (m < 0.0 ? m - b : m);
+ } else {
+ double m = fmod(a, b);
+ return m < 0 ? m + b : m;
+ }
+}
+
val mod(val anum, val bnum)
{
tail:
@@ -785,7 +796,7 @@ tail:
return normalize(n);
}
case FLNUM:
- return flo(fmod(c_num(anum), c_flo(bnum)));
+ return flo(dmod(c_num(anum), c_flo(bnum)));
default:
break;
}
@@ -836,7 +847,7 @@ tail:
}
}
case FLNUM:
- return flo(fmod(c_flo(anum), c_num(bnum)));
+ return flo(dmod(c_flo(anum), c_num(bnum)));
default:
break;
}
@@ -867,7 +878,7 @@ tail:
return normalize(n);
}
case TYPE_PAIR(FLNUM, FLNUM):
- return flo(fmod(c_flo(anum), c_flo(bnum)));
+ return flo(dmod(c_flo(anum), c_flo(bnum)));
case TYPE_PAIR(BGNUM, FLNUM):
anum = flo_int(anum);
goto tail;
diff --git a/txr.1 b/txr.1
index af09709a..4a103abb 100644
--- a/txr.1
+++ b/txr.1
@@ -6772,7 +6772,7 @@ produces the sum over all of the arguments.
Similarly, the * function requires zero or more arguments. When called
with no arguments, it produces 1 (the identity element for multiplication).
-Otherwise it produces of all the arguments.
+Otherwise it produces the product of all the arguments.
The semantics of - changes from subtraction to additive inverse
when there is only one argument. The argument is treated as a subtrahend,
@@ -6806,7 +6806,7 @@ character, or subtracted from a character. For instance (- #\e9 #\e0) is 9.
The Unicode value of a character C can be found using (- C #\ex0): the
displacement from the NUL character.
-Therefore:
+The rules can be stated as a set of restrictions:
Two characters may not be added together.
@@ -6818,9 +6818,39 @@ in any operation.
A character may not be an operand of multiplication.
-.SS Arithmetic function *
+.SS Arithmetic functions /, trunc, mod
-.SS Arithmetic function /, trunc, mod
+.TP
+Syntax:
+
+ (/ <dividend> <divisor>)
+ (trunc <dividend> <divisor>)
+ (mod <dividend> <divisor>)
+
+Description:
+
+The arguments to these functions are numbers. Characters are not permitted.
+
+The / function performs floating-point division. Each operands is first
+converted to floating-point type, if necessary.
+
+The trunc function performs a division 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 mod function performs a modulus operation. Firstly, the absolute value
+of the divisor is taken to be a modulus. Then a residue of the dividend
+with respect to the modulus is calculated. The residue's sign follows
+that of the sign of the divisor. That is, it is the smallest magnitude
+(closest to zero) residue of the dividend with respect to the absolute
+value of the divisor, having the same sign as the 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
+(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.
.SS Arithmetic function gcd