1/// @ref gtc_bitfield
2/// @file glm/gtc/bitfield.inl
3
4#include "../simd/integer.h"
5
6namespace glm{
7namespace detail
8{
9	template <typename PARAM, typename RET>
10	GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y);
11
12	template <typename PARAM, typename RET>
13	GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z);
14
15	template <typename PARAM, typename RET>
16	GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z, PARAM w);
17
18	template <>
19	GLM_FUNC_QUALIFIER glm::uint16 bitfieldInterleave(glm::uint8 x, glm::uint8 y)
20	{
21		glm::uint16 REG1(x);
22		glm::uint16 REG2(y);
23
24		REG1 = ((REG1 <<  4) | REG1) & glm::uint16(0x0F0F);
25		REG2 = ((REG2 <<  4) | REG2) & glm::uint16(0x0F0F);
26
27		REG1 = ((REG1 <<  2) | REG1) & glm::uint16(0x3333);
28		REG2 = ((REG2 <<  2) | REG2) & glm::uint16(0x3333);
29
30		REG1 = ((REG1 <<  1) | REG1) & glm::uint16(0x5555);
31		REG2 = ((REG2 <<  1) | REG2) & glm::uint16(0x5555);
32
33		return REG1 | (REG2 << 1);
34	}
35
36	template <>
37	GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint16 x, glm::uint16 y)
38	{
39		glm::uint32 REG1(x);
40		glm::uint32 REG2(y);
41
42		REG1 = ((REG1 <<  8) | REG1) & glm::uint32(0x00FF00FF);
43		REG2 = ((REG2 <<  8) | REG2) & glm::uint32(0x00FF00FF);
44
45		REG1 = ((REG1 <<  4) | REG1) & glm::uint32(0x0F0F0F0F);
46		REG2 = ((REG2 <<  4) | REG2) & glm::uint32(0x0F0F0F0F);
47
48		REG1 = ((REG1 <<  2) | REG1) & glm::uint32(0x33333333);
49		REG2 = ((REG2 <<  2) | REG2) & glm::uint32(0x33333333);
50
51		REG1 = ((REG1 <<  1) | REG1) & glm::uint32(0x55555555);
52		REG2 = ((REG2 <<  1) | REG2) & glm::uint32(0x55555555);
53
54		return REG1 | (REG2 << 1);
55	}
56
57	template <>
58	GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y)
59	{
60		glm::uint64 REG1(x);
61		glm::uint64 REG2(y);
62
63		REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFFull);
64		REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFFull);
65
66		REG1 = ((REG1 <<  8) | REG1) & glm::uint64(0x00FF00FF00FF00FFull);
67		REG2 = ((REG2 <<  8) | REG2) & glm::uint64(0x00FF00FF00FF00FFull);
68
69		REG1 = ((REG1 <<  4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0Full);
70		REG2 = ((REG2 <<  4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0Full);
71
72		REG1 = ((REG1 <<  2) | REG1) & glm::uint64(0x3333333333333333ull);
73		REG2 = ((REG2 <<  2) | REG2) & glm::uint64(0x3333333333333333ull);
74
75		REG1 = ((REG1 <<  1) | REG1) & glm::uint64(0x5555555555555555ull);
76		REG2 = ((REG2 <<  1) | REG2) & glm::uint64(0x5555555555555555ull);
77
78		return REG1 | (REG2 << 1);
79	}
80
81	template <>
82	GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z)
83	{
84		glm::uint32 REG1(x);
85		glm::uint32 REG2(y);
86		glm::uint32 REG3(z);
87
88		REG1 = ((REG1 << 16) | REG1) & glm::uint32(0x00FF0000FF0000FF);
89		REG2 = ((REG2 << 16) | REG2) & glm::uint32(0x00FF0000FF0000FF);
90		REG3 = ((REG3 << 16) | REG3) & glm::uint32(0x00FF0000FF0000FF);
91
92		REG1 = ((REG1 <<  8) | REG1) & glm::uint32(0xF00F00F00F00F00F);
93		REG2 = ((REG2 <<  8) | REG2) & glm::uint32(0xF00F00F00F00F00F);
94		REG3 = ((REG3 <<  8) | REG3) & glm::uint32(0xF00F00F00F00F00F);
95
96		REG1 = ((REG1 <<  4) | REG1) & glm::uint32(0x30C30C30C30C30C3);
97		REG2 = ((REG2 <<  4) | REG2) & glm::uint32(0x30C30C30C30C30C3);
98		REG3 = ((REG3 <<  4) | REG3) & glm::uint32(0x30C30C30C30C30C3);
99
100		REG1 = ((REG1 <<  2) | REG1) & glm::uint32(0x9249249249249249);
101		REG2 = ((REG2 <<  2) | REG2) & glm::uint32(0x9249249249249249);
102		REG3 = ((REG3 <<  2) | REG3) & glm::uint32(0x9249249249249249);
103
104		return REG1 | (REG2 << 1) | (REG3 << 2);
105	}
106
107	template <>
108	GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z)
109	{
110		glm::uint64 REG1(x);
111		glm::uint64 REG2(y);
112		glm::uint64 REG3(z);
113
114		REG1 = ((REG1 << 32) | REG1) & glm::uint64(0xFFFF00000000FFFFull);
115		REG2 = ((REG2 << 32) | REG2) & glm::uint64(0xFFFF00000000FFFFull);
116		REG3 = ((REG3 << 32) | REG3) & glm::uint64(0xFFFF00000000FFFFull);
117
118		REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x00FF0000FF0000FFull);
119		REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x00FF0000FF0000FFull);
120		REG3 = ((REG3 << 16) | REG3) & glm::uint64(0x00FF0000FF0000FFull);
121
122		REG1 = ((REG1 <<  8) | REG1) & glm::uint64(0xF00F00F00F00F00Full);
123		REG2 = ((REG2 <<  8) | REG2) & glm::uint64(0xF00F00F00F00F00Full);
124		REG3 = ((REG3 <<  8) | REG3) & glm::uint64(0xF00F00F00F00F00Full);
125
126		REG1 = ((REG1 <<  4) | REG1) & glm::uint64(0x30C30C30C30C30C3ull);
127		REG2 = ((REG2 <<  4) | REG2) & glm::uint64(0x30C30C30C30C30C3ull);
128		REG3 = ((REG3 <<  4) | REG3) & glm::uint64(0x30C30C30C30C30C3ull);
129
130		REG1 = ((REG1 <<  2) | REG1) & glm::uint64(0x9249249249249249ull);
131		REG2 = ((REG2 <<  2) | REG2) & glm::uint64(0x9249249249249249ull);
132		REG3 = ((REG3 <<  2) | REG3) & glm::uint64(0x9249249249249249ull);
133
134		return REG1 | (REG2 << 1) | (REG3 << 2);
135	}
136
137	template <>
138	GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y, glm::uint32 z)
139	{
140		glm::uint64 REG1(x);
141		glm::uint64 REG2(y);
142		glm::uint64 REG3(z);
143
144		REG1 = ((REG1 << 32) | REG1) & glm::uint64(0xFFFF00000000FFFFull);
145		REG2 = ((REG2 << 32) | REG2) & glm::uint64(0xFFFF00000000FFFFull);
146		REG3 = ((REG3 << 32) | REG3) & glm::uint64(0xFFFF00000000FFFFull);
147
148		REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x00FF0000FF0000FFull);
149		REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x00FF0000FF0000FFull);
150		REG3 = ((REG3 << 16) | REG3) & glm::uint64(0x00FF0000FF0000FFull);
151
152		REG1 = ((REG1 <<  8) | REG1) & glm::uint64(0xF00F00F00F00F00Full);
153		REG2 = ((REG2 <<  8) | REG2) & glm::uint64(0xF00F00F00F00F00Full);
154		REG3 = ((REG3 <<  8) | REG3) & glm::uint64(0xF00F00F00F00F00Full);
155
156		REG1 = ((REG1 <<  4) | REG1) & glm::uint64(0x30C30C30C30C30C3ull);
157		REG2 = ((REG2 <<  4) | REG2) & glm::uint64(0x30C30C30C30C30C3ull);
158		REG3 = ((REG3 <<  4) | REG3) & glm::uint64(0x30C30C30C30C30C3ull);
159
160		REG1 = ((REG1 <<  2) | REG1) & glm::uint64(0x9249249249249249ull);
161		REG2 = ((REG2 <<  2) | REG2) & glm::uint64(0x9249249249249249ull);
162		REG3 = ((REG3 <<  2) | REG3) & glm::uint64(0x9249249249249249ull);
163
164		return REG1 | (REG2 << 1) | (REG3 << 2);
165	}
166
167	template <>
168	GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z, glm::uint8 w)
169	{
170		glm::uint32 REG1(x);
171		glm::uint32 REG2(y);
172		glm::uint32 REG3(z);
173		glm::uint32 REG4(w);
174
175		REG1 = ((REG1 << 12) | REG1) & glm::uint32(0x000F000F000F000F);
176		REG2 = ((REG2 << 12) | REG2) & glm::uint32(0x000F000F000F000F);
177		REG3 = ((REG3 << 12) | REG3) & glm::uint32(0x000F000F000F000F);
178		REG4 = ((REG4 << 12) | REG4) & glm::uint32(0x000F000F000F000F);
179
180		REG1 = ((REG1 <<  6) | REG1) & glm::uint32(0x0303030303030303);
181		REG2 = ((REG2 <<  6) | REG2) & glm::uint32(0x0303030303030303);
182		REG3 = ((REG3 <<  6) | REG3) & glm::uint32(0x0303030303030303);
183		REG4 = ((REG4 <<  6) | REG4) & glm::uint32(0x0303030303030303);
184
185		REG1 = ((REG1 <<  3) | REG1) & glm::uint32(0x1111111111111111);
186		REG2 = ((REG2 <<  3) | REG2) & glm::uint32(0x1111111111111111);
187		REG3 = ((REG3 <<  3) | REG3) & glm::uint32(0x1111111111111111);
188		REG4 = ((REG4 <<  3) | REG4) & glm::uint32(0x1111111111111111);
189
190		return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3);
191	}
192
193	template <>
194	GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z, glm::uint16 w)
195	{
196		glm::uint64 REG1(x);
197		glm::uint64 REG2(y);
198		glm::uint64 REG3(z);
199		glm::uint64 REG4(w);
200
201		REG1 = ((REG1 << 24) | REG1) & glm::uint64(0x000000FF000000FFull);
202		REG2 = ((REG2 << 24) | REG2) & glm::uint64(0x000000FF000000FFull);
203		REG3 = ((REG3 << 24) | REG3) & glm::uint64(0x000000FF000000FFull);
204		REG4 = ((REG4 << 24) | REG4) & glm::uint64(0x000000FF000000FFull);
205
206		REG1 = ((REG1 << 12) | REG1) & glm::uint64(0x000F000F000F000Full);
207		REG2 = ((REG2 << 12) | REG2) & glm::uint64(0x000F000F000F000Full);
208		REG3 = ((REG3 << 12) | REG3) & glm::uint64(0x000F000F000F000Full);
209		REG4 = ((REG4 << 12) | REG4) & glm::uint64(0x000F000F000F000Full);
210
211		REG1 = ((REG1 <<  6) | REG1) & glm::uint64(0x0303030303030303ull);
212		REG2 = ((REG2 <<  6) | REG2) & glm::uint64(0x0303030303030303ull);
213		REG3 = ((REG3 <<  6) | REG3) & glm::uint64(0x0303030303030303ull);
214		REG4 = ((REG4 <<  6) | REG4) & glm::uint64(0x0303030303030303ull);
215
216		REG1 = ((REG1 <<  3) | REG1) & glm::uint64(0x1111111111111111ull);
217		REG2 = ((REG2 <<  3) | REG2) & glm::uint64(0x1111111111111111ull);
218		REG3 = ((REG3 <<  3) | REG3) & glm::uint64(0x1111111111111111ull);
219		REG4 = ((REG4 <<  3) | REG4) & glm::uint64(0x1111111111111111ull);
220
221		return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3);
222	}
223}//namespace detail
224
225	template <typename genIUType>
226	GLM_FUNC_QUALIFIER genIUType mask(genIUType Bits)
227	{
228		GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'mask' accepts only integer values");
229
230		return Bits >= sizeof(genIUType) * 8 ? ~static_cast<genIUType>(0) : (static_cast<genIUType>(1) << Bits) - static_cast<genIUType>(1);
231	}
232
233	template <typename T, precision P, template <typename, precision> class vecIUType>
234	GLM_FUNC_QUALIFIER vecIUType<T, P> mask(vecIUType<T, P> const& v)
235	{
236		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'mask' accepts only integer values");
237
238		return detail::functor1<T, T, P, vecIUType>::call(mask, v);
239	}
240
241	template <typename genIType>
242	GLM_FUNC_QUALIFIER genIType bitfieldRotateRight(genIType In, int Shift)
243	{
244		GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateRight' accepts only integer values");
245
246		int const BitSize = static_cast<genIType>(sizeof(genIType) * 8);
247		return (In << static_cast<genIType>(Shift)) | (In >> static_cast<genIType>(BitSize - Shift));
248	}
249
250	template <typename T, precision P, template <typename, precision> class vecType>
251	GLM_FUNC_QUALIFIER vecType<T, P> bitfieldRotateRight(vecType<T, P> const & In, int Shift)
252	{
253		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateRight' accepts only integer values");
254
255		int const BitSize = static_cast<int>(sizeof(T) * 8);
256		return (In << static_cast<T>(Shift)) | (In >> static_cast<T>(BitSize - Shift));
257	}
258
259	template <typename genIType>
260	GLM_FUNC_QUALIFIER genIType bitfieldRotateLeft(genIType In, int Shift)
261	{
262		GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateLeft' accepts only integer values");
263
264		int const BitSize = static_cast<genIType>(sizeof(genIType) * 8);
265		return (In >> static_cast<genIType>(Shift)) | (In << static_cast<genIType>(BitSize - Shift));
266	}
267
268	template <typename T, precision P, template <typename, precision> class vecType>
269	GLM_FUNC_QUALIFIER vecType<T, P> bitfieldRotateLeft(vecType<T, P> const& In, int Shift)
270	{
271		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateLeft' accepts only integer values");
272
273		int const BitSize = static_cast<int>(sizeof(T) * 8);
274		return (In >> static_cast<T>(Shift)) | (In << static_cast<T>(BitSize - Shift));
275	}
276
277	template <typename genIUType>
278	GLM_FUNC_QUALIFIER genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount)
279	{
280		return Value | static_cast<genIUType>(mask(BitCount) << FirstBit);
281	}
282
283	template <typename T, precision P, template <typename, precision> class vecType>
284	GLM_FUNC_QUALIFIER vecType<T, P> bitfieldFillOne(vecType<T, P> const& Value, int FirstBit, int BitCount)
285	{
286		return Value | static_cast<T>(mask(BitCount) << FirstBit);
287	}
288
289	template <typename genIUType>
290	GLM_FUNC_QUALIFIER genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount)
291	{
292		return Value & static_cast<genIUType>(~(mask(BitCount) << FirstBit));
293	}
294
295	template <typename T, precision P, template <typename, precision> class vecType>
296	GLM_FUNC_QUALIFIER vecType<T, P> bitfieldFillZero(vecType<T, P> const& Value, int FirstBit, int BitCount)
297	{
298		return Value & static_cast<T>(~(mask(BitCount) << FirstBit));
299	}
300
301	GLM_FUNC_QUALIFIER int16 bitfieldInterleave(int8 x, int8 y)
302	{
303		union sign8
304		{
305			int8 i;
306			uint8 u;
307		} sign_x, sign_y;
308
309		union sign16
310		{
311			int16 i;
312			uint16 u;
313		} result;
314
315		sign_x.i = x;
316		sign_y.i = y;
317		result.u = bitfieldInterleave(sign_x.u, sign_y.u);
318
319		return result.i;
320	}
321
322	GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(uint8 x, uint8 y)
323	{
324		return detail::bitfieldInterleave<uint8, uint16>(x, y);
325	}
326
327	GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int16 x, int16 y)
328	{
329		union sign16
330		{
331			int16 i;
332			uint16 u;
333		} sign_x, sign_y;
334
335		union sign32
336		{
337			int32 i;
338			uint32 u;
339		} result;
340
341		sign_x.i = x;
342		sign_y.i = y;
343		result.u = bitfieldInterleave(sign_x.u, sign_y.u);
344
345		return result.i;
346	}
347
348	GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint16 x, uint16 y)
349	{
350		return detail::bitfieldInterleave<uint16, uint32>(x, y);
351	}
352
353	GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y)
354	{
355		union sign32
356		{
357			int32 i;
358			uint32 u;
359		} sign_x, sign_y;
360
361		union sign64
362		{
363			int64 i;
364			uint64 u;
365		} result;
366
367		sign_x.i = x;
368		sign_y.i = y;
369		result.u = bitfieldInterleave(sign_x.u, sign_y.u);
370
371		return result.i;
372	}
373
374	GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y)
375	{
376		return detail::bitfieldInterleave<uint32, uint64>(x, y);
377	}
378
379	GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z)
380	{
381		union sign8
382		{
383			int8 i;
384			uint8 u;
385		} sign_x, sign_y, sign_z;
386
387		union sign32
388		{
389			int32 i;
390			uint32 u;
391		} result;
392
393		sign_x.i = x;
394		sign_y.i = y;
395		sign_z.i = z;
396		result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u);
397
398		return result.i;
399	}
400
401	GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z)
402	{
403		return detail::bitfieldInterleave<uint8, uint32>(x, y, z);
404	}
405
406	GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z)
407	{
408		union sign16
409		{
410			int16 i;
411			uint16 u;
412		} sign_x, sign_y, sign_z;
413
414		union sign64
415		{
416			int64 i;
417			uint64 u;
418		} result;
419
420		sign_x.i = x;
421		sign_y.i = y;
422		sign_z.i = z;
423		result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u);
424
425		return result.i;
426	}
427
428	GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z)
429	{
430		return detail::bitfieldInterleave<uint32, uint64>(x, y, z);
431	}
432
433	GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y, int32 z)
434	{
435		union sign16
436		{
437			int32 i;
438			uint32 u;
439		} sign_x, sign_y, sign_z;
440
441		union sign64
442		{
443			int64 i;
444			uint64 u;
445		} result;
446
447		sign_x.i = x;
448		sign_y.i = y;
449		sign_z.i = z;
450		result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u);
451
452		return result.i;
453	}
454
455	GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z)
456	{
457		return detail::bitfieldInterleave<uint32, uint64>(x, y, z);
458	}
459
460	GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w)
461	{
462		union sign8
463		{
464			int8 i;
465			uint8 u;
466		} sign_x, sign_y, sign_z, sign_w;
467
468		union sign32
469		{
470			int32 i;
471			uint32 u;
472		} result;
473
474		sign_x.i = x;
475		sign_y.i = y;
476		sign_z.i = z;
477		sign_w.i = w;
478		result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u);
479
480		return result.i;
481	}
482
483	GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w)
484	{
485		return detail::bitfieldInterleave<uint8, uint32>(x, y, z, w);
486	}
487
488	GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w)
489	{
490		union sign16
491		{
492			int16 i;
493			uint16 u;
494		} sign_x, sign_y, sign_z, sign_w;
495
496		union sign64
497		{
498			int64 i;
499			uint64 u;
500		} result;
501
502		sign_x.i = x;
503		sign_y.i = y;
504		sign_z.i = z;
505		sign_w.i = w;
506		result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u);
507
508		return result.i;
509	}
510
511	GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w)
512	{
513		return detail::bitfieldInterleave<uint16, uint64>(x, y, z, w);
514	}
515}//namespace glm
516