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