summaryrefslogtreecommitdiff
path: root/thirdparty/graphite/src/inc/bits.h
blob: 168ff256d37dcd12e95eebf7f03aabce6848f893 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2012, SIL International, All rights reserved.

#pragma once

namespace graphite2
{


#if defined GRAPHITE2_BUILTINS && (defined __GNUC__ || defined __clang__)

template<typename T>
inline unsigned int bit_set_count(T v)
{
    return __builtin_popcount(v);
}

template<>
inline unsigned int bit_set_count(int16 v)
{
    return __builtin_popcount(static_cast<uint16>(v));
}

template<>
inline unsigned int bit_set_count(int8 v)
{
    return __builtin_popcount(static_cast<uint8>(v));
}

template<>
inline unsigned int bit_set_count(unsigned long v)
{
    return __builtin_popcountl(v);
}

template<>
inline unsigned int bit_set_count(signed long v)
{
    return __builtin_popcountl(v);
}

template<>
inline unsigned int bit_set_count(unsigned long long v)
{
    return __builtin_popcountll(v);
}

template<>
inline unsigned int bit_set_count(signed long long v)
{
    return __builtin_popcountll(v);
}

#else

template<typename T>
inline unsigned int bit_set_count(T v)
{
	static size_t const ONES = ~0;

	v = v - ((v >> 1) & T(ONES/3));                      // temp
    v = (v & T(ONES/15*3)) + ((v >> 2) & T(ONES/15*3));  // temp
    v = (v + (v >> 4)) & T(ONES/255*15);                 // temp
    return (T)(v * T(ONES/255)) >> (sizeof(T)-1)*8;      // count
}

#endif

//TODO: Changed these to uintmax_t when we go to C++11
template<int S>
inline size_t _mask_over_val(size_t v)
{
    v = _mask_over_val<S/2>(v);
    v |= v >> S*4;
    return v;
}

//TODO: Changed these to uintmax_t when we go to C++11
template<>
inline size_t _mask_over_val<1>(size_t v)
{
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    return v;
}

template<typename T>
inline T mask_over_val(T v)
{
    return T(_mask_over_val<sizeof(T)>(v));
}

template<typename T>
inline unsigned long next_highest_power2(T v)
{
    return _mask_over_val<sizeof(T)>(v-1)+1;
}

template<typename T>
inline unsigned int log_binary(T v)
{
    return bit_set_count(mask_over_val(v))-1;
}

template<typename T>
inline T has_zero(const T x)
{
    return (x - T(~T(0)/255)) & ~x & T(~T(0)/255*128);
}

template<typename T>
inline T zero_bytes(const T x, unsigned char n)
{
    const T t = T(~T(0)/255*n);
    return T((has_zero(x^t) >> 7)*n);
}

#if 0
inline float float_round(float x, uint32 m)
{
    *reinterpret_cast<unsigned int *>(&x) &= m;
    return *reinterpret_cast<float *>(&x);
}
#endif

}