Type Punning with Pun Cast¶
template <typename T, typename U>
T pxart::pun_cast(U x);
Reinterprets object of type U
as object of type T
with the same bit representation. T
and U
need to have the same size. This function adheres to the strict-aliasing rules.
Typically, such type punning is done to reinterpret floating-point types as unsigned integers to manipulate their sign bit and compute the absolute value for example. Here, pun_cast
can also be used to reinterpret an SIMD type as an arbitray vector type to be able to access single elements.
Include Scheme¶
#include <pxart/utility/pun_cast.hpp>
Complexity¶
Constant time complexity. The function should result in only one processor instruction but uses std::memcpy
to not violate the strict-aliasing rules.
Exceptions¶
The function itself throws no exceptions. But the inner call to std::memcpy
could throw.
Example¶
#include <array>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <random>
//
#include <pxart/simd256/mt19937.hpp>
#include <pxart/utility/pun_cast.hpp>
using namespace std;
int main() {
// Define standard random number generator for comparisons.
std::mt19937 rng{};
// Define PRNG which uses 256-bit vector registers as output.
pxart::simd256::mt19937 vrng{};
using uint_type = decltype(vrng)::uint_type;
constexpr size_t simd_size = decltype(vrng)::simd_size;
constexpr size_t n = 10;
for (int i = 0; i < n; i += simd_size) {
// Generate random 256-bit vector and reinterpret it as 8-dimensional array
// of 32-bit unsigned integers.
const auto vrnd = pxart::pun_cast<array<uint_type, simd_size>>(vrng());
// Output generated random numbers.
for (int j = 0; j < simd_size; ++j) {
const auto rnd = rng();
cout << setw(20) << rnd << setw(20) << vrnd[j] << '\n';
}
}
}
Last update: January 18, 2021