Skip to content

Commit d632644

Browse files
committed
Check in working test_hyp2f1 example
1 parent c3402fb commit d632644

File tree

3 files changed

+73
-29
lines changed

3 files changed

+73
-29
lines changed

tests/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
if(NOT DEFINED ENV{XSREF_TABLES_PATH})
2+
message(FATAL_ERROR "XSREF_TABLES_PATH environment variable is not set. Specify the path to xsref/tables in your environment.")
3+
endif()
4+
5+
set(XSREF_TABLES_PATH $ENV{XSREF_TABLES_PATH})
6+
17
find_package(Catch2 3 REQUIRED)
28
find_package(Arrow REQUIRED)
39
find_package(Parquet REQUIRED)
410

5-
611
add_library(xsf INTERFACE)
712
target_include_directories(xsf INTERFACE ${CMAKE_SOURCE_DIR}/include)
813

@@ -11,6 +16,7 @@ foreach(test_file ${TEST_SOURCES})
1116
get_filename_component(test_name ${test_file} NAME_WE)
1217
add_executable(${test_name}.test ${test_file})
1318
target_link_libraries(${test_name}.test PRIVATE Catch2::Catch2WithMain Arrow::arrow_shared Parquet::parquet_shared xsf)
19+
target_compile_definitions(${test_name}.test PRIVATE XSREF_TABLES_PATH="${XSREF_TABLES_PATH}")
1420
include(CTest)
1521
include(Catch)
1622
catch_discover_tests(${test_name}.test)

tests/test_hyp2f1.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,44 @@
1+
#include <complex>
2+
#include <filesystem>
3+
#include <iomanip>
4+
#include <iostream>
5+
#include <limits>
6+
#include <tuple>
7+
18
#include <catch2/catch_test_macros.hpp>
29

3-
#include <xsf/hyp2f1.h>
410
#include <xsf/fp_error_metrics.h>
11+
#include <xsf/hyp2f1.h>
512

613
#include "testing_utils.h"
714

15+
namespace fs = std::filesystem;
16+
17+
fs::path hyp2f1_tables_path{fs::path(XSREF_TABLES_PATH) / "scipy_special_tests" / "hyp2f1"};
818

