fastpfor 0.9.0

FastPFOR lib with C++ Rust wrapper and pure Rust implementation
#include <vector>
#include <memory>
#include <limits>
#include <random>
#include <cmath>
#include <string>

#include "gtest/gtest.h"

#include "codecs.h"
#include "fastpfor.h"

namespace FastPForLib {

  using ::testing::TestWithParam;
  using ::testing::Values;

  class FastPForTest : public ::testing::TestWithParam<std::string> {
    public:
      virtual void SetUp() {
        std::string name = GetParam();
        if (name == "FastPFor128") {
          codec.reset(new FastPFor<4>());
        } else if (name == "FastPFor256") {
          codec.reset(new FastPFor<8>());
        } else {
          throw new std::logic_error("Unknown codec " + name);
        }
      }

      protected:
        std::unique_ptr<IntegerCODEC> codec;
        std::vector<int32_t> in32;
        std::vector<int64_t> in64;
        std::vector<int32_t> out32;
        std::vector<int64_t> out64;

        void _verify() {
          size_t inSize = in32.size();
          std::vector<uint32_t> encoded(in32.size() * 2, ~0);
          size_t encodeSize = encoded.size();

          codec->encodeArray(
                             reinterpret_cast<uint32_t *>(in32.data()),
                             inSize,
                             encoded.data(),
                             encodeSize);

          out32.resize(inSize);
          codec->decodeArray(
                             encoded.data(),
                             encodeSize,
                             reinterpret_cast<uint32_t *>(out32.data()),
                             inSize);

          bool passed = true;
          for (size_t i = 0; i < inSize; ++i) {
            if (in32[i] != out32[i]) {
              passed = false;
            }
            EXPECT_EQ(in32[i], out32[i]);
          }
          if (!passed) {
            std::cout << "Test failed with int32 input: ";
            for (size_t i = 0; i < inSize; ++i) {
              std::cout << in32[i] << " ";
            }
            std::cout << std::endl;
          }
        }

        void _verify64() {
          size_t inSize = in64.size();
          std::vector<uint32_t> encoded(in64.size() * 4, ~0);
          size_t encodeSize = encoded.size();

          codec->encodeArray(
                             reinterpret_cast<uint64_t *>(in64.data()),
                             inSize,
                             encoded.data(),
                             encodeSize);

          out64.resize(inSize);
          codec->decodeArray(
                             encoded.data(),
                             encodeSize,
                             reinterpret_cast<uint64_t *>(out64.data()),
                             inSize);

          bool passed = true;
          for (size_t i = 0; i < inSize; ++i) {
            if (in64[i] != out64[i]) {
              passed = false;
            }
            EXPECT_EQ(in64[i], out64[i]);
          }
          if (!passed) {
            std::cout << "Test failed with int64 input: ";
            for (size_t i = 0; i < inSize; ++i) {
              std::cout << in64[i] << " ";
            }
            std::cout << std::endl;
          }
        }

        void _copy64() {
          in64.clear();
          for (size_t i = 0; i < in32.size(); ++i) {
            in64.push_back(in32[i]);
          }
        }

	template<typename T>
        void _genDataRandom(std::vector<T>& v, uint32_t values) {
          v.resize(values);
          std::mt19937_64 e2(123456);
          std::uniform_int_distribution<T> dist(
                                  std::numeric_limits<T>::min(),
                                  std::numeric_limits<T>::max());
	  std::generate_n(std::begin(v), values, std::bind(dist, e2));
        }

        void _genDataWithFixBits(
                                 std::vector<int32_t>& v,
                                 uint32_t bits,
                                 uint32_t values) {
          v.clear();
          std::mt19937_64 e2(123456);
          std::uniform_int_distribution<uint32_t> dist(
                                  0,
                                  bits == 32 ? ~0U : (1U << bits) - 1);
          for (size_t i = 0; i < values; ++i) {
            v.push_back(static_cast<int32_t>(dist(e2) | 1U << (bits - 1)));
          }
        }

        void _genDataWithFixBits64(
                                   std::vector<int64_t>& v,
                                   uint32_t bits,
                                   uint32_t values) {
          v.clear();
          std::mt19937_64 e2(123456);
          std::uniform_int_distribution<uint64_t> dist(
                                  0,
                                  bits == 64 ? ~0UL : (1ULL << bits) - 1);
          for (size_t i = 0; i < values; ++i) {
            v.push_back(static_cast<int32_t>(dist(e2) | 1ULL << (bits - 1)));
          }
        }
    };

  TEST_P(FastPForTest, increasingSequence) {
    in32.resize(0);
    for (int i = -100; i < 156; ++i) {
      in32.push_back(i);
    }
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, randomNumbers) {
    _genDataRandom(in32, 65536);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, randomNumbers64) {
    _genDataRandom(in64, 65536);
    _verify64();
  }

