# [SciPy-dev] problems with amin/amax when nan present

eric eric at enthought.com
Fri Aug 16 02:11:29 CDT 2002

```Dave and I just ran across this NaN issue while working on Chaco:

>>> a = array([-1,0,1.])
>>> b = a/0.0
>>> b
array([             -inf,               nan,               inf])
>>> amin(b)
inf

This should be -inf.

>>> c = array((-1,b[1],1))
>>> c
array([-1.        ,         nan,  1.        ])
>>> amin(c)
1.0

This should be -1.

It looks like the NaNs are what cause the problems.  IF only -inf and
inf are present, they behave correctly:

>>> d=b.copy()
>>> d[1] = 0
>>> d
array([             -inf,   0.00000000e+000,               inf])
>>> amin(d)
-inf
>>> amax(d)
inf

So, I've found an ugly fix listed at the end of this message.  It will
make amin/amax slower (probably 2X) even for the case when NaNs aren't
present because it has to test for if any NaNs exists.  Correct is more
important than fast, but I was wondering if anyone has a better
solution.  We could test within the minimum/maximum methods in C using
isnan(), I suppose, to save the extra array creation.

Thanks,
eric

# fix.py
from scipy_base import *

def my_min(a,axis=-1):
nans = isnan(a)
has_nans = sometrue(ravel(nans))
if has_nans:
inf_in_array = sometrue(a == Inf,axis=axis)
b = a.copy()
else:
b = a
result = amin(b,axis)
if has_nans:
if type(result) is ArrayType:
logical_and(result == Inf,inf_in_array)),NaN)

elif (not inf_in_array) and (result == Inf):
result = NaN
return result

def my_max(a,axis=-1):
nans = isnan(a)
has_nans = sometrue(ravel(nans))
if has_nans:
neg_inf_in_array = sometrue(a == -Inf,axis=axis)
b = a.copy()
else:
b = a
result = amax(b,axis)
if has_nans:
if type(result) is ArrayType:
logical_and(result ==
-Inf,neg_inf_in_array)),NaN)
elif not(neg_inf_in_array) and (result == -Inf):
result = NaN
return result

a = array((-1.,0.,1.))
print 'a:', a
print 'min(a):', my_min(a)
print 'max(a):', my_max(a)

b = a/0.
print 'b:', b
print 'min(b):', my_min(b)
print 'max(b):', my_max(b)

c = array((0.,0.,0.))/0.
print 'c:', c
print 'min(c):', my_min(c)
print 'max(c):', my_max(c)

# [eric at enthoughtaus1 tmp]\$ python fix.py
# a: [-1.  0.  1.]
# min(a): -1.0
# max(a): 1.0
# b: [             -inf               nan               inf]
# min(b): -inf
# max(b): inf
# c: [              nan               nan               nan]
# min(c): nan
# max(c): nan

```