1 // -*- C++ -*-
2 /** @file */
3 #pragma once
4 
5 #include <cstdint>
6 #include "arch.hpp"
7 #include <cstdlib>
8 
9 #include <type_traits>
10 #include <iostream>
11 namespace arm_cmsis_dsp {
12 
13 /** \addtogroup FIXED Fixed point datatypes
14  *  \ingroup DSPPP
15  *  @{
16  */
17 
18 /*
19 
20 Normally those kind of definitions are in a compiler file
21 in Core or Core_A.
22 
23 But for MSVC compiler it is a bit special. The goal is very specific
24 to CMSIS-DSP and only to allow the use of this library from other
25 systems like Python or Matlab.
26 
27 MSVC is not going to be used to cross-compile to ARM. So, having a MSVC
28 compiler file in Core or Core_A would not make sense.
29 
30 */
31 #if defined ( _MSC_VER ) || defined(__GNUC_PYTHON__) || defined(__APPLE_CC__)
__CLZ(uint32_t data)32 __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t data)
33 {
34   if (data == 0U) { return 32U; }
35 
36   uint32_t count = 0U;
37   uint32_t mask = 0x80000000U;
38 
39   while ((data & mask) == 0U)
40   {
41     count += 1U;
42     mask = mask >> 1U;
43   }
44   return count;
45 }
46 
__SSAT(int32_t val,uint32_t sat)47 __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
48 {
49   if ((sat >= 1U) && (sat <= 32U))
50   {
51     const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
52     const int32_t min = -1 - max ;
53     if (val > max)
54     {
55       return max;
56     }
57     else if (val < min)
58     {
59       return min;
60     }
61   }
62   return val;
63 }
64 
__USAT(int32_t val,uint32_t sat)65 __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
66 {
67   if (sat <= 31U)
68   {
69     const uint32_t max = ((1U << sat) - 1U);
70     if (val > (int32_t)max)
71     {
72       return max;
73     }
74     else if (val < 0)
75     {
76       return 0U;
77     }
78   }
79   return (uint32_t)val;
80 }
81 #endif
82 
83 #if !defined(ARM_MATH_DSP)
clip_int64_to_q31(int64_t x)84 __STATIC_FORCEINLINE int32_t clip_int64_to_q31(
85   int64_t x)
86   {
87     return ((int32_t) (x >> 32) != ((int32_t) x >> 31)) ?
88       ((0x7FFFFFFF ^ ((int32_t) (x >> 63)))) : (int32_t) x;
89   }
90 
__QADD(int32_t x,int32_t y)91 __STATIC_FORCEINLINE int32_t __QADD(
92   int32_t x,
93   int32_t y)
94   {
95     return ((int32_t)(clip_int64_to_q31((int64_t)x + (int32_t)y)));
96   }
97 
98 
99   /*
100    * @brief C custom defined QSUB
101    */
__QSUB(int32_t x,int32_t y)102   __STATIC_FORCEINLINE int32_t __QSUB(
103   int32_t x,
104   int32_t y)
105   {
106     return ((int32_t)(clip_int64_to_q31((int64_t)x - (int32_t)y)));
107   }
108 
109 
110 #endif
111 
112 /**
113  * @brief  Function to identify the template for fixed number
114  *         representable on 64 bits
115  *
116  * @param M number of mantissa bit (without sign bit)
117  * @param F number of fractional bits
118  * @param S sign or unsigned
119  * @return True if the template must be selected
120  */
test64(const int M,const int F,const int S)121 constexpr bool test64(const int M,const int F,const int S){return((M+F+S)>32 && (M+F+S)<=64);}
122 
123 /**
124  * @brief  Function to identify the template for fixed number
125  *         representable on 32 bits
126  *
127  * @param M number of mantissa bit (without sign bit)
128  * @param F number of fractional bits
129  * @param S sign or unsigned
130  * @return True if the template must be selected
131  */
test32(const int M,const int F,const int S)132 constexpr bool test32(const int M,const int F,const int S){return((M+F+S)>16 && (M+F+S)<=32);}
133 
134 /**
135  * @brief  Function to identify the template for fixed number
136  *         representable on 16 bits
137  *
138  * @param M number of mantissa bit (without sign bit)
139  * @param F number of fractional bits
140  * @param S sign or unsigned
141  * @return True if the template must be selected
142  */
test16(const int M,const int F,const int S)143 constexpr bool test16(const int M,const int F,const int S){return((M+F+S)>8  && (M+F+S)<=16);}
144 
145 /**
146  * @brief  Function to identify the template for fixed number
147  *         representable on 8 bits
148  *
149  * @param M number of mantissa bit (without sign bit)
150  * @param F number of fractional bits
151  * @param S sign or unsigned
152  * @return True if the template must be selected
153  */
test8(const int M,const int F,const int S)154 constexpr bool test8 (const int M,const int F,const int S){return((M+F+S)<=8);}
155 
156 /**
157  * @brief  Storage type for a fixed point number
158  *
159  * @tparam M Number of bits for mantissa (without sign bit)
160  * @tparam F Number of bits for fractional part
161  * @tparam s signed or unsigned
162  *
163  */
164 template<int M,int F,bool s = true,bool = true>
165 struct fixed_storage_type
166 {
167 };
168 
169 
170 /**
171  * @brief  Storage type for a fixed point number representable on int64
172  *
173  * @tparam M Number of bits for mantissa (without sign bit)
174  * @tparam F Number of bits for fractional part
175  *
176  */
177 template<int M,int F>
178 struct fixed_storage_type<M,F,true,test64(M,F,1)>
179 {
180     //! Storage for the fixed point number
181     typedef int64_t value_type;
182     //! Storage for the widening of this fixed point number datatype
183     typedef int64_t wider_type;
184     //! Storage for the narrowing of this fixed point number datatype
185     typedef int32_t narrow_type;
186 };
187 
188 /**
189  * @brief  Storage type for a fixed point number representable on uint64
190  *
191  * @tparam M Number of bits for mantissa (without sign bit)
192  * @tparam F Number of bits for fractional part
193  *
194  */
195 template<int M,int F>
196 struct fixed_storage_type<M,F,false,test64(M,F,0)>
197 {
198     //! Storage for the fixed point number
199     typedef uint64_t value_type;
200     //! Storage for the widening of this fixed point number datatype
201     typedef uint64_t wider_type;
202     //! Storage for the narrowing of this fixed point number datatype
203     typedef uint32_t narrow_type;
204 };
205 
206 
207 /**
208  * @brief  Storage type for a fixed point number representable on int32
209  *
210  * @tparam M Number of bits for mantissa (without sign bit)
211  * @tparam F Number of bits for fractional part
212  *
213  */
214 template<int M,int F>
215 struct fixed_storage_type<M,F,true,test32(M,F,1)>
216 {
217     //! Storage for the fixed point number
218     typedef int32_t value_type;
219     //! Storage for the widening of this fixed point number datatype
220     typedef int64_t wider_type;
221     //! Storage for the narrowing of this fixed point number datatype
222     typedef int16_t narrow_type;
223 };
224 
225 /**
226  * @brief  Storage type for a fixed point number representable on uint32
227  *
228  * @tparam M Number of bits for mantissa (without sign bit)
229  * @tparam F Number of bits for fractional part
230  *
231  */
232 template<int M,int F>
233 struct fixed_storage_type<M,F,false,test32(M,F,0)>
234 {
235     //! Storage for the fixed point number
236     typedef uint32_t value_type;
237     //! Storage for the widening of this fixed point number datatype
238     typedef uint64_t wider_type;
239     //! Storage for the narrowing of this fixed point number datatype
240     typedef uint16_t narrow_type;
241 };
242 
243 
244 /**
245  * @brief  Storage type for a fixed point number representable on int16
246  *
247  * @tparam M Number of bits for mantissa (without sign bit)
248  * @tparam F Number of bits for fractional part
249  *
250  */
251 template<int M,int F>
252 struct fixed_storage_type<M,F, true,test16(M,F,1)>
253 {
254     //! Storage for the fixed point number
255     typedef int16_t value_type;
256     //! Storage for the widening of this fixed point number datatype
257     typedef int32_t wider_type;
258     //! Storage for the narrowing of this fixed point number datatype
259     typedef int8_t narrow_type;
260 };
261 
262 /**
263  * @brief  Storage type for a fixed point number representable on uint16
264  *
265  * @tparam M Number of bits for mantissa (without sign bit)
266  * @tparam F Number of bits for fractional part
267  *
268  */
269 template<int M,int F>
270 struct fixed_storage_type<M,F, false,test16(M,F,0)>
271 {
272     //! Storage for the fixed point number
273     typedef uint16_t value_type;
274     //! Storage for the widening of this fixed point number datatype
275     typedef uint32_t wider_type;
276     //! Storage for the narrowing of this fixed point number datatype
277     typedef uint8_t narrow_type;
278 };
279 
280 /**
281  * @brief  Storage type for a fixed point number representable on int8
282  *
283  * @tparam M Number of bits for mantissa (without sign bit)
284  * @tparam F Number of bits for fractional part
285  *
286  */
287 template<int M,int F>
288 struct fixed_storage_type<M,F,true,test8(M,F,1)>
289 {
290     //! Storage for the fixed point number
291     typedef int8_t value_type;
292     //! Storage for the widening of this fixed point number datatype
293     typedef int16_t wider_type;
294     //! Storage for the narrowing of this fixed point number datatype
295     typedef int8_t narrow_type;
296 };
297 
298 /**
299  * @brief  Storage type for a fixed point number representable on uint8
300  *
301  * @tparam M Number of bits for mantissa (without sign bit)
302  * @tparam F Number of bits for fractional part
303  *
304  */
305 template<int M,int F>
306 struct fixed_storage_type<M,F,false,test8(M,F,0)>
307 {
308     //! Storage for the fixed point number
309     typedef uint8_t value_type;
310     //! Storage for the widening of this fixed point number datatype
311     typedef uint16_t wider_type;
312     //! Storage for the narrowing of this fixed point number datatype
313     typedef uint8_t narrow_type;
314 };
315 
316 
317 /**
318  * @brief  Fixed point template
319  *
320  * @tparam M Number of bits for mantissa (without sign bit)#
321  * @tparam F Number of bits for fractional part
322  * @tparam S Signed or unsigned
323  * @tparam T storage datatype
324  *
325  */
326 template<int M, int F, bool S = true,
327          typename T=typename fixed_storage_type<M,F,S>::value_type>
328 struct Q {};
329 
330 /**
331  * @brief  Signed fixed point datatypes on 64 bits
332  *
333  * @tparam M Number of bits for mantissa (without sign bit)
334  * @tparam F Number of bits for fractional part
335  *
336  */
337 template<int M,int F>
338 struct Q<M,F,true,int64_t> {
339   //! Number of fractional bits
340   constexpr static int fracBits = F;
341   //! Number of mantissa bits (without sign bit)
342   constexpr static int mantissaBits = M;
343   //! Is this number representation signed
344   constexpr static bool isSigned = true;
345   //! Storage type for the value
346   using value_type = typename fixed_storage_type<M,F,true>::value_type;
347   //! Storage type for the widening of the value
348   using wider_type = typename fixed_storage_type<M,F,true>::wider_type;
349 
350   //! Maximum representable positive value
351   constexpr static value_type maxVal = 0x7FFFFFFFFFFFFFFFLL;
352 
353   //! Minimum representable negative value
354   constexpr static value_type minVal = 0x8000000000000000LL;
355 
356   /**
357    * @brief  Convert a float to fixed point
358    *
359    * @param f float value
360    * @return the fixed point value in the storage type
361    *
362    */
convertarm_cmsis_dsp::Q363   constexpr static value_type convert(const float f) {
364     return(f >= 1.0f ? maxVal : (f <= -1.0f ? minVal : value_type(f * (float)((maxVal >> (63 - F)) ))));
365   };
366 
367   //! Storage value
368   value_type v;
369 
370   /**
371    * @brief  Create a new zero fixed point
372    */
Qarm_cmsis_dsp::Q373   constexpr Q():v(0){};
374 
375   /**
376    * @brief  Create a new fixed point from a raw integer
377    * @param x the raw integer
378    */
Qarm_cmsis_dsp::Q379   constexpr explicit Q(const value_type x):v(x){};
380 
381   /**
382    * @brief  Create a new fixed point from a float
383    * @param x the float
384    * @return The fixed point representing the float value with saturation
385    */
farm_cmsis_dsp::Q386   constexpr static Q f(const float x){return Q(convert(x));}
387 
388   /**
389    * @brief  Fixed point number representing 1
390    * @return Fixed point representing 1
391    */
onearm_cmsis_dsp::Q392   constexpr static Q one() {return f(1.0f);};
393 
394   Q(Q&& other)=default;
395   Q(const Q& other)=default;
396   Q& operator=(Q&& other)=default;
397   Q& operator=(const Q& other)=default;
398 
399 
400   /**
401    * @brief  Convert an unsigned fixed point to this fixed point
402    * @param other The unsigned fixed point number
403    *
404    * Some problem may occur since the unsigned may not be representable
405    * with the less bits required for the sign representation.
406    * This convertion is not saturating.
407    */
Qarm_cmsis_dsp::Q408   constexpr explicit Q(const Q<M,F,false>&other)
409     :v{value_type(other.v)} {};
410 
411    /**
412     * @brief  this == b
413     * @param b the other fixed point
414     * @return true if this == b
415     */
operator ==arm_cmsis_dsp::Q416    bool operator==(const Q& b) const
417    {
418      return(v == b.v);
419    }
420 
421    /**
422     * @brief  this != b
423     * @param b the other fixed point
424     * @return true if this != b
425     */
operator !=arm_cmsis_dsp::Q426    bool operator!=(const Q& b) const
427    {
428      return(v != b.v);
429    }
430 
431    /**
432     * @brief  this < b
433     * @param b the other fixed point
434     * @return true if this < b
435     */
operator <arm_cmsis_dsp::Q436    bool operator<(const Q& b) const
437    {
438      return(v < b.v);
439    }
440 
441    /**
442     * @brief  this > b
443     * @param b the other fixed point
444     * @return true if this > b
445     */
operator >arm_cmsis_dsp::Q446    bool operator>(const Q& b) const
447    {
448      return(v > b.v);
449    }
450 
451    /**
452     * @brief  this <= b
453     * @param b the other fixed point
454     * @return true if this <= b
455     */
operator <=arm_cmsis_dsp::Q456    bool operator<=(const Q& b) const
457    {
458      return(v <= b.v);
459    }
460 
461    /**
462     * @brief  this >= b
463     * @param b the other fixed point
464     * @return true if this >= b
465     */
operator >=arm_cmsis_dsp::Q466    bool operator>=(const Q& b) const
467    {
468      return(v >= b.v);
469    }
470 
471 
472    /**
473    * @brief  this += other
474    * @param other the other fixed point
475    * @return true if this += other
476    */
operator +=arm_cmsis_dsp::Q477    Q & operator+=(const Q other)
478    {
479        v += other.v;
480        return(*this);
481    }
482 
483    /**
484    * @brief  this -= other
485    * @param other the other fixed point
486    * @return true if this += other
487    */
operator -=arm_cmsis_dsp::Q488    Q & operator-=(const Q other)
489    {
490        v -= other.v;
491        return(*this);
492    }
493 
494 
495    /**
496     * @brief  Display fixed point number for debug purpose
497     * @param stream Output stream
498     * @param other The fixed point to display
499     * @return the stream
500     *
501     */
operator <<(std::ostream & stream,const Q & other)502    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
503         stream << double(1.0*other.v / (maxVal >> (63 - F))) << "_Q(" << M << "," << F << ")";;
504         return(stream);
505    }
506 
507 };
508 
509 /**
510  * @brief  Unsigned fixed point datatypes on 64 bits
511  *
512  * @tparam M Number of bits for mantissa (without sign bit)
513  * @tparam F Number of bits for fractional part
514  *
515  */
516 template<int M,int F>
517 struct Q<M,F,false,uint64_t> {
518   //! Number of fractional bits
519   constexpr static int fracBits = F;
520   //! Number of mantissa bits (without sign bit)
521   constexpr static int mantissaBits = M;
522   //! Is this number representation signed
523   constexpr static bool isSigned = false;
524   //! Storage type for the value
525   using value_type = typename fixed_storage_type<M,F,false>::value_type;
526   //! Storage type for the widening of the value
527   using wider_type = typename fixed_storage_type<M,F,false>::wider_type;
528   //! Maximum representable positive value
529   constexpr static value_type maxVal = 0xFFFFFFFFFFFFFFFFLL;
530 
531   /**
532    * @brief  Convert a float to fixed point
533    *
534    * @param f float value
535    * @return the fixed point value in the storage type
536    *
537    */
convertarm_cmsis_dsp::Q538   constexpr static value_type convert(const float f) {
539     return(f >= 1.0f ? maxVal : (f <= 0.0f ? 0LL : value_type(f * (float)((maxVal >> (64 - F))))));
540   };
541 
542   //! Storage value
543   value_type v;
544 
545   /**
546    * @brief  Create a new zero fixed point
547    */
Qarm_cmsis_dsp::Q548   constexpr Q():v(0){};
549 
550    /**
551    * @brief  Create a new fixed point from a raw integer
552    * @param x the raw integer
553    */
Qarm_cmsis_dsp::Q554   constexpr explicit Q(const value_type x):v(x){};
555 
556   /**
557    * @brief  Create a new fixed point from a float
558    * @param x the float
559    * @return The fixed point representing the float value with saturation
560    */
farm_cmsis_dsp::Q561   constexpr static Q f(const float x){return Q(convert(x));}
562 
563   /**
564    * @brief  Fixed point number representing 1
565    * @return Fixed point representing 1
566    */
onearm_cmsis_dsp::Q567   constexpr static Q one() {return f(1.0f);};
568 
569   Q(Q&& other)=default;
570   Q(const Q& other)=default;
571   Q& operator=(Q&& other)=default;
572   Q& operator=(const Q& other)=default;
573 
574     /**
575     * @brief  Display fixed point number for debug purpose
576     * @param stream Output stream
577     * @param other The fixed point to display
578     * @return the stream
579     *
580     */
operator <<(std::ostream & stream,const Q & other)581    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
582         stream << double(1.0*other.v / (maxVal >> (64 - F))) << "_UQ(" << M << "," << F << ")";;
583         return(stream);
584    }
585 
586    /**
587     * @brief  this == b
588     * @param b the other fixed point
589     * @return true if this == b
590     */
operator ==arm_cmsis_dsp::Q591    bool operator==(const Q& b) const
592    {
593      return(v == b.v);
594    }
595 
596    /**
597     * @brief  this != b
598     * @param b the other fixed point
599     * @return true if this != b
600     */
operator !=arm_cmsis_dsp::Q601    bool operator!=(const Q& b) const
602    {
603      return(v != b.v);
604    }
605 
606     /**
607     * @brief  this < b
608     * @param b the other fixed point
609     * @return true if this < b
610     */
operator <arm_cmsis_dsp::Q611    bool operator<(const Q& b) const
612    {
613      return(v < b.v);
614    }
615 
616    /**
617     * @brief  this > b
618     * @param b the other fixed point
619     * @return true if this > b
620     */
operator >arm_cmsis_dsp::Q621    bool operator>(const Q& b) const
622    {
623      return(v > b.v);
624    }
625 
626    /**
627     * @brief  this <= b
628     * @param b the other fixed point
629     * @return true if this <= b
630     */
operator <=arm_cmsis_dsp::Q631    bool operator<=(const Q& b) const
632    {
633      return(v <= b.v);
634    }
635 
636    /**
637     * @brief  this >= b
638     * @param b the other fixed point
639     * @return true if this >= b
640     */
operator >=arm_cmsis_dsp::Q641    bool operator>=(const Q& b) const
642    {
643      return(v >= b.v);
644    }
645 
646 };
647 
648 /**
649  * @brief  Signed fixed point datatypes on 32 bits
650  *
651  * @tparam M Number of bits for mantissa (without sign bit)
652  * @tparam F Number of bits for fractional part
653  *
654  */
655 template<int M,int F>
656 struct Q<M,F,true,int32_t> {
657   //! Number of fractional bits
658   constexpr static int fracBits = F;
659 
660   //! Number of mantissa bits (without sign bit)
661   constexpr static int mantissaBits = M;
662 
663   //! Is this number representation signed
664   constexpr static bool isSigned = true;
665 
666   //! Storage type for the value
667   using value_type = typename fixed_storage_type<M,F,true>::value_type;
668 
669   //! Storage type for the widening of the value
670   using wider_type = typename fixed_storage_type<M,F,true>::wider_type;
671 
672   //! Maximum representable positive value
673   constexpr static value_type maxVal = 0x7FFFFFFFL;
674 
675   //! Minimum representable negative value
676   constexpr static value_type minVal = 0x80000000L;
677 
678   /**
679    * @brief  Saturate a wider type to the current type
680    *
681    * @param i the wider integer type
682    * @return the saturated value
683    *
684    */
satarm_cmsis_dsp::Q685   constexpr static value_type sat(const wider_type i) {
686     return (i > (value_type)maxVal ? maxVal : (i<(value_type)minVal ? minVal : i));
687   };
688 
689   /**
690    * @brief  Convert a float to fixed point with saturation
691    *
692    * @param f float value
693    * @return the fixed point value in the storage type
694    *
695    */
convertarm_cmsis_dsp::Q696   constexpr static value_type convert(const float f) {
697     return(f >= 1.0f ? maxVal : (f <= -1.0f ? minVal : value_type(f * (float)((wider_type)1<<F))));
698   };
699 
700   //! Storage value
701   value_type v;
702 
703   /**
704    * @brief  Create a new zero fixed point
705    */
Qarm_cmsis_dsp::Q706   constexpr Q():v(0){};
707 
708   /**
709    * @brief  Create a new fixed point from a raw integer
710    * @param x the raw integer
711    */
Qarm_cmsis_dsp::Q712   constexpr explicit Q(const value_type x):v(x){};
713 
714    /**
715    * @brief  Create a new fixed point from a float
716    * @param x the float
717    * @return The fixed point representing the float value with saturation
718    */
farm_cmsis_dsp::Q719   constexpr static Q f(const float x){return Q(convert(x));}
720 
721   /**
722    * @brief  Fixed point number representing 1
723    * @return Fixed point representing 1
724    */
onearm_cmsis_dsp::Q725   constexpr static Q one() {return f(1.0f);};
726 
727   Q(Q&& other)=default;
728   Q(const Q& other)=default;
729   Q& operator=(Q&& other)=default;
730   Q& operator=(const Q& other)=default;
731 
732   /**
733    * @brief  Convert an unsigned fixed point to this fixed point
734    * @param other The unsigned fixed point number
735    *
736    * Some problem may occur since the unsigned may not be representable
737    * with the less bits required for the sign representation.
738    * This convertion is not saturating.
739    */
Qarm_cmsis_dsp::Q740   constexpr explicit Q(const Q<M,F,false>&other):
741   v{value_type(other.v)} {};
742 
743   /**
744     * @brief  this == b
745     * @param b the other fixed point
746     * @return true if this == b
747     */
operator ==arm_cmsis_dsp::Q748   bool operator==(const Q& b) const
749    {
750      return(v == b.v);
751    }
752 
753    /**
754     * @brief  this != b
755     * @param b the other fixed point
756     * @return true if this != b
757     */
operator !=arm_cmsis_dsp::Q758    bool operator!=(const Q& b) const
759    {
760      return(v != b.v);
761    }
762 
763    /**
764     * @brief  this < b
765     * @param b the other fixed point
766     * @return true if this < b
767     */
operator <arm_cmsis_dsp::Q768    bool operator<(const Q& b) const
769    {
770      return(v < b.v);
771    }
772 
773    /**
774     * @brief  this > b
775     * @param b the other fixed point
776     * @return true if this > b
777     */
operator >arm_cmsis_dsp::Q778    bool operator>(const Q& b) const
779    {
780      return(v > b.v);
781    }
782 
783    /**
784     * @brief  this <= b
785     * @param b the other fixed point
786     * @return true if this <= b
787     */
operator <=arm_cmsis_dsp::Q788    bool operator<=(const Q& b) const
789    {
790      return(v <= b.v);
791    }
792 
793    /**
794     * @brief  this >= b
795     * @param b the other fixed point
796     * @return true if this >= b
797     */
operator >=arm_cmsis_dsp::Q798    bool operator>=(const Q& b) const
799    {
800      return(v >= b.v);
801    }
802 
803    /**
804    * @brief  this += other
805    * @param other the other fixed point
806    * @return true if this += other
807    */
operator +=arm_cmsis_dsp::Q808    Q & operator+=(const Q other)
809    {
810        v = __QADD(v,other.v);
811        return(*this);
812    }
813 
814 
815    /**
816    * @brief  this -= other
817    * @param other the other fixed point
818    * @return true if this += other
819    */
operator -=arm_cmsis_dsp::Q820    Q & operator-=(const Q other)
821    {
822        v = __QSUB(v,other.v);
823        return(*this);
824    }
825 
826     /**
827     * @brief  Display fixed point number for debug purpose
828     * @param stream Output stream
829     * @param other The fixed point to display
830     * @return the stream
831     *
832     */
operator <<(std::ostream & stream,const Q & other)833    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
834         stream << double(1.0*other.v / ((wider_type)1<<F)) << "_Q(" << M << "," << F << ")";;
835         return(stream);
836    }
837 
838 };
839 
840 /**
841  * @brief  Unsigned fixed point datatypes on 32 bits
842  *
843  * @tparam M Number of bits for mantissa (without sign bit)
844  * @tparam F Number of bits for fractional part
845  *
846  */
847 template<int M,int F>
848 struct Q<M,F,false,uint32_t> {
849   //! Number of fractional bits
850   constexpr static int fracBits = F;
851   //! Number of mantissa bits (without sign bit)
852   constexpr static int mantissaBits = M;
853   //! Is this number representation signed
854   constexpr static bool isSigned = false;
855   //! Storage type for the value
856   using value_type = typename fixed_storage_type<M,F,false>::value_type;
857   //! Storage type for the widening of the value
858   using wider_type = typename fixed_storage_type<M,F,false>::wider_type;
859 
860   //! Maximum representable positive value
861   constexpr static value_type maxVal = 0xFFFFFFFFL;
862 
863   /**
864    * @brief  Saturate a wider type to the current type
865    *
866    * @param i the wider integer type
867    * @return the saturated value
868    *
869    */
satarm_cmsis_dsp::Q870   constexpr static value_type sat(const wider_type i) {
871     return (i > (value_type)maxVal ? maxVal : i);
872   };
873 
874   /**
875    * @brief  Convert a float to fixed point with saturation
876    *
877    * @param f float value
878    * @return the fixed point value in the storage type
879    *
880    */
convertarm_cmsis_dsp::Q881   constexpr static value_type convert(const float f) {
882     return(f >= 1.0f ? maxVal : (f <= 0.0f ? 0 : value_type(f * (float)((wider_type)1<<F))));
883   };
884 
885   //! Storage value
886   value_type v;
887 
888    /**
889    * @brief  Create a new zero fixed point
890    */
Qarm_cmsis_dsp::Q891   constexpr Q():v(0){};
892 
893   /**
894    * @brief  Create a new fixed point from a raw integer
895    * @param x the raw integer
896    */
Qarm_cmsis_dsp::Q897   constexpr explicit Q(const value_type x):v(x){};
898 
899   /**
900    * @brief  Create a new fixed point from a float
901    * @param x the float
902    * @return The fixed point representing the float value with saturation
903    */
farm_cmsis_dsp::Q904   constexpr static Q f(const float x){return Q(convert(x));}
905 
906   /**
907    * @brief  Fixed point number representing 1
908    * @return Fixed point representing 1
909    */
onearm_cmsis_dsp::Q910   constexpr static Q one() {return f(1.0f);};
911 
912   Q(Q&& other)=default;
913   Q(const Q& other)=default;
914   Q& operator=(Q&& other)=default;
915   Q& operator=(const Q& other)=default;
916 
917    /**
918     * @brief  Display fixed point number for debug purpose
919     * @param stream Output stream
920     * @param other The fixed point to display
921     * @return the stream
922     *
923     */
operator <<(std::ostream & stream,const Q & other)924    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
925         stream << double(1.0*other.v / ((wider_type)1<<F)) << "_UQ(" << M << "," << F << ")";;
926         return(stream);
927    }
928 
929    /**
930     * @brief  this == b
931     * @param b the other fixed point
932     * @return true if this == b
933     */
operator ==arm_cmsis_dsp::Q934    bool operator==(const Q& b) const
935    {
936      return(v == b.v);
937    }
938 
939    /**
940     * @brief  this != b
941     * @param b the other fixed point
942     * @return true if this != b
943     */
operator !=arm_cmsis_dsp::Q944    bool operator!=(const Q& b) const
945    {
946      return(v != b.v);
947    }
948 
949    /**
950     * @brief  this < b
951     * @param b the other fixed point
952     * @return true if this < b
953     */
operator <arm_cmsis_dsp::Q954    bool operator<(const Q& b) const
955    {
956      return(v < b.v);
957    }
958 
959    /**
960     * @brief  this > b
961     * @param b the other fixed point
962     * @return true if this > b
963     */
operator >arm_cmsis_dsp::Q964    bool operator>(const Q& b) const
965    {
966      return(v > b.v);
967    }
968 
969    /**
970     * @brief  this <= b
971     * @param b the other fixed point
972     * @return true if this <= b
973     */
operator <=arm_cmsis_dsp::Q974    bool operator<=(const Q& b) const
975    {
976      return(v <= b.v);
977    }
978 
979     /**
980     * @brief  this >= b
981     * @param b the other fixed point
982     * @return true if this >= b
983     */
operator >=arm_cmsis_dsp::Q984    bool operator>=(const Q& b) const
985    {
986      return(v >= b.v);
987    }
988 };
989 
990 /**
991  * @brief  Signed fixed point datatypes on 16 bits
992  *
993  * @tparam M Number of bits for mantissa (without sign bit)
994  * @tparam F Number of bits for fractional part
995  *
996  */
997 template<int M,int F>
998 struct Q<M,F,true,int16_t> {
999   //! Number of fractional bits
1000   constexpr static int fracBits = F;
1001 
1002   //! Number of mantissa bits (without sign bit)
1003   constexpr static int mantissaBits = M;
1004 
1005   //! Is this number representation signed
1006   constexpr static bool isSigned = true;
1007 
1008   //! Storage type for the value
1009   using value_type = typename fixed_storage_type<M,F,true>::value_type;
1010 
1011   //! Storage type for the widening of the value
1012   using wider_type = typename fixed_storage_type<M,F,true>::wider_type;
1013 
1014   //! Maximum representable positive value
1015   constexpr static value_type maxVal = 0x7FFF;
1016 
1017   //! Minimum representable negative value
1018   constexpr static value_type minVal = 0x8000;
1019 
1020    /**
1021    * @brief  Saturate a wider type to the current type
1022    *
1023    * @param i the wider integer type
1024    * @return the saturated value
1025    *
1026    */
satarm_cmsis_dsp::Q1027   constexpr static value_type sat(const wider_type i) {
1028     return (i > (value_type)maxVal ? maxVal : (i<(value_type)minVal ? minVal : i));
1029   };
1030 
1031   /**
1032    * @brief  Convert a float to fixed point with saturation
1033    *
1034    * @param f float value
1035    * @return the fixed point value in the storage type
1036    *
1037    */
convertarm_cmsis_dsp::Q1038   constexpr static value_type convert(const float f) {
1039     return(f >= 1.0f ? maxVal : (f <= -1.0f ? minVal : value_type(f * (float)((wider_type)1<<F))));
1040   };
1041 
1042   //! Storage value
1043   value_type v;
1044 
1045   /**
1046    * @brief  Create a new zero fixed point
1047    */
Qarm_cmsis_dsp::Q1048   constexpr Q():v(0){};
1049 
1050   /**
1051    * @brief  Create a new fixed point from a raw integer
1052    * @param x the raw integer
1053    */
Qarm_cmsis_dsp::Q1054   constexpr explicit Q(const value_type x):v(x){};
1055 
1056    /**
1057    * @brief  Create a new fixed point from a float
1058    * @param x the float
1059    * @return The fixed point representing the float value with saturation
1060    */
farm_cmsis_dsp::Q1061   constexpr static Q f(const float x){return Q(convert(x));}
1062 
1063   /**
1064    * @brief  Fixed point number representing 1
1065    * @return Fixed point representing 1
1066    */
onearm_cmsis_dsp::Q1067   constexpr static Q one() {return f(1.0f);};
1068 
1069   Q(Q&& other)=default;
1070   Q(const Q& other)=default;
1071   Q& operator=(Q&& other)=default;
1072   Q& operator=(const Q& other)=default;
1073 
1074   /**
1075    * @brief  Convert an unsigned fixed point to this fixed point
1076    * @param other The unsigned fixed point number
1077    *
1078    * Some problem may occur since the unsigned may not be representable
1079    * with the less bits required for the sign representation.
1080    * This convertion is not saturating.
1081    */
Qarm_cmsis_dsp::Q1082   constexpr explicit Q(const Q<M,F,false>&other):v{value_type(other.v)} {};
1083 
1084    /**
1085     * @brief  this == b
1086     * @param b the other fixed point
1087     * @return true if this == b
1088     */
operator ==arm_cmsis_dsp::Q1089    bool operator==(const Q& b) const
1090    {
1091      return(v == b.v);
1092    }
1093 
1094   /**
1095     * @brief  this != b
1096     * @param b the other fixed point
1097     * @return true if this != b
1098     */
operator !=arm_cmsis_dsp::Q1099    bool operator!=(const Q& b) const
1100    {
1101      return(v != b.v);
1102    }
1103 
1104    /**
1105     * @brief  this < b
1106     * @param b the other fixed point
1107     * @return true if this < b
1108     */
operator <arm_cmsis_dsp::Q1109    bool operator<(const Q& b) const
1110    {
1111      return(v < b.v);
1112    }
1113 
1114     /**
1115     * @brief  this > b
1116     * @param b the other fixed point
1117     * @return true if this > b
1118     */
operator >arm_cmsis_dsp::Q1119    bool operator>(const Q& b) const
1120    {
1121      return(v > b.v);
1122    }
1123 
1124     /**
1125     * @brief  this <= b
1126     * @param b the other fixed point
1127     * @return true if this <= b
1128     */
operator <=arm_cmsis_dsp::Q1129    bool operator<=(const Q& b) const
1130    {
1131      return(v <= b.v);
1132    }
1133 
1134    /**
1135     * @brief  this >= b
1136     * @param b the other fixed point
1137     * @return true if this >= b
1138     */
operator >=arm_cmsis_dsp::Q1139    bool operator>=(const Q& b) const
1140    {
1141      return(v >= b.v);
1142    }
1143 
1144     /**
1145    * @brief  this += other
1146    * @param other the other fixed point
1147    * @return true if this += other
1148    */
operator +=arm_cmsis_dsp::Q1149    Q & operator+=(const Q other)
1150    {
1151     #if !defined(ARM_MATH_DSP)
1152       v = __SSAT((value_type)v + other.v,16);
1153     #else
1154       v = (value_type) __QADD16(v, other.v);
1155     #endif
1156     return(*this);
1157    }
1158 
1159    /**
1160    * @brief  this -= other
1161    * @param other the other fixed point
1162    * @return true if this += other
1163    */
operator -=arm_cmsis_dsp::Q1164    Q & operator-=(const Q other)
1165    {
1166     #if !defined(ARM_MATH_DSP)
1167        v = __SSAT((value_type)v - other.v,16);
1168     #else
1169        v = (value_type) __QSUB16(v, other.v);
1170     #endif
1171     return(*this);
1172    }
1173 
1174    /**
1175     * @brief  Display fixed point number for debug purpose
1176     * @param stream Output stream
1177     * @param other The fixed point to display
1178     * @return the stream
1179     *
1180     */
operator <<(std::ostream & stream,const Q & other)1181    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
1182         stream << double(1.0*other.v / (((wider_type)1)<<F)) << "_Q(" << M << "," << F << ")";;
1183         return(stream);
1184    }
1185 
1186 };
1187 
1188 /**
1189  * @brief  Unsigned fixed point datatypes on 16 bits
1190  *
1191  * @tparam M Number of bits for mantissa (without sign bit)
1192  * @tparam F Number of bits for fractional part
1193  *
1194  */
1195 template<int M,int F>
1196 struct Q<M,F,false,uint16_t> {
1197   //! Number of fractional bits
1198   constexpr static int fracBits = F;
1199   //! Number of mantissa bits (without sign bit)
1200   constexpr static int mantissaBits = M;
1201   //! Is this number representation signed
1202   constexpr static bool isSigned = false;
1203   //! Storage type for the value
1204   using value_type = typename fixed_storage_type<M,F,false>::value_type;
1205   //! Storage type for the widening of the value
1206   using wider_type = typename fixed_storage_type<M,F,false>::wider_type;
1207   //! Maximum representable positive value
1208   constexpr static value_type maxVal = 0xFFFF;
1209 
1210   /**
1211    * @brief  Saturate a wider type to the current type
1212    *
1213    * @param i the wider integer type
1214    * @return the saturated value
1215    *
1216    */
satarm_cmsis_dsp::Q1217   constexpr static value_type sat(const wider_type i) {
1218     return (i > (value_type)maxVal ? maxVal : i);
1219   };
1220 
1221   /**
1222    * @brief  Convert a float to fixed point with saturation
1223    *
1224    * @param f float value
1225    * @return the fixed point value in the storage type
1226    *
1227    */
convertarm_cmsis_dsp::Q1228   constexpr static value_type convert(const float f) {
1229     return(f >= 1.0f ? maxVal : (f <= 0.0f ? 0 : value_type(f * (float)((wider_type)1<<F))));
1230   };
1231 
1232   //! Storage value
1233   value_type v;
1234 
1235   /**
1236    * @brief  Create a new zero fixed point
1237    */
Qarm_cmsis_dsp::Q1238   constexpr Q():v(0){};
1239 
1240   /**
1241    * @brief  Create a new fixed point from a raw integer
1242    * @param x the raw integer
1243    */
Qarm_cmsis_dsp::Q1244   constexpr explicit Q(const value_type x):v(x){};
1245 
1246    /**
1247    * @brief  Create a new fixed point from a float
1248    * @param x the float
1249    * @return The fixed point representing the float value with saturation
1250    */
farm_cmsis_dsp::Q1251   constexpr static Q f(const float x){return Q(convert(x));}
1252 
1253   /**
1254    * @brief  Fixed point number representing 1
1255    * @return Fixed point representing 1
1256    */
onearm_cmsis_dsp::Q1257   constexpr static Q one() {return f(1.0f);};
1258 
1259   Q(Q&& other)=default;
1260   Q(const Q& other)=default;
1261   Q& operator=(Q&& other)=default;
1262   Q& operator=(const Q& other)=default;
1263 
1264   /**
1265     * @brief  this == b
1266     * @param b the other fixed point
1267     * @return true if this == b
1268     */
operator ==arm_cmsis_dsp::Q1269   bool operator==(const Q& b) const
1270    {
1271      return(v == b.v);
1272    }
1273 
1274    /**
1275     * @brief  this != b
1276     * @param b the other fixed point
1277     * @return true if this != b
1278     */
operator !=arm_cmsis_dsp::Q1279    bool operator!=(const Q& b) const
1280    {
1281      return(v != b.v);
1282    }
1283 
1284    /**
1285     * @brief  this < b
1286     * @param b the other fixed point
1287     * @return true if this < b
1288     */
operator <arm_cmsis_dsp::Q1289    bool operator<(const Q& b) const
1290    {
1291      return(v < b.v);
1292    }
1293 
1294     /**
1295     * @brief  this > b
1296     * @param b the other fixed point
1297     * @return true if this > b
1298     */
operator >arm_cmsis_dsp::Q1299    bool operator>(const Q& b) const
1300    {
1301      return(v > b.v);
1302    }
1303 
1304     /**
1305     * @brief  this <= b
1306     * @param b the other fixed point
1307     * @return true if this <= b
1308     */
operator <=arm_cmsis_dsp::Q1309    bool operator<=(const Q& b) const
1310    {
1311      return(v <= b.v);
1312    }
1313 
1314    /**
1315     * @brief  this >= b
1316     * @param b the other fixed point
1317     * @return true if this >= b
1318     */
operator >=arm_cmsis_dsp::Q1319    bool operator>=(const Q& b) const
1320    {
1321      return(v >= b.v);
1322    }
1323 
1324    /**
1325    * @brief  this += other
1326    * @param other the other fixed point
1327    * @return true if this += other
1328    */
operator +=arm_cmsis_dsp::Q1329    Q & operator+=(const Q other)
1330    {
1331     v = __USAT((value_type)v + other.v,16);
1332     return(*this);
1333    }
1334 
1335 
1336    /**
1337     * @brief  Display fixed point number for debug purpose
1338     * @param stream Output stream
1339     * @param other The fixed point to display
1340     * @return the stream
1341     *
1342     */
operator <<(std::ostream & stream,const Q & other)1343    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
1344         stream << double(1.0*other.v / ((wider_type)1<<F)) << "_UQ(" << M << "," << F << ")";;
1345         return(stream);
1346    }
1347 
1348 };
1349 
1350 /**
1351  * @brief  Signed fixed point datatypes on 8 bits
1352  *
1353  * @tparam M Number of bits for mantissa (without sign bit)
1354  * @tparam F Number of bits for fractional part
1355  *
1356  */
1357 template<int M,int F>
1358 struct Q<M,F,true,int8_t> {
1359   //! Number of fractional bits
1360   constexpr static int fracBits = F;
1361   //! Number of mantissa bits (without sign bit)
1362   constexpr static int mantissaBits = M;
1363   //! Is this number representation signed
1364   constexpr static bool isSigned = true;
1365   //! Storage type for the value
1366   using value_type = typename fixed_storage_type<M,F,true>::value_type;
1367   //! Storage type for the widening of the value
1368   using wider_type = typename fixed_storage_type<M,F,true>::wider_type;
1369   //! Maximum representable positive value
1370   constexpr static value_type maxVal = 0x7F;
1371   //! Minimum representable negative value
1372   constexpr static value_type minVal = 0x80;
1373 
1374    /**
1375    * @brief  Saturate a wider type to the current type
1376    *
1377    * @param i the wider integer type
1378    * @return the saturated value
1379    *
1380    */
satarm_cmsis_dsp::Q1381   constexpr static value_type sat(const wider_type i) {
1382     return (i > (value_type)maxVal ? maxVal : (i<(value_type)minVal ? minVal : i));
1383   };
1384 
1385 
1386   /**
1387    * @brief  Convert a float to fixed point with saturation
1388    *
1389    * @param f float value
1390    * @return the fixed point value in the storage type
1391    *
1392    */
convertarm_cmsis_dsp::Q1393   constexpr static value_type convert(const float f) {
1394     return(f >= 1.0f ? maxVal : (f <= -1.0f ? minVal : value_type(f * (float)((wider_type)1<<F))));
1395   };
1396 
1397   //! Storage value
1398   value_type v;
1399 
1400    /**
1401    * @brief  Create a new zero fixed point
1402    */
Qarm_cmsis_dsp::Q1403   constexpr Q():v(0){};
1404 
1405    /**
1406    * @brief  Create a new fixed point from a raw integer
1407    * @param x the raw integer
1408    */
Qarm_cmsis_dsp::Q1409   constexpr explicit Q(const value_type x):v(x){};
1410 
1411    /**
1412    * @brief  Create a new fixed point from a float
1413    * @param x the float
1414    * @return The fixed point representing the float value with saturation
1415    */
farm_cmsis_dsp::Q1416   constexpr static Q f(const float x){return Q(convert(x));}
1417 
1418   /**
1419    * @brief  Fixed point number representing 1
1420    * @return Fixed point representing 1
1421    */
onearm_cmsis_dsp::Q1422   constexpr static Q one() {return f(1.0f);};
1423 
1424   Q(Q&& other)=default;
1425   Q(const Q& other)=default;
1426   Q& operator=(Q&& other)=default;
1427   Q& operator=(const Q& other)=default;
1428 
1429   /**
1430    * @brief  Convert an unsigned fixed point to this fixed point
1431    * @param other The unsigned fixed point number
1432    *
1433    * Some problem may occur since the unsigned may not be representable
1434    * with the less bits required for the sign representation.
1435    * This convertion is not saturating.
1436    */
Qarm_cmsis_dsp::Q1437   constexpr explicit Q(const Q<M,F,false>&other):v{value_type(other.v)} {};
1438 
1439   /**
1440     * @brief  this == b
1441     * @param b the other fixed point
1442     * @return true if this == b
1443     */
operator ==arm_cmsis_dsp::Q1444   bool operator==(const Q& b) const
1445    {
1446      return(v == b.v);
1447    }
1448 
1449    /**
1450     * @brief  this != b
1451     * @param b the other fixed point
1452     * @return true if this != b
1453     */
operator !=arm_cmsis_dsp::Q1454    bool operator!=(const Q& b) const
1455    {
1456      return(v != b.v);
1457    }
1458 
1459    /**
1460     * @brief  this < b
1461     * @param b the other fixed point
1462     * @return true if this < b
1463     */
operator <arm_cmsis_dsp::Q1464    bool operator<(const Q& b) const
1465    {
1466      return(v < b.v);
1467    }
1468 
1469    /**
1470     * @brief  this > b
1471     * @param b the other fixed point
1472     * @return true if this > b
1473     */
operator >arm_cmsis_dsp::Q1474    bool operator>(const Q& b) const
1475    {
1476      return(v > b.v);
1477    }
1478 
1479    /**
1480     * @brief  this <= b
1481     * @param b the other fixed point
1482     * @return true if this <= b
1483     */
operator <=arm_cmsis_dsp::Q1484    bool operator<=(const Q& b) const
1485    {
1486      return(v <= b.v);
1487    }
1488 
1489     /**
1490     * @brief  this >= b
1491     * @param b the other fixed point
1492     * @return true if this >= b
1493     */
operator >=arm_cmsis_dsp::Q1494    bool operator>=(const Q& b) const
1495    {
1496      return(v >= b.v);
1497    }
1498 
1499     /**
1500    * @brief  this += other
1501    * @param other the other fixed point
1502    * @return true if this += other
1503    */
operator +=arm_cmsis_dsp::Q1504    Q & operator+=(const Q other)
1505    {
1506      #if !defined(ARM_MATH_DSP)
1507         v = __SSAT((value_type)v + other.v,8);
1508      #else
1509         v = (value_type) __QADD8(v, other.v);
1510      #endif
1511     return(*this);
1512    }
1513 
1514   /**
1515    * @brief  this -= other
1516    * @param other the other fixed point
1517    * @return true if this += other
1518    */
operator -=arm_cmsis_dsp::Q1519    Q & operator-=(const Q other)
1520    {
1521      #if !defined(ARM_MATH_DSP)
1522          v = __SSAT((value_type)v + other.v,8);
1523      #else
1524          v = (value_type) __QSUB8(v, other.v);
1525      #endif
1526     return(*this);
1527    }
1528 
1529     /**
1530     * @brief  Display fixed point number for debug purpose
1531     * @param stream Output stream
1532     * @param other The fixed point to display
1533     * @return the stream
1534     *
1535     */
operator <<(std::ostream & stream,const Q & other)1536    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
1537         stream << double(1.0*other.v / ((wider_type)1<<F)) << "_Q(" << M << "," << F << ")";
1538         return(stream);
1539    }
1540 
1541 };
1542 
1543 /**
1544  * @brief  Unsigned fixed point datatypes on 8 bits
1545  *
1546  * @tparam M Number of bits for mantissa (without sign bit)
1547  * @tparam F Number of bits for fractional part
1548  *
1549  */
1550 template<int M,int F>
1551 struct Q<M,F,false,uint8_t> {
1552   //! Number of fractional bits
1553   constexpr static int fracBits = F;
1554   //! Number of mantissa bits (without sign bit)
1555   constexpr static int mantissaBits = M;
1556   //! Is this number representation signed
1557   constexpr static bool isSigned = false;
1558   //! Storage type for the value
1559   using value_type = typename fixed_storage_type<M,F,false>::value_type;
1560   //! Storage type for the widening of the value
1561   using wider_type = typename fixed_storage_type<M,F,false>::wider_type;
1562 
1563   //! Maximum representable positive value
1564   constexpr static value_type maxVal = 0xFF;
1565 
1566   /**
1567    * @brief  Saturate a wider type to the current type
1568    *
1569    * @param i the wider integer type
1570    * @return the saturated value
1571    *
1572    */
satarm_cmsis_dsp::Q1573   constexpr static value_type sat(const wider_type i) {
1574     return (i > (value_type)maxVal ? maxVal : i);
1575   };
1576 
1577   /**
1578    * @brief  Convert a float to fixed point with saturation
1579    *
1580    * @param f float value
1581    * @return the fixed point value in the storage type
1582    *
1583    */
convertarm_cmsis_dsp::Q1584   constexpr static value_type convert(const float f) {
1585     return(f >= 1.0f ? maxVal : (f <= 0.0f ? 0 : value_type(f * (float)((wider_type)1<<F))));
1586   };
1587 
1588   //! Storage value
1589   value_type v;
1590 
1591   /**
1592    * @brief  Create a new zero fixed point
1593    */
Qarm_cmsis_dsp::Q1594   constexpr Q():v(0){};
1595 
1596   /**
1597    * @brief  Create a new fixed point from a raw integer
1598    * @param x the raw integer
1599    */
Qarm_cmsis_dsp::Q1600   constexpr explicit Q(const value_type x):v(x){};
1601 
1602    /**
1603    * @brief  Create a new fixed point from a float
1604    * @param x the float
1605    * @return The fixed point representing the float value with saturation
1606    */
farm_cmsis_dsp::Q1607   constexpr static Q f(const float x){return Q(convert(x));}
1608 
1609   /**
1610    * @brief  Fixed point number representing 1
1611    * @return Fixed point representing 1
1612    */
onearm_cmsis_dsp::Q1613   constexpr static Q one() {return f(1.0f);};
1614 
1615   Q(Q&& other)=default;
1616   Q(const Q& other)=default;
1617   Q& operator=(Q&& other)=default;
1618   Q& operator=(const Q& other)=default;
1619 
1620   /**
1621     * @brief  this == b
1622     * @param b the other fixed point
1623     * @return true if this == b
1624     */
operator ==arm_cmsis_dsp::Q1625   bool operator==(const Q& b) const
1626    {
1627      return(v == b.v);
1628    }
1629 
1630    /**
1631     * @brief  this != b
1632     * @param b the other fixed point
1633     * @return true if this != b
1634     */
operator !=arm_cmsis_dsp::Q1635    bool operator!=(const Q& b) const
1636    {
1637      return(v != b.v);
1638    }
1639 
1640    /**
1641     * @brief  this < b
1642     * @param b the other fixed point
1643     * @return true if this < b
1644     */
operator <arm_cmsis_dsp::Q1645    bool operator<(const Q& b) const
1646    {
1647      return(v < b.v);
1648    }
1649 
1650    /**
1651     * @brief  this > b
1652     * @param b the other fixed point
1653     * @return true if this > b
1654     */
operator >arm_cmsis_dsp::Q1655    bool operator>(const Q& b) const
1656    {
1657      return(v > b.v);
1658    }
1659 
1660    /**
1661     * @brief  this <= b
1662     * @param b the other fixed point
1663     * @return true if this <= b
1664     */
operator <=arm_cmsis_dsp::Q1665    bool operator<=(const Q& b) const
1666    {
1667      return(v <= b.v);
1668    }
1669 
1670    /**
1671     * @brief  this >= b
1672     * @param b the other fixed point
1673     * @return true if this >= b
1674     */
operator >=arm_cmsis_dsp::Q1675    bool operator>=(const Q& b) const
1676    {
1677      return(v >= b.v);
1678    }
1679 
1680    /**
1681    * @brief  this += other
1682    * @param other the other fixed point
1683    * @return true if this += other
1684    */
operator +=arm_cmsis_dsp::Q1685    Q & operator+=(const Q other)
1686    {
1687     v = __USAT((value_type)v + other.v,8);
1688     return(*this);
1689    }
1690 
1691     /**
1692     * @brief  Display fixed point number for debug purpose
1693     * @param stream Output stream
1694     * @param other The fixed point to display
1695     * @return the stream
1696     *
1697     */
operator <<(std::ostream & stream,const Q & other)1698    friend std::ostream& operator<< (std::ostream& stream, const Q& other) {
1699         stream << double(1.0*other.v / ((wider_type)1<<F)) << "_UQ(" << M << "," << F << ")";
1700         return(stream);
1701    }
1702 
1703 };
1704 
1705 
1706 //! Q63 datatype
1707 using Q63 = Q<0,63>;
1708 
1709 //! Q31 datatype
1710 using Q31 = Q<0,31>;
1711 
1712 //! Q15 datatype
1713 using Q15 = Q<0,15>;
1714 
1715 //! Q7 datatype
1716 using Q7  = Q<0,7>;
1717 
1718 /**
1719  * @brief q63 literal
1720  * @param x long double value
1721  * @return Q63 value
1722  *
1723  * You can write
1724  * \code{.cpp}
1725  * Q63 b = 0.4_q63;
1726  * \endcode
1727  *
1728  * The float is converted to Q63 at build time.
1729  *
1730  */
operator ""_q63(long double x)1731 constexpr Q63 operator ""_q63(long double x){return Q63(Q63::convert((float)x));}
1732 
1733 /**
1734  * @brief q31 literal
1735  * @param x long double value
1736  * @return Q31 value
1737  *
1738  * You can write
1739  * \code{.cpp}
1740  * Q31 b = 0.4_q31;
1741  * \endcode
1742  *
1743  * The float is converted to Q31 at build time.
1744  *
1745  */
operator ""_q31(long double x)1746 constexpr Q31 operator ""_q31(long double x){return Q31(Q31::convert((float)x));}
1747 
1748 /**
1749  * @brief q15 literal
1750  * @param x long double value
1751  * @return Q15 value
1752  *
1753  * You can write
1754  * \code{.cpp}
1755  * Q15 b = 0.4_q15;
1756  * \endcode
1757  *
1758  * The float is converted to Q15 at build time.
1759  *
1760  */
operator ""_q15(long double x)1761 constexpr Q15 operator ""_q15(long double x){return Q15(Q15::convert((float)x));}
1762 
1763 /**
1764  * @brief q7 literal
1765  * @param x long double value
1766  * @return Q7 value
1767  *
1768  * You can write
1769  * \code{.cpp}
1770  * Q7 b = 0.4_q7;
1771  * \endcode
1772  *
1773  * The float is converted to Q7 at build time.
1774  *
1775  */
operator ""_q7(long double x)1776 constexpr Q7 operator ""_q7(long double x){return Q7(Q7::convert((float)x));}
1777 
1778 
1779 /**
1780  * @brief Multiplication of two fixed point numbers A and B
1781  * @tparam MA Number of mantissa bits for A
1782  * @tparam FA Number of fractional bits for A
1783  * @tparam MB Number of mantissa bits for B
1784  * @tparam FB Number of fractional bits for B
1785  * @tparam SA Is A using a signed representation
1786  * @tparam SB Is B using a signed representation
1787  * @param a First fixed point number
1788  * @param b Second fixed point number
1789  * @return return the product of the two fixed point (and use adapted type)
1790  *
1791  *
1792  */
1793 template<int MA,int FA,int MB,int FB,bool SA,bool SB>
mult(const Q<MA,FA,SA> & a,const Q<MB,FB,SB> & b)1794 inline Q< MA+MB+1 , FA+FB,SA || SB> mult(const Q<MA,FA,SA> &a,
1795                                          const Q<MB,FB,SB> &b)
1796 {
1797     /*
1798 
1799     Why mantissa of result is MA + MB + 1.
1800     If we take as example, Q7 * Q7 and we multiply
1801     0x80 * 0x80 (-128 * -128) we get 0x4000 and if we shift right by 7
1802     we get 0x080 (on 9 bits). If the additional mantissa bit was not
1803     kept, we would get 0x80 (on 8 bits) which would mean a negative
1804     number.
1805 
1806     Saturation of 0x080 (on 9 bits) will give 0x7F whereas
1807     saturation of 0x80 (on 8 bits) would keep 0x80 and thus
1808     the wrong sign.
1809 
1810     By using MA + MB + 1 we ensure that Q7 * Q7 is Q<1,14>
1811     and not Q<0,14>.
1812 
1813     To convert Q<1,14> to Q<0,7> we need a toFract and a saturate.
1814 
1815     */
1816     using ResType = typename Q< MA+MB+1 , FA+FB,SA || SB>::value_type;
1817     ResType res = ((ResType)a.v * (ResType)b.v);
1818     return(Q<MA+MB+1,FA+FB,SA || SB>(res));
1819 }
1820 
1821 
1822 /**
1823  * @brief Add two fixed point numbers with saturation
1824  * @tparam M Number of mantissa bits for the fixed point number
1825  * @tparam F Number of fractional bits for the fixed point number
1826  * @tparam S Is the fixed point number using a signed representation
1827  * @param a First fixed point number
1828  * @param b Second fixed point number
1829  * @return return the sum with saturation (if supported by the datatype)
1830  *
1831  *
1832  */
1833 template<int M,int F,bool S>
operator +(const Q<M,F,S> & a,const Q<M,F,S> & b)1834 inline Q<M,F,S> operator+(const Q<M,F,S> &a,const Q<M,F,S> &b)
1835 {
1836     Q<M,F,S> ret(a);
1837     ret+=b;
1838     return ret;
1839 }
1840 
1841 /**
1842  * @brief Subtract two fixed point numbers with saturation
1843  * @tparam M Number of mantissa bits for the fixed point number
1844  * @tparam F Number of fractional bits for the fixed point number
1845  * @tparam S Is the fixed point number using a signed representation
1846  * @param a First fixed point number
1847  * @param b Second fixed point number
1848  * @return return the subtraction with saturation (if supported by the datatype)
1849  *
1850  *
1851  */
1852 template<int M,int F,bool S>
operator -(const Q<M,F,S> & a,const Q<M,F,S> & b)1853 inline Q<M,F,S> operator-(const Q<M,F,S> &a,const Q<M,F,S> &b)
1854 {
1855     Q<M,F,S> ret(a);
1856     ret-=b;
1857     return ret;
1858 }
1859 
1860 /**
1861  * @brief Negate a fixed point number with saturation
1862  * @tparam M Number of mantissa bits for the fixed point number
1863  * @tparam F Number of fractional bits for the fixed point number
1864  * @tparam S Is the fixed point number using a signed representation
1865  * @param a First fixed point number
1866  * @return return negation with saturation (if supported by the datatype)
1867  *
1868  *
1869  */
1870 template<int M,int F,bool S>
operator -(const Q<M,F,S> & a)1871 inline Q<M,F,S> operator-(const Q<M,F,S> &a)
1872 {
1873     Q<M,F,S> ret;
1874     ret-=a;
1875     return ret;
1876 }
1877 
1878 // Unsaturating add
1879 /**
1880  * @brief Add two fixed point numbers without saturation
1881  * @tparam M Number of mantissa bits for the fixed point number
1882  * @tparam F Number of fractional bits for the fixed point number
1883  * @tparam S Is the fixed point number using a signed representation
1884  * @param a First fixed point number
1885  * @param b Second fixed point number
1886  * @return return the sum without saturation
1887  *
1888  *
1889  */
1890 template<int M,int F,bool S>
add(const Q<M,F,S> & a,const Q<M,F,S> & b)1891 inline Q<M,F,S> add(const Q<M,F,S> &a,const Q<M,F,S> &b)
1892 {
1893     return Q<M,F,S>(a.v + b.v);
1894 }
1895 
1896 // Unsaturating sub
1897 /**
1898  * @brief Subtract two fixed point numbers without saturation
1899  * @tparam M Number of mantissa bits for the fixed point number
1900  * @tparam F Number of fractional bits for the fixed point number
1901  * @tparam S Is the fixed point number using a signed representation
1902  * @param a First fixed point number
1903  * @param b Second fixed point number
1904  * @return return the subtraction  without saturation
1905  *
1906  *
1907  */
1908 template<int M,int F,bool S>
sub(const Q<M,F,S> & a,const Q<M,F,S> & b)1909 inline Q<M,F,S> sub(const Q<M,F,S> &a,const Q<M,F,S> &b)
1910 {
1911     return Q<M,F,S>(a.v - b.v);
1912 }
1913 
1914 
1915 template<int N>
1916 constexpr std::integral_constant<int, N> i_{};
1917 
1918 /**
1919  * @brief Shift right a fixed point number with a shift known at build time
1920  * @tparam M Number of mantissa bits for the fixed point number
1921  * @tparam F Number of fractional bits for the fixed point number
1922  * @tparam S Is the fixed point number using a signed representation
1923  * @param a First fixed point number
1924  * @return return the shifted fixed point number
1925  *
1926  *
1927  */
1928 template<int M,int F, int N,bool S>
operator >>(const Q<M,F,S> & a,std::integral_constant<int,N>)1929 inline Q<M,F,S> operator >>(const Q<M,F,S> &a, std::integral_constant<int, N>) noexcept {
1930     return Q<M,F,S>(a.v >> N);
1931 }
1932 
1933 
1934 /**
1935  * @brief Shift left a fixed point number with a shift known at build time
1936  * @tparam M Number of mantissa bits for the fixed point number
1937  * @tparam F Number of fractional bits for the fixed point number
1938  * @tparam S Is the fixed point number using a signed representation
1939  * @param a First fixed point number
1940  * @return return the shifted fixed point number
1941  *
1942  *
1943  */
1944 template<int M,int F,int N,bool S>
operator <<(const Q<M,F,S> & a,std::integral_constant<int,N>)1945 inline Q< M+N , F,S> operator <<(const Q<M,F,S> &a,  std::integral_constant<int, N>) noexcept {
1946     using ResType = typename Q<M+N,F,S>::value_type;
1947     return Q<M+N,F,S>(ResType(a.v) << N);
1948 }
1949 
1950 
1951 /**
1952  * @brief Saturate a signed fixed point number
1953  * @tparam MD Number of mantissa bits for the destination fixed point number
1954  * @tparam MS Number of mantissa bits for the source fixed point number
1955  * @tparam S Is the fixed point number using a signed representation
1956  * @param src First fixed point number
1957  * @return return the saturated fixed point number
1958  *
1959  * Only applies if the number is signed, the representation requires less
1960  * than 32 bits (since there is no saturating instruction for 64 bits) and
1961  * if destination has less mantissa bits.
1962  *
1963  * If destination has more or equal number of mantissa bits then it does
1964  * not make sense to saturate.
1965  */
1966 template<int MD=0,int MS,int F>
saturate(const Q<MS,F,true> & src,typename std::enable_if<(MD<MS)&& ((MD+F)<31)>::type * =nullptr)1967 inline Q<MD,F,true> saturate(const Q<MS,F,true> &src,
1968                              typename std::enable_if<(MD < MS) && ((MD+F)<31)>::type* = nullptr)
1969 {
1970     return(Q<MD,F,true>(__SSAT(src.v, MD+F+1)));
1971 }
1972 
1973 
1974 /**
1975  * @brief Saturate an unsigned fixed point number
1976  * @tparam MD Number of mantissa bits for the destination fixed point number
1977  * @tparam MS Number of mantissa bits for the source fixed point number
1978  * @tparam S Is the fixed point number using a signed representation
1979  * @param src The fixed point number
1980  * @return return the saturated fixed point number
1981  *
1982  * Only applies if the number is unsigned, the representation requires less
1983  * than 31 bits (since there is no saturating instruction for 64 bits) and
1984  * if destination has less mantissa bits.
1985  *
1986  * If destination has more or equal number of mantissa bits then it does
1987  * not make sense to saturate.
1988  */
1989 template<int MD=0,int MS,int F>
saturate(const Q<MS,F,false> & src,typename std::enable_if<(MD<MS)&& ((MD+F)<31)>::type * =nullptr)1990 inline Q<MD,F,false> saturate(const Q<MS,F,false> &src,typename std::enable_if<(MD < MS) && ((MD+F)<31)>::type* = nullptr)
1991 {
1992     return(Q<MD,F,false>(__USAT(src.v, MD+F+1)));
1993 }
1994 
1995 
1996 template<int M,int FD,int FS,bool S,bool = true>
1997 struct FixedCastShift {};
1998 
1999 /* Positive shift */
2000 
2001 /**
2002  * @brief Changed fractional representation of a fixed point number using a shift
2003  * @tparam M Number of mantissa bits for the fixed point number
2004  * @tparam FD Number of fractional bits for the destination fixed point number
2005  * @tparam FS Number of fractional bits for the source fixed point number
2006  * @tparam S Is the fixed point number using a signed representation
2007  * @param src The fixed point number
2008  * @return return the fixed point number with different fractional part format
2009  *
2010  * Only applies if FD > FS
2011  */
2012 template<int M,int FD,int FS,bool S>
2013 struct FixedCastShift<M,FD,FS,S,(FD>FS)> {
shiftarm_cmsis_dsp::FixedCastShift2014     constexpr static Q<M,FD,S> shift(const Q<M,FS,S> &src)
2015     {
2016         using DstType = typename Q<M,FD,S>::value_type;
2017         return(Q<M,FD,S>(DstType(src.v) << (FD-FS)));
2018     }
2019 };
2020 
2021 /**
2022  * @brief Changed fractional representation of a fixed point number using a shift
2023  * @tparam M Number of mantissa bits for the fixed point number
2024  * @tparam FD Number of fractional bits for the destination fixed point number
2025  * @tparam FS Number of fractional bits for the source fixed point number
2026  * @tparam S Is the fixed point number using a signed representation
2027  * @param src The fixed point number
2028  * @return return the fixed point number with different fractional part format
2029  *
2030  * Only applies if FD < FS
2031  */
2032 template<int M,int FD,int FS,bool S>
2033 struct FixedCastShift<M,FD,FS,S,(FD<FS)> {
shiftarm_cmsis_dsp::FixedCastShift2034     constexpr static Q<M,FD,S> shift(const Q<M,FS,S> &src)
2035     {
2036         using DstType = typename Q<M,FD,S>::value_type;
2037         using SrcType = typename Q<M,FS,S>::value_type;
2038 
2039         return(Q<M,FD,S>(DstType(SrcType(src.v) >> (FS-FD))));
2040     }
2041 };
2042 
2043 /**
2044  * @brief Convert between different fractional part formats
2045  * @tparam M Number of mantissa bits for the fixed point number
2046  * @tparam FD Number of fractional bits for the destination fixed point number
2047  * @tparam FS Number of fractional bits for the source fixed point number
2048  * @tparam S Is the fixed point number using a signed representation
2049  * @param src The fixed point number
2050  * @return return the fixed point number with different fractional part format
2051  *
2052  */
2053 template<int FD,int M,int FS,bool S>
toFrac(const Q<M,FS,S> & src)2054 inline Q<M,FD,S> toFrac(const Q<M,FS,S> &src)
2055 {
2056     return(FixedCastShift<M,FD,FS,S>::shift(src));
2057 }
2058 
2059 
2060 /**
2061  * @brief Accumulation without saturation
2062  * @tparam MD Number of mantissa bits for the destination fixed point number
2063  * @tparam MS Number of mantissa bits for the source fixed point number
2064  * @tparam F Number of fractional bits for fixed point number
2065  * @tparam S Is the fixed point number using a signed representation
2066  *
2067  */
2068 template<int MD,int MS,int F,bool S,bool = true>
2069 struct Accumulate;
2070 
2071 /**
2072  * @brief Accumulation without saturation
2073  * @tparam MD Number of mantissa bits for the destination fixed point number
2074  * @tparam MS Number of mantissa bits for the source fixed point number
2075  * @tparam F Number of fractional bits for fixed point number
2076  * @tparam S Is the fixed point number using a signed representation
2077  *
2078  */
2079 template<int MD,int MS,int F,bool S>
2080 struct Accumulate<MD,MS,F,S,true> {
2081   /**
2082    * @brief      Accumulation without saturation
2083    *
2084    * @param[in]  a     first fixed point number
2085    * @param[in]  b     second fixed point number
2086    *
2087    * @return     The sum of both fixed point number with more
2088    *             matissa bits.
2089    */
accarm_cmsis_dsp::Accumulate2090   static Q<MD,F,S> acc (const Q<MD,F,S> &a,const Q<MS,F,S> &b)
2091   {
2092      using DstType = typename Q<MD,F,S>::value_type;
2093      return(Q<MD,F,S>(DstType(a.v) + DstType(b.v)));
2094   }
2095 };
2096 
2097 /**
2098  * @brief      Accumulate without saturation
2099  *
2100  * @param[in]  a     First fixed point number
2101  * @param[in]  b     Second fixed point number
2102  *
2103  * @tparam     MD    Number of mantissa bits for destination
2104  * @tparam     MS    Number of mantissa bits fro source
2105  * @tparam     F     Number of fractional bits
2106  * @tparam     S     Is the representation signed
2107  *
2108  * @return     Sum of two numbers without saturation and using the
2109  *             destination number of mantissa bits
2110  */
2111 template<int MD,int MS,int F,bool S>
accumulate(const Q<MD,F,S> & a,const Q<MS,F,S> & b)2112 inline Q<MD,F,S> accumulate(const Q<MD,F,S> &a,const Q<MS,F,S> &b)
2113 {
2114    return(Accumulate<MD,MS,F,S,(MD>MS)>::acc(a,b));
2115 }
2116 
2117 
2118 template<int M,int F>
_abs(const Q<M,F,true> a)2119 inline Q<M,F,true> _abs(const Q<M,F,true> a)
2120 {
2121     using DestType = typename Q<M,F,true>::value_type;
2122     return(Q<M,F>(DestType(abs(a.v))));
2123 }
2124 
2125 /**
2126  * @brief      Multiplication operator.
2127  *
2128  * @param[in]  a     First value
2129  * @param[in]  b     Second value
2130  *
2131  * @return     The result of the multiplication with saturation
2132  */
operator *(const Q7 & a,const Q7 & b)2133 inline Q7 operator*(const Q7 &a,const Q7 &b)
2134 {
2135     return(saturate(toFrac<7>(mult(a,b))));
2136 }
2137 
2138 /**
2139  * @brief      Multiplication operator.
2140  *
2141  * @param[in]  a     First value
2142  * @param[in]  b     Second value
2143  *
2144  * @return     The result of the multiplication with saturation
2145  */
operator *(const Q15 & a,const Q15 & b)2146 inline Q15 operator*(const Q15 &a,const Q15 &b)
2147 {
2148     return (saturate(toFrac<15>(mult(a,b))));
2149 }
2150 
2151 /**
2152  * @brief      Multiplication operator.
2153  *
2154  * @param[in]  a     First value
2155  * @param[in]  b     Second value
2156  *
2157  * @return     The result of the multiplication with saturation
2158  */
operator *(const Q31 & a,const Q31 & b)2159 inline Q31 operator*(const Q31 &a,const Q31 &b)
2160 {
2161     return (toFrac<31>(saturate(toFrac<30>(mult(a,b)))));
2162 }
2163 
2164 /**
2165  * @brief      Greater-than comparison operator.
2166  *
2167  * @param[in]  a     First value
2168  * @param[in]  b     Second value
2169  *
2170  * @tparam     M     Number of mantissa bits
2171  * @tparam     F     Number of fractional bits
2172  *
2173  * @return     The result of the greater-than comparison
2174  */
2175 template<int M,int F>
operator >(const Q<M,F> & a,const Q<M,F> & b)2176 inline bool operator>(const Q<M,F> &a,const Q<M,F> &b)
2177 {
2178     return(a.v>b.v);
2179 }
2180 
2181 /**
2182  * @brief      Less-than comparison operator.
2183  *
2184  * @param[in]  a     First value
2185  * @param[in]  b     Second value
2186  *
2187  * @tparam     M     Number of mantissa bits
2188  * @tparam     F     Number of fractional bits
2189  *
2190  * @return     The result of the less-than comparison
2191  */
2192 template<int M,int F>
operator <(const Q<M,F> & a,const Q<M,F> & b)2193 inline bool operator<(const Q<M,F> &a,const Q<M,F> &b)
2194 {
2195     return(a.v<b.v);
2196 }
2197 
2198 /**
2199  * @brief      Greater-than-or-equal comparison operator.
2200  *
2201  * @param[in]  a     First value
2202  * @param[in]  b     Second value
2203  *
2204  * @tparam     M     Number of mantissa bits
2205  * @tparam     F     Number of fractional bits
2206  *
2207  * @return     The result of the greater-than-or-equal comparison
2208  */
2209 template<int M,int F>
operator >=(const Q<M,F> & a,const Q<M,F> & b)2210 inline bool operator>=(const Q<M,F> &a,const Q<M,F> &b)
2211 {
2212     return(a.v>=b.v);
2213 }
2214 
2215 /**
2216  * @brief      Less-than-or-equal comparison operator.
2217  *
2218  * @param[in]  a     First value
2219  * @param[in]  b     Second value
2220  *
2221  * @tparam     M     Number of mantissa bits
2222  * @tparam     F     Number of fractional bits
2223  *
2224  * @return     The result of the less-than-or-equal comparison
2225  */
2226 template<int M,int F>
operator <=(const Q<M,F> & a,const Q<M,F> & b)2227 inline bool operator<=(const Q<M,F> &a,const Q<M,F> &b)
2228 {
2229     return(a.v<=b.v);
2230 }
2231 
2232 /**
2233  * @brief      Equality operator.
2234  *
2235  * @param[in]  a     First value
2236  * @param[in]  b     Second value
2237  *
2238  * @tparam     M     Number of mantissa bits
2239  * @tparam     F     Number of fractional bits
2240  *
2241  * @return     The result of the equality
2242  */
2243 template<int M,int F>
operator ==(const Q<M,F> a,const Q<M,F> b)2244 inline bool operator==(const Q<M,F> a,const Q<M,F> b)
2245 {
2246     return(a.v==b.v);
2247 }
2248 
2249 /**
2250  * @brief      Inequality operator.
2251  *
2252  * @param[in]  a     First value
2253  * @param[in]  b     Second value
2254  *
2255  * @tparam     M     Number of mantissa bits
2256  * @tparam     F     Number of fractional bits
2257  *
2258  * @return     The result of the inequality
2259  */
2260 template<int M,int F>
operator !=(const Q<M,F> a,const Q<M,F> b)2261 inline bool operator!=(const Q<M,F> a,const Q<M,F> b)
2262 {
2263     return(a.v!=b.v);
2264 }
2265 
2266 /**
2267  * @brief      Division operator.
2268  *
2269  * @param[in]  a     First fixed point value
2270  * @param[in]  b     Integer
2271  *
2272  * @tparam     M     Number of mantissa bits
2273  * @tparam     F     Number of fractional bits
2274  * @tparam     S     Is representation signed
2275  *
2276  * @return     The result of the division
2277  */
2278 template<int M,int F,bool S>
operator /(const Q<M,F,S> a,const int32_t b)2279 inline Q<M,F,S> operator/(const Q<M,F,S> a,const int32_t b)
2280 {
2281     return(Q<M,F,S>(a.v / b));
2282 }
2283 
2284 /**
2285  * @brief      No op operator.
2286  *
2287  * @param[in]  a     Fixed point number
2288  *
2289  * @tparam     M     Number of mantissa bits
2290  * @tparam     F     Number of fractional bits
2291  * @tparam     S     Is the representation signed
2292  *
2293  * @return     The result of the addition
2294  */
2295 template<int M,int F, bool S>
operator +(const Q<M,F,S> & a)2296 inline Q<M,F,S> operator+(const Q<M,F,S> &a)
2297 {
2298     return(a);
2299 }
2300 
2301 /*! @} */
2302 
2303 }