Commit 06d553fb authored by Utkarsh Ayachit's avatar Utkarsh Ayachit

BUG #15438: Handle NaN when computing array range.

A small tweak to the vtkDataArrayPrivate makes it possible for us to
handle NaN in arrays when computing ranges. We should not include NaN
when computing the range. By ensuring that the "left" argument to the
min/max functions is never a NaN, we are assured that they min/max calls
won't return a NaN.

Also added a test for the same.
parent 202b3b42
......@@ -29,16 +29,21 @@ namespace msvc
// Those min and max functions replace std ones because their
// implementation used to generate very slow code with MSVC.
// See https://randomascii.wordpress.com/2013/11/24/stdmin-causing-three-times-slowdown-on-vc/
// The comparison expression in min/max are written so that if the "condition" is false,
// the "left" value is returned. This is consistent with STL's implementations
// and also handles the cases where the right value may be a NaN properly.
// All code using these methods should ensure that the "left" value is never
// NaN.
template <class ValueType>
ValueType max(const ValueType& left, const ValueType& right)
{
return left > right ? left : right;
return right > left ? right : left;
}
template <class ValueType>
ValueType min(const ValueType& left, const ValueType& right)
{
return left <= right ? left : right;
return right <= left ? right : left;
}
}
#endif
......@@ -74,8 +79,8 @@ struct ComputeScalarRange
{
for(int i = 0, j = 0; i < NumComps; ++i, j+=2)
{
tempRange[j] = detail::min(value[i], tempRange[j]);
tempRange[j+1] = detail::max(value[i], tempRange[j+1]);
tempRange[j] = detail::min(tempRange[j], value[i]);
tempRange[j+1] = detail::max(tempRange[j+1], value[i]);
}
}
......@@ -164,8 +169,8 @@ bool DoComputeScalarRange(InputIteratorType begin, InputIteratorType end,
{
for(int i = 0, j = 0; i < numComp; ++i, j+=2)
{
tempRange[j] = detail::min(value[i], tempRange[j]);
tempRange[j+1] = detail::max(value[i], tempRange[j+1]);
tempRange[j] = detail::min(tempRange[j], value[i]);
tempRange[j+1] = detail::max(tempRange[j+1], value[i]);
}
}
......@@ -210,8 +215,8 @@ bool DoComputeVectorRange(InputIteratorType begin, InputIteratorType end,
const double t = static_cast<double>(value[i]);
squaredSum += t * t;
}
range[0] = detail::min(squaredSum, range[0]);
range[1] = detail::max(squaredSum, range[1]);
range[0] = detail::min(range[0], squaredSum);
range[1] = detail::max(range[1], squaredSum);
}
//now that we have computed the smallest and largest value, take the
......
vtk_add_test_python(
TestExodusPolyhedra.py
TestExodusWithNaN.py,NO_RT,NO_VALID
)
#!/usr/bin/env python
# This test loads an Exodus file with NaNs and we test that the vtkDataArray
# returns a correct range for the array with NaNs i.e. not including the NaN.
from vtk import *
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
rdr = vtkExodusIIReader()
rdr.SetFileName(str(VTK_DATA_ROOT) + "/Data/cyl_with_NaN.g")
rdr.UpdateInformation()
rdr.SetPointResultArrayStatus("dist_from_origin", 1);
rdr.Update()
data = rdr.GetOutput().GetBlock(0).GetBlock(0)
# Test that this dataset with NaNs gets a correct range i.e. range without NaNs
# in it.
drange = data.GetPointData().GetArray("dist_from_origin").GetRange()[:]
print "'dist_from_origin' Range: ", drange
assert (abs(drange[0] - 0.5) < 1e-3) and (abs(drange[1] - 1.118) < 1e-3)
df330c4e2d7603b5d7c16d54b1d4d43f
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment