rustfst 0.1.3

Library for Weighted Finite States Transducers as decribed by Mohri and Allauzen
Documentation
use semirings::{CompleteSemiring, Semiring, StarSemiring, WeaklyDivisibleSemiring};
use std::f32;
use std::ops::{Add, AddAssign, Mul, MulAssign};

#[derive(Clone, Debug, PartialEq, Default)]
pub struct LogWeight {
    value: f32,
}

impl LogWeight {
    pub fn new(value: f32) -> Self {
        LogWeight { value }
    }
}

fn ln_pos_exp(x: f32) -> f32 {
    ((-x).exp()).ln_1p()
}

impl Semiring for LogWeight {
    type Type = f32;

    fn plus(&self, rhs: &Self) -> Self {
        let f1 = self.value();
        let f2 = rhs.value();
        if f1 == f32::INFINITY {
            return rhs.clone();
        } else if f2 == f32::INFINITY {
            return self.clone();
        } else if f1 > f2 {
            return Self::new(f2 - ln_pos_exp(f1 - f2));
        } else {
            return Self::new(f1 - ln_pos_exp(f2 - f1));
        }
    }

    fn times(&self, rhs: &Self) -> Self {
        let f1 = self.value();
        let f2 = rhs.value();
        if f1 == f32::INFINITY {
            return self.clone();
        } else if f2 == f32::INFINITY {
            return rhs.clone();
        } else {
            return Self::new(f1 + f2);
        }
    }

    fn zero() -> Self {
        Self::new(f32::INFINITY)
    }

    fn one() -> Self {
        Self::new(0.0)
    }

    fn value(&self) -> Self::Type {
        self.value
    }

    fn set_value(&mut self, value: <Self as Semiring>::Type) {
        self.value = value
    }
}

add_mul_semiring!(LogWeight);
display_semiring!(LogWeight);

impl CompleteSemiring for LogWeight {}

impl StarSemiring for LogWeight {
    fn closure(&self) -> Self {
        if self.value >= 0.0 && self.value < 1.0 {
            Self::new((1.0 - self.value).ln())
        } else {
            Self::new(f32::NEG_INFINITY)
        }
    }
}

impl WeaklyDivisibleSemiring for LogWeight {
    fn inverse(&self) -> Self {
        Self::new(-self.value)
    }

    fn divide(&self, rhs: &Self) -> Self {
        Self::new(self.value - rhs.value)
    }
}