[ 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 /* 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) |
html generated using doxygen and Python
|