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