scalc/
impls.rs

1// Copyright 2019 LEXUGE
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16// use(s)
17use {
18    crate::SCell,
19    num_traits::{
20        CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Num, One, Signed,
21        Zero,
22    },
23    std::{
24        ops::{Add, Div, Mul, Not, Rem, Sub},
25        str::FromStr,
26    },
27};
28
29// Basic implementations
30impl<T> SCell<T> {
31    /// Create a new `SCell`
32    pub fn new(data: T) -> Self {
33        SCell { data }
34    }
35    /// Get the data of underlying type `T`
36    pub fn get_data(&self) -> &T {
37        &self.data
38    }
39}
40
41// Implementations of methods which are given in `One` and `Zero`
42impl<T: Zero> SCell<T> {
43    /// See `num` crate for more information
44    pub fn zero() -> Self {
45        SCell::new(T::zero())
46    }
47    /// See `num` crate for more information
48    pub fn is_zero(&self) -> bool {
49        self.data.is_zero()
50    }
51}
52impl<T: One + PartialEq> SCell<T> {
53    /// See `num` crate for more information
54    pub fn one() -> Self {
55        SCell::new(T::one())
56    }
57    /// See `num` crate for more information
58    pub fn is_one(&self) -> bool {
59        self.data.is_one()
60    }
61}
62
63// Implementations of `Ops`
64ops!(+=, add, Add);
65ops!(-=, sub, Sub);
66ops!(*=, mul, Mul);
67ops!(/=, div, Div);
68ops!(%=, rem, Rem);
69ops!(neg);
70
71// Implementation of method which is given in `Num`
72impl<T: Num + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + CheckedRem> SCell<T> {
73    /// See `num` crate for more information
74    pub fn from_str_radix(str: &str, radix: u32) -> Result<Self, T::FromStrRadixErr> {
75        let data = T::from_str_radix(str, radix)?;
76        Ok(SCell { data })
77    }
78}
79
80// Implementation of methods which are given in `Signed`
81impl<
82        T: Signed
83            + CheckedAdd
84            + CheckedSub
85            + CheckedMul
86            + CheckedDiv
87            + CheckedRem
88            + CheckedNeg
89            + Ord
90            + Copy,
91    > SCell<T>
92{
93    /// See `num` crate for more information
94    pub fn abs(&self) -> Option<Self> {
95        if *self < Self::zero() {
96            -*self
97        } else {
98            Some(*self)
99        }
100    }
101    /// See `num` crate for more information
102    pub fn abs_sub(&self, other: &Self) -> Option<Self> {
103        if *self <= *other {
104            Some(Self::zero())
105        } else {
106            *self - *other
107        }
108    }
109    /// See `num` crate for more information
110    pub fn signum(&self) -> Self {
111        SCell {
112            data: self.data.signum(),
113        }
114    }
115    /// See `num` crate for more information
116    pub fn is_positive(&self) -> bool {
117        self.data.is_positive()
118    }
119    /// See `num` crate for more information
120    pub fn is_negative(&self) -> bool {
121        self.data.is_negative()
122    }
123}
124
125// Implementation of `FromStr`
126impl<T: FromStr> FromStr for SCell<T> {
127    type Err = T::Err;
128    fn from_str(s: &str) -> Result<Self, Self::Err> {
129        Ok(SCell::new(T::from_str(s)?))
130    }
131}
132
133// Implementation of `Not`
134impl<T: Not> Not for SCell<T> {
135    type Output = SCell<T::Output>;
136    fn not(self) -> Self::Output {
137        SCell::new(!self.data)
138    }
139}