I want to implement a mapping from integer to float, but my low-level knowledge is a little bit rusty. The mapping is described in this paper :
3.2 Mapping to Integer
We could compute prediction residuals via floating-point subtraction, however this might cause underflow with irreversible loss of information that precludes reconstruction of> the actual value. Instead, as in [7, 22], we map the predicted and actual floats p and f to their sign-magnitude binary integer representation. On platforms implementing signmagnitude integer arithmetic, we could now simply compute integer residuals via subtraction, however most current platforms implement two’s complement arithmetic. To address this, we map the sign-magnitude representation to unsigned integers by flipping either the most significant bit (for positive floats) or all bits (for negative floats). The result is a monotonic mapping of floats to unsigned integers that preserves ordering and even linearity of differences for floats with the same sign and exponent. This approach is also similar to [16], however we benefit by allowing a carry to propagate from mantissa to exponent in case p and f are close but separated by an exponent boundary, which would be signaled as a large misprediction in [16].
There is also some C sample code, but i'm not quite sure, if i copied the right part:
typedef float F32;
typedef int I32;
typedef unsigned int U32;
I32 exponentPred = (((U32&)floatnum) & 0x7F800000) >> 23;
I32 signPred = (((U32&)floatnum) & 0x80000000) == 0x80000000;
I32 mantissaPred = (((U32&)floatnum) & 0x007FFFFF);
So my questions are :
Thanks, plasmido
0x80000000 is 1000000 00000000 00000000 00000000
0x7F800000 is 0111111 10000000 00000000 00000000
0x007FFFFF is 0000000 01111111 11111111 11111111
Now assume you have a floating point variable with these digits, each char standing for one binary digit:
floatnum = SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
((U32&)floatnum) & 0x7F800000 is 0EEEEEEE E0000000 0000000 00000000
Finally do a right shift >>23 to get
0000000 0000000 0000000 EEEEEEEE
((U32&)floatnum) & 0x80000000 is S0000000 00000000 0000000 00000000
Thus selecting the sign.
Finally, the last line selects the mantissa:
((U32&)floatnum) & 0x007FFFFF is 00000000 0MMMMMMM MMMMMMMM MMMMMMMM
Basically, the code is splitting the float into the three parts, using a bitmask.
//Edit ugly solution removed, found a better solution in matlab:
raw = typecast( single(floatNum), 'uint32' )
exponentPred=bitget(raw,[31:-1:22])
signPred=bitget(raw,[32])]
mantissaPred=bitget(raw,[23:-1:1])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With