use crate::algebra::mv::Mv;
use crate::algebra::signature::Signature;
use crate::governance::expr::{EvalContext, Expr};
use crate::scalar::Scalar;
#[derive(Clone, Debug)]
pub struct Construction {
pub class_index: usize,
pub arity: usize,
pub body: Expr,
}
#[derive(Clone, Debug)]
pub enum ConstructionError {
ArityMismatch { expected: usize, got: usize },
IndexOutOfRange { index: usize, len: usize },
}
impl Construction {
pub fn construct(
&self,
params: &[Scalar],
sig: &Signature,
derived_gens: &[Mv],
constructions: &[Construction],
) -> Result<Mv, ConstructionError> {
if params.len() != self.arity {
return Err(ConstructionError::ArityMismatch {
expected: self.arity,
got: params.len(),
});
}
let ctx = EvalContext {
params,
sig,
derived_gens,
constructions,
mv_table: &[],
governances: &[],
mv_governance_indices: &[],
embeddings: &[],
morphisms: &[],
probe_mv: None,
object_mv: None,
};
Ok(self.body.eval(&ctx))
}
}
impl std::fmt::Display for ConstructionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConstructionError::ArityMismatch { expected, got } => write!(
f,
"arity mismatch: expected {} params, got {}",
expected, got
),
ConstructionError::IndexOutOfRange { index, len } => write!(
f,
"construction index {} out of range (have {})",
index, len
),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::governance::expr::Expr;
#[test]
fn vga_vector_construction() {
let sig = Signature::new(0, 0, 3).unwrap();
let c = Construction {
class_index: 0,
arity: 3,
body: Expr::Add(
Expr::add(
Expr::mul(Expr::param(0), Expr::gen(0)),
Expr::mul(Expr::param(1), Expr::gen(1)),
),
Expr::mul(Expr::param(2), Expr::gen(2)),
),
};
let params = vec![Scalar::from(3i64), Scalar::from(4i64), Scalar::from(5i64)];
let mv = c.construct(¶ms, &sig, &[], &[]).unwrap();
assert_eq!(mv.coefficient(0b001), Scalar::from(3i64));
assert_eq!(mv.coefficient(0b010), Scalar::from(4i64));
assert_eq!(mv.coefficient(0b100), Scalar::from(5i64));
assert_eq!(mv.len(), 3);
}
#[test]
fn arity_mismatch() {
let sig = Signature::new(0, 0, 3).unwrap();
let c = Construction {
class_index: 0,
arity: 3,
body: Expr::Generator(0),
};
let params = vec![Scalar::from(1i64)]; assert!(c.construct(¶ms, &sig, &[], &[]).is_err());
}
}