Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
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
30namespace util {
31
32 template<typename N>
33 inline constexpr bool
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 {
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 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 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 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) and 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 or 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*/
long long int llong
Definition integral.hpp:32
bool almostEqual(double d1, double d2, unsigned int ulp=2)
epsilon comparison of doubles.
constexpr int ilog2(I num)
Integral binary logarithm (disregarding fractional part)
IDiv< I > iDiv(I num, I den)
IDiv< I > floorwrap(I num, I den)
scale wrapping operation.
I floordiv(I num, I den)
floor function for integer arithmetics.
constexpr bool isPow2(N n)
IDiv(int num, int den)
IDiv(llong num, llong den)
IDiv(long num, long den)
helper to treat int or long division uniformly
IDiv(I num, I den)