| export const description = `Special and sample values for WGSL scalar types`; |
| |
| import { assert } from '../../common/util/util.js'; |
| import { uint32ToFloat32 } from '../util/conversion.js'; |
| |
| /** Returns an array of subnormal f32 numbers. |
| * Subnormals are non-zero finite numbers with the minimum representable |
| * exponent. |
| */ |
| export function subnormalF32Examples(): Array<number> { |
| // The results, as uint32 values. |
| const result_as_bits: number[] = []; |
| |
| const max_mantissa = 0x7f_ffff; |
| const sign_bits = [0, 0x8000_0000]; |
| for (const sign_bit of sign_bits) { |
| // exponent bits must be zero. |
| const sign_and_exponent = sign_bit; |
| |
| // Set all bits |
| result_as_bits.push(sign_and_exponent | max_mantissa); |
| |
| // Set each of the lower bits individually. |
| for (let lower_bits = 1; lower_bits <= max_mantissa; lower_bits <<= 1) { |
| result_as_bits.push(sign_and_exponent | lower_bits); |
| } |
| } |
| assert( |
| result_as_bits.length === 2 * (1 + 23), |
| 'subnormal number sample count is ' + result_as_bits.length.toString() |
| ); |
| return result_as_bits.map(u => uint32ToFloat32(u)); |
| } |
| |
| /** Returns an array of normal f32 numbers. |
| * Normal numbers are not: zero, Nan, infinity, subnormal. |
| */ |
| export function normalF32Examples(): Array<number> { |
| const result: number[] = [1.0, -2.0]; |
| |
| const max_mantissa_as_bits = 0x7f_ffff; |
| const min_exponent_as_bits = 0x0080_0000; |
| const max_exponent_as_bits = 0x7f00_0000; // Max normal exponent |
| const sign_bits = [0, 0x8000_0000]; |
| for (const sign_bit of sign_bits) { |
| for (let e = min_exponent_as_bits; e <= max_exponent_as_bits; e += min_exponent_as_bits) { |
| const sign_and_exponent = sign_bit | e; |
| |
| // Set zero mantissa bits |
| result.push(uint32ToFloat32(sign_and_exponent)); |
| // Set all mantissa bits |
| result.push(uint32ToFloat32(sign_and_exponent | max_mantissa_as_bits)); |
| |
| // Set each of the lower bits individually. |
| for (let lower_bits = 1; lower_bits <= max_mantissa_as_bits; lower_bits <<= 1) { |
| result.push(uint32ToFloat32(sign_and_exponent | lower_bits)); |
| } |
| } |
| } |
| assert( |
| result.length === 2 + 2 * 254 * 25, |
| 'normal number sample count is ' + result.length.toString() |
| ); |
| return result; |
| } |
| |
| /** Returns an array of 32-bit NaNs, as Uint32 bit patterns. |
| * NaNs have: maximum exponent, but the mantissa is not zero. |
| */ |
| export function nanF32BitsExamples(): Array<number> { |
| const result: number[] = []; |
| const exponent_bit = 0x7f80_0000; |
| const sign_bits = [0, 0x8000_0000]; |
| for (const sign_bit of sign_bits) { |
| const sign_and_exponent = sign_bit | exponent_bit; |
| const bits = sign_and_exponent | 0x40_0000; |
| // Only the most significant bit of the mantissa is set. |
| result.push(bits); |
| |
| // Quiet and signalling NaNs differ based on the most significant bit |
| // of the mantissa. Try both. |
| for (const quiet_signalling of [0, 0x40_0000]) { |
| // Set each of the lower bits. |
| for (let lower_bits = 1; lower_bits < 0x40_0000; lower_bits <<= 1) { |
| const bits = sign_and_exponent | quiet_signalling | lower_bits; |
| result.push(bits); |
| } |
| } |
| } |
| return result; |
| } |