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 }