#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace std;

typedef unsigned char uchar;
struct float3 {
    float x, y, z;
};
ostream &operator<<(ostream &out, float3 v) {
    return out << fixed << setprecision(2) << "float3( "
        << setw(5) << v.x << ","
        << setw(5) << v.y << ","
        << setw(5) << v.z << " )";
}
struct uchar4 {
    uchar x, y, z, w;
};
ostream &operator<<(ostream &out, uchar4 v) {
    return out << "uchar4( "
        << setw(3) << (int)v.x << ","
        << setw(3) << (int)v.y << ","
        << setw(3) << (int)v.z << ","
        << setw(3) << (int)v.w << " )";
}


float3 unpackCompactVector(uchar4 packed) {
    float exp = (float)(packed.w & 0x1F) - 16.0;
    float factor = exp2(exp) / 256.0;
    float x = (float)(packed.x) * factor * (packed.w & 0x20 ? -1.0 : 1.0);
    float y = (float)(packed.y) * factor * (packed.w & 0x40 ? -1.0 : 1.0);
    float z = (float)(packed.z) * factor * (packed.w & 0x80 ? -1.0 : 1.0);
    float3 result = { x, y, z };
    return result;
}

uchar4 packCompactVector(float3 vec) {
    float xAbs = abs(vec.x);   uchar xSign = vec.x < 0.0 ? 0x20 : 0;
    float yAbs = abs(vec.y);   uchar ySign = vec.y < 0.0 ? 0x40 : 0;
    float zAbs = abs(vec.z);   uchar zSign = vec.z < 0.0 ? 0x80 : 0;
    float maxAbs = max(max(xAbs, yAbs), zAbs);
    int exp = floor(log2(maxAbs)) + 1;
    float factor = exp2(exp);
    uchar xMant = floor(xAbs / factor * 256);
    uchar yMant = floor(yAbs / factor * 256);
    uchar zMant = floor(zAbs / factor * 256);
    uchar w = ((exp + 16) & 0x1F) + xSign + ySign + zSign;
    uchar4 result = { xMant, yMant, zMant, w };
    return result;
}



int main() {
    vector<float3> testCases = {
        { 1.0, 3.0, 7.95 },
        { 1.0, 3.0, 7.98 },
        { 1.0,-3.0, 8.00 },
        {-1.0, 3.0, 8.05 },
        {-1.0,-3.0, 8.10 },
    };
    for (float3 v : testCases) {
        uchar4 packed = packCompactVector(v);
        float3 unpacked = unpackCompactVector(packed);
        cout << v << " -> " << packed << " -> " << unpacked << endl;
    }
}