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) Lumiera.org
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
29 #ifndef LIB_UTIL_QUANT_H
30 #define LIB_UTIL_QUANT_H
31 
32 #include <cstdlib>
33 #include <climits>
34 #include <cfloat>
35 #include <cmath>
36 
37 
38 
39 namespace util {
40 
41 
43  template<typename I>
44  struct IDiv
45  {
46  I quot;
47  I rem;
48 
49  IDiv (I num, I den)
50  : quot(num/den)
51  , rem(num - quot*den)
52  { }
53  };
54 
55  template<>
56  struct IDiv<int>
57  : div_t
58  {
59  IDiv<int> (int num, int den)
60  : div_t(div (num,den))
61  { }
62  };
63 
64  template<>
65  struct IDiv<long>
66  : ldiv_t
67  {
68  IDiv<long> (long num, long den)
69  : ldiv_t(ldiv (num,den))
70  { }
71  };
72 
73  template<>
74  struct IDiv<long long>
75  : lldiv_t
76  {
77  IDiv<long long> (long long num, long long den)
78  : lldiv_t(lldiv (num,den))
79  { }
80  };
81 
82  template<typename I>
83  inline IDiv<I>
84  iDiv (I num, I den)
85  {
86  return IDiv<I>{num,den};
87  }
88 
89 
97  template<typename I>
98  inline I
99  floordiv (I num, I den)
100  {
101  if (0 < (num^den))
102  return num/den;
103  else
104  { // truncate similar to floor()
105  IDiv<I> res(num,den);
106  return (res.rem)? res.quot-1 // negative results truncated towards next smaller int
107  : res.quot; //..unless the division result not truncated at all
108  }
109  }
110 
119  template<typename I>
120  inline IDiv<I>
121  floorwrap (I num, I den)
122  {
123  IDiv<I> res(num,den);
124  if (0 > (num^den) && res.rem)
125  { // negative results
126  // wrapped similar to floor()
127  --res.quot;
128  res.rem = den - (-res.rem);
129  }
130  return res;
131  }
132 
133 
134 
151  inline bool
152  almostEqual (double d1, double d2, unsigned int ulp =2)
153  {
154  using std::fabs;
155  return fabs (d1-d2) < DBL_EPSILON * fabs (d1+d2) * ulp
156  || fabs (d1-d2) < DBL_MIN; // special treatment for subnormal results
157  }
158 
159 
160 
178  template<typename I>
179  inline constexpr int
180  ilog2 (I num)
181  {
182  if (num <= 0)
183  return -1;
184  const I MAX_POW = sizeof(I)*CHAR_BIT - 1;
185  int logB{0};
186  auto remove_power = [&](I pow) constexpr
187  {
188  if (pow > MAX_POW) return;
189  if (num >= I{1} << pow)
190  {
191  logB += pow;
192  num >>= pow;
193  }
194  };
195  remove_power(32);
196  remove_power(16);
197  remove_power (8);
198  remove_power (4);
199  remove_power (2);
200  remove_power (1);
201 
202  return logB;
203  }
204 
205 
206 } // namespace util
207 #endif /*UTIL_QUANT_H*/
I floordiv(I num, I den)
floor function for integer arithmetics.
Definition: util-quant.hpp:99
helper to treat int or long division uniformly
Definition: util-quant.hpp:44
IDiv< I > floorwrap(I num, I den)
scale wrapping operation.
Definition: util-quant.hpp:121
IDiv< I > iDiv(I num, I den)
Definition: util-quant.hpp:84
bool almostEqual(double d1, double d2, unsigned int ulp=2)
epsilon comparison of doubles.
Definition: util-quant.hpp:152
constexpr int ilog2(I num)
Integral binary logarithm (disregarding fractional part)
Definition: util-quant.hpp:180