2

I have vertices coming in as float_3's. I want to add an integer to them and then ship them out as float_4's. I don't want to convert the integer into a float with the same value, I need the bits to be exactly the same (the integer is a bucket xyz value bit shifted together).

Here is what I tried:

void tagVerts (vector<float_3> &Verts, vector<float_4> &Output) {
    int len = Verts.size();
    for (int i = 0; i < len; i++) {
        Output[i].xyz = Verts[i];
        Output[i].w = reinterpret_cast<float>(XYZTag(Verts[i]));
    }
}

it says invalid type conversion :/

EDIT: float_3 and float_4 are from amp.h, as far as I can tell they are just 3 or 4 floats in a struct with a bunch of conversion and assignment helper functions.

XYZTag is as follows:

int XYZTag(float_3 pos) {
    pos = pos * mul + add;
    int_3 posi (static_cast<int>(pos.x), static_cast<int>(pos.y), static_cast<int>(pos.z));
    return((posi.x << 10) + posi.y << 10) + posi.z;
}
user81993
  • 6,167
  • 6
  • 32
  • 64
  • How are `float_3`, `float_4`, and `XYZTag` defined? – R Sahu Feb 24 '15 at 05:18
  • You can't `reinterpret_cast(an_int)` - use `static_cast(an_int)`, or leave the cast out completely and the compiler will do it implicitly. – Tony Delroy Feb 24 '15 at 05:24
  • but that just gets the value, which is bound to get mangled up with bigger numbers, i need the exact bits so i can do the inverse once they get to the destination. – user81993 Feb 24 '15 at 05:26

3 Answers3

3

You must not interpret the bits of an int as a float as doing so would violate strict aliasing rules and therefore invoke undefined behavior. The correct way to do this is to copy the bits over using memcpy.

#include <cstring>

inline float
int_bits_to_float(const int bits)
{
  static_assert(sizeof(int) >= sizeof(float), "too few bits");
  float target;
  std::memcpy(&target, &bits, sizeof(float));
  return target;
}

As terrible a solution as it might seem to be at a first glance, we should really expect the compiler to figure out that this can be optimized down to a few move instructions. GCC does this even at default optimization level.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
0

reinterpret_cast will not reinterpret an int as a float, but it can reinterpret a pointer.

int temp = XYZTag(Verts[i]);
Output[i].w = *reinterpret_cast<float*>(&temp);
//            ^                      ^  ^

This will stuff the exact bits of your int into the float Output[i].w. It will be your responsibility to ensure that those types are the same size.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
0

You cannot reinterpret_cast<> the int directly. The static_cast<> will not do what you want.

To copy the bit pattern to another type, you need something like:

int val = 23;
float bitCopy = *reinterpret_cast<float*>(&val);

Now, for this to work at all, you better have sizeof(float) and sizeof(int) the same.

Further, we'll have to assume you know what you are doing to want this at all.

Keith
  • 6,756
  • 19
  • 23