/* Copyright (C) 2018 David Robillard This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #undef NDEBUG #include "test_utils.hpp" #include "chilbert/BoundedBitVec.hpp" #include "chilbert/DynamicBitVec.hpp" #include "chilbert/SmallBitVec.hpp" #include "chilbert/StaticBitVec.hpp" #include "chilbert/detail/gray_code_rank.hpp" #include #include #include #include #include #include #include template T get_mask(const std::array& ms, const size_t d, const size_t step) { T mask = make_zero_bitvec(); size_t b; chilbert::detail::extract_mask(ms.data(), D, d, step, mask, b); assert(b == mask.count()); return mask; } template void test_extract_mask(Context& ctx) { for (size_t d = 0; d < D; ++d) { const auto ms = make_random_precisions(ctx); const auto max_m = *std::max_element(std::begin(ms), std::end(ms)); const size_t step = rand_between(ctx, 0, max_m); const auto mask = get_mask(ms, d, step); for (size_t i = 0; i < D; ++i) { assert(mask.test(i) == (ms[(d + i) % D] > step)); } } } template void test_gray_code_rank(Context& ctx) { for (size_t d = 0; d < D; ++d) { // Generate random mask const auto mask = make_random_bitvec(ctx); // Generate two random values and their gray codes const auto a = make_random_bitvec(ctx); const auto b = make_random_bitvec(ctx); auto ga = a; chilbert::detail::gray_code(ga); auto gb = b; chilbert::detail::gray_code(gb); // Calculate gray code ranks auto ra = make_zero_bitvec(); chilbert::detail::gray_code_rank(mask, ga, D, ra); auto rb = make_zero_bitvec(); chilbert::detail::gray_code_rank(mask, gb, D, rb); // Ensure ranks have at most mask.count() bits auto max = make_zero_bitvec(); chilbert::detail::set_bit(max, mask.count(), 1); assert(ra < max); assert(rb < max); // Test fundamental property of gray code ranks const auto mga = ga & mask; const auto mgb = gb & mask; assert((mga < mgb) == (ra < rb)); // Test inversion const auto pat = ~mask; auto ga_out = make_zero_bitvec(); auto gag_out = make_zero_bitvec(); chilbert::detail::gray_code_rank_inv( mask, pat, ra, D, mask.count(), gag_out, ga_out); assert((ga_out & mask) == (ga & mask)); auto gag_check = ga_out; chilbert::detail::gray_code(gag_check); assert(gag_check == gag_out); } } template void test(Context& ctx) { test_extract_mask(ctx); test_gray_code_rank(ctx); } int main() { Context ctx; test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test, 64, 1>(ctx); test, 64, 31>(ctx); test, 64, 32>(ctx); test, 64, 33>(ctx); test, 64, 60>(ctx); test, 64, 64>(ctx); test, 96, 65>(ctx); test, 1024, 997>(ctx); test, 64, 1>(ctx); test, 64, 31>(ctx); test, 64, 32>(ctx); test, 64, 33>(ctx); test, 64, 60>(ctx); test, 64, 64>(ctx); test, 96, 65>(ctx); test, 1024, 997>(ctx); test, 1024, 997>(ctx); return 0; }