// Copyright 2018-2022 David Robillard // SPDX-License-Identifier: GPL-2.0-or-later #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/operations.hpp" #include "chilbert/operators.hpp" #include #include #include template void test_and(Context& ctx) { const T a = make_random_bitvec(ctx); const T b = make_random_bitvec(ctx); T r = a; assert((a & b) == (r &= b)); for (size_t i = 0; i < N; ++i) { assert(r.test(i) == (a.test(i) && b.test(i))); } } template void test_or(Context& ctx) { const T a = make_random_bitvec(ctx); const T b = make_random_bitvec(ctx); T r = a; assert((a | b) == (r |= b)); for (size_t i = 0; i < N; ++i) { assert(r.test(i) == (a.test(i) || b.test(i))); } } template void test_xor(Context& ctx) { const T a = make_random_bitvec(ctx); const T b = make_random_bitvec(ctx); T r = a; assert((a ^ b) == (r ^= b)); for (size_t i = 0; i < N; ++i) { assert(r.test(i) == (a.test(i) != b.test(i))); } } template void test_not(Context& ctx) { const T v = make_random_bitvec(ctx); const T r = ~v; for (size_t i = 0; i < N; ++i) { assert(r.test(i) == !v.test(i)); } } template void test_flip_one(Context&) { T v = make_zero_bitvec(); for (size_t i = 0; i < N; ++i) { assert(v.none()); v.flip(i); for (size_t j = 0; j < N; ++j) { assert(v.test(j) == (j == i)); } v.flip(i); assert(v.none()); } } template void test_flip_all(Context& ctx) { const T a = make_random_bitvec(ctx); T r = a; r.flip(); for (size_t i = 0; i < N; ++i) { assert(r.test(i) == !a.test(i)); } } template void test_none(Context&) { T v = make_zero_bitvec(); assert(v.none()); v.set(); assert(v.none() == (N == 0)); if (N > 1) { v.reset(N / 2); assert(!v.none()); v.reset(); v.set(N / 2); assert(!v.none()); } } template void test_set_reset_one(Context&) { T v = make_zero_bitvec(); for (size_t i = 0; i < N; ++i) { assert(v.none()); v.set(i); for (size_t j = 0; j < N; ++j) { assert(v.test(j) == (j == i)); } v.reset(i); assert(v.none()); } } template void test_set_all(Context&) { T v = make_zero_bitvec(); v.set(); for (size_t i = 0; i < N; ++i) { assert(v.test(i)); } } template void test_reset_all(Context&) { T v = make_zero_bitvec(); v.set(); v.reset(); for (size_t i = 0; i < N; ++i) { assert(!v.test(i)); } } template void test_left_shift(Context& ctx) { for (size_t s = 0; s < N; ++s) { const T v = make_random_bitvec(ctx); T r = v; assert((v << s) == (r <<= s)); for (size_t i = 0; i < s; ++i) { assert(!r.test(i)); } for (size_t i = s; i < N; ++i) { assert(r.test(i) == v.test(i - s)); } } } template void test_right_shift(Context& ctx) { for (size_t s = 0; s < N; ++s) { const T v = make_random_bitvec(ctx); T r = v; assert((v >> s) == (r >>= s)); for (size_t i = N - 1; i > N - s - 1; --i) { assert(!r.test(i)); } for (size_t i = 0; i <= N - s - 1; ++i) { assert(r.test(i) == v.test(i + s)); } } } template void test_left_rotate(Context& ctx) { const T v = make_random_bitvec(ctx); for (size_t bits = 0; bits <= N; ++bits) { T r = v; r.rotl(bits); if (N > 0) { for (size_t i = 0; i < N; ++i) { assert(r.test((i + bits) % N) == v.test(i)); } } } } template void test_right_rotate(Context& ctx) { const T v = make_random_bitvec(ctx); for (size_t bits = 0; bits <= N; ++bits) { T r = v; r.rotr(bits); if (N > 0) { for (size_t i = 0; i < N; ++i) { assert(r.test(i) == v.test((i + bits) % N)); } } } } template void test_find_first(Context&) { T v = make_zero_bitvec(); for (size_t i = 0; i < N; ++i) { v.reset(); v.set(i); for (size_t j = i + 1; j < N; ++j) { v.set(j, static_cast(rand() % 2)); } assert(size_t(v.find_first()) == i + 1); } } template void test_gray_code(Context& ctx) { const T v = make_random_bitvec(ctx); T r = v; chilbert::detail::gray_code(r); if (N > 0) { assert(N == 1 || r == (v ^ (v >> 1))); T s = r; chilbert::detail::gray_code_inv(s); assert(s == v); } } template void test_comparison(Context&) { T a = make_zero_bitvec(); T b = make_zero_bitvec(); for (size_t bit = 1; bit < N; ++bit) { chilbert::detail::set_bit(a, bit, 1); for (size_t i = 0; i < bit; ++i) { chilbert::detail::set_bit(a, i, rand() % 2 == 0); chilbert::detail::set_bit(b, i, rand() % 2 == 0); } assert(b < a); } } template void test_iteration(Context&) { T v = make_zero_bitvec(); size_t count = 0; for (const auto bit : v) { assert(!bit); ++count; } assert(count == N); v.flip(); count = 0; for (const auto bit : v) { assert(bit); ++count; } assert(count == N); } template void test(Context& ctx) { test_and(ctx); test_or(ctx); test_xor(ctx); test_not(ctx); test_flip_one(ctx); test_flip_all(ctx); test_none(ctx); test_set_reset_one(ctx); test_set_all(ctx); test_reset_all(ctx); test_left_shift(ctx); test_right_shift(ctx); test_left_rotate(ctx); test_right_rotate(ctx); test_find_first(ctx); test_gray_code(ctx); test_comparison(ctx); test_iteration(ctx); } int main() { Context ctx; // test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); #ifdef _MSC_VER # pragma message("DynamicBitVec rotl and rotr are broken on MSVC") #else test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); test(ctx); #endif test, 0>(ctx); test, 1>(ctx); test, 31>(ctx); test, 32>(ctx); test, 33>(ctx); test, 63>(ctx); test, 64>(ctx); test, 65>(ctx); test, 997>(ctx); test, 0>(ctx); test, 1>(ctx); test, 31>(ctx); test, 32>(ctx); test, 33>(ctx); test, 63>(ctx); test, 64>(ctx); test, 65>(ctx); test, 997>(ctx); test, 997>(ctx); return 0; }