Skip to content

Instantly share code, notes, and snippets.

@kaneta1992
Created January 13, 2019 17:49
Show Gist options
  • Save kaneta1992/f4c19ec069903fb6c94af33dc72be034 to your computer and use it in GitHub Desktop.
Save kaneta1992/f4c19ec069903fb6c94af33dc72be034 to your computer and use it in GitHub Desktop.
GLSLで使いたいのでビット演算を使わずにfloatをunsigned char 4つにパック・アンパックする
#include <cmath>
#include <limits>
#include <iostream>
struct ivec4 {
unsigned char x, y, z, w;
};
float fract(float x) {
return x - std::floorf(x);
}
float sign(float x) {
if (x > 0.0f) {
return 1.0f;
}
else if (x == 0.0f) {
return 0.0f;
}
else {
return -1.0f;
}
}
unsigned char step(float a, float b) {
return a <= b ? 1 : 0;
}
ivec4 packn(float val) {
float a = fract(val);
float b = fract(val * 256.0f);
float c = fract(val * 256.0f * 256.0f);
ivec4 ret;
ret.y = unsigned char(a * 256.0f);
ret.z = unsigned char(b * 256.0f);
ret.w = unsigned char(c * 128.0f);
return ret;
}
float unpackn(ivec4 packed) {
return (packed.y / 256.0f) + (packed.z / 256.0f / 256.0f) + (packed.w / 128.0f / 256.0f / 256.0f);
}
ivec4 pack(float val) {
float s = sign(val);
val *= s;
float log = std::log2f(val);
float exp = std::floorf(log);
float pow = std::powf(2.0f, exp);
float m = val / pow;
ivec4 packed = packn(m - 1.0f);
packed.x = unsigned char(exp + 127.0f);
packed.w += step(s, 0.0) * 128;
return packed;
}
float unpack(ivec4 packed) {
float e = float(packed.x - 127.0f);
float f = std::floorf(float(packed.w / 128.0f));
float s = sign(f - 0.5f);
packed.w -= unsigned char(f * 128);
float m = unpackn(packed) + 1.0f;
return m * std::powf(2.0f, float(e)) * -s;
}
int main() {
std::cout << std::fixed;
float val = 0.114514f;
ivec4 packed = packn(val);
std::cout << "val = " << val << " unpacked = " << unpackn(packed) << std::endl;
val = -121.0001f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
val = 114514.1919f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
val = 456.4322f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
val = -0.000012f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
val = 1.0f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
val = 0.0f;
packed = pack(val);
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl;
getchar();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment