export function nextAfterF16()

in src/webgpu/util/math.ts [272:327]


export function nextAfterF16(val: number, dir: NextDirection, mode: FlushMode): number {
  if (Number.isNaN(val)) {
    return val;
  }

  if (val === Number.POSITIVE_INFINITY) {
    return kValue.f16.positive.infinity;
  }

  if (val === Number.NEGATIVE_INFINITY) {
    return kValue.f16.negative.infinity;
  }

  assert(
    val <= kValue.f16.positive.max && val >= kValue.f16.negative.min,
    `${val} is not in the range of f16`
  );

  val = mode === 'flush' ? flushSubnormalNumberF16(val) : val;

  // -/+0 === 0 returns true
  if (val === 0) {
    if (dir === 'positive') {
      return mode === 'flush' ? kValue.f16.positive.min : kValue.f16.positive.subnormal.min;
    } else {
      return mode === 'flush' ? kValue.f16.negative.max : kValue.f16.negative.subnormal.max;
    }
  }

  nextAfterF16Float[0] = val; // This quantizes from number (f64) to f16
  if (
    (dir === 'positive' && nextAfterF16Float[0] <= val) ||
    (dir === 'negative' && nextAfterF16Float[0] >= val)
  ) {
    // val is either f16 precise or quantizing rounded in the opposite direction
    // from what is needed, so need to calculate the value in the correct
    // direction.
    const is_positive = (nextAfterF16Hex[0] & 0x8000) === 0;
    if (is_positive === (dir === 'positive')) {
      nextAfterF16Hex[0] += 1;
    } else {
      nextAfterF16Hex[0] -= 1;
    }
  }

  // Checking for overflow
  if ((nextAfterF16Hex[0] & 0x7c00) === 0x7c00) {
    if (dir === 'positive') {
      return kValue.f16.positive.infinity;
    } else {
      return kValue.f16.negative.infinity;
    }
  }

  return mode === 'flush' ? flushSubnormalNumberF16(nextAfterF16Float[0]) : nextAfterF16Float[0];
}