Interestingly, even when adapting your solution to my program like below, unsafeIndex still is slower (by about 2s or 2%) than uncons like in the second version:
unsafeIndex
let x1 = BSU.unsafeIndex rest2 0
let x2 = BSU.unsafeIndex rest2 1
let x3 = BSU.unsafeIndex rest2 2
let x4 = BSU.unsafeIndex rest2 3
let x5 = BSU.unsafeIndex rest2 4
let (temp, rest) = case x1 of
-- ord '-' == 45 => -N.N or -NN.N
W8# 45#Word8 -> case x3 of
-- ord '.' == 46 => -N.N
W8# 46#Word8 -> (528 - fromIntegral x2 * 10 - fromIntegral x4, BS.drop 4 rest2)
-- -NN.N
_ -> (5328 - fromIntegral x2 * 100 - fromIntegral x3 * 10 - fromIntegral x5, BS.drop 5 rest2)
-- N.N or NN.N
_ -> case x2 of
-- ord '.' == 46 => N.N
W8# 46#Word8 -> (fromIntegral x1 * 10 + fromIntegral x3 - 528, BS.drop 3 rest2)
-- NN.N
_ -> (fromIntegral x1 * 100 + fromIntegral x2 * 10 + fromIntegral x4 - 5328, BS.drop 4 rest2)
hyperfine -w 1 -r 5 './exe-exe ../measurements.txt > solution.txt'
Benchmark 1: ./exe-exe ../measurements.txt > solution.txt
Time (mean ± σ): 99.749 s ± 0.512 s [User: 90.609 s, System: 20.358 s]
Range (min … max): 99.099 s … 100.309 s 5 runs
uncons
{-# INLINE parseNegTemp #-}
parseNegTemp :: BS.ByteString -> (Int, BS.ByteString)
parseNegTemp rest = case BS.uncons rest of
Nothing -> (0, rest)
Just (ch1, rest3) -> case BS.uncons rest3 of
Nothing -> (0, rest3)
Just ('.', rest4) -> case BS.uncons rest4 of
Nothing -> (0, rest4)
Just (ch2, rest5) -> (528 - 10 * ord ch1 - ord ch2, rest5)
Just (ch2, rest4) -> case BS.uncons rest4 of
Nothing -> (0, rest4)
-- Must be '.'
Just (_, rest5) -> case BS.uncons rest5 of
Nothing -> (0, rest5)
Just (ch3, rest6) -> (5328 - 100 * ord ch1 - 10 * ord ch2 - ord ch3, rest6)
{-# INLINE parseTemp #-}
parseTemp :: Char -> BS.ByteString -> (Int, BS.ByteString)
parseTemp ch1 rest = case BS.uncons rest of
Nothing -> (0, rest)
Just ('.', rest4) -> case BS.uncons rest4 of
Nothing -> (0, rest4)
Just (ch2, rest5) -> (10 * ord ch1 + ord ch2 - 528, rest5)
Just (ch2, rest4) -> case BS.uncons rest4 of
Nothing -> (0, rest4)
-- Must be '.'
Just (_, rest5) -> case BS.uncons rest5 of
Nothing -> (0, rest5)
Just (ch3, rest6) -> (100 * ord ch1 + 10 * ord ch2 + ord ch3 - 5328, rest6)
hyperfine -w 1 -r 5 './exe-exe ../measurements.txt > solution.txt'
Benchmark 1: ./exe-exe ../measurements.txt > solution.txt
Time (mean ± σ): 97.509 s ± 0.695 s [User: 88.850 s, System: 17.293 s]
Range (min … max): 96.692 s … 98.301 s 5 runs
Interesting, thanks, will take a look!