rangeOfMatchingNumbers function

Tuple2<int, int> rangeOfMatchingNumbers(
  1. double value,
  2. double relativeDifference
)

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());
}