(a_hot: &[u8], b_hot: &[u8], dim: usize)
| 56 | |
| 57 | #[cfg(target_arch = "aarch64")] |
| 58 | fn ternary_dot_neon(a_hot: &[u8], b_hot: &[u8], dim: usize) -> i32 { |
| 59 | use std::arch::aarch64::*; |
| 60 | |
| 61 | let a_trits = unpack_hot(a_hot, dim); |
| 62 | let b_trits = unpack_hot(b_hot, dim); |
| 63 | |
| 64 | let len = a_trits.len(); |
| 65 | let chunks = len / 16; |
| 66 | let mut acc: i32; |
| 67 | |
| 68 | unsafe { |
| 69 | let mut sum = vdupq_n_s32(0i32); |
| 70 | for i in 0..chunks { |
| 71 | let a_ptr = a_trits.as_ptr().add(i * 16); |
| 72 | let b_ptr = b_trits.as_ptr().add(i * 16); |
| 73 | let a_vec = vld1q_s8(a_ptr); |
| 74 | let b_vec = vld1q_s8(b_ptr); |
| 75 | let prod = vmulq_s8(a_vec, b_vec); |
| 76 | let prod_lo = vmovl_s8(vget_low_s8(prod)); |
| 77 | let prod_hi = vmovl_s8(vget_high_s8(prod)); |
| 78 | let prod32_lo = vmovl_s16(vget_low_s16(prod_lo)); |
| 79 | let prod32_hi = vmovl_s16(vget_high_s16(prod_lo)); |
| 80 | let prod32_lo2 = vmovl_s16(vget_low_s16(prod_hi)); |
| 81 | let prod32_hi2 = vmovl_s16(vget_high_s16(prod_hi)); |
| 82 | sum = vaddq_s32( |
| 83 | sum, |
| 84 | vaddq_s32( |
| 85 | vaddq_s32(prod32_lo, prod32_hi), |
| 86 | vaddq_s32(prod32_lo2, prod32_hi2), |
| 87 | ), |
| 88 | ); |
| 89 | } |
| 90 | acc = vaddvq_s32(sum); |
| 91 | for i in (chunks * 16)..len { |
| 92 | acc += a_trits[i] as i32 * b_trits[i] as i32; |
| 93 | } |
| 94 | } |
| 95 | acc |
| 96 | } |
| 97 | |
| 98 | type DotFn = fn(&[u8], &[u8], usize) -> i32; |
| 99 |
nothing calls this directly
no test coverage detected