diff options
Diffstat (limited to 'Userland/Libraries/LibSoftGPU')
-rw-r--r-- | Userland/Libraries/LibSoftGPU/SIMD.h | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/Userland/Libraries/LibSoftGPU/SIMD.h b/Userland/Libraries/LibSoftGPU/SIMD.h index 4e16c92c25..e24c198c37 100644 --- a/Userland/Libraries/LibSoftGPU/SIMD.h +++ b/Userland/Libraries/LibSoftGPU/SIMD.h @@ -103,4 +103,25 @@ ALWAYS_INLINE static Vector2<AK::SIMD::f32x4> ddy(Vector2<AK::SIMD::f32x4> const }; } +// Calculates a quadratic approximation of log2, exploiting the fact that IEEE754 floats are represented as mantissa * 2^exponent. +// See https://stackoverflow.com/questions/9411823/fast-log2float-x-implementation-c +ALWAYS_INLINE static AK::SIMD::f32x4 log2_approximate(AK::SIMD::f32x4 v) +{ + union { + AK::SIMD::f32x4 float_val; + AK::SIMD::i32x4 int_val; + } u { v }; + + // Extract just the exponent minus 1, giving a lower integral bound for log2. + auto log = AK::SIMD::to_f32x4(((u.int_val >> 23) & 255) - 128); + + // Replace the exponent with 0, giving a value between 1 and 2. + u.int_val &= ~(255 << 23); + u.int_val |= 127 << 23; + + // Approximate log2 by adding a quadratic function of u to the integral part. + log += (-0.34484843f * u.float_val + 2.02466578f) * u.float_val - 0.67487759f; + return log; +} + } |