diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin new file mode 100644 index 000000000..115df177a --- /dev/null +++ b/core/math/fixed/fixed.odin @@ -0,0 +1,133 @@ +package math_fixed + +import "core:math" +import "core:strconv" + +import "intrinsics" +_ :: intrinsics; + +Fixed :: struct($Backing: typeid, Fraction_Width: uint) + where + intrinsics.type_is_integer(Backing), + 0 <= Fraction_Width, + Fraction_Width <= 8*size_of(Backing) { + i: Backing, +} + +Fixed4_4 :: distinct Fixed(i8, 4); +Fixed5_3 :: distinct Fixed(i8, 3); +Fixed6_2 :: distinct Fixed(i8, 2); +Fixed7_1 :: distinct Fixed(i8, 1); + +Fixed8_8 :: distinct Fixed(i16, 8); +Fixed13_3 :: distinct Fixed(i16, 3); + +Fixed16_16 :: distinct Fixed(i32, 16); +Fixed26_6 :: distinct Fixed(i32, 6); + +Fixed32_32 :: distinct Fixed(i64, 32); +Fixed52_12 :: distinct Fixed(i64, 12); + + +init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { + i, f := math.modf(val); + x.i = Backing(f * (1< f64 { + res := f64(x.i >> Fraction_Width); + res += f64(x.i & (1< T { + return {x.i + y.i}; +} +sub :: proc(x, y: $T/Fixed) -> T { + return {x.i - y.i}; +} + +mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { + z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width); + return; +} +mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { + z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width); + return; +} + +div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { + z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width); + return; +} +div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { + z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width); + return; +} + + +floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { + return x.i >> Fraction_Width; +} +ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { + Integer :: 8*size_of(Backing) - Fraction_Width; + return (x.i + (1 << Integer-1)) >> Fraction_Width; +} +round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { + Integer :: 8*size_of(Backing) - Fraction_Width; + return (x.i + (1 << (Integer - 1))) >> Fraction_Width; +} + + + +append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { + x := x; + buf: [48]byte; + i := 0; + if x.i < 0 { + buf[i] = '-'; + i += 1; + x.i = -x.i; + } + + integer := x.i >> Fraction_Width; + fraction := x.i & (1< 0 { + fraction *= 10; + buf[i] = byte('0' + (fraction>>Fraction_Width)); + i += 1; + fraction &= 1< string { + buf: [48]byte; + s := append(buf[:], x); + str := make([]byte, len(s), allocator); + copy(str, s); + return string(str); +}