Lumiera  0.pre.03
»edit your freedom«
util-quant.hpp
Go to the documentation of this file.
1 /*
2  UTIL-QUANT.hpp - helper functions to deal with quantisation and comparison
3 
4  Copyright (C)
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
20 #ifndef LIB_UTIL_QUANT_H
21 #define LIB_UTIL_QUANT_H
22 
23 #include <cstdlib>
24 #include <climits>
25 #include <cfloat>
26 #include <cmath>
27 
28 
29 
30 namespace util {
31 
32  template<typename N>
33  inline bool constexpr
34  isPow2 (N n)
35  {
36  return n > 0 and !(n & (n-1));
37  }; // at each power of 2, a new bit is set for the first time
38 
39 
41  template<typename I>
42  struct IDiv
43  {
44  I quot;
45  I rem;
46 
47  IDiv (I num, I den)
48  : quot(num/den)
49  , rem(num - quot*den)
50  { }
51  };
52 
53  template<>
54  struct IDiv<int>
55  : div_t
56  {
57  IDiv<int> (int num, int den)
58  : div_t(div (num,den))
59  { }
60  };
61 
62  template<>
63  struct IDiv<long>
64  : ldiv_t
65  {
66  IDiv<long> (long num, long den)
67  : ldiv_t(ldiv (num,den))
68  { }
69  };
70 
71  template<>
72  struct IDiv<llong>
73  : lldiv_t
74  {
75  IDiv<llong> (llong num, llong den)
76  : lldiv_t(lldiv (num,den))
77  { }
78  };
79 
80  template<typename I>
81  inline IDiv<I>
82  iDiv (I num, I den)
83  {
84  return IDiv<I>{num,den};
85  }
86 
87 
95  template<typename I>
96  inline I
97  floordiv (I num, I den)
98  {
99  if (0 < (num^den))
100  return num/den;
101  else
102  { // truncate similar to floor()
103  IDiv<I> res(num,den);
104  return (res.rem)? res.quot-1 // negative results truncated towards next smaller int
105  : res.quot; //..unless the division result not truncated at all
106  }
107  }
108 
117  template<typename I>
118  inline IDiv<I>
119  floorwrap (I num, I den)
120  {
121  IDiv<I> res(num,den);
122  if (0 > (num^den) && res.rem)
123  { // negative results
124  // wrapped similar to floor()
125  --res.quot;
126  res.rem = den - (-res.rem);
127  }
128  return res;
129  }
130 
131 
132 
149  inline bool
150  almostEqual (double d1, double d2, unsigned int ulp =2)
151  {
152  using std::fabs;
153  return fabs (d1-d2) < DBL_EPSILON * fabs (d1+d2) * ulp
154  || fabs (d1-d2) < DBL_MIN; // special treatment for subnormal results
155  }
156 
157 
158 
176  template<typename I>
177  inline constexpr int
178  ilog2 (I num)
179  {
180  if (num <= 0)
181  return -1;
182  const I MAX_POW = sizeof(I)*CHAR_BIT - 1;
183  int logB{0};
184  auto remove_power = [&](I pow) constexpr
185  {
186  if (pow > MAX_POW) return;
187  if (num >= I{1} << pow)
188  {
189  logB += pow;
190  num >>= pow;
191  }
192  };
193  remove_power(32);
194  remove_power(16);
195  remove_power (8);
196  remove_power (4);
197  remove_power (2);
198  remove_power (1);
199 
200  return logB;
201  }
202 
203 
204 } // namespace util
205 #endif /*UTIL_QUANT_H*/
I floordiv(I num, I den)
floor function for integer arithmetics.
Definition: util-quant.hpp:97
helper to treat int or long division uniformly
Definition: util-quant.hpp:42
IDiv< I > floorwrap(I num, I den)
scale wrapping operation.
Definition: util-quant.hpp:119
IDiv< I > iDiv(I num, I den)
Definition: util-quant.hpp:82
bool almostEqual(double d1, double d2, unsigned int ulp=2)
epsilon comparison of doubles.
Definition: util-quant.hpp:150
constexpr int ilog2(I num)
Integral binary logarithm (disregarding fractional part)
Definition: util-quant.hpp:178