diff options
author | Adrián Medraño Calvo <adrian@medranocalvo.com> | 2018-07-13 11:24:32 (GMT) |
---|---|---|
committer | Adrián Medraño Calvo <adrian@medranocalvo.com> | 2018-07-13 11:24:32 (GMT) |
commit | f4f7bb6aaad924ee83d7cc6b5b90c7c89083b698 (patch) | |
tree | 0697daecd7a74acd5cfc8da737177ee67d23154d /generic | |
parent | 061316ced72f9e6bc09e36e8fb42b41465e953ce (diff) | |
download | blt-f4f7bb6aaad924ee83d7cc6b5b90c7c89083b698.zip blt-f4f7bb6aaad924ee83d7cc6b5b90c7c89083b698.tar.gz blt-f4f7bb6aaad924ee83d7cc6b5b90c7c89083b698.tar.bz2 |
Expand scale range to be at least DBL_EPSILON
A very small data range (from zero to a small floating point subnormal)
caused nTicks to be excessively big, ending up in a request for a huge
memory allocation for the axis.
This commit limits the number of ticks and the scale range to values
less than the floating point epsilon.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkbltGrAxis.C | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/generic/tkbltGrAxis.C b/generic/tkbltGrAxis.C index bac6316..8532600 100644 --- a/generic/tkbltGrAxis.C +++ b/generic/tkbltGrAxis.C @@ -819,18 +819,30 @@ void Axis::linearScale(double min, double max) double range = max - min; if (ops->reqStep > 0.0) { step = ops->reqStep; - while ((2 * step) >= range) + while ((2 * step) >= range && step >= (2 * DBL_EPSILON)) { step *= 0.5; - } + } + } else { range = niceNum(range, 0); step = niceNum(range / ops->reqNumMajorTicks, 1); } - - axisMin = tickMin = floor(min / step) * step + 0.0; - axisMax = tickMax = ceil(max / step) * step + 0.0; - - nTicks = (int)((tickMax-tickMin) / step) + 1; + if (step >= DBL_EPSILON) { + axisMin = tickMin = floor(min / step) * step + 0.0; + axisMax = tickMax = ceil(max / step) * step + 0.0; + nTicks = (int)((tickMax-tickMin) / step) + 1; + } else { + /* + * A zero step can result from having a too small range, such that + * the floating point can no longer represent fractions of it (think + * subnormals). In such a case, let's just have two steps: the + * minimum and the maximum. + */ + axisMin = tickMin = min; + axisMax = tickMax = min + DBL_EPSILON; + step = DBL_EPSILON; + nTicks = 2; + } } majorSweep_.step = step; majorSweep_.initial = tickMin; @@ -870,7 +882,7 @@ void Axis::setRange(AxisRange *rangePtr, double min, double max) rangePtr->max = max; rangePtr->range = max - min; if (fabs(rangePtr->range) < DBL_EPSILON) { - rangePtr->range = 1.0; + rangePtr->range = DBL_EPSILON; } rangePtr->scale = 1.0 / rangePtr->range; } |