1// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2// Copyright 2012, SIL International, All rights reserved.
3
4#pragma once
5
6namespace graphite2
7{
8
9
10#if defined GRAPHITE2_BUILTINS && (defined __GNUC__ || defined __clang__)
11
12template<typename T>
13inline unsigned int bit_set_count(T v)
14{
15 return __builtin_popcount(v);
16}
17
18template<>
19inline unsigned int bit_set_count(int16 v)
20{
21 return __builtin_popcount(static_cast<uint16>(v));
22}
23
24template<>
25inline unsigned int bit_set_count(int8 v)
26{
27 return __builtin_popcount(static_cast<uint8>(v));
28}
29
30template<>
31inline unsigned int bit_set_count(unsigned long v)
32{
33 return __builtin_popcountl(v);
34}
35
36template<>
37inline unsigned int bit_set_count(signed long v)
38{
39 return __builtin_popcountl(v);
40}
41
42template<>
43inline unsigned int bit_set_count(unsigned long long v)
44{
45 return __builtin_popcountll(v);
46}
47
48template<>
49inline unsigned int bit_set_count(signed long long v)
50{
51 return __builtin_popcountll(v);
52}
53
54#else
55
56template<typename T>
57inline unsigned int bit_set_count(T v)
58{
59 static size_t const ONES = ~0;
60
61 v = v - ((v >> 1) & T(ONES/3)); // temp
62 v = (v & T(ONES/15*3)) + ((v >> 2) & T(ONES/15*3)); // temp
63 v = (v + (v >> 4)) & T(ONES/255*15); // temp
64 return (T)(v * T(ONES/255)) >> (sizeof(T)-1)*8; // count
65}
66
67#endif
68
69//TODO: Changed these to uintmax_t when we go to C++11
70template<int S>
71inline size_t _mask_over_val(size_t v)
72{
73 v = _mask_over_val<S/2>(v);
74 v |= v >> S*4;
75 return v;
76}
77
78//TODO: Changed these to uintmax_t when we go to C++11
79template<>
80inline size_t _mask_over_val<1>(size_t v)
81{
82 v |= v >> 1;
83 v |= v >> 2;
84 v |= v >> 4;
85 return v;
86}
87
88template<typename T>
89inline T mask_over_val(T v)
90{
91 return T(_mask_over_val<sizeof(T)>(v));
92}
93
94template<typename T>
95inline unsigned long next_highest_power2(T v)
96{
97 return _mask_over_val<sizeof(T)>(v-1)+1;
98}
99
100template<typename T>
101inline unsigned int log_binary(T v)
102{
103 return bit_set_count(mask_over_val(v))-1;
104}
105
106template<typename T>
107inline T has_zero(const T x)
108{
109 return (x - T(~T(0)/255)) & ~x & T(~T(0)/255*128);
110}
111
112template<typename T>
113inline T zero_bytes(const T x, unsigned char n)
114{
115 const T t = T(~T(0)/255*n);
116 return T((has_zero(x^t) >> 7)*n);
117}
118
119#if 0
120inline float float_round(float x, uint32 m)
121{
122 *reinterpret_cast<unsigned int *>(&x) &= m;
123 return *reinterpret_cast<float *>(&x);
124}
125#endif
126
127}
128