count_newlines/
lib.rs

1#![no_std]
2#[cfg(target_arch="x86_64")]
3use core::arch::x86_64::*;
4#[cfg(all(target_arch="x86", target_feature="sse2"))]
5use core::arch::x86::*;
6
7/// Counts the number of newlines in a slice.
8pub fn count_newlines(slice: &[u8]) -> usize {
9  let mut count = 0;
10  let mut slice = slice;
11  #[cfg(target_feature="sse2")] {
12    unsafe {
13      let splat = _mm_set1_epi8(b'\n' as _);
14      while slice.len() >= 64 {
15        let ptr = slice.as_ptr().cast::<__m128i>();
16        for i in 0..4 {
17          let simd = _mm_loadu_si128(ptr.add(i));
18          count += _mm_movemask_epi8(_mm_cmpeq_epi8(splat, simd)).count_ones() as usize;
19        }
20        slice = &slice[64..];
21      }
22      while slice.len() >= 16 {
23        let bytes = _mm_loadu_si128(slice.as_ptr().cast());
24        count += _mm_movemask_epi8(_mm_cmpeq_epi8(splat, bytes)).count_ones() as usize;
25        slice = &slice[16..];
26      }
27    }
28  }
29  for c in slice {
30    if *c == b'\n' {
31      count += 1;
32    }
33  }
34  count
35}