From 36c4b40a0f2789fd87db3be3fe9e27e0aaaba1c6 Mon Sep 17 00:00:00 2001 From: Claudio Scafuri <claudio.scafuri@elettra.eu> Date: Wed, 25 Sep 2024 13:52:10 +0200 Subject: [PATCH] debian 12, restructured --- Makefile | 82 +- .../interpolatingpolynomial.h | 0 interpolator.h => include/interpolator.h | 0 .../multipolynomial.h | 0 periodicspline.h => include/periodicspline.h | 0 spline.h => include/spline.h | 0 spltest.cpp | 138 --- interpolator.cpp => src/interpolator.cpp | 0 .../multipolynomial.cpp | 0 periodicspline.cpp => src/periodicspline.cpp | 0 spline.cpp => src/spline.cpp | 0 test_freespline.cpp | 263 ---- test_inverse.cpp | 67 -- test_multipoly.cpp | 282 ----- test_obj/test_runner.gcda | Bin 0 -> 27324 bytes test_obj/test_runner.gcno | Bin 0 -> 248972 bytes test_periodicspline.cpp | 242 ---- test_spline.cpp | 209 ---- test_src/test_runner.cpp | 1064 +++++++++++++++++ 19 files changed, 1117 insertions(+), 1230 deletions(-) rename interpolatingpolynomial.h => include/interpolatingpolynomial.h (100%) rename interpolator.h => include/interpolator.h (100%) rename multipolynomial.h => include/multipolynomial.h (100%) rename periodicspline.h => include/periodicspline.h (100%) rename spline.h => include/spline.h (100%) delete mode 100644 spltest.cpp rename interpolator.cpp => src/interpolator.cpp (100%) rename multipolynomial.cpp => src/multipolynomial.cpp (100%) rename periodicspline.cpp => src/periodicspline.cpp (100%) rename spline.cpp => src/spline.cpp (100%) delete mode 100644 test_freespline.cpp delete mode 100644 test_inverse.cpp delete mode 100644 test_multipoly.cpp create mode 100644 test_obj/test_runner.gcda create mode 100644 test_obj/test_runner.gcno delete mode 100644 test_periodicspline.cpp delete mode 100644 test_spline.cpp create mode 100644 test_src/test_runner.cpp diff --git a/Makefile b/Makefile index 9553e53..52aa79c 100644 --- a/Makefile +++ b/Makefile @@ -40,10 +40,17 @@ DEBUG = -ggdb3 RANLIB = ranlib #OPTIM = -O2 -INCLUDE = -I. +INCLUDE = -I include CXXFLAGS += -std=c++17 -fPIC -D_REENTRANT $(DEBUG) $(OPTIM) $(WARN) $(INCLUDE) CFLAGS = $(CXXFLAGS) PROJECTHOME = . + +SRC_DIR = src +OBJ_DIR = obj +TEST_DIR = test +TEST_OBJ_DIR = test_obj +TEST_RUNNER = test_runner + ############################################## # support for shared libray versioning # @@ -84,9 +91,12 @@ LOCALDESTDIRHEADERS = $(LOCALPREFIX)/include # header files to be installed for distribution INSTHEADERS = periodicspline.h spline.h multipolynomial.h interpolatingpolynomial.h interpolator.h ################################################ +SRCS = $(wildcard $(SRC_DIR)/*.cpp) +OBJS = $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS)) -OBJS = periodicspline.o spline.o multipolynomial.o interpolator.o +TEST_SRCS = test_src/test_runner.cpp +TEST_OBJS = test_obj/test_runner.o ######################################################################################## # compiler warnings @@ -97,48 +107,59 @@ WARN+= -pedantic -Wno-long-long # test with mysql due to long long variables! ####################################### #options for coverage and performance analysis -#DEBUG += -fprofile-arcs -ftest-coverage -pg -#LDFLAGS += -fprofile-arcs -ftest-coverage -pg +DEBUG += -fprofile-arcs -ftest-coverage -pg +LDFLAGS += -fprofile-arcs -ftest-coverage -pg ##################################### +# Compile source files to object files +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp + @mkdir -p $(OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + -all: lib libstatic test - -lib: $(PROJECTHOME)/lib/$(DT_SHLIB) - -libstatic: $(PROJECTHOME)/lib/$(LIBRARY) - -check: check_spline check_multipoly +# Compile test source files to object files +$(TEST_OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp + @mkdir -p $(TEST_OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ +$(TEST_OBJS): $(TEST_SRCS) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Test target: compile and link the test executable +test: $(TEST_OBJS) $(OBJS) + $(info [$(TEST_OBJS)]) + $(info [$(TEST_SRCS)]) + $(info [$(OBJS)]) + $(CXX) $(CXXFLAGS) $(TEST_OBJS) $(OBJS) -o $(TEST_RUNNER) + ./$(TEST_RUNNER) -test: test_spline test_inverse test_freespline test_multipoly test_periodicspline spltest -test_spline: test_spline.o spline.o interpolator.o +all: lib libstatic -test_inverse: test_inverse.o spline.o interpolator.o +lib: $(PROJECTHOME)/lib/$(DT_SHLIB) -test_freespline: test_freespline.o spline.o interpolator.o +libstatic: $(PROJECTHOME)/lib/$(LIBRARY) -test_periodicspline: test_periodicspline.o periodicspline.o interpolator.o +check: test + gcov test_src/test_runner.cpp + gcov src/spline.cpp + gcov src/interpolator.cpp + gcov src/multipolynomial.cpp + gcov src/peridocspline.cpp + valgrind --num-callers=20 --leak-check=yes --leak-resolution=high --leak-check=full --show-reachable=yes --log-file=test_runner.grind ./test_runner -spltest: spltest.o spline.o interpolator.o -test_multipoly: test_multipoly.o multipolynomial.o interpolator.o -check_spline: test_spline +check_exec: test_runner ./test_spline - gcov test_spline.cpp - gcov spline.cpp - gcov interpolator.cpp + gcov test_src/test_runner.cpp + gcov src/spline.cpp + gcov src/interpolator.cpp + gcov src/multipolynomial.cpp + gcov src/peridocspline.cpp valgrind --num-callers=20 --leak-check=yes --leak-resolution=high --leak-check=full --show-reachable=yes --log-file=test_spline.grind ./test_spline -check_multipoly: test_multipoly - gcov test_multipoly.cpp - gcov multipoly.cpp - gcov interpolator.cpp - valgrind --num-callers=20 --leak-check=yes --leak-resolution=high --leak-check=full --show-reachable=yes --log-file=test_multipoly.grind ./test_multipoly - $(PROJECTHOME)/lib/$(LIBRARY):$(OBJS) $(MAKEFILE) # @echo "Archiving $(LIBRARY) ... $(OBJS)" mkdir -p -m 755 $(PROJECTHOME)/lib @@ -160,7 +181,10 @@ doc: docclean: rm -rf docs doxy.log clean: - rm -f *.o core* *.gcov *.gcno *.gcda *.grind *grind.core.* *.valgrind dump* gmon.out doxygen_log.txt dump* *.csv + rm -rf $(OBJ_DIR) + rm -rf $(TEST_RUNNER) + rm -rf $(TEST_OBJS) + rm -f *.o core* *.gcov *.gcno *.gcda *.grind *grind.core.* *.valgrind dump* gmon.out doxygen_log.txt dump* *.csv perf.data rm -f test_spline test_inverse test_periodicspline test_freespline test_multipoly test_magnets test_dipole test_quadrupole test_sextupole test_kicker test_solenoid spltest rm -f *.csv rm -f doxy.log diff --git a/interpolatingpolynomial.h b/include/interpolatingpolynomial.h similarity index 100% rename from interpolatingpolynomial.h rename to include/interpolatingpolynomial.h diff --git a/interpolator.h b/include/interpolator.h similarity index 100% rename from interpolator.h rename to include/interpolator.h diff --git a/multipolynomial.h b/include/multipolynomial.h similarity index 100% rename from multipolynomial.h rename to include/multipolynomial.h diff --git a/periodicspline.h b/include/periodicspline.h similarity index 100% rename from periodicspline.h rename to include/periodicspline.h diff --git a/spline.h b/include/spline.h similarity index 100% rename from spline.h rename to include/spline.h diff --git a/spltest.cpp b/spltest.cpp deleted file mode 100644 index 3bd43a2..0000000 --- a/spltest.cpp +++ /dev/null @@ -1,138 +0,0 @@ - - -/* $Author: claudio $ - * - * $Revision: 1.1.1.1 $ - * - * $Log: spltest.cpp,v $ - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - */ - -#include <cstdlib> -#include <iostream> -#include <iomanip> -#include "spline.h" - - -using namespace std; -using namespace Interpolator; - -int main(){ - - try{ - double i_qd[]={0.0,14.8056,74.028,148.056,222.084,296.112,333.126,370.14}; - double g_qd[]={0.0,0.7745,3.9519,7.9231,11.8187,15.7069,17.5649,19.2667}; -// doubleVector iqd; -// doubleVector fieldqd; - vector<double> iqd; - vector<double> fieldqd; - - //controle printout of table - int PRECISION=16; - int WIDTH=20; - - for (unsigned int i=0;i<8;i++){ - iqd.push_back(i_qd[i]); - fieldqd.push_back(g_qd[i]); - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << iqd[i]; - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << fieldqd[i] << endl; - } - Spline* dir= new Spline(iqd,fieldqd); - Spline* inv= new Spline(fieldqd,iqd); - - - double min=0.0,max=i_qd[7]; - unsigned int steps=200; - double mincur=min; - double inccur=(max-min)/steps; - double I,g,inv_I; - cout << setw(WIDTH) << right; - cout << "I"; - - cout << setw(WIDTH) << right; - cout << "g" ; - - cout << setw(WIDTH) << right; - cout << "inv_I" ; - - - - cout << endl; - for(unsigned int i=0;i<=steps;i++){ - I=mincur+ i*inccur; - g=dir->evaluate(I); - inv_I=inv->evaluate(g); - - - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << I; - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << g; - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << inv_I; - - - if(I != 0.0) { - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << 10000.0*((I-inv_I)/I); - } - else{ - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << 0.0; - } - -// if(dir->bracket(g,I,1.0e-4,xmin,xmax)){ -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << xmin; -// -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << xmax; -// -// double I2=dir->solve(g,xmin,xmax,1.0e-8,100); -// -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << I2; -// -// } -// else{ -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << "------"; -// -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << "++++++"; -// -// cout << setprecision(PRECISION) << setw(WIDTH) << right; -// cout << "//////"; -// } - { - - - double I2=dir->inverse_evaluate(g,I); - - cout << setprecision(PRECISION) << setw(WIDTH) << right; - cout << I2; - - } - - - cout << endl; - } - - delete inv; - delete dir; - } - catch(std::invalid_argument& ex) - { - cout<<ex.what()<<endl; - } - return 0; -} diff --git a/interpolator.cpp b/src/interpolator.cpp similarity index 100% rename from interpolator.cpp rename to src/interpolator.cpp diff --git a/multipolynomial.cpp b/src/multipolynomial.cpp similarity index 100% rename from multipolynomial.cpp rename to src/multipolynomial.cpp diff --git a/periodicspline.cpp b/src/periodicspline.cpp similarity index 100% rename from periodicspline.cpp rename to src/periodicspline.cpp diff --git a/spline.cpp b/src/spline.cpp similarity index 100% rename from spline.cpp rename to src/spline.cpp diff --git a/test_freespline.cpp b/test_freespline.cpp deleted file mode 100644 index 1856840..0000000 --- a/test_freespline.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * program to test spline class - * - * $Author: claudio $ - * - * $Revision: 1.1.1.1 $ - * - * $Log: test_freespline.cpp,v $ - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - * - */ - -#include <iostream> -#include <fstream> -#include "spline.h" -#include <cmath> - - -using namespace std; -using namespace Interpolator; - -int main(){ - cout<< "test of Spline interpolator class" << endl; - doubleVector x0,y0; - const int NP=30; - for(int i=0; i < NP; i++){ - x0.push_back(i*i*.02); - y0.push_back(sin(i*i*.02)); - } - Spline* test_spline = new Spline(x0,y0,NAN,0.0); - { - doubleVector a; - vector<double> b; - test_spline->get_base_points(a,b); - cout<<"test get_base_points()"<<endl; - for(int i=0; i < NP; i++ ) - if((x0[i] != a[i]) ||(y0[i] != b[i])){ - cout << i << " " << x0[i] << " " << a[i] << " | "<< y0[i] << " " << b[i] << endl; - return -1; - } - - } - { - cout << "test get_range()" << endl; - double minx,maxx; - test_spline->get_range(minx,maxx); - if( (minx != x0[0]) || (maxx != x0[NP-1]) ){ - cout << minx << " " << x0[0] << " | " << maxx << " " << x0[NP-1] << endl; - return -1; - } - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { cout << "test evaluate()for plot" << endl; - doubleVector X; - doubleVector Y; - double range=x0[NP-1]; - double nsteps=300; - for(int i=0;i<=nsteps;i++){ - X.push_back((range*i)/nsteps); - Y.push_back(test_spline->evaluate(X[i])); - } - //print out data - cout<<"---------------------------"<<endl; - for(int i=0; i < NP; i++) cout<<x0[i]<<"\t"<<y0[i]<<endl; - cout<<"---------------------------"<<endl; - for(int i=0; i < nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"+++++++++++++++++++++++++++"<<endl; - } - { - cout << "test evaluate()for doubleVector" << endl; - doubleVector X; - doubleVector Y; - double range=x0[NP-1]; - double nsteps=300; - for(int i=0;i<=nsteps;i++) - X.push_back((range*i)/nsteps); - Y=test_spline->evaluate(X); - //print out data - cout<<"###########################"<<endl; - for(int i=0; i < nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"***************************"<<endl; - } - { - cout << "test range exception" << endl; - try{ - test_spline->evaluate(-10.0); - cerr << "range_error not thrown!" << endl; - } - catch(std::range_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with unequal lengths" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.0); - - y.push_back(4.0); - y.push_back(5.0); - Spline spl(x,y,NAN,0.0); - cerr << "length_error not thrown!" << endl; - } - catch(std::length_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with out of order data" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(1.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - Spline spl(x,y,NAN,0.0); - cerr << "domain_error not thrown!" << endl; - } - catch(std::domain_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "Test copy constructor" << endl; - Spline copy_spline(*test_spline); - double minx,maxx,copyminx,copymaxx; - test_spline->get_range(minx,maxx); - copy_spline.get_range(copyminx,copymaxx); - if( (minx != copyminx) || (maxx != copymaxx) ){ - cerr << "COPY FAILED!" << endl; - return -1; - } - double range=x0[NP-1]; - double nsteps=100; - for(int i=0;i<nsteps;i++){ - double val=(range*i)/nsteps; - double y,ycopy; - ycopy=copy_spline.evaluate(val); - y=test_spline->evaluate(val); - if(y != ycopy){ - cerr << "COPY FAILED " << val << " " << y << " " << ycopy << endl; - } - } - } - { - cout << "Test copy assignment operator" << endl; - Spline oper_spline=*test_spline; - double minx,maxx,operminx,opermaxx; - test_spline->get_range(minx,maxx); - oper_spline.get_range(operminx,opermaxx); - if( (minx != operminx) || (maxx != opermaxx) ){ - cerr << "ASSIGN COPY FAILED!" << endl; - return -1; - } - double range=x0[NP-1]; - double nsteps=100; - for(int i=0;i<nsteps;i++){ - double val=(range*i)/nsteps; - double y,yoper; - yoper=oper_spline.evaluate(val); - y=test_spline->evaluate(val); - if(y != yoper){ - cerr << "COPY FAILED " << val << " " << y << " " << yoper << endl; - } - } - } - cout << "test delete" << endl; - delete test_spline; - { - cout << "test leaks - new/delete" << endl; - Spline *dynspl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - dynspl = new Spline(x,y,NAN,0.0); - delete dynspl; - } - } - { - cout << "test leaks - stack" << endl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - Spline stspl(x,y,NAN,0.0); - } - } - - { - cout <<"test end conditions" << endl; - std::ofstream outfile; - outfile.open("splineval.csv",ios::out); //CHECK success - if ( (outfile.rdstate() & ifstream::failbit ) != 0 ) return -1; - doubleVector x,y; - x.push_back(0.0);y.push_back(0.0); - x.push_back(1.0);y.push_back(1.0); - x.push_back(1.5);y.push_back(1.0); - x.push_back(2.0);y.push_back(1.0); - x.push_back(3.0);y.push_back(0.0); - Spline nsp(x,y); //natural spline - Spline zsp(x,y,0.0,0.0); // spline with 0 derivate start and stop - Spline nzsp(x,y,NAN,0.0); // spline with 0 derivate at stop - Spline znsp(x,y,0.0,NAN); // spline with 0 derivate at start - Spline ddsp(x,y,-0.5,0.5); // spline with derivatives at start and stop - double X; - double Yn,Yz,Ynz,Yzn,Ydd; - double range=3.0; - int nsteps=300; - for(int i=0;i<=nsteps;i++){ - X=((range*i)/nsteps); - Yn=nsp.evaluate(X); - Yz=zsp.evaluate(X); - Ynz=nzsp.evaluate(X); - Yzn=znsp.evaluate(X); - Ydd=ddsp.evaluate(X); - outfile<< X << "\t\t" << Yn << "\t\t" << Yz << "\t\t" << Ynz << "\t\t" << Yzn << "\t\t" << Ydd << std::endl; - } - outfile.close(); - } - return 0; -} diff --git a/test_inverse.cpp b/test_inverse.cpp deleted file mode 100644 index 0fa48ce..0000000 --- a/test_inverse.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * program to test spline classes - * - * $Author: claudio $ - * - * $Revision: 1.1 $ - * - * $Log: test_inverse.cpp,v $ - * Revision 1.1 2017-03-03 15:32:40 claudio - * correctetd spline::inverse_calculate if returned value is at range limit - * - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - * - */ - -#include <iostream> -#include "spline.h" -#include <cmath> -//#include <stdexcept> - -using namespace std; -using namespace Interpolator; -int main(){ - cout << "test spline::inverse_evaluate" << endl; - { - - doubleVector x,y; - x.push_back(10.0); y.push_back(83.6); - x.push_back(12); y.push_back(68.3); - x.push_back( 14); y.push_back( 55.7); - x.push_back( 16); y.push_back(45.5); - x.push_back( 18); y.push_back(37.3); - x.push_back( 20); y.push_back(30.7); - x.push_back( 22); y.push_back( 25.4); - x.push_back( 24); y.push_back( 21.2); - x.push_back( 26); y.push_back( 17.9); - x.push_back( 28); y.push_back( 15.2); - x.push_back( 30); y.push_back( 13.1); - x.push_back( 32); y.push_back( 11.4); - x.push_back( 34); y.push_back( 10.1); - x.push_back( 36); y.push_back( 9); - x.push_back( 40); y.push_back( 7.5); - x.push_back( 50); y.push_back( 5.77); - Spline *lambdasplie = new Spline(x,y); - double gmin,gmax; - - lambdasplie->get_range(gmin,gmax); - double max = lambdasplie->evaluate(gmin); - double min = lambdasplie->evaluate(gmax); - double initial=min +((max-min)/2); - - double l=min; - double gap, linv; - cout << "l\tgap\tlinverse" << endl; - cout.precision(8); - while (l<max){ - gap = lambdasplie->inverse_evaluate(l,initial); - linv = lambdasplie->evaluate(gap); - cout << l <<"\t" << gap << "\t" << linv <<endl; - l+=0.05; - } - delete lambdasplie; - } - return 0; -} diff --git a/test_multipoly.cpp b/test_multipoly.cpp deleted file mode 100644 index d67022b..0000000 --- a/test_multipoly.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - * program to test multipolynomial class - * - * $Author: claudio $ - * - * $Revision: 1.1.1.1 $ - * - * $Log: test_multipoly.cpp,v $ - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - */ - -#include <iostream> -#include "multipolynomial.h" - -using namespace std; -using namespace Interpolator; - -int main(){ - cout << "test of multiPolynomial interpolator class" << endl; - try{ - //create interpolating polynomials - - InterpolatingPolynomial p0,p1,p2; - p0.xMin=0.5; - p0.xMax=1.5; - p0.coefficient.push_back(1.1); - - p1.xMin=1.5; - p1.xMax=2.5; - p1.coefficient.push_back(1.1); - p1.coefficient.push_back(2.2); - - p2.xMin=2.5; - p2.xMax=3.5; - p2.coefficient.push_back(1.1); - p2.coefficient.push_back(2.2); - p2.coefficient.push_back(3.3); - - //stuff polynomial into vector - - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - pvector.push_back(p1); - pvector.push_back(p2); - - multiPolynomial *multipoly = new multiPolynomial(pvector); - double minX,maxX; - multipoly->get_range(minX,maxX); - if( (minX != p0.xMin) || ( maxX != p2.xMax) ){ - cout << "multiPoly.get_range(): error " << minX << " " << maxX << " " << p0.xMin << " " << p2.xMax << endl; - return -1; //stop further testing - } - delete multipoly; - } - catch(...){ - cerr << " unexpected excpetion!" << endl; - return -1; - } - - { - cout << "test a single 2nd degree polynomial " << endl; - try{ - InterpolatingPolynomial p0; - p0.xMin=0.0; - p0.xMax=4.0; - p0.coefficient.push_back(0.0); //a0 - p0.coefficient.push_back(0.0); //a1 - p0.coefficient.push_back(1.0); //a2 --> Y=X*X - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - multiPolynomial *multipoly = new multiPolynomial(pvector); - double v=0.0,y; - y=multipoly->evaluate(v); if( y != 0.0 ){ cerr << "value not correct (0.0): " << y << endl; return -1; } - v=1.0; - y=multipoly->evaluate(v); if( y != 1.0 ){ cerr << "value not correct (1.0): " << y << endl; return -1; } - v=4.0; - y=multipoly->evaluate(v); if( y != 16.0 ){ cerr << "value not correct (16.0): " << y << endl; return -1; } - doubleVector X; - for (int i=0; i<=400;i++) X.push_back(i/100.0); //create range for testing - doubleVector Y=multipoly->evaluate(X); - cout << "----------------------------------" << endl; - for (unsigned int i=0; i < X.size(); i++) cout << X[i] << "\t" << Y[i] << endl; - cout << "----------------------------------" << endl; - delete multipoly; - } - catch(std::range_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - catch(std::length_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - try{ - //create interpolating polynomials - cout << "test non contiguos" << endl; - InterpolatingPolynomial p0,p1,p2; - p0.xMin=0.5; - p0.xMax=1.5; - p0.coefficient.push_back(1.1); - - p1.xMin=1.6; // <------- - p1.xMax=2.5; - p1.coefficient.push_back(1.1); - p1.coefficient.push_back(2.2); - - p2.xMin=2.5; - p2.xMax=3.5; - p2.coefficient.push_back(1.1); - p2.coefficient.push_back(2.2); - p2.coefficient.push_back(3.3); - - //stuff polynomial into vector - - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - pvector.push_back(p1); - pvector.push_back(p2); - - multiPolynomial *multipoly = new multiPolynomial(pvector); - delete multipoly; - } - catch(std::domain_error& ex){ - cout << "OK expected exception: " << ex.what() << endl; - - } - catch(...){ - cerr << " unexpected excpetion!" << endl; - return -1; - } - - try{ - //create interpolating polynomials - cout << "test 3 polynomials" << endl; - InterpolatingPolynomial p0,p1,p2; - p0.xMin=0.0; - p0.xMax=1.5; - p0.coefficient.push_back(1.0); //c[0] - - p1.xMin=1.5; - p1.xMax=2.5; - p1.coefficient.push_back(0.0); //c[0] - p1.coefficient.push_back(0.0); //c[1] - p1.coefficient.push_back(1.0); //c[2] - - p2.xMin=2.5; - p2.xMax=3.5; - p2.coefficient.push_back(5.0); //c[0] - p2.coefficient.push_back(-2.0); //c[1] - //stuff polynomial into vector - - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - pvector.push_back(p1); - pvector.push_back(p2); - - multiPolynomial *multipoly = new multiPolynomial(pvector); - doubleVector X; - for (int i=0; i<=350;i++) X.push_back(i/100.0); //create range for testing - doubleVector Y=multipoly->evaluate(X); - cout << "-+++++++++++++++++++++++++++++++++" << endl; - for (unsigned int i=0; i < X.size(); i++) cout << X[i] << "\t" << Y[i] << endl; - cout << "++++++++++++++++++++++++++++++++++" << endl; - delete multipoly; - } - catch(std::domain_error& ex){ - cout << "unexpected exception: " << ex.what() << endl; - return -1; - } - catch(std::range_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - catch(std::length_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - catch(...){ - cerr << " unexpected excpetion!" << endl; - return -1; - } - - try{ - //create interpolating polynomials - cout << "test 3 identical polynomials" << endl; - InterpolatingPolynomial p0,p1,p2; - p0.xMin=0.0; - p0.xMax=1.5; - p0.coefficient.push_back(1.0); //c[0] - - - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - pvector.push_back(p0); - pvector.push_back(p0); - - multiPolynomial *multipoly = new multiPolynomial(pvector); - doubleVector X; - for (int i=0; i<=150;i++) X.push_back(i/100.0); //create range for testing - doubleVector Y=multipoly->evaluate(X); - cout << "**********************************" << endl; - for (unsigned int i=0; i < X.size(); i++) cout << X[i] << "\t" << Y[i] << endl; - cout << "**********************************" << endl; - delete multipoly; - } - catch(std::domain_error& ex){ - cout << "OK, exception caught: " << ex.what() << endl; - } - catch(std::range_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - catch(std::length_error& ex){ - std::cerr << ex.what() << std::endl; - return -1; - } - catch(...){ - cerr << " unexpected excpetion!" << endl; - return -1; - } - try{ - //create interpolating polynomials - cout << "test copy constructor" << endl; - InterpolatingPolynomial p0,p1,p2; - p0.xMin=0.0; - p0.xMax=1.5; - p0.coefficient.push_back(1.0); //c[0] - - p1.xMin=1.5; - p1.xMax=2.5; - p1.coefficient.push_back(0.0); //c[0] - p1.coefficient.push_back(0.0); //c[1] - p1.coefficient.push_back(1.0); //c[2] - - p2.xMin=2.5; - p2.xMax=3.5; - p2.coefficient.push_back(5.0); //c[0] - p2.coefficient.push_back(-2.0); //c[1] - //stuff polynomial into vector - - InterpolatingPolynoamialVector pvector; - pvector.push_back(p0); - pvector.push_back(p1); - pvector.push_back(p2); - - multiPolynomial *multipoly = new multiPolynomial(pvector); - multiPolynomial copypoly=*multipoly; - doubleVector X; - for (int i=0; i<=350;i++) X.push_back(i/100.0); //create range for testing - doubleVector Y=multipoly->evaluate(X); - doubleVector Yc=copypoly.evaluate(X); - - for (unsigned int i=0; i < X.size(); i++){ - if (Y[i] != Yc[i]) - cerr << "COPY ERROR: " << X[i] << " " << Y[i] << " " << Yc[i] <<endl; - } - delete multipoly; - } - catch(...){ - cerr << " test copy constructor: unexpected excpetion!" << endl; - return -1; - } - } - { - cout << "test interpolatore for constat value on simmetric range" << endl; - InterpolatingPolynomial p0; - InterpolatingPolynoamialVector pvector; - p0.xMin=-5.0; - p0.xMax=5.0; - p0.coefficient.push_back(0.52); //c[0] - pvector.push_back(p0); - multiPolynomial *multipoly = new multiPolynomial(pvector); - double a0=-4.99; - cout << "for "<< a0 << " "<< multipoly->evaluate(a0); - a0=4.99; - cout << "for "<< a0 << " "<< multipoly->evaluate(a0); - delete multipoly; - } - return 0; -} diff --git a/test_obj/test_runner.gcda b/test_obj/test_runner.gcda new file mode 100644 index 0000000000000000000000000000000000000000..4efd016f8520e9fa7d1cf9bf6795fd8490652704 GIT binary patch literal 27324 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 A{r~^~ literal 0 HcmV?d00001 diff --git a/test_obj/test_runner.gcno b/test_obj/test_runner.gcno new file mode 100644 index 0000000000000000000000000000000000000000..4b985fd5a481894c197ae972ac0804f07a7a4f90 GIT binary patch literal 248972 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%0Doa%O#lxv zuoi&7GO#v)hZtA~z~2~H7r@^cSP#I%D*Tgytw6-TRhWLfdnM?$#6M+h2O{QTV0!>_ zGq3}Ic~p2T1N(xA$Ez?e1Fr!QPiEj;0P`_$5rFwscsc`b2NBO;;2i*-rNRO#EXcqW zpsIycSd4)Wfrw`-&`z=!XW_#jY6%7-SW<<hR9KpUkAOCoQDIpIJ_;h1Q(<`qJ_aII zU?A$8N(@91&tc$dP}M37d<wv-3|s?XH3qH)usQ?R0a$~9>jA8#!a6Ffufhfjv<0gn z3!eiWbS{GtY^1{TRM?n-&x1Ceufhu$_yUM{p$eNYa07_gl!2&oG8l*=HfP|gpsFnx z_!@vM8TdMYtr++wfEP3HEdVcJ;M)LR%D_zkUZ%pfDr~R9D->ueT?ZC!1|8Iq!3cIz zVP_R~Vc-_f#;z*t#=!SL#O^BW!NB)H#GVX9ozt6vC}Lj*?gv#Jz(DkE?t>W^|4weZ zhBbtN@$cg{IFy0$@8UK%jDhj*;Wjv&f${I)Hkir4`1fxc9Kk^J71|?JIGTaztEID4 zIG%y=uU)pznZUsKS1ucz$iVp5EgPJ~!1z}!8=TC*_}45OoWj8PS1cQx%0ToD!qZeZ zlY!_PglDA=)6#ErZ9H{wiKdT?TehI_lh1Bw>K^y((z;z%-EsZ<W{nu#vUQD`Ei<$F zj~+Q<Sa0{ZX00QS24@azGh*1p%n`!}_a2tfu6N6JHF{=bG_9F2&J~iDR?h9!#*P_X zZE$AaVPpICuhzG6<!Uu*R_il3YfQB<S;Kk;5vmSK%jYiU+i6>WpO$uEdLH-K_O!I7 z>3Os7)3QG(>C?_|Y4$e&w)k3_eflz3h=ct0v!w-}%FIY_?0)utGmu)%91ORhlpso~ z?ek^0`}CXL&56ZV4VyNt!G7!XR_<|jr`M?2vqN^b_w3VqO#lCpzOU~($ok&j|L^I0 ztI?57?fZY1l9qm-EAq)af0W<#=YY-D_nqA1|B}8xGIoQ9j~v#_jsj}{Ki6it-1*$@ z@BjCVgw^QCrjEqFOG!(g=!*QHamk`<H+|c}MxvT~>_&oIZ~n7`OF8COn8E+KQn|Is ztytmO<d&EsE|;y3{{FwCa~rzy{Sw31%As(}NVgLF@}iUwbn1pPUmEzx7sszky;HN- zZkx4y@c#>)I?(mVTW>Dzm9{bWnbxUxiSS=flKtG1U%&r<>dWD&-Sw8=(lgypE2bCk z^46i{JFP2AxW{Pu)qB)Gk@@@ojw4-rG4b!GB6S)4cPVM<Q(O;r*|UA>cV(Wq#d@@A za*zK1)6`L3jK-g)?BK65;<$@yr*A6y^}g<(+A~P@jIBR-#F*^YX$?k>?%#Ltn8715 zGlscerlpl}dycPsy>d@VyWO+JF)r_y;XN}|?X|GWp8Ygo*1tZEzus-(eq;G;OQk;c z*W>nw;CnsJE+Hemk-PU#O>BApE+Z|yzboUkBEwp=dUr!^>&jpqZI{(Mvt5>(mn~g? zx;?9RR{wTAv%|81>_web?tZto%$7%g1HpFW1+F~b7pc_8>T+b$I`H3Rq@`Qiy0ofQ zyX2T1C$F7ZeZ>jxanCOOhP4?Nc344|fM#B1|MA)1KX|hHy?r@ahTHvY3q}>c%krIM zuL*2-GQGOH^&N7wc-bVlNw*ofX7<iwDm-0zy^X%Ta_HG5bNui&!TZIevL17JOS=7W ox1Zv6U-vxOKPT7S+Lv^s)ONpT+GBOF_(!&&FZ@xFRR5^^57*w-HUIzs literal 0 HcmV?d00001 diff --git a/test_periodicspline.cpp b/test_periodicspline.cpp deleted file mode 100644 index 2d8af4e..0000000 --- a/test_periodicspline.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * program to test peridic spline class - * - * $Author: claudio $ - * - * $Revision: 1.2 $ - * - * $Log: test_periodicspline.cpp,v $ - * Revision 1.2 2017-03-06 13:13:20 claudio - * use unsigned for comparison - * - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - * - */ - -#include <iostream> -#include "periodicspline.h" -#include <cmath> - -using namespace std; -using namespace Interpolator; - -int main(){ - cout<< "test of periodicSpline interpolator class" << endl; - doubleVector x0,y0; - const int NP=15; - const double k = (2*M_PI)/NP; - for(int i=0; i <= NP; i++){ - x0.push_back(i*k); - y0.push_back(sin(i*k)); - } - periodicSpline* test_spline = new periodicSpline(x0,y0); - { - doubleVector a; - doubleVector b; - test_spline->get_base_points(a,b); - cout<<"test get_base_points()"<<endl; - for(unsigned int i=0; i < a.size()-1; i++ ) - if((x0[i] != a[i]) ||(y0[i] != b[i])){ - cout << i << " " << x0[i] << " " << a[i] << " | "<< y0[i] << " " << b[i] << endl; - return -1; - } - - } - { - cout << "test get_range()" << endl; - double minx,maxx; - test_spline->get_range(minx,maxx); - int I=x0.size()-1; - if( (minx != x0[0]) || (maxx != x0[I]) ){ - cout << minx << " " << x0[0] << " | " << maxx << " " << x0[I] << endl; - return -1; - } - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { cout << "test evaluate()for plot" << endl; - doubleVector X; - doubleVector Y; - double minx; - double range; - test_spline->get_range(minx,range); - double nsteps=100; - for(int i=0;i<=nsteps;i++){ - X.push_back((range*i)/nsteps); - Y.push_back(test_spline->evaluate(X[i])); - } - //print out data - cout<<"---------------------------"<<endl; - for(unsigned int i=0; i < x0.size(); i++) cout<<x0[i]<<"\t"<<y0[i]<<endl; - cout<<"---------------------------"<<endl; - for(int i=0; i <= nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"+++++++++++++++++++++++++++"<<endl; - } - { - cout << "test evaluate()for doubleVector" << endl; - doubleVector X; - doubleVector Y; - double minx; - double range; - test_spline->get_range(minx,range); - double nsteps=100; - for(int i=0;i<=nsteps;i++) - X.push_back((range*i)/nsteps); - Y=test_spline->evaluate(X); - //print out data - cout<<"###########################"<<endl; - for(int i=0; i <= nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"***************************"<<endl; - } - { - cout << "test range exception" << endl; - try{ - test_spline->evaluate(-10.0); - cerr << "range_error not thrown!" << endl; - } - catch(std::range_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with unequal lengths" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.0); - - y.push_back(4.0); - y.push_back(5.0); - periodicSpline spl(x,y); - cerr << "length_error not thrown!" << endl; - } - catch(std::length_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with out of order data" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(1.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - periodicSpline spl(x,y); - cerr << "domain_error not thrown!" << endl; - } - catch(std::domain_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "Test copy constructor" << endl; - periodicSpline copy_spline(*test_spline); - double minx,maxx,copyminx,copymaxx; - test_spline->get_range(minx,maxx); - copy_spline.get_range(copyminx,copymaxx); - if( (minx != copyminx) || (maxx != copymaxx) ){ - cerr << "COPY FAILED!" << endl; - return -1; - } - double range; - test_spline->get_range(minx,range); - double nsteps=100; - for(int i=0;i<nsteps;i++){ - double val=(range*i)/nsteps; - double y,ycopy; - ycopy=copy_spline.evaluate(val); - y=test_spline->evaluate(val); - if(y != ycopy){ - cerr << "COPY FAILED " << val << " " << y << " " << ycopy << endl; - } - } - } - { - cout << "Test copy operator" << endl; - periodicSpline copy_spline(*test_spline); - copy_spline=*test_spline; - double minx,maxx,copyminx,copymaxx; - test_spline->get_range(minx,maxx); - copy_spline.get_range(copyminx,copymaxx); - if( (minx != copyminx) || (maxx != copymaxx) ){ - cerr << "COPY FAILED!" << endl; - return -1; - } - double range; - test_spline->get_range(minx,range); - double nsteps=100; - for(int i=0;i<nsteps;i++){ - double val=(range*i)/nsteps; - double y,ycopy; - ycopy=copy_spline.evaluate(val); - y=test_spline->evaluate(val); - if(y != ycopy){ - cerr << "COPY FAILED " << val << " " << y << " " << ycopy << endl; - } - } - } - cout << "test delete" << endl; - delete test_spline; - { - cout << "test leaks - new/delete" << endl; - periodicSpline *dynspl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - dynspl = new periodicSpline(x,y); - delete dynspl; - } - } - { - cout << "test leaks - stack" << endl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - periodicSpline stspl(x,y); - } - } - - return 0; -} diff --git a/test_spline.cpp b/test_spline.cpp deleted file mode 100644 index b2f0a97..0000000 --- a/test_spline.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * program to test spline classes - * - * $Author: claudio $ - * - * $Revision: 1.1.1.1 $ - * - * $Log: test_spline.cpp,v $ - * Revision 1.1.1.1 2012-09-05 08:17:22 claudio - * Interpolator utility classes - * - * - */ - -#include <iostream> -#include "spline.h" -#include <cmath> -//#include <stdexcept> - -using namespace std; -using namespace Interpolator; -int main(){ - cout<< "test of Spline interpolator class" << endl; - doubleVector x0,y0; - const int NP=30; - for(int i=0; i < NP; i++){ - x0.push_back(i*i*.02); - y0.push_back(sin(i*i*.02)); - } - Spline* test_spline = new Spline(x0,y0); - { - doubleVector a; - doubleVector b; - test_spline->get_base_points(a,b); - cout<<"test get_base_points()"<<endl; - for(int i=0; i < NP; i++ ) - if((x0[i] != a[i]) ||(y0[i] != b[i])){ - cout << i << " " << x0[i] << " " << a[i] << " | "<< y0[i] << " " << b[i] << endl; - return -1; - } - - } - { - cout << "test get_range()" << endl; - double minx,maxx; - test_spline->get_range(minx,maxx); - if( (minx != x0[0]) || (maxx != x0[NP-1]) ){ - cout << minx << " " << x0[0] << " | " << maxx << " " << x0[NP-1] << endl; - return -1; - } - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { - cout << "test evaluate()" << endl; - double xn=0.02; - double yn=test_spline->evaluate(xn); - cout << xn << " " << yn << endl; - yn=test_spline->evaluate(x0[5]); - cout << xn << " " << yn << " " << y0[5] << endl; - } - { cout << "test evaluate()for plot" << endl; - doubleVector X; - doubleVector Y; - double range=x0[NP-1]; - double nsteps=100; - for(int i=0;i<nsteps;i++){ - X.push_back((range*i)/nsteps); - Y.push_back(test_spline->evaluate(X[i])); - } - //print out data - cout<<"---------------------------"<<endl; - for(int i=0; i < NP; i++) cout<<x0[i]<<"\t"<<y0[i]<<endl; - cout<<"---------------------------"<<endl; - for(int i=0; i < nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"+++++++++++++++++++++++++++"<<endl; - } - { - cout << "test evaluate()for doubleVector" << endl; - doubleVector X; - doubleVector Y; - double range=x0[NP-1]; - double nsteps=100; - for(int i=0;i<nsteps;i++) - X.push_back((range*i)/nsteps); - Y=test_spline->evaluate(X); - //print out data - cout<<"###########################"<<endl; - for(int i=0; i < nsteps; i++) cout<<X[i]<<"\t"<<Y[i]<<endl; - cout<<"***************************"<<endl; - } - { - cout << "test range exception" << endl; - try{ - test_spline->evaluate(-10.0); - cerr << "range_error not thrown!" << endl; - } - catch(std::range_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with unequal lengths" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.0); - - y.push_back(4.0); - y.push_back(5.0); - Spline spl(x,y); - cerr << "length_error not thrown!" << endl; - } - catch(std::length_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "test constructor with out of order data" << endl; - try{ - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(1.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - Spline spl(x,y); - cerr << "domain_error not thrown!" << endl; - } - catch(std::domain_error& ex){ - cout << "OK, catched expected exception: "<< ex.what() << endl; - } - catch(...){ - cerr << "unexpected exception thrown!" << endl; - } - } - { - cout << "Test copy constructor" << endl; - //Spline copy_spline=*test_spline; - Spline copy_spline(*test_spline); - double minx,maxx,copyminx,copymaxx; - test_spline->get_range(minx,maxx); - copy_spline.get_range(copyminx,copymaxx); - if( (minx != copyminx) || (maxx != copymaxx) ){ - cerr << "COPY FAILED!" << endl; - return -1; - } - double range=x0[NP-1]; - double nsteps=100; - for(int i=0;i<nsteps;i++){ - double val=(range*i)/nsteps; - double y,ycopy; - ycopy=copy_spline.evaluate(val); - y=test_spline->evaluate(val); - if(y != ycopy){ - cerr << "COPY FAILED " << val << " " << y << " " << ycopy << endl; - } - } - } - cout << "test delete" << endl; - delete test_spline; - { - cout << "test leaks - new/delete" << endl; - Spline *dynspl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - dynspl = new Spline(x,y); - delete dynspl; - } - } - { - cout << "test leaks - stack" << endl; - doubleVector x,y; - x.push_back(1.0); - x.push_back(2.0); - x.push_back(3.5); - - y.push_back(4.0); - y.push_back(5.0); - y.push_back(6.0); - for(int i=0; i < 100 ; i++){ - Spline stspl(x,y); - } - } - - return 0; -} diff --git a/test_src/test_runner.cpp b/test_src/test_runner.cpp new file mode 100644 index 0000000..346ac10 --- /dev/null +++ b/test_src/test_runner.cpp @@ -0,0 +1,1064 @@ +/* + * program to test interpolator library + * + */ + +#include <iostream> +#include <fstream> +#include <iomanip> +#include "spline.h" +#include "multipolynomial.h" +#include "periodicspline.h" +#include <cmath> + +using namespace std; +using namespace Interpolator; + +int main() { + { + cout << "test of multiPolynomial interpolator class" << endl; + try { + //create interpolating polynomials + + InterpolatingPolynomial p0, p1, p2; + p0.xMin = 0.5; + p0.xMax = 1.5; + p0.coefficient.push_back(1.1); + + p1.xMin = 1.5; + p1.xMax = 2.5; + p1.coefficient.push_back(1.1); + p1.coefficient.push_back(2.2); + + p2.xMin = 2.5; + p2.xMax = 3.5; + p2.coefficient.push_back(1.1); + p2.coefficient.push_back(2.2); + p2.coefficient.push_back(3.3); + + //stuff polynomial into vector + + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + pvector.push_back(p1); + pvector.push_back(p2); + + multiPolynomial *multipoly = new multiPolynomial(pvector); + double minX, maxX; + multipoly->get_range(minX, maxX); + if ((minX != p0.xMin) || (maxX != p2.xMax)) { + cout << "multiPoly.get_range(): error " << minX << " " << maxX + << " " << p0.xMin << " " << p2.xMax << endl; + return -1; //stop further testing + } + delete multipoly; + } catch (...) { + cerr << " unexpected excpetion!" << endl; + return -1; + } + + { + cout << "test a single 2nd degree polynomial " << endl; + try { + InterpolatingPolynomial p0; + p0.xMin = 0.0; + p0.xMax = 4.0; + p0.coefficient.push_back(0.0); //a0 + p0.coefficient.push_back(0.0); //a1 + p0.coefficient.push_back(1.0); //a2 --> Y=X*X + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + multiPolynomial *multipoly = new multiPolynomial(pvector); + double v = 0.0, y; + y = multipoly->evaluate(v); + if (y != 0.0) { + cerr << "value not correct (0.0): " << y << endl; + return -1; + } + v = 1.0; + y = multipoly->evaluate(v); + if (y != 1.0) { + cerr << "value not correct (1.0): " << y << endl; + return -1; + } + v = 4.0; + y = multipoly->evaluate(v); + if (y != 16.0) { + cerr << "value not correct (16.0): " << y << endl; + return -1; + } + doubleVector X; + for (int i = 0; i <= 400; i++) + X.push_back(i / 100.0); //create range for testing + doubleVector Y = multipoly->evaluate(X); + cout << "----------------------------------" << endl; + for (unsigned int i = 0; i < X.size(); i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "----------------------------------" << endl; + delete multipoly; + } catch (std::range_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } catch (std::length_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } + try { + //create interpolating polynomials + cout << "test non contiguos" << endl; + InterpolatingPolynomial p0, p1, p2; + p0.xMin = 0.5; + p0.xMax = 1.5; + p0.coefficient.push_back(1.1); + + p1.xMin = 1.6; // <------- + p1.xMax = 2.5; + p1.coefficient.push_back(1.1); + p1.coefficient.push_back(2.2); + + p2.xMin = 2.5; + p2.xMax = 3.5; + p2.coefficient.push_back(1.1); + p2.coefficient.push_back(2.2); + p2.coefficient.push_back(3.3); + + //stuff polynomial into vector + + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + pvector.push_back(p1); + pvector.push_back(p2); + + multiPolynomial *multipoly = new multiPolynomial(pvector); + delete multipoly; + } catch (std::domain_error &ex) { + cout << "OK expected exception: " << ex.what() << endl; + + } catch (...) { + cerr << " unexpected excpetion!" << endl; + return -1; + } + + try { + //create interpolating polynomials + cout << "test 3 polynomials" << endl; + InterpolatingPolynomial p0, p1, p2; + p0.xMin = 0.0; + p0.xMax = 1.5; + p0.coefficient.push_back(1.0); //c[0] + + p1.xMin = 1.5; + p1.xMax = 2.5; + p1.coefficient.push_back(0.0); //c[0] + p1.coefficient.push_back(0.0); //c[1] + p1.coefficient.push_back(1.0); //c[2] + + p2.xMin = 2.5; + p2.xMax = 3.5; + p2.coefficient.push_back(5.0); //c[0] + p2.coefficient.push_back(-2.0); //c[1] + //stuff polynomial into vector + + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + pvector.push_back(p1); + pvector.push_back(p2); + + multiPolynomial *multipoly = new multiPolynomial(pvector); + doubleVector X; + for (int i = 0; i <= 350; i++) + X.push_back(i / 100.0); //create range for testing + doubleVector Y = multipoly->evaluate(X); + cout << "-+++++++++++++++++++++++++++++++++" << endl; + for (unsigned int i = 0; i < X.size(); i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "++++++++++++++++++++++++++++++++++" << endl; + delete multipoly; + } catch (std::domain_error &ex) { + cout << "unexpected exception: " << ex.what() << endl; + return -1; + } catch (std::range_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } catch (std::length_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } catch (...) { + cerr << " unexpected excpetion!" << endl; + return -1; + } + + try { + //create interpolating polynomials + cout << "test 3 identical polynomials" << endl; + InterpolatingPolynomial p0, p1, p2; + p0.xMin = 0.0; + p0.xMax = 1.5; + p0.coefficient.push_back(1.0); //c[0] + + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + pvector.push_back(p0); + pvector.push_back(p0); + + multiPolynomial *multipoly = new multiPolynomial(pvector); + doubleVector X; + for (int i = 0; i <= 150; i++) + X.push_back(i / 100.0); //create range for testing + doubleVector Y = multipoly->evaluate(X); + cout << "**********************************" << endl; + for (unsigned int i = 0; i < X.size(); i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "**********************************" << endl; + delete multipoly; + } catch (std::domain_error &ex) { + cout << "OK, exception caught: " << ex.what() << endl; + } catch (std::range_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } catch (std::length_error &ex) { + std::cerr << ex.what() << std::endl; + return -1; + } catch (...) { + cerr << " unexpected excpetion!" << endl; + return -1; + } + try { + //create interpolating polynomials + cout << "test copy constructor" << endl; + InterpolatingPolynomial p0, p1, p2; + p0.xMin = 0.0; + p0.xMax = 1.5; + p0.coefficient.push_back(1.0); //c[0] + + p1.xMin = 1.5; + p1.xMax = 2.5; + p1.coefficient.push_back(0.0); //c[0] + p1.coefficient.push_back(0.0); //c[1] + p1.coefficient.push_back(1.0); //c[2] + + p2.xMin = 2.5; + p2.xMax = 3.5; + p2.coefficient.push_back(5.0); //c[0] + p2.coefficient.push_back(-2.0); //c[1] + //stuff polynomial into vector + + InterpolatingPolynoamialVector pvector; + pvector.push_back(p0); + pvector.push_back(p1); + pvector.push_back(p2); + + multiPolynomial *multipoly = new multiPolynomial(pvector); + multiPolynomial copypoly = *multipoly; + doubleVector X; + for (int i = 0; i <= 350; i++) + X.push_back(i / 100.0); //create range for testing + doubleVector Y = multipoly->evaluate(X); + doubleVector Yc = copypoly.evaluate(X); + + for (unsigned int i = 0; i < X.size(); i++) { + if (Y[i] != Yc[i]) + cerr << "COPY ERROR: " << X[i] << " " << Y[i] << " " + << Yc[i] << endl; + } + delete multipoly; + } catch (...) { + cerr << " test copy constructor: unexpected excpetion!" << endl; + return -1; + } + } + { + cout << "test interpolatore for constat value on simmetric range" + << endl; + InterpolatingPolynomial p0; + InterpolatingPolynoamialVector pvector; + p0.xMin = -5.0; + p0.xMax = 5.0; + p0.coefficient.push_back(0.52); //c[0] + pvector.push_back(p0); + multiPolynomial *multipoly = new multiPolynomial(pvector); + double a0 = -4.99; + cout << "for " << a0 << " " << multipoly->evaluate(a0); + a0 = 4.99; + cout << "for " << a0 << " " << multipoly->evaluate(a0); + delete multipoly; + } + } + //################################################################ + { + cout << "test of Spline interpolator class" << endl; + doubleVector x0, y0; + const int NP = 30; + for (int i = 0; i < NP; i++) { + x0.push_back(i * i * .02); + y0.push_back(sin(i * i * .02)); + } + Spline *test_spline = new Spline(x0, y0, NAN, 0.0); + { + doubleVector a; + vector<double> b; + test_spline->get_base_points(a, b); + cout << "test get_base_points()" << endl; + for (int i = 0; i < NP; i++) + if ((x0[i] != a[i]) || (y0[i] != b[i])) { + cout << i << " " << x0[i] << " " << a[i] << " | " << y0[i] + << " " << b[i] << endl; + return -1; + } + + } + { + cout << "test get_range()" << endl; + double minx, maxx; + test_spline->get_range(minx, maxx); + if ((minx != x0[0]) || (maxx != x0[NP - 1])) { + cout << minx << " " << x0[0] << " | " << maxx << " " + << x0[NP - 1] << endl; + return -1; + } + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()for plot" << endl; + doubleVector X; + doubleVector Y; + double range = x0[NP - 1]; + double nsteps = 300; + for (int i = 0; i <= nsteps; i++) { + X.push_back((range * i) / nsteps); + Y.push_back(test_spline->evaluate(X[i])); + } + //print out data + cout << "---------------------------" << endl; + for (int i = 0; i < NP; i++) + cout << x0[i] << "\t" << y0[i] << endl; + cout << "---------------------------" << endl; + for (int i = 0; i < nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "+++++++++++++++++++++++++++" << endl; + } + { + cout << "test evaluate()for doubleVector" << endl; + doubleVector X; + doubleVector Y; + double range = x0[NP - 1]; + double nsteps = 300; + for (int i = 0; i <= nsteps; i++) + X.push_back((range * i) / nsteps); + Y = test_spline->evaluate(X); + //print out data + cout << "###########################" << endl; + for (int i = 0; i < nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "***************************" << endl; + } + { + cout << "test range exception" << endl; + try { + test_spline->evaluate(-10.0); + cerr << "range_error not thrown!" << endl; + } catch (std::range_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with unequal lengths" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.0); + + y.push_back(4.0); + y.push_back(5.0); + Spline spl(x, y, NAN, 0.0); + cerr << "length_error not thrown!" << endl; + } catch (std::length_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with out of order data" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(1.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + Spline spl(x, y, NAN, 0.0); + cerr << "domain_error not thrown!" << endl; + } catch (std::domain_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "Test copy constructor" << endl; + Spline copy_spline(*test_spline); + double minx, maxx, copyminx, copymaxx; + test_spline->get_range(minx, maxx); + copy_spline.get_range(copyminx, copymaxx); + if ((minx != copyminx) || (maxx != copymaxx)) { + cerr << "COPY FAILED!" << endl; + return -1; + } + double range = x0[NP - 1]; + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, ycopy; + ycopy = copy_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != ycopy) { + cerr << "COPY FAILED " << val << " " << y << " " << ycopy + << endl; + } + } + } + { + cout << "Test copy assignment operator" << endl; + Spline oper_spline = *test_spline; + double minx, maxx, operminx, opermaxx; + test_spline->get_range(minx, maxx); + oper_spline.get_range(operminx, opermaxx); + if ((minx != operminx) || (maxx != opermaxx)) { + cerr << "ASSIGN COPY FAILED!" << endl; + return -1; + } + double range = x0[NP - 1]; + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, yoper; + yoper = oper_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != yoper) { + cerr << "COPY FAILED " << val << " " << y << " " << yoper + << endl; + } + } + } + cout << "test delete" << endl; + delete test_spline; + { + cout << "test leaks - new/delete" << endl; + Spline *dynspl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + dynspl = new Spline(x, y, NAN, 0.0); + delete dynspl; + } + } + { + cout << "test leaks - stack" << endl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + Spline stspl(x, y, NAN, 0.0); + } + } + + { + cout << "test end conditions" << endl; + std::ofstream outfile; + outfile.open("splineval.csv", ios::out); //CHECK success + if ((outfile.rdstate() & ifstream::failbit) != 0) + return -1; + doubleVector x, y; + x.push_back(0.0); + y.push_back(0.0); + x.push_back(1.0); + y.push_back(1.0); + x.push_back(1.5); + y.push_back(1.0); + x.push_back(2.0); + y.push_back(1.0); + x.push_back(3.0); + y.push_back(0.0); + Spline nsp(x, y); //natural spline + Spline zsp(x, y, 0.0, 0.0); // spline with 0 derivate start and stop + Spline nzsp(x, y, NAN, 0.0); // spline with 0 derivate at stop + Spline znsp(x, y, 0.0, NAN); // spline with 0 derivate at start + Spline ddsp(x, y, -0.5, 0.5); // spline with derivatives at start and stop + double X; + double Yn, Yz, Ynz, Yzn, Ydd; + double range = 3.0; + int nsteps = 300; + for (int i = 0; i <= nsteps; i++) { + X = ((range * i) / nsteps); + Yn = nsp.evaluate(X); + Yz = zsp.evaluate(X); + Ynz = nzsp.evaluate(X); + Yzn = znsp.evaluate(X); + Ydd = ddsp.evaluate(X); + outfile << X << "\t\t" << Yn << "\t\t" << Yz << "\t\t" << Ynz + << "\t\t" << Yzn << "\t\t" << Ydd << std::endl; + } + outfile.close(); + } + } + //###################################################################### + { + cout << "test of Spline interpolator class" << endl; + doubleVector x0, y0; + const int NP = 30; + for (int i = 0; i < NP; i++) { + x0.push_back(i * i * .02); + y0.push_back(sin(i * i * .02)); + } + Spline *test_spline = new Spline(x0, y0, NAN, 0.0); + { + doubleVector a; + vector<double> b; + test_spline->get_base_points(a, b); + cout << "test get_base_points()" << endl; + for (int i = 0; i < NP; i++) + if ((x0[i] != a[i]) || (y0[i] != b[i])) { + cout << i << " " << x0[i] << " " << a[i] << " | " << y0[i] + << " " << b[i] << endl; + return -1; + } + + } + { + cout << "test get_range()" << endl; + double minx, maxx; + test_spline->get_range(minx, maxx); + if ((minx != x0[0]) || (maxx != x0[NP - 1])) { + cout << minx << " " << x0[0] << " | " << maxx << " " + << x0[NP - 1] << endl; + return -1; + } + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()for plot" << endl; + doubleVector X; + doubleVector Y; + double range = x0[NP - 1]; + double nsteps = 300; + for (int i = 0; i <= nsteps; i++) { + X.push_back((range * i) / nsteps); + Y.push_back(test_spline->evaluate(X[i])); + } + //print out data + cout << "---------------------------" << endl; + for (int i = 0; i < NP; i++) + cout << x0[i] << "\t" << y0[i] << endl; + cout << "---------------------------" << endl; + for (int i = 0; i < nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "+++++++++++++++++++++++++++" << endl; + } + { + cout << "test evaluate()for doubleVector" << endl; + doubleVector X; + doubleVector Y; + double range = x0[NP - 1]; + double nsteps = 300; + for (int i = 0; i <= nsteps; i++) + X.push_back((range * i) / nsteps); + Y = test_spline->evaluate(X); + //print out data + cout << "###########################" << endl; + for (int i = 0; i < nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "***************************" << endl; + } + { + cout << "test range exception" << endl; + try { + test_spline->evaluate(-10.0); + cerr << "range_error not thrown!" << endl; + } catch (std::range_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with unequal lengths" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.0); + + y.push_back(4.0); + y.push_back(5.0); + Spline spl(x, y, NAN, 0.0); + cerr << "length_error not thrown!" << endl; + } catch (std::length_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with out of order data" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(1.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + Spline spl(x, y, NAN, 0.0); + cerr << "domain_error not thrown!" << endl; + } catch (std::domain_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "Test copy constructor" << endl; + Spline copy_spline(*test_spline); + double minx, maxx, copyminx, copymaxx; + test_spline->get_range(minx, maxx); + copy_spline.get_range(copyminx, copymaxx); + if ((minx != copyminx) || (maxx != copymaxx)) { + cerr << "COPY FAILED!" << endl; + return -1; + } + double range = x0[NP - 1]; + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, ycopy; + ycopy = copy_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != ycopy) { + cerr << "COPY FAILED " << val << " " << y << " " << ycopy + << endl; + } + } + } + { + cout << "Test copy assignment operator" << endl; + Spline oper_spline = *test_spline; + double minx, maxx, operminx, opermaxx; + test_spline->get_range(minx, maxx); + oper_spline.get_range(operminx, opermaxx); + if ((minx != operminx) || (maxx != opermaxx)) { + cerr << "ASSIGN COPY FAILED!" << endl; + return -1; + } + double range = x0[NP - 1]; + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, yoper; + yoper = oper_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != yoper) { + cerr << "COPY FAILED " << val << " " << y << " " << yoper + << endl; + } + } + } + cout << "test delete" << endl; + delete test_spline; + { + cout << "test leaks - new/delete" << endl; + Spline *dynspl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + dynspl = new Spline(x, y, NAN, 0.0); + delete dynspl; + } + } + { + cout << "test leaks - stack" << endl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + Spline stspl(x, y, NAN, 0.0); + } + } + + { + cout << "test end conditions" << endl; + std::ofstream outfile; + outfile.open("splineval.csv", ios::out); //CHECK success + if ((outfile.rdstate() & ifstream::failbit) != 0) + return -1; + doubleVector x, y; + x.push_back(0.0); + y.push_back(0.0); + x.push_back(1.0); + y.push_back(1.0); + x.push_back(1.5); + y.push_back(1.0); + x.push_back(2.0); + y.push_back(1.0); + x.push_back(3.0); + y.push_back(0.0); + Spline nsp(x, y); //natural spline + Spline zsp(x, y, 0.0, 0.0); // spline with 0 derivate start and stop + Spline nzsp(x, y, NAN, 0.0); // spline with 0 derivate at stop + Spline znsp(x, y, 0.0, NAN); // spline with 0 derivate at start + Spline ddsp(x, y, -0.5, 0.5); // spline with derivatives at start and stop + double X; + double Yn, Yz, Ynz, Yzn, Ydd; + double range = 3.0; + int nsteps = 300; + for (int i = 0; i <= nsteps; i++) { + X = ((range * i) / nsteps); + Yn = nsp.evaluate(X); + Yz = zsp.evaluate(X); + Ynz = nzsp.evaluate(X); + Yzn = znsp.evaluate(X); + Ydd = ddsp.evaluate(X); + outfile << X << "\t\t" << Yn << "\t\t" << Yz << "\t\t" << Ynz + << "\t\t" << Yzn << "\t\t" << Ydd << std::endl; + } + outfile.close(); + } + } + //####################################################################### + { + cout << "test spline::inverse_evaluate" << endl; + { + + doubleVector x, y; + x.push_back(10.0); + y.push_back(83.6); + x.push_back(12); + y.push_back(68.3); + x.push_back(14); + y.push_back(55.7); + x.push_back(16); + y.push_back(45.5); + x.push_back(18); + y.push_back(37.3); + x.push_back(20); + y.push_back(30.7); + x.push_back(22); + y.push_back(25.4); + x.push_back(24); + y.push_back(21.2); + x.push_back(26); + y.push_back(17.9); + x.push_back(28); + y.push_back(15.2); + x.push_back(30); + y.push_back(13.1); + x.push_back(32); + y.push_back(11.4); + x.push_back(34); + y.push_back(10.1); + x.push_back(36); + y.push_back(9); + x.push_back(40); + y.push_back(7.5); + x.push_back(50); + y.push_back(5.77); + Spline *lambdasplie = new Spline(x, y); + double gmin, gmax; + + lambdasplie->get_range(gmin, gmax); + double max = lambdasplie->evaluate(gmin); + double min = lambdasplie->evaluate(gmax); + double initial = min + ((max - min) / 2); + + double l = min; + double gap, linv; + cout << "l\tgap\tlinverse" << endl; + cout.precision(8); + while (l < max) { + gap = lambdasplie->inverse_evaluate(l, initial); + linv = lambdasplie->evaluate(gap); + cout << l << "\t" << gap << "\t" << linv << endl; + l += 0.05; + } + delete lambdasplie; + } + } + //############################################################### + { + cout << "test of periodicSpline interpolator class" << endl; + doubleVector x0, y0; + const int NP = 15; + const double k = (2 * M_PI) / NP; + for (int i = 0; i <= NP; i++) { + x0.push_back(i * k); + y0.push_back(sin(i * k)); + } + periodicSpline *test_spline = new periodicSpline(x0, y0); + { + doubleVector a; + doubleVector b; + test_spline->get_base_points(a, b); + cout << "test get_base_points()" << endl; + for (unsigned int i = 0; i < a.size() - 1; i++) + if ((x0[i] != a[i]) || (y0[i] != b[i])) { + cout << i << " " << x0[i] << " " << a[i] << " | " << y0[i] + << " " << b[i] << endl; + return -1; + } + + } + { + cout << "test get_range()" << endl; + double minx, maxx; + test_spline->get_range(minx, maxx); + int I = x0.size() - 1; + if ((minx != x0[0]) || (maxx != x0[I])) { + cout << minx << " " << x0[0] << " | " << maxx << " " << x0[I] + << endl; + return -1; + } + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()" << endl; + double xn = 0.02; + double yn = test_spline->evaluate(xn); + cout << xn << " " << yn << endl; + yn = test_spline->evaluate(x0[5]); + cout << xn << " " << yn << " " << y0[5] << endl; + } + { + cout << "test evaluate()for plot" << endl; + doubleVector X; + doubleVector Y; + double minx; + double range; + test_spline->get_range(minx, range); + double nsteps = 100; + for (int i = 0; i <= nsteps; i++) { + X.push_back((range * i) / nsteps); + Y.push_back(test_spline->evaluate(X[i])); + } + //print out data + cout << "---------------------------" << endl; + for (unsigned int i = 0; i < x0.size(); i++) + cout << x0[i] << "\t" << y0[i] << endl; + cout << "---------------------------" << endl; + for (int i = 0; i <= nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "+++++++++++++++++++++++++++" << endl; + } + { + cout << "test evaluate()for doubleVector" << endl; + doubleVector X; + doubleVector Y; + double minx; + double range; + test_spline->get_range(minx, range); + double nsteps = 100; + for (int i = 0; i <= nsteps; i++) + X.push_back((range * i) / nsteps); + Y = test_spline->evaluate(X); + //print out data + cout << "###########################" << endl; + for (int i = 0; i <= nsteps; i++) + cout << X[i] << "\t" << Y[i] << endl; + cout << "***************************" << endl; + } + { + cout << "test range exception" << endl; + try { + test_spline->evaluate(-10.0); + cerr << "range_error not thrown!" << endl; + } catch (std::range_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with unequal lengths" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.0); + + y.push_back(4.0); + y.push_back(5.0); + periodicSpline spl(x, y); + cerr << "length_error not thrown!" << endl; + } catch (std::length_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "test constructor with out of order data" << endl; + try { + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(1.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + periodicSpline spl(x, y); + cerr << "domain_error not thrown!" << endl; + } catch (std::domain_error &ex) { + cout << "OK, catched expected exception: " << ex.what() << endl; + } catch (...) { + cerr << "unexpected exception thrown!" << endl; + } + } + { + cout << "Test copy constructor" << endl; + periodicSpline copy_spline(*test_spline); + double minx, maxx, copyminx, copymaxx; + test_spline->get_range(minx, maxx); + copy_spline.get_range(copyminx, copymaxx); + if ((minx != copyminx) || (maxx != copymaxx)) { + cerr << "COPY FAILED!" << endl; + return -1; + } + double range; + test_spline->get_range(minx, range); + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, ycopy; + ycopy = copy_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != ycopy) { + cerr << "COPY FAILED " << val << " " << y << " " << ycopy + << endl; + } + } + } + { + cout << "Test copy operator" << endl; + periodicSpline copy_spline(*test_spline); + copy_spline = *test_spline; + double minx, maxx, copyminx, copymaxx; + test_spline->get_range(minx, maxx); + copy_spline.get_range(copyminx, copymaxx); + if ((minx != copyminx) || (maxx != copymaxx)) { + cerr << "COPY FAILED!" << endl; + return -1; + } + double range; + test_spline->get_range(minx, range); + double nsteps = 100; + for (int i = 0; i < nsteps; i++) { + double val = (range * i) / nsteps; + double y, ycopy; + ycopy = copy_spline.evaluate(val); + y = test_spline->evaluate(val); + if (y != ycopy) { + cerr << "COPY FAILED " << val << " " << y << " " << ycopy + << endl; + } + } + } + cout << "test delete" << endl; + delete test_spline; + { + cout << "test leaks - new/delete" << endl; + periodicSpline *dynspl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + dynspl = new periodicSpline(x, y); + delete dynspl; + } + } + { + cout << "test leaks - stack" << endl; + doubleVector x, y; + x.push_back(1.0); + x.push_back(2.0); + x.push_back(3.5); + + y.push_back(4.0); + y.push_back(5.0); + y.push_back(6.0); + for (int i = 0; i < 100; i++) { + periodicSpline stspl(x, y); + } + } + } +return 0; +} -- GitLab