Skip to content

Instantly share code, notes, and snippets.

@3Hren
Created February 26, 2021 13:57
Show Gist options
  • Save 3Hren/e2c3e41a3b83f1b8e5aa8b6323463495 to your computer and use it in GitHub Desktop.
Save 3Hren/e2c3e41a3b83f1b8e5aa8b6323463495 to your computer and use it in GitHub Desktop.
// 0..4294967295
// buf.len() after stripping leading zeros must be >= 16.
pub fn parse_u32(buf: &[u8]) -> Result<(&[u8], u32), ExpectedDecNumber> {
const RANGES: [u8; 16] = [b'0', b'9', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const SHUFFLE_MASK: [u8; 16] = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
const FACTOR1: [u16; 8] = [1, 10, 100, 1000, 1, 10, 100, 1000];
const FACTOR2: [u32; 4] = [1, 10000, 100000000, 0];
let mut zi = 0;
let len = buf.len();
if len == 0 {
return Err(ExpectedDecNumber);
}
// Strip leading zeros.
while zi < len && buf[zi] == b'0' {
zi += 1;
}
let xmm2 = unsafe { _mm_setzero_si128() };
let ranges16 = unsafe { _mm_loadu_si128(RANGES.as_ptr() as *const _) };
let xmm1 = unsafe { buf.as_ptr().offset(zi as isize) } as usize;
let xmm1 = unsafe { _mm_loadu_si128(xmm1 as *const _) };
let idx = unsafe {
_mm_cmpistri(
ranges16,
xmm1,
_SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_NEGATIVE_POLARITY,
)
};
if idx == 0 {
return if zi > 0 {
Ok((&buf[zi..], 0))
} else {
Err(ExpectedDecNumber)
};
}
let i = idx - 16;
// Reverse.
let xmm0 = unsafe { Xmm { i32: i }.xmm };
let xmm0 = unsafe { _mm_shuffle_epi8(xmm0, xmm2) };
let shuffle16 = unsafe { _mm_loadu_si128(SHUFFLE_MASK.as_ptr() as *const _) };
let xmm0 = unsafe { _mm_add_epi8(xmm0, shuffle16) };
let xmm1 = unsafe { _mm_shuffle_epi8(xmm1, xmm0) };
let xmm0 = unsafe { Xmm { u8: b'0' }.xmm };
let xmm0 = unsafe { _mm_shuffle_epi8(xmm0, xmm2) };
// Subtract b'0'.
let xmm1 = unsafe { _mm_subs_epu8(xmm1, xmm0) };
let xmm0 = xmm1;
// Multiply by 10^0, 10^1, ... 10^5, 0, 0, 0.
let xmm0 = unsafe { _mm_unpacklo_epi8(xmm0, xmm2) };
let xmm1 = unsafe { _mm_unpackhi_epi8(xmm1, xmm2) };
let factor16 = unsafe { _mm_loadu_si128(FACTOR1.as_ptr() as *const _) };
let xmm0 = unsafe { _mm_madd_epi16(xmm0, factor16) };
let xmm1 = unsafe { _mm_madd_epi16(xmm1, factor16) };
let xmm0 = unsafe { _mm_hadd_epi32(xmm0, xmm1) };
let factor16l = unsafe { _mm_loadu_si128(FACTOR2.as_ptr() as *const _) };
let xmm0 = unsafe { _mm_mullo_epi32(xmm0, factor16l) };
let xmm1 = unsafe { _mm_shuffle_epi32(xmm0, 0b11101110) };
let xmm0 = unsafe { _mm_add_epi32(xmm0, xmm1) };
let xmm1 = unsafe { _mm_shuffle_epi32(xmm0, 0b01010101) };
let xmm0 = unsafe { _mm_add_epi32(xmm0, xmm1) };
let out = unsafe { Xmm { xmm: xmm0 }.u32 };
Ok((&buf[idx as usize..], out))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment