114 #define FIXMATH_UNSAFE
119 #include "IntegerType.h"
127 template<
typename T> constexpr T shiftR(T x, int8_t bits) {
return (bits > 0 ? (x >> (bits)) : bits < 0 ? (x << (-bits)) : x);}
128 constexpr int8_t sBitsToBytes(int8_t N) {
return (((N)>>3)+1);}
129 constexpr int8_t uBitsToBytes(int8_t N) {
return (((N-1)>>3)+1);}
130 template<
typename T> constexpr T FM_max(T N1, T N2) {
return (N1) > (N2) ? (N1) : (N2);}
131 template<
typename T> constexpr T FM_min(T N1, T N2) {
return (N1) > (N2) ? (N2) : (N1);}
132 constexpr uint64_t sFullRange(int8_t N) {
return uint64_t(1)<<N;}
133 constexpr uint64_t uFullRange(int8_t N) {
return ((uint64_t(1)<<(N-1))-1) + (uint64_t(1)<<(N-1));}
134 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))));}
135 constexpr uint64_t rangeShift(int8_t N, int8_t SH, uint64_t RANGE) {
return ((SH < N) ? (RANGE) : (shiftR(RANGE,(N-SH))));}
142 static constexpr int8_t bitsNeeded() {
return (value < 1 ? 0 : 1); }
149 template<
int8_t NI,
int8_t NF, u
int64_t RANGE=FixMathPrivate::sFullRange(NI+NF)>
153 template<
int8_t NI,
int8_t NF, u
int64_t RANGE=FixMathPrivate::uFullRange(NI+NF)>
158 template<
int8_t NF, u
int64_t RANGE>
using UFixByRange_t=
UFix<NIcount<RANGE>()-NF, NF, RANGE>;
160 template<
int8_t NF, u
int64_t RANGE>
using SFixByRange_t=
SFix<NIcount<RANGE-1>()-NF, NF, RANGE>;
168 template<
int8_t NI,
int8_t NF, u
int64_t RANGE>
171 static_assert(NI+NF<=64,
"The total width of a UFix cannot exceed 64bits");
172 typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF)>::unsigned_type internal_type ;
173 typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF+1)>::unsigned_type next_greater_type ;
184 constexpr
UFix(
float fl) : internal_value((fl * (next_greater_type(1) << NF))) {}
190 constexpr
UFix(
double fl) : internal_value(static_cast<internal_type> (fl * (next_greater_type(1) << NF))) {}
201 constexpr
UFix(T value,
bool as_raw=
false) : internal_value(as_raw ? value : (internal_type(value) << NF)) {}
219 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
228 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
238 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
244 return worktype(worktype(*this).asRaw() + worktype(op).
asRaw(),
true);
251 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
256 return worktype(worktype(*this).asRaw() + worktype(op).
asRaw(),
true);
259 #ifdef FIXMATH_UNSAFE
268 return UFix<NI,NF>(internal_value+((internal_type)op<<NF),
true);
278 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
282 typedef SFixByRange_t<FM_max(NF,_NF), FM_max(shiftR(RANGE,FM_max(NF,_NF)-NF), shiftR(_RANGE,FM_max(NF,_NF)-_NF))> worktype;
284 return worktype(worktype(*this).asRaw() - worktype(op).
asRaw(),
true);
292 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
298 #ifdef FIXMATH_UNSAFE
307 return UFix<NI,NF>(internal_value-((internal_type)op<<NF),
true);
325 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
329 return worktype((
typename worktype::internal_type) (internal_value)*op.
asRaw(),
true);
336 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
340 return worktype((
typename worktype::internal_type) (internal_value)*op.
asRaw(),
true);
343 #ifdef FIXMATH_UNSAFE
366 static_assert(NI+NF<=64, "The fast inverse cannot be computed for when NI+NF>63. Reduce the number of bits.
");
367 return UFix<NF,NI>((onesbitmask()/internal_value),true);
376 constexpr UFix<NF,_NF> inv() const
378 return UFix<_NF,NF>(internal_value,true).invFast();
388 constexpr UFix<NF,FixMathPrivate::FM_min(NI*2+NF,64-NF)> invFull() 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)
390 static_assert(2*NI+2*NF<=64, "The accurate inverse cannot be computed
for when 2*NI+2*NF>63. Reduce the number of bits.
");
391 return inv<NI*2+NF>();
402 template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF-1,64-NF)>
403 constexpr UFix<NF,_NF> invAccurate() const
405 static_assert(NF+_NF+1<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
406 return UFix<NF,_NF>(UFix<NF,_NF+1>::msbone()/internal_value,true);
409 /* template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF,64-NF)>
410 constexpr UFix<NF,_NF-1> invAccurateb() const
412 static_assert(NF+_NF<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
413 return UFix<NF,_NF-1>(UFix<NF,_NF>::msbone()/internal_value,true);
417 /* template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF,64-NF)>
418 constexpr UFix<NF,_NF> invAccurate() const
420 static_assert(NF+_NF<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
421 return UFix<NF,_NF>(UFix<NF,_NF-1>(UFix<NF,_NF>::msbone()/internal_value,true)); // the last cast is to have the same return type.
434 constexpr UFix<NI,NF> operator>> (const int8_t op) const
436 return UFix<NI,NF>(internal_value>>op,true);
440 #ifdef FIXMATH_UNSAFE
447 constexpr UFix<NI,NF> operator<< (const int8_t op) const
449 return UFix<NI,NF>(internal_value<<op,true);
458 constexpr UFix<FixMathPrivate::FM_max(NI-op,0),NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR() const
460 return UFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
468 constexpr UFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL() const
470 return UFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
475 /** Comparison with another UFix.
477 @return true if this is bigger than op, false otherwise
479 template<int8_t _NI, int8_t _NF>
480 constexpr bool operator> (const UFix<_NI,_NF>& op) const
482 using namespace FixMathPrivate;
483 typedef UFix<FM_max(NI, _NI),FM_max(NF, _NF)> comptype; // type suitable for comparison
484 return (comptype(*this).asRaw()>comptype(op).asRaw());
491 template<int8_t _NI, int8_t _NF>
492 constexpr bool operator< (const UFix<_NI,_NF>& op) const
502 template<int8_t _NI, int8_t _NF>
503 constexpr bool operator== (const UFix<_NI,_NF>& op) const
505 using namespace FixMathPrivate;
506 typedef UFix<FM_max(NI, _NI),FM_max(NF, _NF)> comptype; // type suitable for comparison
507 return (comptype(*this).asRaw()==comptype(op).asRaw());
514 template<int8_t _NI, int8_t _NF>
515 constexpr bool operator!= (const UFix<_NI,_NF>& op) const
517 typedef UFix<FixMathPrivate::FM_max(NI, _NI),FixMathPrivate::FM_max(NF, _NF)> comptype; // type suitable for comparison
518 return (comptype(*this).asRaw()!=comptype(op).asRaw());
524 constexpr SFix<NI,NF,RANGE> asSFix() const
526 return SFix<NI,NF,RANGE>(internal_value,true);
532 constexpr float asFloat() const { return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
537 constexpr typename IntegerType<FixMathPrivate::uBitsToBytes(NI)>::unsigned_type asInt() const
539 return UFix<NI,0>(*this).asRaw();
545 constexpr internal_type asRaw() const { return internal_value; }
550 static constexpr int8_t getNI() {return NI;}
555 static constexpr int8_t getNF() {return NF;}
560 static constexpr int8_t getRANGE() {return RANGE;}
578 template<int8_t BITS> static constexpr void assertSize() { static_assert(NI+NF <= BITS, "Data type is larger than expected!
"); }
580 template<int8_t, int8_t, uint64_t> friend class UFix; // for access to internal_type
581 template<int8_t, int8_t, uint64_t> friend class SFix;
583 internal_type internal_value;
584 //static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
585 static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF-1)) + ((1ULL<< (NI+NF-1)) - 1)); }
586 static constexpr internal_type msbone() { return (internal_type) (1ULL<< (NI+NF-1)); }
590 #ifdef FIXMATH_UNSAFE
592 template <int8_t NI, int8_t NF>
593 constexpr UFix<NI, NF> operator*(uint8_t op, const UFix<NI, NF>& uf) {return uf*op;}
595 template <int8_t NI, int8_t NF>
596 constexpr UFix<NI, NF> operator*(uint16_t op, const UFix<NI, NF>& uf) {return uf*op;}
598 template <int8_t NI, int8_t NF>
599 constexpr UFix<NI, NF> operator*(uint32_t op, const UFix<NI, NF>& uf) {return uf*op;}
601 template <int8_t NI, int8_t NF>
602 constexpr UFix<NI, NF> operator*(uint64_t op, const UFix<NI, NF>& uf) {return uf*op;}
604 template <int8_t NI, int8_t NF>
605 constexpr UFix<NI, NF> operator*(int8_t op, const UFix<NI, NF>& uf) {return uf*op;}
607 template <int8_t NI, int8_t NF>
608 constexpr UFix<NI, NF> operator*(int16_t op, const UFix<NI, NF>& uf) {return uf*op;}
610 template <int8_t NI, int8_t NF>
611 constexpr UFix<NI, NF> operator*(int32_t op, const UFix<NI, NF>& uf) {return uf*op;}
613 template <int8_t NI, int8_t NF>
614 constexpr UFix<NI, NF> operator*(int64_t op, const UFix<NI, NF>& uf) {return uf*op;}
616 template <int8_t NI, int8_t NF>
617 constexpr UFix<NI, NF> operator*(float op, const UFix<NI, NF>& uf) {return uf*op;}
619 template <int8_t NI, int8_t NF>
620 constexpr UFix<NI, NF> operator*(double op, const UFix<NI, NF>& uf) {return uf*op;}
623 template <int8_t NI, int8_t NF>
624 constexpr UFix<NI, NF> operator+(uint8_t op, const UFix<NI, NF>& uf) {return uf+op;}
626 template <int8_t NI, int8_t NF>
627 constexpr UFix<NI, NF> operator+(uint16_t op, const UFix<NI, NF>& uf) {return uf+op;}
629 template <int8_t NI, int8_t NF>
630 constexpr UFix<NI, NF> operator+(uint32_t op, const UFix<NI, NF>& uf) {return uf+op;}
632 template <int8_t NI, int8_t NF>
633 constexpr UFix<NI, NF> operator+(uint64_t op, const UFix<NI, NF>& uf) {return uf+op;}
635 template <int8_t NI, int8_t NF>
636 constexpr UFix<NI, NF> operator+(int8_t op, const UFix<NI, NF>& uf) {return uf+op;}
638 template <int8_t NI, int8_t NF>
639 constexpr UFix<NI, NF> operator+(int16_t op, const UFix<NI, NF>& uf) {return uf+op;}
641 template <int8_t NI, int8_t NF>
642 constexpr UFix<NI, NF> operator+(int32_t op, const UFix<NI, NF>& uf) {return uf+op;}
644 template <int8_t NI, int8_t NF>
645 constexpr UFix<NI, NF> operator+(int64_t op, const UFix<NI, NF>& uf) {return uf+op;}
647 template <int8_t NI, int8_t NF>
648 constexpr UFix<NI, NF> operator+(float op, const UFix<NI, NF>& uf) {return uf+op;}
650 template <int8_t NI, int8_t NF>
651 constexpr UFix<NI, NF> operator+(double op, const UFix<NI, NF>& uf) {return uf+op;}
654 template <int8_t NI, int8_t NF>
655 constexpr SFix<NI, NF> operator-(uint8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
657 template <int8_t NI, int8_t NF>
658 constexpr SFix<NI, NF> operator-(uint16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
660 template <int8_t NI, int8_t NF>
661 constexpr SFix<NI, NF> operator-(uint32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
663 template <int8_t NI, int8_t NF>
664 constexpr SFix<NI, NF> operator-(uint64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
666 template <int8_t NI, int8_t NF>
667 constexpr SFix<NI, NF> operator-(int8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
669 template <int8_t NI, int8_t NF>
670 constexpr SFix<NI, NF> operator-(int16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
672 template <int8_t NI, int8_t NF>
673 constexpr SFix<NI, NF> operator-(int32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
675 template <int8_t NI, int8_t NF>
676 constexpr SFix<NI, NF> operator-(int64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
678 template <int8_t NI, int8_t NF>
679 constexpr SFix<NI, NF> operator-(float op, const UFix<NI, NF>& uf) {return -uf+op;}
681 template <int8_t NI, int8_t NF>
682 constexpr SFix<NI, NF> operator-(double op, const UFix<NI, NF>& uf) {return -uf+op;}
703 constexpr inline UFix<0, sizeof(T)*8> toUFraction(T val) {
704 return UFix<0, sizeof(T)*8>::fromRaw(val);
722 constexpr inline UFix<sizeof(T)*8,0> toUInt(T val) {
723 return UFix<sizeof(T)*8,0>::fromRaw(val);
738 // TODO: auto sixteen = UFixAuto<16>(); could be made to return UFix<1, -4>!
739 template<uint64_t value>
740 constexpr FixMathPrivate::UFixByRange_t<0, value> UFixAuto() {
741 return FixMathPrivate::UFixByRange_t<0, value>::fromRaw(value);
752 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.
755 static_assert(NI+NF<64, "The total width of a
SFix cannot exceed 63bits
");
756 typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NI+NF)>::signed_type internal_type ; // smallest size that fits our internal integer
757 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.
768 constexpr SFix(float fl) : internal_value(/*static_cast<internal_type>*/(fl * (next_greater_type(1) << NF))) {}
774 constexpr SFix(double fl) : internal_value(static_cast<internal_type> (fl * (next_greater_type(1) << NF))) {}
784 constexpr SFix(T value,bool as_raw=false) : internal_value(as_raw ? value : (internal_type(value) << NF)) {};
791 static constexpr SFix<NI,NF> fromRaw(T raw){return SFix<NI,NF>(raw,true);}
798 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
799 constexpr SFix(const SFix<_NI,_NF, _RANGE>& sf) : internal_value(FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::sBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::signed_type) sf.asRaw(),(_NF-NF))) {}
805 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
806 constexpr SFix(const UFix<_NI,_NF, _RANGE>& uf) : internal_value(FixMathPrivate::shiftR((typename IntegerType<FixMathPrivate::uBitsToBytes(FixMathPrivate::FM_max(NI+NF,_NI+_NF))>::unsigned_type) uf.asRaw(),(_NF-NF))) {};
814 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
815 constexpr FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const SFix<_NI,_NF,_RANGE>& op) const
817 typedef FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> worktype;
818 return worktype(worktype(*this).asRaw() + worktype(op).asRaw(), true);
826 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
827 constexpr FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator+ (const UFix<_NI,_NF,_RANGE>& op2) const
832 #ifdef FIXMATH_UNSAFE
839 constexpr SFix<NI,NF> operator+ (const T op) const
841 return SFix<NI,NF>(internal_value+(op<<NF),true);
851 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
852 constexpr FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator- (const SFix<_NI,_NF, _RANGE>& op) const
854 typedef FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> worktype;
855 return worktype(worktype(*this).asRaw() - worktype(op).asRaw(), true);
862 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
863 constexpr FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> operator- (const UFix<_NI,_NF, _RANGE>& op) const
865 typedef FixMathPrivate::SFixByRange_t<FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)> worktype;
866 return worktype(worktype(*this).asRaw() - worktype(op).asRaw(), true);
869 #ifdef FIXMATH_UNSAFE
876 constexpr SFix<NI,NF> operator- (const T op) const
878 return SFix<NI,NF>(internal_value-(op<<NF),true);
885 /* constexpr SFix<NI,NF,RANGE> operator-() const
887 return SFix<NI,NF,RANGE>(-internal_value,true);
889 constexpr FixMathPrivate::SFixByRange_t<NF,RANGE+1> operator-() const
891 typedef FixMathPrivate::SFixByRange_t<NF, RANGE+1> returntype;
892 return returntype(-internal_value,true);
901 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
902 constexpr FixMathPrivate::SFixByRange_t<NF+_NF, RANGE*_RANGE> operator* (const SFix<_NI,_NF,_RANGE>& op) const
904 typedef FixMathPrivate::SFixByRange_t<NF+_NF, RANGE*_RANGE> worktype;
905 return worktype((typename worktype::internal_type)(internal_value)*op.asRaw(), true);
913 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
914 constexpr FixMathPrivate::SFixByRange_t<NF+_NF, RANGE*_RANGE> operator* (const UFix<_NI,_NF,_RANGE>& op2) const
919 #ifdef FIXMATH_UNSAFE
926 constexpr SFix<NI,NF> operator* (const T op) const
928 return SFix<NI,NF>(internal_value*op,true);
942 constexpr SFix<NF,NI> invFast() const
944 static_assert(NI+NF<=63, "The fast inverse cannot be computed
for when NI+NF>63. Reduce the number of bits.
");
945 return SFix<NF,NI>((onesbitmask()/internal_value),true);
953 constexpr SFix<NF,_NF> inv() const
955 return SFix<_NF,NF>(internal_value,true).invFast();
963 constexpr SFix<NF,FixMathPrivate::FM_min(NI*2+NF,63-NF)> invFull() const
965 return inv<NI*2+NF>();
977 template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF-1,63-NF)>
978 constexpr SFix<NF,_NF> invAccurate() const
980 static_assert(NF+_NF+1<=63, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
981 return SFix<NF,_NF>(SFix<NF,_NF+1>::msbone()/internal_value,true);
992 constexpr SFix<NI,NF> operator>> (const int8_t op) const
994 return SFix<NI,NF>(internal_value>>op,true);
997 #ifdef FIXMATH_UNSAFE
1004 constexpr SFix<NI,NF> operator<< (const int8_t op) const
1006 return SFix<NI,NF>(internal_value<<op,true);
1015 constexpr SFix<FixMathPrivate::FM_max(NI-op,0), NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR()
1017 return SFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
1025 constexpr SFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL()
1027 return SFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
1037 template<int8_t _NI, int8_t _NF>
1038 constexpr bool operator> (const SFix<_NI,_NF>& op) const
1040 using namespace FixMathPrivate;
1041 typedef SFix<FM_max(NI, _NI), FM_max(NF, _NF)> comptype; // common type suitable for comparison
1042 return comptype(*this).asRaw()>comptype(op).asRaw();
1049 template<int8_t _NI, int8_t _NF>
1050 constexpr bool operator< (const SFix<_NI,_NF>& op) const
1060 template<int8_t _NI, int8_t _NF>
1061 constexpr bool operator== (const SFix<_NI,_NF>& op) const
1063 using namespace FixMathPrivate;
1064 typedef SFix<FM_max(NI, _NI), FM_max(NF, _NF)> comptype; // common type suitable for comparison
1065 return comptype(*this).asRaw()==comptype(op).asRaw();
1072 template<int8_t _NI, int8_t _NF>
1073 constexpr bool operator!= (const SFix<_NI,_NF>& op) const
1075 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> comptype; // common type suitable for comparison
1076 return comptype(*this).asRaw()!=comptype(op).asRaw();
1083 constexpr UFix<NI,NF,RANGE> asUFix() const
1085 return UFix<NI,NF,RANGE>(internal_value,true);
1092 constexpr float asFloat() const {return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
1098 constexpr typename IntegerType<FixMathPrivate::sBitsToBytes(NI+1)>::signed_type asInt() const // the +1 is to ensure that no overflow occurs at the lower end of the container (ie when getting the integer part of SFix<7,N>(-128.4), which is a valid SFix<7,N>) because the floor is done towards negative values.
1100 SFix<NI+1,0> integer_part(*this);
1101 return integer_part.asRaw();
1107 constexpr internal_type asRaw() const {return internal_value; }
1112 static constexpr int8_t getNI() {return NI;}
1117 static constexpr int8_t getNF() {return NF;}
1122 static constexpr int8_t getRANGE() {return RANGE;}
1130 template<int8_t BITS> static constexpr void assertSize() { static_assert(NI+NF+1 <= BITS, "Data type is larger than expected!
"); }
1132 template<int8_t, int8_t, uint64_t> friend class UFix; // for access to internal_type
1133 template<int8_t, int8_t, uint64_t> friend class SFix;
1135 internal_type internal_value;
1136 //static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
1137 static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF-1)) + ((1ULL<< (NI+NF-1)) - 1)); }
1138 static constexpr internal_type msbone() { return (internal_type) (1ULL<< (NI+NF-1)); }
1142 #ifdef FIXMATH_UNSAFE
1146 template <int8_t NI, int8_t NF>
1147 constexpr SFix<NI, NF> operator*(uint8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1149 template <int8_t NI, int8_t NF>
1150 constexpr SFix<NI, NF> operator*(uint16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1152 template <int8_t NI, int8_t NF>
1153 constexpr SFix<NI, NF> operator*(uint32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1155 template <int8_t NI, int8_t NF>
1156 constexpr SFix<NI, NF> operator*(uint64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1158 template <int8_t NI, int8_t NF>
1159 constexpr SFix<NI, NF> operator*(int8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1161 template <int8_t NI, int8_t NF>
1162 constexpr SFix<NI, NF> operator*(int16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1164 template <int8_t NI, int8_t NF>
1165 constexpr SFix<NI, NF> operator*(int32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1167 template <int8_t NI, int8_t NF>
1168 constexpr SFix<NI, NF> operator*(int64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1170 template <int8_t NI, int8_t NF>
1171 constexpr SFix<NI, NF> operator*(float op, const SFix<NI, NF>& uf) {return uf*op;}
1173 template <int8_t NI, int8_t NF>
1174 constexpr SFix<NI, NF> operator*(double op, const SFix<NI, NF>& uf) {return uf*op;}
1177 template <int8_t NI, int8_t NF>
1178 constexpr SFix<NI, NF> operator+(uint8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1180 template <int8_t NI, int8_t NF>
1181 constexpr SFix<NI, NF> operator+(uint16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1183 template <int8_t NI, int8_t NF>
1184 constexpr SFix<NI, NF> operator+(uint32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1186 template <int8_t NI, int8_t NF>
1187 constexpr SFix<NI, NF> operator+(uint64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1189 template <int8_t NI, int8_t NF>
1190 constexpr SFix<NI, NF> operator+(int8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1192 template <int8_t NI, int8_t NF>
1193 constexpr SFix<NI, NF> operator+(int16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1195 template <int8_t NI, int8_t NF>
1196 constexpr SFix<NI, NF> operator+(int32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1198 template <int8_t NI, int8_t NF>
1199 constexpr SFix<NI, NF> operator+(int64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1201 template <int8_t NI, int8_t NF>
1202 constexpr SFix<NI, NF> operator+(float op, const SFix<NI, NF>& uf) {return uf+op;}
1204 template <int8_t NI, int8_t NF>
1205 constexpr SFix<NI, NF> operator+(double op, const SFix<NI, NF>& uf) {return uf+op;}
1208 template <int8_t NI, int8_t NF>
1209 constexpr SFix<NI, NF> operator-(uint8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1211 template <int8_t NI, int8_t NF>
1212 constexpr SFix<NI, NF> operator-(uint16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1214 template <int8_t NI, int8_t NF>
1215 constexpr SFix<NI, NF> operator-(uint32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1217 template <int8_t NI, int8_t NF>
1218 constexpr SFix<NI, NF> operator-(uint64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1220 template <int8_t NI, int8_t NF>
1221 constexpr SFix<NI, NF> operator-(int8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1223 template <int8_t NI, int8_t NF>
1224 constexpr SFix<NI, NF> operator-(int16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1226 template <int8_t NI, int8_t NF>
1227 constexpr SFix<NI, NF> operator-(int32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1229 template <int8_t NI, int8_t NF>
1230 constexpr SFix<NI, NF> operator-(int64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1232 template <int8_t NI, int8_t NF>
1233 constexpr SFix<NI, NF> operator-(float op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1235 template <int8_t NI, int8_t NF>
1236 constexpr SFix<NI, NF> operator-(double op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1244 // Comparison between SFix and UFix
1251 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1252 constexpr bool operator> (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1254 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1255 return worktype(op1).asRaw() > worktype(op2).asRaw();
1263 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1264 constexpr bool operator> (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1266 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1267 return worktype(op1).asRaw() > worktype(op2).asRaw();
1275 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1276 constexpr bool operator< (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1287 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1288 constexpr bool operator< (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1299 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1300 constexpr bool operator== (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2)
1302 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1303 return (worktype(op1).asRaw() == worktype(op2).asRaw());
1312 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1313 constexpr bool operator== (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1323 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1324 constexpr bool operator!= (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1326 return !(op1 == op2);
1335 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1336 constexpr bool operator!= (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1338 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> comptype;
1339 return (comptype(op1).asRaw() != comptype(op2).asRaw());;
1360 template<typename T>
1361 constexpr SFix<0, sizeof(T)*8-1> toSFraction(T val) {
1362 return SFix<0, sizeof(T)*8-1>::fromRaw(val);
1379 template<typename T>
1380 constexpr SFix<sizeof(T)*8-1,0> toSInt(T val) {
1381 return SFix<sizeof(T)*8-1,0>::fromRaw(val);
1396 template<int64_t value>
1397 constexpr const FixMathPrivate::SFixByRange_t<0, value < 0 ? -value : value+1> SFixAuto() {
1398 return FixMathPrivate::SFixByRange_t<0, value < 0 ? -value : value+1>::fromRaw(value);
1401 #include "FixMath_Autotests.h
"
Definition: FixMath.h:754
constexpr internal_type asRaw() const
Definition: FixMath.h:1107
Definition: FixMath.h:170
constexpr SFix< NI, NF, RANGE > operator-() const
Definition: FixMath.h:314
constexpr internal_type asRaw() const
Definition: FixMath.h:545
constexpr UFix(float fl)
Definition: FixMath.h:184
constexpr UFix(double fl)
Definition: FixMath.h:190
constexpr UFix(T value, bool as_raw=false)
Definition: FixMath.h:201
constexpr UFix()
Definition: FixMath.h:178
constexpr UFix< NF, NI > invFast() const
Definition: FixMath.h:364
constexpr FixMathPrivate::UFixByRange_t< NF+_NF, RANGE *_RANGE > operator*(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:326
static constexpr UFix< NI, NF > fromRaw(T raw)
Definition: FixMath.h:209
constexpr UFix(const UFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:220
constexpr FixMathPrivate::UFixByRange_t< FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF, _NF, RANGE, _RANGE)> operator+(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:239
constexpr UFix(const SFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:229
Definition: FixMath.h:126
Definition: FixMath.h:138
Definition: IntegerType.h:9