9-
TEST_CASE("hyp2f1 example text", "[hyp2f1_example]") {
10-
REQUIRE ( xsf::extended_relative_error(xsf::hyp2f1(1.0, 0.9, 0.8, 0.2), 1.2848765105679898) < 1e-12 );
19+
TEST_CASE("hyp2f1 complex scipy.special cases", "[hyp2f1][complex][scipy-special]") {
20+
auto [input, output, tol] = GENERATE(
21+
xsf_test_cases<
22+
std::tuple<double, double, double, std::complex<double>>, std::tuple<std::complex<double>, bool>, double>(
23+
hyp2f1_tables_path / "In_d_d_d_cd-cd.parquet", hyp2f1_tables_path / "Out_d_d_d_cd-cd.parquet",
24+
hyp2f1_tables_path / "Err_d_d_d_cd-cd_gcc-linux-x86_64.parquet"
25+
)
26+
);
27+
auto [a, b, c, z] = input;
28+
auto [desired, fallback] = output;
29+
auto actual = xsf::hyp2f1(a, b, c, z);
30+
auto error = xsf::extended_relative_error(actual, desired);
31+
INFO(
32+
"Inputs: " << std::setprecision(std::numeric_limits<double>::max_digits10) << '\n'
33+
<< "a: " << a << '\n'
34+
<< "b: " << b << '\n'
35+
<< "c: " << c << '\n'
36+
<< "z: " << z << '\n'
37+
<< "Output: \n"
38+
<< "desired: " << desired << '\n'
39+
<< "actual: " << actual << '\n'
40+
<< "error: " << error << '\n'
41+
<< "tolerance: " << tol << '\n'
42+
);
43+
REQUIRE(error <= 2 * tol);
1144
}

tests/testing_utils.h

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <complex>
2+
#include <filesystem>
23
#include <iostream>
4+
#include <stdexcept>
35
#include <tuple>
46
#include <type_traits>
57

@@ -31,9 +33,10 @@ class TableReader {
3133
PARQUET_ASSIGN_OR_THROW(infile_, arrow::io::ReadableFile::Open(file_path));
3234
parquet::StreamReader stream{parquet::ParquetFileReader::Open(infile_)};
3335
stream_ = std::make_unique<parquet::StreamReader>(std::move(stream));
36+
file_path_ = std::move(file_path);
3437
}
3538

36-
T operator()() {
39+
T next() {
3740
T row;
3841
fill_row(row);
3942
return row;
@@ -58,59 +61,61 @@ class TableReader {
5861
V real;
5962
V imag;
6063
*stream_ >> real >> imag;
61-
element = T(real, imag);
64+
element = U(real, imag);
6265
} else {
6366
*stream_ >> element;
6467
}
6568
}
6669

6770
std::shared_ptr<arrow::io::ReadableFile> infile_;
6871
std::unique_ptr<parquet::StreamReader> stream_;
72+
std::string file_path_;
6973
};
7074

7175
template <typename T1, typename T2, typename T3>
72-
class XsfTestCaseGenerator final
73-
: public Catch::Generators::IGenerator<std::tuple<T1, T2, T3>> {
76+
class XsfTestCaseGenerator final : public Catch::Generators::IGenerator<std::tuple<T1, T2, T3>> {
7477
public:
7578
XsfTestCaseGenerator(
76-
TableReader<T1> &input_reader, TableReader<T2> &output_reader,
77-
TableReader<T3> &tol_reader
79+
std::unique_ptr<TableReader<T1>> input_reader, std::unique_ptr<TableReader<T2>> output_reader,
80+
std::unique_ptr<TableReader<T3>> tol_reader
7881
)
79-
: input_reader_(input_reader), output_reader_(output_reader), tol_reader_(tol_reader) {}
82+
: input_reader_(std::move(input_reader)), output_reader_(std::move(output_reader)),
83+
tol_reader_(std::move(tol_reader)) {
84+
if (!next()) {
85+
throw std::runtime_error("XsfTestCaseGenerator received an empty table\n");
86+
}
87+
}
8088

8189
std::tuple<T1, T2, T3> const &get() const override { return current_case_; }
8290

8391
bool next() override {
84-
if (input_reader_.eof() || output_reader_.eof() || tol_reader_.eof()) {
92+
if (input_reader_->eof() || output_reader_->eof() || tol_reader_->eof()) {
8593
return false;
8694
}
87-
88-
auto inputs = input_reader_();
89-
auto outputs = output_reader_();
90-
auto tolerance = tol_reader_();
91-
92-
current_case_ = std::make_tuple(inputs, outputs, tolerance);
95+
current_case_ = std::make_tuple(input_reader_->next(), output_reader_->next(), tol_reader_->next());
9396
return true;
9497
}
9598

9699
private:
97-
TableReader<T1> &input_reader_;
98-
TableReader<T2> &output_reader_;
99-
TableReader<T3> &tol_reader_;
100-
100+
std::unique_ptr<TableReader<T1>> input_reader_;
101+
std::unique_ptr<TableReader<T2>> output_reader_;
102+
std::unique_ptr<TableReader<T3>> tol_reader_;
101103
std::tuple<T1, T2, T3> current_case_;
102104
};
103105

104-
105106
template <typename T1, typename T2, typename T3>
106-
Catch::Generators::GeneratorWrapper<std::tuple<T1, T2, T3>>
107-
xsf_test_cases(const std::string &input_path, std::string &output_path, std::string &tol_path) {
108-
TableReader<T1> input_reader(input_path);
109-
TableReader<T2> output_reader(output_path);
110-
TableReader<T3> tol_reader(tol_path);
107+
Catch::Generators::GeneratorWrapper<std::tuple<T1, T2, T3>> xsf_test_cases(
108+
const std::filesystem::path &input_path, const std::filesystem::path &output_path,
109+
const std::filesystem::path &tol_path
110+
) {
111+
auto input_reader = std::make_unique<TableReader<T1>>(input_path.string());
112+
auto output_reader = std::make_unique<TableReader<T2>>(output_path.string());
113+
auto tol_reader = std::make_unique<TableReader<T3>>(tol_path.string());
111114

112115
return Catch::Generators::GeneratorWrapper<std::tuple<T1, T2, T3>>(
113-
Catch::Detail::make_unique<XsfTestCaseGenerator>(input_reader, output_reader, tol_reader)
116+
Catch::Detail::make_unique<XsfTestCaseGenerator<T1, T2, T3>>(
117+
std::move(input_reader), std::move(output_reader), std::move(tol_reader)
118+
)
114119
);
115120
}
116121

0 commit comments

Comments
 (0)