hermes_simd_core/view/
unary.rs1use crate::align::Alignment;
2use crate::arch::SimdArch;
3use crate::execution::ExecutionMode;
4use crate::kernel::SimdKernel;
5use crate::ops::UnaryOp;
6use crate::scalar::Scalar;
7use crate::view::{SimdError, SimdView};
8
9impl<'a, T: 'a, Arch: SimdArch + SimdKernel<T>, Align: Alignment, Mode: ExecutionMode, Ref: 'a>
10 SimdView<'a, T, Arch, Align, Mode, Ref>
11where
12 T: Scalar,
13{
14 #[inline(always)]
22 pub fn map_unary<Op: UnaryOp<T>>(&self, op: Op, out: &mut [T]) -> Result<(), SimdError> {
23 let data = self.as_slice();
24 let len = data.len();
25 if out.len() < len {
26 return Err(SimdError::InsufficientOutputLength);
27 }
28 let lane_count = Arch::LANE_COUNT;
29 let simd_len = (len / lane_count) * lane_count;
30 let ptr_in = data.as_ptr();
31 let ptr_out = out.as_mut_ptr();
32
33 unsafe {
34 let load = |p: *const T| {
35 if crate::align::is_aligned_for_arch::<Arch, Align>() {
36 Arch::load_aligned(p)
37 } else {
38 Arch::load_unaligned(p)
39 }
40 };
41 let store = |p: *mut T, v: Arch::Vector| {
42 if crate::align::is_aligned_for_arch::<Arch, Align>()
45 && (p as usize) % Align::ALIGN_BYTES == 0
46 {
47 Arch::store_aligned(p, v)
48 } else {
49 Arch::store_unaligned(p, v)
50 }
51 };
52 for i in (0..simd_len).step_by(lane_count) {
53 let v = load(ptr_in.add(i));
54 let r = op.apply::<Arch>(v);
55 store(ptr_out.add(i), r);
56 }
57 }
58
59 for i in simd_len..len {
60 out[i] = op.apply_scalar(data[i]);
61 }
62
63 Ok(())
64 }
65}
66
67impl<'a, T: 'a, Arch: SimdArch + SimdKernel<T>, Align: Alignment, Mode: ExecutionMode>
68 SimdView<'a, T, Arch, Align, Mode, &'a mut [T]>
69where
70 T: Scalar,
71{
72 #[inline(always)]
77 pub fn map_unary_in_place<Op: UnaryOp<T>>(&mut self, op: Op) {
78 let slice = self.as_slice_mut();
79 let len = slice.len();
80 let lane_count = Arch::LANE_COUNT;
81 let simd_len = (len / lane_count) * lane_count;
82 let ptr = slice.as_mut_ptr();
83
84 unsafe {
85 let load = |p: *mut T| {
86 if crate::align::is_aligned_for_arch::<Arch, Align>() {
87 Arch::load_aligned(p)
88 } else {
89 Arch::load_unaligned(p)
90 }
91 };
92 let store = |p: *mut T, v: Arch::Vector| {
93 if crate::align::is_aligned_for_arch::<Arch, Align>() {
94 Arch::store_aligned(p, v)
95 } else {
96 Arch::store_unaligned(p, v)
97 }
98 };
99 for i in (0..simd_len).step_by(lane_count) {
100 let v = load(ptr.add(i));
101 let r = op.apply::<Arch>(v);
102 store(ptr.add(i), r);
103 }
104 }
105
106 for i in simd_len..len {
107 slice[i] = op.apply_scalar(slice[i]);
108 }
109 }
110}