use crate::expr::Expr;
use crate::governance::Governance;
use std::sync::Arc;
#[derive(Clone)]
pub struct Geoit {
governance: Arc<Governance>,
value: Expr,
}
impl Geoit {
pub fn new(gov: Governance, value: Expr) -> Geoit {
Geoit {
governance: Arc::new(gov),
value,
}
}
pub fn shared(gov: Arc<Governance>, value: Expr) -> Geoit {
Geoit {
governance: gov,
value,
}
}
pub fn governance(&self) -> &Governance {
&self.governance
}
pub fn shared_governance(&self) -> Arc<Governance> {
Arc::clone(&self.governance)
}
pub fn value(&self) -> &Expr {
&self.value
}
pub fn into_value(self) -> Expr {
self.value
}
pub fn is_zero(&self) -> bool {
self.value.is_zero()
}
pub fn sibling(&self, value: Expr) -> Geoit {
Geoit {
governance: Arc::clone(&self.governance),
value,
}
}
pub fn canonical(&self) -> Geoit {
let value = self.governance.canonicalize(&self.value);
Geoit {
governance: Arc::clone(&self.governance),
value,
}
}
pub fn mul(&self, other: &Geoit) -> Geoit {
debug_assert!(
Arc::ptr_eq(&self.governance, &other.governance),
"governed product requires shared governance"
);
let product = self.governance.mul(&self.value, &other.value);
Geoit {
governance: Arc::clone(&self.governance),
value: product,
}
}
pub fn add(&self, other: &Geoit) -> Geoit {
debug_assert!(Arc::ptr_eq(&self.governance, &other.governance));
Geoit {
governance: Arc::clone(&self.governance),
value: self.value.add(&other.value),
}
}
}
impl PartialEq for Geoit {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.governance, &other.governance) && self.value == other.value
}
}
impl Eq for Geoit {}
impl std::fmt::Debug for Geoit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Geoit({:?}, {})", self.governance, self.value)
}
}
impl std::fmt::Display for Geoit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gen::Gen;
use crate::rat::Rat;
use crate::word::Word;
fn ei(i: u32) -> Gen {
Gen::imaginary(i)
}
#[test]
fn creation_and_value() {
let gov = Governance::cl(1, 0, 0);
let g = Geoit::new(gov, Expr::gen(ei(0)));
assert_eq!(*g.value(), Expr::gen(ei(0)));
}
#[test]
fn canonical_cl100_square() {
let gov = Governance::cl(1, 0, 0);
let e1e1 = Expr::term(Rat::one(), Word::from_gens(&[ei(0), ei(0)]));
let g = Geoit::new(gov, e1e1);
let c = g.canonical();
assert_eq!(*c.value(), Expr::int(-1));
}
#[test]
fn sibling_shares_governance() {
let gov = Governance::cl(2, 0, 0);
let g1 = Geoit::new(gov, Expr::gen(ei(0)));
let g2 = g1.sibling(Expr::gen(Gen::imaginary(1)));
assert!(Arc::ptr_eq(
&g1.shared_governance(),
&g2.shared_governance()
));
}
#[test]
fn equality_requires_shared_governance() {
let gov1 = Governance::cl(1, 0, 0);
let gov2 = Governance::cl(1, 0, 0);
let g1 = Geoit::new(gov1, Expr::gen(ei(0)));
let g2 = Geoit::new(gov2, Expr::gen(ei(0)));
assert_ne!(g1, g2);
let g3 = g1.sibling(Expr::gen(ei(0)));
assert_eq!(g1, g3);
}
#[test]
fn governed_product_cl100() {
let gov = Governance::cl(1, 0, 0);
let g1 = Geoit::new(gov, Expr::gen(ei(0)));
let g2 = g1.sibling(Expr::gen(ei(0)));
let prod = g1.mul(&g2);
assert_eq!(prod.into_value(), Expr::int(-1));
}
#[test]
fn use_governance_cl() {
let gov = Governance::cl(2, 0, 0);
let _g = Geoit::new(gov, Expr::zero());
}
}