// Copyright (c) 2019, Vincent SAMY // All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // The views and conclusions contained in the software and documentation are those // of the authors and should not be interpreted as representing official policies, // either expressed or implied, of the FreeBSD Project. #pragma once #include "catch_helper.h" #include "differentiators.h" #include "difi" #include #include using namespace difi; template class DiffTester { friend Derived; static constexpr const size_t TSize = std::tuple_size_v; public: DiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) : m_filters(filters) , m_f(f) , m_df(df) {} void run(const std::array& eps) { testRunner(eps); } private: template void test(Filter& filt, T eps) { static_cast(*this).testFilter(filt, eps); } template void testRunner(const std::array& eps) { test(std::get(m_filters), eps[Index]); testRunner(eps); } template <> void testRunner<0>(const std::array& eps) { test(std::get<0>(m_filters), eps[0]); } private: vectX_t m_f; vectX_t m_df; Tuple m_filters; }; template class TFDiffTester : public DiffTester> { friend DiffTester>; public: TFDiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) : DiffTester(filters, f, df) {} void setFilterTimestep(T step) { setStep(step); } private: template void testFilter(Filter& filt, T eps) { for (int i = 0; i < 50; ++i) { auto value = filt.stepFilter(m_f(i)); // First initialize, some steps value = 2.; } for (int i = 50; i < STEPS; ++i) { auto value = filt.stepFilter(m_f(i)); REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); } } template void setStep(T step) { std::get(m_filters).setTimestep(step); setStep(step); } template <> void setStep<0>(T step) { std::get<0>(m_filters).setTimestep(step); } }; template class TVDiffTester : public DiffTester> { friend DiffTester>; public: TVDiffTester(const Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df) : DiffTester(filters, f, df) , m_time(t) {} private: template void testFilter(Filter& filt, T eps) { for (int i = 0; i < 50; ++i) { auto value = filt.stepFilter(m_time(i), m_f(i)); // First initialize, some steps value = 2.; } for (int i = 50; i < STEPS; ++i) { auto value = filt.stepFilter(m_time(i), m_f(i)); REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); } } private: vectX_t m_time; }; template using central_list = std::tuple, LowNoiseLanczosDiff, SuperLowNoiseLanczosDiff, CenteredNoiseRobust2Diff, CenteredNoiseRobust4Diff>; template TFDiffTester> generateCTester(const vectX_t& f, const vectX_t& df) { return { central_list{}, f, df }; } template TFDiffTester>> generateC2OTester(const vectX_t& f, const vectX_t& df) { return { std::tuple>{}, f, df }; } template using tv_central_list = std::tuple, TVCenteredNoiseRobust4Diff>; template TVDiffTester> generateTVCTester(const vectX_t& t, const vectX_t& f, const vectX_t& df) { return { tv_central_list{}, t, f, df }; }