#![feature(generic_const_exprs, portable_simd, stmt_expr_attributes)]
use std::{hint::assert_unchecked, ops::Range, simd::prelude::*};
#[unsafe(no_mangle)]
pub unsafe fn run(x: &[u8]) -> u64 {
let i = unsafe { x.as_chunks_unchecked::<{ 141 + 1 }>() };
#[rustfmt::skip]
static LUT: [(usize, usize); 141] = [(0, 0), (0, 0), (70, 70), (0, 0), (69, 71), (0, 0), (68, 72), (0, 0), (67, 73), (0, 0), (66, 74), (0, 0), (65, 75), (0, 0), (64, 76), (0, 0), (63, 77), (0, 0), (62, 78), (0, 0), (61, 79), (0, 0), (60, 80), (0, 0), (59, 81), (0, 0), (58, 82), (0, 0), (57, 83), (0, 0), (56, 84), (0, 0), (55, 85), (0, 0), (54, 86), (0, 0), (53, 87), (0, 0), (52, 88), (0, 0), (51, 89), (0, 0), (50, 90), (0, 0), (49, 91), (0, 0), (48, 92), (0, 0), (47, 93), (0, 0), (46, 94), (0, 0), (45, 95), (0, 0), (44, 96), (0, 0), (43, 97), (0, 0), (42, 98), (0, 0), (41, 99), (0, 0), (40, 100), (0, 0), (39, 101), (0, 0), (38, 102), (0, 0), (37, 103), (0, 0), (36, 104), (0, 0), (35, 105), (0, 0), (34, 106), (0, 0), (33, 107), (0, 0), (32, 108), (0, 0), (31, 109), (0, 0), (30, 110), (0, 0), (29, 111), (0, 0), (28, 112), (0, 0), (27, 113), (0, 0), (26, 114), (0, 0), (25, 115), (0, 0), (24, 116), (0, 0), (23, 117), (0, 0), (22, 118), (0, 0), (21, 119), (0, 0), (20, 120), (0, 0), (19, 121), (0, 0), (18, 122), (0, 0), (17, 123), (0, 0), (16, 124), (0, 0), (15, 125), (0, 0), (14, 126), (0, 0), (13, 127), (0, 0), (12, 128), (0, 0), (11, 129), (0, 0), (10, 130), (0, 0), (9, 131), (0, 0), (8, 132), (0, 0), (7, 133), (0, 0), (6, 134), (0, 0), (5, 135), (0, 0), (4, 136), (0, 0), (3, 137), (0, 0), (2, 138), (0, 0), (1, 139)];
for n in (1..141).rev().step_by(2) {
let lem = &i[n];
println!("{n}: {}", lem.iter().filter(|x| **x == b'^').count());
// assert_eq!((start, end), LUT[n]);
// assert_eq!(LUT[n], (start, end));
// println!("({start}, {end}),");
}
// println!("{LUT:?}");
assert_unchecked(i.len() == 142);
let mut v = [1u64; 141];
let split = Simd::splat(b'^');
let mut f = #[inline(always)]
|(star, end): (usize, usize), line: &[u8; 142]| {
let mut f = #[inline(always)]
|mut mask: u64, o: usize| {
while mask != 0 {
let x = mask.trailing_zeros() as usize + o;
mask ^= mask & mask.wrapping_neg();
*v.get_unchecked_mut(x) = *v.get_unchecked(x - 1) + *v.get_unchecked(x + 1);
}
};
// let (star, end) = LUT[ix];
if (end - star) < 64 {
let mask = u8x64::load_or_default(&line[star..])
.simd_eq(split)
.to_bitmask();
f(mask, star);
} else if (end - star) < 128 {
let mask = u8x64::load_or_default(&line[star..])
.simd_eq(split)
.to_bitmask();
f(mask, star);
let mask = u8x64::load_or_default(&line[star + 64..])
.simd_eq(split)
.to_bitmask();
f(mask, star + 64);
} else {
let mask = u8x64::load_or_default(&line[star..])
.simd_eq(split)
.to_bitmask();
f(mask, star);
let mask = u8x64::load_or_default(&line[star + 64..])
.simd_eq(split)
.to_bitmask();
f(mask, star + 64);
let mask = u8x64::load_or_default(&line[star + 128..])
.simd_eq(split)
.to_bitmask();
f(mask, star + 128);
}
// if ix > 65 {
// let mask = u8x64::load_or_default(&line[..39])
// .simd_eq(split)
// .to_bitmask();
// f(mask, 0);
// }
// let middle = u8x64::load_or_default(&line[39..])
// .simd_eq(split)
// .to_bitmask();
// f(middle, 39);
// if ix > 65 {
// let end = u8x64::load_or_default(&line[39 + 64..])
// .simd_eq(split)
// .to_bitmask();
// f(end, 39 + 64);
// }
};
f(const { LUT[140] }, &i[140]);
f(const { LUT[138] }, &i[138]);
f(const { LUT[136] }, &i[136]);
f(const { LUT[134] }, &i[134]);
f(const { LUT[132] }, &i[132]);
f(const { LUT[130] }, &i[130]);
f(const { LUT[128] }, &i[128]);
f(const { LUT[126] }, &i[126]);
f(const { LUT[124] }, &i[124]);
f(const { LUT[122] }, &i[122]);
f(const { LUT[120] }, &i[120]);
f(const { LUT[118] }, &i[118]);
f(const { LUT[116] }, &i[116]);
f(const { LUT[114] }, &i[114]);
f(const { LUT[112] }, &i[112]);
f(const { LUT[110] }, &i[110]);
f(const { LUT[108] }, &i[108]);
f(const { LUT[106] }, &i[106]);
f(const { LUT[104] }, &i[104]);
f(const { LUT[102] }, &i[102]);
f(const { LUT[100] }, &i[100]);
f(const { LUT[98] }, &i[98]);
f(const { LUT[96] }, &i[96]);
f(const { LUT[94] }, &i[94]);
f(const { LUT[92] }, &i[92]);
f(const { LUT[90] }, &i[90]);
f(const { LUT[88] }, &i[88]);
f(const { LUT[86] }, &i[86]);
f(const { LUT[84] }, &i[84]);
f(const { LUT[82] }, &i[82]);
f(const { LUT[80] }, &i[80]);
f(const { LUT[78] }, &i[78]);
f(const { LUT[76] }, &i[76]);
f(const { LUT[74] }, &i[74]);
f(const { LUT[72] }, &i[72]);
f(const { LUT[70] }, &i[70]);
f(const { LUT[68] }, &i[68]);
f(const { LUT[66] }, &i[66]);
f(const { LUT[64] }, &i[64]);
f(const { LUT[62] }, &i[62]);
f(const { LUT[60] }, &i[60]);
f(const { LUT[58] }, &i[58]);
f(const { LUT[56] }, &i[56]);
f(const { LUT[54] }, &i[54]);
f(const { LUT[52] }, &i[52]);
f(const { LUT[50] }, &i[50]);
f(const { LUT[48] }, &i[48]);
f(const { LUT[46] }, &i[46]);
f(const { LUT[44] }, &i[44]);
f(const { LUT[42] }, &i[42]);
f(const { LUT[40] }, &i[40]);
f(const { LUT[38] }, &i[38]);
f(const { LUT[36] }, &i[36]);
f(const { LUT[34] }, &i[34]);
f(const { LUT[32] }, &i[32]);
f(const { LUT[30] }, &i[30]);
f(const { LUT[28] }, &i[28]);
f(const { LUT[26] }, &i[26]);
f(const { LUT[24] }, &i[24]);
f(const { LUT[22] }, &i[22]);
f(const { LUT[20] }, &i[20]);
f(const { LUT[18] }, &i[18]);
f(const { LUT[16] }, &i[16]);
f(const { LUT[14] }, &i[14]);
f(const { LUT[12] }, &i[12]);
f(const { LUT[10] }, &i[10]);
f(const { LUT[8] }, &i[8]);
f(const { LUT[6] }, &i[6]);
f(const { LUT[4] }, &i[4]);
f(const { LUT[2] }, &i[2]);
// for n in (1..141).rev().step_by(2) {
// println!("f({n}, &i[{n}]);");
// f(n, &i[n]);
// }
*v.get_unchecked(70)
}