rangeOfMatchingNumbers function
Determines the range of that will match the specified value with the given tolerance.
Returns tuple with the number of ULPS between the value
and
the value - relativeDifference
as first, and the number of ULPS between
the value
and the value + relativeDifference
as second value.
Throws ArgumentError if relativeDifference
is smaller than zero.
Throws ArgumentError if value
is double.infinity
or double.negativeInfinity
.
Throws ArgumentError if value
is double.nan
.
Implementation
Tuple2<int, int> rangeOfMatchingNumbers(
double value, double relativeDifference) {
// Make sure the relative is non-negative
if (relativeDifference < 0) {
throw ArgumentError.value(
relativeDifference, 'relativeDifference', messages.argumentNotNegative);
}
// If the value is infinity (positive or negative) then
// we can't determine the range.
if (value.isInfinite) {
throw ArgumentError('Value is infinite.');
}
// If the value is a NaN then we can't determine the range.
if (value.isNaN) {
throw ArgumentError('Value is not a number.');
}
// If the value is zero (0.0) then we can't calculate the relative difference
// so return the ulps counts for the difference.
if (value.compareTo(0.0) == 0) {
var bytes = ByteData(8);
bytes.setFloat64(0, relativeDifference);
var v = bytes.getInt64(0);
return Tuple2<int, int>(v, v);
}
// Calculate the ulps for the maximum and minimum values
// Note that these can overflow
int max = asDirectionalInt64(value + (relativeDifference * value.abs()));
int min = asDirectionalInt64(value - (relativeDifference * value.abs()));
// Calculate the ulps from the value
int intValue = asDirectionalInt64(value);
// Determine the ranges
return Tuple2<int, int>((intValue - min).abs(), (max - intValue).abs());
}