1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use super::literal::*;
use super::free_group_term::FreeGroupTerm;
use super::Term;
use std::ops::Mul;

/// Short means length at most three
#[derive(Eq, PartialOrd, PartialEq, Ord, Debug, Clone, Copy)]
pub struct ShortFreeGroupTerm {
    pub left:  Option<Literal>,
    pub mid:   Option<Literal>,
    pub right: Option<Literal>
}

impl ShortFreeGroupTerm {
    pub fn new(
        left: Option<Literal>, 
        mid: Option<Literal>, 
        right: Option<Literal>) -> ShortFreeGroupTerm {
        ShortFreeGroupTerm {
            left: left,
            mid: mid,
            right: right
        }
    }
}

impl From<FreeGroupTerm> for ShortFreeGroupTerm {
    /// ignores everything after the third symbol
    fn from(term: FreeGroupTerm) -> ShortFreeGroupTerm {
        let literals = term.literals;
        match literals.len() {
            0 => ShortFreeGroupTerm::new(None, None, None),
            1 => ShortFreeGroupTerm::new(Some(literals[0]), None, None),
            2 => ShortFreeGroupTerm::new(Some(literals[0]), Some(literals[1]), None),
            _ => ShortFreeGroupTerm::new(Some(literals[0]), Some(literals[1]), Some(literals[2]))
        }
    }
}

impl From<&str> for ShortFreeGroupTerm {
    fn from(s: &str) -> ShortFreeGroupTerm {
        ShortFreeGroupTerm::from(FreeGroupTerm::from(s))
    }
}

impl From<char> for ShortFreeGroupTerm {
    fn from(c: char) -> ShortFreeGroupTerm {
        ShortFreeGroupTerm::from(FreeGroupTerm::from(c))
    }
}

impl From<Literal> for ShortFreeGroupTerm {
    fn from(x: Literal) -> ShortFreeGroupTerm {
        ShortFreeGroupTerm::from(FreeGroupTerm::from(x))
    }
}

impl ToString for ShortFreeGroupTerm {
    fn to_string(&self) -> String {
        let mut string = String::new();
        for option in &[self.left, self.mid, self.right] {
            match option {
                Some(literal) => string.push_str(literal.to_string().as_str()),
                None => {}
            };
        }
        if string.len() == 0 {
            string.push('e');
        }
        return string;
    }
}

impl Term for ShortFreeGroupTerm {
    fn inverse(&self) -> ShortFreeGroupTerm {
        match (self.left, self.mid, self.right) {
            (Some(x), Some(y), Some(z)) => {
                ShortFreeGroupTerm {
                    left:  Some(x.inverse()),
                    mid:   Some(y.inverse()),
                    right: Some(z.inverse())
                }
            },
            (Some(x), Some(y), None) => {
                ShortFreeGroupTerm {
                    left:  Some(y.inverse()),
                    mid:   Some(x.inverse()),
                    right: None
                }
            },
            (Some(x), None, None) => {
                ShortFreeGroupTerm {
                    left:  Some(x.inverse()),
                    mid:   None,
                    right: None,
                }
            },
            (None, None, None) => {
                ShortFreeGroupTerm {
                    left:  None,
                    mid:   None,
                    right: None
                }
            }
            _ => panic!("invalid short term ...")
        }
    }
}

pub trait Len {
    fn len(&self) -> usize;
}

impl Len for ShortFreeGroupTerm {
    fn len(&self) -> usize {
        match (self.left, self.mid, self.right) {
            (None, None, None)          => 0,
            (Some(_), None, None)       => 1,
            (Some(_), Some(_), None)    => 2,
            (Some(_), Some(_), Some(_)) => 3,
            _                           => panic!("Invalid short free group term!")
        }
    }
}

pub struct LongFreeGroupTermError;

impl Mul for ShortFreeGroupTerm {
    type Output = ShortFreeGroupTerm;

    /// Warning: This does not check whether the product is indeed short.
    fn mul(self, other: ShortFreeGroupTerm) -> ShortFreeGroupTerm {
        ShortFreeGroupTerm::from(FreeGroupTerm::from(self) * FreeGroupTerm::from(other))
    }
}