in src/webgpu/util/math.ts [191:246]
export function nextAfterF32(val: number, dir: NextDirection, mode: FlushMode): number {
if (Number.isNaN(val)) {
return val;
}
if (val === Number.POSITIVE_INFINITY) {
return kValue.f32.positive.infinity;
}
if (val === Number.NEGATIVE_INFINITY) {
return kValue.f32.negative.infinity;
}
assert(
val <= kValue.f32.positive.max && val >= kValue.f32.negative.min,
`${val} is not in the range of f32`
);
val = mode === 'flush' ? flushSubnormalNumberF32(val) : val;
// -/+0 === 0 returns true
if (val === 0) {
if (dir === 'positive') {
return mode === 'flush' ? kValue.f32.positive.min : kValue.f32.positive.subnormal.min;
} else {
return mode === 'flush' ? kValue.f32.negative.max : kValue.f32.negative.subnormal.max;
}
}
nextAfterF32Float[0] = val; // This quantizes from number (f64) to f32
if (
(dir === 'positive' && nextAfterF32Float[0] <= val) ||
(dir === 'negative' && nextAfterF32Float[0] >= val)
) {
// val is either f32 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 = (nextAfterF32Int[0] & 0x80000000) === 0;
if (is_positive === (dir === 'positive')) {
nextAfterF32Int[0] += 1;
} else {
nextAfterF32Int[0] -= 1;
}
}
// Checking for overflow
if ((nextAfterF32Int[0] & 0x7f800000) === 0x7f800000) {
if (dir === 'positive') {
return kValue.f32.positive.infinity;
} else {
return kValue.f32.negative.infinity;
}
}
return mode === 'flush' ? flushSubnormalNumberF32(nextAfterF32Float[0]) : nextAfterF32Float[0];
}