mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
527 lines
58 KiB
HTML
527 lines
58 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>Testing</title>
|
|
<link rel="stylesheet" href="../../math.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
|
<link rel="home" href="../../index.html" title="Math Toolkit 3.0.0">
|
|
<link rel="up" href="../special_tut.html" title="Tutorial: How to Write a New Special Function">
|
|
<link rel="prev" href="special_tut_impl.html" title="Implementation">
|
|
<link rel="next" href="../relative_error.html" title="Relative Error">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<table cellpadding="2" width="100%"><tr>
|
|
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
|
|
<td align="center"><a href="../../../../../../index.html">Home</a></td>
|
|
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
|
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="special_tut_impl.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../special_tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../relative_error.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="math_toolkit.special_tut.special_tut_test"></a><a class="link" href="special_tut_test.html" title="Testing">Testing</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
We work under the assumption that untested code doesn't work, so some tests
|
|
for your new special function are in order, we'll divide these up in to 3
|
|
main categories:
|
|
</p>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h0"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.spot_tests"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.spot_tests">Spot Tests</a>
|
|
</h5>
|
|
<p>
|
|
Spot tests consist of checking that the expected exception is generated when
|
|
the inputs are in error (or otherwise generate undefined values), and checking
|
|
any special values. We can check for expected exceptions with <code class="computeroutput"><span class="identifier">BOOST_CHECK_THROW</span></code>, so for example if it's
|
|
a domain error for the last parameter to be outside the range <code class="computeroutput"><span class="special">[</span><span class="number">0</span><span class="special">,</span><span class="number">1</span><span class="special">]</span></code> then we
|
|
might have:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">BOOST_CHECK_THROW</span><span class="special">(</span><span class="identifier">my_special</span><span class="special">(</span><span class="number">0</span><span class="special">,</span> <span class="special">-</span><span class="number">0.1</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CHECK_THROW</span><span class="special">(</span><span class="identifier">my_special</span><span class="special">(</span><span class="number">0</span><span class="special">,</span> <span class="number">1.1</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">domain_error</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
When the function has known exact values (typically integer values) we can
|
|
use <code class="computeroutput"><span class="identifier">BOOST_CHECK_EQUAL</span></code>:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">BOOST_CHECK_EQUAL</span><span class="special">(</span><span class="identifier">my_special</span><span class="special">(</span><span class="number">1.0</span><span class="special">,</span> <span class="number">0.0</span><span class="special">),</span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CHECK_EQUAL</span><span class="special">(</span><span class="identifier">my_special</span><span class="special">(</span><span class="number">1.0</span><span class="special">,</span> <span class="number">1.0</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
When the function has known values which are not exact (from a floating point
|
|
perspective) then we can use <code class="computeroutput"><span class="identifier">BOOST_CHECK_CLOSE_FRACTION</span></code>:
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Assumes 4 epsilon is as close as we can get to a true value of 2Pi:</span>
|
|
<span class="identifier">BOOST_CHECK_CLOSE_FRACTION</span><span class="special">(</span><span class="identifier">my_special</span><span class="special">(</span><span class="number">0.5</span><span class="special">,</span> <span class="number">0.5</span><span class="special">),</span> <span class="number">2</span> <span class="special">*</span> <span class="identifier">constants</span><span class="special">::</span><span class="identifier">pi</span><span class="special"><</span><span class="keyword">double</span><span class="special">>(),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">double</span><span class="special">>::</span><span class="identifier">epsilon</span><span class="special">()</span> <span class="special">*</span> <span class="number">4</span><span class="special">);</span>
|
|
</pre>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h1"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.independent_test_values"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.independent_test_values">Independent
|
|
Test Values</a>
|
|
</h5>
|
|
<p>
|
|
If the function is implemented by some other known good source (for example
|
|
Mathematica or it's online versions <a href="http://functions.wolfram.com" target="_top">functions.wolfram.com</a>
|
|
or <a href="http://www.wolframalpha.com" target="_top">www.wolframalpha.com</a>
|
|
then it's a good idea to sanity check our implementation by having at least
|
|
one independently generated value for each code branch our implementation
|
|
may take. To slot these in nicely with our testing framework it's best to
|
|
tabulate these like this:
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// function values calculated on http://functions.wolfram.com/</span>
|
|
<span class="keyword">static</span> <span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">array</span><span class="special"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">array</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span> <span class="number">3</span><span class="special">>,</span> <span class="number">10</span><span class="special">></span> <span class="identifier">my_special_data</span> <span class="special">=</span> <span class="special">{{</span>
|
|
<span class="special">{{</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">}},</span>
|
|
<span class="special">{{</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="identifier">SC_</span><span class="special">(</span><span class="number">1.26606587775200833559824462521471753760767031135496220680814</span><span class="special">)</span> <span class="special">}},</span>
|
|
<span class="comment">/* More values here... */</span>
|
|
<span class="special">}};</span>
|
|
</pre>
|
|
<p>
|
|
We'll see how to use this table and the meaning of the <code class="computeroutput"><span class="identifier">SC_</span></code>
|
|
macro later. One important point is to make sure that the input values have
|
|
exact binary representations: so choose values such as 1.5, 1.25, 1.125 etc.
|
|
This ensures that if <code class="computeroutput"><span class="identifier">my_special</span></code>
|
|
is unusually sensitive in one area, that we don't get apparently large errors
|
|
just because the inputs are 0.5 ulp in error.
|
|
</p>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h2"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.random_test_values"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.random_test_values">Random
|
|
Test Values</a>
|
|
</h5>
|
|
<p>
|
|
We can generate a large number of test values to check both for future regressions,
|
|
and for accumulated rounding or cancellation error in our implementation.
|
|
Ideally we would use an independent implementation for this (for example
|
|
my_special may be defined in directly terms of other special functions but
|
|
not implemented that way for performance or accuracy reasons). Alternatively
|
|
we may use our own implementation directly, but with any special cases (asymptotic
|
|
expansions etc) disabled. We have a set of <a class="link" href="../internals/test_data.html" title="Graphing, Profiling, and Generating Test Data for Special Functions">tools</a>
|
|
to generate test data directly, here's a typical example:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_MATH_STANDALONE</span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multiprecision</span><span class="special">/</span><span class="identifier">cpp_dec_float</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">test_data</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">test</span><span class="special">/</span><span class="identifier">included</span><span class="special">/</span><span class="identifier">prg_exec_monitor</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">fstream</span><span class="special">></span>
|
|
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">std</span><span class="special">;</span>
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multiprecision</span><span class="special">;</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="identifier">T</span> <span class="identifier">my_special</span><span class="special">(</span><span class="identifier">T</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">b</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">// Implementation of my_special here...</span>
|
|
<span class="keyword">return</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">cpp_main</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span><span class="special">*</span><span class="identifier">argv</span> <span class="special">[])</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// We'll use so many digits of precision that any</span>
|
|
<span class="comment">// calculation errors will still leave us with</span>
|
|
<span class="comment">// 40-50 good digits. We'll only run this program</span>
|
|
<span class="comment">// once so it doesn't matter too much how long this takes!</span>
|
|
<span class="comment">//</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">number</span><span class="special"><</span><span class="identifier">cpp_dec_float</span><span class="special"><</span><span class="number">500</span><span class="special">></span> <span class="special">></span> <span class="identifier">bignum</span><span class="special">;</span>
|
|
|
|
<span class="identifier">parameter_info</span><span class="special"><</span><span class="identifier">bignum</span><span class="special">></span> <span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">;</span>
|
|
<span class="identifier">test_data</span><span class="special"><</span><span class="identifier">bignum</span><span class="special">></span> <span class="identifier">data</span><span class="special">;</span>
|
|
|
|
<span class="keyword">bool</span> <span class="identifier">cont</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">line</span><span class="special">;</span>
|
|
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">argc</span> <span class="special"><</span> <span class="number">1</span><span class="special">)</span>
|
|
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
|
|
|
|
<span class="keyword">do</span><span class="special">{</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// User interface which prompts for </span>
|
|
<span class="comment">// range of input parameters:</span>
|
|
<span class="comment">//</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="number">0</span> <span class="special">==</span> <span class="identifier">get_user_parameter_info</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="string">"a"</span><span class="special">))</span>
|
|
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="number">0</span> <span class="special">==</span> <span class="identifier">get_user_parameter_info</span><span class="special">(</span><span class="identifier">arg2</span><span class="special">,</span> <span class="string">"b"</span><span class="special">))</span>
|
|
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
|
|
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Get a pointer to the function and call</span>
|
|
<span class="comment">// test_data::insert to actually generate</span>
|
|
<span class="comment">// the values.</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">bignum</span> <span class="special">(*</span><span class="identifier">fp</span><span class="special">)(</span><span class="identifier">bignum</span><span class="special">,</span> <span class="identifier">bignum</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">my_special</span><span class="special">;</span>
|
|
<span class="identifier">data</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">fp</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">);</span>
|
|
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Any more data [y/n]?"</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">getline</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span><span class="special">,</span> <span class="identifier">line</span><span class="special">);</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">algorithm</span><span class="special">::</span><span class="identifier">trim</span><span class="special">(</span><span class="identifier">line</span><span class="special">);</span>
|
|
<span class="identifier">cont</span> <span class="special">=</span> <span class="special">(</span><span class="identifier">line</span> <span class="special">==</span> <span class="string">"y"</span><span class="special">);</span>
|
|
<span class="special">}</span><span class="keyword">while</span><span class="special">(</span><span class="identifier">cont</span><span class="special">);</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Just need to write the results to a file:</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Enter name of test data file [default=my_special.ipp]"</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">getline</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span><span class="special">,</span> <span class="identifier">line</span><span class="special">);</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">algorithm</span><span class="special">::</span><span class="identifier">trim</span><span class="special">(</span><span class="identifier">line</span><span class="special">);</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">line</span> <span class="special">==</span> <span class="string">""</span><span class="special">)</span>
|
|
<span class="identifier">line</span> <span class="special">=</span> <span class="string">"my_special.ipp"</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ofstream</span> <span class="identifier">ofs</span><span class="special">(</span><span class="identifier">line</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">());</span>
|
|
<span class="identifier">line</span><span class="special">.</span><span class="identifier">erase</span><span class="special">(</span><span class="identifier">line</span><span class="special">.</span><span class="identifier">find</span><span class="special">(</span><span class="char">'.'</span><span class="special">));</span>
|
|
<span class="identifier">ofs</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">scientific</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">setprecision</span><span class="special">(</span><span class="number">50</span><span class="special">);</span>
|
|
<span class="identifier">write_code</span><span class="special">(</span><span class="identifier">ofs</span><span class="special">,</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">line</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">());</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
Typically several sets of data will be generated this way, including random
|
|
values in some "normal" range, extreme values (very large or very
|
|
small), and values close to any "interesting" behaviour of the
|
|
function (singularities etc).
|
|
</p>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h3"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.the_test_file_header"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.the_test_file_header">The
|
|
Test File Header</a>
|
|
</h5>
|
|
<p>
|
|
We split the actual test file into 2 distinct parts: a header that contains
|
|
the testing code as a series of function templates, and the actual .cpp test
|
|
driver that decides which types are tested, and sets the "expected"
|
|
error rates for those types. It's done this way because:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
We want to test with both built in floating point types, and with multiprecision
|
|
types. However, both compile and runtimes with the latter can be too
|
|
long for the folks who run the tests to realistically cope with, so it
|
|
makes sense to split the test into (at least) 2 parts.
|
|
</li>
|
|
<li class="listitem">
|
|
The definition of the SC_ macro used in our tables of data may differ
|
|
depending on what type we're testing (see below). Again this is largely
|
|
a matter of managing compile times as large tables of user-defined-types
|
|
can take a crazy amount of time to compile with some compilers.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
The test header contains 2 functions:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">do_test</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">type_name</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">test_name</span><span class="special">);</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">T</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">type_name</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
Before implementing those, we'll include the headers we'll need, and provide
|
|
a default definition for the SC_ macro:
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// A couple of Boost.Test headers in case we need any BOOST_CHECK_* macros:</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">test</span><span class="special">/</span><span class="identifier">unit_test</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">test</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">floating_point_comparison</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="comment">// Our function to test:</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">my_special</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="comment">// We need boost::array for our test data, plus a few headers from</span>
|
|
<span class="comment">// libs/math/test that contain our testing machinery:</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="string">"functor.hpp"</span>
|
|
<span class="preprocessor">#include</span> <span class="string">"handle_test_result.hpp"</span>
|
|
<span class="preprocessor">#include</span> <span class="string">"table_type.hpp"</span>
|
|
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">SC_</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">SC_</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">table_type</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">type</span><span class="special">>(</span><span class="identifier">BOOST_JOIN</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">L</span><span class="special">))</span>
|
|
<span class="preprocessor">#endif</span>
|
|
</pre>
|
|
<p>
|
|
The easiest function to implement is the "test" function which
|
|
is what we'll be calling from the test-driver program. It simply includes
|
|
the files containing the tabular test data and calls <code class="computeroutput"><span class="identifier">do_test</span></code>
|
|
function for each table, along with a description of what's being tested:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">test</span><span class="special">(</span><span class="identifier">T</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">type_name</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// The actual test data is rather verbose, so it's in a separate file</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// The contents are as follows, each row of data contains</span>
|
|
<span class="comment">// three items, input value a, input value b and my_special(a, b):</span>
|
|
<span class="comment">//</span>
|
|
<span class="preprocessor"># include</span> <span class="string">"my_special_1.ipp"</span>
|
|
|
|
<span class="identifier">do_test</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">my_special_1</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="string">"MySpecial Function: Mathematica Values"</span><span class="special">);</span>
|
|
|
|
<span class="preprocessor"># include</span> <span class="string">"my_special_2.ipp"</span>
|
|
|
|
<span class="identifier">do_test</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">my_special_2</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="string">"MySpecial Function: Random Values"</span><span class="special">);</span>
|
|
|
|
<span class="preprocessor"># include</span> <span class="string">"my_special_3.ipp"</span>
|
|
|
|
<span class="identifier">do_test</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">my_special_3</span><span class="special">,</span> <span class="identifier">name</span><span class="special">,</span> <span class="string">"MySpecial Function: Very Small Values"</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
The function <code class="computeroutput"><span class="identifier">do_test</span></code> takes
|
|
each table of data and calculates values for each row of data, along with
|
|
statistics for max and mean error etc, most of this is handled by some boilerplate
|
|
code:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">do_test</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">type_name</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">test_name</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">// Get the type of each row and each element in the rows:</span>
|
|
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">::</span><span class="identifier">value_type</span> <span class="identifier">row_type</span><span class="special">;</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">Real</span> <span class="identifier">value_type</span><span class="special">;</span>
|
|
|
|
<span class="comment">// Get a pointer to our function, we have to use a workaround here</span>
|
|
<span class="comment">// as some compilers require the template types to be explicitly</span>
|
|
<span class="comment">// specified, while others don't much like it if it is!</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">value_type</span> <span class="special">(*</span><span class="identifier">pg</span><span class="special">)(</span><span class="identifier">value_type</span><span class="special">,</span> <span class="identifier">value_type</span><span class="special">);</span>
|
|
<span class="preprocessor">#if</span> <span class="identifier">defined</span><span class="special">(</span><span class="identifier">BOOST_MATH_NO_DEDUCED_FUNCTION_POINTERS</span><span class="special">)</span>
|
|
<span class="identifier">pg</span> <span class="identifier">funcp</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">my_special</span><span class="special"><</span><span class="identifier">value_type</span><span class="special">,</span> <span class="identifier">value_type</span><span class="special">>;</span>
|
|
<span class="preprocessor">#else</span>
|
|
<span class="identifier">pg</span> <span class="identifier">funcp</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">my_special</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="comment">// Somewhere to hold our results:</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">::</span><span class="identifier">test_result</span><span class="special"><</span><span class="identifier">value_type</span><span class="special">></span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="comment">// And some pretty printing:</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Testing "</span> <span class="special"><<</span> <span class="identifier">test_name</span> <span class="special"><<</span> <span class="string">" with type "</span> <span class="special"><<</span> <span class="identifier">type_name</span>
|
|
<span class="special"><<</span> <span class="string">"\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"</span><span class="special">;</span>
|
|
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Test my_special against data:</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">result</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">tools</span><span class="special">::</span><span class="identifier">test_hetero</span><span class="special"><</span><span class="identifier">Real</span><span class="special">>(</span>
|
|
<span class="comment">/* First argument is the table */</span>
|
|
<span class="identifier">data</span><span class="special">,</span>
|
|
<span class="comment">/* Next comes our function pointer, plus the indexes of it's arguments in the table */</span>
|
|
<span class="identifier">bind_func</span><span class="special"><</span><span class="identifier">Real</span><span class="special">>(</span><span class="identifier">funcp</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">1</span><span class="special">),</span>
|
|
<span class="comment">/* Then the index of the result in the table - potentially we can test several
|
|
related functions this way, each having the same input arguments, and different
|
|
output values in different indexes in the table */</span>
|
|
<span class="identifier">extract_result</span><span class="special"><</span><span class="identifier">Real</span><span class="special">>(</span><span class="number">2</span><span class="special">));</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Finish off with some boilerplate to check the results were within the expected errors,</span>
|
|
<span class="comment">// and pretty print the results:</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">handle_test_result</span><span class="special">(</span><span class="identifier">result</span><span class="special">,</span> <span class="identifier">data</span><span class="special">[</span><span class="identifier">result</span><span class="special">.</span><span class="identifier">worst</span><span class="special">()],</span> <span class="identifier">result</span><span class="special">.</span><span class="identifier">worst</span><span class="special">(),</span> <span class="identifier">type_name</span><span class="special">,</span> <span class="string">"boost::math::my_special"</span><span class="special">,</span> <span class="identifier">test_name</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
Now we just need to write the test driver program, at it's most basic it
|
|
looks something like this:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">math_fwd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">test</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">stats</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="string">"functor.hpp"</span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="string">"handle_test_result.hpp"</span>
|
|
<span class="preprocessor">#include</span> <span class="string">"test_my_special.hpp"</span>
|
|
|
|
<span class="identifier">BOOST_AUTO_TEST_CASE</span><span class="special">(</span> <span class="identifier">test_main</span> <span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Test each floating point type, plus real_concept.</span>
|
|
<span class="comment">// We specify the name of each type by hand as typeid(T).name()</span>
|
|
<span class="comment">// often gives an unreadable mangled name.</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">test</span><span class="special">(</span><span class="number">0.1F</span><span class="special">,</span> <span class="string">"float"</span><span class="special">);</span>
|
|
<span class="identifier">test</span><span class="special">(</span><span class="number">0.1</span><span class="special">,</span> <span class="string">"double"</span><span class="special">);</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Testing of long double and real_concept is protected</span>
|
|
<span class="comment">// by some logic to disable these for unsupported</span>
|
|
<span class="comment">// or problem compilers.</span>
|
|
<span class="comment">//</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS</span>
|
|
<span class="identifier">test</span><span class="special">(</span><span class="number">0.1L</span><span class="special">,</span> <span class="string">"long double"</span><span class="special">);</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_MATH_NO_REAL_CONCEPT_TESTS</span>
|
|
<span class="identifier">test</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">concepts</span><span class="special">::</span><span class="identifier">real_concept</span><span class="special">(</span><span class="number">0.1</span><span class="special">),</span> <span class="string">"real_concept);
|
|
#endif
|
|
#else
|
|
std::cout << "</span><span class="special"><</span><span class="identifier">note</span><span class="special">></span><span class="identifier">The</span> <span class="keyword">long</span> <span class="keyword">double</span> <span class="identifier">tests</span> <span class="identifier">have</span> <span class="identifier">been</span> <span class="identifier">disabled</span> <span class="identifier">on</span> <span class="keyword">this</span> <span class="identifier">platform</span> <span class="string">"
|
|
"</span><span class="identifier">either</span> <span class="identifier">because</span> <span class="identifier">the</span> <span class="keyword">long</span> <span class="keyword">double</span> <span class="identifier">overloads</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">usual</span> <span class="identifier">math</span> <span class="identifier">functions</span> <span class="identifier">are</span> <span class="string">"
|
|
"</span><span class="keyword">not</span> <span class="identifier">available</span> <span class="identifier">at</span> <span class="identifier">all</span><span class="special">,</span> <span class="keyword">or</span> <span class="identifier">because</span> <span class="identifier">they</span> <span class="identifier">are</span> <span class="identifier">too</span> <span class="identifier">inaccurate</span> <span class="keyword">for</span> <span class="identifier">these</span> <span class="identifier">tests</span> <span class="string">"
|
|
"</span><span class="identifier">to</span> <span class="identifier">pass</span><span class="special">.</</span><span class="identifier">note</span><span class="special">></span><span class="error">"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
That's almost all there is too it - except that if the above program is run
|
|
it's very likely that all the tests will fail as the default maximum allowable
|
|
error is 1 epsilon. So we'll define a function (don't forget to call it from
|
|
the start of the <code class="computeroutput"><span class="identifier">test_main</span></code>
|
|
above) to up the limits to something sensible, based both on the function
|
|
we're calling and on the particular tests plus the platform and compiler:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">expected_results</span><span class="special">()</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Define the max and mean errors expected for</span>
|
|
<span class="comment">// various compilers and platforms.</span>
|
|
<span class="comment">//</span>
|
|
<span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">largest_type</span><span class="special">;</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">digits</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">policy</span><span class="special"><></span> <span class="special">>()</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">digits</span><span class="special"><</span><span class="keyword">long</span> <span class="keyword">double</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">policies</span><span class="special">::</span><span class="identifier">policy</span><span class="special"><></span> <span class="special">>())</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">largest_type</span> <span class="special">=</span> <span class="string">"(long\\s+)?double|real_concept"</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">else</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">largest_type</span> <span class="special">=</span> <span class="string">"long double|real_concept"</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="preprocessor">#else</span>
|
|
<span class="identifier">largest_type</span> <span class="special">=</span> <span class="string">"(long\\s+)?double"</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// We call add_expected_result for each error rate we wish to adjust, these tell</span>
|
|
<span class="comment">// handle_test_result what level of error is acceptable. We can have as many calls</span>
|
|
<span class="comment">// to add_expected_result as we need, each one establishes a rule for acceptable error</span>
|
|
<span class="comment">// with rules set first given preference.</span>
|
|
<span class="comment">//</span>
|
|
<span class="identifier">add_expected_result</span><span class="special">(</span>
|
|
<span class="comment">/* First argument is a regular expression to match against the name of the compiler
|
|
set in BOOST_COMPILER */</span>
|
|
<span class="string">".*"</span><span class="special">,</span>
|
|
<span class="comment">/* Second argument is a regular expression to match against the name of the
|
|
C++ standard library as set in BOOST_STDLIB */</span>
|
|
<span class="string">".*"</span><span class="special">,</span>
|
|
<span class="comment">/* Third argument is a regular expression to match against the name of the
|
|
platform as set in BOOST_PLATFORM */</span>
|
|
<span class="string">".*"</span><span class="special">,</span>
|
|
<span class="comment">/* Forth argument is the name of the type being tested, normally we will
|
|
only need to up the acceptable error rate for the widest floating
|
|
point type being tested */</span>
|
|
<span class="identifier">largest_real</span><span class="special">,</span>
|
|
<span class="comment">/* Fifth argument is a regular expression to match against
|
|
the name of the group of data being tested */</span>
|
|
<span class="string">"MySpecial Function:.*Small.*"</span><span class="special">,</span>
|
|
<span class="comment">/* Sixth argument is a regular expression to match against the name
|
|
of the function being tested */</span>
|
|
<span class="string">"boost::math::my_special"</span><span class="special">,</span>
|
|
<span class="comment">/* Seventh argument is the maximum allowable error expressed in units
|
|
of machine epsilon passed as a long integer value */</span>
|
|
<span class="number">50</span><span class="special">,</span>
|
|
<span class="comment">/* Eighth argument is the maximum allowable mean error expressed in units
|
|
of machine epsilon passed as a long integer value */</span>
|
|
<span class="number">20</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h4"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.testing_multiprecision_types"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.testing_multiprecision_types">Testing
|
|
Multiprecision Types</a>
|
|
</h5>
|
|
<p>
|
|
Testing of multiprecision types is handled by the test drivers in libs/multiprecision/test/math,
|
|
please refer to these for examples. Note that these tests are run only occasionally
|
|
as they take a lot of CPU cycles to build and run.
|
|
</p>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h5"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.improving_compile_times"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.improving_compile_times">Improving
|
|
Compile Times</a>
|
|
</h5>
|
|
<p>
|
|
As noted above, these test programs can take a while to build as we're instantiating
|
|
a lot of templates for several different types, and our test runners are
|
|
already stretched to the limit, and probably using outdated "spare"
|
|
hardware. There are two things we can do to speed things up:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Use a precompiled header.
|
|
</li>
|
|
<li class="listitem">
|
|
Use separate compilation of our special function templates.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
We can make these changes by changing the list of includes from:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">math_fwd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">test</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">tools</span><span class="special">/</span><span class="identifier">stats</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">array</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="string">"functor.hpp"</span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="string">"handle_test_result.hpp"</span>
|
|
</pre>
|
|
<p>
|
|
To just:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">pch_light</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
</pre>
|
|
<p>
|
|
And changing
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">my_special</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
</pre>
|
|
<p>
|
|
To:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">math_fwd</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
</pre>
|
|
<p>
|
|
The Jamfile target that builds the test program will need the targets
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">test_instances</span><span class="comment">//test_instances pch_light</span>
|
|
</pre>
|
|
<p>
|
|
adding to it's list of source dependencies (see the Jamfile for examples).
|
|
</p>
|
|
<p>
|
|
Finally the project in libs/math/test/test_instances will need modifying
|
|
to instantiate function <code class="computeroutput"><span class="identifier">my_special</span></code>.
|
|
</p>
|
|
<p>
|
|
These changes should be made last, when <code class="computeroutput"><span class="identifier">my_special</span></code>
|
|
is stable and the code is in Trunk.
|
|
</p>
|
|
<h5>
|
|
<a name="math_toolkit.special_tut.special_tut_test.h6"></a>
|
|
<span class="phrase"><a name="math_toolkit.special_tut.special_tut_test.concept_checks"></a></span><a class="link" href="special_tut_test.html#math_toolkit.special_tut.special_tut_test.concept_checks">Concept
|
|
Checks</a>
|
|
</h5>
|
|
<p>
|
|
Our concept checks verify that your function's implementation makes no assumptions
|
|
that aren't required by our <a class="link" href="../real_concepts.html" title="Conceptual Requirements for Real Number Types">Real
|
|
number conceptual requirements</a>. They also check for various common
|
|
bugs and programming traps that we've fallen into over time. To add your
|
|
function to these tests, edit libs/math/test/compile_test/instantiate.hpp
|
|
to add calls to your function: there are 7 calls to each function, each with
|
|
a different purpose. Search for something like "ibeta" or "gamm_p"
|
|
and follow their examples.
|
|
</p>
|
|
</div>
|
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
|
<td align="left"></td>
|
|
<td align="right"><div class="copyright-footer">Copyright © 2006-2021 Nikhar Agrawal, Anton Bikineev, Matthew Borland,
|
|
Paul A. Bristow, Marco Guazzone, Christopher Kormanyos, Hubert Holin, Bruno
|
|
Lalande, John Maddock, Evan Miller, Jeremy Murphy, Matthew Pulver, Johan Råde,
|
|
Gautam Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle
|
|
Walker and Xiaogang Zhang<p>
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
</p>
|
|
</div></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="special_tut_impl.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../special_tut.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../relative_error.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|