% expr abs(0.0)
-0.0
Tcl version is 8.5.5, but it guess it's also in CVS (core-8-5-branch):
tclBasic.c (abs function)
7437 if (d <= 0.0) {
7438 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
7439 } else {
7440 Tcl_SetObjResult(interp, objv[1]);
7441 }
should be
7437 if (d < 0.0) {
7438 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
7439 } else {
7440 Tcl_SetObjResult(interp, objv[1]);
7441 }
Yes, this problem is in head as well.
And the same for TCL_NUMBER_LONG. There
the "<=" should be "<" as well. The effect is only
the unnecessary creation of an object, but still.....
Please fix. Thanks!
Turns out not that trivial to fix. See: also [Bug 1893815]
tcl::mathfunc commands and non-canonical string reps
Fixed in HEAD, to be backported to 8.5 and 8.4
Added some more tests, just to prove that the TCL_NUMBER_LONG was not quite right either. The problem
is that in ieee floating point math, -0.0 == 0.0 gives true! This means that you cannot really distinguish
-0.0 and 0.0 in floating point math.
Looking at the test cases, the rule seems to be:
- If the input looks negative, take the negative of the output and take that as a result.
- otherwise, take the unchanged input.
No, what looks negative? For example, -0.0 and -0 look negative, but really are
not: they are both forms of zero! Still, we want to output resp. 0.0 and 0 in those
cases. So, we need to distinguish between -0.0 and 0.0 (in the float case) and
between 0 and -0 (in the long case). How do we do that.
In the float case, we can use memcmp(). In the long case, I see no other way to look
for ´-´ characters (if there is a string representation). Anyway, this way I could
make all test cases pass.
For 8.4 the story is a little bit different. The only 'mistake' was that abs(-0.0) returns
-0.0, which is in fact correct, but not expected regarding the above rules. Numbers
like 1e-324 result in an underflow immediately in 8.4, it seems not worth to
fix that. But the abs(-0.0) case still can be fixed, therefore leaving this issue open.
In the 'long' case, if you've got -0 then you're on a ones-complement machine and we no longer guarantee Tcl to work right. :-)
>In the 'long' case, if you've got -0 then you're on a ones-complement
>machine and we no longer guarantee Tcl to work right. :-)
What happened, is that:
expr {abs(0x0)} --> 0
expr {abs(0x1)} --> 0x1
I would at least expect the two answers to
have the same form.... That's what this fix
is about in the "long" case
Oh no, I meant
::tcl::mathfunc::abs 0x0 --> 0 (old output) 0x0 (new output)
::tcl::mathfunc::abs 0x1 --> 0x1
That's what this fix is about regarding longs in Tcl 8.5/8.6. In
Tcl 8.4 there is no ::tcl::mathfunc::abs, so this is no issue.
Relevant test cases backported to Tcl 8.4 as well, and minor
fix applied to tclExecute.c to make them all pass.
DONE