114 #define FIXMATH_UNSAFE
119 #include "IntegerType.h"
128 template<
typename T> constexpr T shiftR(T x, int8_t bits) {
return (bits > 0 ? (x >> (bits)) : bits < 0 ? (x << (-bits)) : x);}
129 constexpr int8_t sBitsToBytes(int8_t N) {
return (((N)>>3)+1);}
130 constexpr int8_t uBitsToBytes(int8_t N) {
return (((N-1)>>3)+1);}
131 template<
typename T> constexpr T FM_max(T N1, T N2) {
return (N1) > (N2) ? (N1) : (N2);}
132 template<
typename T> constexpr T FM_min(T N1, T N2) {
return (N1) > (N2) ? (N2) : (N1);}
133 constexpr uint64_t sFullRange(int8_t N) {
return uint64_t(1)<<N;}
134 constexpr uint64_t uFullRange(int8_t N) {
return ((uint64_t(1)<<(N-1))-1) + (uint64_t(1)<<(N-1));}
135 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))));}
136 constexpr uint64_t rangeShift(int8_t N, int8_t SH, uint64_t RANGE) {
return ((SH < N) ? (RANGE) : (shiftR(RANGE,(N-SH))));}
140 template<
int8_t NI,
int8_t NF, u
int64_t RANGE=FixMathPrivate::sFullRange(NI+NF)>
144 template<
int8_t NI,
int8_t NF, u
int64_t RANGE=FixMathPrivate::uFullRange(NI+NF)>
154 template<
int8_t NI,
int8_t NF, u
int64_t RANGE>
157 static_assert(NI+NF<=64,
"The total width of a UFix cannot exceed 64bits");
158 typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF)>::unsigned_type internal_type ;
159 typedef typename IntegerType<FixMathPrivate::uBitsToBytes(NI+NF+1)>::unsigned_type next_greater_type ;
170 constexpr
UFix(
float fl) : internal_value((fl * (next_greater_type(1) << NF))) {}
176 constexpr
UFix(
double fl) : internal_value(static_cast<internal_type> (fl * (next_greater_type(1) << NF))) {}
187 constexpr
UFix(T value,
bool as_raw=
false) : internal_value(as_raw ? value : (internal_type(value) << NF)) {}
205 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
214 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
224 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
228 typedef UFix<FM_max(NI,_NI), FM_max(NF,_NF), rangeAdd(NF,_NF,RANGE,_RANGE)> temptype;
229 typedef typename temptype::UFixNIadj_t worktype;
231 return worktype(worktype(*this).asRaw() + worktype(op).
asRaw(),
true);
238 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
239 constexpr
typename SFix<FixMathPrivate::FM_max(NI,_NI), FixMathPrivate::FM_max(NF,_NF), FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t
operator+ (
const SFix<_NI,_NF,_RANGE>& op)
const
242 typedef SFix<FM_max(NI,_NI), FM_max(NF,_NF), rangeAdd(NF,_NF,RANGE,_RANGE)> temptype;
243 typedef typename temptype::SFixNIadj_t worktype;
245 return worktype(worktype(*this).asRaw() + worktype(op).
asRaw(),
true);
248 #ifdef FIXMATH_UNSAFE
257 return UFix<NI,NF>(internal_value+((internal_type)op<<NF),
true);
267 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
268 constexpr
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
271 typedef SFix<FM_max(NI,_NI),FM_max(NF,_NF), FM_max(shiftR(RANGE,FM_max(NF,_NF)-NF), shiftR(_RANGE,FM_max(NF,_NF)-_NF))> worktype;
273 return worktype(worktype(*this).asRaw() - worktype(op).
asRaw(),
true);
281 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
282 constexpr
typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t
operator- (
const SFix<_NI,_NF, _RANGE>& op2)
const
287 #ifdef FIXMATH_UNSAFE
296 return UFix<NI,NF>(internal_value-((internal_type)op<<NF),
true);
314 template<
int8_t _NI,
int8_t _NF, u
int64_t _RANGE>
318 return worktype((
typename worktype::internal_type) (internal_value)*op.
asRaw(),
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);
332 #ifdef FIXMATH_UNSAFE
355 static_assert(NI+NF<=64, "The fast inverse cannot be computed for when NI+NF>63. Reduce the number of bits.
");
356 return UFix<NF,NI>((onesbitmask()/internal_value),true);
365 constexpr UFix<NF,_NF> inv() const
367 return UFix<_NF,NF>(internal_value,true).invFast();
377 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)
379 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.
");
380 return inv<NI*2+NF>();
391 template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF-1,64-NF)>
392 constexpr UFix<NF,_NF> invAccurate() const
394 static_assert(NF+_NF+1<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
395 return UFix<NF,_NF>(UFix<NF,_NF+1>::msbone()/internal_value,true);
398 /* template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF,64-NF)>
399 constexpr UFix<NF,_NF-1> invAccurateb() const
401 static_assert(NF+_NF<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
402 return UFix<NF,_NF-1>(UFix<NF,_NF>::msbone()/internal_value,true);
406 /* template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF,64-NF)>
407 constexpr UFix<NF,_NF> invAccurate() const
409 static_assert(NF+_NF<=64, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
410 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.
423 constexpr UFix<NI,NF> operator>> (const int8_t op) const
425 return UFix<NI,NF>(internal_value>>op,true);
429 #ifdef FIXMATH_UNSAFE
436 constexpr UFix<NI,NF> operator<< (const int8_t op) const
438 return UFix<NI,NF>(internal_value<<op,true);
447 constexpr UFix<FixMathPrivate::FM_max(NI-op,0),NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR() const
449 return UFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
457 constexpr UFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL() const
459 return UFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
464 /** Comparison with another UFix.
466 @return true if this is bigger than op, false otherwise
468 template<int8_t _NI, int8_t _NF>
469 constexpr bool operator> (const UFix<_NI,_NF>& op) const
471 using namespace FixMathPrivate;
472 typedef UFix<FM_max(NI, _NI),FM_max(NF, _NF)> comptype; // type suitable for comparison
473 return (comptype(*this).asRaw()>comptype(op).asRaw());
480 template<int8_t _NI, int8_t _NF>
481 constexpr bool operator< (const UFix<_NI,_NF>& op) const
491 template<int8_t _NI, int8_t _NF>
492 constexpr bool operator== (const UFix<_NI,_NF>& op) const
494 using namespace FixMathPrivate;
495 typedef UFix<FM_max(NI, _NI),FM_max(NF, _NF)> comptype; // type suitable for comparison
496 return (comptype(*this).asRaw()==comptype(op).asRaw());
503 template<int8_t _NI, int8_t _NF>
504 constexpr bool operator!= (const UFix<_NI,_NF>& op) const
506 typedef UFix<FixMathPrivate::FM_max(NI, _NI),FixMathPrivate::FM_max(NF, _NF)> comptype; // type suitable for comparison
507 return (comptype(*this).asRaw()!=comptype(op).asRaw());
513 constexpr SFix<NI,NF,RANGE> asSFix() const
515 return SFix<NI,NF,RANGE>(internal_value,true);
521 constexpr float asFloat() const { return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
526 constexpr typename IntegerType<FixMathPrivate::uBitsToBytes(NI)>::unsigned_type asInt() const
528 return UFix<NI,0>(*this).asRaw();
534 constexpr internal_type asRaw() const { return internal_value; }
539 static constexpr int8_t getNI() {return NI;}
544 static constexpr int8_t getNF() {return NF;}
562 template<int8_t BITS> static constexpr void assertSize() { static_assert(NI+NF <= BITS, "Data type is larger than expected!
"); }
564 template<int8_t, int8_t, uint64_t> friend class UFix; // All sibling specializations shall be friends, too
565 template<int8_t, int8_t, uint64_t> friend class SFix;
566 static constexpr uint64_t maxRANGE(int8_t delta_bits=0) { return ((uint64_t(1)<<(NI+NF+delta_bits-1)) - 1 + (uint64_t(1)<<(NI+NF+delta_bits-1))); } // == 1 << NI+NF+delta_bits, but not overflowing at NIF+NF+delta_bits==64
567 typedef UFix<(RANGE > maxRANGE()) ? NI+1 : (RANGE > maxRANGE(-1)) ? NI : NI-1, NF, RANGE> UFixNIadj_t;
569 internal_type internal_value;
570 //static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
571 static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF-1)) + ((1ULL<< (NI+NF-1)) - 1)); }
572 static constexpr internal_type msbone() { return (internal_type) (1ULL<< (NI+NF-1)); }
576 #ifdef FIXMATH_UNSAFE
578 template <int8_t NI, int8_t NF>
579 constexpr UFix<NI, NF> operator*(uint8_t op, const UFix<NI, NF>& uf) {return uf*op;}
581 template <int8_t NI, int8_t NF>
582 constexpr UFix<NI, NF> operator*(uint16_t op, const UFix<NI, NF>& uf) {return uf*op;}
584 template <int8_t NI, int8_t NF>
585 constexpr UFix<NI, NF> operator*(uint32_t op, const UFix<NI, NF>& uf) {return uf*op;}
587 template <int8_t NI, int8_t NF>
588 constexpr UFix<NI, NF> operator*(uint64_t op, const UFix<NI, NF>& uf) {return uf*op;}
590 template <int8_t NI, int8_t NF>
591 constexpr UFix<NI, NF> operator*(int8_t op, const UFix<NI, NF>& uf) {return uf*op;}
593 template <int8_t NI, int8_t NF>
594 constexpr UFix<NI, NF> operator*(int16_t op, const UFix<NI, NF>& uf) {return uf*op;}
596 template <int8_t NI, int8_t NF>
597 constexpr UFix<NI, NF> operator*(int32_t op, const UFix<NI, NF>& uf) {return uf*op;}
599 template <int8_t NI, int8_t NF>
600 constexpr UFix<NI, NF> operator*(int64_t op, const UFix<NI, NF>& uf) {return uf*op;}
602 template <int8_t NI, int8_t NF>
603 constexpr UFix<NI, NF> operator*(float op, const UFix<NI, NF>& uf) {return uf*op;}
605 template <int8_t NI, int8_t NF>
606 constexpr UFix<NI, NF> operator*(double op, const UFix<NI, NF>& uf) {return uf*op;}
609 template <int8_t NI, int8_t NF>
610 constexpr UFix<NI, NF> operator+(uint8_t op, const UFix<NI, NF>& uf) {return uf+op;}
612 template <int8_t NI, int8_t NF>
613 constexpr UFix<NI, NF> operator+(uint16_t op, const UFix<NI, NF>& uf) {return uf+op;}
615 template <int8_t NI, int8_t NF>
616 constexpr UFix<NI, NF> operator+(uint32_t op, const UFix<NI, NF>& uf) {return uf+op;}
618 template <int8_t NI, int8_t NF>
619 constexpr UFix<NI, NF> operator+(uint64_t op, const UFix<NI, NF>& uf) {return uf+op;}
621 template <int8_t NI, int8_t NF>
622 constexpr UFix<NI, NF> operator+(int8_t op, const UFix<NI, NF>& uf) {return uf+op;}
624 template <int8_t NI, int8_t NF>
625 constexpr UFix<NI, NF> operator+(int16_t op, const UFix<NI, NF>& uf) {return uf+op;}
627 template <int8_t NI, int8_t NF>
628 constexpr UFix<NI, NF> operator+(int32_t op, const UFix<NI, NF>& uf) {return uf+op;}
630 template <int8_t NI, int8_t NF>
631 constexpr UFix<NI, NF> operator+(int64_t op, const UFix<NI, NF>& uf) {return uf+op;}
633 template <int8_t NI, int8_t NF>
634 constexpr UFix<NI, NF> operator+(float op, const UFix<NI, NF>& uf) {return uf+op;}
636 template <int8_t NI, int8_t NF>
637 constexpr UFix<NI, NF> operator+(double op, const UFix<NI, NF>& uf) {return uf+op;}
640 template <int8_t NI, int8_t NF>
641 constexpr SFix<NI, NF> operator-(uint8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
643 template <int8_t NI, int8_t NF>
644 constexpr SFix<NI, NF> operator-(uint16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
646 template <int8_t NI, int8_t NF>
647 constexpr SFix<NI, NF> operator-(uint32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
649 template <int8_t NI, int8_t NF>
650 constexpr SFix<NI, NF> operator-(uint64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
652 template <int8_t NI, int8_t NF>
653 constexpr SFix<NI, NF> operator-(int8_t op, const UFix<NI, NF>& uf) {return -uf+op;}
655 template <int8_t NI, int8_t NF>
656 constexpr SFix<NI, NF> operator-(int16_t op, const UFix<NI, NF>& uf) {return -uf+op;}
658 template <int8_t NI, int8_t NF>
659 constexpr SFix<NI, NF> operator-(int32_t op, const UFix<NI, NF>& uf) {return -uf+op;}
661 template <int8_t NI, int8_t NF>
662 constexpr SFix<NI, NF> operator-(int64_t op, const UFix<NI, NF>& uf) {return -uf+op;}
664 template <int8_t NI, int8_t NF>
665 constexpr SFix<NI, NF> operator-(float op, const UFix<NI, NF>& uf) {return -uf+op;}
667 template <int8_t NI, int8_t NF>
668 constexpr SFix<NI, NF> operator-(double op, const UFix<NI, NF>& uf) {return -uf+op;}
685 constexpr inline UFix<0, sizeof(T)*8> toUFraction(T val) {
686 return UFix<0, sizeof(T)*8>::fromRaw(val);
700 constexpr inline UFix<sizeof(T)*8,0> toUInt(T val) {
701 return UFix<sizeof(T)*8,0>::fromRaw(val);
712 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.
715 static_assert(NI+NF<64, "The total width of a
SFix cannot exceed 63bits
");
716 typedef typename IntegerType<FixMathPrivate::sBitsToBytes(NI+NF)>::signed_type internal_type ; // smallest size that fits our internal integer
717 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.
728 constexpr SFix(float fl) : internal_value(/*static_cast<internal_type>*/(fl * (next_greater_type(1) << NF))) {}
734 constexpr SFix(double fl) : internal_value(static_cast<internal_type> (fl * (next_greater_type(1) << NF))) {}
744 constexpr SFix(T value,bool as_raw=false) : internal_value(as_raw ? value : (internal_type(value) << NF)) {};
751 static constexpr SFix<NI,NF> fromRaw(T raw){return SFix<NI,NF>(raw,true);}
758 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
759 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))) {}
765 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
766 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))) {};
774 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
775 constexpr typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t operator+ (const SFix<_NI,_NF,_RANGE>& op) const
777 using namespace FixMathPrivate;
778 typedef typename SFix<FM_max(NI,_NI),FM_max(NF,_NF),rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t worktype;
779 return worktype(worktype(*this).asRaw() + worktype(op).asRaw(), true);
787 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
788 constexpr typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t operator+ (const UFix<_NI,_NF,_RANGE>& op2) const
793 #ifdef FIXMATH_UNSAFE
800 constexpr SFix<NI,NF> operator+ (const T op) const
802 return SFix<NI,NF>(internal_value+(op<<NF),true);
812 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
813 constexpr typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t operator- (const SFix<_NI,_NF, _RANGE>& op) const
815 typedef typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t worktype;
816 return worktype(worktype(*this).asRaw() - worktype(op).asRaw(), true);
823 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
824 constexpr typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t operator- (const UFix<_NI,_NF, _RANGE>& op) const
826 typedef typename SFix<FixMathPrivate::FM_max(NI,_NI),FixMathPrivate::FM_max(NF,_NF),FixMathPrivate::rangeAdd(NF,_NF,RANGE,_RANGE)>::SFixNIadj_t worktype;
827 return worktype(worktype(*this).asRaw() - worktype(op).asRaw(), true);
830 #ifdef FIXMATH_UNSAFE
837 constexpr SFix<NI,NF> operator- (const T op) const
839 return SFix<NI,NF>(internal_value-(op<<NF),true);
846 constexpr SFix<NI,NF,RANGE> operator-() const
848 return SFix<NI,NF,RANGE>(-internal_value,true);
857 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
858 constexpr typename SFix<NI+_NI, NF+_NF, RANGE*_RANGE>::SFixNIadj_t operator* (const SFix<_NI,_NF,_RANGE>& op) const
860 typedef typename SFix<NI+_NI, NF+_NF, RANGE*_RANGE>::SFixNIadj_t worktype;
861 return worktype((typename worktype::internal_type)(internal_value)*op.asRaw(), true);
869 template<int8_t _NI, int8_t _NF, uint64_t _RANGE>
870 constexpr typename SFix<NI+_NI, NF+_NF, RANGE*_RANGE>::SFixNIadj_t operator* (const UFix<_NI,_NF,_RANGE>& op2) const
875 #ifdef FIXMATH_UNSAFE
882 constexpr SFix<NI,NF> operator* (const T op) const
884 return SFix<NI,NF>(internal_value*op,true);
898 constexpr SFix<NF,NI> invFast() const
900 static_assert(NI+NF<=63, "The fast inverse cannot be computed
for when NI+NF>63. Reduce the number of bits.
");
901 return SFix<NF,NI>((onesbitmask()/internal_value),true);
909 constexpr SFix<NF,_NF> inv() const
911 return SFix<_NF,NF>(internal_value,true).invFast();
919 constexpr SFix<NF,FixMathPrivate::FM_min(NI*2+NF,63-NF)> invFull() const
921 return inv<NI*2+NF>();
933 template<int8_t _NF=FixMathPrivate::FM_min(NI*2+NF-1,63-NF)>
934 constexpr SFix<NF,_NF> invAccurate() const
936 static_assert(NF+_NF+1<=63, "The accurate inverse cannot be computed because the asked precision is too great. Reduce the number of bits.
");
937 return SFix<NF,_NF>(SFix<NF,_NF+1>::msbone()/internal_value,true);
948 constexpr SFix<NI,NF> operator>> (const int8_t op) const
950 return SFix<NI,NF>(internal_value>>op,true);
953 #ifdef FIXMATH_UNSAFE
960 constexpr SFix<NI,NF> operator<< (const int8_t op) const
962 return SFix<NI,NF>(internal_value<<op,true);
971 constexpr SFix<FixMathPrivate::FM_max(NI-op,0), NF+op, FixMathPrivate::rangeShift(NI,op,RANGE)> sR()
973 return SFix<FixMathPrivate::FM_max(NI-op,0),NF+op,FixMathPrivate::rangeShift(NI,op,RANGE)>(internal_value,true);
981 constexpr SFix<NI+op,FixMathPrivate::FM_max(NF-op,0),FixMathPrivate::rangeShift(NF,op,RANGE)> sL()
983 return SFix<NI+op,FixMathPrivate::FM_max(NF-op,0)>(internal_value,true);
993 template<int8_t _NI, int8_t _NF>
994 constexpr bool operator> (const SFix<_NI,_NF>& op) const
996 using namespace FixMathPrivate;
997 typedef SFix<FM_max(NI, _NI), FM_max(NF, _NF)> comptype; // common type suitable for comparison
998 return comptype(*this).asRaw()>comptype(op).asRaw();
1005 template<int8_t _NI, int8_t _NF>
1006 constexpr bool operator< (const SFix<_NI,_NF>& op) const
1016 template<int8_t _NI, int8_t _NF>
1017 constexpr bool operator== (const SFix<_NI,_NF>& op) const
1019 using namespace FixMathPrivate;
1020 typedef SFix<FM_max(NI, _NI), FM_max(NF, _NF)> comptype; // common type suitable for comparison
1021 return comptype(*this).asRaw()==comptype(op).asRaw();
1028 template<int8_t _NI, int8_t _NF>
1029 constexpr bool operator!= (const SFix<_NI,_NF>& op) const
1031 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> comptype; // common type suitable for comparison
1032 return comptype(*this).asRaw()!=comptype(op).asRaw();
1039 constexpr UFix<NI,NF,RANGE> asUFix() const
1041 return UFix<NI,NF,RANGE>(internal_value,true);
1048 constexpr float asFloat() const {return (static_cast<float>(internal_value)) / (next_greater_type(1)<<NF); }
1054 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.
1056 SFix<NI+1,0> integer_part(*this);
1057 return integer_part.asRaw();
1063 constexpr internal_type asRaw() const {return internal_value; }
1068 static constexpr int8_t getNI() {return NI;}
1073 static constexpr int8_t getNF() {return NF;}
1081 template<int8_t BITS> static constexpr void assertSize() { static_assert(NI+NF+1 <= BITS, "Data type is larger than expected!
"); }
1083 template<int8_t, int8_t, uint64_t> friend class UFix; // for access to UFixNIadj_t
1084 template<int8_t, int8_t, uint64_t> friend class SFix;
1085 static constexpr uint64_t maxRANGE(int8_t delta_bits=0) { return (uint64_t(1)<<(NI+NF+delta_bits)); } // no -1 for signed, because negative number actually extend to -2^n, not just 2^n-1
1086 typedef UFix<(RANGE > maxRANGE()) ? NI+1 : (RANGE > maxRANGE(-1)) ? NI : NI-1, NF, RANGE> SFixNIadj_t;
1088 internal_type internal_value;
1089 //static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF)) - 1); }
1090 static constexpr internal_type onesbitmask() { return (internal_type) ((1ULL<< (NI+NF-1)) + ((1ULL<< (NI+NF-1)) - 1)); }
1091 static constexpr internal_type msbone() { return (internal_type) (1ULL<< (NI+NF-1)); }
1095 #ifdef FIXMATH_UNSAFE
1099 template <int8_t NI, int8_t NF>
1100 constexpr SFix<NI, NF> operator*(uint8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1102 template <int8_t NI, int8_t NF>
1103 constexpr SFix<NI, NF> operator*(uint16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1105 template <int8_t NI, int8_t NF>
1106 constexpr SFix<NI, NF> operator*(uint32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1108 template <int8_t NI, int8_t NF>
1109 constexpr SFix<NI, NF> operator*(uint64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1111 template <int8_t NI, int8_t NF>
1112 constexpr SFix<NI, NF> operator*(int8_t op, const SFix<NI, NF>& uf) {return uf*op;}
1114 template <int8_t NI, int8_t NF>
1115 constexpr SFix<NI, NF> operator*(int16_t op, const SFix<NI, NF>& uf) {return uf*op;}
1117 template <int8_t NI, int8_t NF>
1118 constexpr SFix<NI, NF> operator*(int32_t op, const SFix<NI, NF>& uf) {return uf*op;}
1120 template <int8_t NI, int8_t NF>
1121 constexpr SFix<NI, NF> operator*(int64_t op, const SFix<NI, NF>& uf) {return uf*op;}
1123 template <int8_t NI, int8_t NF>
1124 constexpr SFix<NI, NF> operator*(float op, const SFix<NI, NF>& uf) {return uf*op;}
1126 template <int8_t NI, int8_t NF>
1127 constexpr SFix<NI, NF> operator*(double op, const SFix<NI, NF>& uf) {return uf*op;}
1130 template <int8_t NI, int8_t NF>
1131 constexpr SFix<NI, NF> operator+(uint8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1133 template <int8_t NI, int8_t NF>
1134 constexpr SFix<NI, NF> operator+(uint16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1136 template <int8_t NI, int8_t NF>
1137 constexpr SFix<NI, NF> operator+(uint32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1139 template <int8_t NI, int8_t NF>
1140 constexpr SFix<NI, NF> operator+(uint64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1142 template <int8_t NI, int8_t NF>
1143 constexpr SFix<NI, NF> operator+(int8_t op, const SFix<NI, NF>& uf) {return uf+op;}
1145 template <int8_t NI, int8_t NF>
1146 constexpr SFix<NI, NF> operator+(int16_t op, const SFix<NI, NF>& uf) {return uf+op;}
1148 template <int8_t NI, int8_t NF>
1149 constexpr SFix<NI, NF> operator+(int32_t op, const SFix<NI, NF>& uf) {return uf+op;}
1151 template <int8_t NI, int8_t NF>
1152 constexpr SFix<NI, NF> operator+(int64_t op, const SFix<NI, NF>& uf) {return uf+op;}
1154 template <int8_t NI, int8_t NF>
1155 constexpr SFix<NI, NF> operator+(float op, const SFix<NI, NF>& uf) {return uf+op;}
1157 template <int8_t NI, int8_t NF>
1158 constexpr SFix<NI, NF> operator+(double op, const SFix<NI, NF>& uf) {return uf+op;}
1161 template <int8_t NI, int8_t NF>
1162 constexpr SFix<NI, NF> operator-(uint8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1164 template <int8_t NI, int8_t NF>
1165 constexpr SFix<NI, NF> operator-(uint16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1167 template <int8_t NI, int8_t NF>
1168 constexpr SFix<NI, NF> operator-(uint32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1170 template <int8_t NI, int8_t NF>
1171 constexpr SFix<NI, NF> operator-(uint64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1173 template <int8_t NI, int8_t NF>
1174 constexpr SFix<NI, NF> operator-(int8_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1176 template <int8_t NI, int8_t NF>
1177 constexpr SFix<NI, NF> operator-(int16_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1179 template <int8_t NI, int8_t NF>
1180 constexpr SFix<NI, NF> operator-(int32_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1182 template <int8_t NI, int8_t NF>
1183 constexpr SFix<NI, NF> operator-(int64_t op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1185 template <int8_t NI, int8_t NF>
1186 constexpr SFix<NI, NF> operator-(float op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1188 template <int8_t NI, int8_t NF>
1189 constexpr SFix<NI, NF> operator-(double op, const SFix<NI, NF>& uf) {return (-uf)+op;}
1197 // Comparison between SFix and UFix
1204 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1205 constexpr bool operator> (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1207 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1208 return worktype(op1).asRaw() > worktype(op2).asRaw();
1216 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1217 constexpr bool operator> (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1219 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1220 return worktype(op1).asRaw() > worktype(op2).asRaw();
1228 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1229 constexpr bool operator< (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1240 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1241 constexpr bool operator< (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1252 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1253 constexpr bool operator== (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2)
1255 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> worktype;
1256 return (worktype(op1).asRaw() == worktype(op2).asRaw());
1265 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1266 constexpr bool operator== (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1276 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1277 constexpr bool operator!= (const SFix<NI,NF>& op1, const UFix<_NI,_NF>& op2 )
1279 return !(op1 == op2);
1288 template<int8_t NI, int8_t NF, int8_t _NI, int8_t _NF>
1289 constexpr bool operator!= (const UFix<NI,NF>& op1, const SFix<_NI,_NF>& op2 )
1291 typedef SFix<FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF)> comptype;
1292 return (comptype(op1).asRaw() != comptype(op2).asRaw());;
1309 template<typename T>
1310 constexpr SFix<0, sizeof(T)*8-1> toSFraction(T val) {
1311 return SFix<0, sizeof(T)*8-1>::fromRaw(val);
1324 template<typename T>
1325 constexpr SFix<sizeof(T)*8-1,0> toSInt(T val) {
1326 return SFix<sizeof(T)*8-1,0>::fromRaw(val);
1331 #include "FixMath_Autotests.h
"
Definition: FixMath.h:714
constexpr internal_type asRaw() const
Definition: FixMath.h:1063
Definition: FixMath.h:156
constexpr SFix< NI, NF, RANGE > operator-() const
Definition: FixMath.h:303
constexpr internal_type asRaw() const
Definition: FixMath.h:534
constexpr UFix(float fl)
Definition: FixMath.h:170
constexpr UFix(double fl)
Definition: FixMath.h:176
constexpr UFix< NI+_NI, NF+_NF, RANGE *_RANGE >::UFixNIadj_t operator*(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:315
constexpr UFix(T value, bool as_raw=false)
Definition: FixMath.h:187
constexpr UFix()
Definition: FixMath.h:164
constexpr UFix< NF, NI > invFast() const
Definition: FixMath.h:353
static constexpr UFix< NI, NF > fromRaw(T raw)
Definition: FixMath.h:195
constexpr UFix(const UFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:206
constexpr UFix< FixMathPrivate::FM_max(NI, _NI), FixMathPrivate::FM_max(NF, _NF), FixMathPrivate::rangeAdd(NF, _NF, RANGE, _RANGE)>::UFixNIadj_t operator+(const UFix< _NI, _NF, _RANGE > &op) const
Definition: FixMath.h:225
constexpr UFix(const SFix< _NI, _NF, _RANGE > &uf)
Definition: FixMath.h:215
Definition: FixMath.h:127
Definition: IntegerType.h:9