It really doesn't make sense to me that a clamp() function would *limit to* a NaN.  I realize one can write various implementations that act differently here, but the principle of least surprise seems violated by letting a NaN be an actual end point IMO.  numpy.clip() seems to behave just right, FWIW.

If I'm asking for a value that is "not more than (less than) my bounds" I don't want all my values to become NaN's. by virtue of that.  A regular number is not affirmatively outside the bounds of a NaN in a commonsense way.  It's just not comparable to it at all.  So for that purpose—no determinable bound—a NaN amounts to the same thing as an Inf (but just for this purpose, they are very different in other contexts).

I guess I think of clamping as "pulling in the values that are *definitely* outside a range." Nothing is definite that way with a NaN.  So 'clamp(nan, -1, 1)' is conceptually 'nan' because the unknown value might or might not be "really" outside the range (but not definitely).  And likewise 'clamp(X, nan, nan)' has to be X because we can't *know* X is outside the range.

A NaN, conceptually, is a value that *might* exist, if only we knew more and could determine it.... but as is, it's just "unknown."

On Tue, Aug 2, 2016 at 4:50 PM, Chris Barker <chris.barker@noaa.gov> wrote:
On Tue, Aug 2, 2016 at 11:45 AM, Random832 <random832@fastmail.com> wrote:
Sure, but what the standard doesn't say is exactly what sequence of
comparisons is entailed by a clamp function.

def clamp(x, a, b):
    if x < a: return a
    else:
        if x > b: return b
        else: return x

def clamp(x, a, b):
    if a <= x:
        if x <= b: return x
        else: return b
    else: return a

There are, technically, eight possible naive implementations, varying
along three axes:

Exactly-- I thought this was self evident, but apparently not -- thanks for spelling it out.
 
All such functions are equivalent if {a, b, x} is a set over which the
relational operators define a total ordering, and a <= b. However, this
is not the case if NaN is used for any of the arguments.

Exactly again -- NaN's are kind of a pain :-(

As for the convert to floats issue -- correctness is more important than performance, and performance is probably most important for the special case of all floats. (or floats and integers, I suppose) -- i'm sure we can find a solution. LIkely something iike the second option above would work fine, and also work for anything with an ordinary total ordering.

-Chris


--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker@noaa.gov

_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/



--
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.