[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

fixedpoint.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2004-2005 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_FIXEDPOINT_HXX
37 #define VIGRA_FIXEDPOINT_HXX
38 
39 #include "mathutil.hxx"
40 #include "static_assert.hxx"
41 #include "error.hxx"
42 #include "numerictraits.hxx"
43 
44 namespace vigra {
45 
46 template <unsigned IntBits, unsigned FractionalBits>
47 class FixedPoint;
48 
49 struct Error_FixedPointTraits_not_specialized_for_this_case;
50 
51 template <class T1, class T2>
52 class FixedPointTraits
53 {
54 public:
55  typedef Error_FixedPointTraits_not_specialized_for_this_case PlusType;
56  typedef Error_FixedPointTraits_not_specialized_for_this_case MinusType;
57  typedef Error_FixedPointTraits_not_specialized_for_this_case MultipliesType;
58 // typedef Error_FixedPointTraits_not_specialized_for_this_case DividesType;
59 };
60 
61 // return type policy:
62 // * try to allocate enough bits to represent the biggest possible result
63 // * in case of add/subtract: if all bits of the internal int are used up,
64 // keep the representation
65 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
66 class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
67 {
68  enum { MaxIntBits = (IntBits1 < IntBits2) ? IntBits2 : IntBits1,
69  MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1,
70  PlusMinusIntBits = (MaxIntBits + 1 + MaxFracBits < 32) ?
71  MaxIntBits + 1 : MaxIntBits,
72  MultipliesFracBits = (IntBits1 + IntBits2 < 31)
73  ? (FracBits1 + FracBits2) > (31 - IntBits1 - IntBits2)
74  ? 31 - IntBits1 - IntBits2
75  : FracBits1 + FracBits2
76  : 0
77  };
78 public:
79  typedef FixedPoint<PlusMinusIntBits, MaxFracBits> PlusType;
80  typedef FixedPoint<PlusMinusIntBits, MaxFracBits> MinusType;
81  typedef FixedPoint<IntBits1 + IntBits2, MultipliesFracBits> MultipliesType;
82 // typedef FixedPoint<IntBits1 + FracBits2, FracBits1 + IntBits2> DividesType;
83 };
84 
85 template <unsigned IntBits, unsigned FracBits>
86 struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
87 {
88  enum { SRTotalBits = (IntBits + FracBits + 1) / 2,
89  SRIntBits = (IntBits + 1) / 2,
90  SRFracBits = SRTotalBits - SRIntBits
91  };
92 public:
93  typedef FixedPoint<IntBits, FracBits> Type;
94  typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
95  typedef Type SquareRootArgument;
96 };
97 
98 
99 #ifndef DOXYGEN
100 
101 template <int N>
102 struct FixedPoint_overflow_error__More_than_31_bits_requested
103 : staticAssert::AssertBool<(N < 32)>
104 {};
105 
106 #endif /* DOXYGEN */
107 
108 
109 
110 template <bool Predicate>
111 struct FixedPoint_assignment_error__Target_object_has_too_few_integer_bits
112 : staticAssert::AssertBool<Predicate>
113 {};
114 
115 enum FixedPointNoShift { FPNoShift };
116 
117 namespace detail {
118 
119 template <bool MustRound>
120 struct FPAssignWithRound;
121 
122 template <>
123 struct FPAssignWithRound<false>
124 {
125  template <int N>
126  static inline int exec(int v) { return v << (-N); }
127 };
128 
129 template <>
130 struct FPAssignWithRound<true>
131 {
132  template <int N>
133  static inline int exec(int const v)
134  {
135  return (v + (1 << (N - 1))) >> (N);
136  }
137 };
138 
139 template <bool MustRound>
140 struct FPMulImplementation;
141 
142 template <>
143 struct FPMulImplementation<false>
144 {
145  template <int N>
146  static inline int exec(int l, int r) { return (l * r) << (-N); }
147 };
148 
149 template <>
150 struct FPMulImplementation<true>
151 {
152  template <int N>
153  static inline int exec(int l, int r)
154  {
155  // there is not enough space in the result
156  // => perform calculations that preserve as much accuracy as possible
157  enum { diffl = N / 2, diffr = N - diffl, maskl = (1 << diffl) - 1, maskr = (1 << diffr) - 1 };
158  int shiftl = l >> diffl;
159  int shiftr = r >> diffr;
160 
161  return shiftl * shiftr + (((l & maskl) * shiftr) >> diffl) +
162  (((r & maskr) * shiftl) >> diffr);
163  }
164 };
165 
166 } // namespace detail
167 
168 /********************************************************/
169 /* */
170 /* FixedPoint */
171 /* */
172 /********************************************************/
173 
174 /** Template for fixed point arithmetic.
175 
176  Fixed point arithmetic is used when computations with fractional accuracy
177  must be made at the highest speed possible (e.g. in the inner loop
178  of a volume rendering routine). The speed-up relative to floating
179  point arithmetic can be dramatic, especially when one can avoid
180  conversions between integer and floating point numbers (these are
181  very expensive because integer and floating point arithmetic
182  resides in different pipelines).
183 
184  The template wraps an <tt>int</tt> and uses <tt>IntBits</tt> to
185  represent the integral part of a number, and <tt>FractionalBits</tt>
186  for the fractional part, where <tt>IntBits + FractionalBits < 32</tt>.
187  (The 32rd bit is reserved because FixedPoint is a signed type).
188  These numbers will be automatically allocated in an intelligent way
189  in the result of an arithmetic operation. For example, when two
190  fixed point numbers are multiplied, the required number of integer
191  bits in the result is the sum of the number of integer bits of the
192  arguments, but only when so many bits are available. This is figured out
193  by means of FixedPointTraits, and a compile-time error is raised
194  when no suitable representation can be found. The idea is that the right
195  thing happens automatically as often as possible.
196 
197  <tt>FixedPoint</tt> implements the required interface of an
198  \ref AlgebraicRing and the required numeric and
199  promotion traits. In addition, it supports functions <tt>add</tt>,
200  <tt>sub</tt>, and <tt>mul</tt>, where a particular layout of the result can
201  be enforced.
202 
203  <tt>unsigned char, signed char, unsigned short, signed short, int</tt> can be
204  transformed into a FixedPoint with appropriate layout by means of the factory
205  function <tt>fixedPoint()</tt>.
206 
207  <b>See also:</b>
208  <ul>
209  <li> \ref FixedPointOperations
210  <li> \ref FixedPointTraits
211  </ul>
212 
213  <b>\#include</b> <vigra/fixedpoint.hxx><br>
214  Namespace: vigra
215 */
216 template <unsigned IntBits, unsigned FractionalBits>
217 class FixedPoint
218 {
219 public:
220  enum {
221  INT_BITS = IntBits,
222  FRACTIONAL_BITS = FractionalBits,
223  TOTAL_BITS = IntBits + FractionalBits,
224  MAX = (int)(((unsigned)1 << TOTAL_BITS) - 1),
225  ONE = 1 << FractionalBits,
226  ONE_HALF = ONE >> 1,
227  FRACTIONAL_MASK = ONE - 1,
228  INT_MASK = MAX ^ FRACTIONAL_MASK
229  };
230 
231  Int32 value;
232 
233  FixedPoint()
234  {
235  VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
236  }
237 
238  /** Construct from an int (fractional part will become zero).
239  */
240  explicit FixedPoint(int v)
241  : value(v << FractionalBits)
242  {
243  VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
244  }
245 
246  /** Construct from an int by a bitwise copy. This is normally only used internally.
247  */
248  FixedPoint(int v, FixedPointNoShift)
249  : value(v)
250  {
251  VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
252  }
253 
254  /** Construct from an double and round the fractional part to
255  <tt>FractionalBits</tt> accuracy. A PreconditionViolation exception is raised when
256  the integer part is too small to represent the number.
257  */
258  explicit FixedPoint(double rhs)
259  : value((int)round(rhs * ONE))
260  {
261  VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
262  vigra_precondition(abs(rhs * ONE) <= (double)MAX,
263  "FixedPoint(double rhs): Too few integer bits to convert rhs.");
264  }
265 
266  /** Copy constructor.
267  */
268  FixedPoint(const FixedPoint &other)
269  : value(other.value)
270  {}
271 
272  /** Construct from a FixedPoint with different layout. It rounds as appropriate and raises
273  a compile-time error when the target type has too few integer bits.
274  */
275  template <unsigned Int2, unsigned Frac2>
276  FixedPoint(const FixedPoint<Int2, Frac2> &other)
277  : value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<int(Frac2) - int(FractionalBits)>(other.value))
278  {
279  VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_requested<(IntBits + FractionalBits)>));
280  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
281  }
282 
283  /** Assignment from int. The fractional part will become zero.
284  A PreconditionViolation exception is raised when
285  the integer part is too small to represent the number.
286  */
287  FixedPoint &operator=(int rhs)
288  {
289  vigra_precondition(abs(rhs) < (1 << IntBits),
290  "FixedPoint::operator=(int rhs): Too few integer bits to represent rhs.");
291  value = rhs << FractionalBits;
292  return *this;
293  }
294 
295  /** Assignment form double. The fractional part is rounded, and a
296  PreconditionViolation exception is raised when
297  the integer part is too small to represent the number.
298  */
299  FixedPoint &operator=(double rhs)
300  {
301  vigra_precondition(abs(rhs) <= ((1 << IntBits) - 1),
302  "FixedPoint::operator=(double rhs): Too few integer bits to convert rhs.");
303  value = (int)round(rhs * ONE);
304  return *this;
305  }
306 
307  /** Copy assignment.
308  */
309  FixedPoint & operator=(const FixedPoint &other)
310  {
311  value = other.value;
312  return *this;
313  }
314 
315  /** Assignment from a FixedPoint with different layout. It rounds as appropriate and raises
316  a compile-time error when the target type has too few integer bits.
317  */
318  template <unsigned Int2, unsigned Frac2>
319  FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other)
320  {
321  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
322  value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<int(Frac2) - int(FractionalBits)>(other.value);
323  return *this;
324  }
325 
326  /** Negation.
327  */
328  FixedPoint operator-() const
329  {
330  return FixedPoint(-value, FPNoShift);
331  }
332 
333  /** Pre-increment.
334  */
335  FixedPoint & operator++()
336  {
337  value += ONE;
338  return *this;
339  }
340 
341  /** Post-increment.
342  */
343  FixedPoint operator++(int)
344  {
345  FixedPoint old(*this);
346  value += ONE;
347  return old;
348  }
349 
350  /** Pre-decrement.
351  */
352  FixedPoint & operator--()
353  {
354  value -= ONE;
355  return *this;
356  }
357 
358  /** Post-decrement.
359  */
360  FixedPoint operator--(int)
361  {
362  FixedPoint old(*this);
363  value -= ONE;
364  return old;
365  }
366 
367  /** Add-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
368  a compile-time error when the target type has too few integer bits.
369  */
370  template <unsigned Int2, unsigned Frac2>
371  FixedPoint & operator+=(const FixedPoint<Int2, Frac2> &other)
372  {
373  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
374  value += detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
375  return *this;
376  }
377 
378  /** Subtract-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
379  a compile-time error when the target type has too few integer bits.
380  */
381  template <unsigned Int2, unsigned Frac2>
382  FixedPoint & operator-=(const FixedPoint<Int2, Frac2> &other)
383  {
384  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
385  value -= detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template exec<Frac2 - FractionalBits>(other.value);
386  return *this;
387  }
388 
389  /** Multiply-assignment from a FixedPoint with different layout. It rounds as appropriate and raises
390  a compile-time error when the target type has too few integer bits.
391  */
392  template <unsigned Int2, unsigned Frac2>
393  FixedPoint & operator*=(const FixedPoint<Int2, Frac2> &other)
394  {
395  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits >= Int2)>));
396  value = detail::FPMulImplementation<(Frac2 > 0)>::template exec<Frac2>(value, other.value);
397  return *this;
398  }
399 };
400 
401 #define VIGRA_FIXED_POINT_FACTORY(T, INTBITS) \
402  inline FixedPoint<INTBITS, 0> fixedPoint(T t) \
403  { \
404  return FixedPoint<INTBITS, 0>(t, FPNoShift); \
405  }
406 
407 VIGRA_FIXED_POINT_FACTORY(unsigned char, 8)
408 VIGRA_FIXED_POINT_FACTORY(signed char, 7)
409 VIGRA_FIXED_POINT_FACTORY(unsigned short, 16)
410 VIGRA_FIXED_POINT_FACTORY(signed short, 15)
411 VIGRA_FIXED_POINT_FACTORY(int, 31)
412 
413 #undef VIGRA_FIXED_POINT_FACTORY
414 
415 template <class T>
416 struct FixedPointCast;
417 
418 #define VIGRA_FIXED_POINT_CAST(type) \
419 template <> \
420 struct FixedPointCast<type> \
421 { \
422  template <unsigned IntBits, unsigned FracBits> \
423  static type cast(FixedPoint<IntBits, FracBits> v) \
424  { \
425  return round(v); \
426  } \
427 };
428 
429 VIGRA_FIXED_POINT_CAST(Int8)
430 VIGRA_FIXED_POINT_CAST(UInt8)
431 VIGRA_FIXED_POINT_CAST(Int16)
432 VIGRA_FIXED_POINT_CAST(UInt16)
433 VIGRA_FIXED_POINT_CAST(Int32)
434 VIGRA_FIXED_POINT_CAST(UInt32)
435 
436 #undef VIGRA_FIXED_POINT_CAST
437 
438 template <>
439 struct FixedPointCast<float>
440 {
441  template <unsigned IntBits, unsigned FracBits>
442  static float cast(FixedPoint<IntBits, FracBits> v)
443  {
444  return (float)v.value / FixedPoint<IntBits, FracBits>::ONE;
445  }
446 };
447 
448 template <>
449 struct FixedPointCast<double>
450 {
451  template <unsigned IntBits, unsigned FracBits>
452  static double cast(FixedPoint<IntBits, FracBits> v)
453  {
454  return (double)v.value / FixedPoint<IntBits, FracBits>::ONE;
455  }
456 };
457 
458 /********************************************************/
459 /* */
460 /* FixedPointOperations */
461 /* */
462 /********************************************************/
463 
464 /** \addtogroup FixedPointOperations Functions for FixedPoint
465 
466  \brief <b>\#include</b> <vigra/fixedpoint.hxx><br>
467 
468  These functions fulfill the requirements of an \ref AlgebraicRing.
469 
470  Namespace: vigra
471  <p>
472 
473  */
474 //@{
475 
476  /** Convert a FixedPoint to a built-in type.
477  If the target is integral, the value is rounded.<br>
478  Usage:
479  \code
480  FixedPoint<16,15> fp(...);
481 
482  double d = fixed_point_cast<double>(fp);
483  \endcode
484  */
485 template <class TARGET, unsigned IntBits, unsigned FracBits>
486 TARGET fixed_point_cast(FixedPoint<IntBits, FracBits> v)
487 {
488  return FixedPointCast<TARGET>::cast(v);
489 }
490 
491  /// equal
492 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
493 inline
494 bool operator==(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
495 {
496  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
497  return (l.value << (MaxFracBits - FracBits1)) == (r.value << (MaxFracBits - FracBits2));
498 }
499 
500  /// not equal
501 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
502 inline
503 bool operator!=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
504 {
505  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
506  return (l.value << (MaxFracBits - FracBits1)) != (r.value << (MaxFracBits - FracBits2));
507 }
508 
509  /// less than
510 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
511 inline
512 bool operator<(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
513 {
514  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
515  return (l.value << (MaxFracBits - FracBits1)) < (r.value << (MaxFracBits - FracBits2));
516 }
517 
518  /// less or equal
519 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
520 inline
521 bool operator<=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
522 {
523  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
524  return (l.value << (MaxFracBits - FracBits1)) <= (r.value << (MaxFracBits - FracBits2));
525 }
526 
527  /// greater
528 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
529 inline
530 bool operator>(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
531 {
532  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
533  return (l.value << (MaxFracBits - FracBits1)) > (r.value << (MaxFracBits - FracBits2));
534 }
535 
536  /// greater or equal
537 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
538 inline
539 bool operator>=(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
540 {
541  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
542  return (l.value << (MaxFracBits - FracBits1)) >= (r.value << (MaxFracBits - FracBits2));
543 }
544 
545  /// addition with automatic determination of the appropriate result type.
546 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
547 inline
548 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
549 operator+(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
550 {
551  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
552  return typename
553  FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
554  PlusType((l.value << (MaxFracBits - FracBits1)) + (r.value << (MaxFracBits - FracBits2)), FPNoShift);
555 }
556 
557  /// addition with enforced result type.
558 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
559  unsigned IntBits3, unsigned FracBits3>
560 inline void
561 add(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
562  FixedPoint<IntBits3, FracBits3> & result)
563 {
564  result = l + r;
565 }
566 
567  /// subtraction with automatic determination of the appropriate result type.
568 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
569 inline
570 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MinusType
571 operator-(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
572 {
573  enum { MaxFracBits = (FracBits1 < FracBits2) ? FracBits2 : FracBits1 };
574  return typename
575  FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
576  MinusType((l.value << (MaxFracBits - FracBits1)) - (r.value << (MaxFracBits - FracBits2)), FPNoShift);
577 }
578 
579  /// subtraction with enforced result type.
580 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
581  unsigned IntBits3, unsigned FracBits3>
582 inline void
583 sub(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
584  FixedPoint<IntBits3, FracBits3> & result)
585 {
586  result = l - r;
587 }
588 
589  /// multiplication with automatic determination of the appropriate result type.
590 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
591 inline
592 typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MultipliesType
593 operator*(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r)
594 {
595  typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::
596  MultipliesType res;
597  mul(l, r, res);
598  return res;
599 }
600 
601  /// multiplication with enforced result type.
602 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
603  unsigned IntBits3, unsigned FracBits3>
604 inline void
605 mul(FixedPoint<IntBits1, FracBits1> l, FixedPoint<IntBits2, FracBits2> r,
606  FixedPoint<IntBits3, FracBits3> & result)
607 {
608  VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has_too_few_integer_bits<(IntBits1 + IntBits2 <= IntBits3)>));
609  enum { diff = FracBits1 + FracBits2 - FracBits3 };
610  result.value = detail::FPMulImplementation<(diff > 0)>::template exec<diff>(l.value, r.value);
611 }
612 
613  /// square root.
614 template <unsigned IntBits, unsigned FracBits>
615 inline typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult
616 sqrt(FixedPoint<IntBits, FracBits> v)
617 {
618  return typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult(sqrti(v.value), FPNoShift);
619 }
620 
621  /// absolute value.
622 template <unsigned IntBits, unsigned FracBits>
623 inline FixedPoint<IntBits, FracBits>
624 abs(FixedPoint<IntBits, FracBits> v)
625 {
626  return FixedPoint<IntBits, FracBits>(abs(v.value), FPNoShift);
627 }
628 
629  /// squared norm (same as v*v).
630 template <unsigned IntBits, unsigned FracBits>
631 inline
632 typename FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
633 squaredNorm(FixedPoint<IntBits, FracBits> v)
634 {
635  return v*v;
636 }
637 
638  /// norm (same as abs).
639 template <unsigned IntBits, unsigned FracBits>
640 inline
641 FixedPoint<IntBits, FracBits>
642 norm(FixedPoint<IntBits, FracBits> const & v)
643 {
644  return abs(v);
645 }
646 
647  /// fractional part.
648 template <unsigned IntBits, unsigned FracBits>
649 inline FixedPoint<0, FracBits>
650 frac(FixedPoint<IntBits, FracBits> v)
651 {
652  return FixedPoint<0, FracBits>(v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK, FPNoShift);
653 }
654 
655  /// dual fractional part: <tt>1 - frac(v)</tt>.
656 template <unsigned IntBits, unsigned FracBits>
657 inline FixedPoint<0, FracBits>
658 dual_frac(FixedPoint<IntBits, FracBits> v)
659 {
660  return FixedPoint<0, FracBits>(FixedPoint<0, FracBits>::ONE -
661  (v.value & FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK), FPNoShift);
662 }
663 
664  /// rounding down.
665 template <unsigned IntBits, unsigned FracBits>
666 inline int
667 floor(FixedPoint<IntBits, FracBits> v)
668 {
669  return(v.value >> FracBits);
670 }
671 
672  /// rounding up.
673 template <unsigned IntBits, unsigned FracBits>
674 inline int
675 ceil(FixedPoint<IntBits, FracBits> v)
676 {
677  return((v.value + FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK) >> FracBits);
678 }
679 
680  /// rounding to the nearest integer.
681 template <unsigned IntBits, unsigned FracBits>
682 inline int
683 round(FixedPoint<IntBits, FracBits> v)
684 {
685  return((v.value + FixedPoint<IntBits, FracBits>::ONE_HALF) >> FracBits);
686 }
687 
688 //@}
689 
690 /********************************************************/
691 /* */
692 /* FixedPoint-Traits */
693 /* */
694 /********************************************************/
695 
696 /** \page FixedPointTraits Numeric and Promote Traits of FixedPoint
697 
698  The numeric and promote traits for FixedPoint follow
699  the general specifications for \ref NumericPromotionTraits and
700  \ref AlgebraicRing. They are implemented in terms of the traits of the basic types by
701  partial template specialization:
702 
703  \code
704 
705  template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
706  class FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >
707  {
708  typedef FixedPoint<PlusMinusIntBits, MaxFracBits> PlusType;
709  typedef FixedPoint<PlusMinusIntBits, MaxFracBits> MinusType;
710  typedef FixedPoint<IntBits1 + IntBits2, FracBits1 + FracBits2> MultipliesType;
711  };
712 
713  template <unsigned IntBits, unsigned FracBits>
714  struct NumericTraits<FixedPoint<IntBits, FracBits> >
715  {
716  typedef FixedPoint<IntBits, FracBits> Type;
717  // Promote undefined because it depends on the layout, use FixedPointTraits
718  // RealPromote in AlgebraicRing -- multiplication with double is not supported.
719  // ComplexPromote in AlgebraicRing -- multiplication with double is not supported.
720  typedef Type ValueType;
721 
722  typedef VigraFalseType isIntegral;
723  typedef VigraTrueType isScalar;
724  typedef VigraTrueType isSigned;
725  typedef VigraTrueType isOrdered;
726  typedef VigraFalseType isComplex;
727 
728  ... // etc.
729  };
730 
731  template <unsigned IntBits, unsigned FracBits>
732  struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
733  {
734  typedef FixedPoint<IntBits, FracBits> Type;
735  typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
736  typedef Type SquareRootArgument;
737  };
738 
739  template <unsigned IntBits, unsigned FracBits>
740  struct NormTraits<FixedPoint<IntBits, FracBits> >
741  {
742  typedef FixedPoint<IntBits, FracBits> Type;
743  typedef typename
744  FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
745  SquaredNormType;
746  typedef Type NormType;
747  };
748 
749  template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
750  struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
751  FixedPoint<IntBits2, FracBits2> >
752  {
753  typedef typename
754  FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
755  Promote;
756  };
757  \endcode
758 
759  <b>\#include</b> <vigra/fixedpoint.hxx><br>
760  Namespace: vigra
761 
762 */
763 template <unsigned IntBits, unsigned FracBits>
764 struct NumericTraits<FixedPoint<IntBits, FracBits> >
765 {
766  typedef FixedPoint<IntBits, FracBits> Type;
767  //typedef FixedPoint<IntBits, FracBits> Promote;
768  //typedef FixedPoint<IntBits, FracBits> RealPromote;
769  //typedef std::complex<RealPromote> ComplexPromote;
770  typedef Type ValueType;
771 
772  typedef VigraFalseType isIntegral;
773  typedef VigraTrueType isScalar;
774  typedef VigraTrueType isSigned;
775  typedef VigraTrueType isOrdered;
776  typedef VigraFalseType isComplex;
777 
778  static Type zero() { return Type(0, FPNoShift); }
779  static Type one() { return Type(Type::ONE, FPNoShift); }
780  static Type nonZero() { return one(); }
781  static Type epsilon() { return Type(1, FPNoShift); }
782  static Type smallestPositive() { return Type(1, FPNoShift); }
783  static Type max() { return Type( Type::MAX, FPNoShift); }
784  static Type min() { return -max(); }
785 };
786 
787 template <unsigned IntBits, unsigned FracBits>
788 struct NormTraits<FixedPoint<IntBits, FracBits> >
789 {
790  typedef FixedPoint<IntBits, FracBits> Type;
791  typedef typename
792  FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
793  SquaredNormType;
794  typedef Type NormType;
795 };
796 
797 template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
798 struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
799  FixedPoint<IntBits2, FracBits2> >
800 {
801  typedef typename
802  FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
803  Promote;
804 };
805 
806 /***********************************************************************************/
807 
808 enum FPOverflowHandling { FPOverflowIgnore, FPOverflowSaturate, FPOverflowError };
809 
810 template <int IntBits, FPOverflowHandling OverflowHandling = FPOverflowIgnore>
811 class FixedPoint16;
812 
813 /********************************************************/
814 /* */
815 /* FixedPoint16-Traits */
816 /* */
817 /********************************************************/
818 
819 /** \page FixedPoint16Traits Numeric and Promote Traits of FixedPoint16
820 
821  The numeric and promote traits for FixedPoint16 follow
822  the general specifications for \ref NumericPromotionTraits and
823  \ref AlgebraicRing. They are implemented in terms of the traits of the basic types by
824  partial template specialization:
825 
826  \code
827  template <int IntBits, FPOverflowHandling OverflowHandling>
828  struct NumericTraits<FixedPoint16<IntBits, OverflowHandling> >
829  {
830  typedef FixedPoint16<IntBits, OverflowHandling> Type;
831  typedef Type Promote;
832  // RealPromote undefined -- multiplication with double is not supported.
833  // ComplexPromote undefined -- multiplication with double is not supported.
834  typedef Type ValueType;
835 
836  typedef VigraFalseType isIntegral;
837  typedef VigraTrueType isScalar;
838  typedef VigraTrueType isSigned;
839  typedef VigraTrueType isOrdered;
840  typedef VigraFalseType isComplex;
841 
842  ... // etc.
843  };
844 
845  template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
846  struct PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>,
847  FixedPoint16<IntBits2, OverflowHandling> >
848  {
849  typedef FixedPoint16<MetaMax<IntBits1, IntBits2>::value, OverflowHandling> Promote;
850  ... // etc.
851  };
852 
853  template <int IntBits, FPOverflowHandling OverflowHandling>
854  struct NormTraits<FixedPoint16<IntBits, OverflowHandling> >
855  {
856  typedef FixedPoint16<IntBits, OverflowHandling> Type;
857  typedef typename PromoteTraits<Type, Type>::Promote SquaredNormType;
858  typedef Type NormType;
859  };
860 
861  template <int IntBits, FPOverflowHandling OverflowHandling>
862  struct SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >
863  {
864  typedef FixedPoint16<IntBits, OverflowHandling> Type;
865  typedef FixedPoint16<(IntBits + 1) / 2, OverflowHandling> SquareRootResult;
866  typedef Type SquareRootArgument;
867  };
868  \endcode
869 
870  <b>\#include</b> <vigra/fixedpoint.hxx><br>
871  Namespace: vigra
872 
873 */
874 template <int IntBits, FPOverflowHandling OverflowHandling>
875 struct NumericTraits<FixedPoint16<IntBits, OverflowHandling> >
876 {
877  typedef FixedPoint16<IntBits, OverflowHandling> Type;
878  typedef Type Promote;
879  // RealPromote undefined -- multiplication with double is not supported.
880  // ComplexPromote undefined -- multiplication with double is not supported.
881  typedef Type ValueType;
882 
883  typedef VigraFalseType isIntegral;
884  typedef VigraTrueType isScalar;
885  typedef VigraTrueType isSigned;
886  typedef VigraTrueType isOrdered;
887  typedef VigraFalseType isComplex;
888 
889  static Type zero() { return Type(0, FPNoShift); }
890  static Type one() { return Type(Type::ONE, FPNoShift); }
891  static Type nonZero() { return one(); }
892  static Type epsilon() { return Type(1, FPNoShift); }
893  static Type smallestPositive() { return Type(1, FPNoShift); }
894  static Type max() { return Type( Type::MAX, FPNoShift); }
895  static Type min() { return Type( Type::MIN, FPNoShift); }
896 
897  static Promote toPromote(Type v) { return v; }
898  static Type fromPromote(Promote v) { return v; };
899 };
900 
901 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
902 struct PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>,
903  FixedPoint16<IntBits2, OverflowHandling> >
904 {
905  typedef FixedPoint16<MetaMax<IntBits1, IntBits2>::value, OverflowHandling> Promote;
906  static Promote toPromote(FixedPoint16<IntBits1, OverflowHandling> v) { return Promote(v); }
907  static Promote toPromote(FixedPoint16<IntBits2, OverflowHandling> v) { return Promote(v); }
908 };
909 
910 template <int IntBits, FPOverflowHandling OverflowHandling>
911 struct PromoteTraits<FixedPoint16<IntBits, OverflowHandling>,
912  FixedPoint16<IntBits, OverflowHandling> >
913 {
914  typedef FixedPoint16<IntBits, OverflowHandling> Promote;
915  static Promote toPromote(FixedPoint16<IntBits, OverflowHandling> v) { return v; }
916 };
917 
918 template <int IntBits, FPOverflowHandling OverflowHandling>
919 struct NormTraits<FixedPoint16<IntBits, OverflowHandling> >
920 {
921  typedef FixedPoint16<IntBits, OverflowHandling> Type;
922  typedef typename PromoteTraits<Type, Type>::Promote SquaredNormType;
923  typedef Type NormType;
924 };
925 
926 template <int IntBits, FPOverflowHandling OverflowHandling>
927 struct SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >
928 {
929  typedef FixedPoint16<IntBits, OverflowHandling> Type;
930  typedef FixedPoint16<(IntBits + 1) / 2, OverflowHandling> SquareRootResult;
931  typedef Type SquareRootArgument;
932 };
933 
934 #ifndef DOXYGEN
935 
936 template <bool Compatible>
937 struct FixedPoint_error__Right_shift_operator_has_unsupported_semantics
938 : staticAssert::AssertBool<Compatible>
939 {};
940 
941 #endif /* DOXYGEN */
942 
943 template <bool Predicate>
944 struct FixedPoint16_assignment_error__Target_object_has_too_few_integer_bits
945 : staticAssert::AssertBool<Predicate>
946 {};
947 
948 namespace detail {
949 
950 template<int BeforeIntBits, int AfterIntBits,
951  bool Round = false,
952  bool RightShift = (AfterIntBits >= BeforeIntBits)>
953 struct FP16Align;
954 
955 template<int BeforeIntBits>
956 struct FP16Align<BeforeIntBits, BeforeIntBits, true, true>
957 {
958  static inline Int32 exec(Int32 v)
959  {
960  return v;
961  }
962 };
963 
964 template<int BeforeIntBits>
965 struct FP16Align<BeforeIntBits, BeforeIntBits, false, true>
966 {
967  static inline Int32 exec(Int32 v)
968  {
969  return v;
970  }
971 };
972 
973 template<int BeforeIntBits, int AfterIntBits>
974 struct FP16Align<BeforeIntBits, AfterIntBits, false, true>
975 {
976  static inline Int32 exec(Int32 v)
977  {
978  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
979  return v >> (AfterIntBits - BeforeIntBits);
980  }
981 };
982 
983 template<int BeforeIntBits, int AfterIntBits>
984 struct FP16Align<BeforeIntBits, AfterIntBits, true, true>
985 {
986  enum { ONE_HALF = 1 << (AfterIntBits - BeforeIntBits - 1) };
987  static inline Int32 exec(Int32 v)
988  {
989  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
990  return (v + ONE_HALF) >> (AfterIntBits - BeforeIntBits);
991  }
992 };
993 
994 template<int BeforeIntBits, int AfterIntBits, bool Round>
995 struct FP16Align<BeforeIntBits, AfterIntBits, Round, false>
996 {
997  static inline Int32 exec(Int32 v)
998  {
999  return v << (BeforeIntBits - AfterIntBits);
1000  }
1001 };
1002 
1003 template <FPOverflowHandling OverflowHandling = FPOverflowIgnore>
1004 struct FP16OverflowHandling
1005 {
1006  static inline Int32 exec(Int32 v)
1007  {
1008  return v;
1009  }
1010 
1011  static inline Int32 exec(UInt32 v)
1012  {
1013  return v;
1014  }
1015 };
1016 
1017 template <>
1018 struct FP16OverflowHandling<FPOverflowSaturate>
1019 {
1020  static inline Int32 exec(Int32 v)
1021  {
1022  if(v >= 1 << 15)
1023  return (1 << 15) - 1;
1024  if(v < -(1 << 15))
1025  return -(1 << 15);
1026  return v;
1027  }
1028  static inline Int32 exec(UInt32 v)
1029  {
1030  if(v >= 1 << 15)
1031  return (1 << 15) - 1;
1032  return v;
1033  }
1034 };
1035 
1036 template <>
1037 struct FP16OverflowHandling<FPOverflowError>
1038 {
1039  static inline Int32 exec(Int32 v)
1040  {
1041  vigra_precondition(v < (1 << 15) && v >= -(1 << 15),
1042  "FixedPoint16: Operation overflows.");
1043  return v;
1044  }
1045  static inline Int32 exec(UInt32 v)
1046  {
1047  vigra_precondition(v < (1 << 15),
1048  "FixedPoint16: Operation overflows.");
1049  return v;
1050  }
1051 };
1052 
1053 
1054 template <int IntBits1, int IntBits2, int IntBitsOut,
1055  FPOverflowHandling OverflowHandling >
1056 struct FP16AddImpl
1057 {
1058  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1059  static inline Int32 exec(Int32 t1, Int32 t2)
1060  {
1061  return FP16OverflowHandling<OverflowHandling>::exec(
1062  FP16Align<MinIntBits, IntBitsOut, /*Round*/ true>::exec(
1063  FP16Align<IntBits1, MinIntBits, /*Round*/ false>::exec(t1) +
1064  FP16Align<IntBits2, MinIntBits, /*Round*/ false>::exec(t2)));
1065  }
1066 };
1067 
1068 template <int IntBits1, int IntBits2, int IntBitsOut,
1069  FPOverflowHandling OverflowHandling >
1070 struct FP16SubImpl
1071 {
1072  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1073  static inline Int32 exec(Int32 t1, Int32 t2)
1074  {
1075  return FP16OverflowHandling<OverflowHandling>::exec(
1076  FP16Align<MinIntBits, IntBitsOut, /*Round*/ true>::exec(
1077  FP16Align<IntBits1, MinIntBits, /*Round*/ false>::exec(t1) -
1078  FP16Align<IntBits2, MinIntBits, /*Round*/ false>::exec(t2)));
1079  }
1080 };
1081 
1082 template <int IntBits1, int IntBits2, int IntBitsOut,
1083  FPOverflowHandling OverflowHandling >
1084 struct FP16MulImpl
1085 {
1086  static inline Int32 exec(Int32 t1, Int32 t2)
1087  {
1088  return FP16OverflowHandling<OverflowHandling>::exec(
1089  FP16Align<IntBits1+IntBits2, IntBitsOut+15, /*Round*/ true>::exec(t1*t2));
1090  }
1091 };
1092 
1093 template <int IntBits1, int IntBits2, int IntBitsOut,
1094  FPOverflowHandling OverflowHandling >
1095 struct FP16DivImpl
1096 {
1097  static inline Int32 exec(Int32 t1, Int32 t2)
1098  {
1099  if(t2 == 0)
1100  return (t1 >= 0)
1101  ? (1 << 15) - 1
1102  : -(1 << 15);
1103  return FP16OverflowHandling<OverflowHandling>::exec(
1104  FP16Align<IntBits1-IntBits2, IntBitsOut+1, /*Round*/ true>::exec((t1<<16)/t2));
1105  }
1106 };
1107 
1108 } // namespace detail
1109 
1110 /********************************************************/
1111 /* */
1112 /* FixedPoint16 */
1113 /* */
1114 /********************************************************/
1115 
1116 template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1117 TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v);
1118 
1119 /** Template for 16-bit signed fixed point arithmetic.
1120 
1121  Fixed point arithmetic is used when computations with fractional accuracy
1122  must be made at the highest speed possible (e.g. in the inner loop
1123  of a volume rendering routine). The speed-up relative to floating
1124  point arithmetic can be dramatic, especially when one can avoid
1125  conversions between integer and floating point numbers (these are
1126  very expensive because integer and floating point arithmetic
1127  resides in different pipelines).
1128 
1129  The template wraps an <tt>Int16</tt> and uses <tt>IntBits</tt> to
1130  represent the integral part of a number, and <tt>15 - IntBits</tt>
1131  for the fractional part. The 16th bit is reserved because FixedPoint16
1132  is a signed type. Results of expressions with mixed types will preserve
1133  larger number of <tt>IntBits</tt> of the results, in order to minimize
1134  the possibility for overflow. Nonetheless, overflow can occur, and the
1135  template parameter <tt>OverflowHandling</tt> determines how this will be
1136  handled:
1137 
1138  <DL>
1139  <DT>FPOverflowIgnore<DD> (default) Ignore overflow, i.e. use the usual modulo behavior of the
1140  built-in integer types.
1141 
1142  <DT>FPOverflowSaturate<DD> Use the largest or smallest representable number (depending on sign)
1143  in case of overflow.
1144 
1145  <DT>FPOverflowError<DD> Throw <tt>PreconditionViolation</tt> upon overflow. This is useful for
1146  debugging.
1147  </DL>
1148 
1149  The implementation relies on Int32-arithmetic and requires that the right-shift operator
1150  preserves signedness. Although not enforced by the C++ standard, this is implemented
1151  by most of today's processors. This property is checked by a
1152  VIGRA_STATIC_ASSERT(FixedPoint_error__Right_shift_operator_has_unsupported_semantics).
1153 
1154  <tt>FixedPoint16</tt> implements the required interface of an
1155  \ref AlgebraicRing and the required numeric and
1156  promotion traits. In addition, it supports functions <tt>add</tt>,
1157  <tt>sub</tt>, <tt>mul</tt>, and <tt>div</tt>, where a particular layout
1158  of the result can be enforced.
1159 
1160  Built-in numeric types can be converted into <tt>FixedPoint16</tt> by the
1161  appropriate constructors, and from <tt>FixedPoint16</tt> by means of
1162  <tt>fixed_point_cast&lt;TargetType&gt;(fixedPoint)</tt>.
1163 
1164  <b>See also:</b>
1165  <ul>
1166  <li> \ref FixedPoint16Operations
1167  <li> \ref FixedPoint16Traits
1168  </ul>
1169 
1170  <b>\#include</b> <vigra/fixedpoint.hxx><br>
1171  Namespace: vigra
1172 */
1173 template <int IntBits, FPOverflowHandling OverflowHandling>
1174 class FixedPoint16
1175 {
1176 public:
1177  static const Int32 TOTAL_BITS = 15; // bit 16 is sign
1178  static const Int32 INT_BITS = IntBits;
1179  static const Int32 FRACTIONAL_BITS = TOTAL_BITS - INT_BITS;
1180  static const Int32 MAX = (Int32)((1u << TOTAL_BITS) - 1);
1181  static const Int32 MIN = -(Int32)(1u << TOTAL_BITS);
1182  static const Int32 ONE = 1 << FRACTIONAL_BITS;
1183  static const Int32 ONE_HALF = ONE >> 1;
1184  static const Int32 FRACTIONAL_MASK = (1u << FRACTIONAL_BITS) - 1;
1185  static const Int32 INT_MASK = 0xffffffffu ^ FRACTIONAL_MASK;
1186 
1187  static const FixedPoint16 zero, pi, pi_2, mpi_2;
1188 
1189  Int16 value;
1190 
1191  FixedPoint16()
1192  : value(0)
1193  {
1194  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1195  }
1196 
1197  /** Construct from an int (fractional part will become zero).
1198  Possible overflow is handled according to the target type's <tt>OverflowHandling</tt>.
1199  */
1200  explicit FixedPoint16(Int32 v)
1201  : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v << FRACTIONAL_BITS))
1202  {
1203  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1204  }
1205 
1206  /** Construct from an int by a bitwise copy. This is normally only used internally.
1207  */
1208  FixedPoint16(Int32 v, FixedPointNoShift)
1209  : value(detail::FP16OverflowHandling<OverflowHandling>::exec(v))
1210  {
1211  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1212  }
1213 
1214  /** Construct from a double and round the fractional part to
1215  <tt>FRACTIONAL_BITS</tt> accuracy. Possible overflow is handled according
1216  to the target type's <tt>OverflowHandling</tt>.
1217  */
1218  explicit FixedPoint16(double rhs)
1219  : value(detail::FP16OverflowHandling<OverflowHandling>::exec((Int32)roundi(rhs * ONE)))
1220  {
1221  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1222  }
1223 
1224  /** Copy constructor.
1225  */
1226  FixedPoint16(const FixedPoint16 &other)
1227  : value(other.value)
1228  {
1229  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1230  }
1231 
1232  /** Construct from a FixedPoint16 with different layout. It rounds as appropriate and
1233  handles possible overflow according to the target type's <tt>OverflowHandling</tt>.
1234  */
1235  template <int IntBits2, FPOverflowHandling OverflowHandling2>
1236  FixedPoint16(const FixedPoint16<IntBits2, OverflowHandling2> &other)
1237  : value(detail::FP16OverflowHandling<OverflowHandling>::exec(
1238  detail::FP16Align<IntBits2, IntBits, /*Round*/true>::exec(other.value)))
1239  {
1240  VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_unsupported_semantics<((-1 >> 8) == -1)>));
1241  }
1242 
1243  /** Assignment from int. The fractional part will become zero.
1244  Possible overflow is handled according to the target type's <tt>OverflowHandling</tt>.
1245  */
1246  FixedPoint16 &operator=(Int32 rhs)
1247  {
1248  value = detail::FP16OverflowHandling<OverflowHandling>::exec(rhs << FRACTIONAL_BITS);
1249  return *this;
1250  }
1251 
1252  /** Assignment form double. The fractional part is rounded, and possible overflow is
1253  handled according to the target type's <tt>OverflowHandling</tt>.
1254  */
1255  FixedPoint16 &operator=(double rhs)
1256  {
1257  value = detail::FP16OverflowHandling<OverflowHandling>::exec(roundi(rhs * ONE));
1258  return *this;
1259  }
1260 
1261  /** Copy assignment.
1262  */
1263  FixedPoint16 & operator=(const FixedPoint16 &other)
1264  {
1265  value = other.value;
1266  return *this;
1267  }
1268 
1269  /** Assignment from a FixedPoint16 with different layout. It rounds as appropriate, and possible overflow is
1270  handled according to the target type's <tt>OverflowHandling</tt>.
1271  */
1272  template <int IntBits2>
1273  FixedPoint16 & operator=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1274  {
1275  value = detail::FP16OverflowHandling<OverflowHandling>::exec(
1276  detail::FP16Align<IntBits2, IntBits, /*Round*/true>::exec(other.value));
1277  return *this;
1278  }
1279 
1280  /** Conversion to float
1281  */
1282  operator float() const
1283  {
1284  return fixed_point_cast<float>(*this);
1285  }
1286 
1287  /** Conversion to double
1288  */
1289  operator double() const
1290  {
1291  return fixed_point_cast<double>(*this);
1292  }
1293 
1294  /** Unary plus.
1295  */
1296  FixedPoint16 operator+() const
1297  {
1298  return *this;
1299  }
1300 
1301  /** Negation.
1302  */
1303  FixedPoint16 operator-() const
1304  {
1305  return FixedPoint16(-value, FPNoShift);
1306  }
1307 
1308  /** Pre-increment.
1309  */
1310  FixedPoint16 & operator++()
1311  {
1312  value = detail::FP16OverflowHandling<OverflowHandling>::exec(value+ONE);
1313  return *this;
1314  }
1315 
1316  /** Post-increment.
1317  */
1318  FixedPoint16 operator++(int)
1319  {
1320  FixedPoint16 old(*this);
1321  ++(*this);
1322  return old;
1323  }
1324 
1325  /** Pre-decrement.
1326  */
1327  FixedPoint16 & operator--()
1328  {
1329  value = detail::FP16OverflowHandling<OverflowHandling>::exec(value-ONE);
1330  return *this;
1331  }
1332 
1333  /** Post-decrement.
1334  */
1335  FixedPoint16 operator--(int)
1336  {
1337  FixedPoint16 old(*this);
1338  --(*this);
1339  return old;
1340  }
1341 
1342  /** Add-assignment from a FixedPoint16 with different layout. It rounds as appropriate, and possible overflow is
1343  handled according to the target type's <tt>OverflowHandling</tt>.
1344  */
1345  template <int IntBits2>
1346  FixedPoint16 & operator+=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1347  {
1348  value = detail::FP16AddImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1349  return *this;
1350  }
1351 
1352  /** Subtract-assignment from a FixedPoint16 with different layout. It rounds as appropriate, and possible overflow is
1353  handled according to the target type's <tt>OverflowHandling</tt>.
1354  */
1355  template <int IntBits2>
1356  FixedPoint16 & operator-=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1357  {
1358  value = detail::FP16SubImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1359  return *this;
1360  }
1361 
1362  /** Multiply-assignment from a FixedPoint16 with different layout. It rounds as appropriate, and possible overflow is
1363  handled according to the target type's <tt>OverflowHandling</tt>.
1364  */
1365  template <int IntBits2>
1366  FixedPoint16 & operator*=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1367  {
1368  value = detail::FP16MulImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1369  return *this;
1370  }
1371 
1372  /** Divide-assignment from a FixedPoint16 with different layout. It rounds as appropriate, and possible overflow is
1373  handled according to the target type's <tt>OverflowHandling</tt>.
1374  */
1375  template <int IntBits2>
1376  FixedPoint16 & operator/=(const FixedPoint16<IntBits2, OverflowHandling> &other)
1377  {
1378  value = detail::FP16DivImpl<IntBits, IntBits2, IntBits, OverflowHandling>::exec(value, other.value);
1379  return *this;
1380  }
1381 };
1382 
1383 template <int IntBits, FPOverflowHandling OverflowHandling>
1384 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::zero(0);
1385 
1386 template <int IntBits, FPOverflowHandling OverflowHandling>
1387 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi(M_PI);
1388 
1389 template <int IntBits, FPOverflowHandling OverflowHandling>
1390 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi_2(0.5 * M_PI);
1391 
1392 template <int IntBits, FPOverflowHandling OverflowHandling>
1393 const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::mpi_2(-0.5 * M_PI);
1394 
1395 namespace detail {
1396 
1397 template <class T>
1398 struct FixedPoint16Cast;
1399 
1400 #define VIGRA_FIXED_POINT_CAST(type) \
1401 template <> \
1402 struct FixedPoint16Cast<type> \
1403 { \
1404  template <int IntBits, FPOverflowHandling OverflowHandling> \
1405  static type cast(FixedPoint16<IntBits, OverflowHandling> v) \
1406  { \
1407  return round(v); \
1408  } \
1409 };
1410 
1411 VIGRA_FIXED_POINT_CAST(Int8)
1412 VIGRA_FIXED_POINT_CAST(UInt8)
1413 VIGRA_FIXED_POINT_CAST(Int16)
1414 VIGRA_FIXED_POINT_CAST(UInt16)
1415 VIGRA_FIXED_POINT_CAST(Int32)
1416 VIGRA_FIXED_POINT_CAST(UInt32)
1417 VIGRA_FIXED_POINT_CAST(Int64)
1418 VIGRA_FIXED_POINT_CAST(UInt64)
1419 
1420 #undef VIGRA_FIXED_POINT_CAST
1421 
1422 template <>
1423 struct FixedPoint16Cast<float>
1424 {
1425  template <int IntBits, FPOverflowHandling OverflowHandling>
1426  static float cast(FixedPoint16<IntBits, OverflowHandling> v)
1427  {
1428  return (float)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1429  }
1430 };
1431 
1432 template <>
1433 struct FixedPoint16Cast<double>
1434 {
1435  template <int IntBits, FPOverflowHandling OverflowHandling>
1436  static double cast(FixedPoint16<IntBits, OverflowHandling> v)
1437  {
1438  return (double)v.value / FixedPoint16<IntBits, OverflowHandling>::ONE;
1439  }
1440 };
1441 
1442 } // namespace detail
1443 
1444 /********************************************************/
1445 /* */
1446 /* FixedPoint16Operations */
1447 /* */
1448 /********************************************************/
1449 
1450 /** \addtogroup FixedPoint16Operations Functions for FixedPoint16
1451 
1452  \brief <b>\#include</b> <vigra/fixedpoint.hxx><br>
1453 
1454  These functions fulfill the requirements of an \ref AlgebraicRing.
1455 
1456  Namespace: vigra
1457  <p>
1458 
1459  */
1460 //@{
1461 
1462  /** Convert a FixedPoint16 to a built-in type.
1463  If the target is integral, the value is rounded.<br>
1464  Usage:
1465  \code
1466  FixedPoint16<16,15> fp(...);
1467 
1468  double d = fixed_point_cast<double>(fp);
1469  \endcode
1470  */
1471 template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1472 TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v)
1473 {
1474  return detail::FixedPoint16Cast<TARGET>::cast(v);
1475 }
1476 
1477 
1478  /// equal
1479 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1480 inline
1481 bool operator==(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1482 {
1483  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1484  return (l.value << (IntBits1 - MinIntBits)) == (r.value << (IntBits2 - MinIntBits));
1485 }
1486 
1487  /// not equal
1488 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1489 inline
1490 bool operator!=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1491 {
1492  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1493  return (l.value << (IntBits1 - MinIntBits)) != (r.value << (IntBits2 - MinIntBits));
1494 }
1495 
1496  /// less than
1497 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1498 inline
1499 bool operator<(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1500 {
1501  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1502  return (l.value << (IntBits1 - MinIntBits)) < (r.value << (IntBits2 - MinIntBits));
1503 }
1504 
1505  /// less or equal
1506 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1507 inline
1508 bool operator<=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1509 {
1510  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1511  return (l.value << (IntBits1 - MinIntBits)) <= (r.value << (IntBits2 - MinIntBits));
1512 }
1513 
1514  /// greater
1515 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1516 inline
1517 bool operator>(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1518 {
1519  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1520  return (l.value << (IntBits1 - MinIntBits)) > (r.value << (IntBits2 - MinIntBits));
1521 }
1522 
1523  /// greater or equal
1524 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1525 inline
1526 bool operator>=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1527 {
1528  enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
1529  return (l.value << (IntBits1 - MinIntBits)) >= (r.value << (IntBits2 - MinIntBits));
1530 }
1531 
1532  /// addition with automatic determination of the appropriate result type.
1533 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1534 inline
1535 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1536 operator+(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1537 {
1538  typedef typename
1539  PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1540  Result;
1541  return Result(detail::FP16AddImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1542 }
1543 
1544  /// addition with enforced result type.
1545 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1546 inline
1547 FixedPoint16<IntBits3, OverflowHandling> &
1548 add(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1549  FixedPoint16<IntBits3, OverflowHandling> & result)
1550 {
1551  result.value = detail::FP16AddImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1552  return result;
1553 }
1554 
1555  /// subtraction with automatic determination of the appropriate result type.
1556 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1557 inline
1558 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1559 operator-(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1560 {
1561  typedef typename
1562  PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1563  Result;
1564  return Result(detail::FP16SubImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1565 }
1566 
1567  /// subtraction with enforced result type.
1568 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1569 inline FixedPoint16<IntBits3, OverflowHandling> &
1570 sub(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1571  FixedPoint16<IntBits3, OverflowHandling> & result)
1572 {
1573  result.value = detail::FP16SubImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1574  return result;
1575 }
1576 
1577  /// multiplication with automatic determination of the appropriate result type.
1578 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1579 inline
1580 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1581 operator*(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1582 {
1583  typedef typename
1584  PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1585  Result;
1586  return Result(detail::FP16MulImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1587 }
1588 
1589  /// multiplication with enforced result type.
1590 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1591 inline
1592 FixedPoint16<IntBits3, OverflowHandling> &
1593 mul(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1594  FixedPoint16<IntBits3, OverflowHandling> & result)
1595 {
1596  result.value = detail::FP16MulImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1597  return result;
1598 }
1599 
1600  /// division with automatic determination of the appropriate result type.
1601 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1602 inline
1603 typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1604 operator/(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r)
1605 {
1606  typedef typename
1607  PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1608  Result;
1609  return Result(detail::FP16DivImpl<IntBits1, IntBits2, Result::INT_BITS, OverflowHandling>::exec(l.value, r.value), FPNoShift);
1610 }
1611 
1612  /// division with enforced result type.
1613 template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1614 inline
1615 FixedPoint16<IntBits3, OverflowHandling> &
1616 div(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, OverflowHandling> r,
1617  FixedPoint16<IntBits3, OverflowHandling> & result)
1618 {
1619  result.value = detail::FP16DivImpl<IntBits1, IntBits2, IntBits3, OverflowHandling>::exec(l.value, r.value);
1620  return result;
1621 }
1622 
1623  /// square root.
1624 template <int IntBits, FPOverflowHandling OverflowHandling>
1625 inline typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult
1626 sqrt(FixedPoint16<IntBits, OverflowHandling> v)
1627 {
1628  typedef typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult Result;
1629  enum { Shift = 15 + IntBits - 2*Result::INT_BITS };
1630  return Result(sqrti(v.value << Shift), FPNoShift);
1631 }
1632 
1633 #ifndef VIGRA_NO_HYPOT
1634  using ::hypot;
1635 #endif
1636 
1637  /// Length of hypotenuse.
1638 template <int IntBits, FPOverflowHandling OverflowHandling>
1639 inline FixedPoint16<IntBits, OverflowHandling>
1640 hypot(FixedPoint16<IntBits, OverflowHandling> v1, FixedPoint16<IntBits, OverflowHandling> v2)
1641 {
1642  UInt32 l = abs(v1.value), r = abs(v2.value);
1643  // sq(l) + sq(r) <= 2**31, so overflow handling after sqrti is sufficient
1644  return FixedPoint16<IntBits, OverflowHandling>(
1645  detail::FP16OverflowHandling<OverflowHandling>::exec(sqrti(sq(l) + sq(r))),
1646  FPNoShift);
1647 }
1648 
1649 using std::atan2;
1650 
1651  /// Arctangent. Accuracy better than 1/3 degree (9 significant bits).
1652 template <int IntBits, FPOverflowHandling OverflowHandling>
1653 FixedPoint16<2, OverflowHandling>
1654 atan2(FixedPoint16<IntBits, OverflowHandling> y, FixedPoint16<IntBits, OverflowHandling> x)
1655 {
1656  enum { ResIntBits = 2 };
1657  typedef FixedPoint16<ResIntBits, OverflowHandling> FP;
1658  static const Int32 Pi_4 = 25736, // = roundi(0.25 * M_PI * (1 << 15)), at 15 frac bits
1659  Pi3_4 = 77208, // = roundi(0.75 * M_PI * (1 << 15)),
1660  c1 = 6497, // = roundi(0.19826763260224867 * (1 << 15)),
1661  c2 = -1047730238; // = roundi(-0.9757748231899761 * (1 << 30));
1662 
1663  // coefficients c1 and c2 minimize
1664  //
1665  // NIntegrate[(c1 r^3 + c2 r + Pi/4 - a)^4 /. r -> (Cos[a] - Sin[a])/(Cos[a] + Sin[a]), {a, 0, Pi/2}]
1666  //
1667  // Thanks to Jim Shima, http://www.dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm
1668 
1669  if(x.value == 0)
1670  return (y.value > 0)
1671  ? FP::pi_2
1672  : (y.value < 0)
1673  ? FP::mpi_2
1674  : FP::zero;
1675 
1676  Int32 abs_y = abs(y.value);
1677  Int32 r, angle;
1678  if(x.value > 0)
1679  {
1680  if(y.value == 0)
1681  return FP::zero;
1682  r = ((x.value - abs_y) << 15) / (x.value + abs_y); // 15 frac bits
1683  angle = Pi_4;
1684  }
1685  else
1686  {
1687  if(y.value == 0)
1688  return FP::pi;
1689  r = ((x.value + abs_y) << 15) / (abs_y - x.value); // 15 frac bits
1690  angle = Pi3_4;
1691  }
1692 
1693  angle += r*((c2 + c1 * (sq(r) >> 15)) >> 15) >> 15;
1694 
1695  return (y.value > 0)
1696  ? FP(detail::FP16Align<0, ResIntBits, true>::exec( angle), FPNoShift)
1697  : FP(detail::FP16Align<0, ResIntBits, true>::exec(-angle), FPNoShift);
1698 }
1699 
1700  /// absolute value.
1701 template <int IntBits, FPOverflowHandling OverflowHandling>
1702 inline FixedPoint16<IntBits, OverflowHandling>
1703 abs(FixedPoint16<IntBits, OverflowHandling> v)
1704 {
1705  return FixedPoint16<IntBits, OverflowHandling>(abs(v.value), FPNoShift);
1706 }
1707 
1708  /// squared norm (same as v*v).
1709 template <int IntBits, FPOverflowHandling OverflowHandling>
1710 inline
1711 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::SquaredNormType
1712 squaredNorm(FixedPoint16<IntBits, OverflowHandling> v)
1713 {
1714  return v*v;
1715 }
1716 
1717  /// norm (same as abs).
1718 template <int IntBits, FPOverflowHandling OverflowHandling>
1719 inline
1720 typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::NormType
1721 norm(FixedPoint16<IntBits, OverflowHandling> const & v)
1722 {
1723  return abs(v);
1724 }
1725 
1726  /// fractional part. (difference between v and its floor)
1727 template <int IntBits, FPOverflowHandling OverflowHandling>
1728 inline FixedPoint16<IntBits, OverflowHandling>
1729 frac(FixedPoint16<IntBits, OverflowHandling> v)
1730 {
1731  return FixedPoint16<IntBits, OverflowHandling>(
1732  v.value - (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1733  FPNoShift);
1734 }
1735 
1736  /// dual fractional part. (1 - frac(v))
1737 template <int IntBits, FPOverflowHandling OverflowHandling>
1738 inline FixedPoint16<IntBits, OverflowHandling>
1739 dual_frac(FixedPoint16<IntBits, OverflowHandling> v)
1740 {
1741  return FixedPoint16<IntBits, OverflowHandling>(
1742  FixedPoint16<IntBits, OverflowHandling>::ONE - v.value + (v.value & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
1743  FPNoShift);
1744 }
1745 
1746  /// rounding down.
1747 template <int IntBits, FPOverflowHandling OverflowHandling>
1748 inline Int32
1749 floor(FixedPoint16<IntBits, OverflowHandling> v)
1750 {
1751  return(v.value >> FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1752 }
1753 
1754  /// rounding up.
1755 template <int IntBits, FPOverflowHandling OverflowHandling>
1756 inline Int32
1757 ceil(FixedPoint16<IntBits, OverflowHandling> v)
1758 {
1759  return((v.value + FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_MASK) >>
1760  FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1761 }
1762 
1763  /// rounding to the nearest integer.
1764 template <int IntBits, FPOverflowHandling OverflowHandling>
1765 inline Int32
1766 round(FixedPoint16<IntBits, OverflowHandling> v)
1767 {
1768  return((v.value + FixedPoint16<IntBits, OverflowHandling>::ONE_HALF) >>
1769  FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1770 }
1771 
1772  /// rounding to the nearest integer.
1773 template <int IntBits, FPOverflowHandling OverflowHandling>
1774 inline Int32
1775 roundi(FixedPoint16<IntBits, OverflowHandling> v)
1776 {
1777  return round(v);
1778 }
1779 
1780 //@}
1781 
1782 } // namespace vigra
1783 
1784 namespace std {
1785 
1786 template <int IntBits, vigra::FPOverflowHandling OverflowHandling>
1787 ostream & operator<<(ostream & s, vigra::FixedPoint16<IntBits, OverflowHandling> v)
1788 {
1789  s << vigra::fixed_point_cast<float>(v);
1790  return s;
1791 }
1792 
1793 } // namespace std
1794 
1795 #endif // VIGRA_FIXEDPOINT_HXX
Definition: fixedpoint.hxx:47

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)