138 lines
2.9 KiB
Rust
138 lines
2.9 KiB
Rust
#![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<u64> = {
|
|
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
|
|
}
|
|
} |