]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
7c673cae FG |
2 | // vim: ts=8 sw=2 smarttab |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
11fdf7f2 | 10 | * License version 2.1, as published by the Free Software |
7c673cae | 11 | * Foundation. See file COPYING. |
11fdf7f2 | 12 | * |
7c673cae FG |
13 | */ |
14 | ||
15 | #ifndef CEPH_INTARITH_H | |
16 | #define CEPH_INTARITH_H | |
17 | ||
11fdf7f2 | 18 | #include <type_traits> |
7c673cae | 19 | |
11fdf7f2 TL |
20 | template<typename T, typename U> |
21 | constexpr inline std::make_unsigned_t<std::common_type_t<T, U>> div_round_up(T n, U d) { | |
22 | return (n + d - 1) / d; | |
23 | } | |
7c673cae | 24 | |
7c673cae | 25 | |
11fdf7f2 TL |
26 | template<typename T, typename U> |
27 | constexpr inline std::make_unsigned_t<std::common_type_t<T, U>> round_up_to(T n, U d) { | |
28 | return (n % d ? (n + d - n % d) : n); | |
29 | } | |
7c673cae | 30 | |
11fdf7f2 TL |
31 | template<typename T, typename U> |
32 | constexpr inline std::make_unsigned_t<std::common_type_t<T, U>> shift_round_up(T x, U y) { | |
33 | return (x + (1 << y) - 1) >> y; | |
34 | } | |
7c673cae FG |
35 | |
36 | /* | |
11fdf7f2 | 37 | * Wrapper to determine if value is a power of 2 |
7c673cae | 38 | */ |
11fdf7f2 TL |
39 | template<typename T> |
40 | constexpr inline bool isp2(T x) { | |
41 | return (x & (x - 1)) == 0; | |
42 | } | |
7c673cae FG |
43 | |
44 | /* | |
11fdf7f2 | 45 | * Wrappers for various sorts of alignment and rounding. The "align" must |
7c673cae FG |
46 | * be a power of 2. Often times it is a block, sector, or page. |
47 | */ | |
48 | ||
49 | /* | |
50 | * return x rounded down to an align boundary | |
11fdf7f2 TL |
51 | * eg, p2align(1200, 1024) == 1024 (1*align) |
52 | * eg, p2align(1024, 1024) == 1024 (1*align) | |
53 | * eg, p2align(0x1234, 0x100) == 0x1200 (0x12*align) | |
54 | * eg, p2align(0x5600, 0x100) == 0x5600 (0x56*align) | |
7c673cae | 55 | */ |
11fdf7f2 TL |
56 | template<typename T> |
57 | constexpr inline T p2align(T x, T align) { | |
58 | return x & -align; | |
59 | } | |
7c673cae FG |
60 | |
61 | /* | |
62 | * return x % (mod) align | |
11fdf7f2 TL |
63 | * eg, p2phase(0x1234, 0x100) == 0x34 (x-0x12*align) |
64 | * eg, p2phase(0x5600, 0x100) == 0x00 (x-0x56*align) | |
7c673cae | 65 | */ |
11fdf7f2 TL |
66 | template<typename T> |
67 | constexpr inline T p2phase(T x, T align) { | |
68 | return x & (align - 1); | |
69 | } | |
7c673cae FG |
70 | |
71 | /* | |
72 | * return how much space is left in this block (but if it's perfectly | |
73 | * aligned, return 0). | |
11fdf7f2 TL |
74 | * eg, p2nphase(0x1234, 0x100) == 0xcc (0x13*align-x) |
75 | * eg, p2nphase(0x5600, 0x100) == 0x00 (0x56*align-x) | |
7c673cae | 76 | */ |
11fdf7f2 TL |
77 | template<typename T> |
78 | constexpr inline T p2nphase(T x, T align) { | |
79 | return -x & (align - 1); | |
80 | } | |
7c673cae FG |
81 | |
82 | /* | |
83 | * return x rounded up to an align boundary | |
11fdf7f2 TL |
84 | * eg, p2roundup(0x1234, 0x100) == 0x1300 (0x13*align) |
85 | * eg, p2roundup(0x5600, 0x100) == 0x5600 (0x56*align) | |
7c673cae | 86 | */ |
11fdf7f2 TL |
87 | template<typename T> |
88 | constexpr inline T p2roundup(T x, T align) { | |
89 | return -(-x & -align); | |
90 | } | |
7c673cae FG |
91 | |
92 | // count trailing zeros. | |
93 | // NOTE: the builtin is nondeterministic on 0 input | |
94 | template<class T> | |
95 | inline typename std::enable_if< | |
96 | (std::is_integral<T>::value && | |
97 | sizeof(T) <= sizeof(unsigned)), | |
98 | unsigned>::type ctz(T v) { | |
99 | if (v == 0) | |
100 | return sizeof(v) * 8; | |
101 | return __builtin_ctz(v); | |
102 | } | |
103 | ||
104 | template<class T> | |
105 | inline typename std::enable_if< | |
106 | (std::is_integral<T>::value && | |
107 | sizeof(T) > sizeof(unsigned int) && | |
108 | sizeof(T) <= sizeof(unsigned long)), | |
109 | unsigned>::type ctz(T v) { | |
110 | if (v == 0) | |
111 | return sizeof(v) * 8; | |
112 | return __builtin_ctzl(v); | |
113 | } | |
114 | ||
115 | template<class T> | |
116 | inline typename std::enable_if< | |
117 | (std::is_integral<T>::value && | |
118 | sizeof(T) > sizeof(unsigned long) && | |
119 | sizeof(T) <= sizeof(unsigned long long)), | |
120 | unsigned>::type ctz(T v) { | |
121 | if (v == 0) | |
122 | return sizeof(v) * 8; | |
123 | return __builtin_ctzll(v); | |
124 | } | |
125 | ||
126 | // count leading zeros | |
127 | // NOTE: the builtin is nondeterministic on 0 input | |
128 | template<class T> | |
129 | inline typename std::enable_if< | |
130 | (std::is_integral<T>::value && | |
131 | sizeof(T) <= sizeof(unsigned)), | |
132 | unsigned>::type clz(T v) { | |
133 | if (v == 0) | |
134 | return sizeof(v) * 8; | |
135 | return __builtin_clz(v); | |
136 | } | |
137 | ||
138 | template<class T> | |
139 | inline typename std::enable_if< | |
140 | (std::is_integral<T>::value && | |
141 | sizeof(T) > sizeof(unsigned int) && | |
142 | sizeof(T) <= sizeof(unsigned long)), | |
143 | unsigned>::type clz(T v) { | |
144 | if (v == 0) | |
145 | return sizeof(v) * 8; | |
146 | return __builtin_clzl(v); | |
147 | } | |
148 | ||
149 | template<class T> | |
150 | inline typename std::enable_if< | |
151 | (std::is_integral<T>::value && | |
152 | sizeof(T) > sizeof(unsigned long) && | |
153 | sizeof(T) <= sizeof(unsigned long long)), | |
154 | unsigned>::type clz(T v) { | |
155 | if (v == 0) | |
156 | return sizeof(v) * 8; | |
157 | return __builtin_clzll(v); | |
158 | } | |
159 | ||
160 | // count bits (set + any 0's that follow) | |
161 | template<class T> | |
162 | inline typename std::enable_if< | |
163 | (std::is_integral<T>::value && | |
164 | sizeof(T) <= sizeof(unsigned)), | |
165 | unsigned>::type cbits(T v) { | |
166 | if (v == 0) | |
167 | return 0; | |
168 | return (sizeof(v) * 8) - __builtin_clz(v); | |
169 | } | |
170 | ||
171 | template<class T> | |
172 | inline typename std::enable_if< | |
173 | (std::is_integral<T>::value && | |
174 | sizeof(T) > sizeof(unsigned int) && | |
175 | sizeof(T) <= sizeof(unsigned long)), | |
176 | unsigned>::type cbits(T v) { | |
177 | if (v == 0) | |
178 | return 0; | |
179 | return (sizeof(v) * 8) - __builtin_clzl(v); | |
180 | } | |
181 | ||
182 | template<class T> | |
183 | inline typename std::enable_if< | |
184 | (std::is_integral<T>::value && | |
185 | sizeof(T) > sizeof(unsigned long) && | |
186 | sizeof(T) <= sizeof(unsigned long long)), | |
187 | unsigned>::type cbits(T v) { | |
188 | if (v == 0) | |
189 | return 0; | |
190 | return (sizeof(v) * 8) - __builtin_clzll(v); | |
191 | } | |
192 | ||
193 | #endif |