OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WPOLYNOMIALEQUATIONSOLVERS_TEST_H 00026 #define WPOLYNOMIALEQUATIONSOLVERS_TEST_H 00027 00028 #include <iomanip> 00029 #include <sstream> 00030 #include <string> 00031 #include <utility> 00032 00033 #include <cxxtest/TestSuite.h> 00034 00035 #include "../WPolynomialEquationSolvers.h" 00036 00037 /** 00038 * Testsuite for the WPolynomialEquationSolvers functions 00039 */ 00040 class WPolynomialEquationSolversTest : public CxxTest::TestSuite 00041 { 00042 public: 00043 /** 00044 * If there is no solution an exception should be thrown. 00045 */ 00046 void testRealQuadraticEquationWithNoSolution( void ) 00047 { 00048 TS_ASSERT_THROWS_EQUALS( solveRealQuadraticEquation( 0.0, 0.0, 1.0 ), const WEquationHasNoRoots &e, 00049 std::string( e.what() ), "The equation: 0x^2 + 0x + 1 = 0.0 has no solutions!" ); 00050 } 00051 00052 /** 00053 * x^2 = 0 has only one solution: 0.0. 00054 */ 00055 void testRealQuadraticEquationWithOnlyOneSolution( void ) 00056 { 00057 typedef std::pair< std::complex< double >, std::complex< double > > ComplexPair; 00058 ComplexPair actual = solveRealQuadraticEquation( 1.0, 0.0, 0.0 ); 00059 TS_ASSERT_EQUALS( actual.first, std::complex< double >( 0.0, 0.0 ) ); 00060 TS_ASSERT_EQUALS( actual.second, actual.first ); 00061 } 00062 00063 /** 00064 * x^2 - 1 = 0 has two solutions: 1.0 and -1.0. 00065 */ 00066 void testRealQuadraticEquationWithTwoRealSolutions( void ) 00067 { 00068 typedef std::pair< std::complex< double >, std::complex< double > > ComplexPair; 00069 ComplexPair actual = solveRealQuadraticEquation( 1.0, 0.0, -1.0 ); 00070 ComplexPair expected = ComplexPair( std::complex< double >( -1.0, 0.0 ), std::complex< double >( 1.0, 0.0 ) ); 00071 if( actual.first != expected.first ) 00072 { 00073 std::cout << std::endl << "We assume the order of the pair is swaped, but both solutions are right" << std::endl; 00074 TS_ASSERT_EQUALS( actual.first, expected.second ); 00075 TS_ASSERT_EQUALS( actual.second, expected.first ); 00076 } 00077 else 00078 { 00079 TS_ASSERT_EQUALS( actual.first, expected.first ); 00080 TS_ASSERT_EQUALS( actual.second, expected.second ); 00081 } 00082 } 00083 00084 /** 00085 * x^2 + 1 = 0 has two solutions: i and -i. 00086 */ 00087 void testRealQuadraticEquationWithTwoImaginarySolutions( void ) 00088 { 00089 typedef std::pair< std::complex< double >, std::complex< double > > ComplexPair; 00090 ComplexPair actual = solveRealQuadraticEquation( 1.0, 0.0, 1.0 ); 00091 ComplexPair expected = ComplexPair( std::complex< double >( 0.0, 1.0 ), std::complex< double >( 0.0, -1.0 ) ); 00092 if( actual.first != expected.first ) 00093 { 00094 std::cout << std::endl << "We assume the order of the pair is swaped, but both solutions are right" << std::endl; 00095 TS_ASSERT_EQUALS( actual.first, expected.second ); 00096 TS_ASSERT_EQUALS( actual.second, expected.first ); 00097 } 00098 else 00099 { 00100 TS_ASSERT_EQUALS( actual.first, expected.first ); 00101 TS_ASSERT_EQUALS( actual.second, expected.second ); 00102 } 00103 } 00104 00105 /** 00106 * This test numerical stability: 00107 * x^2 + 9999999999x -9e10 = 0, has solutions according to wolfram alpha: 00108 * x_1 = -1.00000000079999999928x10^10 00109 * x_2 = 8.99999999280000001224 00110 */ 00111 void testRealQuadraticEquationToTestNumericalIssuesAndPrecisions( void ) 00112 { 00113 typedef std::pair< std::complex< double >, std::complex< double > > ComplexPair; 00114 ComplexPair actual = solveRealQuadraticEquation( 1.0, 9999999999.0, -9.0e10 ); 00115 ComplexPair expected = ComplexPair( std::complex< double >( -1.00000000079999999928e10, 0.0 ), std::complex< double >( 8.99999999280000001224, 0.0 ) ); // NOLINT line length 00116 double delta = 0.00000001; // This precision was found by trial and error 00117 if( ( ( std::abs( actual.first - expected.first ) > delta ) && ( std::abs( actual.first - expected.second ) > delta ) ) || 00118 ( ( std::abs( actual.second - expected.second ) > delta ) && ( std::abs( actual.second - expected.first ) > delta ) ) ) 00119 { 00120 std::stringstream ss; 00121 ss << std::fixed << std::setprecision( 16 ) << std::endl; 00122 ss << "Invalid solutions: " << std::endl; 00123 ss << std::real( actual.first ) << " i" << std::imag( actual.first ) << " :::: "; 00124 ss << std::real( actual.second ) << " i" << std::imag( actual.second ) << std::endl; 00125 ss << " were invalid. I expected: " << std::endl; 00126 ss << std::real( expected.first ) << " i" << std::imag( expected.first ) << " :::: "; 00127 ss << std::real( expected.second ) << " i" << std::imag( expected.second ) << std::endl; 00128 std::cout << ss.str(); 00129 TS_FAIL( "Check your numerical stability and the order of the solutions found." ); 00130 } 00131 } 00132 }; 00133 00134 #endif // WPOLYNOMIALEQUATIONSOLVERS_TEST_H