function nearlyEqual (a, b, relTol = 1e-8, absTol = 0) {
  if (relTol <= 0) {
    throw new Error('Relative tolerance must be greater than 0')
  }

  if (absTol < 0) {
    throw new Error('Absolute tolerance must be at least 0')
  }

  // NaN
  if (isNaN(a) || isNaN(b)) {
    return false
  }

  if (!isFinite(a) || !isFinite(b)) {
    return a === b
  }

  if (a === b) {
    return true
  }

  // abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
  return Math.abs(a - b) <= Math.max(relTol * Math.max(Math.abs(a), Math.abs(b)), absTol)
}
Compares two floating point numbers.
@param {number} a - First value to compare
@param {number} b - Second value to compare
@param {number} [relTol=1e-09] - The relative tolerance, indicating the maximum allowed difference relative to the larger absolute value. Must be greater than 0.
@param {number} [absTol=1e-12] - The minimum absolute tolerance, useful for comparisons near zero. Must be at least 0.
@return {boolean} whether the two numbers are nearly equal

@throws {Error} If `relTol` is less than or equal to 0.
@throws {Error} If `absTol` is less than 0.

@example
nearlyEqual(1.000000001, 1.0, 1e-8);            // true
nearlyEqual(1.000000002, 1.0, 0);            // false
nearlyEqual(1.0, 1.009, undefined, 0.01);       // true
nearlyEqual(0.000000001, 0.0, undefined, 1e-8); // true