use std::{
iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use crate::{
instruction::Instruction32, symbolic_var_f::SymbolicVarF, CUDA_P3_EVAL_CODE,
CUDA_P3_EVAL_EXPR_F_CTR, F,
};
use slop_algebra::AbstractField;
#[derive(Debug, Copy, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct SymbolicExprF(pub u32);
impl SymbolicExprF {
pub fn empty() -> Self {
Self(u32::MAX)
}
pub fn alloc() -> Self {
let mut tmp = CUDA_P3_EVAL_EXPR_F_CTR.lock().unwrap();
let id = *tmp;
*tmp += 1;
drop(tmp);
Self(id)
}
pub fn variant(&self) -> u8 {
0
}
pub fn data(&self) -> u32 {
self.0
}
}
impl Default for SymbolicExprF {
fn default() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::zero()));
drop(code);
output
}
}
impl From<F> for SymbolicExprF {
fn from(f: F) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, f));
drop(code);
output
}
}
impl Add<F> for SymbolicExprF {
type Output = Self;
fn add(self, rhs: F) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_add_ec(output, self, rhs));
drop(code);
output
}
}
impl Add<SymbolicVarF> for SymbolicExprF {
type Output = Self;
fn add(self, rhs: SymbolicVarF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_add_ev(output, self, rhs));
drop(code);
output
}
}
impl Add<SymbolicExprF> for SymbolicExprF {
type Output = SymbolicExprF;
fn add(self, rhs: SymbolicExprF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_add_ee(output, self, rhs));
drop(code);
output
}
}
impl AddAssign<SymbolicExprF> for SymbolicExprF {
fn add_assign(&mut self, _: SymbolicExprF) {
unreachable!()
}
}
impl Sub<F> for SymbolicExprF {
type Output = Self;
fn sub(self, rhs: F) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_sub_ec(output, self, rhs));
drop(code);
output
}
}
impl Sub<SymbolicVarF> for SymbolicExprF {
type Output = Self;
fn sub(self, rhs: SymbolicVarF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_sub_ev(output, self, rhs));
drop(code);
output
}
}
impl Sub<SymbolicExprF> for SymbolicExprF {
type Output = Self;
fn sub(self, rhs: SymbolicExprF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_sub_ee(output, self, rhs));
drop(code);
output
}
}
impl SubAssign<SymbolicExprF> for SymbolicExprF {
fn sub_assign(&mut self, _: SymbolicExprF) {
unreachable!()
}
}
impl Mul<F> for SymbolicExprF {
type Output = Self;
fn mul(self, rhs: F) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_mul_ec(output, self, rhs));
drop(code);
output
}
}
impl Mul<SymbolicVarF> for SymbolicExprF {
type Output = Self;
fn mul(self, rhs: SymbolicVarF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_mul_ev(output, self, rhs));
drop(code);
output
}
}
impl Mul<SymbolicExprF> for SymbolicExprF {
type Output = Self;
fn mul(self, rhs: SymbolicExprF) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_mul_ee(output, self, rhs));
drop(code);
output
}
}
impl MulAssign<SymbolicExprF> for SymbolicExprF {
fn mul_assign(&mut self, _: SymbolicExprF) {
unreachable!()
}
}
impl Neg for SymbolicExprF {
type Output = Self;
fn neg(self) -> Self::Output {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_neg_e(output, self));
drop(code);
output
}
}
impl Sum for SymbolicExprF {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
let mut output = SymbolicExprF::zero();
for item in iter {
output = output + item;
}
output
}
}
impl Product for SymbolicExprF {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
let mut output = SymbolicExprF::one();
for item in iter {
output = output * item;
}
output
}
}
impl Clone for SymbolicExprF {
#[allow(clippy::non_canonical_clone_impl)]
fn clone(&self) -> Self {
*self
}
}
impl AbstractField for SymbolicExprF {
type F = F;
fn zero() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::zero()));
drop(code);
output
}
fn one() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::one()));
drop(code);
output
}
fn two() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::two()));
drop(code);
output
}
fn neg_one() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::neg_one()));
drop(code);
output
}
fn from_f(f: Self::F) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, f));
drop(code);
output
}
fn from_bool(b: bool) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_bool(b)));
drop(code);
output
}
fn from_canonical_u8(n: u8) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_canonical_u8(n)));
drop(code);
output
}
fn from_canonical_u16(n: u16) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_canonical_u16(n)));
drop(code);
output
}
fn from_canonical_u32(n: u32) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_canonical_u32(n)));
drop(code);
output
}
fn from_canonical_u64(n: u64) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_canonical_u64(n)));
drop(code);
output
}
fn from_canonical_usize(n: usize) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_canonical_usize(n)));
drop(code);
output
}
fn from_wrapped_u32(n: u32) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_wrapped_u32(n)));
drop(code);
output
}
fn from_wrapped_u64(n: u64) -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::from_wrapped_u64(n)));
drop(code);
output
}
fn generator() -> Self {
let output = SymbolicExprF::alloc();
let mut code = CUDA_P3_EVAL_CODE.lock().unwrap();
code.push(Instruction32::f_assign_c(output, F::generator()));
drop(code);
output
}
}