Research-Stack/5-Applications/scripts/q16_arithmetic.wgsl
allaun 475f6319ea chore(repo): push local 768-commit branch state onto clean remote baseline
This squashes all local history (768 commits) onto the scrubbed PR #90
baseline. Individual commits were lost during filter-repo corruption;
the working tree content is preserved intact.

Build: N/A (working tree state only)
2026-06-15 22:46:50 -05:00

78 lines
2 KiB
WebGPU Shading Language

// Q16_16 fixed-point arithmetic — shared include
//
// This file is a shared WGSL include. The build pipeline should prepend
// this file to any shader that depends on it, e.g.:
// cat q16_arithmetic.wgsl target_shader.wgsl > combined.wgsl
//
// Scale: 2^16 = 65536
const Q16_SCALE: u32 = 65536u;
const Q16_ONE: u32 = 0x00010000u;
const SIGN_BIT: u32 = 0x80000000u;
const TWO_POW_32: u32 = 0x100000000u;
// Extract sign bit as i32 (WGSL: u32 -> bool)
fn is_neg(v: u32) -> bool {
return (v & SIGN_BIT) != 0u;
}
// Convert unsigned Q16_16 to signed integer
fn q16_to_int(v: u32) -> i32 {
return bitcast<i32>(v);
}
// Convert signed integer to unsigned Q16_16
fn int_to_q16(v: i32) -> u32 {
return bitcast<u32>(v);
}
// Q16_16 multiplication: (a * b) >> 16
fn q16_mul(a: u32, b: u32) -> u32 {
let a_signed = q16_to_int(a);
let b_signed = q16_to_int(b);
let product = i64(a_signed) * i64(b_signed);
let result = i32(product >> 16);
return bitcast<u32>(result);
}
// Q16_16 division: (a << 16) / b
fn q16_div(a: u32, b: u32) -> u32 {
let a_signed = q16_to_int(a);
let b_signed = q16_to_int(b);
let num = i64(a_signed) << 16;
let result = i32(num / i64(b_signed));
return bitcast<u32>(result);
}
// Q16_16 negation
fn q16_neg(a: u32) -> u32 {
return int_to_q16(-q16_to_int(a));
}
// Q16_16 absolute value
fn q16_abs(a: u32) -> u32 {
let s = q16_to_int(a);
return select(a, q16_neg(a), is_neg(a));
}
// Q16_16 addition (saturating)
fn q16_add(a: u32, b: u32) -> u32 {
let result = q16_to_int(a) + q16_to_int(b);
return int_to_q16(result);
}
// Q16_16 subtraction (saturating)
fn q16_sub(a: u32, b: u32) -> u32 {
let result = q16_to_int(a) - q16_to_int(b);
return int_to_q16(result);
}
// Q16_16 maximum
fn q16_max(a: u32, b: u32) -> u32 {
return select(b, a, q16_to_int(a) > q16_to_int(b));
}
// Q16_16 minimum
fn q16_min(a: u32, b: u32) -> u32 {
return select(b, a, q16_to_int(a) < q16_to_int(b));
}