1 /*
2 * Copyright (C) 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifndef UTIL_BITPACK_HELPERS_H
25 #define UTIL_BITPACK_HELPERS_H
26
27 #ifndef __OPENCL_VERSION__
28 #include <math.h>
29 #include <stdbool.h>
30
31 #include "util/macros.h"
32 #include "util/u_math.h"
33
34 #ifdef HAVE_VALGRIND
35 #include <valgrind.h>
36 #include <memcheck.h>
37 #ifndef NDEBUG
38 #define util_bitpack_validate_value(x) \
39 VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
40 #endif
41 #endif
42 #else
43 #include "compiler/libcl/libcl.h"
44 #endif
45
46 #ifndef util_bitpack_validate_value
47 #define util_bitpack_validate_value(x)
48 #endif
49
50 ALWAYS_INLINE static uint64_t
util_bitpack_ones(uint32_t start,uint32_t end)51 util_bitpack_ones(uint32_t start, uint32_t end)
52 {
53 return (UINT64_MAX >> (64 - (end - start + 1))) << start;
54 }
55
56 ALWAYS_INLINE static uint64_t
util_bitpack_uint(uint64_t v,uint32_t start,UNUSED uint32_t end)57 util_bitpack_uint(uint64_t v, uint32_t start, UNUSED uint32_t end)
58 {
59 util_bitpack_validate_value(v);
60
61 #ifndef NDEBUG
62 const int bits = end - start + 1;
63 if (bits < 64) {
64 const uint64_t max = u_uintN_max(bits);
65 assert(v <= max);
66 }
67 #endif
68
69 return v << start;
70 }
71
72 ALWAYS_INLINE static uint64_t
util_bitpack_uint_nonzero(uint64_t v,uint32_t start,uint32_t end)73 util_bitpack_uint_nonzero(uint64_t v, uint32_t start, uint32_t end)
74 {
75 assert(v != 0ull);
76 return util_bitpack_uint(v, start, end);
77 }
78
79 ALWAYS_INLINE static uint64_t
util_bitpack_sint(int64_t v,uint32_t start,uint32_t end)80 util_bitpack_sint(int64_t v, uint32_t start, uint32_t end)
81 {
82 const int bits = end - start + 1;
83
84 util_bitpack_validate_value(v);
85
86 #ifndef NDEBUG
87 if (bits < 64) {
88 const int64_t min = u_intN_min(bits);
89 const int64_t max = u_intN_max(bits);
90 assert(min <= v && v <= max);
91 }
92 #endif
93
94 const uint64_t mask = BITFIELD64_MASK(bits);
95
96 return (v & mask) << start;
97 }
98
99 ALWAYS_INLINE static uint64_t
util_bitpack_sint_nonzero(int64_t v,uint32_t start,uint32_t end)100 util_bitpack_sint_nonzero(int64_t v, uint32_t start, uint32_t end)
101 {
102 assert(v != 0ll);
103 return util_bitpack_sint(v, start, end);
104 }
105
106 ALWAYS_INLINE static uint32_t
util_bitpack_float(float v)107 util_bitpack_float(float v)
108 {
109 util_bitpack_validate_value(v);
110 union { float f; uint32_t dw; } x;
111 x.f = v;
112 return x.dw;
113 }
114
115 ALWAYS_INLINE static uint32_t
util_bitpack_float_nonzero(float v)116 util_bitpack_float_nonzero(float v)
117 {
118 assert(v != 0.0f);
119 return util_bitpack_float(v);
120 }
121
122 ALWAYS_INLINE static uint64_t
util_bitpack_sfixed(float v,uint32_t start,uint32_t end,uint32_t fract_bits)123 util_bitpack_sfixed(float v, uint32_t start, uint32_t end,
124 uint32_t fract_bits)
125 {
126 util_bitpack_validate_value(v);
127
128 const float factor = (1 << fract_bits);
129
130 #ifndef NDEBUG
131 const int total_bits = end - start + 1;
132 const float min = u_intN_min(total_bits) / factor;
133 const float max = u_intN_max(total_bits) / factor;
134 assert(min <= v && v <= max);
135 #endif
136
137 const int64_t int_val = llroundf(v * factor);
138 const uint64_t mask = UINT64_MAX >> (64 - (end - start + 1));
139
140 return (int_val & mask) << start;
141 }
142
143 ALWAYS_INLINE static uint64_t
util_bitpack_sfixed_clamp(float v,uint32_t start,uint32_t end,uint32_t fract_bits)144 util_bitpack_sfixed_clamp(float v, uint32_t start, uint32_t end,
145 uint32_t fract_bits)
146 {
147 util_bitpack_validate_value(v);
148
149 const float factor = (1 << fract_bits);
150
151 const int total_bits = end - start + 1;
152 const float min = u_intN_min(total_bits) / factor;
153 const float max = u_intN_max(total_bits) / factor;
154
155 const int64_t int_val = llroundf(CLAMP(v, min, max) * factor);
156 const uint64_t mask = UINT64_MAX >> (64 - (end - start + 1));
157
158 return (int_val & mask) << start;
159 }
160
161 ALWAYS_INLINE static uint64_t
util_bitpack_sfixed_nonzero(float v,uint32_t start,uint32_t end,uint32_t fract_bits)162 util_bitpack_sfixed_nonzero(float v, uint32_t start, uint32_t end,
163 uint32_t fract_bits)
164 {
165 assert(v != 0.0f);
166 return util_bitpack_sfixed(v, start, end, fract_bits);
167 }
168
169 ALWAYS_INLINE static uint64_t
util_bitpack_ufixed(float v,uint32_t start,ASSERTED uint32_t end,uint32_t fract_bits)170 util_bitpack_ufixed(float v, uint32_t start, ASSERTED uint32_t end,
171 uint32_t fract_bits)
172 {
173 util_bitpack_validate_value(v);
174
175 const float factor = (1 << fract_bits);
176
177 #ifndef NDEBUG
178 const int total_bits = end - start + 1;
179 const float min = 0.0f;
180 const float max = u_uintN_max(total_bits) / factor;
181 assert(min <= v && v <= max);
182 #endif
183
184 const uint64_t uint_val = llroundf(v * factor);
185
186 return uint_val << start;
187 }
188
189 ALWAYS_INLINE static uint64_t
util_bitpack_ufixed_clamp(float v,uint32_t start,ASSERTED uint32_t end,uint32_t fract_bits)190 util_bitpack_ufixed_clamp(float v, uint32_t start, ASSERTED uint32_t end,
191 uint32_t fract_bits)
192 {
193 util_bitpack_validate_value(v);
194
195 const float factor = (1 << fract_bits);
196
197 const int total_bits = end - start + 1;
198 const float min = 0.0f;
199 const float max = u_uintN_max(total_bits) / factor;
200
201 const uint64_t uint_val = llroundf(CLAMP(v, min, max) * factor);
202
203 return uint_val << start;
204 }
205
206 ALWAYS_INLINE static uint64_t
util_bitpack_ufixed_nonzero(float v,uint32_t start,uint32_t end,uint32_t fract_bits)207 util_bitpack_ufixed_nonzero(float v, uint32_t start, uint32_t end,
208 uint32_t fract_bits)
209 {
210 assert(v != 0.0f);
211 return util_bitpack_ufixed(v, start, end, fract_bits);
212 }
213
214 #endif /* UTIL_BITPACK_HELPERS_H */
215