[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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) |
html generated using doxygen and Python
|