use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::cmp::Ordering; use std::sync::Arc; use num::{Integer, Signed}; pub type Container = Arc; pub fn container(data: T) -> Container { Arc::new(data) } pub trait NodeData { type Constant: Hash + Ord + Clone + Signed; type Exponent: Hash + Clone + Integer; type Input: Hash + Ord + Clone; type SystemVariable: Hash + Ord + Clone; type Parameter: Hash + Ord + Clone; } pub struct Sum { pub pre_hash: u64, //I would like these fields to be private if possible. pub minus: bool, pub constant: T::Constant, pub terms: Vec>>, } pub struct Product { pub pre_hash: u64, //I would like these fields to be private if possible. pub coefficient: T::Constant, pub powers: Vec>>, } pub struct Power { pub exponent: T::Exponent, pub primitive: Container>, } pub enum Primitive { Input(T::Input), SystemVariable(T::SystemVariable), Parameter(T::Parameter), Sigmoid(bool, Container>), } impl PartialOrd for Sum { fn partial_cmp(&self, other: &Sum) -> Option { Some(self.cmp(other)) } } impl PartialOrd for Product { fn partial_cmp(&self, other: &Product) -> Option { Some(self.cmp(other)) } } impl PartialOrd for Power { fn partial_cmp(&self, other: &Power) -> Option { Some(self.cmp(other)) } } impl PartialOrd for Primitive { fn partial_cmp(&self, other: &Primitive) -> Option { Some(self.cmp(other)) } } impl PartialEq for Sum { fn eq(&self, other: &Sum) -> bool { self.minus == other.minus && self.constant == other.constant && self.terms == other.terms } } impl PartialEq for Product { fn eq(&self, other: &Product) -> bool { self.coefficient == other.coefficient && self.powers == other.powers } } impl PartialEq for Power { fn eq(&self, other: &Power) -> bool { self.exponent == other.exponent && self.primitive == other.primitive } } impl PartialEq for Primitive { fn eq(&self, other: &Primitive) -> bool { match (self, other) { (&Primitive::Input(ref a), &Primitive::Input(ref b)) => a == b, (&Primitive::SystemVariable(ref a), &Primitive::SystemVariable(ref b)) => a == b, (&Primitive::Parameter(ref a), &Primitive::Parameter(ref b)) => a == b, (&Primitive::Sigmoid(minus_a, ref a), &Primitive::Sigmoid(minus_b, ref b)) => { minus_a == minus_b && a == b } _ => false, } } } impl Eq for Sum {} impl Eq for Product {} impl Eq for Power {} impl Eq for Primitive {} impl Hash for Sum { fn hash(&self, state: &mut H) { self.pre_hash.hash(state); } } impl Hash for Product { fn hash(&self, state: &mut H) { self.pre_hash.hash(state); } } impl Hash for Power { fn hash(&self, state: &mut H) { self.exponent.hash(state); self.primitive.hash(state); } } impl Hash for Primitive { fn hash(&self, state: &mut H) { match self { &Primitive::Input(ref a) => { "Input".hash(state); a.hash(state) } &Primitive::SystemVariable(ref a) => { "SystemVariable".hash(state); a.hash(state) } &Primitive::Parameter(ref a) => { "Parameter".hash(state); a.hash(state) } &Primitive::Sigmoid(minus, ref a) => { "Sigmoid".hash(state); minus.hash(state); a.hash(state) } } } } impl Clone for Sum { fn clone(&self) -> Sum { Sum { pre_hash: self.pre_hash.clone(), minus: self.minus.clone(), constant: self.constant.clone(), terms: self.terms.clone(), } } } impl Clone for Product { fn clone(&self) -> Product { Product { pre_hash: self.pre_hash.clone(), coefficient: self.coefficient.clone(), powers: self.powers.clone(), } } } impl Clone for Power { fn clone(&self) -> Power { Power { exponent: self.exponent.clone(), primitive: self.primitive.clone(), } } } impl Clone for Primitive { fn clone(&self) -> Primitive { match self { &Primitive::Input(ref a) => Primitive::Input(a.clone()), &Primitive::SystemVariable(ref a) => Primitive::SystemVariable(a.clone()), &Primitive::Parameter(ref a) => Primitive::Parameter(a.clone()), &Primitive::Sigmoid(minus, ref a) => Primitive::Sigmoid(minus, a.clone()), } } } impl Sum { pub fn new(minus: bool, constant: T::Constant, terms: Vec>>) -> Sum { let mut s = DefaultHasher::new(); minus.hash(&mut s); constant.hash(&mut s); terms.hash(&mut s); Sum { pre_hash: s.finish(), minus: minus, constant: constant, terms: terms, } } } impl Product { pub fn new(coefficient: T::Constant, powers: Vec>>) -> Product { let mut s = DefaultHasher::new(); coefficient.hash(&mut s); powers.hash(&mut s); Product { pre_hash: s.finish(), coefficient: coefficient, powers: powers, } } } impl Power { pub fn new(exponent: T::Exponent, primitive: Container>) -> Power { Power { exponent: exponent, primitive: primitive, } } }