float压缩

1 minute read

Published:

本文介绍float 数据的有损压缩。



#include <stdio.h>
#include <cstdint>

/// navi decode
inline void decode(uint32_t packed, float* out) {
  union {
    uint32_t u32;
    uint8_t u8[4];
  } buff;

  buff.u32 = packed;

#pragma GCC unroll 4
  for (int i = 0; i < 4; ++i) {
    out[3 - i] = buff.u8[i] / 100.0f;
  }
}

inline void decodep50(uint32_t packed, float* out) {
  union {
    uint32_t u32;
    uint16_t u16[2];
  } buff;

  buff.u32 = packed;

#pragma GCC unroll 2
  for (int i = 0; i < 2; ++i) {
    out[1 - i] = buff.u16[i] / 1000.0f;
  }
}

/// nni encode
inline uint32_t encode(const float* __restrict p) {
  return (uint32_t(p[0] * 100) << 24) | (uint32_t(p[1] * 100) << 16) | (uint32_t(p[2] * 100) << 8) |
    uint32_t(p[3] * 100);
}

/// nni encode
inline uint32_t encodep50(const float* __restrict p) {
  return (uint32_t(p[0] * 1000) << 16) | (uint32_t(p[1] * 1000));
}

int main() {
  constexpr int raw_length = 12;
  constexpr int ratio = 2;
  constexpr int encoded_length = raw_length / ratio;

  float raw[raw_length] = {
    0.2341f,
    0.5632f,
    0.1713f,
    0.1225f,
    0.1126f,
    0.8907f,
    0.3339f,
    0.2547f,
    0.7121f,
    0.9982f,
    0.5333f,
    0.9811f,
  };

  uint32_t packed[encoded_length];
  for (int i = 0; i < encoded_length; ++i) {
    if (ratio == 4)
      packed[i] = encode((float*)raw + i * ratio);
    else if (ratio == 2)
      packed[i] = encodep50((float*)raw + i * ratio);
  }

  float out[raw_length];
  for (int i = 0; i < encoded_length; ++i) {
    if (ratio == 4)
      decode(packed[i], (float*)out + i * ratio);
    else if (ratio == 2)
      decodep50(packed[i], (float*)out + i * ratio);
  }

  printf("Raw     values: ");
  for (int i = 0; i < raw_length; ++i) {
    printf("%f ", raw[i]);
  }

  printf("\n");

  printf("Decoded values: ");
  for (int i = 0; i < raw_length; ++i) {
    printf("%.3f ", out[i]);
  }
  printf("\n");

  return 0;
}

// g++  main.cc -o test