Bug 3240 – std.numeric.findRoot only works with real
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2009-08-10T03:04:00Z
Last change time
2015-06-09T01:28:05Z
Assigned to
andrei
Creator
bugzilla
Comments
Comment #0 by bugzilla — 2009-08-10T03:04:36Z
Trying to use std.numeric.findRoot with other types than real gives template instantiation errors originating from lines 599 and 560 in numeric.d (DMD 2.031, SVN rev. 1200):
599 if (a==0) c = ieeeMean(copysign(0.0L, b), b);
560 else if (b==0) c = ieeeMean(copysign(0.0L, a), a);
If a and b are double, I get the following errors:
/usr/local/include/d/phobos2/std/numeric.d(599): Error: template std.math.ieeeMean(T) does not match any function template declaration
/usr/local/include/d/phobos2/std/numeric.d(599): Error: template std.math.ieeeMean(T) cannot deduce template function from argument types !()(real,double)
/usr/local/include/d/phobos2/std/numeric.d(600): Error: template std.math.ieeeMean(T) does not match any function template declaration
/usr/local/include/d/phobos2/std/numeric.d(600): Error: template std.math.ieeeMean(T) cannot deduce template function from argument types !()(real,double)
This is because IFTI doesn't work with implicit conversions (bug 1641 and probably others), and std.math.copysign() always returns a real.
Comment #1 by bugzilla — 2009-08-10T03:29:47Z
Um.. like the actual pasted error messages say, the line numbers should be 599 and 600, not 500 and 560. Sorry, don't know how that happened.
Comment #2 by clugdbug — 2009-08-10T04:40:17Z
Good catch. That's caused by a change to the signature of ieeeMean(). Trivially fixable by inserting casts, though arguably copySign should become a templated function.
BTW I wrote this code for Tango, it will eventually have a signature change to match the new Phobos style. It predates ranges, for example, even though it's a perfect example of a floating-point range-based algorithm. Thus, it's not as generic as it could be.
Don.
Comment #3 by bugzilla — 2009-08-10T04:50:09Z
There's an even simpler fix -- i.e. less typing. :)
Since both a, b and c are of type T, this also works:
599 if (a==0) c = ieeeMean!T(copysign(0.0L, b), b);
600 else if (b==0) c = ieeeMean!T(copysign(0.0L, a), a);
I've added this fix to my local Phobos. I just tried this for fun, and expected to get an error from trying to implicitly cast real to double. But for some reason it worked.
Comment #4 by andrei — 2009-08-10T07:14:55Z
(In reply to comment #3)
> There's an even simpler fix -- i.e. less typing. :)
>
> Since both a, b and c are of type T, this also works:
>
> 599 if (a==0) c = ieeeMean!T(copysign(0.0L, b), b);
> 600 else if (b==0) c = ieeeMean!T(copysign(0.0L, a), a);
>
> I've added this fix to my local Phobos. I just tried this for fun, and expected
> to get an error from trying to implicitly cast real to double. But for some
> reason it worked.
Don, sorry, I took this over before seeing you are considering working on it. You may want to take ownership. Thanks!