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>
66 class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, 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<Frac2 - 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<Frac2 - 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;
1192 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1198 explicit FixedPoint16(Int32 v)
1199 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v << FRACTIONAL_BITS))
1201 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1206 FixedPoint16(Int32 v, FixedPointNoShift)
1207 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v))
1209 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1216 explicit FixedPoint16(double rhs)
1217 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(roundi(rhs * ONE)))
1219 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1224 FixedPoint16(const FixedPoint16 &other)
1225 : value(other.value)
1227 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1233 template <int IntBits2, FPOverflowHandling OverflowHandling2>
1234 FixedPoint16(const FixedPoint16<IntBits2, OverflowHandling2> &other)
1235 : value(detail::FP16OverflowHandling<OverflowHandling>::exec(
1236 detail::FP16Align<IntBits2, IntBits, true>::exec(other.value)))
1238 VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1244 FixedPoint16 &operator=(Int32 rhs)
1246 value = detail::FP16OverflowHandling<OverflowHandling>::exec(rhs << FRACTIONAL_BITS);
1253 FixedPoint16 &operator=(double rhs)
1255 value = detail::FP16OverflowHandling<OverflowHandling>::exec(roundi(rhs * ONE));
1261 FixedPoint16 & operator=(const FixedPoint16 &other)
1263 value = other.value;
1270 template <int IntBits2>
1271 FixedPoint16 & operator=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1273 value = detail::FP16OverflowHandling<OverflowHandling>::exec(
1274 detail::FP16Align<IntBits2, IntBits, true>::exec(other.value));
1280 operator float() const
1282 return fixed_point_cast<float>(*this);
1287 operator double() const
1289 return fixed_point_cast<double>(*this);
1294 FixedPoint16 operator+() const
1301 FixedPoint16 operator-() const
1303 return FixedPoint16(-value, FPNoShift);
1308 FixedPoint16 & operator++()
1310 value = detail::FP16OverflowHandling<OverflowHandling>::exec(value+ONE);
1316 FixedPoint16 operator++(int)
1318 FixedPoint16 old(*this);
1325 FixedPoint16 & operator--()
1327 value = detail::FP16OverflowHandling<OverflowHandling>::exec(value-ONE);
1333 FixedPoint16 operator--(int)
1335 FixedPoint16 old(*this);
1343 template <int IntBits2>
1344 FixedPoint16 & operator+=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1346 value = detail::FP16AddImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1353 template <int IntBits2>
1354 FixedPoint16 & operator-=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1356 value = detail::FP16SubImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1363 template <int IntBits2>
1364 FixedPoint16 & operator*=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1366 value = detail::FP16MulImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1373 template <int IntBits2>
1374 FixedPoint16 & operator/=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1376 value = detail::FP16DivImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1384 struct FixedPoint16Cast;
1386 #define VIGRA_FIXED_POINT_CAST(type) \
1388 struct FixedPoint16Cast<type> \
1390 template <int IntBits, FPOverflowHandling OverflowHandling> \
1391 static type cast(FixedPoint16<IntBits, OverflowHandling> v) \
1397 VIGRA_FIXED_POINT_CAST(Int8)
1398 VIGRA_FIXED_POINT_CAST(UInt8)
1399 VIGRA_FIXED_POINT_CAST(Int16)
1400 VIGRA_FIXED_POINT_CAST(UInt16)
1401 VIGRA_FIXED_POINT_CAST(Int32)
1402 VIGRA_FIXED_POINT_CAST(UInt32)
1403 VIGRA_FIXED_POINT_CAST(Int64)
1404 VIGRA_FIXED_POINT_CAST(UInt64)
1406 #undef VIGRA_FIXED_POINT_CAST
1409 struct FixedPoint16Cast<float>
1411 template <int IntBits, FPOverflowHandling OverflowHandling>
1412 static float cast(FixedPoint16<IntBits, OverflowHandling> v)
1414 return (float)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1419 struct FixedPoint16Cast<double>
1421 template <int IntBits, FPOverflowHandling OverflowHandling>
1422 static double cast(FixedPoint16<IntBits, OverflowHandling> v)
1424 return (double)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1457 template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1458 TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v)
1460 return detail::FixedPoint16Cast<TARGET>::cast(v);
1465 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1467 bool operator==(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1469 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1470 return (l.value << (IntBits1 - MinIntBits)) == (r.value << (IntBits2 - MinIntBits));
1474 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1476 bool operator!=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1478 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1479 return (l.value << (IntBits1 - MinIntBits)) != (r.value << (IntBits2 - MinIntBits));
1483 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1485 bool operator<(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1487 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1488 return (l.value << (IntBits1 - MinIntBits)) < (r.value << (IntBits2 - MinIntBits));
1492 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1494 bool operator<=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1496 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1497 return (l.value << (IntBits1 - MinIntBits)) <= (r.value << (IntBits2 - MinIntBits));
1501 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1503 bool operator>(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1505 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1506 return (l.value << (IntBits1 - MinIntBits)) > (r.value << (IntBits2 - MinIntBits));
1510 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1512 bool operator>=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1514 enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1515 return (l.value << (IntBits1 - MinIntBits)) >= (r.value << (IntBits2 - MinIntBits));
1519 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1521 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1522 operator+(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1525 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1527 return Result(detail::FP16AddImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1531 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1533 FixedPoint16<IntBits3, OverflowHandling> &
1534 add(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1535 FixedPoint16<IntBits3, OverflowHandling> & result)
1537 result.value = detail::FP16AddImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1542 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1544 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1545 operator-(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1548 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1550 return Result(detail::FP16SubImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1554 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1555 inline FixedPoint16<IntBits3, OverflowHandling> &
1556 sub(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1557 FixedPoint16<IntBits3, OverflowHandling> & result)
1559 result.value = detail::FP16SubImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1564 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1566 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1567 operator*(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1570 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1572 return Result(detail::FP16MulImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1576 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1578 FixedPoint16<IntBits3, OverflowHandling> &
1579 mul(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1580 FixedPoint16<IntBits3, OverflowHandling> & result)
1582 result.value = detail::FP16MulImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1587 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1589 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1590 operator/(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1593 PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1595 return Result(detail::FP16DivImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1599 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1601 FixedPoint16<IntBits3, OverflowHandling> &
1602 div(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1603 FixedPoint16<IntBits3, OverflowHandling> & result)
1605 result.value = detail::FP16DivImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1610 template <int IntBits, FPOverflowHandling OverflowHandling>
1611 inline typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult
1612 sqrt(FixedPoint16<IntBits, OverflowHandling> v)
1614 typedef typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult Result;
1615 enum { Shift = 15 + IntBits - 2*Result::INT_BITS };
1616 return Result(sqrti(v.value << Shift), FPNoShift);
1619 #ifndef VIGRA_NO_HYPOT
1624 template <int IntBits, FPOverflowHandling OverflowHandling>
1625 inline FixedPoint16<IntBits, OverflowHandling>
1626 hypot(FixedPoint16<IntBits, OverflowHandling> v1, FixedPoint16<IntBits, OverflowHandling> v2)
1628 UInt32 l = abs(v1.value), r = abs(v2.value);
1630 return FixedPoint16<IntBits, OverflowHandling>(
1631 detail::FP16OverflowHandling<OverflowHandling>::exec(sqrti(sq(l) + sq(r))),
1638 template <int IntBits, FPOverflowHandling OverflowHandling>
1639 FixedPoint16<2, OverflowHandling>
1640 atan2(FixedPoint16<IntBits, OverflowHandling> y, FixedPoint16<IntBits, OverflowHandling> x)
1642 enum { ResIntBits = 2 };
1643 typedef FixedPoint16<ResIntBits, OverflowHandling> FP;
1644 static const FP zero(0), pi(M_PI), pi_2(0.5 * M_PI), mpi_2(-0.5 * M_PI);
1645 static const Int32 Pi_4 = roundi(0.25 * M_PI * (1 << 15)),
1646 Pi3_4 = roundi(0.75 * M_PI * (1 << 15)),
1647 c1 = roundi(0.19826763260224867 * (1 << 15)),
1648 c2 = roundi(-0.9757748231899761 * (1 << 30));
1656 return (y.value > 0)
1662 Int32 abs_y = abs(y.value);
1668 r = ((x.value - abs_y) << 15) / (x.value + abs_y);
1675 r = ((x.value + abs_y) << 15) / (abs_y - x.value);
1679 angle += r*((c2 + c1 * (sq(r) >> 15)) >> 15) >> 15;
1681 return (y.value > 0)
1682 ? FP(detail::FP16Align<0, ResIntBits, true>::exec( angle), FPNoShift)
1683 : FP(detail::FP16Align<0, ResIntBits, true>::exec(-angle), FPNoShift);
1687 template <int IntBits, FPOverflowHandling OverflowHandling>
1688 inline FixedPoint16<IntBits, OverflowHandling>
1689 abs(FixedPoint16<IntBits, OverflowHandling> v)
1691 return FixedPoint16<IntBits, OverflowHandling>(abs(v.value), FPNoShift);
1695 template <int IntBits, FPOverflowHandling OverflowHandling>
1697 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::SquaredNormType
1698 squaredNorm(FixedPoint16<IntBits, OverflowHandling> v)
1704 template <int IntBits, FPOverflowHandling OverflowHandling>
1706 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::NormType
1707 norm(FixedPoint16<IntBits, OverflowHandling> const & v)
1713 template <int IntBits, FPOverflowHandling OverflowHandling>
1714 inline FixedPoint16<IntBits, OverflowHandling>
1715 frac(FixedPoint16<IntBits, OverflowHandling> v)
1717 return FixedPoint16<IntBits, OverflowHandling>(
1718 v.value - (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1723 template <int IntBits, FPOverflowHandling OverflowHandling>
1724 inline FixedPoint16<IntBits, OverflowHandling>
1725 dual_frac(FixedPoint16<IntBits, OverflowHandling> v)
1727 return FixedPoint16<IntBits, OverflowHandling>(
1728 FixedPoint16<IntBits, OverflowHandling>::ONE - v.value + (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1733 template <int IntBits, FPOverflowHandling OverflowHandling>
1735 floor(FixedPoint16<IntBits, OverflowHandling> v)
1737 return(v.value >> FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1741 template <int IntBits, FPOverflowHandling OverflowHandling>
1743 ceil(FixedPoint16<IntBits, OverflowHandling> v)
1745 return((v.value + FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_MASK) >>
1746 FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1750 template <int IntBits, FPOverflowHandling OverflowHandling>
1752 round(FixedPoint16<IntBits, OverflowHandling> v)
1754 return((v.value + FixedPoint16<IntBits, OverflowHandling>::ONE_HALF) >>
1755 FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1759 template <int IntBits, FPOverflowHandling OverflowHandling>
1761 roundi(FixedPoint16<IntBits, OverflowHandling> v)
1772 template <int IntBits, vigra::FPOverflowHandling OverflowHandling>
1773 ostream & operator<<(ostream & s, vigra::FixedPoint16<IntBits, OverflowHandling> v)
1775 s << vigra::fixed_point_cast<float>(v);