110 lines
2.7 KiB
C
110 lines
2.7 KiB
C
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
uint32_t getbits(float f) {
|
|
union { float f; uint32_t u; } hax;
|
|
hax.f = f;
|
|
return hax.u;
|
|
}
|
|
|
|
void printb(uint32_t u) {
|
|
for (uint32_t i = 32; i > 0; i--) {
|
|
if (i == 31 || i == 23) {
|
|
printf(" ");
|
|
}
|
|
printf("%d", (u >> (i - 1))&1);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
uint32_t getbits_meow(float f) {
|
|
printf("original: ");
|
|
printb(getbits(f));
|
|
|
|
// these are untested lol
|
|
if (f == 0.0f) {
|
|
return 0;
|
|
} else if (f == -0.0f) {
|
|
return 1 << 31;
|
|
} else if (f == NAN) {
|
|
// not always accurate
|
|
// there are multiple kinds of nan
|
|
// idk if there's much we can do tbh
|
|
return 0xFFFFFFFF;
|
|
} else if (f == INFINITY) {
|
|
return 0x7F800000;
|
|
} else if (f == -INFINITY) {
|
|
return 0xFF800000;
|
|
}
|
|
uint32_t sign = 0;
|
|
if (f < 0) {
|
|
sign = 1;
|
|
f = -f;
|
|
}
|
|
|
|
uint32_t div_count = 0;
|
|
volatile float f2 = f;
|
|
while (true) {
|
|
volatile float f3 = f2 / 2.0f;
|
|
volatile float f4 = f3 * 2.0f;
|
|
if (f4 != f2) {
|
|
break;
|
|
}
|
|
div_count++;
|
|
f2 = f3;
|
|
}
|
|
|
|
uint32_t mul_count = 0;
|
|
f2 = f;
|
|
while (true) {
|
|
volatile float f3 = f2 * 2.0f;
|
|
volatile float f4 = f3 / 2.0f;
|
|
if (f4 != f2) {
|
|
break;
|
|
}
|
|
mul_count++;
|
|
f2 = f3;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < 254-127-23; i++) {
|
|
f2 = f2 / 2.0f;
|
|
}
|
|
|
|
if (mul_count > 0xFE) {
|
|
// subnormal
|
|
uint32_t mantissa = ((uint32_t) f2) & 0b11111111111111111111111;
|
|
// add back the implicit leading 1 that would be explicit in subnormals
|
|
mantissa |= 1 << 23;
|
|
// shift into place by the number of extra times we were allowed to multiply
|
|
// (indicating the first leading 1 position)
|
|
mantissa >>= (mul_count - 0xFE + 1);
|
|
|
|
printf("result: ");
|
|
printb((sign << 31) | mantissa);
|
|
} else {
|
|
// normal
|
|
// the div count is cool and all but it allows going into subnormal range while maintaing
|
|
// equality which is not good
|
|
// so we use the mul count
|
|
uint32_t exp = 0xFE - mul_count;
|
|
uint32_t mantissa = ((uint32_t) f2) & 0b11111111111111111111111;
|
|
|
|
printf("result: ");
|
|
printb((sign << 31) | ((exp & 0xFF) << 23) | mantissa);
|
|
}
|
|
|
|
printf("----------------\n");
|
|
}
|
|
|
|
int main() {
|
|
getbits_meow(0.00000002f);
|
|
getbits_meow(0.001f);
|
|
getbits_meow(10.0f);
|
|
getbits_meow(100000.0f);
|
|
getbits_meow(10000000000.0f);
|
|
|
|
getbits_meow(0.00000000000000000000000000000000000000001f);
|
|
}
|