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 &lt; 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