1#![no_std]
70
71#![cfg_attr(feature = "i128", feature(i128_type))]
72
73pub extern crate typenum;
74
75pub mod aliases;
77
78use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
79use core::fmt::{Debug, Error, Formatter};
80use core::hash::{Hash, Hasher};
81use core::marker::PhantomData;
82use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
83use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
84
85use typenum::consts::Z0;
86use typenum::marker_traits::{Bit, Integer, Unsigned};
87use typenum::operator_aliases::{AbsVal, Diff, Le, Sum};
88use typenum::type_operators::{Abs, IsLess};
89
90pub struct Fix<Bits, Base, Exp> {
118 pub bits: Bits,
120
121 marker: PhantomData<(Base, Exp)>,
122}
123
124impl<Bits, Base, Exp> Fix<Bits, Base, Exp> {
125 pub fn new(bits: Bits) -> Self {
135 Fix { bits, marker: PhantomData }
136 }
137
138 pub fn convert<ToExp>(self) -> Fix<Bits, Base, ToExp>
150 where
151 Bits: FromUnsigned + Pow + Mul<Output = Bits> + Div<Output = Bits>,
152 Base: Unsigned,
153 Exp: Sub<ToExp>,
154 Diff<Exp, ToExp>: Abs + IsLess<Z0>,
155 AbsVal<Diff<Exp, ToExp>>: Integer
156 {
157 let base = Bits::from_unsigned::<Base>();
158 let diff = AbsVal::<Diff<Exp, ToExp>>::to_i32();
159 let inverse = Le::<Diff<Exp, ToExp>, Z0>::to_bool();
160
161 let ratio = base.pow(diff as u32);
164
165 if inverse {
166 Fix::new(self.bits / ratio)
167 } else {
168 Fix::new(self.bits * ratio)
169 }
170 }
171}
172
173pub trait FromUnsigned {
180 fn from_unsigned<U>() -> Self where U: Unsigned;
182}
183
184impl FromUnsigned for u8 { fn from_unsigned<U: Unsigned>() -> Self { U::to_u8() } }
185impl FromUnsigned for u16 { fn from_unsigned<U: Unsigned>() -> Self { U::to_u16() } }
186impl FromUnsigned for u32 { fn from_unsigned<U: Unsigned>() -> Self { U::to_u32() } }
187impl FromUnsigned for u64 { fn from_unsigned<U: Unsigned>() -> Self { U::to_u64() } }
188impl FromUnsigned for usize { fn from_unsigned<U: Unsigned>() -> Self { U::to_usize() } }
189
190impl FromUnsigned for i8 { fn from_unsigned<U: Unsigned>() -> Self { U::to_i8() } }
191impl FromUnsigned for i16 { fn from_unsigned<U: Unsigned>() -> Self { U::to_i16() } }
192impl FromUnsigned for i32 { fn from_unsigned<U: Unsigned>() -> Self { U::to_i32() } }
193impl FromUnsigned for i64 { fn from_unsigned<U: Unsigned>() -> Self { U::to_i64() } }
194impl FromUnsigned for isize { fn from_unsigned<U: Unsigned>() -> Self { U::to_isize() } }
195
196pub trait Pow {
201 fn pow(self, exp: u32) -> Self;
203}
204
205impl Pow for u8 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
206impl Pow for u16 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
207impl Pow for u32 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
208impl Pow for u64 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
209impl Pow for usize { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
210
211impl Pow for i8 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
212impl Pow for i16 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
213impl Pow for i32 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
214impl Pow for i64 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
215impl Pow for isize { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
216
217#[cfg(feature = "i128")]
218mod __i128 {
219 use super::*;
220 impl FromUnsigned for u128 { fn from_unsigned<U: Unsigned>() -> Self { U::to_u128() } }
221 impl FromUnsigned for i128 { fn from_unsigned<U: Unsigned>() -> Self { U::to_i128() } }
222 impl Pow for u128 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
223 impl Pow for i128 { #[inline] fn pow(self, exp: u32) -> Self { self.pow(exp) } }
224}
225
226impl<Bits, Base, Exp> Copy for Fix<Bits, Base, Exp> where Bits: Copy { }
229impl<Bits, Base, Exp> Clone for Fix<Bits, Base, Exp>
230where Bits: Clone {
231 fn clone(&self) -> Self {
232 Self::new(self.bits.clone())
233 }
234}
235
236impl<Bits, Base, Exp> Default for Fix<Bits, Base, Exp>
237where Bits: Default {
238 fn default() -> Self {
239 Self::new(Bits::default())
240 }
241}
242
243impl<Bits, Base, Exp> Hash for Fix<Bits, Base, Exp>
244where Bits: Hash {
245 fn hash<H>(&self, state: &mut H) where H: Hasher {
246 self.bits.hash(state);
247 }
248}
249
250impl<Bits, Base, Exp> Debug for Fix<Bits, Base, Exp>
251where Bits: Debug, Base: Unsigned, Exp: Integer {
252 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
253 write!(f, "{:?}x{}^{}", self.bits, Base::to_u64(), Exp::to_i64())
254 }
255}
256
257impl<Bits, Base, Exp> Eq for Fix<Bits, Base, Exp> where Bits: Eq { }
260impl<Bits, Base, Exp> PartialEq for Fix<Bits, Base, Exp>
261where Bits: PartialEq {
262 fn eq(&self, rhs: &Self) -> bool {
263 self.bits == rhs.bits
264 }
265}
266
267impl<Bits, Base, Exp> PartialOrd for Fix<Bits, Base, Exp>
268where Bits: PartialOrd {
269 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
270 self.bits.partial_cmp(&rhs.bits)
271 }
272}
273
274impl<Bits, Base, Exp> Ord for Fix<Bits, Base, Exp>
275where Bits: Ord {
276 fn cmp(&self, rhs: &Self) -> Ordering {
277 self.bits.cmp(&rhs.bits)
278 }
279}
280
281impl<Bits, Base, Exp> Neg for Fix<Bits, Base, Exp>
284where Bits: Neg<Output = Bits> {
285 type Output = Self;
286 fn neg(self) -> Self {
287 Self::new(-self.bits)
288 }
289}
290
291impl<Bits, Base, Exp> Add for Fix<Bits, Base, Exp>
292where Bits: Add<Output = Bits> {
293 type Output = Self;
294 fn add(self, rhs: Self) -> Self {
295 Self::new(self.bits + rhs.bits)
296 }
297}
298
299impl<Bits, Base, Exp> Sub for Fix<Bits, Base, Exp>
300where Bits: Sub<Output = Bits> {
301 type Output = Self;
302 fn sub(self, rhs: Self) -> Self {
303 Self::new(self.bits - rhs.bits)
304 }
305}
306
307impl<Bits, Base, LExp, RExp> Mul<Fix<Bits, Base, RExp>> for Fix<Bits, Base, LExp>
308where Bits: Mul<Output = Bits>, LExp: Add<RExp> {
309 type Output = Fix<Bits, Base, Sum<LExp, RExp>>;
310 fn mul(self, rhs: Fix<Bits, Base, RExp>) -> Self::Output {
311 Self::Output::new(self.bits * rhs.bits)
312 }
313}
314
315impl<Bits, Base, LExp, RExp> Div<Fix<Bits, Base, RExp>> for Fix<Bits, Base, LExp>
316where Bits: Div<Output = Bits>, LExp: Sub<RExp> {
317 type Output = Fix<Bits, Base, Diff<LExp, RExp>>;
318 fn div(self, rhs: Fix<Bits, Base, RExp>) -> Self::Output {
319 Self::Output::new(self.bits / rhs.bits)
320 }
321}
322
323impl<Bits, Base, Exp> Rem for Fix<Bits, Base, Exp>
324where Bits: Rem<Output = Bits> {
325 type Output = Self;
326 fn rem(self, rhs: Self) -> Self {
327 Self::new(self.bits % rhs.bits)
328 }
329}
330
331impl<Bits, Base, Exp> Mul<Bits> for Fix<Bits, Base, Exp>
332where Bits: Mul<Output = Bits> {
333 type Output = Self;
334 fn mul(self, rhs: Bits) -> Self {
335 Self::new(self.bits * rhs)
336 }
337}
338
339impl<Bits, Base, Exp> Div<Bits> for Fix<Bits, Base, Exp>
340where Bits: Div<Output = Bits> {
341 type Output = Self;
342 fn div(self, rhs: Bits) -> Self {
343 Self::new(self.bits / rhs)
344 }
345}
346
347impl<Bits, Base, Exp> Rem<Bits> for Fix<Bits, Base, Exp>
348where Bits: Rem<Output = Bits> {
349 type Output = Self;
350 fn rem(self, rhs: Bits) -> Self {
351 Self::new(self.bits % rhs)
352 }
353}
354
355impl<Bits, Base, Exp> AddAssign for Fix<Bits, Base, Exp>
358where Bits: AddAssign {
359 fn add_assign(&mut self, rhs: Self) {
360 self.bits += rhs.bits;
361 }
362}
363
364impl<Bits, Base, Exp> SubAssign for Fix<Bits, Base, Exp>
365where Bits: SubAssign {
366 fn sub_assign(&mut self, rhs: Self) {
367 self.bits -= rhs.bits;
368 }
369}
370
371impl<Bits, Base, Exp> MulAssign<Bits> for Fix<Bits, Base, Exp>
372where Bits: MulAssign {
373 fn mul_assign(&mut self, rhs: Bits) {
374 self.bits *= rhs;
375 }
376}
377
378impl<Bits, Base, Exp> DivAssign<Bits> for Fix<Bits, Base, Exp>
379where Bits: DivAssign {
380 fn div_assign(&mut self, rhs: Bits) {
381 self.bits /= rhs;
382 }
383}
384
385impl<Bits, Base, LExp, RExp> RemAssign<Fix<Bits, Base, RExp>> for Fix<Bits, Base, LExp>
386where Bits: RemAssign {
387 fn rem_assign(&mut self, rhs: Fix<Bits, Base, RExp>) {
388 self.bits %= rhs.bits;
389 }
390}
391
392impl<Bits, Base, Exp> RemAssign<Bits> for Fix<Bits, Base, Exp>
393where Bits: RemAssign {
394 fn rem_assign(&mut self, rhs: Bits) {
395 self.bits %= rhs;
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use aliases::si::{Kilo, Milli, Unit};
402
403 #[test]
404 fn convert_milli_to_kilo() {
405 assert_eq!(Kilo::new(15), Milli::new(15_000_000).convert());
406 }
407
408 #[test]
409 fn convert_kilo_to_milli() {
410 assert_eq!(Milli::new(15_000_000), Kilo::new(15).convert());
411 }
412
413 #[test]
414 fn cmp() {
415 assert!(Kilo::new(1) < Kilo::new(2));
416 }
417
418 #[test]
419 fn neg() {
420 assert_eq!(Kilo::new(-1), -Kilo::new(1i32));
421 }
422
423 #[test]
424 fn add() {
425 assert_eq!(Kilo::new(3), Kilo::new(1) + Kilo::new(2));
426 }
427
428 #[test]
429 fn sub() {
430 assert_eq!(Kilo::new(1), Kilo::new(3) - Kilo::new(2));
431 }
432
433 #[test]
434 fn mul() {
435 assert_eq!(Unit::new(6), Kilo::new(2) * Milli::new(3));
436 }
437
438 #[test]
439 fn div() {
440 assert_eq!(Unit::new(3), Kilo::new(6) / Kilo::new(2));
441 }
442
443 #[test]
444 fn rem() {
445 assert_eq!(Kilo::new(1), Kilo::new(6) % Kilo::new(5));
446 }
447
448 #[test]
449 fn mul_bits() {
450 assert_eq!(Kilo::new(6), Kilo::new(2) * 3);
451 }
452
453 #[test]
454 fn div_bits() {
455 assert_eq!(Kilo::new(3), Kilo::new(6) / 2);
456 }
457
458 #[test]
459 fn rem_bits() {
460 assert_eq!(Kilo::new(1), Kilo::new(6) % 5);
461 }
462
463 #[test]
464 fn add_assign() {
465 let mut a = Kilo::new(1);
466 a += Kilo::new(2);
467 assert_eq!(Kilo::new(3), a);
468 }
469
470 #[test]
471 fn sub_assign() {
472 let mut a = Kilo::new(3);
473 a -= Kilo::new(2);
474 assert_eq!(Kilo::new(1), a);
475 }
476
477 #[test]
478 fn mul_assign_bits() {
479 let mut a = Kilo::new(2);
480 a *= 3;
481 assert_eq!(Kilo::new(6), a);
482 }
483
484 #[test]
485 fn div_assign_bits() {
486 let mut a = Kilo::new(6);
487 a /= 2;
488 assert_eq!(Kilo::new(3), a);
489 }
490
491 #[test]
492 fn rem_assign() {
493 let mut a = Kilo::new(6);
494 a %= Milli::new(5);
495 assert_eq!(Kilo::new(1), a);
496 }
497
498 #[test]
499 fn rem_assign_bits() {
500 let mut a = Kilo::new(6);
501 a %= 5;
502 assert_eq!(Kilo::new(1), a);
503 }
504}