rust_fixed_point_decimal/
unops.rs1use std::ops::Neg;
11
12use num::Integer;
13use rust_fixed_point_decimal_core::ten_pow;
14
15use crate::{
16 prec_constraints::{PrecLimitCheck, True},
17 Decimal, MAX_PREC,
18};
19
20impl<const P: u8> Neg for Decimal<P>
21where
22 PrecLimitCheck<{ P <= MAX_PREC }>: True,
23{
24 type Output = Self;
25
26 fn neg(self) -> Self::Output {
33 Self::Output { coeff: -self.coeff }
34 }
35}
36
37impl<const P: u8> Neg for &Decimal<P>
38where
39 PrecLimitCheck<{ P <= MAX_PREC }>: True,
40{
41 type Output = <Decimal<P> as Neg>::Output;
42
43 fn neg(self) -> Self::Output {
50 Self::Output { coeff: -self.coeff }
51 }
52}
53
54impl<const P: u8> Decimal<P>
55where
56 PrecLimitCheck<{ P <= MAX_PREC }>: True,
57{
58 #[inline]
60 pub fn abs(&self) -> Self {
61 Self {
62 coeff: self.coeff.abs(),
63 }
64 }
65
66 #[inline]
85 pub fn floor(&self) -> Self {
86 match P {
87 0 => self.clone(),
88 _ => Self {
89 coeff: self.coeff.div_floor(&ten_pow(P)) * ten_pow(P),
90 },
91 }
92 }
93
94 #[inline]
113 pub fn ceil(&self) -> Self {
114 match P {
115 0 => self.clone(),
116 _ => Self {
117 coeff: self.coeff.div_ceil(&ten_pow(P)) * ten_pow(P),
118 },
119 }
120 }
121
122 #[inline]
134 pub fn trunc(&self) -> Self {
135 if P == 0 {
136 *self
137 } else {
138 Self {
139 coeff: (self.coeff / ten_pow(P)) * ten_pow(P),
140 }
141 }
142 }
143
144 #[inline]
156 pub fn fract(&self) -> Self {
157 if P == 0 {
158 Self::ZERO
159 } else {
160 Self {
161 coeff: self.coeff % ten_pow(P),
162 }
163 }
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use crate::Decimal;
170
171 #[test]
172 fn test_neg() {
173 let val = 1234567890i128;
174 let x: Decimal<2> = Decimal::new_raw(val);
175 let y = -x;
176 assert_eq!(x.coeff, -y.coeff);
177 let z = -y;
178 assert_eq!(x.coeff, z.coeff);
179 let a = &x;
180 let b = -a;
181 assert_eq!(a.coeff, -b.coeff);
182 }
183
184 #[test]
185 fn test_neg_corner_cases_ok() {
186 let x = Decimal::<2>::MAX;
187 let y = -x;
188 assert_eq!(x.coeff, -y.coeff);
189 let z = -y;
190 assert_eq!(x.coeff, z.coeff);
191 }
192
193 #[test]
194 #[should_panic]
195 fn test_neg_corner_cases_fail() {
196 let x = Decimal::<2>::MIN;
197 let _y = -x;
198 }
199
200 #[test]
201 fn test_abs() {
202 let x = Decimal::<4>::new_raw(-123456789);
203 let y = x.abs();
204 assert_eq!(-x.coeff, y.coeff);
205 let z = y.abs();
206 assert_eq!(y.coeff, z.coeff);
207 let a = &x;
208 let b = a.abs();
209 assert_eq!(-a.coeff, b.coeff);
210 }
211
212 #[test]
213 fn test_floor() {
214 let x = Decimal::<0>::new_raw(123);
215 let y = x.floor();
216 assert_eq!(y.coeff, x.coeff);
217 let x = Decimal::<5>::new_raw(123456789);
218 let y = x.floor();
219 assert_eq!(y.coeff, 123400000);
220 let z = y.floor();
221 assert_eq!(y.coeff, z.coeff);
222 let x = Decimal::<9>::new_raw(-987);
223 let y = x.floor();
224 assert_eq!(y.coeff, -1000000000);
225 let z = y.floor();
226 assert_eq!(y.coeff, z.coeff);
227 let a = &x;
228 let b = a.floor();
229 assert_eq!(b.coeff, y.coeff);
230 }
231
232 #[test]
233 #[should_panic]
234 fn test_floor_overflow() {
235 let x = Decimal::<3>::new_raw((i128::MIN / 1000) * 1000 - 1);
236 let _y = x.floor();
237 }
238
239 #[test]
240 fn test_ceil() {
241 let x = Decimal::<0>::new_raw(123);
242 let y = x.ceil();
243 assert_eq!(y.coeff, x.coeff);
244 let x = Decimal::<5>::new_raw(123400001);
245 let y = x.ceil();
246 assert_eq!(y.coeff, 123500000);
247 let z = y.ceil();
248 assert_eq!(y.coeff, z.coeff);
249 let x = Decimal::<9>::new_raw(-987);
250 let y = x.ceil();
251 assert_eq!(y.coeff, 0);
252 let z = y.ceil();
253 assert_eq!(y.coeff, z.coeff);
254 let a = &x;
255 let b = a.ceil();
256 assert_eq!(b.coeff, y.coeff);
257 }
258
259 #[test]
260 #[should_panic]
261 fn test_ceil_overflow() {
262 let x = Decimal::<2>::new_raw((i128::MAX / 100) * 100 + 1);
263 let _y = x.ceil();
264 }
265
266 #[test]
267 fn test_trunc() {
268 let x = Decimal::<0>::new_raw(12345);
269 let y = x.trunc();
270 assert_eq!(x.coeff, y.coeff);
271 let x = Decimal::<3>::new_raw(98765);
272 let y = x.trunc();
273 assert_eq!(y.coeff, 98000);
274 let x = Decimal::<7>::new_raw(999999);
275 let y = x.trunc();
276 assert_eq!(y.coeff, 0);
277 let a = &x;
278 let b = a.trunc();
279 assert_eq!(b.coeff, y.coeff);
280 }
281
282 #[test]
283 fn test_fract() {
284 let x = Decimal::<0>::new_raw(12345);
285 let y = x.fract();
286 assert_eq!(y.coeff, 0);
287 let x = Decimal::<3>::new_raw(987654);
288 let y = x.fract();
289 assert_eq!(y.coeff, 654);
290 let x = Decimal::<5>::new_raw(9999);
291 let y = x.fract();
292 assert_eq!(y.coeff, 9999);
293 let a = &x;
294 let b = a.fract();
295 assert_eq!(b.coeff, y.coeff);
296 }
297}