36 #ifndef VIGRA_FIXEDPOINT_HXX
37 #define VIGRA_FIXEDPOINT_HXX
39 #include "mathutil.hxx"
40 #include "static_assert.hxx"
42 #include "numerictraits.hxx"
46 template <
unsigned IntBits,
unsigned FractionalBits>
49 struct Error_FixedPointTraits_not_specialized_for_this_case;
51 template <
class T1,
class T2>
52 class FixedPointTraits
55 typedef Error_FixedPointTraits_not_specialized_for_this_case PlusType;
56 typedef Error_FixedPointTraits_not_specialized_for_this_case MinusType;
57 typedef Error_FixedPointTraits_not_specialized_for_this_case MultipliesType;
65 template <
unsigned IntBits1,
unsigned FracBits1,
unsigned IntBits2,
unsigned FracBits2>
68 enum { MaxIntBits = (IntBits1 < IntBits2) ? IntBits2 : IntBits1,
69 MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1,
70 PlusMinusIntBits = (MaxIntBits + 1 + MaxFracBits < 32) ?
71 MaxIntBits + 1 : MaxIntBits,
72 MultipliesFracBits = (IntBits1 + IntBits2 < 31)
73 ? (FracBits1 + FracBits2) > (31 - IntBits1 - IntBits2)
74 ? 31 - IntBits1 - IntBits2
75 : FracBits1 + FracBits2
79 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> PlusType;
80 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> MinusType;
81 typedef FixedPoint<IntBits1 + IntBits2, MultipliesFracBits> MultipliesType;
85 template <
unsigned IntBits,
unsigned FracBits>
86 struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
88 enum { SRTotalBits = (IntBits + FracBits + 1) / 2,
89 SRIntBits = (IntBits + 1) / 2,
90 SRFracBits = SRTotalBits - SRIntBits
93 typedef FixedPoint<IntBits, FracBits> Type;
94 typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
95 typedef Type SquareRootArgument;
102 struct FixedPoint_overflow_error__More_than_31_bits_requested
103 : staticAssert::AssertBool<(N < 32)>
110 template <bool Predicate>
111 struct FixedPoint_assignment_error__Target_object_has_too_few_integer_bits
112 : staticAssert::AssertBool<Predicate>
115 enum FixedPointNoShift { FPNoShift };
119 template <bool MustRound>
120 struct FPAssignWithRound;
123 struct FPAssignWithRound<false>
126 static inline int exec(int v) { return v << (-N); }
130 struct FPAssignWithRound<true>
133 static inline int exec(int const v)
135 return (v + (1 << (N - 1))) >> (N);
139 template <bool MustRound>
140 struct FPMulImplementation;
143 struct FPMulImplementation<false>
146 static inline int exec(int l, int r) { return (l * r) << (-N); }
150 struct FPMulImplementation<true>
153 static inline int exec(int l, int r)
157 enum { diffl = N / 2, diffr = N - diffl, maskl = (1 << diffl) - 1, maskr = (1 << diffr) - 1 };
158 int shiftl = l >> diffl;
159 int shiftr = r >> diffr;
161 return shiftl * shiftr + (((l & maskl) * shiftr) >> diffl) +
162 (((r & maskr) * shiftl) >> diffr);
216 template <unsigned IntBits, unsigned FractionalBits>
222 FRACTIONAL_BITS = FractionalBits,
223 TOTAL_BITS = IntBits + FractionalBits,
224 MAX = (int)(((unsigned)1 << TOTAL_BITS) - 1),
225 ONE = 1 << FractionalBits,
227 FRACTIONAL_MASK = ONE - 1,
228 INT_MASK = MAX ^ FRACTIONAL_MASK
235 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
240 explicit FixedPoint(int v)
241 : value(v << FractionalBits)
243 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
248 FixedPoint(int v, FixedPointNoShift)
251 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
258 explicit FixedPoint(double rhs)
259 : value((int)round(rhs * ONE))
261 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
262 vigra_precondition(abs(rhs * ONE) <= (double)MAX,
263 "FixedPoint(double rhs): Too few integer bits to convert rhs.");
268 FixedPoint(const FixedPoint &other)
275 template <unsigned Int2, unsigned Frac2>
276 FixedPoint(const FixedPoint<Int2, Frac2> &other)
277 : value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<int(Frac2) - int(FractionalBits)>(other.value))
279 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
280 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
287 FixedPoint &operator=(int rhs)
289 vigra_precondition(abs(rhs) < (1 << IntBits),
290 "FixedPoint::operator=(int rhs): Too few integer bits to represent rhs.");
291 value = rhs << FractionalBits;
299 FixedPoint &operator=(double rhs)
301 vigra_precondition(abs(rhs) <= ((1 << IntBits) - 1),
302 "FixedPoint::operator=(double rhs): Too few integer bits to convert rhs.");
303 value = (int)round(rhs * ONE);
309 FixedPoint & operator=(const FixedPoint &other)
318 template <unsigned Int2, unsigned Frac2>
319 FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other)
321 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
322 value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<int(Frac2) - int(FractionalBits)>(other.value);
328 FixedPoint operator-() const
330 return FixedPoint(-value, FPNoShift);
335 FixedPoint & operator++()
343 FixedPoint operator++(int)
345 FixedPoint old(*this);
352 FixedPoint & operator--()
360 FixedPoint operator--(int)
362 FixedPoint old(*this);
370 template <unsigned Int2, unsigned Frac2>
371 FixedPoint & operator+=(const FixedPoint<Int2, Frac2> &other)
373 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
374 value += detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
381 template <unsigned Int2, unsigned Frac2>
382 FixedPoint & operator-=(const FixedPoint<Int2, Frac2> &other)
384 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
385 value -= detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
392 template <unsigned Int2, unsigned Frac2>
393 FixedPoint & operator*=(const FixedPoint<Int2, Frac2> &other)
395 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
396 value = detail::FPMulImplementation<(Frac2 > 0)>::template exec<Frac2>(value, other.value);
401 #define VIGRA_FIXED_POINT_FACTORY(T, INTBITS) \
402 inline FixedPoint<INTBITS, 0> fixedPoint(T t) \
404 return FixedPoint<INTBITS, 0>(t, FPNoShift); \
407 VIGRA_FIXED_POINT_FACTORY(unsigned char, 8)
408 VIGRA_FIXED_POINT_FACTORY(signed char, 7)
409 VIGRA_FIXED_POINT_FACTORY(unsigned short, 16)
410 VIGRA_FIXED_POINT_FACTORY(signed short, 15)
411 VIGRA_FIXED_POINT_FACTORY(int, 31)
413 #undef VIGRA_FIXED_POINT_FACTORY
416 struct FixedPointCast;
418 #define VIGRA_FIXED_POINT_CAST(type) \
420 struct FixedPointCast<type> \
422 template <unsigned IntBits, unsigned FracBits> \
423 static type cast(FixedPoint<IntBits, FracBits> v) \
429 VIGRA_FIXED_POINT_CAST(Int8)
430 VIGRA_FIXED_POINT_CAST(UInt8)
431 VIGRA_FIXED_POINT_CAST(Int16)
432 VIGRA_FIXED_POINT_CAST(UInt16)
433 VIGRA_FIXED_POINT_CAST(Int32)
434 VIGRA_FIXED_POINT_CAST(UInt32)
436 #undef VIGRA_FIXED_POINT_CAST
439 struct FixedPointCast<float>
441 template <unsigned IntBits, unsigned FracBits>
442 static float cast(FixedPoint<IntBits, FracBits> v)
444 return (float)v.value / FixedPoint<IntBits, FracBits>::ONE;
449 struct FixedPointCast<double>
451 template <unsigned IntBits, unsigned FracBits>
452 static double cast(FixedPoint<IntBits, FracBits> v)
454 return (double)v.value / FixedPoint<IntBits, FracBits>::ONE;
485 template <class TARGET, unsigned IntBits, unsigned FracBits>
486 TARGET fixed_point_cast(FixedPoint<IntBits, FracBits> v)
488 return FixedPointCast<TARGET>::cast(v);
492 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
494 bool operator==(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
496 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
497 return (l.value << (MaxFracBits - FracBits1)) == (r.value << (MaxFracBits - FracBits2));
501 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
503 bool operator!=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
505 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
506 return (l.value << (MaxFracBits - FracBits1)) != (r.value << (MaxFracBits - FracBits2));
510 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
512 bool operator<(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
514 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
515 return (l.value << (MaxFracBits - FracBits1)) < (r.value << (MaxFracBits - FracBits2));
519 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
521 bool operator<=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
523 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
524 return (l.value << (MaxFracBits - FracBits1)) <= (r.value << (MaxFracBits - FracBits2));
528 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
530 bool operator>(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
532 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
533 return (l.value << (MaxFracBits - FracBits1)) > (r.value << (MaxFracBits - FracBits2));
537 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
539 bool operator>=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
541 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
542 return (l.value << (MaxFracBits - FracBits1)) >= (r.value << (MaxFracBits - FracBits2));
546 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
548 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
549 operator+(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
551 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
553 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
554 PlusType((l.value << (MaxFracBits - FracBits1)) + (r.value << (MaxFracBits - FracBits2)), FPNoShift);
558 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
559 unsigned IntBits3, unsigned FracBits3>
561 add(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
562 FixedPoint<IntBits3, FracBits3> & result)
568 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
570 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MinusType
571 operator-(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
573 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
575 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
576 MinusType((l.value << (MaxFracBits - FracBits1)) - (r.value << (MaxFracBits - FracBits2)), FPNoShift);
580 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
581 unsigned IntBits3, unsigned FracBits3>
583 sub(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
584 FixedPoint<IntBits3, FracBits3> & result)
590 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
592 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MultipliesType
593 operator*(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
595 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
602 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
603 unsigned IntBits3, unsigned FracBits3>
605 mul(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
606 FixedPoint<IntBits3, FracBits3> & result)
608 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits1 + IntBits2 <= IntBits3)>));
609 enum { diff = FracBits1 + FracBits2 - FracBits3 };
610 result.value = detail::FPMulImplementation<(diff > 0)>::template exec<diff>(l.value, r.value);
614 template <unsigned IntBits, unsigned FracBits>
615 inline typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult
616 sqrt(FixedPoint<IntBits, FracBits> v)
618 return typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult(sqrti(v.value), FPNoShift);
622 template <unsigned IntBits, unsigned FracBits>
623 inline FixedPoint<IntBits, FracBits>
624 abs(FixedPoint<IntBits, FracBits> v)
626 return FixedPoint<IntBits, FracBits>(abs(v.value), FPNoShift);
630 template <unsigned IntBits, unsigned FracBits>
632 typename FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
633 squaredNorm(FixedPoint<IntBits, FracBits> v)
639 template <unsigned IntBits, unsigned FracBits>
641 FixedPoint<IntBits, FracBits>
642 norm(FixedPoint<IntBits, FracBits> const & v)
648 template <unsigned IntBits, unsigned FracBits>
649 inline FixedPoint<0, FracBits>
650 frac(FixedPoint<IntBits, FracBits> v)
652 return FixedPoint<0, FracBits>(v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK, FPNoShift);
656 template <unsigned IntBits, unsigned FracBits>
657 inline FixedPoint<0, FracBits>
658 dual_frac(FixedPoint<IntBits, FracBits> v)
660 return FixedPoint<0, FracBits>(FixedPoint<0, FracBits>::ONE -
661 (v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK), FPNoShift);
665 template <unsigned IntBits, unsigned FracBits>
667 floor(FixedPoint<IntBits, FracBits> v)
669 return(v.value >> FracBits);
673 template <unsigned IntBits, unsigned FracBits>
675 ceil(FixedPoint<IntBits, FracBits> v)
677 return((v.value + FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK) >> FracBits);
681 template <unsigned IntBits, unsigned FracBits>
683 round(FixedPoint<IntBits, FracBits> v)
685 return((v.value + FixedPoint<IntBits, FracBits>::ONE_HALF) >> FracBits);
763 template <unsigned IntBits, unsigned FracBits>
764 struct NumericTraits<FixedPoint<IntBits, FracBits> >
766 typedef FixedPoint<IntBits, FracBits> Type;
770 typedef Type ValueType;
772 typedef VigraFalseType isIntegral;
773 typedef VigraTrueType isScalar;
774 typedef VigraTrueType isSigned;
775 typedef VigraTrueType isOrdered;
776 typedef VigraFalseType isComplex;
778 static Type zero() { return Type(0, FPNoShift); }
779 static Type one() { return Type(Type::ONE, FPNoShift); }
780 static Type nonZero() { return one(); }
781 static Type epsilon() { return Type(1, FPNoShift); }
782 static Type smallestPositive() { return Type(1, FPNoShift); }
783 static Type max() { return Type( Type::MAX, FPNoShift); }
784 static Type min() { return -max(); }
787 template <unsigned IntBits, unsigned FracBits>
788 struct NormTraits<FixedPoint<IntBits, FracBits> >
790 typedef FixedPoint<IntBits, FracBits> Type;
792 FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
794 typedef Type NormType;
797 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
798 struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
799 FixedPoint<IntBits2, FracBits2> >
802 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
808 enum FPOverflowHandling { FPOverflowIgnore, FPOverflowSaturate, FPOverflowError };
810 template <int IntBits, FPOverflowHandling OverflowHandling = FPOverflowIgnore>
874 template <int IntBits, FPOverflowHandling OverflowHandling>
875 struct NumericTraits<FixedPoint16<IntBits, OverflowHandling> >
877 typedef FixedPoint16<IntBits, OverflowHandling> Type;
878 typedef Type Promote;
881 typedef Type ValueType;
883 typedef VigraFalseType isIntegral;
884 typedef VigraTrueType isScalar;
885 typedef VigraTrueType isSigned;
886 typedef VigraTrueType isOrdered;
887 typedef VigraFalseType isComplex;
889 static Type zero() { return Type(0, FPNoShift); }
890 static Type one() { return Type(Type::ONE, FPNoShift); }
891 static Type nonZero() { return one(); }
892 static Type epsilon() { return Type(1, FPNoShift); }
893 static Type smallestPositive() { return Type(1, FPNoShift); }
894 static Type max() { return Type( Type::MAX, FPNoShift); }
895 static Type min() { return Type( Type::MIN, FPNoShift); }
897 static Promote toPromote(Type v) { return v; }
898 static Type fromPromote(Promote v) { return v; };
901 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
902 struct PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>,
903 FixedPoint16<IntBits2, OverflowHandling> >
905 typedef FixedPoint16<MetaMax<IntBits1, IntBits2>::value, OverflowHandling> Promote;
906 static Promote toPromote(FixedPoint16<IntBits1, OverflowHandling> v) { return Promote(v); }
907 static Promote toPromote(FixedPoint16<IntBits2, OverflowHandling> v) { return Promote(v); }
910 template <int IntBits, FPOverflowHandling OverflowHandling>
911 struct PromoteTraits<FixedPoint16<IntBits, OverflowHandling>,
912 FixedPoint16<IntBits, OverflowHandling> >
914 typedef FixedPoint16<IntBits, OverflowHandling> Promote;
915 static Promote toPromote(FixedPoint16<IntBits, OverflowHandling> v) { return v; }
918 template <int IntBits, FPOverflowHandling OverflowHandling>
919 struct NormTraits<FixedPoint16<IntBits, OverflowHandling> >
921 typedef FixedPoint16<IntBits, OverflowHandling> Type;
922 typedef typename PromoteTraits<Type, Type>::Promote SquaredNormType;
923 typedef Type NormType;
926 template <int IntBits, FPOverflowHandling OverflowHandling>
927 struct SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >
929 typedef FixedPoint16<IntBits, OverflowHandling> Type;
930 typedef FixedPoint16<(IntBits + 1) / 2, OverflowHandling> SquareRootResult;
931 typedef Type SquareRootArgument;
936 template <bool Compatible>
937 struct FixedPoint_error__Right_shift_operator_has_unsupported_semantics
938 : staticAssert::AssertBool<Compatible>
943 template <bool Predicate>
944 struct FixedPoint16_assignment_error__Target_object_has_too_few_integer_bits
945 : staticAssert::AssertBool<Predicate>
950 template<int BeforeIntBits, int AfterIntBits,
952 bool RightShift = (AfterIntBits >= BeforeIntBits)>
955 template<int BeforeIntBits>
956 struct FP16Align<BeforeIntBits, BeforeIntBits, true, true>
958 static inline Int32 exec(Int32 v)
964 template<int BeforeIntBits>
965 struct FP16Align<BeforeIntBits, BeforeIntBits, false, true>
967 static inline Int32 exec(Int32 v)
973 template<int BeforeIntBits, int AfterIntBits>
974 struct FP16Align<BeforeIntBits, AfterIntBits, false, true>
976 static inline Int32 exec(Int32 v)
978 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
979 return v >> (AfterIntBits - BeforeIntBits);
983 template<int BeforeIntBits, int AfterIntBits>
984 struct FP16Align<BeforeIntBits, AfterIntBits, true, true>
986 enum { ONE_HALF = 1 << (AfterIntBits - BeforeIntBits - 1) };
987 static inline Int32 exec(Int32 v)
989 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
990 return (v + ONE_HALF) >> (AfterIntBits - BeforeIntBits);
994 template<int BeforeIntBits, int AfterIntBits, bool Round>
995 struct FP16Align<BeforeIntBits, AfterIntBits, Round, false>
997 static inline Int32 exec(Int32 v)
999 return v << (BeforeIntBits - AfterIntBits);
1003 template <FPOverflowHandling OverflowHandling = FPOverflowIgnore>
1004 struct FP16OverflowHandling
1006 static inline Int32 exec(Int32 v)
1011 static inline Int32 exec(UInt32 v)
1018 struct FP16OverflowHandling<FPOverflowSaturate>
1020 static inline Int32 exec(Int32 v)
1023 return (1 << 15) - 1;
1028 static inline Int32 exec(UInt32 v)
1031 return (1 << 15) - 1;
1037 struct FP16OverflowHandling<FPOverflowError>
1039 static inline Int32 exec(Int32 v)
1041 vigra_precondition(v < (1 << 15) && v >= -(1 << 15),
1042 "FixedPoint16: Operation overflows.");
1045 static inline Int32 exec(UInt32 v)
1047 vigra_precondition(v < (1 << 15),
1048 "FixedPoint16: Operation overflows.");
1054 template <int IntBits1, int IntBits2, int IntBitsOut,
1055 FPOverflowHandling OverflowHandling >
1058 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1059 static inline Int32 exec(Int32 t1, Int32 t2)
1061 return FP16OverflowHandling<OverflowHandling>::exec(
1062 FP16Align<MinIntBits, IntBitsOut, true>::exec(
1063 FP16Align<IntBits1, MinIntBits, false>::exec(t1) +
1064 FP16Align<IntBits2, MinIntBits, false>::exec(t2)));
1068 template <int IntBits1, int IntBits2, int IntBitsOut,
1069 FPOverflowHandling OverflowHandling >
1072 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1073 static inline Int32 exec(Int32 t1, Int32 t2)
1075 return FP16OverflowHandling<OverflowHandling>::exec(
1076 FP16Align<MinIntBits, IntBitsOut, true>::exec(
1077 FP16Align<IntBits1, MinIntBits, false>::exec(t1) -
1078 FP16Align<IntBits2, MinIntBits, false>::exec(t2)));
1082 template <int IntBits1, int IntBits2, int IntBitsOut,
1083 FPOverflowHandling OverflowHandling >
1086 static inline Int32 exec(Int32 t1, Int32 t2)
1088 return FP16OverflowHandling<OverflowHandling>::exec(
1089 FP16Align<IntBits1+IntBits2, IntBitsOut+15, true>::exec(t1*t2));
1093 template <int IntBits1, int IntBits2, int IntBitsOut,
1094 FPOverflowHandling OverflowHandling >
1097 static inline Int32 exec(Int32 t1, Int32 t2)
1103 return FP16OverflowHandling<OverflowHandling>::exec(
1104 FP16Align<IntBits1-IntBits2, IntBitsOut+1, true>::exec((t1<<16)/t2));
1116 template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1117 TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v);
1173 template <int IntBits, FPOverflowHandling OverflowHandling>
1177 static const Int32 TOTAL_BITS = 15;
1178 static const Int32 INT_BITS = IntBits;
1179 static const Int32 FRACTIONAL_BITS = TOTAL_BITS - INT_BITS;
1180 static const Int32 MAX = (Int32)((1u << TOTAL_BITS) - 1);
1181 static const Int32 MIN = -(Int32)(1u << TOTAL_BITS);
1182 static const Int32 ONE = 1 << FRACTIONAL_BITS;
1183 static const Int32 ONE_HALF = ONE >> 1;
1184 static const Int32 FRACTIONAL_MASK = (1u << FRACTIONAL_BITS) - 1;
1185 static const Int32 INT_MASK = 0xffffffffu ^ FRACTIONAL_MASK;
1187 static const FixedPoint16 zero, pi, pi_2, mpi_2;
1194 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1200 explicit FixedPoint16(Int32 v)
1201 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v << FRACTIONAL_BITS))
1203 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1208 FixedPoint16(Int32 v, FixedPointNoShift)
1209 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v))
1211 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1218 explicit FixedPoint16(double rhs)
1219 : value(detail::FP16OverflowHandling<OverflowHandling>::exec((Int32)roundi(rhs * ONE)))
1221 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1226 FixedPoint16(const FixedPoint16 &other)
1227 : value(other.value)
1229 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1235 template <int IntBits2, FPOverflowHandling OverflowHandling2>
1236 FixedPoint16(const FixedPoint16<IntBits2, OverflowHandling2> &other)
1237 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(
1238 detail::FP16Align<IntBits2, IntBits, true>::exec(other.value)))
1240 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1246 FixedPoint16 &operator=(Int32 rhs)
1248 value = detail::FP16OverflowHandling<OverflowHandling>::exec(rhs << FRACTIONAL_BITS);
1255 FixedPoint16 &operator=(double rhs)
1257 value = detail::FP16OverflowHandling<OverflowHandling>::exec(roundi(rhs * ONE));
1263 FixedPoint16 & operator=(const FixedPoint16 &other)
1265 value = other.value;
1272 template <int IntBits2>
1273 FixedPoint16 & operator=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1275 value = detail::FP16OverflowHandling<OverflowHandling>::exec(
1276 detail::FP16Align<IntBits2, IntBits, true>::exec(other.value));
1282 operator float() const
1284 return fixed_point_cast<float>(*this);
1289 operator double() const
1291 return fixed_point_cast<double>(*this);
1296 FixedPoint16 operator+() const
1303 FixedPoint16 operator-() const
1305 return FixedPoint16(-value, FPNoShift);
1310 FixedPoint16 & operator++()
1312 value = detail::FP16OverflowHandling<OverflowHandling>::exec(value+ONE);
1318 FixedPoint16 operator++(int)
1320 FixedPoint16 old(*this);
1327 FixedPoint16 & operator--()
1329 value = detail::FP16OverflowHandling<OverflowHandling>::exec(value-ONE);
1335 FixedPoint16 operator--(int)
1337 FixedPoint16 old(*this);
1345 template <int IntBits2>
1346 FixedPoint16 & operator+=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1348 value = detail::FP16AddImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1355 template <int IntBits2>
1356 FixedPoint16 & operator-=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1358 value = detail::FP16SubImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1365 template <int IntBits2>
1366 FixedPoint16 & operator*=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1368 value = detail::FP16MulImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1375 template <int IntBits2>
1376 FixedPoint16 & operator/=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1378 value = detail::FP16DivImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1383 template <int IntBits, FPOverflowHandling OverflowHandling>
1384 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::zero(0);
1386 template <int IntBits, FPOverflowHandling OverflowHandling>
1387 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi(M_PI);
1389 template <int IntBits, FPOverflowHandling OverflowHandling>
1390 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi_2(0.5 * M_PI);
1392 template <int IntBits, FPOverflowHandling OverflowHandling>
1393 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::mpi_2(-0.5 * M_PI);
1398 struct FixedPoint16Cast;
1400 #define VIGRA_FIXED_POINT_CAST(type) \
1402 struct FixedPoint16Cast<type> \
1404 template <int IntBits, FPOverflowHandling OverflowHandling> \
1405 static type cast(FixedPoint16<IntBits, OverflowHandling> v) \
1411 VIGRA_FIXED_POINT_CAST(Int8)
1412 VIGRA_FIXED_POINT_CAST(UInt8)
1413 VIGRA_FIXED_POINT_CAST(Int16)
1414 VIGRA_FIXED_POINT_CAST(UInt16)
1415 VIGRA_FIXED_POINT_CAST(Int32)
1416 VIGRA_FIXED_POINT_CAST(UInt32)
1417 VIGRA_FIXED_POINT_CAST(Int64)
1418 VIGRA_FIXED_POINT_CAST(UInt64)
1420 #undef VIGRA_FIXED_POINT_CAST
1423 struct FixedPoint16Cast<float>
1425 template <int IntBits, FPOverflowHandling OverflowHandling>
1426 static float cast(FixedPoint16<IntBits, OverflowHandling> v)
1428 return (float)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1433 struct FixedPoint16Cast<double>
1435 template <int IntBits, FPOverflowHandling OverflowHandling>
1436 static double cast(FixedPoint16<IntBits, OverflowHandling> v)
1438 return (double)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1471 template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1472 TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v)
1474 return detail::FixedPoint16Cast<TARGET>::cast(v);
1479 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1481 bool operator==(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1483 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1484 return (l.value << (IntBits1 - MinIntBits)) == (r.value << (IntBits2 - MinIntBits));
1488 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1490 bool operator!=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1492 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1493 return (l.value << (IntBits1 - MinIntBits)) != (r.value << (IntBits2 - MinIntBits));
1497 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1499 bool operator<(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1501 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1502 return (l.value << (IntBits1 - MinIntBits)) < (r.value << (IntBits2 - MinIntBits));
1506 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1508 bool operator<=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1510 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1511 return (l.value << (IntBits1 - MinIntBits)) <= (r.value << (IntBits2 - MinIntBits));
1515 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1517 bool operator>(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1519 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1520 return (l.value << (IntBits1 - MinIntBits)) > (r.value << (IntBits2 - MinIntBits));
1524 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1526 bool operator>=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1528 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1529 return (l.value << (IntBits1 - MinIntBits)) >= (r.value << (IntBits2 - MinIntBits));
1533 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1535 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1536 operator+(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1539 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1541 return Result(detail::FP16AddImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1545 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1547 FixedPoint16<IntBits3, OverflowHandling> &
1548 add(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1549 FixedPoint16<IntBits3, OverflowHandling> & result)
1551 result.value = detail::FP16AddImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1556 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1558 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1559 operator-(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1562 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1564 return Result(detail::FP16SubImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1568 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1569 inline FixedPoint16<IntBits3, OverflowHandling> &
1570 sub(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1571 FixedPoint16<IntBits3, OverflowHandling> & result)
1573 result.value = detail::FP16SubImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1578 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1580 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1581 operator*(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1584 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1586 return Result(detail::FP16MulImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1590 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1592 FixedPoint16<IntBits3, OverflowHandling> &
1593 mul(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1594 FixedPoint16<IntBits3, OverflowHandling> & result)
1596 result.value = detail::FP16MulImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1601 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1603 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1604 operator/(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1607 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1609 return Result(detail::FP16DivImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1613 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1615 FixedPoint16<IntBits3, OverflowHandling> &
1616 div(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1617 FixedPoint16<IntBits3, OverflowHandling> & result)
1619 result.value = detail::FP16DivImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1624 template <int IntBits, FPOverflowHandling OverflowHandling>
1625 inline typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult
1626 sqrt(FixedPoint16<IntBits, OverflowHandling> v)
1628 typedef typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult Result;
1629 enum { Shift = 15 + IntBits - 2*Result::INT_BITS };
1630 return Result(sqrti(v.value << Shift), FPNoShift);
1633 #ifndef VIGRA_NO_HYPOT
1638 template <int IntBits, FPOverflowHandling OverflowHandling>
1639 inline FixedPoint16<IntBits, OverflowHandling>
1640 hypot(FixedPoint16<IntBits, OverflowHandling> v1, FixedPoint16<IntBits, OverflowHandling> v2)
1642 UInt32 l = abs(v1.value), r = abs(v2.value);
1644 return FixedPoint16<IntBits, OverflowHandling>(
1645 detail::FP16OverflowHandling<OverflowHandling>::exec(sqrti(sq(l) + sq(r))),
1652 template <int IntBits, FPOverflowHandling OverflowHandling>
1653 FixedPoint16<2, OverflowHandling>
1654 atan2(FixedPoint16<IntBits, OverflowHandling> y, FixedPoint16<IntBits, OverflowHandling> x)
1656 enum { ResIntBits = 2 };
1657 typedef FixedPoint16<ResIntBits, OverflowHandling> FP;
1658 static const Int32 Pi_4 = 25736,
1670 return (y.value > 0)
1676 Int32 abs_y = abs(y.value);
1682 r = ((x.value - abs_y) << 15) / (x.value + abs_y);
1689 r = ((x.value + abs_y) << 15) / (abs_y - x.value);
1693 angle += r*((c2 + c1 * (sq(r) >> 15)) >> 15) >> 15;
1695 return (y.value > 0)
1696 ? FP(detail::FP16Align<0, ResIntBits, true>::exec( angle), FPNoShift)
1697 : FP(detail::FP16Align<0, ResIntBits, true>::exec(-angle), FPNoShift);
1701 template <int IntBits, FPOverflowHandling OverflowHandling>
1702 inline FixedPoint16<IntBits, OverflowHandling>
1703 abs(FixedPoint16<IntBits, OverflowHandling> v)
1705 return FixedPoint16<IntBits, OverflowHandling>(abs(v.value), FPNoShift);
1709 template <int IntBits, FPOverflowHandling OverflowHandling>
1711 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::SquaredNormType
1712 squaredNorm(FixedPoint16<IntBits, OverflowHandling> v)
1718 template <int IntBits, FPOverflowHandling OverflowHandling>
1720 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::NormType
1721 norm(FixedPoint16<IntBits, OverflowHandling> const & v)
1727 template <int IntBits, FPOverflowHandling OverflowHandling>
1728 inline FixedPoint16<IntBits, OverflowHandling>
1729 frac(FixedPoint16<IntBits, OverflowHandling> v)
1731 return FixedPoint16<IntBits, OverflowHandling>(
1732 v.value - (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1737 template <int IntBits, FPOverflowHandling OverflowHandling>
1738 inline FixedPoint16<IntBits, OverflowHandling>
1739 dual_frac(FixedPoint16<IntBits, OverflowHandling> v)
1741 return FixedPoint16<IntBits, OverflowHandling>(
1742 FixedPoint16<IntBits, OverflowHandling>::ONE - v.value + (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1747 template <int IntBits, FPOverflowHandling OverflowHandling>
1749 floor(FixedPoint16<IntBits, OverflowHandling> v)
1751 return(v.value >> FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1755 template <int IntBits, FPOverflowHandling OverflowHandling>
1757 ceil(FixedPoint16<IntBits, OverflowHandling> v)
1759 return((v.value + FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_MASK) >>
1760 FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1764 template <int IntBits, FPOverflowHandling OverflowHandling>
1766 round(FixedPoint16<IntBits, OverflowHandling> v)
1768 return((v.value + FixedPoint16<IntBits, OverflowHandling>::ONE_HALF) >>
1769 FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1773 template <int IntBits, FPOverflowHandling OverflowHandling>
1775 roundi(FixedPoint16<IntBits, OverflowHandling> v)
1786 template <int IntBits, vigra::FPOverflowHandling OverflowHandling>
1787 ostream & operator<<(ostream & s, vigra::FixedPoint16<IntBits, OverflowHandling> v)
1789 s << vigra::fixed_point_cast<float>(v);
Definition: fixedpoint.hxx:47