Commit 8fce07c5 authored by Ben Boeckel's avatar Ben Boeckel

vtkSMCoreUtilities: Revert range adjustment logic

It seems that there is a code generation bug in GCC which has crept into
our binaries. For zero-length ranges near zero, the integer manipulation
logic does not work and comes out with a zero range again.

Debugging shows that the floating point values come out of the
AdjustTRange function fine, but are zero'd again when assigned back into
the double using the cvtss2sd instruction.

This reverts the following commits:

    "Add include needed for old gcc versions"
    commit d93bc11b

    "Update the tiny range delta to work when passing in doubles"
    commit fe2cf0b0

    "Fix strict aliasing warnings in vtkSMCoreUtilities AdjustRange"
    commit 450a1545

    "vtkSMCoreUtilities now adjusts ranges properly when min~=max."
    commit 604cbe44
parent 7db25af8
Pipeline #41171 passed with stage
......@@ -25,8 +25,6 @@
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
#include <sstream>
......@@ -142,32 +140,8 @@ bool vtkSMCoreUtilities::AdjustRangeForLog(double range[2])
return false;
}
namespace
{
template <typename T>
struct MinDelta
{
};
// This value seems to work well for float ranges we have tested
template <>
struct MinDelta<float>
{
static const int value = 65536;
};
// There are 29 more bits in a double's mantissa compared to a float. Shift the
// offset so that the 65536 is in the same position relative to the beginning of
// the mantissa. This causes the modified range to still be valid when it is
// downcast to float later on.
template <>
struct MinDelta<double>
{
static const vtkTypeInt64 value = static_cast<vtkTypeInt64>(65536) << 29;
};
//----------------------------------------------------------------------------
template <typename T, typename EquivSizeIntT>
bool AdjustTRange(T range[2], EquivSizeIntT)
bool vtkSMCoreUtilities::AdjustRange(double range[2])
{
if (range[1] < range[0])
{
......@@ -175,67 +149,24 @@ bool AdjustTRange(T range[2], EquivSizeIntT)
return false;
}
const bool spans_zero_boundary = range[0] < 0 && range[1] > 0;
if (spans_zero_boundary)
{ // nothing needs to be done, but this check is required.
// if we convert into integer space the delta difference will overflow
// an integer
return false;
// the range must be large enough, compared to values order of magnitude
double rangeOrderOfMagnitude = 1e-11;
if (rangeOrderOfMagnitude < std::abs(range[0]))
{
rangeOrderOfMagnitude = std::abs(range[0]);
}
EquivSizeIntT irange[2];
// needs to be a memcpy to avoid strict aliasing issues, doing a count
// of 2*sizeof(T) to couple both values at the same time
std::memcpy(irange, range, sizeof(T) * 2);
const EquivSizeIntT minDelta = MinDelta<T>::value;
// determine the absolute delta between these two numbers.
EquivSizeIntT delta = std::abs(irange[1] - irange[0]);
// if our delta is smaller than the min delta push out the max value
// so that it is equal to minRange + minDelta. When our range is entirely
// negative we should instead subtract from our max, to max a larger negative
// value
if (delta < minDelta && irange[1] < 0)
if (rangeOrderOfMagnitude < std::abs(range[1]))
{
irange[1] = irange[0] - minDelta;
// needs to be a memcpy to avoid strict aliasing issues
std::memcpy(range + 1, irange + 1, sizeof(T));
return true;
rangeOrderOfMagnitude = std::abs(range[1]);
}
if (delta < minDelta)
double rangeMinLength = rangeOrderOfMagnitude * 1e-5;
if ((range[1] - range[0]) < rangeMinLength)
{
irange[1] = irange[0] + minDelta;
// needs to be a memcpy to avoid strict aliasing issues
std::memcpy(range + 1, irange + 1, sizeof(T));
range[1] = range[0] + rangeMinLength;
return true;
}
return false;
}
}
//----------------------------------------------------------------------------
bool vtkSMCoreUtilities::AdjustRange(double range[2])
{
// when the values are between [-2, 2] and you push the max out you need to
// make sure you do it in float space, since if you do it in double space the
// values will be truncated downstream and be made equivalent again. Once
// you move out of this range the double space is generally not truncated
if (range[0] > -2 && range[0] < 2)
{
float frange[2] = { static_cast<float>(range[0]), static_cast<float>(range[1]) };
bool result = AdjustTRange(frange, int());
if (result)
{ // range should be left untouched to avoid loss of precision when no
// adjustment was needed
range[0] = static_cast<double>(frange[0]);
range[1] = static_cast<double>(frange[1]);
}
return result;
}
vtkTypeInt64 intType = 0;
return AdjustTRange(range, intType);
}
//----------------------------------------------------------------------------
void vtkSMCoreUtilities::PrintSelf(ostream& os, vtkIndent indent)
......
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