Skip to content

Instantly share code, notes, and snippets.

@larryhou
Last active March 7, 2021 14:06
Show Gist options
  • Select an option

  • Save larryhou/c36a62d8424e7f035b63b0b75479e391 to your computer and use it in GitHub Desktop.

Select an option

Save larryhou/c36a62d8424e7f035b63b0b75479e391 to your computer and use it in GitHub Desktop.
convert memory layout among half/float/double
#include <iostream>
#include <cmath>
#ifndef DEFINE_FLOAT_TYPE
#define DEFINE_FLOAT_TYPE(_n,_s,_e,_f) \
const uint##_s##_t _n##_SIZE = _s; \
const uint##_s##_t _n##_EXPONENT_SIZE = _e; \
const uint##_s##_t _n##_FRACTION_SIZE = _f; \
const uint##_s##_t _n##_FRACTION_MASK = ((uint##_s##_t)1 << _n##_FRACTION_SIZE) - 1; \
const uint##_s##_t _n##_EXPONENT_MASK = ((uint##_s##_t)1 << _n##_EXPONENT_SIZE) - 1; \
const uint##_s##_t _n##_EXPONENT_BIAS = pow(2, _n##_EXPONENT_SIZE - 1) - 1;
#endif
DEFINE_FLOAT_TYPE(HALF, 16, 5, 10)
DEFINE_FLOAT_TYPE(FLOAT, 32, 8, 23)
DEFINE_FLOAT_TYPE(DOUBLE, 64, 11, 52)
#ifndef SHRINK_FLOAT
#define SHRINK_FLOAT(_name, _bn, _bs, _sn, _ss)\
uint##_ss##_t _name(uint##_bs##_t v)\
{\
std::cout << "call: "#_name << " " << v << std::endl; \
return (v >> (_bn##_SIZE - 1) & 1) << (_sn##_SIZE - 1)\
| ((v >> _bn##_FRACTION_SIZE & _bn##_EXPONENT_MASK) - _bn##_EXPONENT_BIAS + _sn##_EXPONENT_BIAS) << _sn##_FRACTION_SIZE\
| ((v & _bn##_FRACTION_MASK) >> (_bn##_FRACTION_SIZE - _sn##_FRACTION_SIZE));\
}
#endif
#ifndef ENLARGE_FLOAT
#define ENLARGE_FLOAT(_name, _bn, _bs, _sn, _ss)\
uint##_bs##_t _name(uint##_ss##_t v)\
{\
std::cout << "call: "#_name << " " << v << std::endl; \
return (uint##_bs##_t)(v >> (_sn##_SIZE - 1) & 1) << (_bn##_SIZE - 1)\
| (uint##_bs##_t)((v >> _sn##_FRACTION_SIZE & _sn##_EXPONENT_MASK) - _sn##_EXPONENT_BIAS + _bn##_EXPONENT_BIAS) << _bn##_FRACTION_SIZE \
| ((uint##_bs##_t)(v & _sn##_FRACTION_MASK) << (_bn##_FRACTION_SIZE - _sn##_FRACTION_SIZE));\
}
#endif
SHRINK_FLOAT(float2half, FLOAT, 32, HALF, 16)
SHRINK_FLOAT(double2half, DOUBLE, 64, HALF, 16)
SHRINK_FLOAT(double2float, DOUBLE, 64, FLOAT, 32)
ENLARGE_FLOAT(half2float, FLOAT, 32, HALF, 16)
ENLARGE_FLOAT(half2double, DOUBLE, 64, HALF, 16)
ENLARGE_FLOAT(float2double, DOUBLE, 64, FLOAT, 32)
int main(int argc, char *argv[])
{
double d = 3.1415926;
float f = 3.14;
uint64_t f2d = float2double(*(uint32_t *)&f);
double dc = pow(-1, f2d>>63&1)*pow(2.0, (f2d>>52&DOUBLE_EXPONENT_MASK) - DOUBLE_EXPONENT_BIAS)*(1.0+double(f2d&DOUBLE_FRACTION_MASK)/double(DOUBLE_FRACTION_MASK+1));
std::cout << f << '{' << *(uint32_t *)&f << "} => {" << f2d << "}" << *(double *)&f2d << " *" << dc << std::endl;
uint32_t d2f = double2float(*(uint64_t *)&d);
float fc = pow(-1, d2f>>23&1)*pow(2.0, (d2f>>23&FLOAT_EXPONENT_MASK) - FLOAT_EXPONENT_BIAS)*(1.0+float(d2f&FLOAT_FRACTION_MASK)/float(FLOAT_FRACTION_MASK+1));
std::cout << d << '{' << *(uint64_t *)&d << "} => {" << d2f << "}" << *(float *)&d2f << " *" << fc << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment