]> git.proxmox.com Git - ceph.git/blame - ceph/src/include/intarith.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / include / intarith.h
CommitLineData
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
20template<typename T, typename U>
21constexpr 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
26template<typename T, typename U>
27constexpr 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
31template<typename T, typename U>
32constexpr 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
39template<typename T>
40constexpr 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
56template<typename T>
57constexpr 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
66template<typename T>
67constexpr 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
77template<typename T>
78constexpr 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
87template<typename T>
88constexpr 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
94template<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
104template<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
115template<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
128template<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
138template<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
149template<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)
161template<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
171template<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
182template<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