From e66e9960d35ec530c1aaa90b146941ffb547ac6b Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 8 Mar 2025 12:28:25 +0200 Subject: [PATCH] math: fix `./v -prod -cstrict -cc gcc-11 vlib/math/math_bench_test.v` (use unions to implement f64_bits/1 and f64_from_bits/1 for compilers != tcc) --- vlib/math/math_bench_test.v | 2 +- vlib/math/unsafe.v | 50 +++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/vlib/math/math_bench_test.v b/vlib/math/math_bench_test.v index 43c76c4983..af31064e97 100644 --- a/vlib/math/math_bench_test.v +++ b/vlib/math/math_bench_test.v @@ -3,7 +3,7 @@ module main import math import benchmark -const max_iter = 1000 +const max_iter = 100_000 fn test_benchmark_acos() { mut x := 0.0 diff --git a/vlib/math/unsafe.v b/vlib/math/unsafe.v index dc91804197..68e6a42263 100644 --- a/vlib/math/unsafe.v +++ b/vlib/math/unsafe.v @@ -3,13 +3,24 @@ // that can be found in the LICENSE file. module math +union U32_F32 { + u u32 + f f32 +} + // f32_bits returns the IEEE 754 binary representation of f, // with the sign bit of f and the result in the same bit position. // f32_bits(f32_from_bits(x)) == x. @[inline] pub fn f32_bits(f f32) u32 { - p := *unsafe { &u32(&f) } - return p + $if tinyc { + return *unsafe { &u32(&f) } // this is faster for tcc, but causes `error: dereferencing type-punned pointer will break strict-aliasing rules` on gcc, with -cstrict + } + return unsafe { + U32_F32{ + f: f + }.u + } } // f32_from_bits returns the floating-point number corresponding @@ -18,8 +29,19 @@ pub fn f32_bits(f f32) u32 { // f32_from_bits(f32_bits(x)) == x. @[inline] pub fn f32_from_bits(b u32) f32 { - p := *unsafe { &f32(&b) } - return p + $if tinyc { + return *unsafe { &f32(&b) } + } + return unsafe { + U32_F32{ + u: b + }.f + } +} + +union U64_F64 { + u u64 + f f64 } // f64_bits returns the IEEE 754 binary representation of f, @@ -27,8 +49,14 @@ pub fn f32_from_bits(b u32) f32 { // and f64_bits(f64_from_bits(x)) == x. @[inline] pub fn f64_bits(f f64) u64 { - p := *unsafe { &u64(&f) } - return p + $if tinyc { + return *unsafe { &u64(&f) } + } + return unsafe { + U64_F64{ + f: f + }.u + } } // f64_from_bits returns the floating-point number corresponding @@ -37,8 +65,14 @@ pub fn f64_bits(f f64) u64 { // f64_from_bits(f64_bits(x)) == x. @[inline] pub fn f64_from_bits(b u64) f64 { - p := *unsafe { &f64(&b) } - return p + $if tinyc { + return *unsafe { &f64(&b) } + } + return unsafe { + U64_F64{ + u: b + }.f + } } // with_set_low_word sets low word of `f` to `lo`