1use crate::{
2 blas::block::{MatrixBlock, MatrixBlockSlice},
3 limb::Limb,
4};
5
6pub(super) fn add_simd(target: &mut [Limb], source: &[Limb], min_limb: usize) {
7 for (target_limb, source_limb) in target.iter_mut().zip(source.iter()).skip(min_limb) {
8 *target_limb ^= source_limb
9 }
10}
11
12pub(super) fn gather_block_simd(slice: MatrixBlockSlice) -> MatrixBlock {
13 let mut limbs = [0; 64];
14 for (i, limb) in slice.iter().enumerate() {
15 limbs[i] = *limb;
16 }
17 MatrixBlock::new(limbs)
18}
19
20pub fn gemm_block_simd(a: MatrixBlock, b: MatrixBlock, c: &mut MatrixBlock) {
40 for (result_limb, a_limb) in c.iter_mut().zip(a.iter()) {
42 let a_limb_iter = BitIterator::new(*a_limb);
43 for (b_limb, a_bit) in b.iter().zip(a_limb_iter) {
45 *result_limb ^= *b_limb * (a_bit as Limb);
46 }
47 }
48}
49
50struct BitIterator {
51 limb: Limb,
52 bit_index: usize,
53}
54
55impl BitIterator {
56 fn new(limb: Limb) -> Self {
57 Self { limb, bit_index: 0 }
58 }
59}
60
61impl Iterator for BitIterator {
62 type Item = bool;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 if self.bit_index >= crate::constants::BITS_PER_LIMB {
66 return None;
67 }
68 let result = self.limb & 1 == 1;
69 self.limb >>= 1;
70 self.bit_index += 1;
71 Some(result)
72 }
73}