use crate::expr::Expr;
use crate::governance::Governance;
use crate::rat::Rat;
use crate::trace::{TraceGen, TraceWalk};
use crate::word::Word;
pub const TRIT_SIZE: usize = 1;
pub fn gen_size() -> usize {
TRIT_SIZE
}
pub fn word_size(w: &Word) -> usize {
w.grade()
}
pub fn tern_size(v: i64) -> usize {
if v == 0 {
return 1;
}
let mut abs = v.unsigned_abs();
let mut digits = 0usize;
while abs > 0 {
abs = (abs + 1) / 3; digits += 1;
}
digits.max(1)
}
pub fn rat_size(r: &Rat) -> usize {
tern_size(r.numerator().to_i64()) + tern_size(r.denominator().to_i64())
}
pub fn term_size(coeff: &Rat, word: &Word) -> usize {
rat_size(coeff) + word_size(word)
}
pub fn expr_size(e: &Expr) -> usize {
e.terms().map(|(w, c)| term_size(c, w)).sum()
}
pub fn tracegen_size(tg: &TraceGen) -> TritWordSize {
let rule_trits = tg.rule_idx; let start_trits = tg.start; let sep_trits = 2; let matched_trits = tg.matched.grade(); let total = rule_trits + sep_trits + start_trits + matched_trits;
TritWordSize {
rule_idx_trits: rule_trits,
start_trits,
sep_trits: 2,
matched_trits,
total_trits: total,
bits: total * 2,
bytes: (total * 2).div_ceil(8),
}
}
pub fn tracewalk_size(tw: &TraceWalk) -> WalkSize {
let step_sizes: Vec<TritWordSize> = tw.steps().iter().map(tracegen_size).collect();
let total_trits: usize = step_sizes.iter().map(|s| s.total_trits).sum();
WalkSize {
steps: tw.len(),
step_sizes,
total_trits,
bits: total_trits * 2,
bytes: (total_trits * 2).div_ceil(8),
}
}
pub fn governance_size(gov: &Governance) -> GovSize {
let mut total_trits = 0usize;
let mut relation_sizes = Vec::new();
for rel in gov.relations() {
let src = word_size(&rel.source);
let tgt = expr_size(&rel.target);
total_trits += src + tgt;
relation_sizes.push(RelSize {
source_trits: src,
target_trits: tgt,
});
}
GovSize {
num_relations: gov.num_relations(),
relation_sizes,
total_trits,
bits: total_trits * 2,
bytes: (total_trits * 2).div_ceil(8),
}
}
pub fn certificate_size(walk: &TraceWalk, kot_gov: &Governance) -> CertSize {
let n1 = tracewalk_size(walk);
let n2 = governance_size(kot_gov);
let n3_trits = n1.total_trits + n2.total_trits;
CertSize {
n1,
n2,
n3_trits,
n3_bits: n3_trits * 2,
n3_bytes: (n3_trits * 2).div_ceil(8),
}
}
#[derive(Debug, Clone)]
pub struct TritWordSize {
pub rule_idx_trits: usize,
pub start_trits: usize,
pub sep_trits: usize,
pub matched_trits: usize,
pub total_trits: usize,
pub bits: usize,
pub bytes: usize,
}
#[derive(Debug, Clone)]
pub struct WalkSize {
pub steps: usize,
pub step_sizes: Vec<TritWordSize>,
pub total_trits: usize,
pub bits: usize,
pub bytes: usize,
}
#[derive(Debug, Clone)]
pub struct RelSize {
pub source_trits: usize,
pub target_trits: usize,
}
#[derive(Debug, Clone)]
pub struct GovSize {
pub num_relations: usize,
pub relation_sizes: Vec<RelSize>,
pub total_trits: usize,
pub bits: usize,
pub bytes: usize,
}
#[derive(Debug, Clone)]
pub struct CertSize {
pub n1: WalkSize, pub n2: GovSize, pub n3_trits: usize, pub n3_bits: usize,
pub n3_bytes: usize,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::expr::Expr;
use crate::gen::Gen;
use crate::rat::Rat;
use crate::trace::TraceGen;
use crate::word::Word;
#[test]
fn gen_is_one_trit() {
assert_eq!(gen_size(), 1);
}
#[test]
fn word_grade2_is_2_trits() {
let w = Word::from_gens(&[Gen::imaginary(0), Gen::imaginary(1)]);
assert_eq!(word_size(&w), 2);
}
#[test]
fn scalar_word_is_0_trits() {
assert_eq!(word_size(&Word::scalar()), 0);
}
#[test]
fn tern_zero_is_1_trit() {
assert_eq!(tern_size(0), 1);
}
#[test]
fn tern_one_is_1_trit() {
assert_eq!(tern_size(1), 1);
}
#[test]
fn tern_neg_one_is_1_trit() {
assert_eq!(tern_size(-1), 1);
}
#[test]
fn tern_4_needs_2_trits() {
assert_eq!(tern_size(4), 2);
}
#[test]
fn rat_one_is_2_trits() {
assert_eq!(rat_size(&Rat::one()), 2);
}
#[test]
fn rat_neg_one_is_2_trits() {
assert_eq!(rat_size(&Rat::neg_one()), 2);
}
#[test]
fn expr_int_neg1_size() {
assert_eq!(expr_size(&Expr::int(-1)), 2);
}
#[test]
fn expr_gen_size() {
let e = Expr::gen(Gen::imaginary(0));
assert_eq!(expr_size(&e), 3);
}
#[test]
fn tracegen_e1e1_step_size() {
let tg = TraceGen::new(
0,
0,
Word::from_gens(&[Gen::imaginary(0), Gen::imaginary(0)]),
);
let size = tracegen_size(&tg);
assert_eq!(size.rule_idx_trits, 0);
assert_eq!(size.start_trits, 0);
assert_eq!(size.sep_trits, 2);
assert_eq!(size.matched_trits, 2);
assert_eq!(size.total_trits, 4);
assert_eq!(size.bits, 8);
}
#[test]
fn tracegen_with_nonzero_rule_and_start() {
let tg = TraceGen::new(3, 2, Word::from_gens(&[Gen::hyperbolic(0)]));
let size = tracegen_size(&tg);
assert_eq!(size.total_trits, 8);
}
#[test]
fn walk_single_step_e1e1_is_4_trits() {
use crate::trace::TraceWalk;
let tg = TraceGen::new(
0,
0,
Word::from_gens(&[Gen::imaginary(0), Gen::imaginary(0)]),
);
let walk = TraceWalk::singleton(tg);
let size = tracewalk_size(&walk);
assert_eq!(size.steps, 1);
assert_eq!(size.total_trits, 4);
assert_eq!(size.bits, 8);
assert_eq!(size.bytes, 1);
}
#[test]
fn empty_walk_is_0_trits() {
use crate::trace::TraceWalk;
let walk = TraceWalk::empty();
let size = tracewalk_size(&walk);
assert_eq!(size.total_trits, 0);
}
#[test]
fn governance_cl100_size() {
use crate::governance::Governance;
let gov = Governance::cl(1, 0, 0);
let size = governance_size(&gov);
assert_eq!(size.num_relations, 1);
assert_eq!(size.total_trits, 4);
}
#[test]
fn size_scales_with_algebra() {
use crate::governance::Governance;
let g1 = governance_size(&Governance::cl(1, 0, 0));
let g2 = governance_size(&Governance::cl(2, 0, 0));
let g3 = governance_size(&Governance::cl(3, 0, 0));
assert!(g2.total_trits > g1.total_trits);
assert!(g3.total_trits > g2.total_trits);
}
}