[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

# vigra/fixedpoint.hxx

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 2004-2005 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
    00008 /*    The VIGRA Website is                                              */
    00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00010 /*    Please direct questions, bug reports, and contributions to        */
    00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00012 /*        vigra@informatik.uni-hamburg.de                               */
    00013 /*                                                                      */
    00014 /*    Permission is hereby granted, free of charge, to any person       */
    00015 /*    obtaining a copy of this software and associated documentation    */
    00016 /*    files (the "Software"), to deal in the Software without           */
    00017 /*    restriction, including without limitation the rights to use,      */
    00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00019 /*    sell copies of the Software, and to permit persons to whom the    */
    00020 /*    Software is furnished to do so, subject to the following          */
    00021 /*    conditions:                                                       */
    00022 /*                                                                      */
    00023 /*    The above copyright notice and this permission notice shall be    */
    00024 /*    included in all copies or substantial portions of the             */
    00025 /*    Software.                                                         */
    00026 /*                                                                      */
    00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00035 /*                                                                      */
    00036 /************************************************************************/
    00037
    00038 #ifndef VIGRA_FIXEDPOINT_HXX
    00039 #define VIGRA_FIXEDPOINT_HXX
    00040
    00041 #include "mathutil.hxx"
    00042 #include "static_assert.hxx"
    00043 #include "error.hxx"
    00044 #include "numerictraits.hxx"
    00045
    00046 namespace vigra {
    00047
    00048 template <unsigned IntBits, unsigned FractionalBits>
    00049 class FixedPoint;
    00050
    00051 struct Error_FixedPointTraits_not_specialized_for_this_case;
    00052
    00053 template <class T1, class T2>
    00054 class FixedPointTraits
    00055 {
    00056 public:
    00057     typedef Error_FixedPointTraits_not_specialized_for_this_case PlusType;
    00058     typedef Error_FixedPointTraits_not_specialized_for_this_case MinusType;
    00059     typedef Error_FixedPointTraits_not_specialized_for_this_case MultipliesType;
    00060 //    typedef Error_FixedPointTraits_not_specialized_for_this_case DividesType;
    00061 };
    00062
    00063 // return type policy:
    00064 //     * try to allocate enough bits to represent the biggest possible result
    00065 //     * in case of add/subtract: if all bits of the internal int are used up,
    00066 //                                keep the representation
    00067 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00068 class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
    00069 {
    00070     enum { MaxIntBits  = (IntBits1 < IntBits2) ? IntBits2 : IntBits1,
    00071            MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1,
    00072            PlusMinusIntBits = (MaxIntBits + 1 + MaxFracBits < 32) ?
    00073                                MaxIntBits + 1 : MaxIntBits,
    00074            MultipliesFracBits = (IntBits1 + IntBits2 < 31)
    00075                                     ? (FracBits1 + FracBits2) > (31 - IntBits1 - IntBits2)
    00076                                             ? 31 - IntBits1 - IntBits2
    00077                                             : FracBits1 + FracBits2
    00078                                     : 0
    00079          };
    00080 public:
    00081     typedef FixedPoint<PlusMinusIntBits, MaxFracBits>               PlusType;
    00082     typedef FixedPoint<PlusMinusIntBits, MaxFracBits>               MinusType;
    00083     typedef FixedPoint<IntBits1 + IntBits2, MultipliesFracBits>  MultipliesType;
    00084 //    typedef FixedPoint<IntBits1 + FracBits2, FracBits1 + IntBits2>  DividesType;
    00085 };
    00086
    00087 template <unsigned IntBits, unsigned FracBits>
    00088 struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
    00089 {
    00090     enum { SRTotalBits = (IntBits + FracBits + 1) / 2,
    00091            SRIntBits   = (IntBits + 1) / 2,
    00092            SRFracBits  = SRTotalBits - SRIntBits
    00093          };
    00094 public:
    00095     typedef FixedPoint<IntBits, FracBits>      Type;
    00096     typedef FixedPoint<SRIntBits, SRFracBits>  SquareRootResult;
    00097     typedef Type                               SquareRootArgument;
    00098 };
    00099
    00100
    00101 #ifndef DOXYGEN
    00102
    00103 template <int N>
    00104 struct FixedPoint_overflow_error__More_than_31_bits_requested
    00105 : staticAssert::AssertBool<(N < 32)>
    00106 {};
    00107
    00108 #endif /* DOXYGEN */
    00109
    00110
    00111
    00112 template <bool Predicate>
    00113 struct FixedPoint_assignment_error__Target_object_has_too_few_integer_bits
    00114 : staticAssert::AssertBool<Predicate>
    00115 {};
    00116
    00117 enum FixedPointNoShift { FPNoShift };
    00118
    00119 namespace detail {
    00120
    00121 template <bool MustRound>
    00122 struct FPAssignWithRound;
    00123
    00124 template <>
    00125 struct FPAssignWithRound<false>
    00126 {
    00127     template <int N>
    00128     static inline int exec(int v) { return v << (-N); }
    00129 };
    00130
    00131 template <>
    00132 struct FPAssignWithRound<true>
    00133 {
    00134     template <int N>
    00135     static inline int exec(int const v)
    00136     {
    00137         return (v + (1 << (N - 1))) >> (N);
    00138     }
    00139 };
    00140
    00141 template <bool MustRound>
    00142 struct FPMulImplementation;
    00143
    00144 template <>
    00145 struct FPMulImplementation<false>
    00146 {
    00147     template <int N>
    00148     static inline int exec(int l, int r) { return (l * r) << (-N); }
    00149 };
    00150
    00151 template <>
    00152 struct FPMulImplementation<true>
    00153 {
    00154     template <int N>
    00155     static inline int exec(int l, int r)
    00156     {
    00157         // there is not enough space in the result
    00158         // => perform calculations that preserve as much accuracy as possible
    00159         enum { diffl = N / 2, diffr = N  - diffl, maskl = (1 << diffl) - 1, maskr = (1 << diffr) - 1 };
    00160         int shiftl = l >> diffl;
    00161         int shiftr = r >> diffr;
    00162
    00163         return shiftl * shiftr + (((l & maskl) * shiftr) >> diffl) +
    00164                                  (((r & maskr) * shiftl) >> diffr);
    00165     }
    00166 };
    00167
    00168 } // namespace detail
    00169
    00170 /********************************************************/
    00171 /*                                                      */
    00172 /*                      FixedPoint                      */
    00173 /*                                                      */
    00174 /********************************************************/
    00175
    00176 /** Template for fixed point arithmetic.
    00177
    00178     Fixed point arithmetic is used when computations with fractional accuracy
    00179     must be made at the highest speed possible (e.g. in the inner loop
    00180     of a volume rendering routine). The speed-up relative to floating
    00181     point arithmetic can be dramatic, especially when one can avoid
    00182     conversions between integer anfloating point numbers (these are
    00183     very expensive because integer and floating point arithmetic
    00184     resides in different pipelines).
    00185
    00186     The template wraps an <tt>int</tt> and uses <tt>IntBits</tt> to
    00187     represent the integral part of a number, and <tt>FractionalBits</tt>
    00188     for the fractional part, where <tt>IntBits + FractionalBits < 32</tt>.
    00189     (The 32rd bit is reserved because FixedPoint is a signed type).
    00190     These numbers will be automatically allocated in an intelligent way
    00191     in the result of an arithmetic operation. For example, when two
    00192     fixed point numbers are multiplied, the required number of integer
    00193     bits in the result is the sum of the number of integer bits of the
    00194     arguments, but only when so many bits are avaiable. This is figured out
    00195     by means of FixedPointTraits, and a compile-time error is raised
    00196     when no suitable representation can be found. The idea is that the right
    00197     thing happens automatically as often as possible.
    00198
    00199     <tt>FixedPoint</tt> implements the required interface of an
    00200     \ref AlgebraicRing and the required numeric and
    00201     promotion traits. In addition, it supports functions <tt>add</tt>,
    00202     <tt>sub</tt>, and <tt>mul</tt>, where a particular layout of the result can
    00203     be enforced.
    00204
    00205     <tt>unsigned char, signed char, unsigned short, signed short, int</tt> can be
    00206     transformed into a FixedPoint with appropriate layout by means of the factory
    00207     function <tt>fixedPoint()</tt>.
    00208
    00209     <b>See also:</b>
    00210     <ul>
    00211     <li> \ref FixedPointOperations
    00212     <li> \ref FixedPointTraits
    00213     </ul>
    00214
    00215     <b>\#include</b> <<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>><br>
    00216     Namespace: vigra
    00217 */
    00218 template <unsigned IntBits, unsigned FractionalBits>
    00219 class FixedPoint
    00220 {
    00221 public:
    00222     enum {
    00223         INT_BITS        = IntBits,
    00224         FRACTIONAL_BITS = FractionalBits,
    00225         TOTAL_BITS      = IntBits + FractionalBits,
    00226         MAX             = (int)(((unsigned)1 << TOTAL_BITS) - 1),
    00227         ONE             = 1 << FractionalBits,
    00228         ONE_HALF        = ONE >> 1,
    00229         FRACTIONAL_MASK = ONE - 1,
    00230         INT_MASK        = MAX ^ FRACTIONAL_MASK
    00231     };
    00232
    00233     Int32 value;
    00234
    00235     FixedPoint()
    00236     {
    00237         VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
    00238     }
    00239
    00240         /** Construct from an int (fractional part will become zero).
    00241         */
    00242     explicit FixedPoint(int v)
    00243     : value(v << FractionalBits)
    00244     {
    00245         VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
    00246     }
    00247
    00248         /** Construct from an int by a bitwise copy. This is normally only used internally.
    00249         */
    00250     FixedPoint(int v, FixedPointNoShift)
    00251     : value(v)
    00252     {
    00253         VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
    00254     }
    00255
    00256         /** Construct from an double and round the fractional part to
    00257             <tt>FractionalBits</tt> accuracy. A PreconditionViolation exception is raised when
    00258             the integer part is too small to represent the number.
    00259         */
    00260     explicit FixedPoint(double rhs)
    00261     : value((int)round(rhs * ONE))
    00262     {
    00263         VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
    00264         vigra_precondition(abs(rhs * ONE) <= (double)MAX,
    00265             "FixedPoint(double rhs): Too few integer bits to convert rhs.");
    00266     }
    00267
    00268         /** Copy constructor.
    00269         */
    00270     FixedPoint(const FixedPoint &other)
    00271     : value(other.value)
    00272     {}
    00273
    00274         /** Construct from a FixedPoint with different layout. It rounds as appropriate and raises
    00275             a compile-time error when the target type has too few integer bits.
    00276         */
    00277     template <unsigned Int2, unsigned Frac2>
    00278     FixedPoint(const FixedPoint<Int2, Frac2> &other)
    00279     : value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value))
    00280     {
    00281         VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
    00282         VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
    00283     }
    00284
    00285         /** Assignment from int. The fractional part will become zero.
    00286             A PreconditionViolation exception is raised when
    00287             the integer part is too small to represent the number.
    00288         */
    00289     FixedPoint &operator=(int rhs)
    00290     {
    00291         vigra_precondition(abs(rhs) < (1 << IntBits),
    00292             "FixedPoint::operator=(int rhs): Too few integer bits to represent rhs.");
    00293         value = rhs << FractionalBits;
    00294         return *this;
    00295     }
    00296
    00297         /** Assignment form double. The fractional part is rounded, and a
    00298             PreconditionViolation exception is raised when
    00299             the integer part is too small to represent the number.
    00300         */
    00301     FixedPoint &operator=(double rhs)
    00302     {
    00303         vigra_precondition(abs(rhs) <= ((1 << IntBits) - 1),
    00304             "FixedPoint::operator=(double rhs): Too few integer bits to convert rhs.");
    00305         value = (int)round(rhs * ONE);
    00306         return *this;
    00307     }
    00308
    00309         /** Copy assignment.
    00310         */
    00311     FixedPoint & operator=(const FixedPoint &other)
    00312     {
    00313         value = other.value;
    00314         return *this;
    00315     }
    00316
    00317         /** Assignment from a FixedPoint with different layout. It rounds as appropriate and raises
    00318             a compile-time error when the target type has too few integer bits.
    00319         */
    00320     template <unsigned Int2, unsigned Frac2>
    00321     FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other)
    00322     {
    00323         VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
    00324         value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
    00325         return *this;
    00326     }
    00327
    00328         /** Negation.
    00329         */
    00330     FixedPoint operator-() const
    00331     {
    00332         return FixedPoint(-value, FPNoShift);
    00333     }
    00334
    00335         /** Pre-increment.
    00336         */
    00337     FixedPoint & operator++()
    00338     {
    00339         value += ONE;
    00340         return *this;
    00341     }
    00342
    00343         /** Post-increment.
    00344         */
    00345     FixedPoint operator++(int)
    00346     {
    00347         FixedPoint old(*this);
    00348         value += ONE;
    00349         return old;
    00350     }
    00351
    00352         /** Pre-decrement.
    00353         */
    00354     FixedPoint & operator--()
    00355     {
    00356         value -= ONE;
    00357         return *this;
    00358     }
    00359
    00360         /** Post-decrement.
    00361         */
    00362     FixedPoint operator--(int)
    00363     {
    00364         FixedPoint old(*this);
    00365         value -= ONE;
    00366         return old;
    00367     }
    00368
    00369         /** Add-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
    00370             a compile-time error when the target type has too few integer bits.
    00371         */
    00372     template <unsigned Int2, unsigned Frac2>
    00373     FixedPoint & operator+=(const FixedPoint<Int2, Frac2> &other)
    00374     {
    00375         VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
    00376         value += detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
    00377         return *this;
    00378     }
    00379
    00380         /** Subtract-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
    00381             a compile-time error when the target type has too few integer bits.
    00382         */
    00383     template <unsigned Int2, unsigned Frac2>
    00384     FixedPoint & operator-=(const FixedPoint<Int2, Frac2> &other)
    00385     {
    00386         VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
    00387         value -= detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
    00388         return *this;
    00389     }
    00390
    00391         /** Multiply-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
    00392             a compile-time error when the target type has too few integer bits.
    00393         */
    00394     template <unsigned Int2, unsigned Frac2>
    00395     FixedPoint & operator*=(const FixedPoint<Int2, Frac2> &other)
    00396     {
    00397         VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
    00398         value = detail::FPMulImplementation<(Frac2 > 0)>::template exec<Frac2>(value, other.value);
    00399         return *this;
    00400     }
    00401 };
    00402
    00403 #define VIGRA_FIXED_POINT_FACTORY(T, INTBITS) \
    00404     inline FixedPoint<INTBITS, 0> fixedPoint(T t) \
    00405     { \
    00406         return FixedPoint<INTBITS, 0>(t, FPNoShift); \
    00407     }
    00408
    00409 VIGRA_FIXED_POINT_FACTORY(unsigned char, 8)
    00410 VIGRA_FIXED_POINT_FACTORY(signed char, 7)
    00411 VIGRA_FIXED_POINT_FACTORY(unsigned short, 16)
    00412 VIGRA_FIXED_POINT_FACTORY(signed short, 15)
    00413 VIGRA_FIXED_POINT_FACTORY(int, 31)
    00414
    00415 #undef VIGRA_FIXED_POINT_FACTORY
    00416
    00417 template <class T>
    00418 struct FixedPointCast;
    00419
    00420 #define VIGRA_FIXED_POINT_CAST(type) \
    00421 template <> \
    00422 struct FixedPointCast<type> \
    00423 { \
    00424     template <unsigned IntBits, unsigned FracBits> \
    00425     static type cast(FixedPoint<IntBits, FracBits> v) \
    00426     { \
    00427         return round(v); \
    00428     } \
    00429 };
    00430
    00431 VIGRA_FIXED_POINT_CAST(Int8)
    00432 VIGRA_FIXED_POINT_CAST(UInt8)
    00433 VIGRA_FIXED_POINT_CAST(Int16)
    00434 VIGRA_FIXED_POINT_CAST(UInt16)
    00435 VIGRA_FIXED_POINT_CAST(Int32)
    00436 VIGRA_FIXED_POINT_CAST(UInt32)
    00437
    00438 #undef VIGRA_FIXED_POINT_CAST
    00439
    00440 template <>
    00441 struct FixedPointCast<float>
    00442 {
    00443     template <unsigned IntBits, unsigned FracBits>
    00444     static float cast(FixedPoint<IntBits, FracBits> v)
    00445     {
    00446         return (float)v.value / FixedPoint<IntBits, FracBits>::ONE;
    00447     }
    00448 };
    00449
    00450 template <>
    00451 struct FixedPointCast<double>
    00452 {
    00453     template <unsigned IntBits, unsigned FracBits>
    00454     static double cast(FixedPoint<IntBits, FracBits> v)
    00455     {
    00456         return (double)v.value / FixedPoint<IntBits, FracBits>::ONE;
    00457     }
    00458 };
    00459
    00460 /********************************************************/
    00461 /*                                                      */
    00462 /*                 FixedPointOperations                 */
    00463 /*                                                      */
    00464 /********************************************************/
    00465
    00466 /** \addtogroup FixedPointOperations Functions for FixedPoint
    00467
    00468     \brief     <b>\#include</b> <<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>><br>
    00469
    00470     These functions fulfill the requirements of an \ref AlgebraicRing.
    00471
    00472     Namespace: vigra
    00473     <p>
    00474
    00475  */
    00476 //@{
    00477
    00478     /** Convert a FixedPoint to a built-in type.
    00479         If the target is integral, the value is rounded.<br>
    00480         Usage:
    00481         \code
    00482         FixedPoint<16,15> fp(...);
    00483
    00484         double d = fixed_point_cast<double>(fp);
    00485         \endcode
    00486     */
    00487 template <class TARGET, unsigned IntBits, unsigned FracBits>
    00488 TARGET fixed_point_cast(FixedPoint<IntBits, FracBits> v)
    00489 {
    00490     return FixedPointCast<TARGET>::cast(v);
    00491 }
    00492
    00493     /// equal
    00494 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00495 inline
    00496 bool operator==(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00497 {
    00498     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00499     return (l.value << (MaxFracBits - FracBits1)) == (r.value << (MaxFracBits - FracBits2));
    00500 }
    00501
    00502     /// not equal
    00503 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00504 inline
    00505 bool operator!=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00506 {
    00507     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00508     return (l.value << (MaxFracBits - FracBits1)) != (r.value << (MaxFracBits - FracBits2));
    00509 }
    00510
    00511     /// less than
    00512 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00513 inline
    00514 bool operator<(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00515 {
    00516     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00517     return (l.value << (MaxFracBits - FracBits1)) < (r.value << (MaxFracBits - FracBits2));
    00518 }
    00519
    00520     /// less or equal
    00521 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00522 inline
    00523 bool operator<=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00524 {
    00525     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00526     return (l.value << (MaxFracBits - FracBits1)) <= (r.value << (MaxFracBits - FracBits2));
    00527 }
    00528
    00529     /// greater
    00530 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00531 inline
    00532 bool operator>(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00533 {
    00534     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00535     return (l.value << (MaxFracBits - FracBits1)) > (r.value << (MaxFracBits - FracBits2));
    00536 }
    00537
    00538     /// greater or equal
    00539 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00540 inline
    00541 bool operator>=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00542 {
    00543     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00544     return (l.value << (MaxFracBits - FracBits1)) >= (r.value << (MaxFracBits - FracBits2));
    00545 }
    00546
    00547     /// addition with automatic determination of the appropriate result type.
    00548 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00549 inline
    00550 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
    00551 operator+(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00552 {
    00553     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00554     return typename
    00555         FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
    00556         PlusType((l.value << (MaxFracBits - FracBits1)) + (r.value << (MaxFracBits - FracBits2)), FPNoShift);
    00557 }
    00558
    00559     /// addition with enforced result type.
    00560 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
    00561           unsigned IntBits3, unsigned FracBits3>
    00562 inline void
    00563 add(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
    00564     FixedPoint<IntBits3, FracBits3> & result)
    00565 {
    00566     result = l + r;
    00567 }
    00568
    00569     /// subtraction with automatic determination of the appropriate result type.
    00570 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00571 inline
    00572 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MinusType
    00573 operator-(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00574 {
    00575     enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
    00576     return typename
    00577         FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
    00578         MinusType((l.value << (MaxFracBits - FracBits1)) - (r.value << (MaxFracBits - FracBits2)), FPNoShift);
    00579 }
    00580
    00581     /// subtraction with enforced result type.
    00582 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
    00583           unsigned IntBits3, unsigned FracBits3>
    00584 inline void
    00585 sub(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
    00586     FixedPoint<IntBits3, FracBits3> & result)
    00587 {
    00588     result = l - r;
    00589 }
    00590
    00591     /// multiplication with automatic determination of the appropriate result type.
    00592 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00593 inline
    00594 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MultipliesType
    00595 operator*(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
    00596 {
    00597     typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
    00598         MultipliesType res;
    00599     mul(l, r, res);
    00600     return res;
    00601 }
    00602
    00603     /// multiplication with enforced result type.
    00604 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
    00605           unsigned IntBits3, unsigned FracBits3>
    00606 inline void
    00607 mul(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
    00608     FixedPoint<IntBits3, FracBits3> & result)
    00609 {
    00610     VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits1 + IntBits2 <= IntBits3)>));
    00611     enum { diff = FracBits1 + FracBits2 - FracBits3 };
    00612     result.value = detail::FPMulImplementation<(diff > 0)>::template exec<diff>(l.value, r.value);
    00613 }
    00614
    00615     /// square root.
    00616 template <unsigned IntBits, unsigned FracBits>
    00617 inline typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult
    00618 sqrt(FixedPoint<IntBits, FracBits> v)
    00619 {
    00620     return typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult(sqrti(v.value), FPNoShift);
    00621 }
    00622
    00623     /// absolute value.
    00624 template <unsigned IntBits, unsigned FracBits>
    00625 inline FixedPoint<IntBits, FracBits>
    00626 abs(FixedPoint<IntBits, FracBits> v)
    00627 {
    00628     return FixedPoint<IntBits, FracBits>(abs(v.value), FPNoShift);
    00629 }
    00630
    00631     /// squared norm (same as v*v).
    00632 template <unsigned IntBits, unsigned FracBits>
    00633 inline
    00634 typename FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
    00635 squaredNorm(FixedPoint<IntBits, FracBits> v)
    00636 {
    00637     return v*v;
    00638 }
    00639
    00640     /// norm (same as abs).
    00641 template <unsigned IntBits, unsigned FracBits>
    00642 inline
    00643 FixedPoint<IntBits, FracBits>
    00644 norm(FixedPoint<IntBits, FracBits> const & v)
    00645 {
    00646     return abs(v);
    00647 }
    00648
    00649     /// fractional part.
    00650 template <unsigned IntBits, unsigned FracBits>
    00651 inline FixedPoint<0, FracBits>
    00652 frac(FixedPoint<IntBits, FracBits> v)
    00653 {
    00654     return FixedPoint<0, FracBits>(v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK, FPNoShift);
    00655 }
    00656
    00657     /// dual fractional part: <tt>1 - frac(v)</tt>.
    00658 template <unsigned IntBits, unsigned FracBits>
    00659 inline FixedPoint<0, FracBits>
    00660 dual_frac(FixedPoint<IntBits, FracBits> v)
    00661 {
    00662     return FixedPoint<0, FracBits>(FixedPoint<0, FracBits>::ONE -
    00663                                    (v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK), FPNoShift);
    00664 }
    00665
    00666     /// rounding down.
    00667 template <unsigned IntBits, unsigned FracBits>
    00668 inline int
    00669 floor(FixedPoint<IntBits, FracBits> v)
    00670 {
    00671     return(v.value >> FracBits);
    00672 }
    00673
    00674     /// rounding up.
    00675 template <unsigned IntBits, unsigned FracBits>
    00676 inline int
    00677 ceil(FixedPoint<IntBits, FracBits> v)
    00678 {
    00679     return((v.value + FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK) >> FracBits);
    00680 }
    00681
    00682     /// rounding to the nearest integer.
    00683 template <unsigned IntBits, unsigned FracBits>
    00684 inline int
    00685 round(FixedPoint<IntBits, FracBits> v)
    00686 {
    00687     return((v.value + FixedPoint<IntBits, FracBits>::ONE_HALF) >> FracBits);
    00688 }
    00689
    00690 //@}
    00691
    00692 /********************************************************/
    00693 /*                                                      */
    00694 /*                     FixedPoint-Traits                */
    00695 /*                                                      */
    00696 /********************************************************/
    00697
    00698 /** \page FixedPointTraits Numeric and Promote Traits of FixedPoint
    00699
    00700     The numeric and promote traits for FixedPoint follow
    00701     the general specifications for \ref NumericPromotionTraits and
    00702     \ref AlgebraicRing. They are implemented in terms of the traits of the basic types by
    00703     partial template specialization:
    00704
    00705     \code
    00706
    00707     template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00708     class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
    00709     {
    00710         typedef FixedPoint<PlusMinusIntBits, MaxFracBits>               PlusType;
    00711         typedef FixedPoint<PlusMinusIntBits, MaxFracBits>               MinusType;
    00712         typedef FixedPoint<IntBits1 + IntBits2, FracBits1 + FracBits2>  MultipliesType;
    00713     };
    00714
    00715     template <unsigned IntBits, unsigned FracBits>
    00716     struct NumericTraits<FixedPoint<IntBits, FracBits> >
    00717     {
    00718         typedef FixedPoint<IntBits, FracBits> Type;
    00719             // Promote undefined because it depends on the layout, use FixedPointTraits
    00720             // RealPromote in AlgebraicRing -- multiplication with double is not supported.
    00721             // ComplexPromote in AlgebraicRing -- multiplication with double is not supported.
    00722         typedef Type ValueType;
    00723
    00724         typedef VigraFalseType isIntegral;
    00725         typedef VigraTrueType  isScalar;
    00726         typedef VigraTrueType  isSigned;
    00727         typedef VigraTrueType  isOrdered;
    00728         typedef VigraFalseType isComplex;
    00729
    00730         ... // etc.
    00731     };
    00732
    00733     template <unsigned IntBits, unsigned FracBits>
    00734     struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
    00735     {
    00736         typedef FixedPoint<IntBits, FracBits>      Type;
    00737         typedef FixedPoint<SRIntBits, SRFracBits>  SquareRootResult;
    00738         typedef Type                               SquareRootArgument;
    00739     };
    00740
    00741     template <unsigned IntBits, unsigned FracBits>
    00742     struct NormTraits<FixedPoint<IntBits, FracBits> >
    00743     {
    00744         typedef FixedPoint<IntBits, FracBits>         Type;
    00745         typedef typename
    00746             FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
    00747                                                       SquaredNormType;
    00748         typedef Type                                  NormType;
    00749     };
    00750
    00751     template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00752     struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
    00753                          FixedPoint<IntBits2, FracBits2> >
    00754     {
    00755         typedef typename
    00756             FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
    00757             Promote;
    00758     };
    00759     \endcode
    00760
    00761     <b>\#include</b> <<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>><br>
    00762     Namespace: vigra
    00763
    00764 */
    00765 template <unsigned IntBits, unsigned FracBits>
    00766 struct NumericTraits<FixedPoint<IntBits, FracBits> >
    00767 {
    00768     typedef FixedPoint<IntBits, FracBits> Type;
    00769         //typedef FixedPoint<IntBits, FracBits> Promote;
    00770         //typedef FixedPoint<IntBits, FracBits> RealPromote;
    00771         //typedef std::complex<RealPromote> ComplexPromote;
    00772     typedef Type ValueType;
    00773
    00774     typedef VigraFalseType isIntegral;
    00775     typedef VigraTrueType  isScalar;
    00776     typedef VigraTrueType  isSigned;
    00777     typedef VigraTrueType  isOrdered;
    00778     typedef VigraFalseType isComplex;
    00779
    00780     static Type zero() { return Type(0, FPNoShift); }
    00781     static Type one() { return Type(Type::ONE, FPNoShift); }
    00782     static Type nonZero() { return one(); }
    00783     static Type epsilon() { return Type(1, FPNoShift); }
    00784     static Type smallestPositive() { return Type(1, FPNoShift); }
    00785     static Type max() { return Type( Type::MAX, FPNoShift); }
    00786     static Type min() { return -max(); }
    00787 };
    00788
    00789 template <unsigned IntBits, unsigned FracBits>
    00790 struct NormTraits<FixedPoint<IntBits, FracBits> >
    00791 {
    00792     typedef FixedPoint<IntBits, FracBits>         Type;
    00793     typedef typename
    00794         FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
    00795                                                   SquaredNormType;
    00796     typedef Type                                  NormType;
    00797 };
    00798
    00799 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
    00800 struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
    00801                      FixedPoint<IntBits2, FracBits2> >
    00802 {
    00803     typedef typename
    00804         FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
    00805         Promote;
    00806 };
    00807
    00808 } // namespace vigra
    00809
    00810 #endif // VIGRA_FIXEDPOINT_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python VIGRA 1.6.0 (13 Aug 2008)