/* 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/BigBitVec.hpp" #include "chilbert/FixBitVec.hpp" #include "chilbert/GrayCodeRank.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::extractMask(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 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); // 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; grayCode(ga); auto gb = b; grayCode(gb); // Calculate gray code ranks auto ra = make_zero_bitvec(); chilbert::grayCodeRank(mask, ga, D, ra); auto rb = make_zero_bitvec(); chilbert::grayCodeRank(mask, gb, D, rb); // Ensure ranks have at most mask.count() bits if (mask.count() < N) { auto max = make_zero_bitvec(); setBit(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(); grayCodeRankInv(mask, pat, ra, D, mask.count(), gag_out, ga_out); assert((ga_out & mask) == (ga & mask)); auto gag_check = ga_out; grayCode(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); return 0; }