src/tools/unitTest/tPolynomialTest.cpp

Go to the documentation of this file.
00001 #include "nMessageMock.h"
00002 #include "tPolynomial.h"
00003 #include <cppunit/extensions/HelperMacros.h>
00004 #include <cppunit/extensions/TestFactoryRegistry.h>
00005 
00006 class tPolynomialTest : public CppUnit::TestFixture {
00007 private:
00008     tPolynomial<nMessageMock> tpEmpty, tpOne, tpZero, tpTwo;
00009 
00010 public:
00011     CPPUNIT_TEST_SUITE( tPolynomialTest );
00012     CPPUNIT_TEST( testEquality );
00013     CPPUNIT_TEST( testAddition );
00014     CPPUNIT_TEST( testMultiplication );
00015     CPPUNIT_TEST( testEvaluateAndBaseArgument );
00016     //    CPPUNIT_TEST( testWriteAndReadToStream );
00017     CPPUNIT_TEST( testParse );
00018     CPPUNIT_TEST( testTranslate );
00019     CPPUNIT_TEST( testSubstitute );
00020     CPPUNIT_TEST_SUITE_END();
00021 
00022 public:
00023     void setUp() {
00024         //        tpEmpty = tPolynomial<nMessageMock> ;
00025         tpZero  = tPolynomial<nMessageMock>(1);
00026         tpZero[(unsigned)0] = 0.0;
00027         tpOne   = tPolynomial<nMessageMock>(1);
00028         tpOne[0] = 1.0;
00029         tpTwo   = tPolynomial<nMessageMock>(1);
00030         tpTwo[0] = 2.0;
00031     }
00032 
00033     void tearDown() {
00034         // Empty
00035     }
00036 
00037     void testEquality() {
00038         CPPUNIT_ASSERT( tpEmpty == tpEmpty );
00039         CPPUNIT_ASSERT( tpOne == tpOne );
00040         CPPUNIT_ASSERT( tpEmpty == tpZero );
00041         CPPUNIT_ASSERT( !(tpZero == tpOne) );
00042         // testing the copy constructor
00043         CPPUNIT_ASSERT( tpOne == tPolynomial<nMessageMock>(tpOne) );
00044 
00045         // testing the tArray constructor
00046         float values[] = {1, 3, 5, 7};
00047         int size = sizeof(values)/sizeof(values[0]);
00048         tArray<float> tValues(size);
00049         for (int i=0; i<size; i++) {
00050             tValues[i] = values[i];
00051         }
00052         tPolynomial<nMessageMock> tpByArray(values, size);
00053         tPolynomial<nMessageMock> tpBytArray(tValues);
00054 
00055         CPPUNIT_ASSERT(tpByArray == tpBytArray);
00056 
00057         // Testing the assignment operator
00058         float randomData[] = {3, 5, 7};
00059         tPolynomial<nMessageMock> initiated(randomData, sizeof(randomData)/sizeof(randomData[0]));
00060         tPolynomial<nMessageMock> uninitiated;
00061 
00062         initiated = tpTwo;
00063         uninitiated = tpTwo;
00064         CPPUNIT_ASSERT( 2.0 == tpTwo[0] );
00065         CPPUNIT_ASSERT( 2.0 == initiated[0] );
00066         CPPUNIT_ASSERT( tpTwo == initiated );
00067         CPPUNIT_ASSERT( tpTwo == uninitiated );
00068     }
00069 
00070     void testAddition() {
00071         // {0} = {-} + {0}
00072         CPPUNIT_ASSERT( tpZero == tpEmpty + tpZero );
00073         // {1} = {0} + {1}
00074         CPPUNIT_ASSERT( tpOne == tpZero + tpOne );
00075         // {2} = {1} + {1}
00076         CPPUNIT_ASSERT( tpTwo == tpOne + tpOne );
00077         // a = b + c
00078         float a[] = {3, 5, 7, 11};
00079         float b[] = {0, 5, 3, -5};
00080         float c[] = {3, 0, 4, 16};
00081         tPolynomial<nMessageMock> tpA(a, sizeof(a)/sizeof(a[0]));
00082         tPolynomial<nMessageMock> tpB(b, sizeof(b)/sizeof(b[0]));
00083         tPolynomial<nMessageMock> tpC(c, sizeof(c)/sizeof(c[0]));
00084 
00085         CPPUNIT_ASSERT( tpA == tpB + tpC );
00086 
00087         // {0} = {-} + 0
00088         CPPUNIT_ASSERT( tpZero == tpEmpty + 0.0 );
00089         // {1} = {0} + 1
00090         CPPUNIT_ASSERT( tpOne == tpZero + 1.0 );
00091         // {2} = {1} + 1
00092         CPPUNIT_ASSERT( tpTwo == tpOne + 1.0 );
00093 
00094         // {a} + 1 == ({b} + 2) + {c} + -1
00095         CPPUNIT_ASSERT( (tpA + 1.0) == (tpB + 2.0) + tpC + -1.0);
00096 
00097 
00098         tPolynomial<nMessageMock> tpAat5 = tpA.adaptToNewReferenceVarValue(5.0);
00099         tPolynomial<nMessageMock> tpBat5 = tpB.adaptToNewReferenceVarValue(5.0);
00100         tPolynomial<nMessageMock> tpCat5 = tpC.adaptToNewReferenceVarValue(5.0);
00101         CPPUNIT_ASSERT( tpAat5 == tpBat5 + tpCat5 );
00102 
00103         //
00104         // Adding 2 polynomial having different referenceVarValue
00105         //
00106         tPolynomial<nMessageMock> tpAat3 = tpA.adaptToNewReferenceVarValue(3.0);
00107         tPolynomial<nMessageMock> tpCat7 = tpC.adaptToNewReferenceVarValue(7.0);
00108 
00109         // Addition
00110         tPolynomial<nMessageMock> tpAat3at5 = tpAat3.adaptToNewReferenceVarValue(5.0);
00111         tPolynomial<nMessageMock> tpCat7at5 = tpCat7.adaptToNewReferenceVarValue(5.0);
00112         tPolynomial<nMessageMock> sum = (tpBat5 + tpCat7);
00113         CPPUNIT_ASSERT( tpAat3 == tpBat5 + tpCat7 );
00114 
00115         // Addition with operator+=
00116         // This modified tpBat5
00117         CPPUNIT_ASSERT( tpAat3 == (tpBat5 += tpCat7) );
00118     }
00119 
00120     void testMultiplication() {
00121         // {0} = {-} * {0}
00122         CPPUNIT_ASSERT( tpZero == tpEmpty * tpZero );
00123         // {0} = {0} * {1}
00124         CPPUNIT_ASSERT( tpZero == tpZero * tpOne );
00125         // {1} = {1} * {1}
00126         CPPUNIT_ASSERT( tpOne == tpOne * tpOne );
00127         // {1,0,0} = {1,0} * {1,0}
00128         float onePower2[] = {0, 1};
00129         tPolynomial<nMessageMock> tpOnePower2( onePower2, sizeof(onePower2)/sizeof(onePower2[0]) );
00130         float onePower3[] = {0, 0, 1};
00131         tPolynomial<nMessageMock> tpOnePower3( onePower3, sizeof(onePower3)/sizeof(onePower3[0]) );
00132 
00133         CPPUNIT_ASSERT( tpOnePower3 == (tpOnePower2 * tpOnePower2) );
00134 
00135         {
00136             // a = b * c
00137             float a[] = {3.0, 2.5, -6.0, -17, -5, 12, 12};
00138             float b[] = {1, 0.0, -2, -2};
00139             float c[] = {3, 2.5, 0, -6};
00140             tPolynomial<nMessageMock> tpA(a, sizeof(a)/sizeof(a[0]));
00141             tPolynomial<nMessageMock> tpB(b, sizeof(b)/sizeof(b[0]));
00142             tPolynomial<nMessageMock> tpC(c, sizeof(c)/sizeof(c[0]));
00143 
00144             CPPUNIT_ASSERT( tpA == tpB * tpC );
00145 
00146             // {0} = {-} * 0
00147             CPPUNIT_ASSERT( tpZero == tpEmpty * 0.0 );
00148             // {0} = {0} * 1
00149             CPPUNIT_ASSERT( tpZero == tpZero * 1.0 );
00150             // {1} = {1} * 1
00151             CPPUNIT_ASSERT( tpOne == tpOne * 1.0 );
00152             // {a} * -2 == ({b} * 2) * ({c} * -1)
00153             CPPUNIT_ASSERT( (tpA * -2.0) == (tpB * 2.0) * (tpC * -1.0));
00154         }
00155 
00156         // Can a tPolynomial be used to make a zone shape turn?
00157         // Zone rotation are described by 4 term:
00158         // a : basic orientation angle
00159         // b : orientation angle in function of the conquest state
00160         // c : basic rotation speed
00161         // d : rotation speed in function of the conquest state
00162         //
00163         // The polynomial used to describe the actual rotation gets computed from both
00164         // a + conquestRate * b + t * (c + conquestRate * d)
00165         //
00166         {
00167             float a = 1.0;
00168             float b = 2.0;
00169             float c = 3.0;
00170             float d = 4.0;
00171             float conquestState[] = {3, 5, 7};
00172             // Manually resolving the following:
00173             // a + conquestRate * b + t * (c + conquestRate * d)
00174             // 1 + {3, 5, 7} * 2 + t * ( 3 + {3, 5, 7} * 4 }
00175             // 1 + {6, 10, 14} + t * ( 3 + {12, 20, 28} }
00176             // {7, 10, 14} + t * ( {15, 20, 28} }
00177             // {7, 10, 14} + {0, 15, 20, 28}
00178             // {7, 25, 34, 28}
00179             //
00180             float resValue[] = {7, 25, 34, 28};
00181             tPolynomial<nMessageMock> res(resValue, sizeof(resValue)/sizeof(resValue[0]));
00182 
00183             float t[] = {0.0, 1.0};
00184             tPolynomial<nMessageMock> tpT( t, sizeof(t)/sizeof(t[0]) );
00185             tPolynomial<nMessageMock> tpConquestState( conquestState, sizeof(conquestState)/sizeof(conquestState[0])  );
00186 
00187             tPolynomial<nMessageMock> tf =
00188                 ( (tpConquestState * b) + a)
00189                 + tpT * ( (tpConquestState * d) + c);
00190 
00191             CPPUNIT_ASSERT(res == tf);
00192         }
00193     }
00194 
00195 #define DELTA 1e-3
00196 
00197     void testEvaluateAndBaseArgument() {
00198         float accelA = 10.0;
00199         float accelB = -10.0;
00200         float a[] = {0, 0, accelA};
00201         float b[] = {50, 45, accelB};
00202         tPolynomial<nMessageMock> tfA(a, sizeof(a)/sizeof(a[0]));
00203         tPolynomial<nMessageMock> tfB(b, sizeof(b)/sizeof(b[0]));
00204 
00205         CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, tfA.evaluate(0), DELTA);
00206         CPPUNIT_ASSERT_DOUBLES_EQUAL( 125.0, tfA.evaluate(5), DELTA);
00207 
00208         CPPUNIT_ASSERT_DOUBLES_EQUAL( 50.0, tfB.evaluate(0), DELTA);
00209         CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, tfB.evaluate(10), DELTA);
00210 
00211         // change the base argument and adjust the coefs to time 5
00212         float NEW_REFERENCE_TIME = 5.0;
00213         tfA = tfA.adaptToNewReferenceVarValue(NEW_REFERENCE_TIME);
00214         tfB = tfB.adaptToNewReferenceVarValue(NEW_REFERENCE_TIME);
00215 
00216         // These should still be true
00217         CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, tfA.evaluate(0), DELTA);
00218         CPPUNIT_ASSERT_DOUBLES_EQUAL( 125.0, tfA.evaluate(5), DELTA);
00219 
00220         CPPUNIT_ASSERT_DOUBLES_EQUAL( 50.0, tfB.evaluate(0), DELTA);
00221         CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, tfB.evaluate(10), DELTA);
00222 
00223         // changing the acceleration
00224         tfA.changeRate(2.0*accelA, 2, NEW_REFERENCE_TIME);
00225         tfB.changeRate(2.0*accelB, 2, NEW_REFERENCE_TIME);
00226 
00227         CPPUNIT_ASSERT_DOUBLES_EQUAL( 125.0 + 50*0 + 20/2.0*0*0, tfA.evaluate(5), DELTA);
00228         CPPUNIT_ASSERT_DOUBLES_EQUAL( 125.0 + 50*5 + 20/2.0*5*5, tfA.evaluate(10), DELTA);
00229 
00230         CPPUNIT_ASSERT_DOUBLES_EQUAL( 150.0 - 5*0 - 20.0/2.0*0*0, tfB.evaluate(5), DELTA);
00231         CPPUNIT_ASSERT_DOUBLES_EQUAL( 150.0 - 5*5 - 20.0/2.0*5*5, tfB.evaluate(10), DELTA);
00232     }
00233 
00234     /*
00235       void testWriteAndReadToStream() {
00236           float a[] = {1.0, 2.0, 10.0};
00237           float b[] = {50, 45, -10.0};
00238           tPolynomial<nMessageMock> tfA(a, sizeof(a)/sizeof(a[0]));
00239           tPolynomial<nMessageMock> tfB(b, sizeof(b)/sizeof(b[0]));
00240           tPolynomial<nMessageMock> tfC;
00241 
00242           nMessageMock messageMock;
00243 
00244           CPPUNIT_ASSERT( !(tfA == tfB) );
00245 
00246           messageMock << tfA;
00247           messageMock.receive();
00248           messageMock >> tfB;
00249 
00250           CPPUNIT_ASSERT( tfA == tfB );
00251       }
00252     */
00253 
00258   void testParse() {
00259     tPolynomial<nMessageMock> tp;
00260 
00261     // Happy sunshine flow
00262     {
00263       tp.parse("");
00264       CPPUNIT_ASSERT( tpEmpty == tp );
00265       
00266       tp.parse("2");
00267       CPPUNIT_ASSERT( tpTwo == tp );
00268       
00269       tp.parse("3;5;7;11");
00270       float b[] = {3, 5, 7, 11};
00271       tPolynomial<nMessageMock> tpB(b, sizeof(b)/sizeof(b[0]));
00272       CPPUNIT_ASSERT( tpB == tp );
00273       
00274       // Try with a smaller polynomial now, ensuring that there is no leakage
00275       tp.parse("3;5");
00276       float a[] = {3, 5};
00277       tPolynomial<nMessageMock> tpA(a, sizeof(a)/sizeof(a[0]));
00278       CPPUNIT_ASSERT( tpA == tp );
00279 
00280       // Quick notation
00281       tp.parse(";;3;5");
00282       float c[] = {0, 0, 3, 5};
00283       tPolynomial<nMessageMock> tpC(c, sizeof(c)/sizeof(c[0]));
00284       CPPUNIT_ASSERT( tpC == tp );
00285 
00286     }
00287 
00288     // not the happy sunshine flow
00289     {
00290       // no elements should be created
00291       tp.parse(";;;;;");
00292       CPPUNIT_ASSERT( tpEmpty == tp );
00293       
00294       // quick notation with extra delimiters
00295       tp.parse(";;3;5;;");
00296       float a[] = {0, 0, 3, 5};
00297       tPolynomial<nMessageMock> tpA(a, sizeof(a)/sizeof(a[0]));
00298       CPPUNIT_ASSERT( tpA == tp );
00299 
00300       // non-numerical information
00301       tp.parse("Hello world!;0;");
00302       CPPUNIT_ASSERT( tpEmpty == tp );
00303     }
00304   }
00305 
00306 
00307   void testTranslate() {
00308     tPolynomial<nMessageMock> tpSource("0;0;1");
00309     tPolynomial<nMessageMock> tpRes("9;6;1");
00310     std::cout << std::endl;
00311     std::cout << "translate" << std::endl;
00312     std::cout << tpSource.toString() << std::endl;
00313     std::cout << tpSource.translate(3).toString() << std::endl;
00314     std::cout << tpRes.toString() << std::endl;
00315     CPPUNIT_ASSERT( tpRes == tpSource.translate(3) );
00316   }
00317 
00318   void testSubstitute() {
00319     // This test will use the following notation:
00320     // tpResultat == tpTransformer.substitute(tpValue);
00321     tPolynomial<nMessageMock> tpValue;
00322     tPolynomial<nMessageMock> tpTransformer;
00323     tPolynomial<nMessageMock> tpResultat;
00324 
00325 
00326     // Similar size
00327     tpValue.parse("3;5");
00328     tpTransformer.parse("7;9");
00329     // V(x) = {3, 5}
00330     // T(y) = {7, 9}
00331     // T(V(x)) :
00332     // a + b*y
00333     // 7 + 9*y
00334     // 7 + 9*(3 + 5*x)
00335     // 7 + 27 + 45*x
00336     // 34 + 45*x
00337     tpResultat.parse("34;45");
00338     CPPUNIT_ASSERT( tpResultat == tpTransformer.substitute(tpValue) );
00339 
00340     // Different size : Much longer value
00341     tpValue.parse("3;5;7;11;13;17");
00342     tpTransformer.parse("7;11");
00343     // V(x) = {3, 5, 7, 11, 13, 17}
00344     // T(y) = {7, 11}
00345     // T(V(x)) :
00346     // a + b*y
00347     // 7 + 11*y
00348     // 7 + 11*(3 + 5*x + 7*x^2 + 11*x^3 + 13*x^4 + 17*x^5)
00349     // 7 + 33 + 55*x + 77*x^2 + 121*x^3 + 143*x^4 + 187*x^5
00350     // 40 + 55*x + 77*x^2 + 121*x^3 + 143*x^4 + 187*x^5
00351     tpResultat.parse("40;55;77;121;143;187");
00352     CPPUNIT_ASSERT( tpResultat == tpTransformer.substitute(tpValue) );
00353 
00354     // Different size : Much longer transformer
00355     tpValue.parse("3;5");
00356     tpTransformer.parse("3;5;7;11;13;17");
00357     // V(x) = {3, 5}
00358     // T(y) = {3, 5, 7, 11, 13, 17}
00359     // T(V(x)) :
00360     // a + b*y + c*y^2 + d*y^3 + e*y^4 + f*y^5
00361     // 3 + 5*y + 7*y^2 + 11*y^3 + 13*y^4 + 17*y^5
00362     // 3 + 5*(3 + 5*x) + 7*(3 + 5*x)^2 + 11*(3 + 5*x)^3 + 13*(3 + 5*x)^4 + 17*(3 + 5*x)^5
00363     // computed using yacas:
00364     // In> Expand(3 + 5*(3 + 5*x) + 7*(3 + 5*x)^2 + 11*(3 + 5*x)^3 + 13*(3 + 5*x)^4 + 17*(3 + 5*x)^5)
00365     // Out> 53125*x^5+167500*x^4+212125*x^3+134950*x^2+43165*x+5562
00366     tpResultat.parse("5562;43165;134950;212125;167500;53125");
00367     CPPUNIT_ASSERT( tpResultat == tpTransformer.substitute(tpValue) );
00368 
00369     // Substitution on a polynomial which reference point has been moved:
00370     // Source@t=0 : {0; 1} ;; both are equivalent, only the ref point has been moved
00371     // Source@t=3 : {3; 1}
00372     // Transform  : {0;0;1} ;; the transform shouldn't have any ref point
00373     tPolynomial<nMessageMock> tpSourceA("0;1");
00374     tPolynomial<nMessageMock> tpSourceB = tpSourceA.adaptToNewReferenceVarValue(3);
00375     tPolynomial<nMessageMock> tpTransform("0;0;1");
00376 
00377     std::cout << std::endl << "#######"  << std::endl;
00378     std::cout << tpSourceA.toString() << std::endl;
00379     std::cout << tpSourceB.toString() << std::endl;
00380     std::cout << tpTransform.substitute(tpSourceA).toString() << std::endl;
00381     std::cout << tpTransform.substitute(tpSourceB).toString() << std::endl;
00382     std::cout << tpTransform.substitute(tpSourceA).adaptToNewReferenceVarValue(3).toString() << std::endl;
00383 
00384   }
00385 
00386 };
00387 
00388 CPPUNIT_TEST_SUITE_REGISTRATION( tPolynomialTest );

Generated on Sat Mar 15 22:56:02 2008 for Armagetron Advanced by  doxygen 1.5.4