1#![cfg_attr(not(feature = "std"), no_std)]
2#![doc = include_str!("../README.md")]
3
4#[cfg(not(feature = "std"))]
5#[allow(unused_imports)]
6use num_traits::float::FloatCore;
7use num_traits::{AsPrimitive, ConstOne, ConstZero, One, Zero};
8
9use core::{
10 fmt, iter,
11 marker::PhantomData,
12 num::Wrapping,
13 ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub},
14 ops::{AddAssign, DivAssign, MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign},
15 ops::{BitAnd, BitOr, BitXor, Not},
16 ops::{BitAndAssign, BitOrAssign, BitXorAssign},
17};
18
19pub trait Shift: Copy + Shl<usize, Output = Self> + Shr<usize, Output = Self> {
23 fn shs(self, f: i8) -> Self;
33}
34
35impl<T: Copy + Shl<usize, Output = T> + Shr<usize, Output = T>> Shift for T {
36 #[inline(always)]
37 fn shs(self, f: i8) -> Self {
38 if f >= 0 {
39 self << (f as _)
40 } else {
41 self >> (-f as _)
42 }
43 }
44}
45
46pub trait Accu<A> {
48 fn up(self) -> A;
57
58 fn down(a: A) -> Self;
67
68 }
77
78#[derive(Default, serde::Serialize, serde::Deserialize)]
99#[repr(transparent)]
100#[serde(transparent)]
101pub struct Q<T, A, const F: i8> {
102 _accu: PhantomData<A>,
104 pub inner: T,
106}
107
108impl<T: Clone, A, const F: i8> Clone for Q<T, A, F> {
109 #[inline]
110 fn clone(&self) -> Self {
111 Self {
112 _accu: PhantomData,
113 inner: self.inner.clone(),
114 }
115 }
116}
117
118impl<T: Copy, A, const F: i8> Copy for Q<T, A, F> {}
119
120impl<T: PartialEq, A, const F: i8> PartialEq for Q<T, A, F> {
121 #[inline]
122 fn eq(&self, other: &Self) -> bool {
123 self.inner.eq(&other.inner)
124 }
125}
126
127impl<T: Eq, A, const F: i8> Eq for Q<T, A, F> where Self: PartialEq {}
128
129impl<T: PartialOrd, A, const F: i8> PartialOrd for Q<T, A, F> {
130 #[inline]
131 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
132 self.inner.partial_cmp(&other.inner)
133 }
134}
135
136impl<T: Ord, A, const F: i8> Ord for Q<T, A, F>
137where
138 Self: PartialOrd,
139{
140 #[inline]
141 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
142 self.inner.cmp(&other.inner)
143 }
144}
145
146impl<T: One + Shift, A, const F: i8> One for Q<T, A, F>
147where
148 Self: Mul<Output = Self>,
149{
150 fn one() -> Self {
151 Self::new(T::one().shs(F))
152 }
153}
154
155impl<T: Zero, A, const F: i8> Zero for Q<T, A, F>
156where
157 Self: Add<Output = Self>,
158{
159 fn zero() -> Self {
160 Self::new(T::zero())
161 }
162
163 fn is_zero(&self) -> bool {
164 self.inner.is_zero()
165 }
166}
167
168impl<T: ConstZero, A, const F: i8> ConstZero for Q<T, A, F> {
169 const ZERO: Self = Self::new(T::ZERO);
170}
171
172impl<T, A, const F: i8> Q<T, A, F> {
173 pub const DELTA: f32 = if F > 0 {
181 1.0 / (1u128 << F) as f32
182 } else {
183 (1u128 << -F) as f32
184 };
185
186 #[inline]
193 pub const fn new(inner: T) -> Self {
194 Self {
195 _accu: PhantomData,
196 inner,
197 }
198 }
199}
200
201impl<T: Shift, A, const F: i8> Q<T, A, F> {
202 #[inline]
211 pub fn scale<const F1: i8>(self) -> Q<T, A, F1> {
212 Q::new(self.inner.shs(F1 - F))
213 }
214
215 #[inline]
222 pub fn trunc(self) -> T {
223 self.inner.shs(-F)
224 }
225
226 #[inline]
233 pub fn from_int(value: T) -> Self {
234 Self::new(value.shs(F))
235 }
236}
237
238impl<A: Shift, T: Accu<A>, const F: i8> Q<A, T, F> {
239 #[inline]
248 pub fn quantize(self) -> T {
249 T::down(self.trunc())
250 }
251}
252
253impl<T: Accu<A> + Shift, A, const F: i8> From<(T, i8)> for Q<T, A, F> {
260 fn from(value: (T, i8)) -> Self {
261 Self::new(value.0.shs(F - value.1))
262 }
263}
264
265impl<T, A, const F: i8> From<Q<T, A, F>> for (T, i8) {
273 fn from(value: Q<T, A, F>) -> Self {
274 (value.inner, F)
275 }
276}
277
278macro_rules! impl_as_float {
288 ($ty:ident) => {
289 impl<T: 'static + Copy, A: 'static, const F: i8> AsPrimitive<Q<T, A, F>> for $ty
290 where
291 $ty: AsPrimitive<T>,
292 {
293 #[inline]
294 fn as_(self) -> Q<T, A, F> {
295 Q::new(
296 (self * const { 1.0 / Q::<T, A, F>::DELTA as $ty })
297 .round()
298 .as_(),
299 )
300 }
301 }
302
303 impl<T: AsPrimitive<$ty>, A: 'static, const F: i8> AsPrimitive<$ty> for Q<T, A, F> {
304 #[inline]
305 fn as_(self) -> $ty {
306 self.inner.as_() * Self::DELTA as $ty
307 }
308 }
309 };
310}
311impl_as_float!(f32);
312impl_as_float!(f64);
313
314impl<T, A, const F: i8> Q<T, A, F>
315where
316 f32: AsPrimitive<Q<T, A, F>>,
317 Self: Copy + 'static,
318{
319 #[inline]
321 pub fn from_f32(value: f32) -> Self {
322 value.as_()
323 }
324}
325
326impl<T, A, const F: i8> Q<T, A, F>
327where
328 f64: AsPrimitive<Q<T, A, F>>,
329 Self: Copy + 'static,
330{
331 #[inline]
333 pub fn from_f64(value: f64) -> Self {
334 value.as_()
335 }
336}
337
338impl<T, A, const F: i8> Q<T, A, F>
339where
340 Self: 'static + Copy + AsPrimitive<f32>,
341{
342 #[inline]
344 pub fn as_f32(self) -> f32 {
345 self.as_()
346 }
347}
348
349impl<T, A, const F: i8> Q<T, A, F>
350where
351 Self: 'static + Copy + AsPrimitive<f64>,
352{
353 #[inline]
355 pub fn as_f64(self) -> f64 {
356 self.as_()
357 }
358}
359
360impl<T, A, const F: i8> AsPrimitive<Self> for Q<T, A, F>
361where
362 Self: Copy + 'static,
363{
364 fn as_(self) -> Self {
365 self
366 }
367}
368
369macro_rules! forward_unop {
370 ($tr:ident::$m:ident) => {
371 impl<T: $tr<Output = T>, A, const F: i8> $tr for Q<T, A, F> {
372 type Output = Self;
373 #[inline]
374 fn $m(self) -> Self::Output {
375 Self::new(<T as $tr>::$m(self.inner))
376 }
377 }
378 };
379}
380forward_unop!(Neg::neg);
381forward_unop!(Not::not);
382
383macro_rules! forward_sh_op {
384 ($tr:ident::$m:ident) => {
385 impl<U, T: $tr<U, Output = T>, A, const F: i8> $tr<U> for Q<T, A, F> {
386 type Output = Self;
387 #[inline]
388 fn $m(self, rhs: U) -> Self::Output {
389 Self::new(<T as $tr<U>>::$m(self.inner, rhs))
390 }
391 }
392 };
393}
394forward_sh_op!(Shr::shr);
395forward_sh_op!(Shl::shl);
396
397macro_rules! forward_sh_assign_op {
398 ($tr:ident::$m:ident) => {
399 impl<T: $tr<U>, U, A, const F: i8> $tr<U> for Q<T, A, F> {
400 #[inline]
401 fn $m(&mut self, rhs: U) {
402 <T as $tr<U>>::$m(&mut self.inner, rhs)
403 }
404 }
405 };
406}
407forward_sh_assign_op!(ShrAssign::shr_assign);
408forward_sh_assign_op!(ShlAssign::shl_assign);
409
410macro_rules! forward_binop {
423 ($tr:ident::$m:ident) => {
424 impl<T: $tr<T, Output = T>, A, const F: i8> $tr for Q<T, A, F> {
425 type Output = Self;
426 #[inline]
427 fn $m(self, rhs: Self) -> Self::Output {
428 Self::new(<T as $tr>::$m(self.inner, rhs.inner))
429 }
430 }
431 };
432}
433forward_binop!(Rem::rem);
434forward_binop!(Add::add);
435forward_binop!(Sub::sub);
436forward_binop!(BitAnd::bitand);
437forward_binop!(BitOr::bitor);
438forward_binop!(BitXor::bitxor);
439
440impl<T: Accu<A>, A: Mul<Output = A>, const F: i8> Mul<T> for Q<T, A, F> {
456 type Output = Q<A, T, F>;
457 #[inline]
458 fn mul(self, rhs: T) -> Q<A, T, F> {
459 Q::new(self.inner.up() * rhs.up())
460 }
461}
462
463impl<T: Div<Output = T>, A, const F: i8> Div<T> for Q<T, A, F> {
464 type Output = Self;
465 #[inline]
466 fn div(self, rhs: T) -> Self {
467 Q::new(self.inner / rhs)
468 }
469}
470
471macro_rules! forward_assign_op_foreign {
472 ($tr:ident::$m:ident) => {
473 impl<T: $tr<T>, A, const F: i8> $tr<T> for Q<T, A, F> {
474 #[inline]
475 fn $m(&mut self, rhs: T) {
476 <T as $tr>::$m(&mut self.inner, rhs)
477 }
478 }
479 };
480}
481forward_assign_op_foreign!(MulAssign::mul_assign);
482forward_assign_op_foreign!(DivAssign::div_assign);
483
484macro_rules! forward_assign_op {
485 ($tr:ident::$m:ident) => {
486 impl<T: $tr<T>, A, const F: i8> $tr for Q<T, A, F> {
487 #[inline]
488 fn $m(&mut self, rhs: Self) {
489 <T as $tr>::$m(&mut self.inner, rhs.inner)
490 }
491 }
492 };
493}
494forward_assign_op!(RemAssign::rem_assign);
495forward_assign_op!(AddAssign::add_assign);
496forward_assign_op!(SubAssign::sub_assign);
497forward_assign_op!(BitAndAssign::bitand_assign);
498forward_assign_op!(BitOrAssign::bitor_assign);
499forward_assign_op!(BitXorAssign::bitxor_assign);
500
501impl<T: Copy + Accu<A>, A: Shift + Mul<A, Output = A>, const F: i8, const F1: i8>
510 MulAssign<Q<T, A, F1>> for Q<T, A, F>
511{
512 #[inline]
513 fn mul_assign(&mut self, rhs: Q<T, A, F1>) {
514 self.inner = T::down((self.inner.up() * rhs.inner.up()).shs(-F1));
515 }
516}
517
518impl<
527 T: Copy + Shift + Accu<A> + Div<T, Output = T>,
528 A: Shift + Div<A, Output = A>,
529 const F: i8,
530 const F1: i8,
531> DivAssign<Q<T, A, F1>> for Q<T, A, F>
532{
533 #[inline]
534 fn div_assign(&mut self, rhs: Q<T, A, F1>) {
535 self.inner = if F1 > 0 {
536 T::down(self.inner.up().shs(F1) / rhs.inner.up())
537 } else {
538 self.inner.shs(F1) / rhs.inner
539 };
540 }
541}
542
543impl<T, A, const F: i8> Mul for Q<T, A, F>
553where
554 Self: MulAssign,
555{
556 type Output = Self;
557 #[inline]
558 fn mul(mut self, rhs: Self) -> Self::Output {
559 self *= rhs;
560 self
561 }
562}
563
564impl<T, A, const F: i8> Div for Q<T, A, F>
571where
572 Self: DivAssign,
573{
574 type Output = Self;
575 #[inline]
576 fn div(mut self, rhs: Self) -> Self::Output {
577 self /= rhs;
578 self
579 }
580}
581
582impl<T: iter::Sum, A, const F: i8> iter::Sum for Q<T, A, F> {
583 #[inline]
584 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
585 Self::new(iter.map(|i| i.inner).sum())
586 }
587}
588
589macro_rules! impl_fmt {
595 ($tr:path) => {
596 impl<T, A, const F: i8> $tr for Q<T, A, F>
597 where
598 Self: Copy + AsPrimitive<f64>,
599 {
600 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
601 <f64 as $tr>::fmt(&(*self).as_(), f)
602 }
603 }
604 };
605}
606impl_fmt!(fmt::Display);
607impl_fmt!(fmt::UpperExp);
608impl_fmt!(fmt::LowerExp);
609
610macro_rules! impl_dot_fmt {
617 ($tr:path) => {
618 impl<T: $tr, A, const F: i8> $tr for Q<T, A, F> {
619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
620 self.inner.fmt(f)
621 }
622 }
623 };
624}
625impl_dot_fmt!(fmt::Debug);
626impl_dot_fmt!(fmt::Binary);
627impl_dot_fmt!(fmt::Octal);
628impl_dot_fmt!(fmt::UpperHex);
629impl_dot_fmt!(fmt::LowerHex);
630
631macro_rules! impl_q {
634 ($alias:ident<$t:ty, $a:ty>) => {
636 impl_q!($alias<$t, $a>, $t, |x| x as _, core::convert::identity);
637 };
638 ($alias:ident<$t:ty, $a:ty>, $wrap:tt) => {
640 impl_q!($alias<$wrap<$t>, $wrap<$a>>, $t, |x: $wrap<_>| $wrap(x.0 as _), $wrap);
641 };
642 ($alias:ident<$t:ty, $a:ty>, $inner:ty, $as:expr, $wrap:expr) => {
644 impl Accu<$a> for $t {
645 #[inline(always)]
646 fn up(self) -> $a {
647 $as(self)
648 }
649 #[inline(always)]
650 fn down(a: $a) -> Self {
651 $as(a)
652 }
653 }
654
655 #[doc = concat!("Fixed point [`", stringify!($t), "`] with [`", stringify!($a), "`] accumulator")]
656 pub type $alias<const F: i8> = Q<$t, $a, F>;
657
658 impl<const F: i8> ConstOne for Q<$t, $a, F> {
659 const ONE: Self = Self::new($wrap(if F >= 0 {1 << F as usize} else {0}));
660 }
661
662 impl<const F: i8> AsPrimitive<$t> for Q<$a, $t, F> {
663 #[inline]
665 fn as_(self) -> $t {
666 self.quantize()
667 }
668 }
669
670 impl<const F: i8> Mul<Q<$t, $a, F>> for $t {
672 type Output = $t;
673
674 #[inline]
675 fn mul(self, rhs: Q<$t, $a, F>) -> Self::Output {
676 (rhs * self).quantize()
677 }
678 }
679
680 impl<const F: i8> Div<Q<$t, $a, F>> for $t {
682 type Output = $t;
683
684 #[inline]
685 fn div(self, rhs: Q<$t, $a, F>) -> Self::Output {
686 if F > 0 {
687 <$t>::down(self.up().shs(F) / rhs.inner.up())
688 } else {
689 self.shs(F) / rhs.inner
690 }
691 }
692 }
693 };
694}
695impl_q!(Q8<i8, i16>);
697impl_q!(Q16<i16, i32>);
698impl_q!(Q32<i32, i64>);
699impl_q!(Q64<i64, i128>);
700impl_q!(P8<u8, u16>);
702impl_q!(P16<u16, u32>);
703impl_q!(P32<u32, u64>);
704impl_q!(P64<u64, u128>);
705impl_q!(W8<i8, i16>, Wrapping);
707impl_q!(W16<i16, i32>, Wrapping);
708impl_q!(W32<i32, i64>, Wrapping);
709impl_q!(W64<i64, i128>, Wrapping);
710impl_q!(V8<u8, u16>, Wrapping);
712impl_q!(V16<u16, u32>, Wrapping);
713impl_q!(V32<u32, u64>, Wrapping);
714impl_q!(V64<u64, u128>, Wrapping);
715
716#[cfg(test)]
719mod test {
720 use super::*;
721
722 #[test]
723 fn simple() {
724 assert_eq!(
725 Q32::<5>::from_int(4) * Q32::<5>::from_int(3),
726 Q32::from_int(3 * 4)
727 );
728 assert_eq!(
729 Q32::<5>::from_int(12) / Q32::<5>::from_int(6),
730 Q32::from_int(2)
731 );
732 assert_eq!(7 * Q32::<4>::new(0x33), 7 * 3 + ((3 * 7) >> 4));
733 }
734
735 #[test]
736 fn display() {
737 assert_eq!(format!("{}", Q32::<9>::new(0x12345)), "145.634765625");
738 assert_eq!(format!("{}", Q32::<9>::from_int(99)), "99");
739 }
740}