#![allow(dead_code)] use std::fs::File; use std::io::{BufRead, BufReader}; use std::str::FromStr; use lazy_static::lazy_static; use lib::compute_async; lazy_static!( static ref DATA: Vec = { let file = File::open("./res/07_weird_assembly_machine.data"); let lines = BufReader::new(file.unwrap()).lines(); let mut data = Vec::new(); for line in lines { data.push(u64::from_str(&line.unwrap()).unwrap()); } data }; ); const FG_DATA_EVEN: &[u64] = &[ 0, 0, 0, 0, 0, 0, 0, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131072, 18446744073709551615, ]; const FG_DATA_ODD: &[u64] = &[131072, 18446744073709551615]; const N: u64 = 10000117800000000; const X: u64 = 5905739161907566595; fn main() { compute_async(|tx| { let mut n = N; let mut x = X; loop { n += 1; x = sub(f(x), n); fn foo(n: u64, mut x: u64, k: u64) -> (u64, u64) { for i in 1..=k { x = sub(fg(x), n + i); } (n + k, x) } (n, x) = foo(n, x, 1_000_000); x = g(x); tx.send((n, x)).unwrap(); } }); } fn f(x: u64) -> u64 { evaluate(x, &DATA[..128], &DATA[..128]) } fn g(x: u64) -> u64 { evaluate(x, &DATA[128..], &DATA[128..]) } fn add(a: u64, b: u64) -> u64 { let (result, overflow) = a.overflowing_add(b); result + overflow as u64 } fn sub(x: u64, mut n: u64) -> u64 { if x <= n { n += 1; } x.wrapping_sub(n) } fn fg(x: u64) -> u64 { !x.rotate_left(17) // evaluate(x, FG_DATA_EVEN, FG_DATA_ODD) } fn fg_n(mut x: u64, n: u64) -> u64 { for _ in 0..n { x = fg(x); } x } fn evaluate(x: u64, data_even: &[u64], data_odd: &[u64]) -> u64 { let data = if x.count_ones() % 2 == 0 { data_even } else { data_odd }; let mut out = 0; for i in 0..data.len() { out = xor_mul(out, x) ^ data[i]; } out } #[cfg(not(all(target_arch = "x86_64", target_feature = "pclmulqdq")))] fn xor_mul(a: u64, mut b: u64) -> u64 { let mut x: u64 = 0; while b != 0 { let c = b.trailing_zeros(); b = b ^ 1u64.rotate_left(c); x = x ^ a.rotate_left(c); } x } #[cfg(all(target_arch = "x86_64", target_feature = "pclmulqdq"))] fn xor_mul(a: u64, b: u64) -> u64 { use std::arch::x86_64::*; unsafe { let a_vec = _mm_set_epi64x(0, a as i64); let b_vec = _mm_set_epi64x(0, b as i64); let result = _mm_clmulepi64_si128(a_vec, b_vec, 0x00); // Extract both 64-bit halves and XOR them let low = _mm_extract_epi64(result, 0) as u64; let high = _mm_extract_epi64(result, 1) as u64; low ^ high } }