(and so are probably minCount, minPos, or mostly everything else that is related to opCmp).
From the discussion https://github.com/D-Programming-Language/phobos/pull/1360 :
min(0, float.nan); //Yields 0
max(0, float.nan); //Yields 0
min(float.nan, 0); //Yields float.nan
max(float.nan, 0); //Yields float.nan
Not sure what the correct solution is: Throwing an exception on NaN might be too expensive? How about an assert, combined with an explicit: "Passing nan is an ERROR", and let the user decide if/ifnot to pay for the check?
Comment #1 by thelastmammoth — 2013-06-22T13:13:06Z
(In reply to comment #0)
> (and so are probably minCount, minPos, or mostly everything else that is
> related to opCmp).
>
> From the discussion https://github.com/D-Programming-Language/phobos/pull/1360
> :
> min(0, float.nan); //Yields 0
> max(0, float.nan); //Yields 0
> min(float.nan, 0); //Yields float.nan
> max(float.nan, 0); //Yields float.nan
>
> Not sure what the correct solution is: Throwing an exception on NaN might be
> too expensive? How about an assert, combined with an explicit: "Passing nan is
> an ERROR", and let the user decide if/ifnot to pay for the check?
I don't see why one would throw on nan, and it would be expensive.
I believe the accepted convention is that nan is treated as missing data for min/max, so that
min(0, float.nan); //Yields 0
max(0, float.nan); //Yields 0
min(float.nan, 0); //Yields 0
max(float.nan, 0); //Yields 0
related discussion:
http://bytes.com/topic/c/answers/528404-max-nan-0-should-nan
matlab does it that way btw.
Comment #2 by simen.kjaras — 2013-06-22T13:16:30Z
Exactly. See documentation of fmax at http://man7.org/linux/man-pages/man3/fmax.3.html
Specifically:
If one argument is a NaN, the other argument is returned.
If both arguments are NaN, a NaN is returned.
Comment #3 by andrej.mitrovich — 2013-06-22T13:31:19Z
Then it needs to be documented in Phobos, and this fixed:
min(0, float.nan); //Yields 0
min(float.nan, 0); //Yields float.nan (should be 0 then?)
Comment #4 by bearophile_hugs — 2013-06-22T13:39:58Z
(In reply to comment #2)
> Exactly. See documentation of fmax at
> http://man7.org/linux/man-pages/man3/fmax.3.html
>
> Specifically:
> If one argument is a NaN, the other argument is returned.
>
> If both arguments are NaN, a NaN is returned.
Isn't it better for min(0, float.nan) to be NaN, just as max(0, float.nan) ?
Comment #5 by monarchdodra — 2013-06-22T14:47:00Z
(In reply to comment #4)
> (In reply to comment #2)
> > Exactly. See documentation of fmax at
> > http://man7.org/linux/man-pages/man3/fmax.3.html
> >
> > Specifically:
> > If one argument is a NaN, the other argument is returned.
> >
> > If both arguments are NaN, a NaN is returned.
>
> Isn't it better for min(0, float.nan) to be NaN, just as max(0, float.nan) ?
Yeah, that sounds like the better behavior: *anything* and nan is always nan.
Comment #6 by thelastmammoth — 2013-06-22T14:49:52Z
(In reply to comment #5)
> (In reply to comment #4)
> > (In reply to comment #2)
> > > Exactly. See documentation of fmax at
> > > http://man7.org/linux/man-pages/man3/fmax.3.html
> > >
> > > Specifically:
> > > If one argument is a NaN, the other argument is returned.
> > >
> > > If both arguments are NaN, a NaN is returned.
> >
> > Isn't it better for min(0, float.nan) to be NaN, just as max(0, float.nan) ?
>
> Yeah, that sounds like the better behavior: *anything* and nan is always nan.
that would indeed seem more logical, although:
* it differs from standard practice
* it incurs additional cost, compared to : return a<b?a:b; because you'd have to check for isNan
Comment #7 by monarchdodra — 2013-06-22T14:59:55Z
(In reply to comment #6)
> (In reply to comment #5)
> > (In reply to comment #4)
> > > (In reply to comment #2)
> > > > Exactly. See documentation of fmax at
> > > > http://man7.org/linux/man-pages/man3/fmax.3.html
> > > >
> > > > Specifically:
> > > > If one argument is a NaN, the other argument is returned.
> > > >
> > > > If both arguments are NaN, a NaN is returned.
> > >
> > > Isn't it better for min(0, float.nan) to be NaN, just as max(0, float.nan) ?
> >
> > Yeah, that sounds like the better behavior: *anything* and nan is always nan.
>
> that would indeed seem more logical, although:
>
> * it differs from standard practice
> * it incurs additional cost, compared to : return a<b?a:b; because you'd have
> to check for isNan
"return a<b?a:b;" doesn't work: you'd have to check for nan regardless of which you return.
Comment #8 by thelastmammoth — 2013-06-22T15:11:43Z
(In reply to comment #7)
> (In reply to comment #6)
> > (In reply to comment #5)
> > > (In reply to comment #4)
> > > > (In reply to comment #2)
> > > > > Exactly. See documentation of fmax at
> > > > > http://man7.org/linux/man-pages/man3/fmax.3.html
> > > > >
> > > > > Specifically:
> > > > > If one argument is a NaN, the other argument is returned.
> > > > >
> > > > > If both arguments are NaN, a NaN is returned.
> > > >
> > > > Isn't it better for min(0, float.nan) to be NaN, just as max(0, float.nan) ?
> > >
> > > Yeah, that sounds like the better behavior: *anything* and nan is always nan.
> >
> > that would indeed seem more logical, although:
> >
> > * it differs from standard practice
> > * it incurs additional cost, compared to : return a<b?a:b; because you'd have
> > to check for isNan
>
> "return a<b?a:b;" doesn't work: you'd have to check for nan regardless of which
> you return.
my bad, which is probably why the current min is buggy.
In that case since there's no penalty might as well do the safest thing, ie returning nan, and provide a minIgnoresNan to do the 'standard behavior', which will return 0 instead of nan.
Comment #10 by ilyayaroshenko — 2016-08-02T20:07:24Z
Default behavior should be that min/max be translated to the single assembler instruction, which can be vectorized. Compiler may have intrinsics for min/max and we should just use them. See also https://llvm.org/bugs/show_bug.cgi?id=24314
Comment #11 by dlang-bugzilla — 2017-07-05T20:10:12Z
@crocopaw created dlang/phobos pull request #7181 "Fix Issue 10448 - min and max are not NaN aware" fixing this issue:
- Fix Issue 10448 - min and max are not NaN aware
https://github.com/dlang/phobos/pull/7181
Comment #13 by dlang — 2019-09-11T12:31:08Z
As experts do not agree on the prefered result I think it's best to document, that NaNs will result in undefined behaviour.
See https://github.com/dlang/phobos/pull/7181 for more details.
Comment #14 by dlang-bot — 2019-10-21T09:49:07Z
@berni44 created dlang/phobos pull request #7240 "Fix Issue 10448 - min and max are not NaN aware" fixing this issue:
- Fix Issue 10448 - min and max are not NaN aware
https://github.com/dlang/phobos/pull/7240
Comment #15 by dlang-bot — 2019-10-21T22:29:13Z
dlang/phobos pull request #7240 "Fix Issue 10448 - min and max are not NaN aware" was merged into master:
- 0320d88c3aecb5af38b68fc2efcbf661d07190a1 by Bernhard Seckinger:
Fix Issue 10448 - min and max are not NaN aware
https://github.com/dlang/phobos/pull/7240