[ 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)