Get random bit off the end of a float - c

I have a float in my program that changes after each iteration, namely G[0]. I want to use the last bit of the mantissa as a "random" bit that I will use to pick which path to take in my computation. However, the calculation I'm using now always prints out 0, while it should be roughly 50/50; what's my error? The function signature defines float* G.
unsigned rand_bit = *((unsigned *)&G[0])>>31;
printf("%i", rand_bit);

First of all, *((unsigned *)&G[0]) causes undefined behaviour by violating the strict aliasing rule. In Standard C it is not permitted to access memory of one type by using a different type, except for a handful of special cases.
You can fix this either by disabling strict aliasing in your compiler, or using a union or memcpy.
(Also your code is relying on unsigned being the same size as float, which is not true in general).
But supposing you did fix those issues, your code is testing the most-significant bit. In the IEEE 32-bit floating point format, that bit is the sign bit. So it will read 0 for positive numbers and 1 for negative numbers.
The last bit of the mantissa would be the least significant bit after reinterpreting the memory as integer.
Corrected code could look like:
unsigned u;
assert( sizeof u == sizeof *G );
memcpy(&u, G, sizeof u);
printf("%u", u & 1);
NB. I would be hesitant about assuming this bit will be "random", if you want a random distribution of bits there are much better options.

Although you actual problem got solved I want to propose to use a union instead, it is a bit cleaner, but I do not know what is faster (if you are using the GPU I think I can safely assume that you want it fast). Endianness is also a problem; I was not able to find much information in that direction regarding GPUs, so here are some lines you might want to use.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int last_bit(float f)
{
// Endianness testing should be done at compile-time, such that a simple macro
// would suffice. Your compiler/libc might already offer one for that
#ifdef USE_TYPE_PUNNING
// So called "type punning" is frowned upon by some
uint32_t ui = 0x76543210;
unsigned char *c = (unsigned char *) &ui;
#else
union {
uint32_t ui;
uint8_t uc[4];
} end = {0x76543210};
// only to save some code branching, end.uc can be used directly, of course
unsigned char *c = (unsigned char *) end.uc;
#endif
int rand_bit;
union {
float fl;
uint32_t ui;
} w;
w.fl = f;
#ifdef DEBUG
printf("%x\n", w.ui);
#endif
// Little endian
if (*c == 0x10) {
rand_bit = w.ui & 0x1;
}
// Big endian
else if (*c == 0x76) {
rand_bit = w.ui & 0x1;
}
// Too old/new
else {
fprintf(stderr, "unknown endianness\n");
return -1;
}
return rand_bit;
}
int main(int argc, char **argv)
{
float f;
// all checks omitted!
if (argc >= 2) {
f = atof(argv[1]);
} else {
// 0x40e00000 even
//f = 7;
// 0x3f8ccccd odd
f = 1.1;
}
printf("last bit of mantissa = %d\n", last_bit(f));
exit(EXIT_SUCCESS);
}

Related

Float to Binary in C

I am asked to convert a float number into a 32 bit unsigned integer. I then have to check if all the bits are zero but I am having trouble with this. Sorry I am new to C
This is what I am doing
float number = 12.5;
// copying number into a 32-bit unsigned int
unsigned int val_number = *((unsigned int*) &number);
At this point I'm very confused on how to check if all bits are zero.
I think I need to loop through all the bits but I don't know how to do that.
To copy the bytes of a 32-bit float to an integer, best to copy to an integer type that is certainly 32-bit. unsigned may be less, same or more than 32-bits.
#include <inttypes.h>
float number = 12.5;
uint32_t val_number32; // 32-bit type
memcpy(&val_number32, &number, sizeof val_number32);
Avoid the cast and assign. It leads to aliasing problems with modern compilers #Andrew.
"... need cast the addresses of a and b to type (unsigned int *) and then dereference the addresses" reflects a risky programing technique.
To test if the bits of the unsigned integer are all zero, simply test with the constant 0.
int bit_all_zero = (val_number32 == 0);
An alternative is to use a union to access the bytes from 2 different encodings.
union {
float val_f;
uint32_t val_u;
} x = { .val_f = 12.5f };
int bit_all_zero = (x.val_u == 0);
Checking if all the bits are zero is equivalent to checking if the number is zero.
So it would be int is_zero = (val_number == 0);

Correct way of reading bytes from IEEE754 floating point format

