FixMath
FixMath.h
Go to the documentation of this file.
1 /*
2  * FixMath.h
3  *
4  * Copyright 2023, Thomas Combriat and the Mozzi team
5  *
6  *
7  * FixMath is licensed under a GNU Lesser General Public Licence
8  *
9  */
10 
11 
104 #ifndef FIXMATH2_H_
105 #define FIXMATH2_H_
106 
107 #if FOR_DOXYGEN_ONLY
108 #define FIXMATH_UNSAFE
109 #endif
110 
111 
112 #include<Arduino.h>
113 #include "IntegerType.h"
114 
115 
116 
117 
121 namespace FixMathPrivate {
122  template<typename T> constexpr T shiftR(T x, int8_t bits) {return (bits > 0 ? (x >> (bits)) : (x << (-bits)));} // shift right with positive values, left with negative
123  constexpr int8_t sBitsToBytes(int8_t N) { return (((N)>>3)+1);} // conversion between Bits and Bytes for signed
124  constexpr int8_t uBitsToBytes(int8_t N) { return (((N-1)>>3)+1);}
125  template<typename T> constexpr T FM_max(T N1, T N2) { return (N1) > (N2) ? (N1) : (N2);}
126  template<typename T> constexpr T FM_min(T N1, T N2) { return (N1) > (N2) ? (N2) : (N1);}
127  constexpr uint64_t sFullRange(int8_t N) { return uint64_t(1)<<N;} // FM_maximum absolute value that can be hold in a signed of size N
128  constexpr uint64_t uFullRange(int8_t N) { return ((uint64_t(1)<<(N-1))-1) + (uint64_t(1)<<(N-1));}
129  constexpr uint64_t rangeAdd(byte NF, byte _NF, uint64_t RANGE, uint64_t _RANGE) { return ((NF > _NF) ? (RANGE + (_RANGE<<(NF-_NF))) : (_RANGE + (RANGE<<(_NF-NF))));} // returns the RANGE following an addition
130  constexpr int8_t neededNIExtra(int8_t NI, int8_t NF, uint64_t RANGE) { return (RANGE > (uFullRange(NI+NF)) ? (NI+1) : (RANGE > (uFullRange(NI+NF-1)) ? (NI) : (NI-1)));} // check if RANGE can be hold in the unsigned type defined by NI and NF
131  constexpr int8_t neededSNIExtra(int8_t NI, int8_t NF, uint64_t RANGE) { return (RANGE > (sFullRange(NI+NF)) ? (NI+1) : (RANGE > (sFullRange(NI+NF-1)) ? (NI) : (NI-1)));} // same for signed
132  constexpr uint64_t rangeShift(int8_t N, int8_t SH, uint64_t RANGE) { return ((SH < N) ? (RANGE) : (shiftR(RANGE,(N-SH))));} // make sure that NI or NF does not turn negative when safe shifts are used.
133 }
134 
135 // Forward declaration
136 template<int8_t NI, int8_t NF, uint64_t RANGE=FixMathPrivate::sFullRange(NI+NF)>
137 class SFix;
138 
139 
140 
146 template<int8_t NI, int8_t NF, uint64_t RANGE=FixMathPrivate::uFullRange(NI+NF)> // NI and NF being the number of bits for the integral and the fractionnal parts respectively.
147 class UFix
148 {
149  static_assert(NI+NF<=64, "The total width of a UFix cannot exceed 64bits");
150  typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF)>::unsigned_type internal_type ; // smallest size that fits our internal integer
151  typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF+1)>::unsigned_type next_greater_type ; // smallest size that fits 1<<NF for sure (NI could be equal to 0). It can be the same than internal_type in some cases.
152 
153 public:
156  UFix() {;}
157 
162  UFix(float fl) {internal_value = /*static_cast<internal_type>*/(fl * (next_greater_type(1) << NF));}
163 
168  UFix(double fl) {internal_value = static_cast<internal_type> (fl * (next_greater_type(1) << NF)); }
169 
170  /* Constructor from integer type (as_frac = false) or from fractionnal value (as_frac=true) can be used to emulate the behavior of for instance Q8n0_to_Q8n8 */
171 
178  template<typename T>
179  UFix(T value,bool as_raw=false) {
180 
181  if (as_raw) internal_value = value;
182  else internal_value = (internal_type(value) << NF);
183  }
184 
185 
190  template<typename T>
191  static UFix<NI,NF> fromRaw(T raw){return UFix<NI,NF>(raw,true);}
192 
193 
194 
195 
196 
201  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
203  internal_value = FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::uBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::unsigned_type) uf.asRaw(),(_NF-NF));
204  }
205 
206 
207 
212  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
214  internal_value = FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::uBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::unsigned_type) uf.asRaw(),(_NF-NF));
215  }
216 
217 
219 
224  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
225  UFix<FixMathPrivate::neededNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const UFix<_NI,_NF,_RANGE>& op) const
226  {
227  constexpr uint64_t new_RANGE = FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE);
228  constexpr int8_t new_NI = FixMathPrivate::neededNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),new_RANGE);
229  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
230  typedef typename IntegerType<FixMathPrivate::uBitsToBytes(new_NI+new_NF)>::unsigned_type return_type;
231  UFix<new_NI,new_NF> left(*this);
232  UFix<new_NI,new_NF> right(op);
233 
234  return_type tt = return_type(left.asRaw()) + right.asRaw();
235  return UFix<new_NI,new_NF,new_RANGE>(tt,true);
236  }
237 
242  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
243  SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const SFix<_NI,_NF,_RANGE>& op) const
244  {
245  constexpr uint64_t new_RANGE = FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE);
246  constexpr int8_t new_NI = FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),new_RANGE);
247  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
248  typedef typename IntegerType<FixMathPrivate::uBitsToBytes(new_NI+new_NF)>::signed_type return_type;
249  SFix<new_NI,new_NF> left(*this);
250  SFix<new_NI,new_NF> right(op);
251 
252  return_type tt = return_type(left.asRaw()) + right.asRaw();
253  return SFix<new_NI,new_NF,new_RANGE>(tt,true);
254  }
255 
256 #ifdef FIXMATH_UNSAFE
262  template<typename T>
263  UFix<NI,NF> operator+ (const T op) const
264  {
265  return UFix<NI,NF>(internal_value+((internal_type)op<<NF),true);
266  }
267 #endif
268 
270 
275  template<int8_t _NI, int8_t _NF, uint64_t _RANGE> // We do not have the +1 after FixMathPrivate::FM_max(NI, _NI) because the substraction between two UFix should fit in the biggest of the two.
276  SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF), FixMathPrivate::FM_max(FixMathPrivate::shiftR(RANGE,FixMathPrivate::FM_max(NF,_NF)-NF), FixMathPrivate::shiftR(_RANGE,FixMathPrivate::FM_max(NF,_NF)-_NF))> operator- (const UFix<_NI,_NF, _RANGE>& op) const
277  {
278  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
279  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
280  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(new_NI+new_NF)>::signed_type return_type;
281  SFix<new_NI,new_NF> left(*this);
282  SFix<new_NI,new_NF> right(op);
283 
284  return_type tt = return_type(left.asRaw()) - right.asRaw();
285  return SFix<new_NI,new_NF,FixMathPrivate::FM_max(FixMathPrivate::shiftR(RANGE,FixMathPrivate::FM_max(NF,_NF)-NF), FixMathPrivate::shiftR(_RANGE,FixMathPrivate::FM_max(NF,_NF)-_NF))>(tt,true);
286  }
287 
288  #ifdef FIXMATH_UNSAFE
294  template<typename T>
295  UFix<NI,NF> operator- (const T op) const
296  {
297  return UFix<NI,NF>(internal_value-((internal_type)op<<NF),true);
298  }
299 #endif
300 
305  {
306  return SFix<NI,NF,RANGE>( -(typename IntegerType<FixMathPrivate::sBitsToBytes(NI+NF)>::signed_type)(internal_value),true);
307  }
308 
310 
315  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
316  UFix<FixMathPrivate::neededNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE),NF+_NF, RANGE*_RANGE> operator* (const UFix<_NI,_NF,_RANGE>& op) const
317  {
318  constexpr int8_t NEW_NI = FixMathPrivate::neededNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE);
319  typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NEW_NI+NF+_NF)>::unsigned_type return_type ;
320  return_type tt = return_type(internal_value)*op.asRaw();
321  return UFix<NEW_NI,(NF+_NF),RANGE*_RANGE>(tt,true);
322  }
323 
328  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
329  SFix<FixMathPrivate::neededSNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE),NF+_NF, RANGE*_RANGE> operator* (const SFix<_NI,_NF,_RANGE>& op) const
330  {
331  constexpr int8_t NEW_NI = FixMathPrivate::neededSNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE);
332  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NEW_NI+NF+_NF)>::signed_type return_type ;
333  return_type tt = return_type(internal_value)*op.asRaw();
334  return SFix<NEW_NI,(NF+_NF),RANGE*_RANGE>(tt,true);
335  }
336 
337  #ifdef FIXMATH_UNSAFE
343  template<typename T>
344  UFix<NI,NF> operator* (const T op) const
345  {
346  return UFix<NI,NF>(internal_value*op,true);
347  }
348 #endif
349 
351 
359  {
360  static_assert(NI+NF<=63, "The fast inverse cannot be computed for when NI+NF>63. Reduce the number of bits.");
361  return UFix<NF,NI>((onesbitmask()/internal_value),true);
362  }
363 
364 
369  template<int8_t _NF>
370  UFix<NF,_NF> inv() const
371  {
372  return UFix<_NF,NF>(internal_value,true).invFast();
373  }
374 
375 
376 
382  UFix<NF,FixMathPrivate::FM_min(NI*2+NF,63-NF)> invAccurate() const // The FixMathPrivate::FM_min is just to remove compiler error when a big FixMath is instanciated but no accurate inverse is actually computed (this would be catch by the static_assert)
383  {
384  static_assert(2*NI+2*NF<=63, "The accurate inverse cannot be computed for when 2*NI+2*NF>63. Reduce the number of bits.");
385  return inv<NI*2+NF>();
386  }
387 
388 
389 
390 
391 
392 
394 
400  UFix<NI,NF> operator>> (const int8_t op) const
401  {
402  return UFix<NI,NF>(internal_value>>op,true);
403  }
404 
405 
406  #ifdef FIXMATH_UNSAFE
413  UFix<NI,NF> operator<< (const int8_t op) const
414  {
415  return UFix<NI,NF>(internal_value<<op,true);
416  }
417 #endif
418 
423  template<int8_t op>
424  UFix<FixMathPrivate::FM_max(NI-op,0),NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR()
425  {
426  return UFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
427  }
428 
433  template<int8_t op>
434  UFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL()
435  {
436  return UFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
437  }
438 
439 
441  /** Comparison with another UFix.
442  @param op A UFix
443  @return true if this is bigger than op, false otherwise
444  */
445  template<int8_t _NI, int8_t _NF>
446  bool operator> (const UFix<_NI,_NF>& op) const
447  {
448  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
449  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
450  UFix<new_NI,new_NF> left(*this);
451  UFix<new_NI,new_NF> right(op);
452  return left.asRaw()>right.asRaw();
453  }
454 
459  template<int8_t _NI, int8_t _NF>
460  bool operator< (const UFix<_NI,_NF>& op) const
461  {
462  return op > *this;
463  }
464 
465 
470  template<int8_t _NI, int8_t _NF>
471  bool operator== (const UFix<_NI,_NF>& op) const
472  {
473  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
474  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
475  UFix<new_NI,new_NF> left(*this);
476  UFix<new_NI,new_NF> right(op);
477  return left.asRaw()==right.asRaw();
478  }
479 
484  template<int8_t _NI, int8_t _NF>
485  bool operator!= (const UFix<_NI,_NF>& op) const
486  {
487  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
488  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
489  UFix<new_NI,new_NF> left(*this);
490  UFix<new_NI,new_NF> right(op);
491  return left.asRaw()!=right.asRaw();
492  }
493 
497  SFix<NI,NF,RANGE> asSFix() const
498  {
499  return SFix<NI,NF,RANGE>(internal_value,true);
500  }
501 
505  float asFloat() const { return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
506 
510  internal_type asRaw() const { return internal_value; }
511 
515  int8_t getNI() const {return NI;}
516 
520  int8_t getNF() const {return NF;}
521 
522 private:
523  internal_type internal_value;
524  static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
525 };
526 
527 
528 #ifdef FIXMATH_UNSAFE
529 // Multiplication
530 template <int8_t NI, int8_t NF>
531 inline UFix<NI, NF> operator*(uint8_t op, const UFix<NI, NF>& uf) {return uf*op;}
532 
533 template <int8_t NI, int8_t NF>
534 inline UFix<NI, NF> operator*(uint16_t op, const UFix<NI, NF>& uf) {return uf*op;}
535 
536 template <int8_t NI, int8_t NF>
537 inline UFix<NI, NF> operator*(uint32_t op, const UFix<NI, NF>& uf) {return uf*op;}
538 
539 template <int8_t NI, int8_t NF>
540 inline UFix<NI, NF> operator*(uint64_t op, const UFix<NI, NF>& uf) {return uf*op;}
541 
542 template <int8_t NI, int8_t NF>
543 inline UFix<NI, NF> operator*(int8_t op, const UFix<NI, NF>& uf) {return uf*op;}
544 
545 template <int8_t NI, int8_t NF>
546 inline UFix<NI, NF> operator*(int16_t op, const UFix<NI, NF>& uf) {return uf*op;}
547 
548 template <int8_t NI, int8_t NF>
549 inline UFix<NI, NF> operator*(int32_t op, const UFix<NI, NF>& uf) {return uf*op;}
550 
551 template <int8_t NI, int8_t NF>
552 inline UFix<NI, NF> operator*(int64_t op, const UFix<NI, NF>& uf) {return uf*op;}
553 
554 template <int8_t NI, int8_t NF>
555 inline UFix<NI, NF> operator*(float op, const UFix<NI, NF>& uf) {return uf*op;}
556 
557 template <int8_t NI, int8_t NF>
558 inline UFix<NI, NF> operator*(double op, const UFix<NI, NF>& uf) {return uf*op;}
559 
560 // Addition
561 template <int8_t NI, int8_t NF>
562 inline UFix<NI, NF> operator+(uint8_t op, const UFix<NI, NF>& uf) {return uf+op;}
563 
564 template <int8_t NI, int8_t NF>
565 inline UFix<NI, NF> operator+(uint16_t op, const UFix<NI, NF>& uf) {return uf+op;}
566 
567 template <int8_t NI, int8_t NF>
568 inline UFix<NI, NF> operator+(uint32_t op, const UFix<NI, NF>& uf) {return uf+op;}
569 
570 template <int8_t NI, int8_t NF>
571 inline UFix<NI, NF> operator+(uint64_t op, const UFix<NI, NF>& uf) {return uf+op;}
572 
573 template <int8_t NI, int8_t NF>
574 inline UFix<NI, NF> operator+(int8_t op, const UFix<NI, NF>& uf) {return uf+op;}
575 
576 template <int8_t NI, int8_t NF>
577 inline UFix<NI, NF> operator+(int16_t op, const UFix<NI, NF>& uf) {return uf+op;}
578 
579 template <int8_t NI, int8_t NF>
580 inline UFix<NI, NF> operator+(int32_t op, const UFix<NI, NF>& uf) {return uf+op;}
581 
582 template <int8_t NI, int8_t NF>
583 inline UFix<NI, NF> operator+(int64_t op, const UFix<NI, NF>& uf) {return uf+op;}
584 
585 template <int8_t NI, int8_t NF>
586 inline UFix<NI, NF> operator+(float op, const UFix<NI, NF>& uf) {return uf+op;}
587 
588 template <int8_t NI, int8_t NF>
589 inline UFix<NI, NF> operator+(double op, const UFix<NI, NF>& uf) {return uf+op;}
590 
591 // Substraction
592 template <int8_t NI, int8_t NF>
593 inline SFix<NI, NF> operator-(uint8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
594 
595 template <int8_t NI, int8_t NF>
596 inline SFix<NI, NF> operator-(uint16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
597 
598 template <int8_t NI, int8_t NF>
599 inline SFix<NI, NF> operator-(uint32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
600 
601 template <int8_t NI, int8_t NF>
602 inline SFix<NI, NF> operator-(uint64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
603 
604 template <int8_t NI, int8_t NF>
605 inline SFix<NI, NF> operator-(int8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
606 
607 template <int8_t NI, int8_t NF>
608 inline SFix<NI, NF> operator-(int16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
609 
610 template <int8_t NI, int8_t NF>
611 inline SFix<NI, NF> operator-(int32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
612 
613 template <int8_t NI, int8_t NF>
614 inline SFix<NI, NF> operator-(int64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
615 
616 template <int8_t NI, int8_t NF>
617 inline SFix<NI, NF> operator-(float op, const UFix<NI, NF>& uf) {return -uf+op;}
618 
619 template <int8_t NI, int8_t NF>
620 inline SFix<NI, NF> operator-(double op, const UFix<NI, NF>& uf) {return -uf+op;}
621 #endif
623 
624 
636 template<typename T>
637 inline UFix<0, sizeof(T)*8> toUFraction(T val) {
638  return UFix<0, sizeof(T)*8>::fromRaw(val);
639 }
640 
651 template<typename T>
652 inline UFix<sizeof(T)*8,0> toUInt(T val) {
653  return UFix<sizeof(T)*8,0>::fromRaw(val);
654 }
655 
656 
657 
664 template<int8_t NI, int8_t NF, uint64_t RANGE> // NI and NF being the number of bits for the integral and the fractionnal parts respectively.
665 class SFix
666 {
667  static_assert(NI+NF<64, "The total width of a SFix cannot exceed 63bits");
668  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NI+NF)>::signed_type internal_type ; // smallest size that fits our internal integer
669  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NI+NF+1)>::signed_type next_greater_type ; // smallest size that fits 1<<NF for sure (NI could be equal to 0). It can be the same than internal_type in some cases.
670 
671 public:
674  SFix() {;}
675 
680  SFix(float fl) {internal_value = /*static_cast<internal_type>*/(fl * (next_greater_type(1) << NF));}
681 
686  SFix(double fl) {internal_value = static_cast<internal_type> (fl * (next_greater_type(1) << NF)); }
687 
688 
695  template<typename T>
696  SFix(T value,bool as_raw=false)
697  {
698  if (as_raw) internal_value = value;
699  else internal_value = (internal_type(value) << NF);
700  }
701 
706  template<typename T>
707  static SFix<NI,NF> fromRaw(T raw){return SFix<NI,NF>(raw,true);}
708 
709 
714  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
715  SFix(const SFix<_NI,_NF, _RANGE>& uf) {
716  internal_value = FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::sBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::signed_type) uf.asRaw(),(_NF-NF));
717 
718  }
719 
724  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
725  SFix(const UFix<_NI,_NF, _RANGE>& uf) {
726  internal_value = FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::uBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::unsigned_type) uf.asRaw(),(_NF-NF));
727  }
728 
730 
735  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
736  SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const SFix<_NI,_NF,_RANGE>& op) const
737  {
738  constexpr uint64_t new_RANGE = FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE);
739  constexpr int8_t new_NI = FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),new_RANGE);
740  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
741  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(new_NI+new_NF)>::signed_type return_type;
742  SFix<new_NI,new_NF> left(*this);
743  SFix<new_NI,new_NF> right(op);
744 
745  return_type tt = return_type(left.asRaw()) + right.asRaw();
746  return SFix<new_NI, new_NF, new_RANGE>(tt,true);
747  }
748 
749 #ifdef FIXMATH_UNSAFE
755  template<typename T>
756  SFix<NI,NF> operator+ (const T op) const
757  {
758  return SFix<NI,NF>(internal_value+(op<<NF),true);
759  }
760 #endif
761 
763 
768  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
769  SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator- (const SFix<_NI,_NF, _RANGE>& op) const
770  {
771  constexpr uint64_t new_RANGE = FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE);
772  constexpr int8_t new_NI = FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),new_RANGE);
773  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
774  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(new_NI+new_NF)>::signed_type return_type;
775  SFix<new_NI,new_NF> left(*this);
776  SFix<new_NI,new_NF> right(op);
777  return_type tt = return_type(left.asRaw()) - return_type(right.asRaw());
778  return SFix<new_NI, new_NF, new_RANGE>(tt,true);
779  }
780 
785  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
786  SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator- (const UFix<_NI,_NF, _RANGE>& op) const
787  {
788  constexpr uint64_t new_RANGE = FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE);
789  constexpr int8_t new_NI = FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),new_RANGE);
790  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
791  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(new_NI+new_NF)>::signed_type return_type;
792  SFix<new_NI,new_NF> left(*this);
793  SFix<new_NI,new_NF> right(op);
794  return_type tt = return_type(left.asRaw()) - return_type(right.asRaw());
795  return SFix<new_NI, new_NF, new_RANGE>(tt,true);
796  }
797 
798  #ifdef FIXMATH_UNSAFE
804  template<typename T>
805  SFix<NI,NF> operator- (const T op) const
806  {
807  return SFix<NI,NF>(internal_value-(op<<NF),true);
808  }
809 #endif
810 
814  SFix<NI,NF,RANGE> operator-() const
815  {
816  return SFix<NI,NF,RANGE>(-internal_value,true);
817  }
818 
820 
825  template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
826  SFix<FixMathPrivate::neededSNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE),NF+_NF, RANGE*_RANGE> operator* (const SFix<_NI,_NF,_RANGE>& op) const
827  {
828  constexpr int8_t NEW_NI = FixMathPrivate::neededSNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE);
829  typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NI+_NI+NF+_NF)>::signed_type return_type ;
830  return_type tt = return_type(internal_value)*op.asRaw();
831  return SFix<NI+_NI,NF+_NF>(tt,true);
832  }
833 
834  #ifdef FIXMATH_UNSAFE
840  template<typename T>
841  SFix<NI,NF> operator* (const T op) const
842  {
843  return SFix<NI,NF>(internal_value*op,true);
844  }
845 #endif
846 
847 
849 
857  SFix<NF,NI> invFast() const
858  {
859  static_assert(NI+NF<=62, "The fast inverse cannot be computed for when NI+NF>63. Reduce the number of bits.");
860  return SFix<NF,NI>((onesbitmask()/internal_value),true);
861  }
862 
867  template<int8_t _NF>
868  SFix<NF,_NF> inv() const
869  {
870  return SFix<_NF,NF>(internal_value,true).invFast();
871  }
872 
878  SFix<NF,FixMathPrivate::FM_min(NI*2+NF,62-NF)> invAccurate() const
879  {
880  return inv<NI*2+NF>();
881  }
882 
883 
885 
891  SFix<NI,NF> operator>> (const int8_t op) const
892  {
893  return SFix<NI,NF>(internal_value>>op,true);
894  }
895 
896  #ifdef FIXMATH_UNSAFE
903  SFix<NI,NF> operator<< (const int8_t op) const
904  {
905  return SFix<NI,NF>(internal_value<<op,true);
906  }
907  #endif
908 
913  template<int8_t op>
914  SFix<FixMathPrivate::FM_max(NI-op,0), NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR()
915  {
916  return SFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
917  }
918 
923 template<int8_t op>
924  SFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL()
925  {
926  return SFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
927  }
928 
929 
931 
936  template<int8_t _NI, int8_t _NF>
937  bool operator> (const SFix<_NI,_NF>& op) const
938  {
939  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
940  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
941  SFix<new_NI,new_NF> left(*this);
942  SFix<new_NI,new_NF> right(op);
943  return left.asRaw()>right.asRaw();
944  }
945 
950  template<int8_t _NI, int8_t _NF>
951  bool operator< (const SFix<_NI,_NF>& op) const
952  {
953  return op > *this;
954  }
955 
956 
961  template<int8_t _NI, int8_t _NF>
962  bool operator== (const SFix<_NI,_NF>& op) const
963  {
964  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
965  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
966  SFix<new_NI,new_NF> left(*this);
967  SFix<new_NI,new_NF> right(op);
968  return left.asRaw()==right.asRaw();
969  }
970 
975  template<int8_t _NI, int8_t _NF>
976  bool operator!= (const SFix<_NI,_NF>& op) const
977  {
978  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
979  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
980  SFix<new_NI,new_NF> left(*this);
981  SFix<new_NI,new_NF> right(op);
982  return left.asRaw()!=right.asRaw();
983  }
984 
985 
989  UFix<NI,NF,RANGE> asUFix() const
990  {
991  return UFix<NI,NF,RANGE>(internal_value,true);
992  }
993 
994 
998  float asFloat() const {return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
999 
1003  internal_type asRaw() const {return internal_value; }
1004 
1008  int8_t getNI() const {return NI;}
1009 
1013  int8_t getNF() const {return NF;}
1014 
1015 
1016 private:
1017  internal_type internal_value;
1018  static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
1019 };
1020 
1021 
1022 #ifdef FIXMATH_UNSAFE
1024 
1025 // Multiplication
1026 template <int8_t NI, int8_t NF>
1027 inline SFix<NI, NF> operator*(uint8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1028 
1029 template <int8_t NI, int8_t NF>
1030 inline SFix<NI, NF> operator*(uint16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1031 
1032 template <int8_t NI, int8_t NF>
1033 inline SFix<NI, NF> operator*(uint32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1034 
1035 template <int8_t NI, int8_t NF>
1036 inline SFix<NI, NF> operator*(uint64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1037 
1038 template <int8_t NI, int8_t NF>
1039 inline SFix<NI, NF> operator*(int8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1040 
1041 template <int8_t NI, int8_t NF>
1042 inline SFix<NI, NF> operator*(int16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1043 
1044 template <int8_t NI, int8_t NF>
1045 inline SFix<NI, NF> operator*(int32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1046 
1047 template <int8_t NI, int8_t NF>
1048 inline SFix<NI, NF> operator*(int64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1049 
1050 template <int8_t NI, int8_t NF>
1051 inline SFix<NI, NF> operator*(float op, const SFix<NI, NF>& uf) {return uf*op;}
1052 
1053 template <int8_t NI, int8_t NF>
1054 inline SFix<NI, NF> operator*(double op, const SFix<NI, NF>& uf) {return uf*op;}
1055 
1056 // Addition
1057 template <int8_t NI, int8_t NF>
1058 inline SFix<NI, NF> operator+(uint8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1059 
1060 template <int8_t NI, int8_t NF>
1061 inline SFix<NI, NF> operator+(uint16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1062 
1063 template <int8_t NI, int8_t NF>
1064 inline SFix<NI, NF> operator+(uint32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1065 
1066 template <int8_t NI, int8_t NF>
1067 inline SFix<NI, NF> operator+(uint64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1068 
1069 template <int8_t NI, int8_t NF>
1070 inline SFix<NI, NF> operator+(int8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1071 
1072 template <int8_t NI, int8_t NF>
1073 inline SFix<NI, NF> operator+(int16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1074 
1075 template <int8_t NI, int8_t NF>
1076 inline SFix<NI, NF> operator+(int32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1077 
1078 template <int8_t NI, int8_t NF>
1079 inline SFix<NI, NF> operator+(int64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1080 
1081 template <int8_t NI, int8_t NF>
1082 inline SFix<NI, NF> operator+(float op, const SFix<NI, NF>& uf) {return uf+op;}
1083 
1084 template <int8_t NI, int8_t NF>
1085 inline SFix<NI, NF> operator+(double op, const SFix<NI, NF>& uf) {return uf+op;}
1086 
1087 // Substraction
1088 template <int8_t NI, int8_t NF>
1089 inline SFix<NI, NF> operator-(uint8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1090 
1091 template <int8_t NI, int8_t NF>
1092 inline SFix<NI, NF> operator-(uint16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1093 
1094 template <int8_t NI, int8_t NF>
1095 inline SFix<NI, NF> operator-(uint32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1096 
1097 template <int8_t NI, int8_t NF>
1098 inline SFix<NI, NF> operator-(uint64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1099 
1100 template <int8_t NI, int8_t NF>
1101 inline SFix<NI, NF> operator-(int8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1102 
1103 template <int8_t NI, int8_t NF>
1104 inline SFix<NI, NF> operator-(int16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1105 
1106 template <int8_t NI, int8_t NF>
1107 inline SFix<NI, NF> operator-(int32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1108 
1109 template <int8_t NI, int8_t NF>
1110 inline SFix<NI, NF> operator-(int64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1111 
1112 template <int8_t NI, int8_t NF>
1113 inline SFix<NI, NF> operator-(float op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1114 
1115 template <int8_t NI, int8_t NF>
1116 inline SFix<NI, NF> operator-(double op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1117 
1118 #endif
1119 
1120 
1121 
1122 
1123 
1124 
1130 template<int8_t NI, int8_t NF, uint64_t RANGE, int8_t _NI, int8_t _NF, uint64_t _RANGE>
1131 inline SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const SFix<NI,NF,RANGE>& op1, const UFix<_NI,_NF,_RANGE>& op2 )
1132 {
1133  return op2+op1;
1134  }
1135 
1136 
1142 template<int8_t NI, int8_t NF, uint64_t RANGE, int8_t _NI, int8_t _NF, uint64_t _RANGE>
1143 inline SFix<FixMathPrivate::neededSNIExtra(FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)),FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator- (const UFix<NI,NF, RANGE>& op1, const SFix<_NI,_NF, _RANGE>& op2)
1144 {
1145  return -op2+op1;
1146  }
1147 
1148 
1154 template<int8_t NI, int8_t NF, uint64_t RANGE, int8_t _NI, int8_t _NF, uint64_t _RANGE>
1155 inline SFix<FixMathPrivate::neededSNIExtra(NI+_NI, NF+_NF, RANGE*_RANGE),NF+_NF, RANGE*_RANGE> operator* (const SFix<_NI,_NF,_RANGE>& op1, const UFix<NI,NF,RANGE>& op2)
1156 {
1157  return op2*op1;
1158 }
1159 
1160 // Comparison between SFix and UFixmath
1161 
1167 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1168 inline bool operator> (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1169 {
1170  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
1171  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
1172  SFix<new_NI,new_NF> left(op1);
1173  SFix<new_NI,new_NF> right(op2);
1174  return left.asRaw() > right.asRaw();
1175 }
1176 
1182 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1183 inline bool operator> (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1184 {
1185  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
1186  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
1187  SFix<new_NI,new_NF> left(op1);
1188  SFix<new_NI,new_NF> right(op2);
1189  return left.asRaw() > right.asRaw();
1190 }
1191 
1197 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1198 inline bool operator< (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1199 {
1200  return op2 > op1;
1201 }
1202 
1203 
1209 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1210 inline bool operator< (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1211 {
1212  return op2 > op1;
1213 }
1214 
1215 
1221 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1222 inline bool operator== (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1223 {
1224  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
1225  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
1226  SFix<new_NI,new_NF> left(op1);
1227  SFix<new_NI,new_NF> right(op2);
1228  return left.asRaw() == right.asRaw();
1229 }
1230 
1231 
1237 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1238 inline bool operator== (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1239 {
1240  return op2 == op1;
1241 }
1242 
1248 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1249 inline bool operator!= (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1250 {
1251  constexpr int8_t new_NI = FixMathPrivate::FM_max(NI, _NI);
1252  constexpr int8_t new_NF = FixMathPrivate::FM_max(NF, _NF);
1253  SFix<new_NI,new_NF> left(op1);
1254  SFix<new_NI,new_NF> right(op2);
1255  return left.asRaw() != right.asRaw();
1256 }
1257 
1258 
1264 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1265 inline bool operator!= (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1266 {
1267  return op2 != op1;
1268 }
1269 
1271 
1272 
1284 template<typename T>
1285 inline SFix<0, sizeof(T)*8-1> toSFraction(T val) {
1286  return SFix<0, sizeof(T)*8-1>::fromRaw(val);
1287 }
1288 
1299 template<typename T>
1300 inline SFix<sizeof(T)*8-1,0> toSInt(T val) {
1301  return SFix<sizeof(T)*8-1,0>::fromRaw(val);
1302 }
1303 
1304 
1305 
1306 
1307 
1308 
1309 #endif
Definition: FixMath.h:666
internal_type asRaw() const
Definition: FixMath.h:1003
Definition: FixMath.h:148
SFix< NI, NF, RANGE > operator-() const
Definition: FixMath.h:304
UFix(double fl)
Definition: FixMath.h:168
UFix()
Definition: FixMath.h:156
UFix(const UFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:202
static UFix< NI, NF > fromRaw(T raw)
Definition: FixMath.h:191
UFix(const SFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:213
UFix(T value, bool as_raw=false)
Definition: FixMath.h:179
UFix(float fl)
Definition: FixMath.h:162
UFix< FixMathPrivate::neededNIExtra(NI+_NI, NF+_NF, RANGE *_RANGE), NF+_NF, RANGE *_RANGE > operator*(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:316
UFix< NF, NI > invFast() const
Definition: FixMath.h:358
internal_type asRaw() const
Definition: FixMath.h:510
UFix< FixMathPrivate::neededNIExtra(FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF, _NF, RANGE, _RANGE)), FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF, _NF, RANGE, _RANGE)> operator+(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:225
Definition: FixMath.h:121
Definition: IntegerType.h:9