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