summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2015-01-12 16:38:00 +0000
committerPeter Stephenson <pws@zsh.org>2015-01-12 16:38:00 +0000
commit5f4325a0a41987a92cee8b64a76e5b0d5e831f60 (patch)
tree8d66f0afe363b606c5841aff3c0c8869c2da4c4d
parent626650f20e5c01fa6554da2a73dc5338a2523842 (diff)
downloadzsh-5f4325a0a41987a92cee8b64a76e5b0d5e831f60.tar.gz
zsh-5f4325a0a41987a92cee8b64a76e5b0d5e831f60.zip
Propagate float/integer type in arithmetic assignment.
Add test. Mention this and also floating point mod change in README.
-rw-r--r--ChangeLog3
-rw-r--r--README48
-rw-r--r--Src/math.c29
-rw-r--r--Test/C01arith.ztst10
4 files changed, 88 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index a9a44a379..4c29d89ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2015-01-12 Peter Stephenson <p.stephenson@samsung.com>
+ * 34255: README, Src/math.c, Test/C01arith.ztst: propagate type
+ from variable assignment. Also note 34230 in README.
+
* 34253: Doc/Zsh/contrib.yo: warning on integer arithmetic
for zcalc, c.f. 34194.
diff --git a/README b/README
index e3ccc70b1..218f27d58 100644
--- a/README
+++ b/README
@@ -35,6 +35,54 @@ Zsh is a shell with lots of features. For a list of some of these, see the
file FEATURES, and for the latest changes see NEWS. For more
details, see the documentation.
+Incompatibilites between 5.0.7 and 5.0.8
+----------------------------------------
+
+A couple of arithmetic operations have changed: the new behaviour
+is intended to be more consistent, but is not compatible with the old.
+
+Previously, the modulus operation, `%', implicitly converted the
+operation to integer and output an integer result, even if one
+or both of the arguments were floating point. Now, the C math
+library fmod() operator is used to implement the operation where
+one of the arguments is floating point. For example:
+
+Old behavour:
+
+% print $(( 5.5 % 2 ))
+1
+
+New behaviour:
+
+% print $(( 5.5 % 2 ))
+1.5
+
+Previously, assignments to variables assigned the correct type to
+variables declared as floating point or integer, but this type was
+not propagated to the value of the expression, as a C programmer
+would naturally expect. Now, the type of the variable is propagated
+so long as the variable is declared as a numeric type (however this
+happened, e.g. the variable may have been implicitly typed by a
+previous assignment). For example:
+
+Old behaviour:
+
+% integer var
+% print $(( var = 5.5 / 2.0 ))
+2.2000000000000002
+% print $var
+2
+
+(the actual rounding error may vary).
+
+New behaviour:
+
+% integer var
+% print $(( var = 5.5 / 2.0 ))
+2
+% print $var
+2
+
Incompatibilities between 5.0.2 and 5.0.5
-----------------------------------------
diff --git a/Src/math.c b/Src/math.c
index 6d096e0df..db42d0f7c 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -880,6 +880,8 @@ getcvar(char *s)
static mnumber
setmathvar(struct mathvalue *mvp, mnumber v)
{
+ Param pm;
+
if (mvp->pval) {
/*
* This value may have been hanging around for a while.
@@ -909,7 +911,32 @@ setmathvar(struct mathvalue *mvp, mnumber v)
if (noeval)
return v;
untokenize(mvp->lval);
- setnparam(mvp->lval, v);
+ pm = setnparam(mvp->lval, v);
+ if (pm) {
+ /*
+ * If we are performing an assignment, we return the
+ * number with the same type as the parameter we are
+ * assigning to, in the spirit of the way assignments
+ * in C work. Note this was a change to long-standing
+ * zsh behaviour.
+ */
+ switch (PM_TYPE(pm->node.flags)) {
+ case PM_INTEGER:
+ if (v.type != MN_INTEGER) {
+ v.u.l = (zlong)v.u.d;
+ v.type = MN_INTEGER;
+ }
+ break;
+
+ case PM_EFLOAT:
+ case PM_FFLOAT:
+ if (v.type != MN_FLOAT) {
+ v.u.d = (double)v.u.l;
+ v.type = MN_FLOAT;
+ }
+ break;
+ }
+ }
return v;
}
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index 8da17f7f4..8e0730d8d 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -16,7 +16,7 @@
print -- $(( rnd = there * 10000 ))
# save rounding problems by converting to integer
0:basic floating point arithmetic
->31415.
+>31415
integer rnd
(( rnd = ((29.1 % 13.0 * 10) + 0.5) ))
@@ -300,3 +300,11 @@
print $(( 0b2 ))
1:Binary numbers don't tend to have 2's in
?(eval):1: bad math expression: operator expected at `2 '
+
+ integer varassi
+ print $(( varassi = 5.5 / 2.0 ))
+ print $varassi
+0:Integer variable assignment converts result to integer
+>2
+>2
+# It's hard to test for integer to float.