Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymatlib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Rahil Doshi
pymatlib
Commits
a42ceecb
Commit
a42ceecb
authored
3 months ago
by
Rahil Doshi
Browse files
Options
Downloads
Patches
Plain Diff
Update tests to check for accuracy, performance of C++ interpolation methods
parent
7079da98
Branches
Branches containing commit
No related tags found
No related merge requests found
Pipeline
#74865
passed
3 months ago
Stage: test
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/pymatlib/core/cpp/test_interpolation.cpp
+199
-512
199 additions, 512 deletions
src/pymatlib/core/cpp/test_interpolation.cpp
with
199 additions
and
512 deletions
src/pymatlib/core/cpp/test_interpolation.cpp
+
199
−
512
View file @
a42ceecb
#include
"interpolate_binary_search_cpp.h"
#include
"interpolate_binary_search_cpp.h"
#include
"interpolate_double_lookup_cpp.h"
#include
"interpolate_double_lookup_cpp.h"
#include
<array>
#include
<array>
#include
<vector>
#include
<random>
#include
<random>
#include
<chrono>
#include
<chrono>
#include
<iomanip>
#include
<iomanip>
#include
<cassert>
#include
<cassert>
#include
<iostream>
#include
<iostream>
#include
<numeric>
#include
"TestArrayContainer.hpp"
#include
"TestArrayContainer.hpp"
/*
void run_comprehensive_tests1() {
std::cout << "\nRunning comprehensive interpolation tests...\n" << std::endl;
// Test Case 1: Basic ascending arrays
{
std::vector<double> T = {100.0, 200.0, 300.0, 400.0, 500.0};
std::vector<double> E = {1.0, 2.0, 3.0, 4.0, 5.0};
// Test middle interpolation
double result = interpolate_binary_search_cpp(T, 2.5, E);
assert(std::abs(result - 250.0) < 1e-8);
std::cout << "Basic ascending test passed" << std::endl;
}
// Test Case 2: Descending arrays
{
std::vector<double> T = {500.0, 400.0, 300.0, 200.0, 100.0};
std::vector<double> E = {5.0, 4.0, 3.0, 2.0, 1.0};
double result = interpolate_binary_search_cpp(T, 2.5, E);
assert(std::abs(result - 250.0) < 1e-8);
std::cout << "Descending array test passed" << std::endl;
}
// Test Case 3: Edge cases
{
std::vector<double> T = {100.0, 200.0, 300.0};
std::vector<double> E = {1.0, 2.0, 3.0};
// Test below minimum
double result = interpolate_binary_search_cpp(T, 0.5, E);
assert(std::abs(result - 100.0) < 1e-8);
// Test above maximum
result = interpolate_binary_search_cpp(T, 3.5, E);
assert(std::abs(result - 300.0) < 1e-8);
std::cout << "Edge cases test passed" << std::endl;
}
// Test Case 4: Double lookup specific tests
{
std::vector<double> T_eq = {100.0, 200.0, 300.0, 400.0, 500.0};
std::vector<double> E_neq = {1.0, 2.1, 3.4, 4.2, 5.0};
std::vector<double> E_eq = {1.0, 2.0, 3.0, 4.0, 5.0};
double inv_delta_E_eq = 1.0;
std::vector<double> idx_map = {0, 0, 1, 2, 3};
double result = interpolate_double_lookup_cpp(2.5, T_eq, E_neq, E_eq,
inv_delta_E_eq, idx_map);
std::cout << result << std::endl;
// assert(std::abs(result - 230.769) < 1e-6);
std::cout << "Double lookup basic test passed" << std::endl;
}
// Test Case 5: Performance comparison
{
const size_t size = 1000000;
std::vector<double> T(size);
std::vector<double> E(size);
std::vector<double> E_eq(size);
std::vector<double> idx_map(size);
// Initialize arrays
for(size_t i = 0; i < size; ++i) {
T[i] = static_cast<double>(i);
E[i] = static_cast<double>(i) * 1.5;
E_eq[i] = static_cast<double>(i);
idx_map[i] = i;
}
double inv_delta_E_eq = 1.0;
// Time binary search
auto start = std::chrono::high_resolution_clock::now();
double result1 = interpolate_binary_search_cpp(T, 500000.5, E);
std::cout << result1 << std::endl;
auto end = std::chrono::high_resolution_clock::now();
auto binary_duration = std::chrono::duration_cast<std::chrono::nanoseconds>
(end - start).count();
// Time double lookup
start = std::chrono::high_resolution_clock::now();
double result2 = interpolate_double_lookup_cpp(500000.5, T, E, E_eq,
inv_delta_E_eq, idx_map);
std::cout << result2 << std::endl;
end = std::chrono::high_resolution_clock::now();
auto double_duration = std::chrono::duration_cast<std::chrono::nanoseconds>
(end - start).count();
std::cout << "\nPerformance test results:" << std::endl;
std::cout << "Binary search: " << binary_duration << " ns" << std::endl;
std::cout << "Double lookup: " << double_duration << " ns" << std::endl;
}
// Test Case 6: Error handling
{
try {
std::vector<double> T = {100.0};
std::vector<double> E = {1.0};
interpolate_binary_search_cpp(T, 1.5, E);
assert(false && "Should throw exception for size < 2");
} catch (const std::runtime_error&) {
std::cout << "Size validation test passed" << std::endl;
}
}
// Test Case 7: Non-uniform spacing
{
std::vector<double> T = {100.0, 150.0, 300.0, 320.0, 500.0};
std::vector<double> E = {1.0, 1.5, 3.0, 3.2, 5.0};
double result = interpolate_binary_search_cpp(T, 2.0, E);
std::cout << "Non-uniform spacing test passed" << std::endl;
}
}
*/
/*
void run_comprehensive_tests2() {
std::cout << "\nRunning comprehensive interpolation tests...\n" << std::endl;
// Test Case 1: Basic tests with both std::vector and std::array
{
// Vector version
std::vector<double> T_vec = {100.0, 200.0, 300.0, 400.0};
std::vector<double> E_vec = {1.0, 2.0, 3.0, 4.0};
double result_vec = interpolate_binary_search_cpp(T_vec, 2.5, E_vec);
assert(std::abs(result_vec - 250.0) < 1e-6);
// Array version
std::array<double, 4> T_arr = {100.0, 200.0, 300.0, 400.0};
std::array<double, 4> E_arr = {1.0, 2.0, 3.0, 4.0};
double result_arr = interpolate_binary_search_cpp(T_arr, 2.5, E_arr);
assert(std::abs(result_arr - 250.0) < 1e-6);
std::cout << "Basic vector/array tests passed" << std::endl;
}
// Test Case 2: Descending order with both containers
{
// Vector version
std::vector<double> T_vec = {400.0, 300.0, 200.0, 100.0};
std::vector<double> E_vec = {4.0, 3.0, 2.0, 1.0};
double result_vec = interpolate_binary_search_cpp(T_vec, 2.5, E_vec);
// Array version
std::array<double, 4> T_arr = {400.0, 300.0, 200.0, 100.0};
std::array<double, 4> E_arr = {4.0, 3.0, 2.0, 1.0};
double result_arr = interpolate_binary_search_cpp(T_arr, 2.5, E_arr);
assert(std::abs(result_vec - result_arr) < 1e-8);
std::cout << "Descending order vector/array tests passed" << std::endl;
}
// Test Case 3: Edge cases for both containers
{
// Vector version
std::vector<double> T_vec = {3273.15, 3263.15, 3253.15, 3243.15};
std::vector<double> E_vec = {1.71e10, 1.70e10, 1.69e10, 1.68e10};
double result_vec_min = interpolate_binary_search_cpp(T_vec, 1.67e10, E_vec);
double result_vec_max = interpolate_binary_search_cpp(T_vec, 1.72e10, E_vec);
// Array version
std::array<double, 4> T_arr = {3273.15, 3263.15, 3253.15, 3243.15};
std::array<double, 4> E_arr = {1.71e10, 1.70e10, 1.69e10, 1.68e10};
double result_arr_min = interpolate_binary_search_cpp(T_arr, 1.67e10, E_arr);
double result_arr_max = interpolate_binary_search_cpp(T_arr, 1.72e10, E_arr);
assert(std::abs(result_vec_min - 3243.15) < 1e-6);
assert(std::abs(result_arr_min - 3243.15) < 1e-6);
assert(std::abs(result_vec_max - 3273.15) < 1e-6);
assert(std::abs(result_arr_max - 3273.15) < 1e-6);
std::cout << "Edge cases vector/array tests passed" << std::endl;
}
// Test Case 4: Double lookup with both containers
{
// Vector version
std::vector<double> T_vec = {100.0, 200.0, 300.0, 400.0};
std::vector<double> E_neq_vec = {1.0, 2.1, 3.4, 4.2};
std::vector<double> E_eq_vec = {1.0, 2.0, 3.0, 4.0};
std::vector<double> idx_map_vec = {0, 0, 1, 2};
// Array version
std::array<double, 4> T_arr = {100.0, 200.0, 300.0, 400.0};
std::array<double, 4> E_neq_arr = {1.0, 2.1, 3.4, 4.2};
std::array<double, 4> E_eq_arr = {1.0, 2.0, 3.0, 4.0};
std::array<double, 4> idx_map_arr = {0, 0, 1, 2};
double inv_delta_E_eq = 1.0;
double result_vec = interpolate_double_lookup_cpp(2.5, T_vec, E_neq_vec,
E_eq_vec, inv_delta_E_eq,
idx_map_vec);
double result_arr = interpolate_double_lookup_cpp(2.5, T_arr, E_neq_arr,
E_eq_arr, inv_delta_E_eq,
idx_map_arr);
assert(std::abs(result_vec - result_arr) < 1e-6);
std::cout << "Double lookup vector/array tests passed" << std::endl;
}
// Test Case 5: Error handling for both containers
{
try {
std::vector<double> T_vec = {100.0};
std::vector<double> E_vec = {1.0};
interpolate_binary_search_cpp(T_vec, 1.5, E_vec);
assert(false && "Should throw exception for vector size < 2");
} catch (const std::runtime_error&) {
std::cout << "Vector size validation passed" << std::endl;
}
try {
std::array<double, 1> T_arr = {100.0};
std::array<double, 1> E_arr = {1.0};
interpolate_binary_search_cpp(T_arr, 1.5, E_arr);
assert(false && "Should throw exception for array size < 2");
} catch (const std::runtime_error&) {
std::cout << "Array size validation passed" << std::endl;
}
}
// Test Case 6: Performance comparison between vector and array
{
const size_t size = 1000000;
std::vector<double> T_vec(size);
std::vector<double> E_vec(size);
std::array<double, 1000> T_arr;
std::array<double, 1000> E_arr;
// Initialize containers
for(size_t i = 0; i < size; ++i) {
T_vec[i] = static_cast<double>(i);
E_vec[i] = static_cast<double>(i) * 1.5;
}
for(size_t i = 0; i < 1000; ++i) {
T_arr[i] = static_cast<double>(i);
E_arr[i] = static_cast<double>(i) * 1.5;
}
// Time vector version
auto start = std::chrono::high_resolution_clock::now();
double result_vec = interpolate_binary_search_cpp(T_vec, 500000.5, E_vec);
auto vector_duration = std::chrono::duration_cast<std::chrono::nanoseconds>
(std::chrono::high_resolution_clock::now() - start).count();
// Time array version
start = std::chrono::high_resolution_clock::now();
double result_arr = interpolate_binary_search_cpp(T_arr, 500.5, E_arr);
auto array_duration = std::chrono::duration_cast<std::chrono::nanoseconds>
(std::chrono::high_resolution_clock::now() - start).count();
std::cout << "\nPerformance comparison:" << std::endl;
std::cout << "Vector duration: " << vector_duration << " ns" << std::endl;
std::cout << "Array duration: " << array_duration << " ns" << std::endl;
}
}
*/
// Helper function to compare floating point numbers
// Helper function to compare floating point numbers
bool
is_equal
(
double
a
,
double
b
,
double
tolerance
=
1e-10
)
{
bool
is_equal
(
double
a
,
double
b
,
double
tolerance
=
1e-10
)
{
return
std
::
abs
(
a
-
b
)
<
tolerance
;
return
std
::
abs
(
a
-
b
)
<
tolerance
;
}
}
void
test_basic_functionality1
()
{
// Use realistic temperature-enthalpy values from search results
const
std
::
vector
<
double
>
T_vec
=
{
2400.0
,
2500.0
,
2600.0
,
2700.0
};
const
std
::
vector
<
double
>
E_vec
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// Test point should be within the data range
const
double
test_E
=
1.695e10
;
const
double
expected_T
=
2550.0
;
// Midpoint interpolation
// Add tolerance appropriate for temperature values
const
double
tolerance
=
1e-6
;
DoubleLookupTests
tests
;
double
result_vec
=
interpolate_binary_search_cpp
(
test_E
,
tests
);
assert
(
std
::
abs
(
result_vec
-
expected_T
)
<
tolerance
);
}
void
test_basic_functionality
()
{
void
test_basic_functionality
()
{
std
::
cout
<<
"
\n
Testing basic functionality..."
<<
std
::
endl
;
std
::
cout
<<
"
\n
Testing basic functionality..."
<<
std
::
endl
;
// Setup test data with precise values
// Ascending order vectors
const
std
::
vector
<
double
>
T_vec
=
{
3243.15
,
3253.15
,
3263.15
,
3273.15
};
const
std
::
vector
<
double
>
E_vec
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// Ascending order arrays
const
std
::
array
<
double
,
4
>
T_arr
=
{
3243.15
,
3253.15
,
3263.15
,
3273.15
};
const
std
::
array
<
double
,
4
>
E_arr
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// Test middle point interpolation
// Test middle point interpolation
const
double
test_E
=
1.695e10
;
const
double
test_E
=
16950000000.0
;
const
double
expected_T
=
3258.15
;
// Binary Search Tests
// Binary Search Tests
{
{
DoubleLookup
Tests
tests
;
BinarySearch
Tests
tests
;
double
result
_arr
=
interpolate
_binary_search_cpp
(
test_E
,
tests
);
double
result
=
tests
.
interpolate
BS
(
test_E
);
assert
(
is_equal
(
result_arr
,
expected_T
));
// Expected value based on T_bs array
double
expected_T
=
3253.15
;
// Verify vector and array results match
assert
(
is_equal
(
result
,
expected_T
));
assert
(
is_equal
(
result_vec
,
result_arr
))
;
std
::
cout
<<
"Basic binary search interpolation passed"
<<
std
::
endl
;
}
}
// Double Lookup Tests
// Double Lookup Tests
{
{
// Setup double lookup specific data
// std::vector<double> E_eq_vec = {1.68e10, 1.69e10, 1.70e10, 1.71e10};
std
::
array
<
double
,
4
>
E_eq_arr
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// std::vector<double> idx_map_vec = {0, 1, 2, 3};
std
::
array
<
double
,
4
>
idx_map_arr
=
{
0
,
1
,
2
,
3
};
const
double
inv_delta_E_eq
=
1.0
/
(
1e9
);
/*double result_vec = interpolate_double_lookup_cpp(
test_E, T_vec, E_vec, E_eq_vec, inv_delta_E_eq, idx_map_vec);
assert(is_equal(result_vec, expected_T));*/
DoubleLookupTests
tests
;
DoubleLookupTests
tests
;
double
result_arr
=
tests
.
interpolateDL
(
test_E
);
double
result
=
tests
.
interpolateDL
(
test_E
);
/*double result_arr = interpolate_double_lookup_cpp(
// Expected value based on T_eq array
test_E, T_arr, E_arr, E_eq_arr, inv_delta_E_eq, idx_map_arr);*/
double
expected_T
=
3258.15
;
assert
(
is_equal
(
result_arr
,
expected_T
));
assert
(
is_equal
(
result
,
expected_T
));
std
::
cout
<<
"Basic double lookup interpolation passed"
<<
std
::
endl
;
// Verify vector and array results match
// assert(is_equal(result_vec, result_arr));
}
}
}
}
void
test_edge_cases_and_errors
()
{
void
test_edge_cases_and_errors
()
{
std
::
cout
<<
"Testing edge cases and error handling..."
<<
std
::
endl
;
std
::
cout
<<
"
\n
Testing edge cases and error handling..."
<<
std
::
endl
;
// Test data for vectors
const
std
::
vector
<
double
>
T_vec
=
{
3243.15
,
3253.15
,
3263.15
,
3273.15
};
const
std
::
vector
<
double
>
E_vec
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// Test data for arrays
// Test boundary values for binary search
const
std
::
array
<
double
,
4
>
T_arr
=
{
3243.15
,
3253.15
,
3263.15
,
3273.15
};
const
std
::
array
<
double
,
4
>
E_arr
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
// Test boundary values
{
{
// Vector tests
BinarySearchTests
tests
;
/*double result_vec_min = interpolate_binary_search_cpp(T_vec, 1.67e10, E_vec);
double result_vec_max = interpolate_binary_search_cpp(T_vec, 1.72e10, E_vec);
assert(is_equal(result_vec_min, 3243.15));
assert(is_equal(result_vec_max, 3273.15));*/
// Array tests
// Test below minimum
DoubleLookupTests
tests
;
double
result_min
=
tests
.
interpolateBS
(
16750000000.0
);
double
result_arr_min
=
interpolate_binary_search_cpp
(
1.67e10
,
tests
);
assert
(
is_equal
(
result_min
,
3243.15
));
double
result_arr_max
=
interpolate_binary_search_cpp
(
1.72e10
,
tests
);
assert
(
is_equal
(
result_arr_min
,
3243.15
));
assert
(
is_equal
(
result_arr_max
,
3273.15
));
}
// Error cases
// Test above maximum
/*{
double
result_max
=
tests
.
interpolateBS
(
17150000000.0
);
// Test vector size mismatch
assert
(
is_equal
(
result_max
,
3278.15
));
std::vector<double> wrong_size_vec = {1.0};
bool caught_vector_error = false;
try {
interpolate_binary_search_cpp(T_vec, 1.70e10, wrong_size_vec);
} catch (const std::runtime_error&) {
caught_vector_error = true;
}
assert(caught_vector_error);
// For arrays, test with non-monotonic values
std::array<double, 4> non_monotonic_arr = {1.71e10, 1.69e10, 1.70e10, 1.68e10}; // Values not in order
bool caught_array_error = false;
try {
interpolate_binary_search_cpp(T_arr, 1.70e10, non_monotonic_arr);
} catch (const std::runtime_error&) {
caught_array_error = true;
}
assert(caught_array_error);
// Compile-time size check for arrays
std
::
cout
<<
"Edge cases for binary search passed"
<<
std
::
endl
;
static_assert(T_arr.size() >= 2, "Array size must be at least 2");
}
static_assert(E_arr.size() >= 2, "Array size must be at least 2");
}*/
// Double Lookup edge cases
// Double Lookup edge cases
{
{
std
::
vector
<
double
>
E_eq_vec
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
DoubleLookupTests
tests
;
std
::
vector
<
double
>
idx_map_vec
=
{
0
,
1
,
2
,
3
};
std
::
array
<
double
,
4
>
E_eq_arr
=
{
1.68e10
,
1.69e10
,
1.70e10
,
1.71e10
};
std
::
array
<
double
,
4
>
idx_map_arr
=
{
0
,
1
,
2
,
3
};
const
double
inv_delta_E_eq
=
1.0
/
(
1e9
);
// Test below minimum
double
result_min
=
tests
.
interpolateDL
(
16750000000.0
);
assert
(
is_equal
(
result_min
,
3243.15
));
// Test above maximum
double
result_max
=
tests
.
interpolateDL
(
17150000000.0
);
assert
(
is_equal
(
result_max
,
3273.15
));
// Array tests
std
::
cout
<<
"Edge cases for double lookup passed"
<<
std
::
endl
;
DoubleLookupTests
tests
;
double
result_arr_min
=
tests
.
interpolateDL
(
1.67e10
);
assert
(
is_equal
(
result_arr_min
,
3243.15
));
}
}
}
}
void
test_interpolation_accuracy
()
{
void
test_interpolation_accuracy
()
{
std
::
cout
<<
"
\n
Testing interpolation accuracy..."
<<
std
::
endl
;
std
::
cout
<<
"
\n
Testing interpolation accuracy..."
<<
std
::
endl
;
// Test data with precise values
// Test data with precise values
struct
TestCase
{
struct
TestCase
{
double
input_E
;
double
input_E
;
double
expected_T
;
double
expected_T_bs
;
double
expected_T_dl
;
double
tolerance
;
double
tolerance
;
std
::
string
description
;
std
::
string
description
;
};
};
const
std
::
vector
<
TestCase
>
test_cases
=
{
const
std
::
vector
<
TestCase
>
test_cases
=
{
// For E=1.705e10 (between 1.70e10 and 1.71e10)
// Test cases with expected interpolated values for both methods
{
1.705e10
,
3268.15
,
1e-10
,
"Mid-point interpolation"
},
{
16850000000.0
,
3245.65
,
3248.15
,
1e-10
,
"Quarter-point interpolation"
},
// For E=1.695e10 (between 1.69e10 and 1.70e10)
{
16950000000.0
,
3253.15
,
3258.15
,
1e-10
,
"Mid-point interpolation"
},
{
1.695e10
,
3258.15
,
1e-10
,
"Quarter-point interpolation"
},
{
17050000000.0
,
3268.15
,
3268.15
,
1e-10
,
"Three-quarter-point interpolation"
},
// For E=1.685e10 (between 1.68e10 and 1.69e10)
{
1.685e10
,
3248.15
,
1e-10
,
"Eighth-point interpolation"
},
// Near exact points
// Near exact points
{
1.70e10
,
3263.15
,
1e-8
,
"Near-exact point"
},
{
16900000000.0
,
3248.15
,
3253.15
,
1e-8
,
"Near-exact point"
},
{
1.69e10
,
3253.15
,
1e-8
,
"Near-exact point"
}
{
17000000000.0
,
3258.15
,
3263.15
,
1e-8
,
"Near-exact point"
}
};
// Setup arrays with high precision values
// For std::vector
const
std
::
vector
<
double
>
T_vec
=
{
3243.15000000
,
3253.15000000
,
3263.15000000
,
3273.15000000
};
const
std
::
vector
<
double
>
E_vec
=
{
1.68000000e10
,
1.69000000e10
,
1.70000000e10
,
1.71000000e10
};
// For std::array
const
std
::
array
<
double
,
4
>
T_arr
=
{
3243.15000000
,
3253.15000000
,
3263.15000000
,
3273.15000000
};
const
std
::
array
<
double
,
4
>
E_arr
=
{
1.68000000e10
,
1.69000000e10
,
1.70000000e10
,
1.71000000e10
};
};
// Setup for double lookup
std
::
vector
<
double
>
E_eq_vec
=
{
1.68000000e10
,
1.69000000e10
,
1.70000000e10
,
1.71000000e10
};
std
::
array
<
double
,
4
>
E_eq_arr
=
{
1.68000000e10
,
1.69000000e10
,
1.70000000e10
,
1.71000000e10
};
std
::
vector
<
double
>
idx_map_vec
=
{
0
,
1
,
2
,
3
};
std
::
array
<
double
,
4
>
idx_map_arr
=
{
0
,
1
,
2
,
3
};
const
double
inv_delta_E_eq
=
1.0
/
(
1e9
);
DoubleLookupTests
tests
;
for
(
const
auto
&
test
:
test_cases
)
{
for
(
const
auto
&
test
:
test_cases
)
{
// Binary Search Tests
// Binary Search Tests
double
result_bin_arr
=
interpolate_binary_search_cpp
(
test
.
input_E
,
tests
);
BinarySearchTests
bs_tests
;
double
result_bs
=
bs_tests
.
interpolateBS
(
test
.
input_E
);
assert
(
is_equal
(
result_bin_vec
,
test
.
expected_T
,
test
.
tolerance
));
assert
(
is_equal
(
result_bs
,
test
.
expected_T_bs
,
test
.
tolerance
));
assert
(
is_equal
(
result_bin_arr
,
test
.
expected_T
,
test
.
tolerance
));
assert
(
is_equal
(
result_bin_vec
,
result_bin_arr
,
test
.
tolerance
));
// Double Lookup Tests
// Double Lookup Tests
double
result_dl_arr
=
tests
.
interpolateDL
(
test
.
input_E
);
DoubleLookupTests
dl_tests
;
double
result_dl
=
dl_tests
.
interpolateDL
(
test
.
input_E
);
assert
(
is_equal
(
result_dl
,
test
.
expected_T_dl
,
test
.
tolerance
));
// assert(is_equal(result_dl_vec, test.expected_T, test.tolerance));
std
::
cout
<<
"Accuracy test passed for "
<<
test
.
description
<<
std
::
endl
;
assert
(
is_equal
(
result_dl_arr
,
test
.
expected_T
,
test
.
tolerance
));
// assert(is_equal(result_dl_vec, result_dl_arr, test.tolerance));
}
}
}
}
void
test_consistency
()
{
std
::
cout
<<
"
\n
Testing interpolation consistency..."
<<
std
::
endl
;
void
test_performance
()
{
// Test that small changes in input produce correspondingly small changes in output
std
::
cout
<<
"
\n
Testing performance..."
<<
std
::
endl
;
BinarySearchTests
bs_tests
;
DoubleLookupTests
dl_tests
;
// Test with different sizes
const
double
base_E
=
16900000000.0
;
const
std
::
vector
<
size_t
>
test_sizes
=
{
100
,
1000
,
10000
,
100000
};
const
double
delta_E
=
100
0000.0
;
// Small change in energy
for
(
size_t
size
:
test_sizes
)
{
double
base_T_bs
=
bs_tests
.
interpolateBS
(
base_E
);
std
::
cout
<<
"
\n
Testing with array size: "
<<
size
<<
std
::
endl
;
double
delta_T_bs
=
bs_tests
.
interpolateBS
(
base_E
+
delta_E
)
-
base_T_bs
;
// Generate test data
double
base_T_dl
=
dl_tests
.
interpolateDL
(
base_E
);
std
::
vector
<
double
>
T_vec
(
size
);
double
delta_T_dl
=
dl_tests
.
interpolateDL
(
base_E
+
delta_E
)
-
base_T_dl
;
std
::
vector
<
double
>
E_vec
(
size
);
std
::
vector
<
double
>
E_eq_vec
(
size
);
std
::
vector
<
double
>
idx_map_vec
(
size
);
// Fill with realistic values
// Check that changes are reasonable (not too large for small input change)
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
assert
(
std
::
abs
(
delta_T_bs
)
<
1.0
);
T_vec
[
i
]
=
3273.15
+
i
*
0.01
;
assert
(
std
::
abs
(
delta_T_dl
)
<
1.0
);
E_vec
[
i
]
=
1.71e10
+
i
*
1e6
+
1e3
*
i
/
2.
;
E_eq_vec
[
i
]
=
1.71e10
+
i
*
1e6
+
1e3
*
i
/
2.
;
idx_map_vec
[
i
]
=
i
;
}
// Create smaller arrays for comparison
std
::
cout
<<
"Consistency test passed"
<<
std
::
endl
;
constexpr
size_t
arr_size
=
1000
;
}
std
::
array
<
double
,
arr_size
>
T_arr
;
std
::
array
<
double
,
arr_size
>
E_arr
;
std
::
array
<
double
,
arr_size
>
E_eq_arr
;
std
::
array
<
double
,
arr_size
>
idx_map_arr
;
for
(
size_t
i
=
0
;
i
<
arr_size
;
++
i
)
{
T_arr
[
i
]
=
T_vec
[
i
];
E_arr
[
i
]
=
E_vec
[
i
];
E_eq_arr
[
i
]
=
E_eq_vec
[
i
];
idx_map_arr
[
i
]
=
idx_map_vec
[
i
];
}
const
double
inv_delta_E_eq
=
1.0
/
(
1e6
);
void
test_stress
()
{
const
int
num_tests
=
1000
;
std
::
cout
<<
"
\n
Performing stress testing..."
<<
std
::
endl
;
// Test points
BinarySearchTests
bs_tests
;
/*std::vector<double> test_points(num_tests);
DoubleLookupTests
dl_tests
;
for (int i = 0; i < num_tests; ++i) {
test_points[i] = 1.70e10 + (i * 1e6);
}*/
// Generate random monotonically increasing test points
// Test with extremely large values
std
::
vector
<
double
>
test_points
(
num_tests
);
double
large_E
=
1.0e20
;
test_points
[
0
]
=
1.70e10
;
// Start value
double
result_large_bs
=
bs_tests
.
interpolateBS
(
large_E
);
std
::
random_device
rd
;
double
result_large_dl
=
dl_tests
.
interpolateDL
(
large_E
);
std
::
mt19937
gen
(
rd
());
std
::
uniform_real_distribution
<
double
>
dist
(
1e5
,
1e6
);
// Random increments between 1e5 and 1e6
for
(
int
i
=
1
;
i
<
num_tests
;
++
i
)
{
// Test with extremely small values
test_points
[
i
]
=
test_points
[
i
-
1
]
+
dist
(
gen
);
double
small_E
=
1.0e-20
;
}
double
result_small_bs
=
bs_tests
.
interpolateBS
(
small_E
);
double
result_small_dl
=
dl_tests
.
interpolateDL
(
small_E
);
// Measure binary search performance
// For extreme values, we should get boundary values
{
assert
(
is_equal
(
result_large_bs
,
3278.15
));
DoubleLookupTests
tests
;
assert
(
is_equal
(
result_large_dl
,
3273.15
));
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
assert
(
is_equal
(
result_small_bs
,
3243.15
));
for
(
const
double
&
E
:
test_points
)
{
assert
(
is_equal
(
result_small_dl
,
3243.15
));
volatile
double
result
=
interpolate_binary_search_cpp
(
E
,
tests
);
}
auto
end
=
std
::
chrono
::
high_resolution_clock
::
now
();
auto
duration
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
end
-
start
).
count
();
std
::
cout
<<
"Binary Search (vector) time: "
<<
duration
<<
" ns"
<<
std
::
endl
;
}
{
std
::
cout
<<
"Stress tests passed"
<<
std
::
endl
;
DoubleLookupTests
tests
;
}
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
for
(
const
double
&
E
:
test_points
)
{
void
test_random_validation
()
{
volatile
double
result
=
interpolate_binary_search_cpp
(
E
,
tests
);
std
::
cout
<<
"
\n
Testing with random inputs..."
<<
std
::
endl
;
}
auto
end
=
std
::
chrono
::
high_resolution_clock
::
now
();
BinarySearchTests
bs_tests
;
auto
duration
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
DoubleLookupTests
dl_tests
;
end
-
start
).
count
();
std
::
cout
<<
"Binary Search (array) time: "
<<
duration
<<
" ns"
<<
std
::
endl
;
std
::
random_device
rd
;
std
::
mt19937
gen
(
rd
());
std
::
uniform_real_distribution
<
double
>
dist
(
16800000000.0
,
17100000000.0
);
const
int
num_tests
=
1000
;
for
(
int
i
=
0
;
i
<
num_tests
;
++
i
)
{
double
random_E
=
dist
(
gen
);
double
result_bs
=
bs_tests
.
interpolateBS
(
random_E
);
double
result_dl
=
dl_tests
.
interpolateDL
(
random_E
);
// Results should be within the temperature range
assert
(
result_bs
>=
3243.15
&&
result_bs
<=
3278.15
);
assert
(
result_dl
>=
3243.15
&&
result_dl
<=
3273.15
);
}
std
::
cout
<<
"Random input validation passed"
<<
std
::
endl
;
}
void
test_performance
()
{
std
::
cout
<<
"
\n
Testing performance..."
<<
std
::
endl
;
// Configuration parameters
constexpr
int
warmupSteps
=
5
;
constexpr
int
outerIterations
=
10
;
constexpr
int
numCells
=
64
*
64
*
64
;
// Setup test data
SS316L
test
;
std
::
vector
<
double
>
random_energies
(
numCells
);
// Generate random values
std
::
random_device
rd
;
std
::
mt19937
gen
(
rd
());
const
double
E_min
=
SS316L
::
E_neq
.
front
()
*
0.8
;
const
double
E_max
=
SS316L
::
E_neq
.
back
()
*
1.2
;
std
::
uniform_real_distribution
<
double
>
dist
(
E_min
,
E_max
);
// Fill random energies
for
(
auto
&
E
:
random_energies
)
{
E
=
dist
(
gen
);
}
// Warmup runs
std
::
cout
<<
"Performing warmup steps..."
<<
std
::
endl
;
for
(
int
i
=
0
;
i
<
warmupSteps
;
++
i
)
{
for
(
const
double
&
E
:
random_energies
)
{
// volatile double result = interpolate_double_lookup_cpp(E, test);
volatile
double
result
=
test
.
interpolateDL
(
E
);
}
}
for
(
int
i
=
0
;
i
<
warmupSteps
;
++
i
)
{
for
(
const
double
&
E
:
random_energies
)
{
volatile
double
result
=
test
.
interpolateBS
(
E
);
}
}
}
// Measure double lookup performance
// Performance measurement
std
::
cout
<<
"
\n
Starting performance measurement..."
<<
std
::
endl
;
std
::
vector
<
double
>
timings_binary
;
std
::
vector
<
double
>
timings_double_lookup
;
for
(
int
iter
=
0
;
iter
<
outerIterations
;
++
iter
)
{
std
::
cout
<<
"
\n
Iteration "
<<
iter
+
1
<<
"/"
<<
outerIterations
<<
std
::
endl
;
// Double Lookup timing
{
{
DoubleLookupTests
tests
;
const
auto
start1
=
std
::
chrono
::
high_resolution_clock
::
now
();
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
for
(
const
double
&
E
:
random_energies
)
{
for
(
const
double
&
E
:
test_points
)
{
volatile
double
result
=
test
.
interpolateDL
(
E
);
volatile
double
result
=
tests
.
interpolateDL
(
E
);
}
}
auto
end
=
std
::
chrono
::
high_resolution_clock
::
now
();
const
auto
end1
=
std
::
chrono
::
high_resolution_clock
::
now
();
auto
duration
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
const
auto
duration1
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
end
-
start
).
count
();
end1
-
start1
).
count
();
std
::
cout
<<
"Double Lookup (vector) time: "
<<
duration
<<
" ns"
<<
std
::
endl
;
timings_double_lookup
.
push_back
(
static_cast
<
double
>
(
duration1
));
std
::
cout
<<
"Double Lookup - Iteration time: "
<<
duration1
<<
" ns"
<<
std
::
endl
;
}
}
// Binary Search timing
{
{
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
const
auto
start2
=
std
::
chrono
::
high_resolution_clock
::
now
();
for
(
const
double
&
E
:
test_points
)
{
for
(
const
double
&
E
:
random_energies
)
{
DoubleLookupTests
tests
;
volatile
double
result
=
test
.
interpolateBS
(
E
);
volatile
double
result
=
tests
.
interpolateDL
(
E
);
}
}
auto
end
=
std
::
chrono
::
high_resolution_clock
::
now
();
const
auto
end2
=
std
::
chrono
::
high_resolution_clock
::
now
();
auto
duration
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
const
auto
duration2
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
nanoseconds
>
(
end
-
start
).
count
();
end2
-
start2
).
count
();
std
::
cout
<<
"Double Lookup (array) time: "
<<
duration
<<
" ns"
<<
std
::
endl
;
timings_binary
.
push_back
(
static_cast
<
double
>
(
duration2
));
std
::
cout
<<
"Binary Search - Iteration time: "
<<
duration2
<<
" ns"
<<
std
::
endl
;
}
}
}
}
// Calculate and print statistics
auto
calc_stats
=
[](
const
std
::
vector
<
double
>&
timings
)
{
double
sum
=
std
::
accumulate
(
timings
.
begin
(),
timings
.
end
(),
0.0
);
double
mean
=
sum
/
static_cast
<
double
>
(
timings
.
size
());
double
sq_sum
=
std
::
inner_product
(
timings
.
begin
(),
timings
.
end
(),
timings
.
begin
(),
0.0
);
double
stdev
=
std
::
sqrt
(
sq_sum
/
static_cast
<
double
>
(
timings
.
size
())
-
mean
*
mean
);
return
std
::
make_pair
(
mean
,
stdev
);
};
auto
[
binary_mean
,
binary_stdev
]
=
calc_stats
(
timings_binary
);
auto
[
lookup_mean
,
lookup_stdev
]
=
calc_stats
(
timings_double_lookup
);
std
::
cout
<<
"
\n
Performance Results ("
<<
numCells
<<
" cells, "
<<
outerIterations
<<
" iterations):"
<<
std
::
endl
;
std
::
cout
<<
"Binary Search:"
<<
std
::
endl
;
std
::
cout
<<
" Mean time: "
<<
binary_mean
<<
" ± "
<<
binary_stdev
<<
" ns"
<<
std
::
endl
;
std
::
cout
<<
" Per cell: "
<<
binary_mean
/
numCells
<<
" ns"
<<
std
::
endl
;
std
::
cout
<<
"Double Lookup:"
<<
std
::
endl
;
std
::
cout
<<
" Mean time: "
<<
lookup_mean
<<
" ± "
<<
lookup_stdev
<<
" ns"
<<
std
::
endl
;
std
::
cout
<<
" Per cell: "
<<
lookup_mean
/
numCells
<<
" ns"
<<
std
::
endl
;
}
}
...
@@ -607,6 +291,9 @@ int main() {
...
@@ -607,6 +291,9 @@ int main() {
test_basic_functionality
();
test_basic_functionality
();
test_edge_cases_and_errors
();
test_edge_cases_and_errors
();
test_interpolation_accuracy
();
test_interpolation_accuracy
();
test_consistency
();
test_stress
();
test_random_validation
();
test_performance
();
test_performance
();
std
::
cout
<<
"
\n
All tests completed successfully!"
<<
std
::
endl
;
std
::
cout
<<
"
\n
All tests completed successfully!"
<<
std
::
endl
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment