1#![expect(
5 clippy::excessive_precision,
6 missing_docs,
7 reason = "TODO: https://github.com/linebender/fearless_simd/issues/40"
8)]
9
10use fearless_simd::{Level, Select, Simd, SimdInto, f32x4, simd_dispatch};
11
12#[cfg(feature = "safe_wrappers")]
15#[inline(always)]
16fn copy_alpha<S: Simd>(a: f32x4<S>, b: f32x4<S>) -> f32x4<S> {
17 #[cfg(target_arch = "aarch64")]
25 if let Some(neon) = a.simd.level().as_neon() {
26 return neon
27 .neon
28 .vcopyq_laneq_f32::<3, 3>(a.into(), b.into())
29 .simd_into(a.simd);
30 }
31 let mut result = a;
32 result[3] = b[3];
33 result
34}
35
36#[cfg(not(feature = "safe_wrappers"))]
38#[inline(always)]
39fn copy_alpha<S: Simd>(a: f32x4<S>, b: f32x4<S>) -> f32x4<S> {
40 #[cfg(target_arch = "aarch64")]
41 if let Some(_neon) = a.simd.level().as_neon() {
42 unsafe {
43 return core::arch::aarch64::vcopyq_laneq_f32::<3, 3>(a.into(), b.into())
44 .simd_into(a.simd);
45 }
46 }
47 let mut result = a;
48 result[3] = b[3];
49 result
50}
51
52#[inline(always)]
53fn to_srgb_impl<S: Simd>(simd: S, rgba: [f32; 4]) -> [f32; 4] {
54 let v: f32x4<S> = rgba.simd_into(simd);
55 let vabs = v.abs();
56 let x = vabs - 5.35862651e-04;
57 let x2 = x * x;
58 let even1 = x * -9.12795913e-01 + -2.88143143e-02;
59 let even2 = x2 * -7.29192910e-01 + even1;
60 let odd1 = x * 1.06133172e+00 + 1.40194533e+00;
61 let odd2 = x2 * 2.07758287e-01 + odd1;
62 let poly = odd2 * x.sqrt() + even2;
63 let lin = vabs * 12.92;
64 let z = vabs.simd_gt(0.0031308).select(poly, lin);
65 let z_signed = z.copysign(v);
66 let result = copy_alpha(z_signed, v);
67 result.into()
68}
69
70simd_dispatch!(fn to_srgb(level, rgba: [f32; 4]) -> [f32; 4] = to_srgb_impl);
71
72fn main() {
73 let level = Level::new();
74 let rgba = [0.1, -0.2, 0.001, 0.4];
75 println!("{:?}", to_srgb(level, rgba));
76}