diff --git a/Cargo.toml b/Cargo.toml index 76f7a77..2cf13bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,9 +11,6 @@ overflow-checks = false [profile.release] opt-level = 3 -[features] -simd = [] - [dependencies] rayon = "1.7.0" hashbrown = "0.14.0" diff --git a/README.md b/README.md index 8202caa..7ee8f73 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Brute-force search tool for short Python expressions (for code golf). Edit the search parameters at the top of `src/params.rs`, then run `cargo run --release`. -If your input/goal vectors have length ≤8, you can try `cargo +nightly run --release --features simd`. - In `main.rs` you can edit the file used as the params module (default `#[path = "params.rs"]`). This way you can manage multiple configurations (e.g. make a `params-fizzbuzz.rs`). ## Example diff --git a/src/main.rs b/src/main.rs index ce8018a..907ea1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,10 @@ -#![cfg_attr(feature = "simd", feature(portable_simd))] - pub mod expr; pub mod operator; +pub mod vec; #[path = "params.rs"] pub mod params; -#[cfg_attr(all(feature = "simd", feature = "portable_simd"), path = "vec_simd.rs")] -#[cfg_attr(not(feature = "simd"), path = "vec.rs")] -pub mod vec; - use expr::{Expr, NonNullExpr, VarCount}; use operator::*; use params::*; diff --git a/src/vec_simd.rs b/src/vec_simd.rs deleted file mode 100644 index f5ec062..0000000 --- a/src/vec_simd.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::{ - ops::{Deref, DerefMut, RangeBounds}, - simd::{i32x8, SimdPartialEq, SimdPartialOrd}, -}; - -use crate::{ - gcd::gcd, - params::{Num, C_STYLE_MOD, GOAL}, -}; - -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct Vector(i32x8); - -impl Deref for Vector { - type Target = i32x8; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Vector { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -macro_rules! impl_op { - ($trait:ident, $func:ident, $op:tt) => { - impl std::ops::$trait<&Self> for Vector { - type Output = Vector; - - #[inline] - fn $func(mut self, rhs: &Self) -> Self::Output { - self.0 $op rhs.0; - self - } - } - } -} - -macro_rules! impl_unary { - ($trait:ident, $func:ident, $op:tt) => { - impl std::ops::$trait for Vector { - type Output = Vector; - - #[inline] - fn $func(mut self) -> Self::Output { - self.0 = $op(self.0); - self - } - } - }; -} - -impl_op!(Add, add, +=); -impl_op!(Sub, sub, -=); -impl_op!(Mul, mul, *=); -impl_op!(Div, div, /=); -impl_op!(Rem, rem, %=); -impl_op!(BitAnd, bitand, &=); -impl_op!(BitOr, bitor, |=); -impl_op!(BitXor, bitxor, ^=); -impl_op!(Shl, shl, <<=); -impl_op!(Shr, shr, >>=); -impl_unary!(Not, not, !); -impl_unary!(Neg, neg, -); - -impl Vector { - #[inline] - pub fn constant(n: Num) -> Vector { - Vector(i32x8::splat(n)) - } - - #[inline] - pub fn from_slice(ns: &[Num]) -> Vector { - let mut v = ns.to_owned(); - if v.len() > 8 { - panic!("SIMD mode is limited to inputs of maximum size 8") - } else if v.len() == 0 { - panic!("Empty input") - } else if v.len() < 8 { - v = v.repeat(8); - v.resize(8, 0); - } - Vector(i32x8::from_slice(&v)) - } - - #[inline] - pub fn map(self, function: fn(Num) -> Num) -> Self { - let mut a = self.to_array(); - for x in &mut a { - *x = function(*x); - } - Self::from_slice(&a) - } -} - -impl IntoIterator for Vector { - type Item = Num; - type IntoIter = std::array::IntoIter; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - IntoIterator::into_iter(self.0.to_array()) - } -} - -#[inline] -pub fn divmod(left: &Vector, right: &Vector) -> Option<(Vector, Vector)> { - if (right.simd_eq(i32x8::splat(0)) - | (left.simd_eq(i32x8::splat(Num::MIN)) & right.simd_eq(i32x8::splat(-1)))) - .any() - { - None - } else if C_STYLE_MOD { - Some((left.clone() / right, left.clone() % right)) - } else { - let modulo = (left.clone() % right + right) % right; - let div = (left.clone() - &modulo) / right; - Some((div, modulo)) - } -} - -#[inline] -pub fn vec_or(left: &Vector, right: &Vector) -> Vector { - let left = left.clone(); - Vector(left.simd_eq(i32x8::splat(0)).select(**right, *left)) -} - -#[inline] -pub fn vec_eq(left: &Vector, right: &Vector) -> Vector { - let left = left.clone(); - Vector(-left.simd_eq(right.0).to_int()) -} - -#[inline] -pub fn vec_lt(left: &Vector, right: &Vector) -> Vector { - let left = left.clone(); - Vector(-left.simd_lt(right.0).to_int()) -} - -#[inline] -pub fn vec_le(left: &Vector, right: &Vector) -> Vector { - let left = left.clone(); - Vector(-left.simd_le(right.0).to_int()) -} - -#[inline] -pub fn vec_gcd(left: &Vector, right: &Vector) -> Vector { - let mut left = left.to_array(); - for (x, y) in left.iter_mut().zip(right.0.to_array()) { - *x = gcd(*x, y); - } - Vector::from_slice(&left) -} - -#[inline] -pub fn vec_pow(left: &Vector, right: &Vector) -> Vector { - let mut left = left.to_array(); - for (x, y) in left.iter_mut().zip(right.0.to_array()) { - *x = x.pow(y as u32); - } - Vector::from_slice(&left) -} - -#[inline] -pub fn vec_in>(vec: &Vector, bounds: R) -> bool { - (0..GOAL.len()).all(|i| bounds.contains(&vec[i])) -}