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

fixedpoint.hxx
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
44namespace vigra {
45
46template <unsigned IntBits, unsigned FractionalBits>
47class FixedPoint;
48
49struct Error_FixedPointTraits_not_specialized_for_this_case;
50
51template <class T1, class T2>
52class FixedPointTraits
53{
54public:
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
65template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
66class 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 };
78public:
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
85template <unsigned IntBits, unsigned FracBits>
86struct SquareRootTraits<FixedPoint<IntBits, FracBits> >
87{
88 enum { SRTotalBits = (IntBits + FracBits + 1) / 2,
89 SRIntBits = (IntBits + 1) / 2,
90 SRFracBits = SRTotalBits - SRIntBits
91 };
92public:
93 typedef FixedPoint<IntBits, FracBits> Type;
94 typedef FixedPoint<SRIntBits, SRFracBits> SquareRootResult;
95 typedef Type SquareRootArgument;
96};
97
98
99#ifndef DOXYGEN
100
101template <int N>
102struct FixedPoint_overflow_error__More_than_31_bits_requested
103: staticAssert::AssertBool<(N < 32)>
104{};
105
106#endif /* DOXYGEN */
107
108
109
110template <bool Predicate>
111struct FixedPoint_assignment_error__Target_object_has_too_few_integer_bits
112: staticAssert::AssertBool<Predicate>
113{};
114
115enum FixedPointNoShift { FPNoShift };
116
117namespace detail {
118
119template <bool MustRound>
120struct FPAssignWithRound;
121
122template <>
123struct FPAssignWithRound<false>
124{
125 template <int N>
126 static inline int exec(int v) { return v << (-N); }
127};
128
129template <>
130struct 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
139template <bool MustRound>
140struct FPMulImplementation;
141
142template <>
143struct FPMulImplementation<false>
144{
145 template <int N>
146 static inline int exec(int l, int r) { return (l * r) << (-N); }
147};
148
149template <>
150struct 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*/
216template <unsigned IntBits, unsigned FractionalBits>
217class FixedPoint
218{
219public:
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
407VIGRA_FIXED_POINT_FACTORY(unsigned char, 8)
408VIGRA_FIXED_POINT_FACTORY(signed char, 7)
409VIGRA_FIXED_POINT_FACTORY(unsigned short, 16)
410VIGRA_FIXED_POINT_FACTORY(signed short, 15)
411VIGRA_FIXED_POINT_FACTORY(int, 31)
412
413#undef VIGRA_FIXED_POINT_FACTORY
414
415template <class T>
416struct FixedPointCast;
417
418#define VIGRA_FIXED_POINT_CAST(type) \
419template <> \
420struct 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
429VIGRA_FIXED_POINT_CAST(Int8)
430VIGRA_FIXED_POINT_CAST(UInt8)
431VIGRA_FIXED_POINT_CAST(Int16)
432VIGRA_FIXED_POINT_CAST(UInt16)
433VIGRA_FIXED_POINT_CAST(Int32)
434VIGRA_FIXED_POINT_CAST(UInt32)
435
436#undef VIGRA_FIXED_POINT_CAST
437
438template <>
439struct 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
448template <>
449struct 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 */
485template <class TARGET, unsigned IntBits, unsigned FracBits>
486TARGET fixed_point_cast(FixedPoint<IntBits, FracBits> v)
487{
488 return FixedPointCast<TARGET>::cast(v);
489}
490
491 /// equal
492template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
493inline
494bool 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
501template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
502inline
503bool 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
510template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
511inline
512bool 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
519template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
520inline
521bool 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
528template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
529inline
530bool 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
537template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
538inline
539bool 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.
546template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
547inline
548typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::PlusType
549operator+(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.
558template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
559 unsigned IntBits3, unsigned FracBits3>
560inline void
561add(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.
568template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
569inline
570typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MinusType
571operator-(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.
580template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
581 unsigned IntBits3, unsigned FracBits3>
582inline void
583sub(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.
590template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
591inline
592typename FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBits2, FracBits2> >::MultipliesType
593operator*(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.
602template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2,
603 unsigned IntBits3, unsigned FracBits3>
604inline void
605mul(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.
614template <unsigned IntBits, unsigned FracBits>
615inline typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult
616sqrt(FixedPoint<IntBits, FracBits> v)
617{
618 return typename SquareRootTraits<FixedPoint<IntBits, FracBits> >::SquareRootResult(sqrti(v.value), FPNoShift);
619}
620
621 /// absolute value.
622template <unsigned IntBits, unsigned FracBits>
623inline FixedPoint<IntBits, FracBits>
624abs(FixedPoint<IntBits, FracBits> v)
625{
626 return FixedPoint<IntBits, FracBits>(abs(v.value), FPNoShift);
627}
628
629 /// squared norm (same as v*v).
630template <unsigned IntBits, unsigned FracBits>
631inline
632typename FixedPointTraits<FixedPoint<IntBits, FracBits>, FixedPoint<IntBits, FracBits> >::MultipliesType
633squaredNorm(FixedPoint<IntBits, FracBits> v)
634{
635 return v*v;
636}
637
638 /// norm (same as abs).
639template <unsigned IntBits, unsigned FracBits>
640inline
641FixedPoint<IntBits, FracBits>
642norm(FixedPoint<IntBits, FracBits> const & v)
643{
644 return abs(v);
645}
646
647 /// fractional part.
648template <unsigned IntBits, unsigned FracBits>
649inline FixedPoint<0, FracBits>
650frac(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>.
656template <unsigned IntBits, unsigned FracBits>
657inline FixedPoint<0, FracBits>
658dual_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.
665template <unsigned IntBits, unsigned FracBits>
666inline int
667floor(FixedPoint<IntBits, FracBits> v)
668{
669 return(v.value >> FracBits);
670}
671
672 /// rounding up.
673template <unsigned IntBits, unsigned FracBits>
674inline int
675ceil(FixedPoint<IntBits, FracBits> v)
676{
677 return((v.value + FixedPoint<IntBits, FracBits>::FRACTIONAL_MASK) >> FracBits);
678}
679
680 /// rounding to the nearest integer.
681template <unsigned IntBits, unsigned FracBits>
682inline int
683round(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*/
763template <unsigned IntBits, unsigned FracBits>
764struct 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
787template <unsigned IntBits, unsigned FracBits>
788struct 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
797template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigned FracBits2>
798struct 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
808enum FPOverflowHandling { FPOverflowIgnore, FPOverflowSaturate, FPOverflowError };
809
810template <int IntBits, FPOverflowHandling OverflowHandling = FPOverflowIgnore>
811class 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*/
874template <int IntBits, FPOverflowHandling OverflowHandling>
875struct 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
901template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
902struct 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
910template <int IntBits, FPOverflowHandling OverflowHandling>
911struct 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
918template <int IntBits, FPOverflowHandling OverflowHandling>
919struct 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
926template <int IntBits, FPOverflowHandling OverflowHandling>
927struct 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
936template <bool Compatible>
937struct FixedPoint_error__Right_shift_operator_has_unsupported_semantics
938: staticAssert::AssertBool<Compatible>
939{};
940
941#endif /* DOXYGEN */
942
943template <bool Predicate>
944struct FixedPoint16_assignment_error__Target_object_has_too_few_integer_bits
945: staticAssert::AssertBool<Predicate>
946{};
947
948namespace detail {
949
950template<int BeforeIntBits, int AfterIntBits,
951 bool Round = false,
952 bool RightShift = (AfterIntBits >= BeforeIntBits)>
953struct FP16Align;
954
955template<int BeforeIntBits>
956struct FP16Align<BeforeIntBits, BeforeIntBits, true, true>
957{
958 static inline Int32 exec(Int32 v)
959 {
960 return v;
961 }
962};
963
964template<int BeforeIntBits>
965struct FP16Align<BeforeIntBits, BeforeIntBits, false, true>
966{
967 static inline Int32 exec(Int32 v)
968 {
969 return v;
970 }
971};
972
973template<int BeforeIntBits, int AfterIntBits>
974struct 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
983template<int BeforeIntBits, int AfterIntBits>
984struct 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
994template<int BeforeIntBits, int AfterIntBits, bool Round>
995struct FP16Align<BeforeIntBits, AfterIntBits, Round, false>
996{
997 static inline Int32 exec(Int32 v)
998 {
999 return v << (BeforeIntBits - AfterIntBits);
1000 }
1001};
1002
1003template <FPOverflowHandling OverflowHandling = FPOverflowIgnore>
1004struct 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
1017template <>
1018struct 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
1036template <>
1037struct 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
1054template <int IntBits1, int IntBits2, int IntBitsOut,
1055 FPOverflowHandling OverflowHandling >
1056struct 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
1068template <int IntBits1, int IntBits2, int IntBitsOut,
1069 FPOverflowHandling OverflowHandling >
1070struct 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
1082template <int IntBits1, int IntBits2, int IntBitsOut,
1083 FPOverflowHandling OverflowHandling >
1084struct 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
1093template <int IntBits1, int IntBits2, int IntBitsOut,
1094 FPOverflowHandling OverflowHandling >
1095struct 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
1116template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1117TARGET 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*/
1173template <int IntBits, FPOverflowHandling OverflowHandling>
1174class FixedPoint16
1175{
1176public:
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
1383template <int IntBits, FPOverflowHandling OverflowHandling>
1384const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::zero(0);
1385
1386template <int IntBits, FPOverflowHandling OverflowHandling>
1387const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi(M_PI);
1388
1389template <int IntBits, FPOverflowHandling OverflowHandling>
1390const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::pi_2(0.5 * M_PI);
1391
1392template <int IntBits, FPOverflowHandling OverflowHandling>
1393const FixedPoint16<IntBits, OverflowHandling> FixedPoint16<IntBits, OverflowHandling>::mpi_2(-0.5 * M_PI);
1394
1395namespace detail {
1396
1397template <class T>
1398struct FixedPoint16Cast;
1399
1400#define VIGRA_FIXED_POINT_CAST(type) \
1401template <> \
1402struct 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
1411VIGRA_FIXED_POINT_CAST(Int8)
1412VIGRA_FIXED_POINT_CAST(UInt8)
1413VIGRA_FIXED_POINT_CAST(Int16)
1414VIGRA_FIXED_POINT_CAST(UInt16)
1415VIGRA_FIXED_POINT_CAST(Int32)
1416VIGRA_FIXED_POINT_CAST(UInt32)
1417VIGRA_FIXED_POINT_CAST(Int64)
1418VIGRA_FIXED_POINT_CAST(UInt64)
1419
1420#undef VIGRA_FIXED_POINT_CAST
1421
1422template <>
1423struct 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
1432template <>
1433struct 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 */
1471template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
1472TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v)
1473{
1474 return detail::FixedPoint16Cast<TARGET>::cast(v);
1475}
1476
1477
1478 /// equal
1479template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1480inline
1481bool 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
1488template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1489inline
1490bool 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
1497template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1498inline
1499bool 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
1506template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1507inline
1508bool 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
1515template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1516inline
1517bool 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
1524template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1525inline
1526bool 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.
1533template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1534inline
1535typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1536operator+(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.
1545template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1546inline
1547FixedPoint16<IntBits3, OverflowHandling> &
1548add(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.
1556template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1557inline
1558typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1559operator-(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.
1568template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1569inline FixedPoint16<IntBits3, OverflowHandling> &
1570sub(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.
1578template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1579inline
1580typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1581operator*(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.
1590template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1591inline
1592FixedPoint16<IntBits3, OverflowHandling> &
1593mul(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.
1601template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
1602inline
1603typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint16<IntBits2, OverflowHandling> >::Promote
1604operator/(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.
1613template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2, int IntBits3>
1614inline
1615FixedPoint16<IntBits3, OverflowHandling> &
1616div(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.
1624template <int IntBits, FPOverflowHandling OverflowHandling>
1625inline typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >::SquareRootResult
1626sqrt(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.
1638template <int IntBits, FPOverflowHandling OverflowHandling>
1639inline FixedPoint16<IntBits, OverflowHandling>
1640hypot(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
1649using std::atan2;
1650
1651 /// Arctangent. Accuracy better than 1/3 degree (9 significant bits).
1652template <int IntBits, FPOverflowHandling OverflowHandling>
1653FixedPoint16<2, OverflowHandling>
1654atan2(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.
1701template <int IntBits, FPOverflowHandling OverflowHandling>
1702inline FixedPoint16<IntBits, OverflowHandling>
1703abs(FixedPoint16<IntBits, OverflowHandling> v)
1704{
1705 return FixedPoint16<IntBits, OverflowHandling>(abs(v.value), FPNoShift);
1706}
1707
1708 /// squared norm (same as v*v).
1709template <int IntBits, FPOverflowHandling OverflowHandling>
1710inline
1711typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::SquaredNormType
1712squaredNorm(FixedPoint16<IntBits, OverflowHandling> v)
1713{
1714 return v*v;
1715}
1716
1717 /// norm (same as abs).
1718template <int IntBits, FPOverflowHandling OverflowHandling>
1719inline
1720typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::NormType
1721norm(FixedPoint16<IntBits, OverflowHandling> const & v)
1722{
1723 return abs(v);
1724}
1725
1726 /// fractional part. (difference between v and its floor)
1727template <int IntBits, FPOverflowHandling OverflowHandling>
1728inline FixedPoint16<IntBits, OverflowHandling>
1729frac(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))
1737template <int IntBits, FPOverflowHandling OverflowHandling>
1738inline FixedPoint16<IntBits, OverflowHandling>
1739dual_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.
1747template <int IntBits, FPOverflowHandling OverflowHandling>
1748inline Int32
1749floor(FixedPoint16<IntBits, OverflowHandling> v)
1750{
1751 return(v.value >> FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_BITS);
1752}
1753
1754 /// rounding up.
1755template <int IntBits, FPOverflowHandling OverflowHandling>
1756inline Int32
1757ceil(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.
1764template <int IntBits, FPOverflowHandling OverflowHandling>
1765inline Int32
1766round(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.
1773template <int IntBits, FPOverflowHandling OverflowHandling>
1774inline Int32
1775roundi(FixedPoint16<IntBits, OverflowHandling> v)
1776{
1777 return round(v);
1778}
1779
1780//@}
1781
1782} // namespace vigra
1783
1784namespace std {
1785
1786template <int IntBits, vigra::FPOverflowHandling OverflowHandling>
1787ostream & 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:218

© 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.12.2 (Mon Apr 14 2025)