  TEST_P(FastPForTest, adHocNumbers64) {
    int64_t data[] = {
                -3673975021604308289,
                277811506958363848,
                -7625128575524920515,
                -3321922176697690625,
                -8484521102416600502,
                4879706116117661039,
                3108316356327171753,
                -5023690236249800232};

    in64.clear();
    for (int i = 0; i < 64; ++i) {
      for (int j = 0; j < 4; ++j) {
        in64.push_back(data[j]);
      }
    }
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_zeors) {
    in32.clear();
    for (int i = 0; i < 256; ++i) {
      in32.push_back(0);
    }
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_zeros_with_exceptions) {
    in32.clear();
    in32.push_back(1024);
    for (int i = 0; i < 254; ++i) {
      in32.push_back(0);
    }
    in32.push_back(1033);

    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_min_max) {
    _genDataRandom(in32, 256);
    in32[0] = std::numeric_limits<int32_t>::min();
    in32[127] = std::numeric_limits<int32_t>::max();
    in32[128] = std::numeric_limits<int32_t>::min();
    in32[255] = std::numeric_limits<int32_t>::max();

    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_min_max64) {
    _genDataRandom(in64, 256);
    in64[0] = std::numeric_limits<int64_t>::min();
    in64[127] = std::numeric_limits<int64_t>::max();
    in64[128] = std::numeric_limits<int64_t>::min();
    in64[255] = std::numeric_limits<int64_t>::max();

    _verify64();
  }

  TEST_P(FastPForTest, fastpack_1_noexcept) {
    _genDataWithFixBits(in32, 1, 1024);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_2_noexcept) {
    _genDataWithFixBits(in32, 2, 1024);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_4_noexcept) {
    _genDataWithFixBits(in32, 4, 1024);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_5_except) {
    _genDataWithFixBits(in32, 5, 256);
    in32[10] = 10002124;
    in32[77] = 20002124;
    in32[177] = 50002124;
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_8_noexcept) {
    _genDataWithFixBits(in32, 8, 512);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_16_noexcept) {
    _genDataWithFixBits(in32, 16, 256);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_22_noexcept) {
    _genDataWithFixBits(in32, 22, 256);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_32_noexcept) {
    _genDataWithFixBits(in32, 32, 768);
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_40_noexcept) {
    _genDataWithFixBits64(in64, 40, 512);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_41_noexcept) {
    _genDataWithFixBits64(in64, 41, 512);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_51_noexcept) {
    _genDataWithFixBits64(in64, 51, 512);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_56_noexcept) {
    _genDataWithFixBits64(in64, 56, 512);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_63_noexcept) {
    _genDataWithFixBits64(in64, 63, 512);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_64_noexcept) {
    _genDataWithFixBits64(in64, 64, 768);
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_7_except_63) {
    _genDataWithFixBits64(in64, 7, 256);
    std::vector<int64_t> excepts;
    _genDataWithFixBits64(excepts, 63, 6);
    in64[0] = excepts[0];
    in64[10] = excepts[1];
    in64[100] = excepts[2];
    in64[133] = excepts[3];
    in64[177] = excepts[4];
    in64[213] = excepts[5];
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_0_except_32) {
    _genDataWithFixBits64(in64, 32, 256);
    for (int i = 20; i < 40; ++i) {
      in64[i] = 0;
    }
    for (int i = 155; i < 195; i += 2) {
      in64[i] = 0;
    }
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_3_except_64) {
    _genDataWithFixBits64(in64, 3, 256);
    for (int i = 20; i < 40; ++i) {
      in64[i] = ~0UL - i;
    }
    for (int i = 155; i < 195; i += 2) {
      in64[i] = ~0UL - i ;
    }
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_13_with_small_numbers) {
    _genDataWithFixBits(in32, 13, 256);
    in32[20] = 3U << 5;
    in32[60] = 2U << 4;
    in32[150] = 7U << 3;
    _verify();
    _copy64();
    _verify64();
  }

  TEST_P(FastPForTest, fastpack_35_with_excepts_and_small_numbers) {
    _genDataWithFixBits64(in64, 35, 256);
    std::vector<int64_t> excepts;
    _genDataWithFixBits64(excepts, 48, 6);
    in64[10] = 5U << 5;
    in64[133] = 7U << 4;
    in64[115] = 6U << 3;

    in64[5] = excepts[0];
    in64[21] = excepts[1];
    in64[22] = excepts[2];
    in64[137] = excepts[3];
    in64[155] = excepts[4];
    in64[221] = excepts[5];
    _verify64();
  }

  INSTANTIATE_TEST_SUITE_P(
      FastPForLib,
      FastPForTest,
      Values("FastPFor128",
             "FastPFor256"));
}