faiss/tests/test_cppcontrib_uintreader.cpp

115 lines
3.4 KiB
C++

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// This test was designed to be run using valgrind or ASAN to test the
// correctness of memory accesses.
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <random>
#include <faiss/utils/hamming.h>
#include <faiss/cppcontrib/detail/UintReader.h>
template <intptr_t N_ELEMENTS, intptr_t CODE_BITS, intptr_t CPOS>
struct TestLoop {
static void test(
const uint8_t* const container,
faiss::BitstringReader& br) {
// validate
const intptr_t uintreader_data = faiss::cppcontrib::detail::
UintReaderRaw<N_ELEMENTS, CODE_BITS, CPOS>::get(container);
const intptr_t bitstringreader_data = br.read(CODE_BITS);
ASSERT_EQ(uintreader_data, bitstringreader_data)
<< "Mismatch between BitstringReader (" << bitstringreader_data
<< ") and UintReader (" << uintreader_data
<< ") for N_ELEMENTS=" << N_ELEMENTS
<< ", CODE_BITS=" << CODE_BITS << ", CPOS=" << CPOS;
//
TestLoop<N_ELEMENTS, CODE_BITS, CPOS + 1>::test(container, br);
}
};
template <intptr_t N_ELEMENTS, intptr_t CODE_BITS>
struct TestLoop<N_ELEMENTS, CODE_BITS, N_ELEMENTS> {
static void test(
const uint8_t* const container,
faiss::BitstringReader& br) {}
};
template <intptr_t N_ELEMENTS, intptr_t CODE_BITS>
void TestUintReader() {
constexpr intptr_t CODE_BYTES = (CODE_BITS * N_ELEMENTS + 7) / 8;
std::default_random_engine rng;
std::uniform_int_distribution<uint64_t> u(0, 1 << CODE_BITS);
// do several attempts
for (size_t attempt = 0; attempt < 10; attempt++) {
// allocate a buffer. This way, not std::vector
std::unique_ptr<uint8_t[]> container(new uint8_t[CODE_BYTES]);
// make it empty
for (size_t i = 0; i < CODE_BYTES; i++) {
container.get()[i] = 0;
}
// populate it
faiss::BitstringWriter bw(container.get(), CODE_BYTES);
for (size_t i = 0; i < N_ELEMENTS; i++) {
bw.write(u(rng), CODE_BITS);
}
// read it back and verify against bitreader
faiss::BitstringReader br(container.get(), CODE_BYTES);
TestLoop<N_ELEMENTS, CODE_BITS, 0>::test(container.get(), br);
}
}
template <intptr_t CODE_BITS>
void TestUintReaderBits() {
TestUintReader<1, CODE_BITS>();
TestUintReader<2, CODE_BITS>();
TestUintReader<3, CODE_BITS>();
TestUintReader<4, CODE_BITS>();
TestUintReader<5, CODE_BITS>();
TestUintReader<6, CODE_BITS>();
TestUintReader<7, CODE_BITS>();
TestUintReader<8, CODE_BITS>();
TestUintReader<9, CODE_BITS>();
TestUintReader<10, CODE_BITS>();
TestUintReader<11, CODE_BITS>();
TestUintReader<12, CODE_BITS>();
TestUintReader<13, CODE_BITS>();
TestUintReader<14, CODE_BITS>();
TestUintReader<15, CODE_BITS>();
TestUintReader<16, CODE_BITS>();
TestUintReader<17, CODE_BITS>();
}
TEST(testCppcontribUintreader, Test8bit) {
TestUintReaderBits<8>();
}
TEST(testCppcontribUintreader, Test10bit) {
TestUintReaderBits<10>();
}
TEST(testCppcontribUintreader, Test12bit) {
TestUintReaderBits<12>();
}
TEST(testCppcontribUintreader, Test16bit) {
TestUintReaderBits<16>();
}