diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 68d4707..3b8409e 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -24,17 +24,18 @@ jobs: config: Debug static_lib: OFF coverage: ON - - os: ubuntu-18.04 + - os: ubuntu-20.04 config: Release static_lib: ON coverage: OFF + fail-fast: false defaults: run: shell: bash runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set Project Name run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" >> $GITHUB_ENV - name: Create Build Directory diff --git a/.gitmodules b/.gitmodules index 7ea6cfc..c914c07 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vendor/googletest"] path = vendor/googletest url = https://github.com/google/googletest.git +[submodule "vendor/courierr"] + path = vendor/courierr + url = https://github.com/bigladder/courierr.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 96dd8ed..6c75f3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,6 @@ if (${PROJECT_NAME}_BUILD_TESTING) endif() endif() - add_subdirectory(src) add_subdirectory(vendor) diff --git a/cmake/compiler-flags.cmake b/cmake/compiler-flags.cmake index 813003a..a213da0 100644 --- a/cmake/compiler-flags.cmake +++ b/cmake/compiler-flags.cmake @@ -2,6 +2,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (UNIX) add_definitions("-fPIC") endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eb23fee..a4e2d13 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,6 @@ set(library_sources gridpoint.h gridpoint.cpp error.h - error.cpp ) option( ${PROJECT_NAME}_STATIC_LIB "Make ${PROJECT_NAME} a static library" ON ) @@ -21,6 +20,8 @@ else() add_library(${PROJECT_NAME} SHARED ${library_sources}) endif() +target_link_libraries(${PROJECT_NAME} PUBLIC courierr fmt) + target_compile_options(btwxt PRIVATE $<$:/W4> $<$,$,$>: diff --git a/src/btwxt.cpp b/src/btwxt.cpp index e76f719..b156936 100644 --- a/src/btwxt.cpp +++ b/src/btwxt.cpp @@ -11,32 +11,40 @@ namespace Btwxt { -RegularGridInterpolator::RegularGridInterpolator() = default; - -RegularGridInterpolator::RegularGridInterpolator(GriddedData &grid_data_in) - : grid_data(grid_data_in), grid_point(grid_data) {} +RegularGridInterpolator::RegularGridInterpolator(const std::vector> &grid, std::shared_ptr messenger) + : grid_data(grid, messenger), grid_point(grid_data, messenger), btwxt_logger(messenger) {} RegularGridInterpolator::RegularGridInterpolator(const std::vector> &grid, - const std::vector> &values) - : grid_data(grid, values), grid_point(grid_data) {} + const std::vector> &values, std::shared_ptr messenger) + : grid_data(grid, values, messenger) + , grid_point(grid_data, messenger) + , btwxt_logger(messenger) +{ +} -RegularGridInterpolator::RegularGridInterpolator(const RegularGridInterpolator &source) { +RegularGridInterpolator::RegularGridInterpolator(const RegularGridInterpolator &source) + : grid_data(source.grid_data), grid_point(source.grid_point), btwxt_logger(source.btwxt_logger) { *this = source; } -double RegularGridInterpolator::get_value_at_target(std::vector target, +std::size_t RegularGridInterpolator::add_value_table(const std::vector &value_vector) { + return grid_data.add_value_table(value_vector); +} + +double RegularGridInterpolator::get_value_at_target(const std::vector& target, std::size_t table_index) { set_new_target(target); - std::vector result = grid_point.get_results(); - return result[table_index]; + auto results = grid_point.get_results(); + return results[table_index]; } double RegularGridInterpolator::get_value_at_target(std::size_t table_index) { - std::vector result = grid_point.get_results(); - return result[table_index]; + auto results = grid_point.get_results(); + return results[table_index]; } -std::vector RegularGridInterpolator::get_values_at_target(const std::vector &target) { +std::vector +RegularGridInterpolator::get_values_at_target(const std::vector &target) { set_new_target(target); return grid_point.get_results(); } @@ -45,22 +53,26 @@ std::vector RegularGridInterpolator::get_values_at_target() { return grid_point.get_results(); } -double RegularGridInterpolator::normalize_values_at_target(std::size_t table_index, const std::vector &target, const double scalar) { +double RegularGridInterpolator::normalize_values_at_target(std::size_t table_index, + const std::vector &target, + const double scalar) { set_new_target(target); return normalize_values_at_target(table_index, scalar); } -double RegularGridInterpolator::normalize_values_at_target(std::size_t table_index, const double scalar) { +double RegularGridInterpolator::normalize_values_at_target(std::size_t table_index, + const double scalar) { return grid_point.normalize_grid_values_at_target(table_index, scalar); } -void RegularGridInterpolator::normalize_values_at_target(const std::vector &target, const double scalar) { +void RegularGridInterpolator::normalize_values_at_target(const std::vector &target, + const double scalar) { set_new_target(target); normalize_values_at_target(scalar); } void RegularGridInterpolator::normalize_values_at_target(const double scalar) { - grid_point.normalize_grid_values_at_target(scalar); + return grid_point.normalize_grid_values_at_target(scalar); } void RegularGridInterpolator::set_new_target(const std::vector &target) { @@ -71,16 +83,25 @@ std::vector RegularGridInterpolator::get_current_target() { return grid_point.get_current_target(); } -void RegularGridInterpolator::clear_current_target() { grid_point = GridPoint(grid_data); } +void RegularGridInterpolator::clear_current_target() { + grid_point = GridPoint(grid_data, btwxt_logger); +} -std::size_t RegularGridInterpolator::get_ndims() { return grid_data.get_ndims(); } +std::size_t RegularGridInterpolator::get_ndims() const { return grid_data.get_ndims(); } -std::vector> &RegularGridInterpolator::get_hypercube() { - return grid_point.get_hypercube(); -} +std::size_t RegularGridInterpolator::get_num_tables() const { return grid_data.get_num_tables(); } std::pair RegularGridInterpolator::get_axis_limits(int dim) { return grid_data.get_extrap_limits(dim); } +void RegularGridInterpolator::set_logger(std::shared_ptr logger, bool set_gridaxes) +{ + btwxt_logger = logger; + grid_point.set_logger(logger); + if (set_gridaxes) { + grid_data.set_logger(logger); + } +} + } // namespace Btwxt diff --git a/src/btwxt.h b/src/btwxt.h index 89500a8..87887b2 100644 --- a/src/btwxt.h +++ b/src/btwxt.h @@ -5,36 +5,31 @@ #define GRIDINTERP_H_ // Standard +#include #include +#include + +#include // btwxt +#include "error.h" #include "griddeddata.h" #include "gridpoint.h" namespace Btwxt { -enum class MsgLevel { MSG_DEBUG, MSG_INFO, MSG_WARN, MSG_ERR }; -extern int LOG_LEVEL; - -typedef void (*BtwxtCallbackFunction)(const MsgLevel messageType, const std::string message, - void *contextPtr); - -extern BtwxtCallbackFunction btwxtCallbackFunction; -extern void *messageCallbackContextPtr; - -void setMessageCallback(BtwxtCallbackFunction callbackFunction, void *contextPtr); - // this will be the public-facing class. class RegularGridInterpolator { public: - // GridSpace, GridAxis, AllValueTables, ValueTable are instantiated in RGI constructor. + RegularGridInterpolator() = default; - RegularGridInterpolator(); + RegularGridInterpolator(GriddedData &grid_data_in, std::shared_ptr messenger) + : grid_data(grid_data_in), grid_point(grid_data, messenger), btwxt_logger(messenger) {} - explicit RegularGridInterpolator(GriddedData &grid_data); + RegularGridInterpolator(const std::vector> &grid, std::shared_ptr messenger); RegularGridInterpolator(const std::vector> &grid, - const std::vector> &values); + const std::vector> &values, std::shared_ptr messenger); RegularGridInterpolator(const RegularGridInterpolator &source); @@ -45,19 +40,34 @@ class RegularGridInterpolator { grid_data = source.grid_data; grid_point = source.grid_point; + btwxt_logger = source.btwxt_logger; if (source.grid_point.grid_data != nullptr) { this->grid_point.grid_data = &this->grid_data; } return *this; } +// RegularGridInterpolator(RegularGridInterpolator&& source) = delete; +// +// RegularGridInterpolator& operator=(RegularGridInterpolator&& source) { +// if (this == &source) { +// return *this; +// } +// grid_data = std::move(source.grid_data); +// grid_point = std::move(source.grid_point); +// if (source.grid_point.grid_data != nullptr) { +// this->grid_point.grid_data = &this->grid_data; +// } +// callback_function_ = std::move(source.callback_function_); // what happens to the function pointer in members? +// caller_context_ = source.caller_context_; +// return *this; +// } + // Add value table to GriddedData - std::size_t add_value_table(std::vector &value_vector) { - return grid_data.add_value_table(value_vector); - } + std::size_t add_value_table(const std::vector &value_vector); // GridPoint gets instantiated inside calculate_value_at_target - double get_value_at_target(std::vector target, std::size_t table_index); + double get_value_at_target(const std::vector& target, std::size_t table_index); double operator()(std::vector target, std::size_t table_index) { return get_value_at_target(std::move(target), table_index); @@ -71,8 +81,8 @@ class RegularGridInterpolator { std::vector get_values_at_target(const std::vector &target); - std::vector operator()(const std::vector &target) { - return get_values_at_target(target); + std::vector operator()(std::vector target) { + return get_values_at_target(std::move(target)); } std::vector operator()() { return get_values_at_target(); } @@ -85,25 +95,43 @@ class RegularGridInterpolator { double normalize_values_at_target(std::size_t table_index, const double scalar = 1.0); - double normalize_values_at_target(std::size_t table_index, const std::vector &target, const double scalar = 1.0); + double normalize_values_at_target(std::size_t table_index, const std::vector &target, + const double scalar = 1.0); std::vector get_current_target(); void clear_current_target(); - std::size_t get_ndims(); + std::size_t get_ndims() const; + + std::size_t get_num_tables() const; void set_axis_interp_method(std::size_t dim, Method method) { grid_data.set_axis_interp_method(dim, method); } - std::vector>& get_hypercube(); + void set_axis_extrap_method(const std::size_t &dim, Method method) { + grid_data.set_axis_extrap_method(dim, method); + } + + void set_axis_extrap_limits(const std::size_t &dim, + const std::pair &extrap_limits) { + grid_data.set_axis_extrap_limits(dim, extrap_limits); + } std::pair get_axis_limits(int dim); + void set_logger(std::shared_ptr logger, bool set_gridaxes = false); + + Courierr::Courierr& get_logger() { return *btwxt_logger; }; + private: + friend class TwoDFixtureWithLoggingContext; + friend class TwoDFixtureWithLoggingContext_set_message_context_Test; + GriddedData grid_data; GridPoint grid_point; + std::shared_ptr btwxt_logger; }; } // namespace Btwxt diff --git a/src/error.cpp b/src/error.cpp deleted file mode 100644 index 758b9bf..0000000 --- a/src/error.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2018 Big Ladder Software LLC. All rights reserved. - * See the LICENSE file for additional terms and conditions. */ - -// Standard -#include -#include - -// Btwxt -#include "error.h" - -namespace Btwxt { - -BtwxtCallbackFunction btwxtCallbackFunction; -void *messageCallbackContextPtr; -int LOG_LEVEL = 2; - -void showMessage(const MsgLevel messageType, const std::string message) { - if (btwxtCallbackFunction != nullptr) { - (*btwxtCallbackFunction)(messageType, message, messageCallbackContextPtr); - } else if (messageType == MsgLevel::MSG_ERR) { - std::cout << " ERROR: " << message << std::endl; - throw std::invalid_argument(stringify(" ERROR: ", message)); - } else { - if (static_cast(messageType) >= Btwxt::LOG_LEVEL) { - std::string prefix(" DEBUG: "); - if (messageType == MsgLevel::MSG_WARN) { - prefix = " WARNING: "; - } else if (messageType == MsgLevel::MSG_INFO) { - prefix = " NOTE: "; - } - std::cout << prefix << message << std::endl; - } - } -} - -void setMessageCallback(BtwxtCallbackFunction callBackFunction, void *contextPtr) { - btwxtCallbackFunction = callBackFunction; - messageCallbackContextPtr = contextPtr; -} - -} // namespace Btwxt diff --git a/src/error.h b/src/error.h index 8ea8a39..bbd97eb 100644 --- a/src/error.h +++ b/src/error.h @@ -4,15 +4,14 @@ #ifndef BTWXT_ERROR_H_ #define BTWXT_ERROR_H_ +#include #include +#include -// BTWXT -#include "btwxt.h" +#include namespace Btwxt { -void showMessage(MsgLevel messageType, std::string message); - struct expand_type { template expand_type(T &&...) {} }; @@ -23,5 +22,21 @@ template std::string stringify(ArgTypes... args) { return oss.str(); } +class BtwxtException : public Courierr::CourierrException { + public: + explicit BtwxtException(const char* message, Courierr::Courierr& logger) + : CourierrException(message, logger) + { + } + explicit BtwxtException(const std::string& message, Courierr::Courierr& logger) + : CourierrException(message, logger) + { + } + explicit BtwxtException(const std::string_view message, Courierr::Courierr& logger) + : CourierrException(message, logger) + { + } +}; + } // namespace Btwxt #endif // BTWXT_ERROR_H_ diff --git a/src/griddeddata.cpp b/src/griddeddata.cpp index 644b9df..7bc7dea 100644 --- a/src/griddeddata.cpp +++ b/src/griddeddata.cpp @@ -2,9 +2,11 @@ * See the LICENSE file for additional terms and conditions. */ // Standard -#include #include #include +#include + +#include // btwxt #include "error.h" @@ -12,17 +14,21 @@ namespace Btwxt { -GridAxis::GridAxis() = default; - -GridAxis::GridAxis(std::vector grid_vector, Method extrapolation_method, - Method interpolation_method, std::pair extrapolation_limits) +GridAxis::GridAxis(std::vector grid_vector, std::shared_ptr logger, + Method extrapolation_method, Method interpolation_method, + std::pair extrapolation_limits) : grid(std::move(grid_vector)), spacing_multipliers(2, std::vector(std::max((int)grid.size() - 1, 0), 1.0)), extrapolation_method(extrapolation_method), interpolation_method(interpolation_method), - extrapolation_limits(std::move(extrapolation_limits)) { + extrapolation_limits(std::move(extrapolation_limits)), + gridaxis_logger(logger) { + if (!logger) + { + throw std::exception(); // TODO: correct exception + } if (grid.size() == 0) { - showMessage(MsgLevel::MSG_ERR, "Cannot create a GridAxis from a zero-length vector."); + throw BtwxtException("Cannot create a GridAxis from a zero-length vector.", *logger); } check_grid_sorted(); check_extrap_limits(); @@ -47,16 +53,17 @@ void GridAxis::set_extrap_limits(const std::pair extrap_limits) check_extrap_limits(); } -double GridAxis::get_spacing_multiplier(const std::size_t &flavor, const std::size_t &index) { +double GridAxis::get_spacing_multiplier(const std::size_t &flavor, const std::size_t &index) const { return spacing_multipliers[flavor][index]; } void GridAxis::calc_spacing_multipliers() { // "0" and "1" are the "flavors" of the calc_spacing_multipliers. - // If you are sitting at the "0" along an edge of the hypercube, you want the "0" flavof + // If you are sitting at the "0" along an edge of the hypercube, you want the "0" flavor if (grid.size() == 1) { - set_interp_method(Method::LINEAR); - showMessage(MsgLevel::MSG_INFO, "A cubic interpolation method is not valid for grid axes with only one value. Interpolation method reset to linear."); + interpolation_method = Method::LINEAR; + gridaxis_logger->info("A cubic interpolation method is not valid for grid axes with only one value. " + "Interpolation method reset to linear."); } double center_spacing; for (std::size_t i = 0; i < grid.size() - 1; i++) { @@ -73,27 +80,30 @@ void GridAxis::calc_spacing_multipliers() { void GridAxis::check_grid_sorted() { bool grid_is_sorted = Btwxt::free_check_sorted(grid); if (!grid_is_sorted) { - showMessage(MsgLevel::MSG_ERR, "axis is not sorted."); + throw BtwxtException("Axis is not sorted.", *gridaxis_logger); } } void GridAxis::check_extrap_limits() { if (extrapolation_limits.first > grid[0]) { - showMessage(MsgLevel::MSG_INFO, stringify("The lower extrapolation limit (", extrapolation_limits.first,") is within the set of grid values. Setting to smallest grid value (", grid[0],").")); + gridaxis_logger->info(stringify("The lower extrapolation limit (", extrapolation_limits.first, + ") is within the set of grid values. Setting to smallest grid value (", + grid[0], ").")); extrapolation_limits.first = grid[0]; } if (extrapolation_limits.second < grid.back()) { - showMessage(MsgLevel::MSG_INFO, stringify("The upper extrapolation limit (", extrapolation_limits.first,") is within the set of grid values. Setting to largest grid value (", grid.back(),").")); + gridaxis_logger->info(stringify("The upper extrapolation limit (", extrapolation_limits.first, + ") is within the set of grid values. Setting to largest grid value (", + grid.back(), ").")); extrapolation_limits.second = grid.back(); } } -GriddedData::GriddedData() = default; - GriddedData::GriddedData(std::vector> grid, - std::vector> values) - : ndims(grid.size()), dimension_lengths(ndims), dimension_step_size(ndims), temp_coords(ndims) { + std::vector> values, std::shared_ptr logger) + : griddeddata_logger(logger), ndims(grid.size()), dimension_lengths(ndims), dimension_step_size(ndims), temp_coords(ndims) { construct_axes(grid); + set_logger(logger); set_dimension_sizes(); num_tables = values.size(); results.resize(num_tables); @@ -101,12 +111,23 @@ GriddedData::GriddedData(std::vector> grid, value_tables = values; } -GriddedData::GriddedData(std::vector grid_axes, std::vector> values) +GriddedData::GriddedData(std::vector> grid, std::shared_ptr logger) + : griddeddata_logger(logger), ndims(grid.size()), dimension_lengths(ndims), dimension_step_size(ndims), temp_coords(ndims) { + construct_axes(grid); + set_logger(logger); + set_dimension_sizes(); + num_tables = 0; +} + +GriddedData::GriddedData(std::vector grid_axes, std::vector> values, + std::shared_ptr logger) : grid_axes(grid_axes), + griddeddata_logger(logger), ndims(grid_axes.size()), dimension_lengths(ndims), dimension_step_size(ndims), temp_coords(ndims) { + set_logger(logger); set_dimension_sizes(); num_tables = values.size(); results.resize(num_tables); @@ -114,12 +135,14 @@ GriddedData::GriddedData(std::vector grid_axes, std::vector grid_axes) +GriddedData::GriddedData(std::vector grid_axes, std::shared_ptr logger) : grid_axes(grid_axes), + griddeddata_logger(logger), ndims(grid_axes.size()), dimension_lengths(ndims), dimension_step_size(ndims), temp_coords(ndims) { + set_logger(logger); set_dimension_sizes(); num_tables = 0; } @@ -129,7 +152,7 @@ void GriddedData::set_dimension_sizes() { for (std::size_t dim = ndims - 1; /* dim >= 0 */ dim < ndims; --dim) { std::size_t length = grid_axes[dim].get_length(); if (length == 0) { - showMessage(MsgLevel::MSG_ERR, stringify("Dimension ", dim, " has an axis of length zero.")); + throw BtwxtException(stringify("Dimension ", dim, " has an axis of length zero."), *griddeddata_logger); } dimension_lengths[dim] = length; dimension_step_size[dim] = num_values; @@ -139,14 +162,14 @@ void GriddedData::set_dimension_sizes() { void GriddedData::construct_axes(const std::vector> &grid) { for (const auto &axis : grid) { - grid_axes.emplace_back(axis); + grid_axes.emplace_back(axis, griddeddata_logger); } } -std::size_t GriddedData::add_value_table(std::vector &value_vector) { +std::size_t GriddedData::add_value_table(const std::vector &value_vector) { if (value_vector.size() != num_values) { - showMessage(MsgLevel::MSG_ERR, stringify("Input value table does not match the grid size: ", - value_vector.size(), " != ", num_values)); + throw BtwxtException(stringify("Input value table does not match the grid size: ", + value_vector.size(), " != ", num_values), *griddeddata_logger); } value_tables.push_back(value_vector); num_tables++; @@ -154,11 +177,7 @@ std::size_t GriddedData::add_value_table(std::vector &value_vector) { return num_tables - 1; } -std::size_t GriddedData::get_ndims() { return grid_axes.size(); } - -std::size_t GriddedData::get_num_tables() { return num_tables; } - -std::size_t GriddedData::get_value_index(const std::vector &coords) { +std::size_t GriddedData::get_value_index(const std::vector &coords) const { std::size_t index = 0; for (std::size_t dim = 0; dim < ndims; ++dim) { index += coords[dim] * dimension_step_size[dim]; @@ -167,7 +186,7 @@ std::size_t GriddedData::get_value_index(const std::vector &coords) } std::size_t GriddedData::get_value_index_relative(const std::vector &coords, - const std::vector &translation) { + const std::vector &translation) { int new_coord; for (std::size_t dim = 0; dim < coords.size(); dim++) { new_coord = static_cast(coords[dim]) + translation[dim]; @@ -198,20 +217,20 @@ std::vector GriddedData::get_values(const std::size_t index) { } std::vector GriddedData::get_values_relative(const std::vector &coords, - const std::vector &translation) { + const std::vector &translation) { return get_values(get_value_index_relative(coords, translation)); } -const std::vector &GriddedData::get_grid_vector(const std::size_t &dim) { +const std::vector &GriddedData::get_grid_vector(const std::size_t dim) { return grid_axes[dim].grid; } -std::pair GriddedData::get_extrap_limits(const std::size_t &dim) { +std::pair GriddedData::get_extrap_limits(const std::size_t dim) const { return grid_axes[dim].extrapolation_limits; } -double GriddedData::get_axis_spacing_mult(const std::size_t &dim, const std::size_t &flavor, - const std::size_t &index) { +double GriddedData::get_axis_spacing_mult(const std::size_t dim, const std::size_t flavor, + const std::size_t index) const { if (grid_axes[dim].interpolation_method == Method::CUBIC) { return grid_axes[dim].get_spacing_multiplier(flavor, index); } else { @@ -219,12 +238,12 @@ double GriddedData::get_axis_spacing_mult(const std::size_t &dim, const std::siz } } -void GriddedData::set_axis_extrap_method(const std::size_t &dim, +void GriddedData::set_axis_extrap_method(const std::size_t dim, const Method extrapolation_method) { grid_axes[dim].extrapolation_method = extrapolation_method; } -std::vector GriddedData::get_extrap_methods() { +std::vector GriddedData::get_extrap_methods() const { std::vector extrap_methods(ndims); for (std::size_t dim = 0; dim < ndims; dim++) { extrap_methods[dim] = grid_axes[dim].extrapolation_method; @@ -232,12 +251,12 @@ std::vector GriddedData::get_extrap_methods() { return extrap_methods; } -void GriddedData::set_axis_extrap_limits(const std::size_t &dim, - const std::pair &extrap_limits) { +void GriddedData::set_axis_extrap_limits(const std::size_t dim, + const std::pair &extrap_limits) { grid_axes[dim].set_extrap_limits(extrap_limits); } -std::vector GriddedData::get_interp_methods() { +std::vector GriddedData::get_interp_methods() const { std::vector interp_methods(ndims); for (std::size_t dim = 0; dim < ndims; dim++) { interp_methods[dim] = grid_axes[dim].interpolation_method; @@ -245,7 +264,7 @@ std::vector GriddedData::get_interp_methods() { return interp_methods; } -void GriddedData::set_axis_interp_method(const std::size_t &dim, +void GriddedData::set_axis_interp_method(const std::size_t dim, const Method interpolation_method) { grid_axes[dim].set_interp_method(interpolation_method); } @@ -253,34 +272,34 @@ void GriddedData::set_axis_interp_method(const std::size_t &dim, void GriddedData::normalize_value_table(std::size_t table_num, double scalar) { auto &table = value_tables[table_num]; if (scalar == 0.0) { - showMessage(MsgLevel::MSG_ERR, "Attempt to normalize values by zero."); + throw BtwxtException("Attempt to normalize values by zero.", *griddeddata_logger); } - scalar = 1.0/scalar; + scalar = 1.0 / scalar; std::transform(table.begin(), table.end(), table.begin(), std::bind(std::multiplies(), std::placeholders::_1, scalar)); } std::string GriddedData::write_data() { - std::vector indices(ndims,0); + std::vector indices(ndims, 0); std::stringstream output(""); - for (std::size_t dim=0; dim < ndims; ++dim) { + for (std::size_t dim = 0; dim < ndims; ++dim) { output << "Axis " << dim + 1 << ","; } - for (std::size_t tab=0; tab < num_tables; ++tab) { + for (std::size_t tab = 0; tab < num_tables; ++tab) { output << "Value " << tab + 1 << ","; } output << std::endl; - for (std::size_t index=0; index < num_values; ++index) { - for (std::size_t dim=0; dim < ndims; ++dim) { + for (std::size_t index = 0; index < num_values; ++index) { + for (std::size_t dim = 0; dim < ndims; ++dim) { output << grid_axes[dim].grid[indices[dim]] << ","; } - for (std::size_t tab=0; tab < num_tables; ++tab) { + for (std::size_t tab = 0; tab < num_tables; ++tab) { output << value_tables[tab][index] << ","; } output << std::endl; ++indices[ndims - 1]; - for (std::size_t dim= ndims - 1; dim > 0; --dim) { + for (std::size_t dim = ndims - 1; dim > 0; --dim) { if (indices[dim] >= dimension_lengths[dim]) { ++indices[dim - 1]; indices[dim] = 0; @@ -290,6 +309,15 @@ std::string GriddedData::write_data() { return output.str(); } +void GriddedData::set_logger(std::shared_ptr logger) +{ + griddeddata_logger = logger; + for (std::size_t dim = 0; dim < ndims; dim++) { + grid_axes[dim].set_logger(logger); + } +} + + // free functions bool free_check_sorted(std::vector my_vec) { // ensures that the grid vector is strictly ascending diff --git a/src/griddeddata.h b/src/griddeddata.h index 20f6f48..647e3cb 100644 --- a/src/griddeddata.h +++ b/src/griddeddata.h @@ -4,8 +4,14 @@ #ifndef GRIDDEDDATA_H_ #define GRIDDEDDATA_H_ +#include "error.h" #include +#include #include +#include +#include + +namespace Courierr { class Courier; } namespace Btwxt { @@ -14,11 +20,12 @@ enum class Method { CONSTANT, LINEAR, CUBIC, UNDEF }; class GridAxis { // A single input dimension of the performance space public: - GridAxis(); + GridAxis() = default; - GridAxis(std::vector grid_vector, Method extrapolation_method = Method::CONSTANT, - Method interpolation_method = Method::LINEAR, - std::pair extrapolation_limits = {-DBL_MAX, DBL_MAX}); + GridAxis(std::vector grid_vector, std::shared_ptr logger, + Method extrapolation_method = Method::CONSTANT, + Method interpolation_method = Method::LINEAR, + std::pair extrapolation_limits = {-DBL_MAX, DBL_MAX}); std::vector grid; std::vector> spacing_multipliers; @@ -26,17 +33,19 @@ class GridAxis { Method interpolation_method; std::pair extrapolation_limits; - // bool is_regular; <-- to add later - std::size_t get_length(); void set_interp_method(Method interpolation_method); void set_extrap_method(Method extrapolation_method); void set_extrap_limits(std::pair extrap_limits); - double get_spacing_multiplier(const std::size_t &flavor, const std::size_t &index); + double get_spacing_multiplier(const std::size_t &flavor, const std::size_t &index) const; + + void set_logger(std::shared_ptr logger) { gridaxis_logger = logger; } + Courierr::Courierr& get_logger() { return *gridaxis_logger; }; private: + std::shared_ptr gridaxis_logger; void calc_spacing_multipliers(); void check_grid_sorted(); void check_extrap_limits(); @@ -44,25 +53,27 @@ class GridAxis { class GriddedData { public: - GriddedData(); + GriddedData() = default; + + GriddedData(std::vector> grid, std::vector> values, std::shared_ptr message_courier); - GriddedData(std::vector> grid, std::vector> values); + GriddedData(std::vector> grid, std::shared_ptr message_courier); - GriddedData(std::vector grid_axes, std::vector> values); + explicit GriddedData(std::vector grid_axes, std::vector> values, std::shared_ptr message_courier); - explicit GriddedData(std::vector grid_axes); + explicit GriddedData(std::vector grid_axes, std::shared_ptr message_courier); - std::size_t get_ndims(); + inline std::size_t get_ndims() const { return grid_axes.size(); } - std::size_t get_num_tables(); + inline std::size_t get_num_tables() const { return num_tables; } - std::size_t add_value_table(std::vector &value_vector); + std::size_t add_value_table(const std::vector &value_vector); - const std::vector &get_grid_vector(const std::size_t &dim); + const std::vector &get_grid_vector(const std::size_t dim); - std::pair get_extrap_limits(const std::size_t &dim); + std::pair get_extrap_limits(const std::size_t dim) const; - std::size_t get_value_index(const std::vector &coords); + std::size_t get_value_index(const std::vector &coords) const; std::size_t get_value_index_relative(const std::vector &coords, const std::vector &translation); @@ -70,41 +81,47 @@ class GriddedData { std::vector get_values(const std::vector &coords); std::vector get_values_relative(const std::vector &coords, - const std::vector &translation); + const std::vector &translation); std::vector get_values(const std::size_t index); - double get_axis_spacing_mult(const std::size_t &dim, const std::size_t &flavor, - const std::size_t &index); + double get_axis_spacing_mult(const std::size_t dim, const std::size_t flavor, + const std::size_t index) const; - std::vector get_interp_methods(); + std::vector get_interp_methods() const; - std::vector get_extrap_methods(); + std::vector get_extrap_methods() const; void normalize_value_table(std::size_t table_num, double scalar = 1.0); - void set_axis_extrap_method(const std::size_t &dim, Method); + void set_axis_extrap_method(const std::size_t dim, Method); - void set_axis_extrap_limits(const std::size_t &dim, + void set_axis_extrap_limits(const std::size_t dim, const std::pair &extrap_limits); - void set_axis_interp_method(const std::size_t &dim, Method); + void set_axis_interp_method(const std::size_t dim, Method); std::string write_data(); + void set_logger(std::shared_ptr logger); + + std::vector grid_axes; + +private: + friend class TwoDFixture; + friend class TwoDFixture_construct_from_axes_Test; + std::shared_ptr griddeddata_logger; std::vector> value_tables; std::size_t num_values; std::size_t num_tables; - std::vector grid_axes; std::size_t ndims; std::vector dimension_lengths; - -private: - void construct_axes(const std::vector> &grid); - void set_dimension_sizes(); std::vector dimension_step_size; std::vector temp_coords; std::vector results; + + void construct_axes(const std::vector> &grid); + void set_dimension_sizes(); }; // free functions diff --git a/src/gridpoint.cpp b/src/gridpoint.cpp index 2b49e47..0e72750 100644 --- a/src/gridpoint.cpp +++ b/src/gridpoint.cpp @@ -2,18 +2,20 @@ * See the LICENSE file for additional terms and conditions. */ // Standard +#include #include #include -#include + +#include // btwxt #include "error.h" -namespace Btwxt { +#include "gridpoint.h" -GridPoint::GridPoint() {} +namespace Btwxt { -GridPoint::GridPoint(GriddedData &grid_data_in) +GridPoint::GridPoint(GriddedData &grid_data_in, std::shared_ptr logger) : grid_data(&grid_data_in), ndims(grid_data->get_ndims()), target(ndims, 0.0), @@ -27,11 +29,13 @@ GridPoint::GridPoint(GriddedData &grid_data_in) weighting_factors(ndims, std::vector(4, 0.0)), interp_coeffs(ndims, std::vector(2, 0.0)), cubic_slope_coeffs(ndims, std::vector(2, 0.0)), - results(grid_data->num_tables), - hypercube_size_hash(0) { + results(grid_data->get_num_tables()), + hypercube_size_hash(0), + gridpoint_logger(logger) +{ } -GridPoint::GridPoint(GriddedData &grid_data_in, std::vector v) +GridPoint::GridPoint(GriddedData &grid_data_in, std::vector v, std::shared_ptr logger) : grid_data(&grid_data_in), ndims(grid_data->get_ndims()), target_is_set(false), @@ -43,17 +47,18 @@ GridPoint::GridPoint(GriddedData &grid_data_in, std::vector v) weighting_factors(ndims, std::vector(4, 0.0)), interp_coeffs(ndims, std::vector(2, 0.0)), cubic_slope_coeffs(ndims, std::vector(2, 0.0)), - results(grid_data->num_tables) { + results(grid_data->get_num_tables()), + gridpoint_logger(logger) +{ set_target(v); } void GridPoint::set_target(const std::vector &v) { if (v.size() != ndims) { - showMessage(MsgLevel::MSG_ERR, - stringify("Target and Gridded Data do not have the same dimensions.")); + throw BtwxtException(stringify("Target and Gridded Data do not have the same dimensions."), *gridpoint_logger); } if (target_is_set) { - if (std::equal(v.begin(), v.end(), target.begin()) && (methods == grid_data->get_interp_methods())) { + if ((v == target) && (methods == grid_data->get_interp_methods())) { return; } } @@ -68,9 +73,7 @@ void GridPoint::set_target(const std::vector &v) { std::vector GridPoint::get_current_target() { if (!target_is_set) { - showMessage(MsgLevel::MSG_WARN, - stringify("The current target was requested, but no target has been set.")); - return target; + gridpoint_logger->warning(stringify("The current target was requested, but no target has been set.")); } return target; } @@ -95,23 +98,26 @@ void GridPoint::set_floor() { } void GridPoint::set_dim_floor(std::size_t dim) { - GridAxis &axis = grid_data->grid_axes[dim]; + const GridAxis &axis = grid_data->grid_axes[dim]; std::size_t l = axis.grid.size(); if (target[dim] < axis.extrapolation_limits.first) { is_inbounds[dim] = Bounds::OUTLAW; point_floor[dim] = 0u; } else if (target[dim] > axis.extrapolation_limits.second) { is_inbounds[dim] = Bounds::OUTLAW; - point_floor[dim] = std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. + point_floor[dim] = + std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. } else if (target[dim] < axis.grid[0]) { is_inbounds[dim] = Bounds::OUTBOUNDS; point_floor[dim] = 0; } else if (target[dim] > axis.grid.back()) { is_inbounds[dim] = Bounds::OUTBOUNDS; - point_floor[dim] = std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. + point_floor[dim] = + std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. } else if (target[dim] == axis.grid.back()) { is_inbounds[dim] = Bounds::INBOUNDS; - point_floor[dim] = std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. + point_floor[dim] = + std::max((int)l - 2, 0); // l-2 because that's the left side of the (l-2, l-1) edge. } else { is_inbounds[dim] = Bounds::INBOUNDS; std::vector::const_iterator upper = @@ -146,9 +152,9 @@ void GridPoint::consolidate_methods() if (target_is_set) { auto extrap_methods = grid_data->get_extrap_methods(); for (std::size_t dim = 0; dim < ndims; dim++) { - if (is_inbounds[dim]==Bounds::OUTBOUNDS) { + if (is_inbounds[dim] == Bounds::OUTBOUNDS) { methods[dim] = extrap_methods[dim]; - } else if (is_inbounds[dim]==Bounds::OUTLAW) { + } else if (is_inbounds[dim] == Bounds::OUTLAW) { // showMessage(MsgLevel::MSG_WARN, stringify("The target is outside the extrapolation limits // in dimension ", dim, // ". Will perform constant extrapolation.")); @@ -166,8 +172,8 @@ void GridPoint::set_hypercube() { set_hypercube(grid_data->get_interp_methods()) void GridPoint::set_hypercube(std::vector m_methods) { if (m_methods.size() != ndims) { - showMessage(MsgLevel::MSG_ERR, stringify("Error setting hypercube. Methods vector does not " - "have the correct number of dimensions.")); + throw BtwxtException(stringify("Error setting hypercube. Methods vector does not " + "have the correct number of dimensions."), *gridpoint_logger); } std::size_t previous_size = hypercube.size(); std::vector> options(ndims, {0, 1}); @@ -182,7 +188,7 @@ void GridPoint::set_hypercube(std::vector m_methods) { } else if (m_methods[dim] == Method::CUBIC) { options[dim] = {-1, 0, 1, 2}; } - hypercube_size_hash += options[dim].size()*digit; + hypercube_size_hash += options[dim].size() * digit; digit *= 10; } hypercube = {{}}; @@ -197,7 +203,7 @@ void GridPoint::set_hypercube(std::vector m_methods) { hypercube = std::move(r); } if (hypercube.size() != previous_size) { - hypercube_values.resize(hypercube.size(), std::vector(grid_data->num_tables)); + hypercube_values.resize(hypercube.size(), std::vector(grid_data->get_num_tables())); hypercube_weights.resize(hypercube.size()); } } @@ -213,8 +219,10 @@ void GridPoint::calculate_interp_coeffs() { if (methods[dim] == Method::CUBIC) { interp_coeffs[dim][0] = 2 * mu * mu * mu - 3 * mu * mu + 1; interp_coeffs[dim][1] = -2 * mu * mu * mu + 3 * mu * mu; - cubic_slope_coeffs[dim][0] = (mu * mu * mu - 2 * mu * mu + mu)*grid_data->get_axis_spacing_mult(dim, 0, point_floor[dim]); - cubic_slope_coeffs[dim][1] = (mu * mu * mu - mu * mu)*grid_data->get_axis_spacing_mult(dim, 1, point_floor[dim]); + cubic_slope_coeffs[dim][0] = (mu * mu * mu - 2 * mu * mu + mu) * + grid_data->get_axis_spacing_mult(dim, 0, point_floor[dim]); + cubic_slope_coeffs[dim][1] = + (mu * mu * mu - mu * mu) * grid_data->get_axis_spacing_mult(dim, 1, point_floor[dim]); } else { if (methods[dim] == Method::CONSTANT) { mu = mu < 0 ? 0 : 1; @@ -232,13 +240,13 @@ void GridPoint::calculate_interp_coeffs() { } void GridPoint::set_hypercube_values() { - if (results.size() != grid_data->num_tables) { - results.resize(grid_data->num_tables); - hypercube_values.resize(hypercube.size(), std::vector(grid_data->num_tables)); + if (results.size() != grid_data->get_num_tables()) { + results.resize(grid_data->get_num_tables()); + hypercube_values.resize(hypercube.size(), std::vector(grid_data->get_num_tables())); hypercube_cache.clear(); } - if (hypercube_cache.count({floor_index,hypercube_size_hash})) { - hypercube_values = hypercube_cache.at({floor_index,hypercube_size_hash}); + if (hypercube_cache.count({floor_index, hypercube_size_hash})) { + hypercube_values = hypercube_cache.at({floor_index, hypercube_size_hash}); return; } std::size_t hypercube_index = 0; @@ -246,7 +254,7 @@ void GridPoint::set_hypercube_values() { hypercube_values[hypercube_index] = grid_data->get_values_relative(point_floor, v); ++hypercube_index; } - hypercube_cache[{floor_index,hypercube_size_hash}] = hypercube_values; + hypercube_cache[{floor_index, hypercube_size_hash}] = hypercube_values; } void GridPoint::set_results() { @@ -255,20 +263,18 @@ void GridPoint::set_results() { for (std::size_t i = 0; i < hypercube.size(); ++i) { hypercube_weights[i] = get_vertex_weight(hypercube[i]); const auto &values = hypercube_values[i]; - for (std::size_t j = 0; j < grid_data->num_tables; ++j) { + for (std::size_t j = 0; j < grid_data->get_num_tables(); ++j) { results[j] += values[j] * hypercube_weights[i]; } } } std::vector GridPoint::get_results() { - if (grid_data->num_tables == 0u) { - showMessage(MsgLevel::MSG_WARN, - stringify("There are no value tables in the gridded data. No results returned.")); + if (grid_data->get_num_tables() == 0u) { + gridpoint_logger->warning(stringify("There are no value tables in the gridded data. No results returned.")); } if (!target_is_set) { - showMessage(MsgLevel::MSG_WARN, - stringify("Results were requested, but no target has been set.")); + gridpoint_logger->warning(stringify("Results were requested, but no target has been set.")); } return results; } @@ -283,12 +289,10 @@ double GridPoint::get_vertex_weight(const std::vector &v) { void GridPoint::normalize_grid_values_at_target(const double scalar) { if (!target_is_set) { - showMessage(MsgLevel::MSG_WARN, - stringify("Cannot normalize grid values. No target has been set.")); - return; + throw BtwxtException(stringify("Cannot normalize grid values. No target has been set."), *gridpoint_logger); } - for (std::size_t table_index = 0; table_index < grid_data->num_tables; ++table_index) { - grid_data->normalize_value_table(table_index,results[table_index]*scalar); + for (std::size_t table_index = 0; table_index < grid_data->get_num_tables(); ++table_index) { + grid_data->normalize_value_table(table_index, results[table_index] * scalar); } hypercube_cache.clear(); set_results(); @@ -296,13 +300,12 @@ void GridPoint::normalize_grid_values_at_target(const double scalar) { double GridPoint::normalize_grid_values_at_target(std::size_t table_num, const double scalar) { if (!target_is_set) { - showMessage(MsgLevel::MSG_WARN, - stringify("Cannot normalize grid values. No target has been set.")); - return scalar; + throw BtwxtException(stringify("Cannot normalize grid values. No target has been set."), *gridpoint_logger); } - // create a scalar which represents the product of the inverted normalization factor and the value in the table at the independent variable reference value - double total_scalar = results[table_num]*scalar; - grid_data->normalize_value_table(table_num,total_scalar); + // create a scalar which represents the product of the inverted normalization factor and the value + // in the table at the independent variable reference value + double total_scalar = results[table_num] * scalar; + grid_data->normalize_value_table(table_num, total_scalar); hypercube_cache.clear(); set_results(); diff --git a/src/gridpoint.h b/src/gridpoint.h index f094179..72c2c9b 100644 --- a/src/gridpoint.h +++ b/src/gridpoint.h @@ -5,24 +5,29 @@ #define GRIDPOINT_H_ // Standard +#include #include +#include #include -#include // btwxt #include "griddeddata.h" +namespace Courierr { class Courierr; } + namespace Btwxt { enum class Bounds { OUTLAW, OUTBOUNDS, INBOUNDS }; + class GridPoint { public: - GridPoint(); - GridPoint(GriddedData &grid_data); + GridPoint() = default; - GridPoint(GriddedData &grid_data, std::vector v); + GridPoint(GriddedData &grid_data, std::shared_ptr logger); + + GridPoint(GriddedData &grid_data, std::vector v, std::shared_ptr logger); void set_target(const std::vector &v); @@ -50,8 +55,15 @@ class GridPoint { void set_floor(); + void set_logger(std::shared_ptr logger) { gridpoint_logger = logger; } + private: friend class RegularGridInterpolator; + friend class ThreeDFixture; + friend class ThreeDFixture_hypercube_Test; + friend class ThreeDFixture_test_hypercube_Test; + friend class ThreeDFixture_make_linear_hypercube_Test; + GriddedData *grid_data; std::size_t ndims; std::vector target; @@ -64,8 +76,8 @@ class GridPoint { std::vector previous_methods; std::vector> hypercube; bool reset_hypercube; - std::vector> weighting_factors; // A set of weighting factors for each dimension - + std::vector> + weighting_factors; // A set of weighting factors for each dimension std::vector> interp_coeffs; std::vector> cubic_slope_coeffs; @@ -74,6 +86,12 @@ class GridPoint { std::vector hypercube_weights; std::vector results; + std::map, std::vector>> hypercube_cache; + + std::size_t hypercube_size_hash; + + std::shared_ptr gridpoint_logger; + void calculate_weights(); void consolidate_methods(); @@ -86,16 +104,12 @@ class GridPoint { void set_hypercube(std::vector methods); - std::vector>& get_hypercube(); + std::vector> &get_hypercube(); void set_hypercube_values(); void set_results(); - - std::map,std::vector>> hypercube_cache; - - std::size_t hypercube_size_hash; - + }; // free functions diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1031b7f..025d83a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,13 +11,13 @@ set(library_sources gridpoint_test.cpp math_test.cpp large_test.cpp - hypercube_test.cpp -) - + hypercube_test.cpp) add_executable(${PROJECT_NAME}_tests ${library_sources}) -target_link_libraries(${PROJECT_NAME}_tests ${PROJECT_NAME} gtest gmock) +target_compile_features(${PROJECT_NAME}_tests PRIVATE cxx_std_17) + +target_link_libraries(${PROJECT_NAME}_tests ${PROJECT_NAME} gtest gmock fmt) include(GoogleTest) diff --git a/test/btwxt_test.cpp b/test/btwxt_test.cpp index 56bc257..8732a49 100644 --- a/test/btwxt_test.cpp +++ b/test/btwxt_test.cpp @@ -9,34 +9,28 @@ // btwxt #include "fixtures.hpp" -#include -#include -#include -using namespace Btwxt; +namespace Btwxt{ TEST_F(TwoDFixture, construct_from_gridded_data) { - Btwxt::LOG_LEVEL = 0; - RegularGridInterpolator rgi_from_grid(test_gridded_data); + RegularGridInterpolator rgi_from_grid(test_gridded_data, courier); std::size_t ndims = rgi_from_grid.get_ndims(); EXPECT_EQ(ndims, 2u); - Btwxt::LOG_LEVEL = 1; } TEST_F(TwoDFixture, target_undefined) { std::vector returned_target; - std::vector bad_floor; - double bad_result; std::string TargetExpectedOut = " WARNING: The current target was requested, but no target has been set.\n"; - std::string ResultsExpectedOut = - " WARNING: Results were requested, but no target has been set.\n"; // The test fixture does not instantiate a GridPoint. EXPECT_STDOUT(returned_target = test_rgi.get_current_target();, TargetExpectedOut); std::vector expected_result = {0, 0}; EXPECT_EQ(returned_target, expected_result); + double bad_result; + std::string ResultsExpectedOut = + " WARNING: Results were requested, but no target has been set.\n"; EXPECT_STDOUT(bad_result = test_rgi.get_value_at_target(0);, ResultsExpectedOut); EXPECT_EQ(bad_result, 0); @@ -76,12 +70,12 @@ TEST_F(CubicFixture, spacing_multiplier) { } TEST_F(CubicFixture, switch_interp_method) { - for (auto i = 0u; i < test_gridded_data.get_ndims(); i++) + for (auto i = 0u; i < test_rgi.get_ndims(); i++) { test_rgi.set_axis_interp_method(i, Method::CUBIC); } std::vector result1 = test_rgi.get_values_at_target(target); - for (auto i = 0u; i < test_gridded_data.get_ndims(); i++) + for (auto i = 0u; i < test_rgi.get_ndims(); i++) { test_rgi.set_axis_interp_method(i, Method::LINEAR); } @@ -92,25 +86,21 @@ TEST_F(CubicFixture, switch_interp_method) { TEST_F(CubicFixture, interpolate) { test_rgi.set_new_target(target); - Btwxt::LOG_LEVEL = 0; auto start = std::chrono::high_resolution_clock::now(); std::vector result = test_rgi.get_values_at_target(); auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); - showMessage(MsgLevel::MSG_INFO, - stringify("Time to do cubic interpolation: ", duration.count(), " microseconds")); - Btwxt::LOG_LEVEL = 1; + BtwxtContextCourierr message_display; + message_display.info(stringify("Time to do cubic interpolation: ", duration.count(), " microseconds")); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(4.158), testing::DoubleEq(11.836))); } TEST_F(TwoDFixture, interpolate) { - Btwxt::LOG_LEVEL = 0; test_rgi.set_new_target(target); // All values, current target std::vector result = test_rgi.get_values_at_target(); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(4.2), testing::DoubleEq(8.4))); - Btwxt::LOG_LEVEL = 1; // Single value, current target double d_result = test_rgi.get_value_at_target(0); EXPECT_DOUBLE_EQ(d_result, 4.2); @@ -127,91 +117,125 @@ TEST_F(TwoDFixture, interpolate) { TEST_F(TwoDFixture, extrapolate) { // axis1 is designated constant extrapolation std::vector const_extr_target = {10, 3}; - Btwxt::LOG_LEVEL = 0; std::vector result = test_rgi(const_extr_target); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(2), testing::DoubleEq(4))); - Btwxt::LOG_LEVEL = 1; // axis0 is designated linear extrapolation std::vector lin_extr_target = {18, 5}; - Btwxt::LOG_LEVEL = 0; result = test_rgi(lin_extr_target); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(1.8), testing::DoubleEq(3.6))); - Btwxt::LOG_LEVEL = 1; } TEST_F(TwoDFixture, invalid_inputs) { - // we expect two errors that the value table inputs do not match the grid - // we expect an error that the target dimensions do not match the grid + std::vector short_target = {1}; + std::string expected_error{" ERROR: Target and Gridded Data do not have the same dimensions.\n"}; + // Redirect cout to temporary local buffer (do not use EXPECT_STDOUT for throwing functions) + std::ostringstream buffer; + std::streambuf *sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + try { + test_rgi.set_new_target(short_target); + } + catch (BtwxtException&) { + EXPECT_STREQ(expected_error.c_str(), buffer.str().c_str()); + } + std::vector long_target = {1, 2, 3}; + buffer.str(""); + buffer.clear(); + try { + test_rgi.set_new_target(long_target); + } + catch (BtwxtException&) { + EXPECT_STREQ(expected_error.c_str(), buffer.str().c_str()); + } + std::cout.rdbuf(sbuf); + std::vector short_values = {6, 3, 2, 8, 4}; - EXPECT_THROW(test_gridded_data.add_value_table(short_values);, std::invalid_argument); + EXPECT_THROW(test_gridded_data.add_value_table(short_values);, BtwxtException); std::vector long_values = {1, 1, 1, 1, 1, 1, 1}; - EXPECT_THROW(test_gridded_data.add_value_table(long_values);, std::invalid_argument); + EXPECT_THROW(test_gridded_data.add_value_table(long_values);, BtwxtException); +} - std::vector short_target = {1}; - EXPECT_THROW(test_rgi.set_new_target(short_target);, std::invalid_argument); - std::vector long_target = {1, 2, 3}; - EXPECT_THROW(test_rgi.set_new_target(long_target);, std::invalid_argument); +TEST_F(TwoDFixture, logger_modify_context) { + std::vector returned_target; + std::string expected_error = " WARNING: The current target was requested, but no target has been set.\n"; + EXPECT_STDOUT(returned_target = test_rgi.get_current_target();, expected_error); + std::string context_str{"Context 1:"}; + courier->set_message_context(reinterpret_cast(&context_str)); + expected_error = "Context 1: WARNING: The current target was requested, but no target has been set.\n"; + EXPECT_STDOUT(test_rgi.get_current_target();, expected_error); } +TEST_F(TwoDFixture, unique_logger_per_rgi_instance) { + std::vector returned_target; + std::string expected_error = " WARNING: The current target was requested, but no target has been set.\n"; + EXPECT_STDOUT(returned_target = test_rgi.get_current_target();, expected_error); + + RegularGridInterpolator rgi2; + rgi2 = test_rgi; + auto logger2 = std::make_shared(); + std::string context_str{"RGI2 Context:"}; + logger2->set_message_context(reinterpret_cast(&context_str)); + rgi2.set_logger(logger2); + std::string expected_error2{"RGI2 Context: WARNING: The current target was requested, but no target has been set.\n"}; + EXPECT_STDOUT(rgi2.get_current_target();, expected_error2); + + EXPECT_STDOUT(test_rgi.get_current_target();, expected_error); // Recheck +} + +TEST_F(TwoDFixture, access_logger_in_btwxt) { + RegularGridInterpolator rgi2(test_gridded_data, std::make_shared()); + std::string context_str{"RGI2 Context:"}; + rgi2.get_logger().set_message_context(reinterpret_cast(&context_str)); + std::string expected_error2{"RGI2 Context: WARNING: The current target was requested, but no target has been set.\n"}; + EXPECT_STDOUT(rgi2.get_current_target();, expected_error2); +} + +//TODO: Test that logger copies in GriddedData/GridPoint are the same/different + TEST_F(OneDFixture, cubic_interpolate) { - Btwxt::LOG_LEVEL = 0; - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); double result = test_rgi.get_values_at_target(target)[0]; - Btwxt::LOG_LEVEL = 1; EXPECT_NEAR(result, 4.804398, 0.0001); } TEST_F(OneDL0Fixture, throw_test) { - Btwxt::LOG_LEVEL = 0; - EXPECT_THROW(GriddedData(grid, values),std::invalid_argument); + EXPECT_THROW(GriddedData(grid, values, std::make_shared()), BtwxtException); } TEST_F(OneDL1Fixture, cubic_interpolate) { - Btwxt::LOG_LEVEL = 0; - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); double result = test_rgi.get_values_at_target(target)[0]; - Btwxt::LOG_LEVEL = 1; EXPECT_NEAR(result, 5., 0.0001); } TEST_F(OneDL2Fixture, cubic_interpolate) { - Btwxt::LOG_LEVEL = 0; - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); double result = test_rgi.get_values_at_target(target)[0]; - Btwxt::LOG_LEVEL = 1; EXPECT_NEAR(result, 5.25, 0.0001); } TEST_F(TwoDFixture, cubic_interpolate) { - Btwxt::LOG_LEVEL = 0; - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); + test_rgi.set_axis_interp_method(1, Method::CUBIC); test_rgi.set_new_target(target); // All values, current target std::vector result = test_rgi.get_values_at_target(); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(4.416), testing::DoubleEq(8.832))); - Btwxt::LOG_LEVEL = 1; } TEST_F(TwoDFixture, normalize) { - Btwxt::LOG_LEVEL = 0; - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); + test_rgi.set_axis_interp_method(1, Method::CUBIC); test_rgi.set_new_target(target); // All values, current target test_rgi.normalize_values_at_target((std::size_t)0); // normalize first value table std::vector result = test_rgi.get_values_at_target(); EXPECT_THAT(result, testing::ElementsAre(testing::DoubleEq(1.0), testing::DoubleEq(8.832))); - Btwxt::LOG_LEVEL = 1; } TEST_F(TwoDSimpleNormalizationFixture, normalization_return_scalar) { @@ -238,3 +262,4 @@ TEST_F(TwoDSimpleNormalizationFixture, normalization_return_compound_scalar) { EXPECT_THAT(return_scalar, testing::DoubleEq(expected_compound_divisor)); EXPECT_THAT(results, testing::ElementsAre(expected_value_at_target)); } +} \ No newline at end of file diff --git a/test/fixtures.hpp b/test/fixtures.hpp index f2d291d..30b8093 100644 --- a/test/fixtures.hpp +++ b/test/fixtures.hpp @@ -4,6 +4,8 @@ #ifndef TEST_FIXTURE_HPP_ #define TEST_FIXTURE_HPP_ +#include + #include "gtest/gtest.h" // btwxt @@ -11,6 +13,8 @@ #include #include +#include + #define EXPECT_STDOUT(action, ExpectedOut) \ { \ std::stringstream buffer; \ @@ -21,76 +25,81 @@ EXPECT_STREQ(ExpectedOut.c_str(), buffer.str().c_str()); \ } -using namespace Btwxt; +class BtwxtContextCourierr : public Courierr::Courierr +{ + public: + void error(const std::string_view message) override { write_message(" ERROR:", message); } + void warning(const std::string_view message) override { write_message(" WARNING:", message); } + void info(const std::string_view message) override { write_message(" NOTE:", message); } + void debug(const std::string_view message) override { write_message(" DEBUG:", message); } + + private: + void write_message(const std::string_view message_type, const std::string_view message) + { + std::string context_string = message_context ? *(reinterpret_cast(message_context)) : ""; + std::cout << fmt::format("{}{} {}", context_string, message_type, message) << std::endl; + } +}; + +namespace Btwxt { class OneDFixture : public testing::Test { protected: RegularGridInterpolator test_rgi; GriddedData test_gridded_data; - std::vector target; + std::vector target{2.5}; OneDFixture() { std::vector> grid = {{0, 2, 5, 10}}; std::vector> values = {{6, 5, 4, 3}}; - target = {2.5}; - test_gridded_data = GriddedData(grid, values); - test_rgi = RegularGridInterpolator(test_gridded_data); + auto courier = std::make_shared(); + test_gridded_data = GriddedData(grid, values, courier); + test_rgi = RegularGridInterpolator(test_gridded_data, courier); } }; class OneDL0Fixture : public testing::Test { protected: - std::vector> grid; - std::vector> values; + std::vector> grid; + std::vector> values; - OneDL0Fixture() { - grid = {{}}; - values = {{}}; - } + OneDL0Fixture() { + grid = {{}}; + values = {{}}; + } }; - class OneDL1Fixture : public testing::Test { protected: - RegularGridInterpolator test_rgi; - GriddedData test_gridded_data; - std::vector target; - - OneDL1Fixture() { - std::vector> grid = {{2}}; - std::vector> values = {{5}}; - - target = {2.5}; - test_gridded_data = GriddedData(grid, values); - test_gridded_data.set_axis_extrap_method(0, Method::LINEAR); - test_rgi = RegularGridInterpolator(test_gridded_data); - } + RegularGridInterpolator test_rgi; + std::vector target{2.5}; + + OneDL1Fixture() : test_rgi({{2}}, {{5}}, std::make_shared()) { test_rgi.set_axis_extrap_method(0, Method::LINEAR); } }; class OneDL2Fixture : public testing::Test { protected: - RegularGridInterpolator test_rgi; - GriddedData test_gridded_data; - std::vector target; - - OneDL2Fixture() { - std::vector> grid = {{0, 10}}; - std::vector> values = {{6, 3}}; - - target = {2.5}; - test_gridded_data = GriddedData(grid, values); - test_gridded_data.set_axis_extrap_method(0, Method::LINEAR); - test_rgi = RegularGridInterpolator(test_gridded_data); - } + RegularGridInterpolator test_rgi; + std::vector target; + + OneDL2Fixture() { + std::vector> grid = {{0, 10}}; + std::vector> values = {{6, 3}}; + + target = {2.5}; + test_rgi = RegularGridInterpolator(grid, values, std::make_shared()); + test_rgi.set_axis_extrap_method(0, Method::LINEAR); + } }; class TwoDFixture : public testing::Test { protected: RegularGridInterpolator test_rgi; GriddedData test_gridded_data; + std::vector target{12, 5}; std::vector> values; - std::vector target; + std::shared_ptr courier = std::make_shared(); TwoDFixture() { std::vector> grid = {{0, 10, 15}, {4, 6}}; @@ -99,41 +108,39 @@ class TwoDFixture : public testing::Test { 2, 8, // 10 4, 2}, // 15 {12, 6, 4, 16, 8, 4}}; - target = {12, 5}; - test_gridded_data = GriddedData(grid, values); + test_gridded_data = GriddedData(grid, values, courier); test_gridded_data.set_axis_extrap_method(0, Method::LINEAR); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi = RegularGridInterpolator(test_gridded_data, courier); } }; class TwoDSimpleNormalizationFixture : public testing::Test { - // TODO: Create a fixture which this one can inherit from - // takes a vector of functions as a parameter (these become separate value tables) - // takes a vector of vectors which is the data structure that stores the grid + // TODO: Create a fixture which this one can inherit from + // takes a vector of functions as a parameter (these become separate value tables) + // takes a vector of vectors which is the data structure that stores the grid protected: - RegularGridInterpolator test_rgi; - GriddedData test_gridded_data; - double test_function (std::vector target){ - assert(target.size() == 2); - return target[0]*target[1]; - } + RegularGridInterpolator test_rgi; + double test_function(std::vector target) { + assert(target.size() == 2); + return target[0] * target[1]; + } - TwoDSimpleNormalizationFixture() { - std::vector> grid = {{2.0, 7.0}, {1.0, 2.0, 3.0}}; - std::vector values; - for (auto x : grid[0]){ - for (auto y : grid[1] ){ - values.push_back(test_function({x,y})); - } - } - test_gridded_data = GriddedData(grid, {values}); - test_gridded_data.set_axis_extrap_method(0, Method::LINEAR); - test_rgi = RegularGridInterpolator(test_gridded_data); + TwoDSimpleNormalizationFixture() { + std::vector> grid = {{2.0, 7.0}, {1.0, 2.0, 3.0}}; + std::vector values; + for (auto x : grid[0]) { + for (auto y : grid[1]) { + values.push_back(test_function({x, y})); + } } + test_rgi = RegularGridInterpolator(grid, {values}, std::make_shared()); + test_rgi.set_axis_extrap_method(0, Method::LINEAR); + } }; class CubicFixture : public testing::Test { protected: + std::shared_ptr courier = std::make_shared(); RegularGridInterpolator test_rgi; GriddedData test_gridded_data; std::vector target; @@ -153,10 +160,9 @@ class CubicFixture : public testing::Test { 25, 20, 10, 5}}; // 20 target = {12, 4.5}; - test_gridded_data = GriddedData(grid, values); + test_gridded_data = GriddedData(grid, values, courier); test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - // test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi = RegularGridInterpolator(test_gridded_data, courier); } }; @@ -165,22 +171,22 @@ class ThreeDFixture : public testing::Test { RegularGridInterpolator test_rgi; GriddedData test_gridded_data; std::vector> values; - std::vector target; + std::vector target{26.9, 12, 5}; ThreeDFixture() { std::vector> grid = {{-15, 0.2, 105}, {0, 10, 15}, {4, 6}}; - // 4 6 + // 4 6 values = {{6, 3, // 0 2, 8, // 10 4, 2, // 15 3, 6, 13, 2, 0, 15, 3, 6, 13, 2, 0, 15}}; - target = {26.9, 12, 5}; - test_gridded_data = GriddedData(grid, values); + auto courier = std::make_shared(); + test_gridded_data = GriddedData(grid, values, courier); test_gridded_data.set_axis_interp_method(0, Method::LINEAR); test_gridded_data.set_axis_interp_method(1, Method::CUBIC); test_gridded_data.set_axis_interp_method(2, Method::LINEAR); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi = RegularGridInterpolator(test_gridded_data, courier); } }; - #endif /* TEST_FIXTURE_HPP_ */ +} // namespace Btwxt \ No newline at end of file diff --git a/test/griddeddata_test.cpp b/test/griddeddata_test.cpp index 5aae283..a31449d 100644 --- a/test/griddeddata_test.cpp +++ b/test/griddeddata_test.cpp @@ -5,16 +5,18 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include +#include // btwxt #include "fixtures.hpp" -#include -#include +#include "error.h" +#include "griddeddata.h" -using namespace Btwxt; +namespace Btwxt { +// TODO: Useful any more? TEST_F(OneDFixture, construct_from_vectors) { - std::size_t ndims = test_gridded_data.get_ndims(); + std::size_t ndims = test_rgi.get_ndims(); EXPECT_EQ(ndims, 1u); } @@ -28,21 +30,20 @@ TEST_F(TwoDFixture, construct_from_vectors) { TEST_F(TwoDFixture, write_data) { EXPECT_EQ("Axis 1,Axis 2,Value 1,Value 2,\n" - "0,4,6,12,\n" - "0,6,3,6,\n" - "10,4,2,4,\n" - "10,6,8,16,\n" - "15,4,4,8,\n" - "15,6,2,4,\n", - test_gridded_data.write_data()); + "0,4,6,12,\n" + "0,6,3,6,\n" + "10,4,2,4,\n" + "10,6,8,16,\n" + "15,4,4,8,\n" + "15,6,2,4,\n", + test_gridded_data.write_data()); } - TEST_F(TwoDFixture, construct_from_axes) { - GridAxis ax0 = GridAxis(std::vector({0, 10, 15})); - GridAxis ax1 = GridAxis(std::vector({4, 6})); + GridAxis ax0 = GridAxis(std::vector({0, 10, 15}), courier); + GridAxis ax1 = GridAxis(std::vector({4, 6}), courier); std::vector test_axes = {ax0, ax1}; - test_gridded_data = GriddedData(test_axes); + test_gridded_data = GriddedData(test_axes, courier); EXPECT_EQ(test_gridded_data.get_ndims(), 2u); EXPECT_EQ(test_gridded_data.get_num_tables(), 0u); EXPECT_THAT(test_gridded_data.dimension_lengths, testing::ElementsAre(3, 2)); @@ -52,7 +53,7 @@ TEST_F(TwoDFixture, construct_from_axes) { std::vector coords{1, 1}; EXPECT_THAT(test_gridded_data.get_values(coords), testing::ElementsAre(8)); - test_gridded_data = GriddedData(test_axes, values); + test_gridded_data = GriddedData(test_axes, values, courier); EXPECT_EQ(test_gridded_data.get_ndims(), 2u); EXPECT_EQ(test_gridded_data.get_num_tables(), 2u); EXPECT_THAT(test_gridded_data.get_values(coords), testing::ElementsAre(8, 16)); @@ -93,9 +94,10 @@ TEST_F(TwoDFixture, get_values_relative) { TEST(GridAxis, sorting) { std::vector grid_vector = {0, 5, 7, 17, 15}; - EXPECT_THROW(GridAxis my_grid_axis = GridAxis(grid_vector);, std::invalid_argument); + auto courier = std::make_shared(); + EXPECT_THROW(GridAxis my_grid_axis = GridAxis(grid_vector, courier), BtwxtException); grid_vector = {0, 5, 7, 10, 15}; - EXPECT_NO_THROW(GridAxis my_grid_axis = GridAxis(grid_vector);); + EXPECT_NO_THROW(GridAxis my_grid_axis = GridAxis(grid_vector, courier);); } TEST_F(CubicFixture, get_spacing_multipliers) { @@ -116,14 +118,16 @@ TEST_F(CubicFixture, get_spacing_multipliers) { TEST(GridAxis, calc_spacing_multipliers) { std::vector grid_vector{6, 10, 15, 20, 22}; - GridAxis test_gridaxis(grid_vector, Method::CONSTANT, Method::CUBIC, {-DBL_MAX, DBL_MAX}); + GridAxis test_gridaxis(grid_vector, std::make_shared(), Method::CONSTANT, Method::CUBIC, + {-DBL_MAX, DBL_MAX}); std::vector> values = test_gridaxis.spacing_multipliers; EXPECT_THAT(values[0], testing::ElementsAre(1, 5.0 / 9, 0.5, 2.0 / 7)); EXPECT_THAT(values[1], testing::ElementsAre(4.0 / 9, 0.5, 5.0 / 7, 1)); } TEST(GridAxis, bad_limits) { - GridAxis my_grid_axis({0, 5, 7, 11, 12, 15}); + auto courier = std::make_shared(); + GridAxis my_grid_axis({0, 5, 7, 11, 12, 15}, courier); std::pair extrap_limits{4, 17}; std::string ExpectedOut = " NOTE: The lower extrapolation limit (4) is within the set of " "grid values. Setting to smallest grid value (0).\n"; @@ -136,3 +140,4 @@ TEST(GridAxis, bad_limits) { EXPECT_STDOUT(my_grid_axis.set_extrap_limits(extrap_limits);, ExpectedOut); EXPECT_EQ(my_grid_axis.extrapolation_limits.second, 15); } +} // namespace Btwxt \ No newline at end of file diff --git a/test/gridpoint_test.cpp b/test/gridpoint_test.cpp index 9417d5c..598b59f 100644 --- a/test/gridpoint_test.cpp +++ b/test/gridpoint_test.cpp @@ -16,7 +16,7 @@ using namespace Btwxt; TEST_F(TwoDFixture, grid_point_basics) { - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); std::vector point_floor = grid_point.get_floor(); std::vector expected_floor{1, 0}; @@ -29,7 +29,7 @@ TEST_F(TwoDFixture, grid_point_basics) { TEST_F(TwoDFixture, grid_point_out_of_bounds) { std::vector oobounds_vector = {16, 3}; - GridPoint grid_point(test_gridded_data, oobounds_vector); + GridPoint grid_point(test_gridded_data, oobounds_vector, courier); std::vector point_floor = grid_point.get_floor(); std::vector expected_floor{1, 0}; @@ -41,21 +41,21 @@ TEST_F(TwoDFixture, grid_point_out_of_bounds) { } TEST_F(TwoDFixture, grid_point_consolidate_methods) { - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); std::vector methods = grid_point.get_methods(); std::vector expected_methods{Method::LINEAR, Method::LINEAR}; EXPECT_EQ(methods, expected_methods); std::vector oobounds_vector = {12, 3}; - grid_point = GridPoint(test_gridded_data, oobounds_vector); + grid_point = GridPoint(test_gridded_data, oobounds_vector, courier); methods = grid_point.get_methods(); expected_methods = {Method::LINEAR, Method::CONSTANT}; EXPECT_EQ(methods, expected_methods); } TEST_F(TwoDFixture, grid_point_interp_coeffs) { - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); std::vector> interp_coeffs = grid_point.get_interp_coeffs(); std::vector> cubic_slope_coeffs = grid_point.get_cubic_slope_coeffs(); @@ -69,7 +69,7 @@ TEST_F(TwoDFixture, grid_point_interp_coeffs) { } TEST_F(CubicFixture, grid_point_interp_coeffs) { - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); std::vector> interp_coeffs = grid_point.get_interp_coeffs(); std::vector> cubic_slope_coeffs = grid_point.get_cubic_slope_coeffs(); @@ -79,6 +79,8 @@ TEST_F(CubicFixture, grid_point_interp_coeffs) { EXPECT_EQ(interp_coeffs[0][0], 2 * mu * mu * mu - 3 * mu * mu + 1); EXPECT_EQ(interp_coeffs[0][1], -2 * mu * mu * mu + 3 * mu * mu); - EXPECT_EQ(cubic_slope_coeffs[0][0], (mu * mu * mu - 2 * mu * mu + mu)*test_gridded_data.get_axis_spacing_mult(0,0,floor)); - EXPECT_EQ(cubic_slope_coeffs[0][1], (mu * mu * mu - mu * mu)*test_gridded_data.get_axis_spacing_mult(0,1,floor)); + EXPECT_EQ(cubic_slope_coeffs[0][0], (mu * mu * mu - 2 * mu * mu + mu) * + test_gridded_data.get_axis_spacing_mult(0, 0, floor)); + EXPECT_EQ(cubic_slope_coeffs[0][1], + (mu * mu * mu - mu * mu) * test_gridded_data.get_axis_spacing_mult(0, 1, floor)); } diff --git a/test/hypercube_test.cpp b/test/hypercube_test.cpp index 03de304..37cf78a 100644 --- a/test/hypercube_test.cpp +++ b/test/hypercube_test.cpp @@ -14,14 +14,17 @@ #include #include -using namespace Btwxt; +namespace Btwxt { TEST_F(ThreeDFixture, hypercube) { - auto hypercube = test_rgi.get_hypercube(); - EXPECT_EQ(hypercube.size(), 16u); } + GridPoint grid_point(test_gridded_data, std::make_shared()); + auto hypercube = grid_point.get_hypercube(); + EXPECT_EQ(hypercube.size(), 16u); +} TEST_F(ThreeDFixture, test_hypercube) { - auto hypercube = test_rgi.get_hypercube(); + GridPoint grid_point(test_gridded_data, std::make_shared()); + auto hypercube = grid_point.get_hypercube(); EXPECT_EQ(hypercube.size(), 2u * 4u * 2u); EXPECT_THAT(hypercube[0], testing::ElementsAre(0, -1, 0)); EXPECT_THAT(hypercube[2], testing::ElementsAre(0, 0, 0)); @@ -30,8 +33,9 @@ TEST_F(ThreeDFixture, test_hypercube) { } TEST_F(ThreeDFixture, make_linear_hypercube) { - test_rgi.set_axis_interp_method(1, Method::LINEAR); - auto hypercube = test_rgi.get_hypercube(); + test_gridded_data.set_axis_interp_method(1, Method::LINEAR); + GridPoint grid_point(test_gridded_data, std::make_shared()); + auto hypercube = grid_point.get_hypercube(); EXPECT_EQ(hypercube.size(), 8u); EXPECT_THAT(hypercube[0], testing::ElementsAre(0, 0, 0)); EXPECT_THAT(hypercube[2], testing::ElementsAre(0, 1, 0)); @@ -50,7 +54,7 @@ TEST(Hypercube, cart_product) { TEST_F(CubicFixture, hypercube_weigh_one_vertex) { test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); std::vector methods = grid_point.get_methods(); std::vector mus = grid_point.get_weights(); @@ -97,18 +101,17 @@ TEST_F(CubicFixture, hypercube_weigh_one_vertex) { TEST_F(CubicFixture, hypercube_calculations) { test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); - std::vector result = grid_point.get_results(); + auto result = grid_point.get_results(); EXPECT_NEAR(result[0], 4.1953, 0.0001); EXPECT_NEAR(result[1], 11.9271, 0.0001); } +// TODO: Determine if testing GridPoint outside of RGI has value - the "unit" of functionality is within RGI TEST_F(OneDFixture, hypercube_calculations) { - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - GridPoint grid_point(test_gridded_data, target); - std::vector methods = grid_point.get_methods(); - - std::vector result = grid_point.get_results(); + test_rgi.set_axis_interp_method(0, Method::CUBIC); + auto result = test_rgi.get_values_at_target(target); EXPECT_NEAR(result[0], 4.804398, 0.00001); } +} // namespace Btwxt \ No newline at end of file diff --git a/test/large_test.cpp b/test/large_test.cpp index a4a17ea..1f655d9 100644 --- a/test/large_test.cpp +++ b/test/large_test.cpp @@ -2,15 +2,16 @@ * See the LICENSE file for additional terms and conditions. */ // Standard -#include "gmock/gmock.h" -#include "gtest/gtest.h" +#include +#include #include #include // btwxt -#include -#include -#include +#include "btwxt.h" +#include "error.h" +#include "griddeddata.h" +#include "fixtures.hpp" using namespace Btwxt; @@ -33,11 +34,11 @@ double fn1(double x0, double x1, double x2, double x3) { return (x0 + x1 + x2 + class LargeFixture : public testing::Test { protected: RegularGridInterpolator test_rgi; - GriddedData test_gridded_data; std::vector target; + BtwxtContextCourierr logger; // constructed only for std::cout LargeFixture() { - std::size_t ndims = 4; + const std::size_t ndims = 4; std::vector> grid(ndims); std::size_t axis_len = 10; // could easily change to vector of lengths @@ -68,12 +69,13 @@ class LargeFixture : public testing::Test { // target = {2.5, 3.5, 1.4, 4.0}; target = {2.2, 3.3, 1.4, 4.1}; // target = {0.0, 0.0, 0.0, 0.0}; - test_gridded_data = GriddedData(grid, values); + ////test_gridded_data = GriddedData(grid, values); // test_gridded_data.set_axis_interp_method(0, Method::CUBIC); // test_gridded_data.set_axis_interp_method(1, Method::CUBIC); // test_gridded_data.set_axis_interp_method(2, Method::CUBIC); // test_gridded_data.set_axis_interp_method(3, Method::CUBIC); - test_rgi = RegularGridInterpolator(test_gridded_data); + auto courier = std::make_shared(); + test_rgi = RegularGridInterpolator(grid, values, courier); } }; @@ -87,68 +89,45 @@ TEST_F(LargeFixture, construct) { TEST_F(LargeFixture, calculate) { test_rgi.set_new_target(target); - Btwxt::LOG_LEVEL = 0; std::vector result = test_rgi.get_values_at_target(); EXPECT_NEAR(result[0], fn0(target[0], target[1], target[2], target[3]), 0.02); EXPECT_DOUBLE_EQ(result[1], fn1(target[0], target[1], target[2], target[3])); - Btwxt::LOG_LEVEL = 1; } TEST_F(LargeFixture, verify_linear) { // no matter what we do, result[1] should always be 11! std::vector result; - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::LINEAR, Method::LINEAR, Method::LINEAR, Method::LINEAR)); - test_rgi = RegularGridInterpolator(test_gridded_data); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::CUBIC, Method::LINEAR, Method::LINEAR, Method::LINEAR)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(3, Method::CUBIC); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::CUBIC, Method::LINEAR, Method::LINEAR, Method::CUBIC)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(3, Method::CUBIC); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(0, Method::LINEAR); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::LINEAR, Method::LINEAR, Method::LINEAR, Method::CUBIC)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::LINEAR); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(2, Method::CUBIC); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::LINEAR, Method::LINEAR, Method::CUBIC, Method::CUBIC)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(2, Method::CUBIC); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(0, Method::CUBIC); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::CUBIC, Method::LINEAR, Method::CUBIC, Method::CUBIC)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(0, Method::CUBIC); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); - test_gridded_data.set_axis_interp_method(1, Method::CUBIC); - EXPECT_THAT(test_gridded_data.get_interp_methods(), - testing::ElementsAre(Method::CUBIC, Method::CUBIC, Method::CUBIC, Method::CUBIC)); - test_rgi = RegularGridInterpolator(test_gridded_data); + test_rgi.set_axis_interp_method(1, Method::CUBIC); test_rgi.set_new_target(target); result = test_rgi.get_values_at_target(); EXPECT_DOUBLE_EQ(result[1], 11); @@ -163,8 +142,7 @@ TEST_F(LargeFixture, timer) { // Get ending timepoint auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); - showMessage(MsgLevel::MSG_INFO, - stringify("Time taken by interpolation: ", duration.count(), " microseconds")); + logger.info(stringify("Time taken by interpolation: ", duration.count(), " microseconds")); // time running the functions straight start = std::chrono::high_resolution_clock::now(); @@ -173,8 +151,7 @@ TEST_F(LargeFixture, timer) { // Get ending timepoint stop = std::chrono::high_resolution_clock::now(); auto nano_duration = std::chrono::duration_cast(stop - start); - showMessage(MsgLevel::MSG_INFO, - stringify("Time taken by direct functions: ", nano_duration.count(), " nanoseconds")); + logger.info(stringify("Time taken by direct functions: ", nano_duration.count(), " nanoseconds")); } TEST_F(LargeFixture, multi_timer) { @@ -184,7 +161,6 @@ TEST_F(LargeFixture, multi_timer) { {4.2, 2.7, 1.3, 4.4}, {2.1, 2.9, 1.8, 1.9}}; for (std::size_t count = 0; count < 10; count++) { - Btwxt::LOG_LEVEL = 2; // Get starting timepoint auto start = std::chrono::high_resolution_clock::now(); for (auto target : set_of_targets) { @@ -193,8 +169,6 @@ TEST_F(LargeFixture, multi_timer) { // Get ending timepoint auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); - Btwxt::LOG_LEVEL = 1; - showMessage(MsgLevel::MSG_INFO, - stringify("Time taken by ten interpolations: ", duration.count(), " microseconds")); + logger.info(stringify("Time taken by ten interpolations: ", duration.count(), " microseconds")); } } diff --git a/test/main_test.cpp b/test/main_test.cpp index 2b693b2..1233353 100644 --- a/test/main_test.cpp +++ b/test/main_test.cpp @@ -10,34 +10,7 @@ using namespace Btwxt; -// use custom callback function b/c we don't want to exit tests on error. -void my_callback(MsgLevel messageType, std::string message, void *contextPtr); - -void my_callback(const MsgLevel messageType, const std::string message, - void * // contextPtr -) { - if (messageType == MsgLevel::MSG_ERR) { - std::cout << " ERROR: " << message << std::endl; - throw std::invalid_argument(stringify(" ERROR: ", message)); - } else { - if (static_cast(messageType) >= Btwxt::LOG_LEVEL) { - std::string prefix(" DEBUG: "); - if (messageType == MsgLevel::MSG_WARN) { - prefix = " WARNING: "; - } else if (messageType == MsgLevel::MSG_INFO) { - prefix = " NOTE: "; - } - std::cout << prefix << message << std::endl; - } - } -} - int main(int argc, char **argv) { - Btwxt::LOG_LEVEL = 1; ::testing::InitGoogleTest(&argc, argv); - - int *my_context_ptr = nullptr; - setMessageCallback(my_callback, my_context_ptr); - return RUN_ALL_TESTS(); } diff --git a/test/math_test.cpp b/test/math_test.cpp index 5f85542..435c000 100644 --- a/test/math_test.cpp +++ b/test/math_test.cpp @@ -9,16 +9,16 @@ #include "gtest/gtest.h" // btwxt -#include -#include -#include +#include "btwxt.h" +#include "error.h" +#include "griddeddata.h" +#include "fixtures.hpp" using namespace Btwxt; // Unit tests on free functions, generally mathematically oriented. TEST(GriddedData, free_check_sorted) { - Btwxt::LOG_LEVEL = 0; std::vector, bool>> my_vecs = {{{1, 3, 5, 7, 9}, true}, {{1, 3, 5, 17, 9}, false}, {{9, 7, 5, 3, 1}, false}, @@ -29,14 +29,14 @@ TEST(GriddedData, free_check_sorted) { is_sorted = Btwxt::free_check_sorted(pair.first); EXPECT_EQ(is_sorted, pair.second); } - Btwxt::LOG_LEVEL = 1; } TEST(GriddedData, locate_coords) { + auto courier = std::make_shared(); std::vector> grid = {{1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6, 7}}; std::vector value1(5 * 7, 0.0); std::vector> values = {value1}; - GriddedData test_gridded_data1(grid, values); + GriddedData test_gridded_data1(grid, values, courier); std::vector coords = {2, 3}; std::vector dimension_lengths = {5, 7}; @@ -48,22 +48,24 @@ TEST(GriddedData, locate_coords) { std::vector value2(5 * 7 * 3, 0.0); values = {value2}; - GriddedData test_gridded_data2(grid, values); + GriddedData test_gridded_data2(grid, values, courier); index = test_gridded_data2.get_value_index(coords); EXPECT_EQ(index, 53u); } TEST(GridPoint, set_dim_floor) { - GridAxis axis({1, 3, 5, 7, 9}); + auto courier = std::make_shared(); + + GridAxis axis({1, 3, 5, 7, 9}, courier); axis.set_extrap_limits({0, 11}); std::vector target = {5.3}; - GriddedData test_gridded_data = GriddedData({axis}); + GriddedData test_gridded_data = GriddedData({axis}, courier); - GridPoint grid_point(test_gridded_data, target); + GridPoint grid_point(test_gridded_data, target, courier); grid_point.set_floor(); diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 72aa3d6..a4d111a 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -13,4 +13,6 @@ if (${PROJECT_NAME}_BUILD_TESTING AND NOT TARGET gtest) mark_as_advanced(BUILD_GTEST BUILD_GMOCK INSTALL_GTEST) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/googletest) -endif() \ No newline at end of file +endif() + +add_subdirectory(courierr) \ No newline at end of file diff --git a/vendor/courierr b/vendor/courierr new file mode 160000 index 0000000..794af6c --- /dev/null +++ b/vendor/courierr @@ -0,0 +1 @@ +Subproject commit 794af6c7e465e2a49399d92f5c749c82b5ba5e75