1use fearless_simd::{Level, dispatch, f32x4, prelude::*};
24
25#[cfg(target_arch = "aarch64")]
26use core::arch::aarch64::{float32x4_t, vcopyq_laneq_f32};
27#[cfg(target_arch = "x86")]
28use core::arch::x86::{__m128, _mm_blend_ps};
29#[cfg(target_arch = "x86_64")]
30use core::arch::x86_64::{__m128, _mm_blend_ps};
31
32fearless_simd::kernel!(
33 #[inline]
35 fn copy_alpha_neon(neon: Neon, a: float32x4_t, b: float32x4_t) -> float32x4_t {
36 vcopyq_laneq_f32::<3, 3>(a, b)
37 }
38);
39
40fearless_simd::kernel!(
41 #[inline]
43 fn copy_alpha_sse4_2(sse4_2: Sse4_2, a: __m128, b: __m128) -> __m128 {
44 _mm_blend_ps::<8>(a, b)
45 }
46);
47
48#[inline(always)] fn copy_alpha<S: Simd>(a: f32x4<S>, b: f32x4<S>) -> f32x4<S> {
54 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
55 if let Some(sse4_2) = a.simd.level().as_sse4_2() {
56 return copy_alpha_sse4_2(sse4_2, a.into(), b.into()).simd_into(a.simd);
57 }
58
59 #[cfg(target_arch = "aarch64")]
60 if let Some(neon) = a.simd.level().as_neon() {
61 return copy_alpha_neon(neon, a.into(), b.into()).simd_into(a.simd);
62 }
63
64 let mut result = a;
65 result[3] = b[3];
66 result
67}
68
69#[inline(always)] fn to_srgb<S: Simd>(simd: S, rgba: [f32; 4]) -> [f32; 4] {
72 let v: f32x4<S> = rgba.simd_into(simd);
73 let vabs = v.abs();
74 let x = vabs - 5.358_626_4e-4;
75 let x2 = x * x;
76 let even1 = x * -9.127_959e-1 + -2.881_431_4e-2;
77 let even2 = x2 * -7.291_929e-1 + even1;
78 let odd1 = x * 1.061_331_7 + 1.401_945_4;
79 let odd2 = x2 * 2.077_583e-1 + odd1;
80 let poly = odd2 * x.sqrt() + even2;
81 let lin = vabs * 12.92;
82 let z = vabs.simd_gt(0.0031308).select(poly, lin);
83 let z_signed = z.copysign(v);
84 let result = copy_alpha(z_signed, v);
85 result.into()
86}
87
88fn main() {
89 let level = Level::new();
90 let rgba = [0.1, -0.2, 0.001, 0.4];
91 let srgb = dispatch!(level, simd=> to_srgb(simd, rgba));
92 println!("{srgb:?}");
93}