1 /************************************************************************/
2 /* */
3 /* Copyright 2004-2005 by Ullrich Koethe */
4 /* Cognitive Systems Group, University of Hamburg, Germany */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* ( Version 1.5.0, Dec 07 2006 ) */
8 /* The VIGRA Website is */
9 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */
10 /* Please direct questions, bug reports, and contributions to */
11 /* koethe@informatik.uni-hamburg.de or */
12 /* vigra@kogs1.informatik.uni-hamburg.de */
13 /* */
14 /* Permission is hereby granted, free of charge, to any person */
15 /* obtaining a copy of this software and associated documentation */
16 /* files (the "Software"), to deal in the Software without */
17 /* restriction, including without limitation the rights to use, */
18 /* copy, modify, merge, publish, distribute, sublicense, and/or */
19 /* sell copies of the Software, and to permit persons to whom the */
20 /* Software is furnished to do so, subject to the following */
21 /* conditions: */
22 /* */
23 /* The above copyright notice and this permission notice shall be */
24 /* included in all copies or substantial portions of the */
25 /* Software. */
26 /* */
27 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
28 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
29 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
30 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
31 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
32 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
33 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
34 /* OTHER DEALINGS IN THE SOFTWARE. */
35 /* */
36 /************************************************************************/
37
38 #ifndef VIGRA_FIXEDPOINT_HXX
39 #define VIGRA_FIXEDPOINT_HXX
40
41 #include "mathutil.hxx"
42 #include "static_assert.hxx"
43 #include "error.hxx"
44 #include "numerictraits.hxx"
45
46 namespace vigra {
47
48 template <unsigned IntBits, unsigned FractionalBits>
49 class FixedPoint;
50
51 struct Error_FixedPointTraits_not_specialized_for_this_case;
52
53 template <class T1, class T2>
54 class FixedPointTraits
55 {
56 public:
57 typedef Error_FixedPointTraits_not_specialized_for_this_case PlusType;
58 typedef Error_FixedPointTraits_not_specialized_for_this_case MinusType;
59 typedef Error_FixedPointTraits_not_specialized_for_this_case MultipliesType;
60 // typedef Error_FixedPointTraits_not_specialized_for_this_case DividesType;
61 };
62
63 // return type policy:
64 // * try to allocate enough bits to represent the biggest possible result
65 // * in case of add/subtract: if all bits of the internal int are used up,
66 // keep the representation
67 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
68 class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
69 {
70 enum { MaxIntBits = (IntBits1 < IntBits2) ? IntBits2 : IntBits1,
71 MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1,
72 PlusMinusIntBits = (MaxIntBits + 1 + MaxFracBits < 32) ?
73 MaxIntBits + 1 : MaxIntBits,
74 MultipliesFracBits = (IntBits1 + IntBits2 < 31)
75 ? (FracBits1 + FracBits2) > (31 - IntBits1 - IntBits2)
76 ? 31 - IntBits1 - IntBits2
77 : FracBits1 + FracBits2
78 : 0
79 };
80 public:
81 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> PlusType;
82 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> MinusType;
83 typedef FixedPoint<IntBits1 + IntBits2, MultipliesFracBits> MultipliesType;
84 // typedef FixedPoint<IntBits1 + FracBits2, FracBits1 + IntBits2> DividesType;
85 };
86
87 template <unsigned IntBits, unsigned FracBits>
88 struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
89 {
90 enum { SRTotalBits = (IntBits + FracBits + 1) / 2,
91 SRIntBits = (IntBits + 1) / 2,
92 SRFracBits = SRTotalBits - SRIntBits
93 };
94 public:
95 typedef FixedPoint<IntBits, FracBits> Type;
96 typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
97 typedef Type SquareRootArgument;
98 };
99
100
101 #ifndef DOXYGEN
102
103 template <int N>
104 struct FixedPoint_overflow_error__More_than_31_bits_requested
105 : staticAssert::AssertBool<(N < 32)>
106 {};
107
108 #endif /* DOXYGEN */
109
110
111
112 template <bool Predicate>
113 struct FixedPoint_assignment_error__Target_object_has_too_few_integer_bits
114 : staticAssert::AssertBool<Predicate>
115 {};
116
117 enum FixedPointNoShift { FPNoShift };
118
119 namespace detail {
120
121 template <bool MustRound>
122 struct FPAssignWithRound;
123
124 template <>
125 struct FPAssignWithRound<false>
126 {
127 template <int N>
128 static inline int exec(int v) { return v << (-N); }
129 };
130
131 template <>
132 struct FPAssignWithRound<true>
133 {
134 template <int N>
135 static inline int exec(int const v)
136 {
137 return (v + (1 << (N - 1))) >> (N);
138 }
139 };
140
141 template <bool MustRound>
142 struct FPMulImplementation;
143
144 template <>
145 struct FPMulImplementation<false>
146 {
147 template <int N>
148 static inline int exec(int l, int r) { return (l * r) << (-N); }
149 };
150
151 template <>
152 struct FPMulImplementation<true>
153 {
154 template <int N>
155 static inline int exec(int l, int r)
156 {
157 // there is not enough space in the result
158 // => perform calculations that preserve as much accuracy as possible
159 enum { diffl = N / 2, diffr = N - diffl, maskl = (1 << diffl) - 1, maskr = (1 << diffr) - 1 };
160 int shiftl = l >> diffl;
161 int shiftr = r >> diffr;
162
163 return shiftl * shiftr + (((l & maskl) * shiftr) >> diffl) +
164 (((r & maskr) * shiftl) >> diffr);
165 }
166 };
167
168 } // namespace detail
169
170 /********************************************************/
171 /* */
172 /* FixedPoint */
173 /* */
174 /********************************************************/
175
176 /** Template for fixed point arithmetic.
177
178 Fixed point arithmetic is used when computations with fractional accuracy
179 must be made at the highest speed possible (e.g. in the inner loop
180 of a volume rendering routine). The speed-up relative to floating
181 point arithmetic can be dramatic, especially when one can avoid
182 conversions between integer anfloating point numbers (these are
183 very expensive because integer and floating point arithmetic
184 resides in different pipelines).
185
186 The template wraps an <tt>int</tt> and uses <tt>IntBits</tt> to
187 represent the integral part of a number, and <tt>FractionalBits</tt>
188 for the fractional part, where <tt>IntBits + FractionalBits < 32</tt>.
189 (The 32rd bit is reserved because FixedPoint is a signed type).
190 These numbers will be automatically allocated in an intelligent way
191 in the result of an arithmetic operation. For example, when two
192 fixed point numbers are multiplied, the required number of integer
193 bits in the result is the sum of the number of integer bits of the
194 arguments, but only when so many bits are avaiable. This is figured out
195 by means of FixedPointTraits, and a compile-time error is raised
196 when no suitable representation can be found. The idea is that the right
197 thing happens automatically as often as possible.
198
199 <tt>FixedPoint</tt> implements the required interface of an
200 \ref AlgebraicRing and the required numeric and
201 promotion traits. In addition, it supports functions <tt>add</tt>,
202 <tt>sub</tt>, and <tt>mul</tt>, where a particular layout of the result can
203 be enforced.
204
205 <tt>unsigned char, signed char, unsigned short, signed short, int</tt> can be
206 transformed into a FixedPoint with appropriate layout by means of the factory
207 function <tt>fixedPoint()</tt>.
208
209 <b>See also:</b>
210 <ul>
211 <li> \ref FixedPointOperations
212 <li> \ref FixedPointTraits
213 </ul>
214
215 <b>\#include</b> "<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>"<br>
216 Namespace: vigra
217 */
218 template <unsigned IntBits, unsigned FractionalBits>
219 class FixedPoint
220 {
221 public:
222 enum {
223 INT_BITS = IntBits,
224 FRACTIONAL_BITS = FractionalBits,
225 TOTAL_BITS = IntBits + FractionalBits,
226 MAX = (int)(((unsigned)1 << TOTAL_BITS) - 1),
227 ONE = 1 << FractionalBits,
228 ONE_HALF = ONE >> 1,
229 FRACTIONAL_MASK = ONE - 1,
230 INT_MASK = MAX ^ FRACTIONAL_MASK
231 };
232
233 Int32 value;
234
235 FixedPoint()
236 {
237 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
238 }
239
240 /** Construct from an int (fractional part will become zero).
241 */
242 explicit FixedPoint(int v)
243 : value(v << FractionalBits)
244 {
245 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
246 }
247
248 /** Construct from an int by a bitwise copy. This is normally only used internally.
249 */
250 FixedPoint(int v, FixedPointNoShift)
251 : value(v)
252 {
253 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
254 }
255
256 /** Construct from an double and round the fractional part to
257 <tt>FractionalBits</tt> accuracy. A PreconditionViolation exception is raised when
258 the integer part is too small to represent the number.
259 */
260 explicit FixedPoint(double rhs)
261 : value((int)round(rhs * ONE))
262 {
263 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
264 vigra_precondition(abs(rhs * ONE) <= (double)MAX,
265 "FixedPoint(double rhs): Too few integer bits to convert rhs.");
266 }
267
268 /** Copy constructor.
269 */
270 FixedPoint(const FixedPoint &other)
271 : value(other.value)
272 {}
273
274 /** Construct from a FixedPoint with different layout. It rounds as appropriate and raises
275 a compile-time error when the target type has too few integer bits.
276 */
277 template <unsigned Int2, unsigned Frac2>
278 FixedPoint(const FixedPoint<Int2, Frac2> &other)
279 : value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value))
280 {
281 VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
282 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
283 }
284
285 /** Assignment from int. The fractional part will become zero.
286 A PreconditionViolation exception is raised when
287 the integer part is too small to represent the number.
288 */
289 FixedPoint &operator=(int rhs)
290 {
291 vigra_precondition(abs(rhs) < (1 << IntBits),
292 "FixedPoint::operator=(int rhs): Too few integer bits to represent rhs.");
293 value = rhs << FractionalBits;
294 return *this;
295 }
296
297 /** Assignment form double. The fractional part is rounded, and a
298 PreconditionViolation exception is raised when
299 the integer part is too small to represent the number.
300 */
301 FixedPoint &operator=(double rhs)
302 {
303 vigra_precondition(abs(rhs) <= ((1 << IntBits) - 1),
304 "FixedPoint::operator=(double rhs): Too few integer bits to convert rhs.");
305 value = (int)round(rhs * ONE);
306 return *this;
307 }
308
309 /** Copy assignment.
310 */
311 FixedPoint & operator=(const FixedPoint &other)
312 {
313 value = other.value;
314 return *this;
315 }
316
privateOrderOpt()317 /** Assignment from a FixedPoint with different layout. It rounds as appropriate and raises
318 a compile-time error when the target type has too few integer bits.
319 */
320 template <unsigned Int2, unsigned Frac2>
321 FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other)
322 {
323 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
324 value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
325 return *this;
326 }
327
328 /** Negation.
329 */
330 FixedPoint operator-() const
331 {
332 return FixedPoint(-value, FPNoShift);
333 }
334
335 /** Pre-increment.
336 */
337 FixedPoint & operator++()
338 {
339 value += ONE;
340 return *this;
341 }
342
343 /** Post-increment.
344 */
345 FixedPoint operator++(int)
346 {
347 FixedPoint old(*this);
348 value += ONE;
349 return old;
350 }
351
352 /** Pre-decrement.
353 */
354 FixedPoint & operator--()
355 {
356 value -= ONE;
357 return *this;
358 }
359
360 /** Post-decrement.
361 */
362 FixedPoint operator--(int)
363 {
364 FixedPoint old(*this);
365 value -= ONE;
366 return old;
367 }
368
369 /** Add-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
370 a compile-time error when the target type has too few integer bits.
371 */
372 template <unsigned Int2, unsigned Frac2>
373 FixedPoint & operator+=(const FixedPoint<Int2, Frac2> &other)
374 {
375 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
376 value += detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
377 return *this;
378 }
379
380 /** Subtract-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
381 a compile-time error when the target type has too few integer bits.
382 */
383 template <unsigned Int2, unsigned Frac2>
384 FixedPoint & operator-=(const FixedPoint<Int2, Frac2> &other)
385 {
386 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
387 value -= detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
388 return *this;
389 }
390
391 /** Multiply-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
392 a compile-time error when the target type has too few integer bits.
393 */
394 template <unsigned Int2, unsigned Frac2>
395 FixedPoint & operator*=(const FixedPoint<Int2, Frac2> &other)
396 {
397 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
398 value = detail::FPMulImplementation<(Frac2 > 0)>::template exec<Frac2>(value, other.value);
399 return *this;
400 }
401 };
402
403 #define VIGRA_FIXED_POINT_FACTORY(T, INTBITS) \
404 inline FixedPoint<INTBITS, 0> fixedPoint(T t) \
405 { \
406 return FixedPoint<INTBITS, 0>(t, FPNoShift); \
407 }
408
409 VIGRA_FIXED_POINT_FACTORY(unsigned char, 8)
410 VIGRA_FIXED_POINT_FACTORY(signed char, 7)
411 VIGRA_FIXED_POINT_FACTORY(unsigned short, 16)
412 VIGRA_FIXED_POINT_FACTORY(signed short, 15)
413 VIGRA_FIXED_POINT_FACTORY(int, 31)
414
415 #undef VIGRA_FIXED_POINT_FACTORY
416
417 template <class T>
418 struct FixedPointCast;
419
420 #define VIGRA_FIXED_POINT_CAST(type) \
421 template <> \
422 struct FixedPointCast<type> \
423 { \
424 template <unsigned IntBits, unsigned FracBits> \
425 static type cast(FixedPoint<IntBits, FracBits> v) \
426 { \
427 return round(v); \
428 } \
429 };
430
431 VIGRA_FIXED_POINT_CAST(Int8)
432 VIGRA_FIXED_POINT_CAST(UInt8)
433 VIGRA_FIXED_POINT_CAST(Int16)
434 VIGRA_FIXED_POINT_CAST(UInt16)
435 VIGRA_FIXED_POINT_CAST(Int32)
436 VIGRA_FIXED_POINT_CAST(UInt32)
437
438 #undef VIGRA_FIXED_POINT_CAST
439
440 template <>
441 struct FixedPointCast<float>
442 {
443 template <unsigned IntBits, unsigned FracBits>
444 static float cast(FixedPoint<IntBits, FracBits> v)
445 {
446 return (float)v.value / FixedPoint<IntBits, FracBits>::ONE;
447 }
448 };
449
450 template <>
451 struct FixedPointCast<double>
452 {
453 template <unsigned IntBits, unsigned FracBits>
454 static double cast(FixedPoint<IntBits, FracBits> v)
455 {
456 return (double)v.value / FixedPoint<IntBits, FracBits>::ONE;
457 }
458 };
459
460 /********************************************************/
461 /* */
462 /* FixedPointOperations */
463 /* */
464 /********************************************************/
465
466 /** \addtogroup FixedPointOperations Functions for FixedPoint
467
468 \brief <b>\#include</b> "<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>"<br>
469
470 These functions fulfill the requirements of an \ref AlgebraicRing.
471
472 Namespace: vigra
473 <p>
474
475 */
476 //@{
477
478 /** Convert a FixedPoint to a built-in type.
479 If the target is integral, the value is rounded.<br>
480 Usage:
481 \code
482 FixedPoint<16,15> fp(...);
483
484 double d = fixed_point_cast<double>(fp);
485 \endcode
486 */
487 template <class TARGET, unsigned IntBits, unsigned FracBits>
488 TARGET fixed_point_cast(FixedPoint<IntBits, FracBits> v)
489 {
490 return FixedPointCast<TARGET>::cast(v);
491 }
492
493 /// equal
494 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
495 inline
496 bool operator==(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
497 {
498 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
499 return (l.value << (MaxFracBits - FracBits1)) == (r.value << (MaxFracBits - FracBits2));
500 }
501
502 /// not equal
503 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
504 inline
505 bool operator!=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
506 {
507 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
508 return (l.value << (MaxFracBits - FracBits1)) != (r.value << (MaxFracBits - FracBits2));
509 }
510
511 /// less than
512 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
513 inline
514 bool operator<(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
515 {
516 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
517 return (l.value << (MaxFracBits - FracBits1)) < (r.value << (MaxFracBits - FracBits2));
518 }
519
520 /// less or equal
521 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
522 inline
523 bool operator<=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
524 {
525 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
526 return (l.value << (MaxFracBits - FracBits1)) <= (r.value << (MaxFracBits - FracBits2));
527 }
528
529 /// greater
530 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
531 inline
532 bool operator>(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
privateCertOpt()533 {
534 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
535 return (l.value << (MaxFracBits - FracBits1)) > (r.value << (MaxFracBits - FracBits2));
536 }
537
538 /// greater or equal
539 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
540 inline
541 bool operator>=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
542 {
543 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
544 return (l.value << (MaxFracBits - FracBits1)) >= (r.value << (MaxFracBits - FracBits2));
545 }
546
547 /// addition with automatic determination of the appropriate result type.
548 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
549 inline
550 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
551 operator+(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
552 {
553 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
554 return typename
555 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
556 PlusType((l.value << (MaxFracBits - FracBits1)) + (r.value << (MaxFracBits - FracBits2)), FPNoShift);
557 }
558
559 /// addition with enforced result type.
560 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
561 unsigned IntBits3, unsigned FracBits3>
562 inline void
563 add(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
564 FixedPoint<IntBits3, FracBits3> & result)
565 {
566 result = l + r;
567 }
568
569 /// subtraction with automatic determination of the appropriate result type.
570 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
571 inline
572 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MinusType
573 operator-(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
574 {
575 enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
576 return typename
577 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
578 MinusType((l.value << (MaxFracBits - FracBits1)) - (r.value << (MaxFracBits - FracBits2)), FPNoShift);
579 }
580
581 /// subtraction with enforced result type.
582 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
583 unsigned IntBits3, unsigned FracBits3>
584 inline void
585 sub(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
586 FixedPoint<IntBits3, FracBits3> & result)
587 {
588 result = l - r;
589 }
590
591 /// multiplication with automatic determination of the appropriate result type.
592 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
593 inline
594 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MultipliesType
595 operator*(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
596 {
597 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
598 MultipliesType res;
599 mul(l, r, res);
600 return res;
601 }
602
603 /// multiplication with enforced result type.
604 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
605 unsigned IntBits3, unsigned FracBits3>
606 inline void
607 mul(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
608 FixedPoint<IntBits3, FracBits3> & result)
609 {
610 VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits1 + IntBits2 <= IntBits3)>));
611 enum { diff = FracBits1 + FracBits2 - FracBits3 };
612 result.value = detail::FPMulImplementation<(diff > 0)>::template exec<diff>(l.value, r.value);
613 }
614
615 /// square root.
616 template <unsigned IntBits, unsigned FracBits>
617 inline typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult
618 sqrt(FixedPoint<IntBits, FracBits> v)
619 {
620 return typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult(sqrti(v.value), FPNoShift);
621 }
622
623 /// absolute value.
624 template <unsigned IntBits, unsigned FracBits>
625 inline FixedPoint<IntBits, FracBits>
626 abs(FixedPoint<IntBits, FracBits> v)
627 {
628 return FixedPoint<IntBits, FracBits>(abs(v.value), FPNoShift);
629 }
630
631 /// squared norm (same as v*v).
632 template <unsigned IntBits, unsigned FracBits>
633 inline
634 typename FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
635 squaredNorm(FixedPoint<IntBits, FracBits> v)
636 {
637 return v*v;
638 }
639
640 /// norm (same as abs).
641 template <unsigned IntBits, unsigned FracBits>
642 inline
643 FixedPoint<IntBits, FracBits>
644 norm(FixedPoint<IntBits, FracBits> const & v)
645 {
646 return abs(v);
647 }
648
649 /// fractional part.
650 template <unsigned IntBits, unsigned FracBits>
651 inline FixedPoint<0, FracBits>
652 frac(FixedPoint<IntBits, FracBits> v)
653 {
654 return FixedPoint<0, FracBits>(v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK, FPNoShift);
655 }
656
657 /// dual fractional part: <tt>1 - frac(v)</tt>.
658 template <unsigned IntBits, unsigned FracBits>
659 inline FixedPoint<0, FracBits>
660 dual_frac(FixedPoint<IntBits, FracBits> v)
661 {
662 return FixedPoint<0, FracBits>(FixedPoint<0, FracBits>::ONE -
663 (v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK), FPNoShift);
664 }
665
666 /// rounding down.
667 template <unsigned IntBits, unsigned FracBits>
668 inline int
669 floor(FixedPoint<IntBits, FracBits> v)
670 {
671 return(v.value >> FracBits);
672 }
673
674 /// rounding up.
675 template <unsigned IntBits, unsigned FracBits>
676 inline int
677 ceil(FixedPoint<IntBits, FracBits> v)
678 {
679 return((v.value + FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK) >> FracBits);
680 }
681
682 /// rounding to the nearest integer.
683 template <unsigned IntBits, unsigned FracBits>
684 inline int
685 round(FixedPoint<IntBits, FracBits> v)
686 {
687 return((v.value + FixedPoint<IntBits, FracBits>::ONE_HALF) >> FracBits);
688 }
689
690 //@}
691
692 /********************************************************/
693 /* */
694 /* FixedPoint-Traits */
695 /* */
696 /********************************************************/
697
698 /** \page FixedPointTraits Numeric and Promote Traits of FixedPoint
699
700 The numeric and promote traits for FixedPoint follow
701 the general specifications for \ref NumericPromotionTraits and
702 \ref AlgebraicRing. They are implemented in terms of the traits of the basic types by
703 partial template specialization:
704
705 \code
706
707 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
708 class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
709 {
710 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> PlusType;
711 typedef FixedPoint<PlusMinusIntBits, MaxFracBits> MinusType;
712 typedef FixedPoint<IntBits1 + IntBits2, FracBits1 + FracBits2> MultipliesType;
713 };
714
715 template <unsigned IntBits, unsigned FracBits>
716 struct NumericTraits<FixedPoint<IntBits, FracBits> >
717 {
718 typedef FixedPoint<IntBits, FracBits> Type;
719 // Promote undefined because it depends on the layout, use FixedPointTraits
720 // RealPromote in AlgebraicRing -- multiplication with double is not supported.
721 // ComplexPromote in AlgebraicRing -- multiplication with double is not supported.
722 typedef Type ValueType;
723
724 typedef VigraFalseType isIntegral;
725 typedef VigraTrueType isScalar;
726 typedef VigraTrueType isSigned;
727 typedef VigraTrueType isOrdered;
728 typedef VigraFalseType isComplex;
729
730 ... // etc.
731 };
732
733 template <unsigned IntBits, unsigned FracBits>
734 struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
735 {
736 typedef FixedPoint<IntBits, FracBits> Type;
737 typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
738 typedef Type SquareRootArgument;
739 };
740
741 template <unsigned IntBits, unsigned FracBits>
742 struct NormTraits<FixedPoint<IntBits, FracBits> >
743 {
744 typedef FixedPoint<IntBits, FracBits> Type;
745 typedef typename
746 FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
747 SquaredNormType;
748 typedef Type NormType;
749 };
750
751 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
752 struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
753 FixedPoint<IntBits2, FracBits2> >
754 {
755 typedef typename
756 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
757 Promote;
758 };
759 \endcode
760
761 <b>\#include</b> "<a href="fixedpoint_8hxx-source.html">vigra/fixedpoint.hxx</a>"<br>
762 Namespace: vigra
763
764 */
765 template <unsigned IntBits, unsigned FracBits>
766 struct NumericTraits<FixedPoint<IntBits, FracBits> >
767 {
768 typedef FixedPoint<IntBits, FracBits> Type;
769 //typedef FixedPoint<IntBits, FracBits> Promote;
770 //typedef FixedPoint<IntBits, FracBits> RealPromote;
771 //typedef std::complex<RealPromote> ComplexPromote;
772 typedef Type ValueType;
773
774 typedef VigraFalseType isIntegral;
775 typedef VigraTrueType isScalar;
776 typedef VigraTrueType isSigned;
777 typedef VigraTrueType isOrdered;
778 typedef VigraFalseType isComplex;
779
780 static Type zero() { return Type(0, FPNoShift); }
781 static Type one() { return Type(Type::ONE, FPNoShift); }
782 static Type nonZero() { return one(); }
783 static Type epsilon() { return Type(1, FPNoShift); }
784 static Type smallestPositive() { return Type(1, FPNoShift); }
785 static Type max() { return Type( Type::MAX, FPNoShift); }
786 static Type min() { return -max(); }
787 };
788
789 template <unsigned IntBits, unsigned FracBits>
790 struct NormTraits<FixedPoint<IntBits, FracBits> >
791 {
792 typedef FixedPoint<IntBits, FracBits> Type;
793 typedef typename
794 FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
795 SquaredNormType;
796 typedef Type NormType;
797 };
798
799 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
800 struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
801 FixedPoint<IntBits2, FracBits2> >
802 {
803 typedef typename
804 FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
805 Promote;
806 };
807
808 } // namespace vigra
809
810 #endif // VIGRA_FIXEDPOINT_HXX
811