Code-Eli  0.3.6
poly_math_test_suite.hpp
Go to the documentation of this file.
1 /*********************************************************************************
2 * Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * David D. Marshall - initial code and implementation
11 ********************************************************************************/
12 
13 #ifndef poly_math_test_suite_hpp
14 #define poly_math_test_suite_hpp
15 
16 #include <typeinfo> // typeid
17 #include <string> // std::string
18 #include <sstream> // std::stringstream
19 #include <iomanip> // std::setw
20 #include <limits> // std::numeric_limits
21 
23 
24 template<typename data__>
25 class poly_math_test_suite : public Test::Suite
26 {
27  protected:
28  void AddTests(const int &)
29  {
36  }
37 
38  void AddTests(const float &)
39  {
46  }
47 
48  void AddTests(const double &)
49  {
56  }
57 
58  void AddTests(const long double &)
59  {
66  }
67 
68  public:
70  {
71  // add the tests
72  AddTests(data__());
73  }
75  {
76  }
77 
78  private:
79 
80  void add_test()
81  {
83 
84  // set coefficients
85  coef1 << 0, 0, 8, 4;
86  coef2 << 1, 2, 3;
87 
88  // create two polynomials
89  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr;
90  typename eli::mutil::poly::polynomial<data__>::data_type eval_out, eval_ref;
91  typename eli::mutil::poly::polynomial<data__>::data_type x[5] = {0, 1, 6, 9, 15};
92 
93  // create polynomial that is addition of two other polynomials
94  pr.add(p1, p2);
95 
96  // test resulting polynomial at several points
97  for (size_t i=0; i<5; ++i)
98  {
99  // test point
100  eval_out=pr.f(x[i]);
101  eval_ref=p1.f(x[i]) + p2.f(x[i]);
102  TEST_ASSERT(eval_out==eval_ref);
103  }
104  }
105 
107  {
108  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(3);
109 
110  // set coefficients
111  coef1 << 0, 0, 8, 4;
112  coef2 << 1, 2, 3;
113 
114  // create polynomial that is addition of two other polynomials
115  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr;
116  typename eli::mutil::poly::polynomial<data__>::data_type eval_out, eval_ref;
117  typename eli::mutil::poly::polynomial<data__>::data_type x[5] = {0, 1, 6, 9, 15};
118 
119  // create polynomial that is subtraction of two other polynomials
120  pr.subtract(p1, p2);
121 
122  // test resulting polynomial at several points
123  for (size_t i=0; i<5; ++i)
124  {
125  // test point
126  eval_out=pr.f(x[i]);
127  eval_ref=p1.f(x[i]) - p2.f(x[i]);
128  TEST_ASSERT(eval_out==eval_ref);
129  }
130  }
131 
133  {
134  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(3);
135 
136  // set coefficients
137  coef1 << 0, 0, 8, 4;
138  coef2 << 1, 2, 3;
139 
140  // create polynomial that is addition of two other polynomials
141  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr;
142  typename eli::mutil::poly::polynomial<data__>::data_type eval_out, eval_ref;
143  typename eli::mutil::poly::polynomial<data__>::data_type x[5] = {0, 1, 6, 9, 15};
144 
145  // create polynomial that is multiplication of two other polynomials
146  pr.multiply(p1, p2);
147 
148  // test resulting polynomial at several points
149  for (size_t i=0; i<5; ++i)
150  {
151  // test point
152  eval_out=pr.f(x[i]);
153  eval_ref=p1.f(x[i]) * p2.f(x[i]);
154  TEST_ASSERT(eval_out==eval_ref);
155  }
156  }
157 
158  void divide_test()
159  {
160  // test against known results: simple test
161  {
162  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(3), coef_q(2), coef_r(2), coef_out;
163 
164  // set coefficients
165  coef1 << -3, 4, -2, 3;
166  coef2 << 3, 3, 1;
167  coef_q <<-11, 3;
168  coef_r << 30, 28;
169 
170  // create polynomials
171  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
172 
173  // create polynomial that is division of two other polynomials
174  pr.divide(prem, p1, p2);
175 
176  // test answers
177  pr.get_coefficients(coef_out);
178  if (coef_out.rows()==coef_q.rows())
179  {
180  TEST_ASSERT(coef_out==coef_q);
181  }
182  else
183  {
184  TEST_ASSERT_MSG(false, "Quotient not correct degree");
185  }
186  prem.get_coefficients(coef_out);
187  if (coef_out.rows()==coef_r.rows())
188  {
189  TEST_ASSERT(coef_out==coef_r);
190  }
191  else
192  {
193  TEST_ASSERT_MSG(false, "Remainder not correct degree");
194  }
195  }
196 
197  // test against known results: this tests zeros in the numerator
198  {
199  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(2), coef_q(3), coef_r(1), coef_out;
200 
201  // set coefficients
202  coef1 <<-1, 0, 0, 1;
203  coef2 << 2, 1;
204  coef_q << 4,-2, 1;
205  coef_r <<-9;
206 
207  // create polynomials
208  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
209 
210  // create polynomial that is division of two other polynomials
211  pr.divide(prem, p1, p2);
212 
213  // test answers
214  pr.get_coefficients(coef_out);
215  if (coef_out.rows()==coef_q.rows())
216  {
217  TEST_ASSERT(coef_out==coef_q);
218  }
219  else
220  {
221  TEST_ASSERT_MSG(false, "Quotient not correct degree");
222  }
223  prem.get_coefficients(coef_out);
224  if (coef_out.rows()==coef_r.rows())
225  {
226  TEST_ASSERT(coef_out==coef_r);
227  }
228  else
229  {
230  TEST_ASSERT_MSG(false, "Remainder not correct degree");
231  }
232  }
233 
234  // test against know results: this tests multiple steps in the division
235  {
236  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(6), coef2(2), coef_q(5), coef_r(1), coef_out;
237 
238  // set coefficients
239  coef1 <<-1, 0, 0, 0, 0,-5;
240  coef2 << 5, 5;
241  coef_q <<-1, 1,-1, 1,-1;
242  coef_r << 4;
243 
244  // create polynomials
245  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
246 
247  // create polynomial that is division of two other polynomials
248  pr.divide(prem, p1, p2);
249 
250  // test answers
251  pr.get_coefficients(coef_out);
252  if (coef_out.rows()==coef_q.rows())
253  {
254  TEST_ASSERT(coef_out==coef_q);
255  }
256  else
257  {
258  TEST_ASSERT_MSG(false, "Quotient not correct degree");
259  }
260  prem.get_coefficients(coef_out);
261  if (coef_out.rows()==coef_r.rows())
262  {
263  TEST_ASSERT(coef_out==coef_r);
264  }
265  else
266  {
267  TEST_ASSERT_MSG(false, "Remainder not correct degree");
268  }
269  }
270 
271  // test against know results: this tests with no remainder
272  {
273  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(3), coef_q(2), coef_r(2), coef_out;
274 
275  // set coefficients
276  coef1 <<-15, 3,-5, 1;
277  coef2 << 3, 0, 1;
278  coef_q << -5, 1;
279  coef_r << 0, 0;
280 
281  // create polynomials
282  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
283 
284  // create polynomial that is division of two other polynomials
285  pr.divide(prem, p1, p2);
286 
287  // test answers
288  pr.get_coefficients(coef_out);
289  if (coef_out.rows()==coef_q.rows())
290  {
291  TEST_ASSERT(coef_out==coef_q);
292  }
293  else
294  {
295  TEST_ASSERT_MSG(false, "Quotient not correct degree");
296  }
297  prem.get_coefficients(coef_out);
298  if (coef_out.rows()==coef_r.rows())
299  {
300  TEST_ASSERT(coef_out==coef_r);
301  }
302  else
303  {
304  TEST_ASSERT_MSG(false, "Remainder not correct degree");
305  }
306  }
307 
308  // test against know results: this tests leading zeros in divisor
309  {
310  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(6), coef2(3), coef_q(5), coef_r(2), coef_out;
311 
312  // set coefficients
313  coef1 <<-1, 0, 0, 0, 0,-5;
314  coef2 << 5, 5, 0;
315  coef_q <<-1, 1,-1, 1,-1;
316  coef_r << 4, 0;
317 
318  // create polynomials
319  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
320 
321  // create polynomial that is division of two other polynomials
322  pr.divide(prem, p1, p2);
323 
324  // test answers
325  pr.get_coefficients(coef_out);
326  if (coef_out.rows()==coef_q.rows())
327  {
328  TEST_ASSERT(coef_out==coef_q);
329  }
330  else
331  {
332  TEST_ASSERT_MSG(false, "Quotient not correct degree");
333  }
334  prem.get_coefficients(coef_out);
335  if (coef_out.rows()==coef_r.rows())
336  {
337  TEST_ASSERT(coef_out==coef_r);
338  }
339  else
340  {
341  TEST_ASSERT_MSG(false, "Remainder not correct degree");
342  }
343  }
344 
345  {
346  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef1(4), coef2(3);
347 
348  // set control points
349  coef1 << 1, 1, 1, 1;
350  coef2 << 1, 1, 0;
351 
352  // create two polynomials
353  eli::mutil::poly::polynomial<data__> p1(coef1), p2(coef2), pr, prem;
354  typename eli::mutil::poly::polynomial<data__>::data_type eval_out, eval_ref;
355  typename eli::mutil::poly::polynomial<data__>::data_type x[5] = {0, 1, 6, 9, 15};
356 
357  // create polynomial that is division of two other polynomials
358  pr.divide(prem, p1, p2);
359 
360  // test resulting polynomials at several points
361  for (size_t i=0; i<5; ++i)
362  {
363  // test point
364  eval_out=pr.f(x[i])+prem.f(x[i])/p2.f(x[i]);
365  eval_ref=p1.f(x[i])/p2.f(x[i]);
366  TEST_ASSERT(eval_out==eval_ref);
367  }
368  }
369  }
370 
372  {
373  // create polynomial with 1 root
374  {
375  data__ roots(2);
377 
378  TEST_ASSERT(p.f(roots)==0);
379  }
380 
381  // create polynomial with 2 roots
382  {
383  data__ roots[2] = {2, -3};
384  eli::mutil::poly::polynomial<data__> p(roots[0], roots[1]);
385 
386  TEST_ASSERT(p.f(roots[0])==0);
387  TEST_ASSERT(p.f(roots[1])==0);
388  }
389 
390  // create polynomial with 3 roots
391  {
392  data__ roots[3] = {2, -3, 5};
393  eli::mutil::poly::polynomial<data__> p(roots[0], roots[1], roots[2]);
394 
395  TEST_ASSERT(p.f(roots[0])==0);
396  TEST_ASSERT(p.f(roots[1])==0);
397  TEST_ASSERT(p.f(roots[2])==0);
398  }
399 
400  // create polynomial with 4 roots
401  {
402  data__ roots[4] = {2, -3, 5, 7};
403  eli::mutil::poly::polynomial<data__> p(roots[0], roots[1], roots[2], roots[3]);
404 
406  p.get_coefficients(c);
407 
408  TEST_ASSERT(p.f(roots[0])==0);
409  TEST_ASSERT(p.f(roots[1])==0);
410  TEST_ASSERT(p.f(roots[2])==0);
411  TEST_ASSERT(p.f(roots[3])==0);
412  }
413 
414  // create polynomial with 4 roots
415  {
416  data__ roots[4] = {2, -3, 5, 7};
417  eli::mutil::poly::polynomial<data__> p(roots, roots+4);
418 
419  TEST_ASSERT(p.f(roots[0])==0);
420  TEST_ASSERT(p.f(roots[1])==0);
421  TEST_ASSERT(p.f(roots[2])==0);
422  TEST_ASSERT(p.f(roots[3])==0);
423  }
424 
425  // create polynomial with many roots
426  {
427  int i, nr;
428 
429  // NOTE: different types fail the below tests at different number of roots
430  if (typeid(data__)==typeid(float))
431  nr=5;
432  else if (typeid(data__)==typeid(double))
433  nr=7;
434  else if (typeid(data__)==typeid(long double))
435  nr=9;
436  else if (typeid(data__)==typeid(int)) // for computational time reasons this is limited
437  nr=9; // but it worked for 30 and took 12 minutes :(
438  else
439  nr=15;
440 
441  std::vector<data__> roots(nr);
442  roots[0]=2;
443  for (i=1; i<static_cast<int>(roots.size()); ++i)
444  roots[i]=3*i-roots[i-1];
445 
446  eli::mutil::poly::polynomial<data__> p(roots.begin(), roots.end());
447  for (i=0; i<static_cast<int>(roots.size()); ++i)
448  {
449  TEST_ASSERT(p.f(roots[i])==0);
450  }
451  }
452  }
453 
455  {
457 
458  // set coefficients
459  coef_in << 3, 5, 1, 8;
460 
462  typename eli::mutil::poly::polynomial<data__>::data_type eval_out, eval_ref;
464 
465  {
466  // test 1st derivative function
468 
469  if (p2==0)
470  {
471  TEST_ASSERT_MSG(false, "Null derivative function");
472  }
473  else
474  {
475  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef_ref, coef_out;
476 
477  coef_ref = coef_in;
478 
479  // compare coefficients
480  p2->get_coefficients(coef_out);
481  if (coef_out.rows()==coef_ref.rows())
482  {
483  TEST_ASSERT(coef_out==coef_ref);
484  }
485  else
486  {
487  TEST_ASSERT_MSG(false, "Degree not correct degree");
488  }
489  }
490  delete p2;
491  }
492 
493  {
494  // test 1st derivative at points
495  t=static_cast<data__>(0);
496  eval_out=p1.fp(t);
497  eval_ref=1*coef_in(1);
498  TEST_ASSERT(eval_out==eval_ref);
499  t=static_cast<data__>(1);
500  eval_out=p1.fp(t);
501  eval_ref=static_cast<data__>(31);
502  TEST_ASSERT(eval_out==eval_ref);
503  t=static_cast<data__>(11);
504  eval_out=p1.fp(t);
505  eval_ref=static_cast<data__>(2931);
506  TEST_ASSERT(eval_out==eval_ref);
507 
508  // test 1st derivative function
510 
511  if (p2==0)
512  {
513  TEST_ASSERT_MSG(false, "Null derivative function");
514  }
515  else
516  {
517  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef_ref(3), coef_out;
518 
519  coef_ref << 1*5, 2*1, 3*8;
520 
521  // compare coefficients
522  p2->get_coefficients(coef_out);
523  if (coef_out.rows()==coef_ref.rows())
524  {
525  TEST_ASSERT(coef_out==coef_ref);
526  }
527  else
528  {
529  TEST_ASSERT_MSG(false, "Degree not correct degree");
530  }
531  }
532  delete p2;
533  }
534 
535  {
536  // test 2nd derivative at points
537  t=static_cast<data__>(0);
538  eval_out=p1.fpp(t);
539  eval_ref=2*1*coef_in(2);
540  TEST_ASSERT(eval_out==eval_ref);
541  t=static_cast<data__>(1);
542  eval_out=p1.fpp(t);
543  eval_ref=static_cast<data__>(50);
544  TEST_ASSERT(eval_out==eval_ref);
545  t=static_cast<data__>(11);
546  eval_out=p1.fpp(t);
547  eval_ref=static_cast<data__>(530);
548  TEST_ASSERT(eval_out==eval_ref);
549 
550  // test 2nd derivative function
552 
553  if (p2==0)
554  {
555  TEST_ASSERT_MSG(false, "Null derivative function");
556  }
557  else
558  {
559  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef_ref(2), coef_out;
560 
561  coef_ref << (2*1)*1, (3*2)*8;
562 
563  // compare coefficients
564  p2->get_coefficients(coef_out);
565  if (coef_out.rows()==coef_ref.rows())
566  {
567  TEST_ASSERT(coef_out==coef_ref);
568  }
569  else
570  {
571  TEST_ASSERT_MSG(false, "Degree not correct degree");
572  }
573  }
574  delete p2;
575  }
576 
577  {
578  // test 3rd derivative at points
579  t=static_cast<data__>(0);
580  eval_out=p1.fppp(t);
581  eval_ref=3*2*1*coef_in(3);
582  TEST_ASSERT(eval_out==eval_ref);
583  t=static_cast<data__>(1);
584  eval_out=p1.fppp(t);
585  eval_ref=static_cast<data__>(48);
586  TEST_ASSERT(eval_out==eval_ref);
587  t=static_cast<data__>(11);
588  eval_out=p1.fppp(t);
589  eval_ref=static_cast<data__>(48);
590  TEST_ASSERT(eval_out==eval_ref);
591 
592  // test 3rd derivative function
594 
595  if (p2==0)
596  {
597  TEST_ASSERT_MSG(false, "Null derivative function");
598  }
599  else
600  {
601  typename eli::mutil::poly::polynomial<data__>::coefficient_type coef_ref(1), coef_out;
602 
603  coef_ref << (3*2*1)*8;
604 
605  // compare coefficients
606  p2->get_coefficients(coef_out);
607  if (coef_out.rows()==coef_ref.rows())
608  {
609  TEST_ASSERT(coef_out==coef_ref);
610  }
611  else
612  {
613  TEST_ASSERT_MSG(false, "Degree not correct degree");
614  }
615  }
616  delete p2;
617  }
618  }
619 
620 };
621 
622 #endif
poly_math_test_suite()
Definition: poly_math_test_suite.hpp:69
void AddTests(const double &)
Definition: poly_math_test_suite.hpp:48
data_type fp(const data_type &t) const
Definition: polynomial.hpp:221
void divide_test()
Definition: poly_math_test_suite.hpp:158
void multiply(const polynomial< data_type > &p1, const polynomial< data_type > &p2)
Definition: polynomial.hpp:383
data_type f(const data_type &t) const
Definition: polynomial.hpp:199
void AddTests(const long double &)
Definition: poly_math_test_suite.hpp:58
void add_test()
Definition: poly_math_test_suite.hpp:80
~poly_math_test_suite()
Definition: poly_math_test_suite.hpp:74
void subtract_test()
Definition: poly_math_test_suite.hpp:106
Definition: polynomial.hpp:31
Eigen::Matrix< data_type, Eigen::Dynamic, 1 > coefficient_type
Definition: polynomial.hpp:35
void subtract(const polynomial< data_type > &p1, const polynomial< data_type > &p2)
Definition: polynomial.hpp:360
void creation_test()
Definition: poly_math_test_suite.hpp:371
void add(const polynomial< data_type > &p1, const polynomial< data_type > &p2)
Definition: polynomial.hpp:337
data_type fpp(const data_type &t) const
Definition: polynomial.hpp:244
void multiply_test()
Definition: poly_math_test_suite.hpp:132
void get_coefficients(coefficient_type &aout) const
Definition: polynomial.hpp:86
void divide(polynomial< data_type > &prem, const polynomial< data_type > &p1, const polynomial< data_type > &p2)
Definition: polynomial.hpp:410
data_type fppp(const data_type &t) const
Definition: polynomial.hpp:267
void AddTests(const float &)
Definition: poly_math_test_suite.hpp:38
void AddTests(const int &)
Definition: poly_math_test_suite.hpp:28
Definition: poly_math_test_suite.hpp:25
void derivative_test()
Definition: poly_math_test_suite.hpp:454
data__ data_type
Definition: polynomial.hpp:34