Skip to content

Instantly share code, notes, and snippets.

@hrydgard
Last active June 9, 2019 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hrydgard/f73b8d9f2bab46e716d09902f08bcb43 to your computer and use it in GitHub Desktop.
Save hrydgard/f73b8d9f2bab46e716d09902f08bcb43 to your computer and use it in GitHub Desktop.
Attempt at exponent-aligned fp addition
#include <iostream>
uint32_t bit_cast(float f) {
uint32_t x;
memcpy(&x, &f, 4);
return x;
}
float bit_cast(uint32_t x) {
float f;
memcpy(&f, &x, 4);
return f;
}
int get_uexp(uint32_t x) {
return (x >> 23) & 0xFF;
}
int get_mant(uint32_t x) {
return x & 0x7FFFFF;
}
// Only works with positive numbers.
float add4(float f[4]) {
uint32_t x[4];
int exps[4];
uint32_t mants[4];
uint32_t max_exp = 0;
for (int i = 0; i < 4; i++) {
x[i] = bit_cast(f[i]);
exps[i] = get_uexp(x[i]);
mants[i] = get_mant(x[i]) << 1; // Preserve one extra bit.
if (exps[i] > max_exp) {
max_exp = exps[i];
}
}
uint32_t mant_sum = 0;
for (int i = 0; i < 4; i++) {
mants[i] |= 0x1000000; // put the hidden 1s in there so the mantissa sum works properly.
mants[i] >>= max_exp - exps[i];
mant_sum += mants[i];
}
mant_sum >>= 1; // Chop off the extra bit.
// Now they all have the same exponent, max_exp.
// Sum the mantissas, adjust, and reconstruct the float.
while (mant_sum >= 0x1000000) {
mant_sum >>= 1;
max_exp += 1;
}
uint32_t y = (max_exp << 23) | (mant_sum & 0x7FFFFF);
return bit_cast(y);
}
int main()
{
std::cout << "Hello World!\n";
float a[4] = { 1.0, 1.0, 1.0, 1.0 };
float b[4] = { bit_cast((uint32_t)0x33800000), bit_cast((uint32_t)0x33800000), bit_cast((uint32_t)0x33800000), bit_cast((uint32_t)0x3F800000) };
// std::cout << add4(a) << std::endl;
std::cout << add4(b) << " " << bit_cast(add4(b)) << std::endl;
printf("%08x", bit_cast(add4(b)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment