interpolation1d

done single-threded 1d interpolations; linear, rational, cubic spline, polynomial and barycentric. Still not done test functions yet. Still missing multi-core options.
This commit is contained in:
2025-09-18 20:18:27 +02:00
parent 92437e5ef1
commit 3a53b6ebf7
29 changed files with 982 additions and 15 deletions
+115
View File
@@ -0,0 +1,115 @@
#include "test_common.h"
#include "./utils/utils.h"
#include "./numerics/inverse.h"
#include "./numerics/matmul.h"
TEST_CASE(Inverse_GJ_Basic_3x3) {
using T = double;
utils::Matrix<T> A(3,3, T{0});
// Well-conditioned 3x3
A(0,0)=3; A(0,1)=0.2; A(0,2)=-0.1;
A(1,0)=0.1; A(1,1)=2.5; A(1,2)=0.3;
A(2,0)=-0.2;A(2,1)=0.4; A(2,2)=2.0;
auto Ainv = numerics::inverse<T>(A, "Gauss-Jordan");
utils::Matrix<T> I;
I.eye(3);
auto prod = numerics::matmul<T>(A, Ainv);
CHECK(prod.nearly_equal(I, (T)1e-10), "inverse(GJ): A*A^{-1} ≈ I");
}
TEST_CASE(Inverse_LU_Basic_3x3) {
using T = double;
utils::Matrix<T> A(3,3, T{0});
A(0,0)=3; A(0,1)=0.2; A(0,2)=-0.1;
A(1,0)=0.1; A(1,1)=2.5; A(1,2)=0.3;
A(2,0)=-0.2;A(2,1)=0.4; A(2,2)=2.0;
auto Ainv = numerics::inverse<T>(A, "LU");
utils::Matrix<T> I;
I.eye(3);
auto prod = numerics::matmul<T>(A, Ainv);
CHECK(prod.nearly_equal(I, (T)1e-10), "inverse(LU): A*A^{-1} ≈ I");
}
TEST_CASE(Inverse_GJ_vs_LU_Consistency) {
using T = double;
utils::Matrix<T> A(3,3, T{0});
A(0,0)=4; A(0,1)=1; A(0,2)=2;
A(1,0)=0; A(1,1)=3; A(1,2)=-1;
A(2,0)=0; A(2,1)=0; A(2,2)=2;
auto GJ = numerics::inverse<T>(A, "Gauss-Jordan");
auto LU = numerics::inverse<T>(A, "LU");
CHECK(GJ.nearly_equal(LU, (T)1e-12), "inverse: GJ and LU produce nearly the same result");
}
TEST_CASE(Inplace_Inverse_LU) {
using T = double;
utils::Matrix<T> A(3,3, T{0});
A(0,0)=3; A(0,1)=0.2; A(0,2)=-0.1;
A(1,0)=0.1; A(1,1)=2.5; A(1,2)=0.3;
A(2,0)=-0.2;A(2,1)=0.4; A(2,2)=2.0;
auto Ainv_ref = numerics::inverse<T>(A, "LU"); // out-of-place
auto A_copy = A;
numerics::inplace_inverse<T>(A_copy, "LU"); // in-place
CHECK(A_copy.nearly_equal(Ainv_ref, (T)1e-12), "inplace_inverse(LU) equals out-of-place");
}
TEST_CASE(Inplace_Inverse_GJ) {
using T = double;
utils::Matrix<T> A(2,2, T{0});
A(0,0)=2; A(0,1)=1;
A(1,0)=1; A(1,1)=3;
auto Ainv_ref = numerics::inverse<T>(A, "Gauss-Jordan");
auto A_copy = A;
numerics::inplace_inverse<T>(A_copy, "Gauss-Jordan");
CHECK(A_copy.nearly_equal(Ainv_ref, (T)1e-12), "inplace_inverse(GJ) equals out-of-place");
}
TEST_CASE(Inverse_Identity) {
using T = double;
utils::Matrix<T> I;
I.eye(3);
auto invI = numerics::inverse<T>(I, "LU");
CHECK(invI.nearly_equal(I, (T)0), "inverse(I) == I");
}
TEST_CASE(Inverse_NonSquare_Throws) {
using T = double;
utils::Matrix<T> A(2,3, T{0}); // non-square
bool threw1=false, threw2=false;
try { auto X = numerics::inverse<T>(A, "LU"); (void)X; } catch(...) { threw1=true; }
try { numerics::inplace_inverse<T>(A, "Gauss-Jordan"); } catch(...) { threw2=true; }
CHECK(threw1 && threw2, "inverse throws on non-square for both methods");
}
TEST_CASE(Inverse_Singular_Throws) {
using T = double;
utils::Matrix<T> S(3,3, T{0});
S(0,0)=1; S(0,1)=2; S(0,2)=3;
S(1,0)=1; S(1,1)=2; S(1,2)=3; // duplicate row -> singular
S(2,0)=0; S(2,1)=1; S(2,2)=0;
bool threw_gj=false, threw_lu=false;
try { auto X = numerics::inverse<T>(S, "Gauss-Jordan"); (void)X; } catch(...) { threw_gj=true; }
try { auto X = numerics::inverse<T>(S, "LU"); (void)X; } catch(...) { threw_lu=true; }
CHECK(threw_gj && threw_lu, "inverse throws on singular for both methods");
}
TEST_CASE(Inverse_Unknown_Method_Throws) {
using T = double;
utils::Matrix<T> A(2,2, T{0});
A(0,0)=1; A(1,1)=1;
bool threw=false;
try { auto X = numerics::inverse<T>(A, "Foobar"); (void)X; } catch(...) { threw=true; }
CHECK(threw, "inverse unknown method throws");
}