I have a requirement where I need to read the 4 raw bytes of the single precision IEEE754 floating point representation as to send on the serial port as it is without any modification. I just wanted to ask what is the correct way of extracting the bytes among the following:
1.) creating a union such as:
typedef union {
float f;
uint8_t bytes[4];
struct {
uint32_t mantissa : 23;
uint32_t exponent : 8;
uint32_t sign : 1;
};
} FloatingPointIEEE754_t ;
and then just reading the bytes[] array after writing to the float variable f?
2.) Or, extracting bytes by a function in which a uint32_t type pointer is made to point to the float variable and then the bytes are extracted via masking
uint32_t extractBitsFloat(float numToExtFrom, uint8_t numOfBits, uint8_t bitPosStartLSB){
uint32_t *p = &numToExtFrom;
/* validate the inputs */
if ((numOfBits > 32) || (bitPosStartLSB > 31)) return NULL;
/* build the mask */
uint32_t mask = ((1 << numOfBits) - 1) << bitPosStartLSB;
return ((*p & mask) >> bitPosStartLSB);
}
where calling will be made like:
valF = -4.235;
byte0 = extractBitsFloat(valF, 8, 0);
byte1 = extractBitsFloat(valF, 8, 8);
byte2 = extractBitsFloat(valF, 8, 16);
byte3 = extractBitsFloat(valF, 8, 24);
Please suggest me the correct way if you think both the above-mentioned methods are wrong!
First of all, I assume you're coding specifically for a platform where float actually is represented in a IEEE754 single. You can't take this for granted in general, so your code won't be portable to all platforms.
Then, the union approach is the correct one. But don't add this bitfield member! There's no guarantee how the bits will be arranged, so you might access the wrong bits. Just do this:
typedef union {
float f;
uint8_t bytes[4];
} FloatingPointIEEE754;
Also, don't add a _t suffix to your own types. On POSIX systems, this is reserved to the implementation, so it's best to always avoid it.
Instead of using a union, accessing the bytes through a char pointer is fine as well:
unsigned char *rep = (unsigned char *)&f;
// access rep[0] to rep[3]
Note in both cases, you are accessing the representation in memory, this means you have to pay attention to the endianness of your machine.
Your second option isn't correct, it violates the strict aliasing rule. In short, you're not allowed to access an object through a pointer that doesn't have compatible type, a char pointer is an explicit exception for accessing the representation. The exact rules are written in 6.5 p7 of N1570, the latest draft to the C11 standard.
You can do:
unsigned char *p = (unsigned char *)&the_float;
and then read 4 bytes from where p is pointing (e.g. p[0], p[1], etc.). The exact best code to "read 4 bytes" depends on what form the serial port function accepts data in.
If you do not care of endianness, just alias a character pointer to the address of a float. The standard explicitely allows to use a charater pointer to access the bytes of the representation of any type. If you need a specific endianness to send the bytes on the serial port, you can test for it before sending:
Simple way, just use native endianness:
float f;
...
char * bytes = &f; // bytes point the the beginning of a char array of size sizeof(f)
Automatically test for endianness and uses big endian (AKA network order). The struct is just a trick to return an array and have thread safe code.
struct float_bytes {
char bytes[sizeof(float)];
};
struct float_bytes(float f) {
float end = 1.;
float_bytes resul;
char *src = (char *) &f;
if (*end == 0) { // end is 0 on a little endian platform, else 0x3f
int i = sizeof(f) { // little endian: reverse the bytes
while (i > 0) {
resul.bytes[--i] = src++;
}
}
else { // already in big endian order, just memcpy
memcpy(&(resul.bytes), &f, sizeof(f));
}
return resul;
}
Beware: the test for endianness will only make sense if floating point is IEEE754 single.

Compile time/macro swap of endianess of float in c99

I have some floats (IEEE-754) that I want to initialize. The floats are fetched by another device (automagically) which runs big endian where I am using little endian and I can't change that.
Normally I would just swap with some built in function, but they are all run-time functions. I'd perfer not having to have an init() function just to swap endianess and it would be great if I could use it for const initializations also.
Something that result in this would be perfect:
#define COMPILE_TIME_SWAPPED_FLOAT(x) (...)
const float a = COMPILE_TIME_SWAPPED_FLOAT(1.0f);
Any great ideas?
Compile time/macro swap of endian-ness of float in c99
OP has other problem with using "reverse" float as a float
A local variable of type float encoding the "reverse" endian floating point value cannot certainly be initialized as a float. Many of the values in reverse byte order would correspond to a Not-A-Number (NAN) in the local float. The assignment may not be stable (bit pattern preserving). It could be:
// not a good plan
float f1 = some_particulate_not_a_number_bit_pattern;
float f2 = some_other_particulate_not_a_number_bit_pattern;
Instead the local "reversed" endian float should just be a uint32_t, 4-byte structure/union or 4-byte array initialized in some way with a float.
// Demo of why a reversed `float` can fail
// The Not-a-numbers bit to control signaling NaN vs. quiet NaN isn't certainly preserved.
int main(void) {
for (;;) {
union {
int32_t i32;
int32_t u32;
float f;
} x,y;
x.i32 = rand();
y.f = x.f;
if (x.u32 ^ y.u32) {
// If bit pattern preserved, this should never print
// v-------+---- biased exponent max (NaN)
// |-------|v--- signaling/quiet bit
// On my machine output is always x1111111 1?xxxxxx xxxxxxxx xxxxxxxx
printf("%08x\n", (unsigned) x.u32);
printf("%08x\n\n", (unsigned) y.u32);
}
}
}
Output
7f8181b1
7fc181b1
...
The below uses a compound literal to meet OP's goal. First initialize a union's float member with the desired float. Then extract it byte-by-byte from its uint8_t member (per desired endian) to initialize a new compound literal's uint8_t array member. Then extract the uint32_t. Works for local variables.
#include <stdint.h>
#include <stdio.h>
typedef uint32_t float_reversed;
typedef union {
uint8_t u8[4];
float_reversed u32;
float f;
} endian_f;
#define ENDIAN_FN(_f,_n) ( (endian_f){.f=(_f)}.u8[(_n)] )
#define ENDIAN_F(_f) ((endian_f){ \
ENDIAN_FN(_f,3), ENDIAN_FN(_f,2), \
ENDIAN_FN(_f,1), ENDIAN_FN(_f,0)}.u32)
void print_hexf(void *f) {
for (size_t i=0; i<sizeof f; i++) {
printf("%02X", ((unsigned char *)f)[i]);
}
puts("");
}
int main(void) {
float f1 = 1.0f;
print_hexf(&f1);
float_reversed f1r = ENDIAN_F(f1);
print_hexf(&f1r);
float_reversed f2r = ENDIAN_F(1.0);
print_hexf(&f2r);
}
Output
0000803F
3F800000
3F800000
I'd say having the preprocessor to swap bytes of some non byte variable isn't possible.
The preprocessor does not know about data types and their representation on byte-level.
If the endian reversal code is available to be inlined then any half decent optimizing compiler will work out the reversed value at compile time.
Taking the reversal code from https://stackoverflow.com/a/2782742/2348315 :
inline float ReverseFloat( const float inFloat )
{
float retVal;
char *floatToConvert = ( char* ) & inFloat;
char *returnFloat = ( char* ) & retVal;
// swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
return retVal;
}
And using it in away that compiler can see all the details:
float reversed10(){
const float reversed = ReverseFloat(10.0f);
return reversed;
}
Compiles to:
reversed10():
vmovss xmm0, DWORD PTR .LC0[rip]
ret
.LC0:
.long 8257
with GCC 7.1 with -O2 enabled.
You can try other compilers over here:
https://godbolt.org/g/rFmJGP

