Code-Eli  0.3.6
simpson_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 simpson_test_suite_hpp
14 #define simpson_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 #include "eli/constants/math.hpp"
24 
25 
26 template <typename data__>
28 {
29  data__ operator()(const data__ &x) {return std::exp(x);}
30 };
31 
32 // default is for bad values
33 template <typename data__>
35 {
36  ap.recursion_depth=0;
37  ap.function_count=0;
38  ap.coarse_value=-1;
39  ap.fine_value=-1;
40  ap.approximate_error=-1;
41 }
42 
43 template <>
45 {
46  ap.recursion_depth=2;
47  ap.function_count=9;
48  ap.coarse_value=17.3731117248535f;
49  ap.fine_value=17.3676300048828f;
50 #ifdef _MSC_VER
51 # ifdef _WIN64
52  ap.approximate_error=5.48267344129272e-05f;
53 # else
54  ap.approximate_error=5.4817199e-05f;
55 # endif
56 #else
57  ap.approximate_error=5.48267344129272e-05f;
58 #endif
59 }
60 
61 template <>
63 {
64  ap.recursion_depth=5;
65  ap.function_count=65;
66  ap.coarse_value=17.367256566284723363;
67  ap.fine_value=17.367255186732954542;
68  ap.approximate_error=1.3795517685433190629e-08;
69 }
70 
71 template <>
73 {
74 #ifdef _MSC_VER
75  ap.recursion_depth=5;
76  ap.function_count=65;
77  ap.coarse_value=17.367256566284723363L;
78  ap.fine_value=17.367255186732954542L;
79  ap.approximate_error=1.3795517685433190629e-08L;
80 #else
81  ap.recursion_depth=6;
82  ap.function_count=129;
83  ap.coarse_value=17.367255186732954673478612761527983820997178554534912109375L;
84  ap.fine_value=17.36725510047939464303157208746597461868077516555786133L;
85 # ifdef __INTEL_COMPILER
86  ap.approximate_error=8.6253560028725869727e-10L;
87 # else
88  ap.approximate_error=8.62535600286716596198481699594144637825189614321885756e-10L;
89 # endif
90 #endif
91 }
92 
93 template<typename data__>
94 class simpson_test_suite : public Test::Suite
95 {
96  protected:
97  void AddTests(const float &)
98  {
102  }
103 
104  void AddTests(const double &)
105  {
109  }
110 
111  void AddTests(const long double &)
112  {
116  }
117 
118  public:
120  {
121  // add the tests
122  AddTests(data__());
123  }
125  {
126  }
127 
128  private:
130  {
131  data__ x1(1.0), x2(3.0), F_exact(std::exp(x2)-std::exp(x1)), F_quad;
132 
133  {
134  size_t n, npts(1001);
135  std::vector<data__> x(npts), f(npts);
136 
137  // set the x points
138  for (n=0; n<npts; ++n)
139  x[n]=(n)*(x2-x1)/(npts-1)+x1;
140 
141  // set the function points
142  for (n=0; n<npts; ++n)
143  f[n]=std::exp(x[n]);
144 
145  // find the integral approximation
147 
148  F_quad=quad(x[1]-x[0], f.begin(), f.end());
149 
150  if (typeid(data__)==typeid(float))
151  {
152  TEST_ASSERT_DELTA(1, F_quad/F_exact, 2e-5);
153  }
154  else
155  {
156  TEST_ASSERT_DELTA(1, F_quad/F_exact, 1e-13);
157  }
158  }
159 
160 // bug in release build for clang current version (3.3) and older
161 #ifdef NDEBUG
162 # ifdef __clang__
163 # if ( (__clang_major__ < 3) || ((__clang_major__==3) && (__clang_minor__<=3)) )
164  TEST_ASSERT_MSG(false, "Clang release build bug cannot build this test.");
165  return;
166 # endif
167 # endif
168 #endif
169  {
170  size_t n, npts(1000);
171  std::vector<data__> x(npts), f(npts);
172 
173  // set the x points
174  for (n=0; n<npts; ++n)
175  x[n]=(n)*(x2-x1)/(npts-1)+x1;
176 
177  // set the function points
178  for (n=0; n<npts; ++n)
179  f[n]=std::exp(x[n]);
180 
181  // find the integral approximation
183 
184  F_quad=quad(x[1]-x[0], f.begin(), f.end());
185 
186  if (typeid(data__)==typeid(float))
187  {
188  TEST_ASSERT_DELTA(1, F_quad/F_exact, 1e-5);
189  }
190  else
191  {
192  TEST_ASSERT_DELTA(1, F_quad/F_exact, 1e-12);
193  }
194  }
195  }
196 
198  {
199  data__ x1(1.0), x2(3.0), F_exact(std::exp(x2)-std::exp(x1)), F_quad;
200 
201  {
202  size_t n, npts(1001);
203  std::vector<data__> x(npts), f(npts);
204 
205  // set the x points
206  for (n=0; n<npts; ++n)
207  x[n]=sin(eli::constants::math<data__>::pi_by_two()*n/(npts-1))*(x2-x1)+x1;
208 
209  // set the function points
210  for (n=0; n<npts; ++n)
211  f[n]=std::exp(x[n]);
212 
213  // find the integral approximation
215 
216  F_quad=quad(x.begin(), f.begin(), f.end());
217 
218  if (typeid(data__)==typeid(float))
219  {
220  TEST_ASSERT_DELTA(1, F_quad/F_exact, 3e-7);
221  }
222  else
223  {
224  TEST_ASSERT_DELTA(1, F_quad/F_exact, 5e-13);
225  }
226  }
227 
228  {
229  size_t n, npts(1000);
230  std::vector<data__> x(npts), f(npts);
231 
232  // set the x points
233  for (n=0; n<npts; ++n)
234  x[n]=sin(eli::constants::math<data__>::pi_by_two()*n/(npts-1))*(x2-x1)+x1;
235 
236  // set the function points
237  for (n=0; n<npts; ++n)
238  f[n]=std::exp(x[n]);
239 
240  // find the integral approximation
242 
243  F_quad=quad(x.begin(), f.begin(), f.end());
244 
245  if (typeid(data__)==typeid(float))
246  {
247  TEST_ASSERT_DELTA(1, F_quad/F_exact, 9e-7);
248  }
249  else
250  {
251  TEST_ASSERT_DELTA(1, F_quad/F_exact, 5e-13);
252  }
253  }
254  }
255 
257  {
258  data__ x0(1.0), x1(3.0), F_exact(std::exp(x1)-std::exp(x0)), F_quad, tol(std::numeric_limits<data__>::epsilon());
259 
260  // find the integral approximation
263 
264  // integrate with depth as termination case
265  ap.tolerance=tol;
266  ap.max_depth=2;
267  F_quad=quad(exp_functor<data__>(), x0, x1, ap);
268  TEST_ASSERT(ap.recursion_depth==ap.max_depth);
269  TEST_ASSERT(std::abs(1 - F_quad/F_exact)>ap.tolerance);
270 
271  // integrate with tolerance as termination case
272  ap.tolerance=tol;
273  ap.max_depth=23;
274  F_quad=quad(exp_functor<data__>(), x0, x1, ap);
275  TEST_ASSERT(ap.recursion_depth<ap.max_depth);
276  TEST_ASSERT_DELTA(1, F_quad/F_exact, ap.tolerance);
277 
278  // integrate to a known state
279  ap=ap2;
280  F_quad=quad(exp_functor<data__>(), x0, x1, ap);
281  get_reference_adaptive_params<data__>(ap_ref);
282 
283  TEST_ASSERT(ap.max_depth==30);
284  TEST_ASSERT(ap.tol_factor==1.25);
285  TEST_ASSERT(ap.error_factor==100.0);
286  TEST_ASSERT(ap.tolerance==ap_ref.tolerance);
287  TEST_ASSERT_DELTA(1, F_quad/F_exact, ap.tolerance);
288  TEST_ASSERT(ap.recursion_depth==ap_ref.recursion_depth);
289  TEST_ASSERT(ap.function_count==ap_ref.function_count);
290  TEST_ASSERT_DELTA(1, ap.coarse_value/ap_ref.coarse_value, std::numeric_limits<data__>::epsilon());
291  TEST_ASSERT_DELTA(1, ap.fine_value/ap_ref.fine_value, std::numeric_limits<data__>::epsilon());
292 
293  // Visual Studio 2012 & 2013 32-bit build float calculation is way off
294  data__ mult_factor(1);
295 #ifdef _MSC_VER
296 # if (((_MSC_VER==1700) || (_MSC_VER==1800)) && !defined(_WIN64))
297  if (typeid(data__)==typeid(float))
298  {
299  mult_factor=static_cast<data__>(1.5e3);
300  }
301 # endif
302 #endif
303  TEST_ASSERT_DELTA(1, ap.approximate_error/ap_ref.approximate_error, mult_factor*std::numeric_limits<data__>::epsilon());
304  }
305 };
306 
307 #endif
data__ coarse_value
Definition: simpson.hpp:33
void get_reference_adaptive_params< float >(typename eli::mutil::quad::simpson< float >::adaptive_params &ap)
Definition: simpson_test_suite.hpp:44
void adaptive_test()
Definition: simpson_test_suite.hpp:256
data__ tolerance
Definition: simpson.hpp:33
Definition: math.hpp:25
size_t function_count
Definition: simpson.hpp:32
void get_reference_adaptive_params< long double >(typename eli::mutil::quad::simpson< long double >::adaptive_params &ap)
Definition: simpson_test_suite.hpp:72
data__ tol_factor
Definition: simpson.hpp:33
void get_reference_adaptive_params(typename eli::mutil::quad::simpson< data__ >::adaptive_params &ap)
Definition: simpson_test_suite.hpp:34
Definition: simpson_test_suite.hpp:94
~simpson_test_suite()
Definition: simpson_test_suite.hpp:124
void get_reference_adaptive_params< double >(typename eli::mutil::quad::simpson< double >::adaptive_params &ap)
Definition: simpson_test_suite.hpp:62
void AddTests(const double &)
Definition: simpson_test_suite.hpp:104
void uniform_points_test()
Definition: simpson_test_suite.hpp:129
size_t recursion_depth
Definition: simpson.hpp:32
void nonuniform_points_test()
Definition: simpson_test_suite.hpp:197
simpson_test_suite()
Definition: simpson_test_suite.hpp:119
void AddTests(const long double &)
Definition: simpson_test_suite.hpp:111
void AddTests(const float &)
Definition: simpson_test_suite.hpp:97
Definition: simpson_test_suite.hpp:27
data__ approximate_error
Definition: simpson.hpp:33
data__ operator()(const data__ &x)
Definition: simpson_test_suite.hpp:29
data__ error_factor
Definition: simpson.hpp:33
size_t max_depth
Definition: simpson.hpp:32
Definition: simpson.hpp:27
data__ fine_value
Definition: simpson.hpp:33