Could copy unsigned int bit values as float but float value not returned to the caller function correctly

In the below code, I have bits correct (it was originally bits<float> type in C++ program, but I just used uint32 in this C program.). I want to use the bits as the ieee754 float value. Assigning just float_var = int_val won't do it because it interprets the value and casts to float. I want to just use the bit values as floating point values.
uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);
float out;
//memcpy(&out, &bits, sizeof(float)); // original
char *outp = &out;
char *bitsp = &bits;
outp[0] = bitsp[0];
outp[1] = bitsp[1];
outp[2] = bitsp[2];
outp[3] = bitsp[3];
ab_printf("out = %x\n", out);
return out;
part of the program run result :
ff = 3.140000
hh = 4248
bits = 40490000
out = 40092000
There must be something basic I don't know.
For your information, above run is turning float 3.14 to half-precision and back to single precision and I printed the intermediate values. 0x4248 is in half-precision 3.140625 and bits 0x40490000 is in single-precision also 3.140625, so I just need to return it as float.
ADD : After reading comments and answers, I did some experiment and found that the single-float value is seen correct inside the function(using type punning using pointer, or using union), but when it is returned to the calling function, it is not printed correctly. method 0 ~ 3 all don't work. Inline function or not doesn't make any difference. There maybe another fault in our system (an embeded, bare-metal) but hope somebody could tell me what might be wrong here.(I am using part of C++ program in a C program here). (The ldexp, ldexpf didn't work).
== half.h ==
typedef unsigned short uint16;
typedef unsigned short half;
extern uint16 float2half_impl(float value);
extern float half2float_impl(half value);
== test4.c ==
#include "half.h"
int main()
{
float vflt = 3.14;
half vhlf;
float vflt2;
ab_printf("vflt = %f\n", vflt);
vhlf = float2half_impl(vflt);
ab_printf("vhlf = %x\n", *(unsigned short *)&vhlf);
float vflt2 = half2float_impl(vhlf);
ab_printf("received : vflt2 = %f\n", vflt2);
}
== half.c ==
#include "half.h"
....
inline float half2float_impl(uint16 value)
{
//typedef bits<float>::type uint32;
typedef unsigned int uint32;
static const uint32 mantissa_table[2048] = {
....
uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
ab_printf("bits = %x\n", bits);
float out;
#define METHOD 3
#if METHOD == 0
memcpy(&out, &bits, sizeof(float));
return out;
#elif METHOD == 1
#warning METHOD 1
ab_printf("xx = %f\n", *(float *)&bits); // prints 3.140625
return bits;
#elif METHOD == 2 // prints float ok but return value float prints wrong
#warning METHOD 2
union {
unsigned int ui;
float xx;
} aa;
aa.ui = bits;
ab_printf("xx = %f\n", aa.xx); // prints 3.140625
return (float)aa.xx; // but return values prints wrong
#elif METHOD == 3 // prints float ok but return value float prints wrong
#warning METHOD 3
ab_printf("xx = %f\n", *(float *)&bits); // prints 3.140625
return *(float *)&bits; // but return values prints wrong
#else
#warning returning 0
return 0;
#endif
}
How about using a union?
union uint32_float_union
{
uint32_t i;
float f;
};
Then you can do something like
union uint32_float_union int_to_float;
int_to_float.i = bits;
printf("float value = %f\n", int_to_float.f);
Using unions for type punning is explicitly allowed by the C specification.
The memcpy way you have commented out should work to, but really breaks strict aliasing. You could use a byte-buffer as an intermediate though:
char buffer[sizeof(float)];
memcpy(buffer, &bits, sizeof(float));
float value;
memcpy(&value, buffer, sizeof(float));
Of course, all this requires that the value in bits actually corresponds to a valid float value (including correct endianness).
This:
out = *(float *)&bits;
Allows you to read bits as a float without any explicit or implicit conversion by using pointer magic.
Notice, however, that endinaness might get you a bit screwed doing this (just like memcpy() would too, so if it worked for you this method should work too, but keep in mind that this can change from architecture to architecture).
If you can be sure that the value bits of an uint32_t contain exactly the bit pattern of a IEEE754 binary32, you can "construct" your float number without requiring your uint32_t not to contain padding or your float actually conforming to IEEE754 (IOW, quite portably), by using the ldexp() function.
Here's a little example .. note it doesn't support subnormal numbers, NaN and inf; adding them is some work but can be done:
#include <stdint.h>
#include <math.h>
// read IEEE754 binary32 representation in a float
float toFloat(uint32_t bits)
{
int16_t exp = (bits >> 23 & 0xff) - 0x96;
// subtracts exponent bias (0x7f) and number of fraction bits (0x17)
int32_t sig = (bits & UINT32_C(0x7fffff)) | UINT32_C(0x800000);
if (bits & UINT32_C(0x80000000)) sig *= -1;
return ldexp(sig, exp);
}
(you could do something similar to create a float from an uint16_t containing a half precision representation, just adapt the constants for selecting the correct bits)

How to get the bit position of any member in structure

How can I get the bit position of any members in structure?
In example>
typedef struct BitExamStruct_
{
unsigned int v1: 3;
unsigned int v2: 4;
unsigned int v3: 5;
unsigned int v4: 6;
} BitExamStruct;
Is there any macro to get the bit position of any members like GetBitPos(v2, BitExamStruct)?
I thought that compiler might know members' location based on bits length in the structure. So I want to know whether I can get it by using just a simple macro without running code.
Thank you in advance.
There is no standard way that I know of to do so, but it doesn't mean you can't find a solution.
The following is not the prettiest code ever; it's a kind of hack to identify where the variable "begins" in memory. Please keep in mind that the following can give different results depending on the endianess:
#include <stdio.h>
#include <string.h>
typedef struct s_toto
{
int a:2;
int b:3;
int c:3;
} t_toto;
int
main()
{
t_toto toto;
unsigned char *c;
int bytes;
int bits;
memset(&toto, 0, sizeof(t_toto));
toto.c = 1;
c = (unsigned char *)&toto;
for (bytes = 0; bytes < (int)sizeof(t_toto); bytes++)
{
if (*c)
break;
}
for (bits = 0; bits < 8; bits++)
{
if (*c & 0b10000000)
break;
*c = (*c << 1);
}
printf("position (bytes=%d, bits=%d): %d\n", bytes, bits, (bytes * 8) + bits);
return 0;
}
What I do is that I initialize the whole structure to 0 and I set 1 as value of the variable I want to locate. The result is that only one bit is set to 1 in the structure. Then I read the memory byte per byte until I find one that's not zero. Once found, I can look at its bits until I find the one that's set.
There is no portable (aka standard C) way. But thinking outside the box, if you need full control or need this information badly, bitfields are the wrong approach. The proper solution is shifting and masking. Of course this is feasible only when you are in control of the source code.

Resources