mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
New sections of examples or cube, fifth, multiprecision and nth root finding, and comparison of timing and iterations.
This commit is contained in:
@@ -490,7 +490,7 @@ These changes should be made last, when `my_special` is stable and the code is i
|
||||
[h4 Concept Checks]
|
||||
|
||||
Our concept checks verify that your function's implementation makes no assumptions that aren't
|
||||
required by our [link math_toolkit.concepts Real number conceptual requirements]. They also
|
||||
required by our [link math_toolkit.real_concepts Real number conceptual requirements]. 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.
|
||||
|
||||
@@ -20,12 +20,12 @@ Of course, the main cost of higher precision is very much decreased
|
||||
(usually at least hundred-fold) computation speed, and big increases in memory use.
|
||||
|
||||
Some libraries offer true
|
||||
[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary precision arithmetic]
|
||||
where the precision is limited only by avilable memory and compute time, but most are used
|
||||
at some arbitrarily-fixed precision, say 100 decimal digits.
|
||||
[@http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic arbitrary-precision arithmetic]
|
||||
where the precision is limited only by available memory and compute time, but most are used
|
||||
at some arbitrarily-fixed precision, say 100 decimal digits, like __boost_multiprecision `cpp_dec_float_100`.
|
||||
|
||||
__multiprecision can operate in both ways, but the most popular choice is likely to be about a hundred
|
||||
decimal digits, though examples of computing tens of thousands of digits have been demonstrated.
|
||||
decimal digits, though examples of computing about a million digits have been demonstrated.
|
||||
|
||||
[section:why_high_precision Why use a high-precision library rather than built-in floating-point types?]
|
||||
|
||||
@@ -37,8 +37,8 @@ Some reasons why one would want to use a higher precision:
|
||||
|
||||
* A much more precise result (many more digits) is just a requirement.
|
||||
* The range of the computed value exceeds the range of the type: factorials are the textbook example.
|
||||
* Using double is (or may be) too inaccurate.
|
||||
* Using long double (or may be) is too inaccurate.
|
||||
* Using `double` is (or may be) too inaccurate.
|
||||
* Using `long double` (or may be) is too inaccurate.
|
||||
* Using an extended precision type implemented in software as
|
||||
[@http://en.wikipedia.org/wiki/Double-double_(arithmetic)#Double-double_arithmetic double-double]
|
||||
([@http://en.wikipedia.org/wiki/Darwin_(operating_system) Darwin]) is sometimes unpredictably inaccurate.
|
||||
@@ -237,7 +237,6 @@ to the majority of functions defined this library when used with `NTL::RR`.
|
||||
There is a concept checking test program for NTL support
|
||||
[@../../../../libs/math/test/ntl_concept_check.cpp here].
|
||||
|
||||
|
||||
[endsect] [/section:use_ntl Using With NTL - a High-Precision Floating-Point Library]
|
||||
|
||||
[section:using_test Using without expression templates for Boost.Test and others]
|
||||
@@ -258,25 +257,25 @@ you will need to override the default `boost::multiprecision::et_on` with
|
||||
A full example code is at [@../../example/test_cpp_float_close_fraction.cpp test_cpp_float_close_fraction.cpp]
|
||||
|
||||
[endsect] [/section:using_test Using without expression templates for Boost.Test and others]
|
||||
|
||||
[endsect] [/section:high_precision Using With High-Precision Floating-Point Libraries]
|
||||
|
||||
[section:real_concepts Conceptual Requirements for Real Number Types]
|
||||
|
||||
[section:concepts Conceptual Requirements for Real Number Types]
|
||||
|
||||
The functions, and statistical distributions in this library can be used with
|
||||
any type /RealType/ that meets the conceptual requirements given below. All
|
||||
the built-in floating-point types will meet these requirements.
|
||||
User-defined types that meet the requirements can also be used.
|
||||
The functions and statistical distributions in this library can be used with
|
||||
any type ['RealType] that meets the conceptual requirements given below. All
|
||||
the built-in floating-point types like `double` will meet these requirements.
|
||||
(Built-in types are also called __fundamental_types).
|
||||
|
||||
User-defined types that meet the conceptual requirements can also be used.
|
||||
For example, with [link math_toolkit.high_precision.use_ntl a thin wrapper class]
|
||||
one of the types provided with [@http://shoup.net/ntl/ NTL (RR)] can be used.
|
||||
But now that __multiprecision library is available,
|
||||
this has become the reference real number type.
|
||||
this has become the preferred real-number type,
|
||||
typically __cpp_dec_float or __cpp_bin_float.
|
||||
|
||||
Submissions of binding to other extended precision types would also still be welcome.
|
||||
|
||||
The guiding principal behind these requirements is that a /RealType/
|
||||
The guiding principal behind these requirements is that a ['RealType]
|
||||
behaves just like a built-in floating-point type.
|
||||
|
||||
[h4 Basic Arithmetic Requirements]
|
||||
@@ -381,8 +380,8 @@ to a string, causing potentially serious loss of accuracy on output.
|
||||
|
||||
Although it might seem obvious that RealType should require `std::numeric_limits`
|
||||
to be specialized, this is not sensible for
|
||||
`NTL::RR` and similar classes where the number of digits is a runtime
|
||||
parameter (where as for `numeric_limits` it has to be fixed at compile time).
|
||||
`NTL::RR` and similar classes where the [*number of digits is a runtime parameter]
|
||||
(whereas for `numeric_limits` everything has to be fixed at compile time).
|
||||
]
|
||||
|
||||
[h4 Standard Library Support Requirements]
|
||||
@@ -391,7 +390,7 @@ Many (though not all) of the functions in this library make calls
|
||||
to standard library functions, the following table summarises the
|
||||
requirements. Note that most of the functions in this library
|
||||
will only call a small subset of the functions listed here, so if in
|
||||
doubt whether a user defined type has enough standard library
|
||||
doubt whether a user-defined type has enough standard library
|
||||
support to be useable the best advise is to try it and see!
|
||||
|
||||
In the following table /r/ is an object of type `RealType`,
|
||||
@@ -441,8 +440,8 @@ boost/math/special_functions/lanczos.hpp] or
|
||||
[@../../../../boost/math/bindings/detail/big_lanczos.hpp
|
||||
boost/math/bindings/detail/big_lanczos.hpp]:
|
||||
in the former case you will need change
|
||||
static_cast's to lexical_cast's, and the constants to /strings/
|
||||
(in order to ensure the coefficients aren't truncated to long double)
|
||||
`static_cast`'s to `lexical_cast`'s, and the constants to /strings/
|
||||
(in order to ensure the coefficients aren't truncated to `long doubl`e)
|
||||
and then specialise `lanczos_traits` for type T. Otherwise you may have to hack
|
||||
[@../../tools/lanczos_generator.cpp
|
||||
libs/math/tools/lanczos_generator.cpp] to find a suitable
|
||||
@@ -450,11 +449,11 @@ approximation for your RealType. The code will still compile if you don't do
|
||||
this, but both accuracy and efficiency will be greatly compromised in any
|
||||
function that makes use of the gamma\/beta\/erf family of functions.
|
||||
|
||||
[endsect] [/section: ]
|
||||
[endsect] [/section:real_concepts Conceptual Requirements for Real Number Types]
|
||||
|
||||
[section:dist_concept Conceptual Requirements for Distribution Types]
|
||||
|
||||
A /DistributionType/ is a type that implements the following conceptual
|
||||
A ['DistributionType] is a type that implements the following conceptual
|
||||
requirements, and encapsulates a statistical distribution.
|
||||
|
||||
Please note that this documentation should not be used as a substitute
|
||||
@@ -463,8 +462,8 @@ for the
|
||||
[link math_toolkit.stat_tut tutorial] of the statistical
|
||||
distributions.
|
||||
|
||||
In the following table, /d/ is an object of type `DistributionType`,
|
||||
/cd/ is an object of type `const DistributionType` and /cr/ is an
|
||||
In the following table, ['d] is an object of type `DistributionType`,
|
||||
['cd] is an object of type `const DistributionType` and ['cr] is an
|
||||
object of a type convertible to `RealType`.
|
||||
|
||||
[table
|
||||
@@ -495,16 +494,16 @@ object of a type convertible to `RealType`.
|
||||
[[variance(cd)][RealType][Returns the variance of the distribution.]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[endsect] [/ section:dist_concept Conceptual Requirements for Distribution Types]
|
||||
|
||||
[section:archetypes Conceptual Archetypes for Reals and Distributions]
|
||||
|
||||
There are a few concept archetypes available:
|
||||
|
||||
* Real concept for floating-point types.
|
||||
* distribution Concept for statistical distributions.
|
||||
* Distribution concept for statistical distributions.
|
||||
|
||||
[h5 Real concept]
|
||||
[h5:real_concept Real concept]
|
||||
|
||||
`std_real_concept` is an archetype for theReal types,
|
||||
including the built-in float, double, long double.
|
||||
@@ -558,7 +557,7 @@ that instantiates every template in this library with type
|
||||
}}} // namespaces
|
||||
|
||||
`real_concept` is an archetype for
|
||||
[link math_toolkit.concepts user defined real types],
|
||||
[link math_toolkit.real_concepts user defined real types],
|
||||
it declares its standard library functions in its own
|
||||
namespace: these will only be found if they are called unqualified
|
||||
allowing argument dependent lookup to locate them. In addition
|
||||
@@ -566,7 +565,7 @@ this type is useable at runtime:
|
||||
this allows code that would not otherwise be exercised by the built-in
|
||||
floating point types to be tested. There is no std::numeric_limits<>
|
||||
support for this type, since numeric_limits is not a conceptual requirement
|
||||
for [link math_toolkit.concepts RealType]s.
|
||||
for [link math_toolkit.real_concepts RealType]s.
|
||||
|
||||
NTL RR is an example of a type meeting the requirements that this type
|
||||
models, but note that use of a thin wrapper class is required: refer to
|
||||
@@ -576,7 +575,7 @@ There is no specific test case for type `real_concept`, instead, since this
|
||||
type is usable at runtime, each individual test case as well as testing
|
||||
`float`, `double` and `long double`, also tests `real_concept`.
|
||||
|
||||
[h6 Distribution Concept]
|
||||
[h6:distribution_concept Distribution Concept]
|
||||
|
||||
Distribution Concept models statistical distributions.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ with a tolerance provided by the user.
|
||||
|
||||
Some background reading is:
|
||||
|
||||
* Knuth D.E. The art of computer programming, vol II, section 4.2, especially Floating-Point_Comparison 4.2.2, pages 198-220.
|
||||
* Knuth D.E. The art of computer programming, vol II, section 4.2, especially Floating-Point Comparison 4.2.2, pages 198-220.
|
||||
* [@http://adtmag.com/articles/2000/03/16/comparing-floatshow-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been-r.aspx
|
||||
Alberto Squassabia, Comparing floats listing]
|
||||
* [@http://adtmag.com/articles/2000/03/16/comparing-floats-how-to-determine-if-floating-quantities-are-close-enough-once-a-tolerance-has-been.aspx
|
||||
|
||||
130
doc/math.css
Normal file
130
doc/math.css
Normal file
@@ -0,0 +1,130 @@
|
||||
@import url('../../../../doc/src/boostbook.css');
|
||||
|
||||
/*=============================================================================
|
||||
Copyright (c) 2004 Joel de Guzman
|
||||
Copyright (c) 2014 John Maddock
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Copyright 2013 Niall Douglas additions for colors and alignment.
|
||||
Copyright 2013 Paul A. Bristow additions for more colors and alignments.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompany-
|
||||
ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
Program listings
|
||||
=============================================================================*/
|
||||
|
||||
/* Code on paragraphs */
|
||||
p tt.computeroutput
|
||||
{
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
pre.synopsis
|
||||
{
|
||||
font-size: 10pt;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
font-size: 10pt;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
|
||||
}
|
||||
@media screen
|
||||
{
|
||||
/* Syntax Highlighting */
|
||||
.comment { color: green; }
|
||||
/* .comment { color: #008000; } */
|
||||
}
|
||||
/* Program listings in tables don't get borders */
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
margin: 0pc 0pc 0pc 0pc;
|
||||
padding: 0pc 0pc 0pc 0pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Table of contents
|
||||
=============================================================================*/
|
||||
|
||||
div.toc
|
||||
{
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.1pc 1pc 0.1pc 1pc;
|
||||
font-size: 100%;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.boost-toc
|
||||
{
|
||||
float: right;
|
||||
padding: 0.5pc;
|
||||
}
|
||||
|
||||
/* Code on toc */
|
||||
.toc .computeroutput { font-size: 120% }
|
||||
|
||||
/* No margin on nested menus */
|
||||
|
||||
.toc dl dl { margin: 0; }
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
Alignment and coloring use 'role' feature, available from Quickbook 1.6 up.
|
||||
Added from Niall Douglas for role color and alignment.
|
||||
http://article.gmane.org/gmane.comp.lib.boost.devel/243318
|
||||
*/
|
||||
|
||||
/* Add text alignment (see http://www.w3schools.com/cssref/pr_text_text-align.asp) */
|
||||
span.aligncenter
|
||||
{
|
||||
display: inline-block; width: 100%; text-align: center;
|
||||
}
|
||||
span.alignright
|
||||
{
|
||||
display: inline-block; width: 100%; text-align: right;
|
||||
}
|
||||
/* alignleft is the default. */
|
||||
span.alignleft
|
||||
{
|
||||
display: inline-block; width: 100%; text-align: left;
|
||||
}
|
||||
|
||||
/* alignjustify stretches the word spacing so that each line has equal width
|
||||
within a chosen fraction of page width (here arbitrarily 20%).
|
||||
*Not* useful inside table items as the column width remains the total string width.
|
||||
Nor very useful, except to temporarily restrict the width.
|
||||
*/
|
||||
span.alignjustify
|
||||
{
|
||||
display: inline-block; width: 20%; text-align: justify;
|
||||
}
|
||||
|
||||
/* Text colors.
|
||||
Names at http://www.w3.org/TR/2002/WD-css3-color-20020219/ 4.3. X11 color keywords.
|
||||
Quickbook Usage: [role red Some red text]
|
||||
|
||||
*/
|
||||
span.red { inline-block; color: red; }
|
||||
span.green { color: green; }
|
||||
span.lime { color: #00FF00; }
|
||||
span.blue { color: blue; }
|
||||
span.navy { color: navy; }
|
||||
span.yellow { color: yellow; }
|
||||
span.magenta { color: magenta; }
|
||||
span.indigo { color: #4B0082; }
|
||||
span.cyan { color: cyan; }
|
||||
span.purple { color: purple; }
|
||||
span.gold { color: gold; }
|
||||
span.silver { color: silver; } /* lighter gray */
|
||||
span.gray { color: #808080; } /* light gray */
|
||||
|
||||
18
doc/math.qbk
18
doc/math.qbk
@@ -64,6 +64,11 @@
|
||||
[def __nearequal '''≊''']
|
||||
[def __spaces '''  '''] [/ two spaces - useful for an indent.]
|
||||
|
||||
[def __tick [role aligncenter [role green \u2714]]] [/ u2714 is a HEAVY CHECK MARK tick (2713 check
|
||||
mark)]
|
||||
[def __cross [role aligncenter [role red \u2718]]] [/ u2718 is a heavy cross]
|
||||
[def __star [role aligncenter [role red \u2736]]] [/ 6-point star]
|
||||
|
||||
[def __caution This is now an official Boost library, but remains a library under
|
||||
development, the code is fully functional and robust, but
|
||||
interfaces, library structure, and function and distribution names
|
||||
@@ -122,7 +127,6 @@ and use the function's name as the link text.]
|
||||
[def __fifth_root [link math_toolkit.roots.root_finding_examples.fifth_root fifth root]]
|
||||
[def __nth_root [link math_toolkit.roots.root_finding_examples.nth_root nth root]]
|
||||
[def __multiprecision_root [link math_toolkit.roots.root_finding_examples.multiprecision_root multiprecision root]]
|
||||
|
||||
[/gammas]
|
||||
[def __lgamma [link math_toolkit.sf_gamma.lgamma lgamma]]
|
||||
[def __digamma [link math_toolkit.sf_gamma.digamma digamma]]
|
||||
@@ -275,6 +279,7 @@ and use the function's name as the link text.]
|
||||
|
||||
[/tools]
|
||||
[def __tuple [link math_toolkit.internals.tuples boost::math::tuple]]
|
||||
[def __tuple_type [link math_toolkit.internals.tuples std::pair, std::tuple, or boost::math::tuple]]
|
||||
|
||||
[/ distribution non-members]
|
||||
[def __cdf [link math_toolkit.dist_ref.nmp.cdf Cumulative Distribution Function]]
|
||||
@@ -352,6 +357,10 @@ and use the function's name as the link text.]
|
||||
__chf, __mean, __median, __mode, __variance, __sd, __skewness,
|
||||
__kurtosis, __kurtosis_excess, __range and __support]
|
||||
|
||||
[def __real_concept [link math_toolkit.real_concepts real concept]]
|
||||
[def __next_float [link math_toolkit.next_float Adjacent Floating-Point Values]]
|
||||
|
||||
[/ External links]
|
||||
[def __gsl [@http://www.gnu.org/software/gsl/ GSL-1.9]]
|
||||
[def __glibc [@http://www.gnu.org/software/libc/ GNU C Lib]]
|
||||
[def __hpc [@http://docs.hp.com/en/B9106-90010/index.html HP-UX C Library]]
|
||||
@@ -365,8 +374,10 @@ and use the function's name as the link text.]
|
||||
[def __cpp_dec_float [@boost:/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html cpp_dec_float]]
|
||||
[def __cpp_bin_float [@boost:/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_bin_float.html cpp_bin_float]]
|
||||
[def __boost_test [@boost:/libs/test/doc/html/index.html Boost.Test]]
|
||||
[def __boost_timer [@boost:/libs/timer/doc/index.html Boost.Timer]]
|
||||
[def __boost_test_fp [@boost:/libs/test/doc/html/boost_test/users_guide/testing_tools/testing_floating_points.html Boost.Test floating-point comparison]]
|
||||
[def __boost_math_fp [link math_toolkit.float_comparison Boost.Math floating-point utilities]]
|
||||
[def __float_distance [@boost:/libs/math/doc/html/math_toolkit/next_float/float_distance.html Boost.Math float_distance]]
|
||||
[def __ulp [@http://en.wikipedia.org/wiki/Unit_in_the_last_place Unit in the last place (ULP)]]
|
||||
[def __R [@http://www.r-project.org/ The R Project for Statistical Computing]]
|
||||
[def __godfrey [link godfrey Godfrey]]
|
||||
@@ -388,6 +399,11 @@ and use the function's name as the link text.]
|
||||
[def __floating_point [@http://en.wikipedia.org/wiki/Floating_point Floating point]]
|
||||
[def __epsilon [@http://en.wikipedia.org/wiki/Machine_epsilon machine epsilon]]
|
||||
[def __ADL [@http://en.cppreference.com/w/cpp/language/adl Argument Dependent Lookup (ADL)]]
|
||||
[def __function_template_instantiation [@http://en.cppreference.com/w/cpp/language/function_template Function template instantiation]]
|
||||
[def __fundamental_types [@http://en.cppreference.com/w/cpp/language/types fundamental]]
|
||||
[def __guard_digits [@http://en.wikipedia.org/wiki/Guard_digit guard digits]]
|
||||
[def __SSE2 [@http://en.wikipedia.org/wiki/SSE2 SSE2 instructions]]
|
||||
[def __representable [@http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding representable]]
|
||||
|
||||
[/ Some composite templates]
|
||||
[template super[x]'''<superscript>'''[x]'''</superscript>''']
|
||||
|
||||
@@ -23,8 +23,8 @@ These two functions locate the minima of the continuous function ['f] using
|
||||
[*Parameters]
|
||||
|
||||
[variablelist
|
||||
[[F] [class of functor]]
|
||||
[[T] [floating-point type for computation and result]]
|
||||
[[F] [class of functor.]]
|
||||
[[T] [floating-point type for computation and result.]]
|
||||
[[f] [The function to minimise a function object (functor) that should be smooth over the
|
||||
range ['\[min, max\]], with no maxima occurring in that interval.]]
|
||||
[[min] [The lower endpoint of the range in which to search for the minima.]]
|
||||
@@ -88,7 +88,7 @@ so choosing a tight min-max range is good.]
|
||||
For simplicity, we set the precision parameter `bits` to `std::numeric_limits<double>::digits`,
|
||||
which is effectively the maximum possible `std::numeric_limits<double>::digits`/2.
|
||||
Nor do we provide a maximum iterations parameter `max_iter`,
|
||||
so the function will iterate until it finds a minimum.
|
||||
(perhaps unwidely), so the function will iterate until it finds a minimum.
|
||||
|
||||
[brent_minimise_double_1]
|
||||
|
||||
@@ -152,7 +152,7 @@ that we reduce the number of iterations from 10 to 7 and the result significantl
|
||||
Showing 13 bits precision with 9 decimal digits from tolerance 0.015625
|
||||
x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009 after 7 iterations.
|
||||
|
||||
[h5:template Templated on floating-point type]
|
||||
[h5:template Templating on floating-point type]
|
||||
|
||||
If we want to switch the floating-point type, then the functor must be revised.
|
||||
|
||||
@@ -185,6 +185,8 @@ For this optional include, the build should define the macro BOOST_HAVE_QUADMATH
|
||||
|
||||
[brent_minimise_mp_include_1]
|
||||
|
||||
or
|
||||
|
||||
[brent_minimise_template_quad]
|
||||
|
||||
[h5:multiprecision Multiprecision]
|
||||
@@ -209,9 +211,9 @@ and with our show function
|
||||
|
||||
[brent_minimise_mp_output_2]
|
||||
|
||||
[tip One can usually rely on __ADL
|
||||
[tip One can usually rely on __function_template_instantiation
|
||||
to avoid specifying the verbose multiprecision types,
|
||||
but some care in needed with the ['type of the values] provided
|
||||
but great care in needed with the ['type of the values] provided
|
||||
to avoid confusing the compiler.
|
||||
]
|
||||
|
||||
@@ -226,7 +228,9 @@ The complete example code is at [@../../example/brent_minimise_example.cpp brent
|
||||
|
||||
[h4 Implementation]
|
||||
|
||||
This is a reasonably faithful implementation of Brent's algorithm, refer to:
|
||||
This is a reasonably faithful implementation of Brent's algorithm.
|
||||
|
||||
[h4 References]
|
||||
|
||||
# Brent, R.P. 1973, Algorithms for Minimization without Derivatives,
|
||||
(Englewood Cliffs, NJ: Prentice-Hall), Chapter 5.
|
||||
|
||||
182
doc/roots/root_comparison.qbk
Normal file
182
doc/roots/root_comparison.qbk
Normal file
@@ -0,0 +1,182 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
[section:root_comparison Comparison of Root Finding Algorithms]
|
||||
|
||||
[section:cbrt_comparison Comparison of Cube Root Finding Algorithms]
|
||||
|
||||
In the table below, the cube root of 28 was computed 10000 for three __fundamental_types floating-point types,
|
||||
and one __multiprecision type __cpp_bin_float using 50 decimal digit precision, using four algorithms.
|
||||
|
||||
The 'exact' answer was computed using a 100 decimal digit type:
|
||||
|
||||
cpp_bin_float_100 full_answer ("3.036588971875662519420809578505669635581453977248111123242141654169177268411884961770250390838097895");
|
||||
|
||||
Times were measured using __boost_timer using `class cpu_timer`.
|
||||
|
||||
* ['Its] is the number of iterations.
|
||||
* ['Times] is the CPU time-taken in arbitrary units.
|
||||
* ['Norm] is a normalized time, in comparison to the quickest algorithm (with value 1.00).
|
||||
* ['Dis] is the distance from the nearest representation of the 'exact' root in bits.
|
||||
Distance from the 'exact' answer is measured by using function __float_distance.
|
||||
One or two bits distance means that all results are effectively 'correct'.
|
||||
Zero means 'exact' - the nearest __representable value for the floating-point type.
|
||||
|
||||
The cube-root function is a simple function, and is a contrived example for root-finding.
|
||||
It does allow us to investigate some of the factors controlling efficiency that may be extrapolated to
|
||||
more complex functions.
|
||||
|
||||
The program used was [@ ../../example/root_finding_algorithms.cpp root_finding_algorithms.cpp].
|
||||
100000 evaluations of each floating-point type and algorithm were used and the CPU times were
|
||||
judged from repeat runs to have an uncertainty of 10 %. Comparing MSVC for `double` and `long double`
|
||||
(which are identical on this patform) may give a guide to uncertainty of timing.
|
||||
|
||||
* The C++ Standard cube root function [@http://en.cppreference.com/w/cpp/numeric/math/cbrt std::cbrt]
|
||||
is only defined for built-in or fundamental types,
|
||||
so cannot be used with any User-Defined floating-point types like __multiprecision.
|
||||
This, and that the cube function is so impeccably-behaved,
|
||||
allows the implementer to use many tricks to achieve a fast computation.
|
||||
On some platforms,`std::cbrt` appeared several times as quick as the more general `boost::math::cbrt`,
|
||||
but results were highly dependent on hardware, compiler and options, 32 or 64-bit and platform.
|
||||
|
||||
* Two compilers in optimise mode were compared: GCC 4.9.1 using Netbeans IDS
|
||||
and Microsoft Visual Studio 2013 (Update 1) on the same hardware.
|
||||
The number of iterations seemed consistent, but the relative run-times surprisingly different.
|
||||
|
||||
* `boost::math::cbrt` allows use with ['any user-defined floating-point type], conveniently
|
||||
__multiprecision. It too can take some advantage of the good-behaviour of the cube function,
|
||||
compared to the more general implementation in the nth root-finding examples. For example,
|
||||
it uses a polynomial to generate a better guess than dividing the exponent by three,
|
||||
and can avoid the complex checks in __newton required to prevent the
|
||||
search going wildly off-track. For a known precision, it may also be possible to
|
||||
fix the number of iterations, allowing inlining. Typically, it was found that computation using type `double`
|
||||
took a few times longer when using the various root-finding algorithms directly.
|
||||
|
||||
* The importance of getting a good guess can be shown by using the `std::pow(x, 1.L/3)` function call
|
||||
to obtain a `double` or `long double` 15 decimal-digit precision guess at cube-root
|
||||
(much closer than the simple divide-exponent-by-3 method to get a 'guess').
|
||||
Using Halley's algorithm, it only took [*a single iteration] to achieve 50 decimal-digit precision.
|
||||
The limitation of this tatic is that the range of possible (exponent) values may be less than the multiprecision type.
|
||||
|
||||
* Using type `float` and __TOMS748, a few less iterations were required, but the time the same as Newton-Raphson.
|
||||
|
||||
* For __fundamental_types, there was little to choose between the three derivative methods,
|
||||
but for __cpp_bin_float, __newton was twice as fast.
|
||||
|
||||
* Compiling with optimisation halved computation times, and any differences between algorithms
|
||||
became nearly negligible. The optimisation speed-up of the __TOMS748 was especially noticable.
|
||||
|
||||
* Using a multiprecision type like `cpp_bin_float_50` for a precision of 50 decimal digits
|
||||
took a lot longer, as expected because most computation
|
||||
uses software rather than 64-bit floating-point hardware.
|
||||
Speeds are often more than 50 times slower.
|
||||
|
||||
* Using `cpp_bin_float_50`, __TOMS748 was much slower showing the benefit of using derivatives.
|
||||
__newton was found to be twice as quick as either of the second-derivative methods:
|
||||
this must reflect the computational cost of calculating and using the extra derivatives
|
||||
versus saving one or two iterations.
|
||||
|
||||
* Only one or two extra ['iterations] are needed to get the remaining 35 digits, whatever the algorithm used.
|
||||
(The time taken was of course much greater for __multiprecision types).
|
||||
|
||||
* Using a 100 decimal-digit type only doubled the time and required only a very few more iterations,
|
||||
so the cost of extra precision is mainly the underlying cost of computing more digits,
|
||||
not in the way the algorithm works. This confirms previous observations using __NTL high-precision types.
|
||||
|
||||
* Experiment suggests that decreasing the number of bits of accuracy required from the maximum possible,
|
||||
for example, to 3/4, does not decrease the accuracy as measured by the floating-point distances:
|
||||
they remain essentially 'right'.
|
||||
This suggests that requiring the maximum-possible accuracy means that an extra unproductive iteration may take place.
|
||||
|
||||
[include root_comparison_tables_gcc_075.qbk]
|
||||
[include root_comparison_tables_msvc_075.qbk]
|
||||
[include root_comparison_tables_gcc.qbk]
|
||||
[include root_comparison_tables_msvc.qbk]
|
||||
|
||||
[endsect] [/section:cbrt_comparison Comparison of Cube Root Finding Algorithms]
|
||||
|
||||
[section:root_n_comparison Comparison of Nth-root Finding Algorithms]
|
||||
|
||||
A second example compares four generalized nth-root finding algorithms for various n-th roots (5, 7 and 13)
|
||||
of a single value 28.0, for four floating-point types, `float`, `double`,
|
||||
`long double` and a __multiprecision type __cpp_bin_float_50
|
||||
and required all and only three-quarters available digits of accuracy.
|
||||
|
||||
Tests used Microsoft Visual Studio 2013 (Update 1) and GCC 4.9.1 using source code
|
||||
[@../../example/root_n_finding_algorithms.cpp root_n_finding_algorithms.cpp].
|
||||
|
||||
The timing uncertainty (especially using MSVC) is at least 5% of normalized time 'Norm'.
|
||||
|
||||
To pick out the 'best' and 'worst' algorithms are highlighted in blue and red.
|
||||
More than one result can be 'best' when normalized times are indistinguishable
|
||||
within the uncertainty.
|
||||
|
||||
[/include roots_table_100_msvc.qbk]
|
||||
[/include roots_table_75_msvc.qbk]
|
||||
|
||||
[include roots_table_75_msvc_X86.qbk]
|
||||
[include roots_table_100_msvc_X86.qbk]
|
||||
|
||||
[/include roots_table_100_msvc_AVX.qbk]
|
||||
[/include roots_table_75_msvc_AVX.qbk]
|
||||
|
||||
[include roots_table_75_msvc_X86_SSE2.qbk]
|
||||
[include roots_table_100_msvc_X86_SSE2.qbk]
|
||||
|
||||
[include roots_table_100_gcc_X64_SSE2.qbk]
|
||||
[include roots_table_75_gcc_X64_SSE2.qbk]
|
||||
|
||||
[include type_info_table_100_msvc.qbk]
|
||||
[include type_info_table_75_msvc.qbk]
|
||||
|
||||
Some tentative conclusions can be drawn from this limited exercise.
|
||||
|
||||
* Perhaps surprisingly, there is little difference between the various algorithms for __fundamental_types floating-point types.
|
||||
Using the first derivatives (__newton) is usually the best, but the improvement over the no-derivative
|
||||
__TOMS748 is considerable in number of iterations, but little in execution time.
|
||||
|
||||
* The extra cost of evaluating the second derivatives (__halley or __schroeder) is usually too much for any net benefit.
|
||||
|
||||
* __halley usually seems better than __schroeder, but for no obvious reason.
|
||||
|
||||
* For a __multiprecision floating-point type, the __newton is a clear winner with a several-fold gain over __TOMS748,
|
||||
and again no improvement from the second-derivative algorithms.
|
||||
|
||||
* The run-time of 50 decimal-digit __multiprecision is about 30-fold greater than `double`.
|
||||
|
||||
* The column 'dis' showing the number of bits distance from the correct result.
|
||||
The Newton-Raphson algorithm shows a bit or two better accuracy than __TOMS748.
|
||||
Multiprecision types have a number of __guard_digits and usually get exactly correct results.
|
||||
|
||||
* The goodness of the 'guess' is especially crucial for __multiprecision.
|
||||
Separate experiments show that evaluating the 'guess' using `double` allows
|
||||
convergence to the final exact result in one or two iterations.
|
||||
So in this contrived example, crudely dividing the exponent by N for a 'guess',
|
||||
it would be far better to use a `pow<double>` or ,
|
||||
if more precise `pow<long double>`, function to estimate a 'guess'.
|
||||
The limitation of this tatic is that the range of possible (exponent) values may be less than the multiprecision type.
|
||||
|
||||
|
||||
* Reducing the number of bits of accuracy to three-quarters required,
|
||||
only reduced the time several percent, and the accuracy barely at all.
|
||||
|
||||
* Using floating-point extension __SSE2 made a modest ten-percent speedup.
|
||||
|
||||
*Using MSVC, there was some improvement using 64-bit, markedly for __multiprecision.
|
||||
|
||||
* The GCC compiler 4.9.1 using 64-bit was at least five-folder faster,
|
||||
apparently reflecting better optimization.
|
||||
|
||||
Clearly, your mileage [*will vary], but in summary, __newton seems the first choice of algorithm,
|
||||
and effort to find a good 'guess' the first speed-up target, especially for __multiprecision.
|
||||
And of course, compiler optimisation is crucial for speed.
|
||||
|
||||
[endsect] [/section:root_n_comparison Comparison of Nth-root Finding Algorithms]
|
||||
|
||||
[endsect] [/section:root_comparison Comparison of Root Finding Algorithms]
|
||||
|
||||
27
doc/roots/root_comparison_tables_gcc.qbk
Normal file
27
doc/roots/root_comparison_tables_gcc.qbk
Normal file
@@ -0,0 +1,27 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h5 Program i:/modular-boost/libs/math/example/root_finding_algorithms.cpp, GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32, Compiled in optimise mode.[br]1000000 evaluations of each of 5 root_finding algorithms.[br]Fraction of maximum possible bits of accuracy required is 1]
|
||||
[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][24]]
|
||||
[[double][17][53][53]]
|
||||
[[long double][21][64][64]]
|
||||
[[cpp_bin_float_50][52][168][168]]
|
||||
] [/table cbrt_5]
|
||||
|
||||
[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algorithm][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[cbrt ][ 0][46875][1.0][ 0][ ][ 0][140625][1.0][ 0][ ][ 0][109375][1.0][ 0][ ][ 0][3906250][1.0][ 0][ ]]
|
||||
[[TOMS748 ][ 8][296875][6.3][ -1][ ][ 11][500000][3.6][ 2][ ][ 10][1828125][17.][ -1][ ][ 7][53562500][14.][ -2][ ]]
|
||||
[[Newton ][ 6][140625][3.0][ 0][ ][ 7][156250][1.1][ 0][ ][ 8][531250][4.9][ -1][ ][ 9][12625000][3.2][ -1][ ]]
|
||||
[[Halley ][ 4][156250][3.3][ 0][ ][ 5][187500][1.3][ 0][ ][ 5][671875][6.1][ -1][ ][ 6][20625000][5.3][ 0][ ]]
|
||||
[[Schroeder][ 5][156250][3.3][ 0][ ][ 6][203125][1.4][ 0][ ][ 6][734375][6.7][ 0][ ][ 7][22656250][5.8][ 0][ ]]
|
||||
] [/end of table cbrt_4]
|
||||
27
doc/roots/root_comparison_tables_gcc_075.qbk
Normal file
27
doc/roots/root_comparison_tables_gcc_075.qbk
Normal file
@@ -0,0 +1,27 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h5 Program i:/modular-boost/libs/math/example/root_finding_algorithms.cpp, GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32, [br]1000000 evaluations of each of 5 root_finding algorithms.[br]Fraction of maximum possible bits of accuracy required is 0.75]
|
||||
[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][18]]
|
||||
[[double][17][53][39]]
|
||||
[[long double][21][64][48]]
|
||||
[[cpp_bin_float_50][52][168][126]]
|
||||
] [/table cbrt_5]
|
||||
|
||||
[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algorithm][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[cbrt ][ 0][187500][1.0][ 0][ ][ 0][390625][1.0][ 0][ ][ 0][406250][1.0][ 0][ ][ 0][25468750][1.0][ 0][ ]]
|
||||
[[TOMS748 ][ 8][1343750][7.2][ -1][ ][ 11][2140625][5.5][ 2][ ][ 10][4796875][12.][ -1][ ][ 7][300296875][12.][ -2][ ]]
|
||||
[[Newton ][ 6][562500][3.0][ 0][ ][ 7][578125][1.5][ 0][ ][ 7][1703125][4.2][ 0][ ][ 9][71203125][2.8][ -1][ ]]
|
||||
[[Halley ][ 4][765625][4.1][ 0][ ][ 4][703125][1.8][ 0][ ][ 5][1750000][4.3][ -1][ ][ 5][95140625][3.7][ 0][ ]]
|
||||
[[Schroeder][ 5][875000][4.7][ 0][ ][ 5][828125][2.1][ 0][ ][ 6][2046875][5.0][ 0][ ][ 7][122906250][4.8][ 0][ ]]
|
||||
] [/end of table cbrt_4]
|
||||
27
doc/roots/root_comparison_tables_msvc.qbk
Normal file
27
doc/roots/root_comparison_tables_msvc.qbk
Normal file
@@ -0,0 +1,27 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h5 Program I:\modular-boost\libs\math\example\root_finding_algorithms.cpp, Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32, Compiled in optimise mode.[br]1000000 evaluations of each of 5 root_finding algorithms.[br]Fraction of maximum possible bits of accuracy required is 1]
|
||||
[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][24]]
|
||||
[[double][17][53][53]]
|
||||
[[long double][17][53][53]]
|
||||
[[cpp_bin_float_50][52][168][168]]
|
||||
] [/table cbrt_5]
|
||||
|
||||
[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algorithm][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[cbrt ][ 0][203125][1.0][ 0][ ][ 0][203125][1.0][ 1][ ][ 0][203125][1.0][ 1][ ][ 0][9312500][1.0][ 0][ ]]
|
||||
[[TOMS748 ][ 8][859375][4.2][ -1][ ][ 11][1109375][5.5][ 2][ ][ 11][1140625][5.6][ 2][ ][ 7][130703125][14.][ -2][ ]]
|
||||
[[Newton ][ 6][1062500][5.2][ 0][ ][ 7][1015625][5.0][ 0][ ][ 7][1031250][5.1][ 0][ ][ 9][33640625][3.6][ -1][ ]]
|
||||
[[Halley ][ 4][1046875][5.2][ 0][ ][ 5][1093750][5.4][ 0][ ][ 5][1078125][5.3][ 0][ ][ 6][60750000][6.5][ 0][ ]]
|
||||
[[Schroeder][ 5][1078125][5.3][ 0][ ][ 6][1078125][5.3][ 0][ ][ 6][1062500][5.2][ 0][ ][ 7][64343750][6.9][ 0][ ]]
|
||||
] [/end of table cbrt_4]
|
||||
27
doc/roots/root_comparison_tables_msvc_075.qbk
Normal file
27
doc/roots/root_comparison_tables_msvc_075.qbk
Normal file
@@ -0,0 +1,27 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h5 Program I:\modular-boost\libs\math\example\root_finding_algorithms.cpp, Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32, Compiled in optimise mode.[br]1000000 evaluations of each of 5 root_finding algorithms.[br]Fraction of maximum possible bits of accuracy required is 0.75]
|
||||
[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][18]]
|
||||
[[double][17][53][39]]
|
||||
[[long double][17][53][39]]
|
||||
[[cpp_bin_float_50][52][168][126]]
|
||||
] [/table cbrt_5]
|
||||
|
||||
[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algorithm][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[cbrt ][ 0][203125][1.0][ 0][ ][ 0][187500][1.0][ 1][ ][ 0][187500][1.0][ 1][ ][ 0][8796875][1.0][ 0][ ]]
|
||||
[[TOMS748 ][ 8][812500][4.0][ -1][ ][ 11][1031250][5.5][ 2][ ][ 11][1093750][5.8][ 2][ ][ 7][126125000][14.][ -2][ ]]
|
||||
[[Newton ][ 6][968750][4.8][ 0][ ][ 7][968750][5.2][ 0][ ][ 7][1015625][5.4][ 0][ ][ 9][30421875][3.5][ -1][ ]]
|
||||
[[Halley ][ 4][984375][4.8][ 0][ ][ 4][1046875][5.6][ 0][ ][ 4][1078125][5.8][ 0][ ][ 5][47453125][5.4][ 0][ ]]
|
||||
[[Schroeder][ 5][968750][4.8][ 0][ ][ 5][1031250][5.5][ 0][ ][ 5][1000000][5.3][ 0][ ][ 7][59140625][6.7][ 0][ ]]
|
||||
] [/end of table cbrt_4]
|
||||
@@ -45,7 +45,7 @@ __spaces ['f(x) = x[cubed] -a]
|
||||
We will first solve this without using any information
|
||||
about the slope or curvature of the cube root function.
|
||||
|
||||
Fortunately, the cube root function is 'Really Well Behaved' in that it is monotonic
|
||||
Fortunately, the cube-root function is 'Really Well Behaved' in that it is monotonic
|
||||
and has only one root (we leave negative values 'as an exercise for the student').
|
||||
|
||||
We then show how adding what we can know about this function, first just the slope
|
||||
@@ -59,10 +59,10 @@ First we define a function object (functor):
|
||||
|
||||
[root_finding_noderiv_1]
|
||||
|
||||
Implementing the cube root function itself is fairly trivial now:
|
||||
Implementing the cube-root function itself is fairly trivial now:
|
||||
the hardest part is finding a good approximation to begin with.
|
||||
In this case we'll just divide the exponent by three.
|
||||
(There are better but more complex guess algorithms used in 'real-life'.)
|
||||
(There are better but more complex guess algorithms used in 'real life'.)
|
||||
|
||||
[root_finding_noderiv_2]
|
||||
|
||||
@@ -80,7 +80,7 @@ The result of `bracket_and_solve_root` is a [@http://www.cplusplus.com/reference
|
||||
of values that could be displayed.
|
||||
|
||||
Tthe number of bits separating them can be found using `float_distance(r.first, r.second)`.
|
||||
The distance is zero (ideal) for 3[super 3] = 27
|
||||
The distance is zero (closest representable) for 3[super 3] = 27
|
||||
but `float_distance(r.first, r.second) = 3` for cube root of 28 with this function.
|
||||
The result (avoiding overflow) is midway between these two values.
|
||||
|
||||
@@ -94,7 +94,7 @@ For the root function, the 1st differential (the slope of the tangent to a curve
|
||||
This algorithm is similar to this [@http://en.wikipedia.org/wiki/Nth_root_algorithm nth root algorithm].
|
||||
|
||||
If you need some reminders, then
|
||||
[@http://en.wikipedia.org/wiki/Derivative#Derivatives_of_elementary_functions Derivatives of elementary functions]
|
||||
[@http://en.wikipedia.org/wiki/Derivative#Derivatives_of_elementary_functions derivatives of elementary functions]
|
||||
may help.
|
||||
|
||||
Using the rule that the derivative of ['x[super n]] for positive n (actually all nonzero n) is ['n x[super n-1]],
|
||||
@@ -242,7 +242,7 @@ The apocryphally astute reader might, by now, be asking "How do we know if this
|
||||
|
||||
For most values, there is, sadly, no 'right' answer.
|
||||
This is because values can only rarely be ['exactly represented] by C++ floating-point types.
|
||||
What we do want is the 'rightest' representation - one that is the nearest representable value.
|
||||
What we do want is the 'best' representation - one that is the nearest __representable value.
|
||||
(For more about how numbers are represented see __floating_point).
|
||||
|
||||
Of course, we might start with finding an external reference source like
|
||||
@@ -276,7 +276,7 @@ at least `max_digits10` decimal digits (17 for 64-bit `double`).
|
||||
|
||||
If we wish to compute [*higher-precision values] then, on some platforms, we may be able to use `long double`
|
||||
with a higher precision than `double` to compare with the very common `double`
|
||||
and/or a more efficient built-in quad floating-point type like __float128.
|
||||
and/or a more efficient built-in quad floating-point type like `__float128`.
|
||||
|
||||
Almost all platforms can easily use __multiprecision,
|
||||
for example, __cpp_dec_float or a binary type __cpp_bin_float types,
|
||||
@@ -297,7 +297,7 @@ that we can use with these includes:
|
||||
|
||||
[root_finding_multiprecision_include_1]
|
||||
|
||||
Some using statements simply their use:
|
||||
Some using statements simplify their use:
|
||||
|
||||
[root_finding_multiprecision_example_1]
|
||||
|
||||
@@ -338,7 +338,7 @@ used to compute the guess and bracket values as `double`.
|
||||
Even more treacherous is passing a `double` as in `cpp_dec_float_50 r = cbrt_2deriv(2.);`
|
||||
which silently gives the 'wrong' result, computing a `double` result and [*then] converting to `cpp_dec_float_50`!
|
||||
All digits beyond `max_digits10` will be incorrect.
|
||||
Making the `cbrt` type explicit with `cbrt_2deriv<cpp_dec_float_50>(2.);` will give you the desired 5o decimal digit precision result.
|
||||
Making the `cbrt` type explicit with `cbrt_2deriv<cpp_dec_float_50>(2.);` will give you the desired 50 decimal digit precision result.
|
||||
] [/tip]
|
||||
|
||||
[h3:nth_root Generalizing to Compute the nth root]
|
||||
@@ -349,7 +349,7 @@ where template parameter `N` is an integer. Our functor and function now have a
|
||||
for the root required.
|
||||
|
||||
[note Since this is a compile-time static process, the resulting code is as efficient as as if hand-coded as the cube and fifth-root examples above.
|
||||
The compiler should also optimise any repeated multiplications.]
|
||||
A good compiler should also optimise any repeated multiplications.]
|
||||
|
||||
Our ['n]th root functor is
|
||||
|
||||
|
||||
30
doc/roots/root_n_comparison_tables.qbk
Normal file
30
doc/roots/root_n_comparison_tables.qbk
Normal file
@@ -0,0 +1,30 @@
|
||||
[/
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode.
|
||||
|
||||
Fraction of maximum possible bits of accuracy required is 0.75
|
||||
[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][18]]
|
||||
[[double][17][53][39]]
|
||||
[[long double][17][53][39]]
|
||||
] [/table cbrt_5]
|
||||
|
||||
[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[cbrt ][ 0][ 156][1.00][ 0][ ][ 0][ 156][1.00][ 1][ ][ 0][ 156][1.00][ 1][ ]]
|
||||
[[TOMS748 ][ 8][ 781][5.01][ -1][ ][ 11][ 1093][7.01][ 2][ ][ 11][ 1093][7.01][ 2][ ]]
|
||||
[[Newton ][ 6][ 1093][7.01][ 0][ ][ 7][ 1093][7.01][ 0][ ][ 7][ 937][6.01][ 0][ ]]
|
||||
[[Halley ][ 4][ 1093][7.01][ 0][ ][ 4][ 937][6.01][ 0][ ][ 4][ 937][6.01][ 0][ ]]
|
||||
[[Schroeder][ 5][ 1093][7.01][ 0][ ][ 5][ 1093][7.01][ 0][ ][ 5][ 1093][7.01][ 0][ ]]
|
||||
] [/end of table cbrt_4]
|
||||
@@ -44,7 +44,7 @@ The functions all take the same parameters:
|
||||
|
||||
[variablelist Parameters of the root finding functions
|
||||
[[F f] [Type F must be a callable function object that accepts one parameter and
|
||||
returns a __tuple:
|
||||
returns a __tuple_type:
|
||||
|
||||
For second-order iterative method ([@http://en.wikipedia.org/wiki/Newton_Raphson Newton Raphson])
|
||||
the __tuple should have [*two] elements containing the evaluation
|
||||
@@ -53,15 +53,15 @@ For second-order iterative method ([@http://en.wikipedia.org/wiki/Newton_Raphson
|
||||
For the third-order methods
|
||||
([@http://en.wikipedia.org/wiki/Halley%27s_method Halley] and
|
||||
Schroeder)
|
||||
the __tuple should have *three* elements containing the evaluation of
|
||||
the `tuple` should have [*three*] elements containing the evaluation of
|
||||
the function and its first and second derivatives.]]
|
||||
[[T guess] [The initial starting value. A good guess is crucial to quick convergence!]]
|
||||
[[T min] [The minimum possible value for the result, this is used as an initial lower bracket.]]
|
||||
[[T max] [The maximum possible value for the result, this is used as an initial upper bracket.]]
|
||||
[[int digits] [The desired number of binary digits precision.]]
|
||||
[[uintmax_t& max_iter] [An optional maximum number of iterations to perform. On exit, this is updated to the actual number of iterations performed.]]
|
||||
[[T] [Floating-point type, typically `double`, often deduced by __ADL.]]
|
||||
[[F] [Floating-point types of the functor, usually deduced from T by __ADL, so it is rarely necessary to define F.]]
|
||||
[[T] [Floating-point type, typically `double`, ]]
|
||||
[[F] [Unary Functor that returns any suitable floating-point type T. ]]
|
||||
]
|
||||
|
||||
When using these functions you should note that:
|
||||
|
||||
@@ -14,12 +14,12 @@ There are several fully-worked __root_finding_examples, including:
|
||||
* __root_finding_example_cbrt_without_derivatives
|
||||
* __root_finding_example_cbrt_with_1_derivative
|
||||
* __root_finding_example_cbrt_with_2_derivatives
|
||||
* __brent_minima for a simple function.
|
||||
|
||||
[include roots_without_derivatives.qbk]
|
||||
[include roots.qbk]
|
||||
[include root_finding_examples.qbk]
|
||||
[include minima.qbk]
|
||||
[include root_comparison.qbk]
|
||||
|
||||
[/ roots_overview.qbk
|
||||
Copyright 2015 John Maddock and Paul A. Bristow.
|
||||
|
||||
37
doc/roots/roots_table_100_gcc_SEE_SEE2_X64.qbk
Normal file
37
doc/roots/roots_table_100_gcc_SEE_SEE2_X64.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_gcc_SEE SEE2 X64 .qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program i:/modular-boost/libs/math/example/root_n_finding_algorithms.cpp,
|
||||
GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32
|
||||
Compiled in optimise mode.]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 296][2.72][ 0][ ][ 11][ 500][3.57][ 1][ ][ 9][ 1593][4.25][ 0][ ][ 12][74953][7.01][ 0][ ]]
|
||||
[[Newton ][ 3][ 109][1.00][ 0][ ][ 5][ 140][1.00][ -1][ ][ 4][ 375][1.00][ 0][ ][ 6][10687][1.00][ 0][ ]]
|
||||
[[Halley ][ 2][ 109][1.00][ 0][ ][ 4][ 171][1.22][ 0][ ][ 3][ 453][1.21][ 0][ ][ 4][17578][1.64][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][1.86][ 0][ ][ 8][ 250][1.79][ -1][ ][ 7][ 609][1.62][ 0][ ][ 8][33546][3.14][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 500][3.21][ 1][ ][ 15][ 687][4.40][ 2][ ][ 13][ 2390][5.11][ 0][ ][ 14][99765][5.95][ 0][ ]]
|
||||
[[Newton ][ 6][ 156][1.00][ 0][ ][ 7][ 156][1.00][ 0][ ][ 6][ 468][1.00][ 0][ ][ 8][16765][1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][1.20][ 0][ ][ 6][ 218][1.40][ 0][ ][ 5][ 796][1.70][ 0][ ][ 6][29250][1.74][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][1.30][ 0][ ][ 6][ 234][1.50][ 0][ ][ 6][ 531][1.13][ 0][ ][ 7][30687][1.83][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 593][3.47][ -2][ ][ 14][ 734][3.93][ 2][ ][ 14][ 2750][5.18][ 1][ ][ 17][155921][7.06][ 2][ ]]
|
||||
[[Newton ][ 7][ 171][1.00][ 0][ ][ 8][ 187][1.00][ 0][ ][ 8][ 531][1.00][ 0][ ][ 10][22093][1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][1.09][ 0][ ][ 6][ 234][1.25][ 0][ ][ 6][ 703][1.32][ 0][ ][ 7][36375][1.65][ 0][ ]]
|
||||
[[Schroeder][ 7][ 234][1.37][ 0][ ][ 7][ 250][1.34][ 0][ ][ 8][ 625][1.18][ 0][ ][ 8][37843][1.71][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_100_gcc_X64_SSE2.qbk
Normal file
37
doc/roots/roots_table_100_gcc_X64_SSE2.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_gcc_X64_SSE2 _X64.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program i:/modular-boost/libs/math/example/root_n_finding_algorithms.cpp,
|
||||
GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32
|
||||
Compiled in optimise mode., _X64_SSE2]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 265][2.43][ 0][ ][ 11][ 468][3.34][ 1][ ][ 9][ 1531][4.08][ 0][ ][ 12][66937][[role red 6.66]][ 0][ ]]
|
||||
[[Newton ][ 3][ 109][[role blue 1.00]][ 0][ ][ 5][ 140][[role blue 1.00]][ -1][ ][ 4][ 375][[role blue 1.00]][ 0][ ][ 6][10046][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 109][[role blue 1.00]][ 0][ ][ 4][ 171][[role blue 1.22]][ 0][ ][ 3][ 468][[role blue 1.25]][ 0][ ][ 4][16390][[role blue 1.63]][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][[role blue 1.86]][ 0][ ][ 8][ 250][[role blue 1.79]][ -1][ ][ 7][ 593][[role blue 1.58]][ 0][ ][ 8][30890][3.07][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 468][3.34][ 1][ ][ 15][ 671][3.92][ 2][ ][ 13][ 2359][[role red 5.21]][ 0][ ][ 14][89843][[role red 5.83]][ 0][ ]]
|
||||
[[Newton ][ 6][ 140][[role blue 1.00]][ 0][ ][ 7][ 171][[role blue 1.00]][ 0][ ][ 6][ 453][[role blue 1.00]][ 0][ ][ 8][15421][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][[role blue 1.34]][ 0][ ][ 6][ 218][[role blue 1.27]][ 0][ ][ 5][ 718][[role blue 1.58]][ 0][ ][ 6][27937][[role blue 1.81]][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][[role blue 1.45]][ 0][ ][ 6][ 203][[role blue 1.19]][ 0][ ][ 6][ 531][[role blue 1.17]][ 0][ ][ 7][28703][[role blue 1.86]][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 562][3.29][ -2][ ][ 14][ 718][3.84][ 2][ ][ 14][ 2734][[role red 5.15]][ 1][ ][ 17][132031][[role red 6.77]][ 2][ ]]
|
||||
[[Newton ][ 7][ 171][[role blue 1.00]][ 0][ ][ 8][ 187][[role blue 1.00]][ 0][ ][ 8][ 531][[role blue 1.00]][ 0][ ][ 10][19515][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][[role blue 1.09]][ 0][ ][ 6][ 218][[role blue 1.17]][ 0][ ][ 6][ 656][[role blue 1.24]][ 0][ ][ 7][32203][[role blue 1.65]][ 0][ ]]
|
||||
[[Schroeder][ 7][ 234][[role blue 1.37]][ 0][ ][ 7][ 234][[role blue 1.25]][ 0][ ][ 8][ 625][[role blue 1.18]][ 0][ ][ 8][34187][[role blue 1.75]][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_100_msvc.qbk
Normal file
37
doc/roots/roots_table_100_msvc.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_msvc.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode.]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 750][[role blue 1.00]][ 0][ ][ 11][ 1015][1.08][ 1][ ][ 11][ 1000][1.03][ 1][ ][ 12][145687][[role red 6.07]][ 0][ ]]
|
||||
[[Newton ][ 3][ 890][1.19][ 0][ ][ 5][ 937][[role blue 1.00]][ -1][ ][ 5][ 968][[role blue 1.00]][ -1][ ][ 6][24000][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 921][1.23][ 0][ ][ 4][ 953][[role blue 1.02]][ 0][ ][ 4][ 968][[role blue 1.00]][ 0][ ][ 4][41468][1.73][ 0][ ]]
|
||||
[[Schroeder][ 6][ 984][1.31][ 0][ ][ 8][ 1062][1.13][ -1][ ][ 8][ 1046][1.08][ -1][ ][ 8][72062][3.00][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1015][1.07][ 1][ ][ 15][ 1218][1.22][ 2][ ][ 15][ 1218][1.24][ 2][ ][ 14][191937][[role red 5.43]][ 0][ ]]
|
||||
[[Newton ][ 6][ 953][[role blue 1.00]][ 0][ ][ 7][ 1000][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 8][35359][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 984][1.03][ 0][ ][ 6][ 1031][1.03][ 0][ ][ 6][ 1015][1.03][ 0][ ][ 6][66968][1.89][ 0][ ]]
|
||||
[[Schroeder][ 6][ 984][1.03][ 0][ ][ 6][ 1000][[role blue 1.00]][ 0][ ][ 6][ 1000][[role blue 1.02]][ 0][ ][ 7][67437][1.91][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1078][1.11][ -2][ ][ 14][ 1312][1.33][ 2][ ][ 14][ 1296][1.28][ 2][ ][ 17][294640][[role red 6.24]][ 2][ ]]
|
||||
[[Newton ][ 7][ 968][[role blue 1.00]][ 0][ ][ 8][ 984][[role blue 1.00]][ 0][ ][ 8][ 1015][[role blue 1.00]][ 0][ ][ 10][47187][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][1.03][ 0][ ][ 6][ 1046][1.06][ 0][ ][ 6][ 1109][1.09][ 0][ ][ 7][79187][1.68][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1062][1.10][ 0][ ][ 7][ 1062][1.08][ 0][ ][ 7][ 1062][1.05][ 0][ ][ 8][78406][1.66][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_100_msvc_AVX.qbk
Normal file
37
doc/roots/roots_table_100_msvc_AVX.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_msvc_AVX.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _AVX]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 734][[role green 1.0000]1.00][ 0][ ][ 11][ 1015][1.06511.07][ 1][ ][ 11][ 1031][1.08181.08][ 1][ ][ 12][145968][[role red 5.8941]5.89][ 0][ ]]
|
||||
[[Newton ][ 3][ 906][1.23431.23][ 0][ ][ 5][ 953][[role green 1.0000]1.00][ -1][ ][ 5][ 953][[role green 1.0000]1.00][ -1][ ][ 6][24765][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 2][ 921][1.25481.25][ 0][ ][ 4][ 1015][1.06511.07][ 0][ ][ 4][ 1000][1.04931.05][ 0][ ][ 4][42156][1.70221.70][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1000][1.36241.36][ 0][ ][ 8][ 1062][1.11441.11][ -1][ ][ 8][ 1062][1.11441.11][ -1][ ][ 8][72500][2.92752.93][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 984][1.03251.03][ 1][ ][ 15][ 1234][1.25411.25][ 2][ ][ 15][ 1218][1.23781.24][ 2][ ][ 14][191484][[role red 5.3353]5.34][ 0][ ]]
|
||||
[[Newton ][ 6][ 953][[role green 1.0000]1.00][ 0][ ][ 7][ 984][[role green 1.0000]1.00][ 0][ ][ 7][ 984][[role green 1.0000]1.00][ 0][ ][ 8][35890][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][1.04931.05][ 0][ ][ 6][ 1046][1.06301.06][ 0][ ][ 6][ 1046][1.06301.06][ 0][ ][ 6][66859][1.86291.86][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1015][1.06511.07][ 0][ ][ 6][ 1015][1.03151.03][ 0][ ][ 6][ 1000][[role green 1.0163]1.02][ 0][ ][ 7][68375][1.90511.91][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1078][1.09551.10][ -2][ ][ 14][ 1265][1.22701.23][ 2][ ][ 14][ 1265][1.22701.23][ 2][ ][ 17][288593][[role red 6.3844]6.38][ 2][ ]]
|
||||
[[Newton ][ 7][ 984][[role green 1.0000]1.00][ 0][ ][ 8][ 1031][[role green 1.0000]1.00][ 0][ ][ 8][ 1031][[role green 1.0000]1.00][ 0][ ][ 10][45203][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 1015][1.03151.03][ 0][ ][ 6][ 1078][1.04561.05][ 0][ ][ 6][ 1062][1.03011.03][ 0][ ][ 7][77625][1.71731.72][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1031][1.04781.05][ 0][ ][ 7][ 1046][[role green 1.0145]1.01][ 0][ ][ 7][ 1031][[role green 1.0000]1.00][ 0][ ][ 8][77718][1.71931.72][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_100_msvc_X86.qbk
Normal file
37
doc/roots/roots_table_100_msvc_X86.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_msvc_X86.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _X86]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 8][ 1109][1.08][ -2][ ][ 11][ 1265][1.29][ 1][ ][ 11][ 1203][1.22][ 1][ ][ 12][145453][[role red 5.95]][ 0][ ]]
|
||||
[[Newton ][ 4][ 1031][[role blue 1.00]][ 0][ ][ 5][ 984][[role blue 1.00]][ -1][ ][ 5][ 984][[role blue 1.00]][ -1][ ][ 6][24453][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 3][ 1046][[role blue 1.01]][ 0][ ][ 4][ 1046][1.06][ 0][ ][ 4][ 1046][1.06][ 0][ ][ 4][40921][1.67][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1250][1.21][ 0][ ][ 8][ 1078][1.10][ -1][ ][ 8][ 1078][1.10][ -1][ ][ 8][70750][2.89][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1562][1.39][ 1][ ][ 15][ 1484][1.51][ 2][ ][ 15][ 1437][1.46][ 2][ ][ 14][188640][[role red 5.29]][ 0][ ]]
|
||||
[[Newton ][ 6][ 1125][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 8][35640][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1156][[role blue 1.03]][ 0][ ][ 6][ 1125][1.14][ 0][ ][ 6][ 1109][1.13][ 0][ ][ 6][65218][1.83][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1187][1.06][ 0][ ][ 6][ 1031][[role blue 1.05]][ 0][ ][ 6][ 1015][[role blue 1.03]][ 0][ ][ 7][66828][1.88][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1812][1.49][ -2][ ][ 14][ 1531][1.48][ 2][ ][ 14][ 1500][1.43][ 2][ ][ 17][284937][[role red 6.38]][ 2][ ]]
|
||||
[[Newton ][ 7][ 1218][[role blue 1.00]][ -1][ ][ 8][ 1031][[role blue 1.00]][ 0][ ][ 8][ 1046][[role blue 1.00]][ 0][ ][ 10][44640][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1265][[role blue 1.04]][ -1][ ][ 6][ 1156][1.12][ 0][ ][ 6][ 1140][1.09][ 0][ ][ 7][77843][1.74][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1343][1.10][ -1][ ][ 7][ 1046][[role blue 1.01]][ 0][ ][ 7][ 1109][1.06][ 0][ ][ 8][77343][1.73][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_100_msvc_X86_SSE2.qbk
Normal file
37
doc/roots/roots_table_100_msvc_X86_SSE2.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_100_msvc_X86_SSE2 .qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _X86_SSE2 ]
|
||||
Fraction of full accuracy 1
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 765][[role blue 1.00]][ 0][ ][ 11][ 1046][1.10][ 1][ ][ 11][ 1015][[role blue 1.05]][ 1][ ][ 12][146437][[role red 5.98]][ 0][ ]]
|
||||
[[Newton ][ 3][ 890][1.16][ 0][ ][ 5][ 953][[role blue 1.00]][ -1][ ][ 5][ 968][[role blue 1.00]][ -1][ ][ 6][24468][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 921][1.20][ 0][ ][ 4][ 968][[role blue 1.02]][ 0][ ][ 4][ 968][[role blue 1.00]][ 0][ ][ 4][42437][1.73][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1015][1.33][ 0][ ][ 8][ 1062][1.11][ -1][ ][ 8][ 1062][1.10][ -1][ ][ 8][74203][3.03][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 984][[role blue 1.02]][ 1][ ][ 15][ 1234][1.25][ 2][ ][ 15][ 1250][1.27][ 2][ ][ 14][193953][[role red 5.37]][ 0][ ]]
|
||||
[[Newton ][ 6][ 968][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 8][36109][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 984][[role blue 1.02]][ 0][ ][ 6][ 1078][1.10][ 0][ ][ 6][ 1046][1.06][ 0][ ][ 6][67312][1.86][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1000][[role blue 1.03]][ 0][ ][ 6][ 1046][1.06][ 0][ ][ 6][ 1000][[role blue 1.02]][ 0][ ][ 7][68156][1.89][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1109][1.13][ -2][ ][ 14][ 1296][1.28][ 2][ ][ 14][ 1281][1.26][ 2][ ][ 17][289984][[role red 6.34]][ 2][ ]]
|
||||
[[Newton ][ 7][ 984][[role blue 1.00]][ 0][ ][ 8][ 1015][[role blue 1.00]][ 0][ ][ 8][ 1015][[role blue 1.00]][ 0][ ][ 10][45734][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][[role blue 1.02]][ 0][ ][ 6][ 1046][[role blue 1.03]][ 0][ ][ 6][ 1062][[role blue 1.05]][ 0][ ][ 7][79453][1.74][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1031][[role blue 1.05]][ 0][ ][ 7][ 1078][1.06][ 0][ ][ 7][ 1046][[role blue 1.03]][ 0][ ][ 8][78437][1.72][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_gcc_SEE_SEE2_X64.qbk
Normal file
37
doc/roots/roots_table_75_gcc_SEE_SEE2_X64.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_gcc_SEE SEE2 X64 .qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program i:/modular-boost/libs/math/example/root_n_finding_algorithms.cpp,
|
||||
GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32
|
||||
Compiled in optimise mode.]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 312][2.50][ 0][ ][ 11][ 484][3.46][ 1][ ][ 9][ 1625][4.17][ 0][ ][ 11][67718][6.46][ 0][ ]]
|
||||
[[Newton ][ 3][ 125][1.00][ 0][ ][ 5][ 140][1.00][ -1][ ][ 4][ 390][1.00][ 0][ ][ 6][10484][1.00][ 0][ ]]
|
||||
[[Halley ][ 2][ 125][1.00][ 0][ ][ 3][ 156][1.11][ 0][ ][ 3][ 453][1.16][ 0][ ][ 4][17359][1.66][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][1.62][ 0][ ][ 7][ 234][1.67][ -1][ ][ 7][ 625][1.60][ 0][ ][ 8][35203][3.36][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 531][3.40][ 1][ ][ 15][ 734][4.29][ 2][ ][ 13][ 2437][5.04][ 0][ ][ 14][105421][6.48][ 0][ ]]
|
||||
[[Newton ][ 5][ 156][1.00][ 0][ ][ 7][ 171][1.00][ 0][ ][ 6][ 484][1.00][ 0][ ][ 8][16281][1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][1.20][ 0][ ][ 6][ 234][1.37][ 0][ ][ 5][ 796][1.64][ 0][ ][ 6][30781][1.89][ 0][ ]]
|
||||
[[Schroeder][ 5][ 187][1.20][ 0][ ][ 6][ 218][1.27][ 0][ ][ 6][ 546][1.13][ 0][ ][ 7][30640][1.88][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types.
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 546][3.19][ 0][ ][ 14][ 750][4.01][ 2][ ][ 14][ 2828][5.33][ 1][ ][ 17][153093][7.82][ 2][ ]]
|
||||
[[Newton ][ 6][ 171][1.00][ 0][ ][ 7][ 187][1.00][ 0][ ][ 8][ 531][1.00][ 0][ ][ 9][19578][1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 203][1.19][ 0][ ][ 6][ 234][1.25][ 0][ ][ 6][ 703][1.32][ 0][ ][ 7][36296][1.85][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][1.19][ 0][ ][ 7][ 250][1.34][ 0][ ][ 7][ 578][1.09][ 0][ ][ 8][38046][1.94][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_gcc_X64_SSE2.qbk
Normal file
37
doc/roots/roots_table_75_gcc_X64_SSE2.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_gcc_X64_SSE2 _X64.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program i:/modular-boost/libs/math/example/root_n_finding_algorithms.cpp,
|
||||
GNU C++ version 4.9.1, GNU libstdc++ version 20140716, Win32
|
||||
Compiled in optimise mode., _X64_SSE2]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 250][2.29][ 0][ ][ 11][ 484][3.87][ 1][ ][ 9][ 1546][4.31][ 0][ ][ 11][57453][[role red 6.11]][ 0][ ]]
|
||||
[[Newton ][ 3][ 109][[role blue 1.00]][ 0][ ][ 5][ 125][[role blue 1.00]][ -1][ ][ 4][ 359][[role blue 1.00]][ 0][ ][ 6][ 9406][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 109][[role blue 1.00]][ 0][ ][ 3][ 140][[role blue 1.12]][ 0][ ][ 3][ 453][[role blue 1.26]][ 0][ ][ 4][15359][[role blue 1.63]][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][[role blue 1.86]][ 0][ ][ 7][ 218][[role blue 1.74]][ -1][ ][ 7][ 562][[role blue 1.57]][ 0][ ][ 8][30921][3.29][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 468][3.74][ 1][ ][ 15][ 671][4.30][ 2][ ][ 13][ 2359][[role red 5.21]][ 0][ ][ 14][88515][[role red 6.05]][ 0][ ]]
|
||||
[[Newton ][ 5][ 125][[role blue 1.00]][ 0][ ][ 7][ 156][[role blue 1.00]][ 0][ ][ 6][ 453][[role blue 1.00]][ 0][ ][ 8][14625][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][[role blue 1.50]][ 0][ ][ 6][ 218][[role blue 1.40]][ 0][ ][ 5][ 718][[role blue 1.58]][ 0][ ][ 6][27843][[role blue 1.90]][ 0][ ]]
|
||||
[[Schroeder][ 5][ 171][[role blue 1.37]][ 0][ ][ 6][ 203][[role blue 1.30]][ 0][ ][ 6][ 515][[role blue 1.14]][ 0][ ][ 7][27640][[role blue 1.89]][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X64_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 515][3.30][ 0][ ][ 14][ 718][4.20][ 2][ ][ 14][ 2765][[role red 5.37]][ 1][ ][ 17][132062][[role red 7.46]][ 2][ ]]
|
||||
[[Newton ][ 6][ 156][[role blue 1.00]][ 0][ ][ 7][ 171][[role blue 1.00]][ 0][ ][ 8][ 515][[role blue 1.00]][ 0][ ][ 9][17703][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 187][[role blue 1.20]][ 0][ ][ 6][ 218][[role blue 1.27]][ 0][ ][ 6][ 671][[role blue 1.30]][ 0][ ][ 7][32000][[role blue 1.81]][ 0][ ]]
|
||||
[[Schroeder][ 6][ 203][[role blue 1.30]][ 0][ ][ 7][ 234][[role blue 1.37]][ 0][ ][ 7][ 578][[role blue 1.12]][ 0][ ][ 8][34265][[role blue 1.94]][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_msvc.qbk
Normal file
37
doc/roots/roots_table_75_msvc.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_msvc.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode.]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 750][[role blue 1.00]][ 0][ ][ 11][ 1031][1.10][ 1][ ][ 11][ 1015][1.08][ 1][ ][ 11][125921][[role red 5.53]][ 0][ ]]
|
||||
[[Newton ][ 3][ 906][1.21][ 0][ ][ 5][ 953][[role blue 1.02]][ -1][ ][ 5][ 937][[role blue 1.00]][ -1][ ][ 6][22750][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 921][1.23][ 0][ ][ 3][ 937][[role blue 1.00]][ 0][ ][ 3][ 953][[role blue 1.02]][ 0][ ][ 4][40125][1.76][ 0][ ]]
|
||||
[[Schroeder][ 6][ 984][1.31][ 0][ ][ 7][ 1000][1.07][ -1][ ][ 7][ 1015][1.08][ -1][ ][ 8][73296][3.22][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1015][1.08][ 1][ ][ 15][ 1265][1.29][ 2][ ][ 15][ 1265][1.31][ 2][ ][ 14][198890][[role red 5.61]][ 0][ ]]
|
||||
[[Newton ][ 5][ 937][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 7][ 1000][1.03][ 0][ ][ 8][35437][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 984][1.05][ 0][ ][ 6][ 1078][1.10][ 0][ ][ 6][ 1046][1.08][ 0][ ][ 6][69484][1.96][ 0][ ]]
|
||||
[[Schroeder][ 5][ 953][[role blue 1.02]][ 0][ ][ 6][ 1000][[role blue 1.02]][ 0][ ][ 6][ 968][[role blue 1.00]][ 0][ ][ 7][67937][1.92][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 1093][1.11][ 0][ ][ 14][ 1343][1.34][ 2][ ][ 14][ 1375][1.35][ 2][ ][ 17][303625][[role red 7.07]][ 2][ ]]
|
||||
[[Newton ][ 6][ 984][[role blue 1.00]][ 0][ ][ 7][ 1000][[role blue 1.00]][ 0][ ][ 7][ 1015][[role blue 1.00]][ 0][ ][ 9][42921][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1031][1.05][ 0][ ][ 6][ 1093][1.09][ 0][ ][ 6][ 1093][1.08][ 0][ ][ 7][83062][1.94][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1046][1.06][ 0][ ][ 7][ 1093][1.09][ 0][ ][ 7][ 1046][1.03][ 0][ ][ 8][86234][2.01][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_msvc_AVX.qbk
Normal file
37
doc/roots/roots_table_75_msvc_AVX.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_msvc_AVX.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _AVX]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 750][[role green 1.0000]1.00][ 0][ ][ 11][ 1031][1.10031.10][ 1][ ][ 11][ 1046][1.09761.10][ 1][ ][ 11][126781][[role red 5.5348]5.53][ 0][ ]]
|
||||
[[Newton ][ 3][ 890][1.18671.19][ 0][ ][ 5][ 937][[role green 1.0000]1.00][ -1][ ][ 5][ 953][[role green 1.0000]1.00][ -1][ ][ 6][22906][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 2][ 937][1.24931.25][ 0][ ][ 3][ 968][1.03311.03][ 0][ ][ 3][ 953][[role green 1.0000]1.00][ 0][ ][ 4][40265][1.75781.76][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1000][1.33331.33][ 0][ ][ 7][ 1031][1.10031.10][ -1][ ][ 7][ 1031][1.08181.08][ -1][ ][ 8][72296][3.15623.16][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 984][1.03251.03][ 1][ ][ 15][ 1218][1.21801.22][ 2][ ][ 15][ 1250][1.29131.29][ 2][ ][ 14][191500][[role red 5.5965]5.60][ 0][ ]]
|
||||
[[Newton ][ 5][ 953][[role green 1.0000]1.00][ 0][ ][ 7][ 1062][1.06201.06][ 0][ ][ 7][ 968][[role green 1.0000]1.00][ 0][ ][ 8][34218][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][1.04931.05][ 0][ ][ 6][ 1109][1.10901.11][ 0][ ][ 6][ 1078][1.11361.11][ 0][ ][ 6][66765][1.95121.95][ 0][ ]]
|
||||
[[Schroeder][ 5][ 984][1.03251.03][ 0][ ][ 6][ 1000][[role green 1.0000]1.00][ 0][ ][ 6][ 1000][1.03311.03][ 0][ ][ 7][65703][1.92011.92][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _AVX
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 1062][1.09711.10][ 0][ ][ 14][ 1281][1.26211.26][ 2][ ][ 14][ 1328][1.32801.33][ 2][ ][ 17][297875][[role red 7.2323]7.23][ 2][ ]]
|
||||
[[Newton ][ 6][ 968][[role green 1.0000]1.00][ 0][ ][ 7][ 1031][[role green 1.0158]1.02][ 0][ ][ 7][ 1000][[role green 1.0000]1.00][ 0][ ][ 9][41187][[role green 1.0000]1.00][ 0][ ]]
|
||||
[[Halley ][ 5][ 1015][1.04861.05][ 0][ ][ 6][ 1171][1.15371.15][ 0][ ][ 6][ 1093][1.09301.09][ 0][ ][ 7][77984][1.89341.89][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1000][1.03311.03][ 0][ ][ 7][ 1015][[role green 1.0000]1.00][ 0][ ][ 7][ 1046][1.04601.05][ 0][ ][ 8][77781][1.88851.89][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_msvc_X86.qbk
Normal file
37
doc/roots/roots_table_75_msvc_X86.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_msvc_X86.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _X86]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 8][ 1062][1.06][ -2][ ][ 11][ 1171][1.21][ 1][ ][ 11][ 1171][1.21][ 1][ ][ 11][122375][[role red 5.45]][ 0][ ]]
|
||||
[[Newton ][ 3][ 1000][[role blue 1.00]][ 0][ ][ 5][ 968][[role blue 1.00]][ -1][ ][ 5][ 968][[role blue 1.00]][ -1][ ][ 6][22468][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 3][ 1062][1.06][ 0][ ][ 3][ 984][[role blue 1.02]][ 0][ ][ 3][ 984][[role blue 1.02]][ 0][ ][ 4][39234][1.75][ 0][ ]]
|
||||
[[Schroeder][ 7][ 1234][1.23][ 0][ ][ 7][ 1046][1.08][ -1][ ][ 7][ 1031][1.07][ -1][ ][ 8][70406][3.13][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1562][1.47][ 1][ ][ 15][ 1484][1.48][ 2][ ][ 15][ 1453][1.45][ 2][ ][ 14][202265][[role red 5.41]][ 0][ ]]
|
||||
[[Newton ][ 5][ 1062][[role blue 1.00]][ 0][ ][ 7][ 1000][[role blue 1.00]][ 0][ ][ 7][ 1000][[role blue 1.00]][ 0][ ][ 8][37359][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1156][1.09][ 0][ ][ 6][ 1125][1.13][ 0][ ][ 6][ 1109][1.11][ 0][ ][ 6][71843][1.92][ 0][ ]]
|
||||
[[Schroeder][ 5][ 1125][1.06][ 0][ ][ 6][ 1031][[role blue 1.03]][ 0][ ][ 6][ 1031][[role blue 1.03]][ 0][ ][ 7][67875][1.82][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 1703][1.40][ 0][ ][ 14][ 1609][1.52][ 2][ ][ 14][ 1562][1.47][ 2][ ][ 17][290031][[role red 6.93]][ 2][ ]]
|
||||
[[Newton ][ 6][ 1218][[role blue 1.00]][ 0][ ][ 7][ 1062][[role blue 1.00]][ 0][ ][ 7][ 1062][[role blue 1.00]][ 0][ ][ 9][41843][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1265][[role blue 1.04]][ -1][ ][ 6][ 1125][1.06][ 0][ ][ 6][ 1125][1.06][ 0][ ][ 7][75937][1.81][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1296][1.06][ 0][ ][ 7][ 1093][[role blue 1.03]][ 0][ ][ 7][ 1078][[role blue 1.02]][ 0][ ][ 8][77500][1.85][ 0][ ]]
|
||||
] [/end of table root]
|
||||
37
doc/roots/roots_table_75_msvc_X86_SSE2.qbk
Normal file
37
doc/roots/roots_table_75_msvc_X86_SSE2.qbk
Normal file
@@ -0,0 +1,37 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/roots_table_75_msvc_X86_SSE2 .qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
|
||||
[h6 Program I:\modular-boost\libs\math\example\root_n_finding_algorithms.cpp,
|
||||
Microsoft Visual C++ version 12.0, Dinkumware standard library version 610, Win32
|
||||
Compiled in optimise mode., _X86_SSE2 ]
|
||||
Fraction of full accuracy 0.75
|
||||
[table:root_5 5th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 7][ 750][[role blue 1.00]][ 0][ ][ 11][ 1031][1.10][ 1][ ][ 11][ 1031][1.12][ 1][ ][ 11][125250][[role red 5.53]][ 0][ ]]
|
||||
[[Newton ][ 3][ 906][1.21][ 0][ ][ 5][ 937][[role blue 1.00]][ -1][ ][ 5][ 953][[role blue 1.03]][ -1][ ][ 6][22640][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 2][ 921][1.23][ 0][ ][ 3][ 953][[role blue 1.02]][ 0][ ][ 3][ 921][[role blue 1.00]][ 0][ ][ 4][39390][1.74][ 0][ ]]
|
||||
[[Schroeder][ 6][ 984][1.31][ 0][ ][ 7][ 1031][1.10][ -1][ ][ 7][ 1031][1.12][ -1][ ][ 8][72515][3.20][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_7 7th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 12][ 1000][1.09][ 1][ ][ 15][ 1218][1.28][ 2][ ][ 15][ 1218][1.26][ 2][ ][ 14][192640][[role red 5.64]][ 0][ ]]
|
||||
[[Newton ][ 5][ 921][[role blue 1.00]][ 0][ ][ 7][ 953][[role blue 1.00]][ 0][ ][ 7][ 968][[role blue 1.00]][ 0][ ][ 8][34156][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][1.09][ 0][ ][ 6][ 1031][1.08][ 0][ ][ 6][ 1031][1.07][ 0][ ][ 6][66625][1.95][ 0][ ]]
|
||||
[[Schroeder][ 5][ 968][1.05][ 0][ ][ 6][ 968][[role blue 1.02]][ 0][ ][ 6][ 1015][[role blue 1.05]][ 0][ ][ 7][64953][1.90][ 0][ ]]
|
||||
] [/end of table root]
|
||||
[table:root_11 11th root(28) for float, double, long double and cpp_bin_float_50 types, using _X86_SSE2
|
||||
[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]
|
||||
[[Algo ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ][Its][Times][Norm][Dis][ ]]
|
||||
[[TOMS748 ][ 11][ 1046][1.08][ 0][ ][ 14][ 1296][1.32][ 2][ ][ 14][ 1312][1.33][ 2][ ][ 17][288437][[role red 6.98]][ 2][ ]]
|
||||
[[Newton ][ 6][ 968][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 7][ 984][[role blue 1.00]][ 0][ ][ 9][41328][[role blue 1.00]][ 0][ ]]
|
||||
[[Halley ][ 5][ 1000][[role blue 1.03]][ 0][ ][ 6][ 1046][1.06][ 0][ ][ 6][ 1046][1.06][ 0][ ][ 7][78593][1.90][ 0][ ]]
|
||||
[[Schroeder][ 6][ 1015][[role blue 1.05]][ 0][ ][ 7][ 1046][1.06][ 0][ ][ 7][ 1046][1.06][ 0][ ][ 8][78218][1.89][ 0][ ]]
|
||||
] [/end of table root]
|
||||
@@ -113,12 +113,12 @@
|
||||
|
||||
[h4 Description]
|
||||
|
||||
These functions solve the root of some function ['f(x)]
|
||||
These functions solve the root of some function ['f(x)] -
|
||||
['without the need for any derivatives of ['f(x)]].
|
||||
|
||||
The `bracket_and_solve_root` functions use __root_finding_TOMS748
|
||||
that is asymptotically the most efficient known,
|
||||
and have been shown to be optimal for a certain classes of smooth functions.
|
||||
by Alefeld, Potra and Shi that is asymptotically the most efficient known,
|
||||
and has been shown to be optimal for a certain classes of smooth functions.
|
||||
Variants with and without __policy_section are provided.
|
||||
|
||||
Alternatively, __bisect is a simple __bisection_wikipedia routine which can be useful
|
||||
@@ -183,15 +183,15 @@ These functions locate the root using __bisection_wikipedia.
|
||||
[[f] [A unary functor which is the function ['f(x)] whose root is to be found.]]
|
||||
[[min] [The left bracket of the interval known to contain the root.]]
|
||||
[[max] [The right bracket of the interval known to contain the root.[br]
|
||||
It is a precondition that /min < max/ and /f(min)*f(max) <= 0/,
|
||||
the function signals evaluation error if these preconditions are violated.
|
||||
It is a precondition that ['min < max] and ['f(min)*f(max) <= 0],
|
||||
the function signals ['evaluation error] if these preconditions are violated.
|
||||
The action taken is controlled by the evaluation error policy.[br]
|
||||
A best guess may be returned, perhaps significantly wrong.]]
|
||||
[[tol] [A binary functor that specifies the termination condition: the function
|
||||
will return the current brackets enclosing the root when ['tol(min, max)] becomes true.]]
|
||||
[[max_iter][The maximum number of invocations of ['f(x)] to make while searching for the root. On exit, this is updated to the actual number of invocations performed.]]
|
||||
[[T] [Floating-point type, typically `double` (often deduced by __ADL)]]
|
||||
[[F] [Floating-point types of the functor, usually deduced from T by __ADL, so it is rarely necessary to define F.]]
|
||||
[[T] [Floating-point type, typically `double`, ]]
|
||||
[[F] [Unary Functor that returns any suitable __tuple_type, of type T. ]]
|
||||
]
|
||||
|
||||
[optional_policy]
|
||||
@@ -242,27 +242,29 @@ because the termination condition ['tol] was satisfied.
|
||||
to find the root of ['f(x)]. It's usable only when ['f(x)] is a monotonic
|
||||
function, and the location of the root is known approximately, and in
|
||||
particular it is known whether the root is occurs for positive or negative
|
||||
/x/. The `bracket_and_solve_root` parameters are:
|
||||
['x].
|
||||
|
||||
The `bracket_and_solve_root` parameters are:
|
||||
|
||||
[variablelist
|
||||
[[f][A unary functor that is the function whose root is to be solved.
|
||||
['f(x)] must be uniformly increasing or decreasing on /x/.]]
|
||||
[[guess][An initial approximation to the root]]
|
||||
['f(x)] must be uniformly increasing or decreasing on ['x].]]
|
||||
[[guess][An initial approximation to the root.]]
|
||||
[[factor][A scaling factor that is used to bracket the root: the value
|
||||
/guess/ is multiplied (or divided as appropriate) by /factor/
|
||||
until two values are found that bracket the root. A value
|
||||
such as 2 is a typical choice for /factor/.]]
|
||||
[[rising][Set to /true/ if ['f(x)] is rising on /x/ and /false/ if ['f(x)]
|
||||
such as 2 is a typical choice for ['factor].]]
|
||||
[[rising][Set to ['true] if ['f(x)] is rising on /x/ and /false/ if ['f(x)]
|
||||
is falling on /x/. This value is used along with the result
|
||||
of /f(guess)/ to determine if /guess/ is
|
||||
above or below the root.]]
|
||||
[[tol] [A binary functor that determines the termination condition for the search
|
||||
for the root. /tol/ is passed the current brackets at each step,
|
||||
when it returns true then the current brackets are returned as the result.]]
|
||||
when it returns true then the current brackets are returned as the pair result.]]
|
||||
[[max_iter] [The maximum number of function invocations to perform in the search
|
||||
for the root. On exit is set to the actual number of invocations performed.]]
|
||||
[[T] [Floating-point type, typically `double`, often deduced by __ADL]]
|
||||
[[F] [Floating-point types of the functor, usually deduced from T by __ADL, so it is rarely necessary to define F.]]
|
||||
[[T] [Floating-point type, typically `double`, ]]
|
||||
[[F] [Unary Functor that returns any suitable __tuple_type, of type T. ]]
|
||||
]
|
||||
|
||||
[optional_policy]
|
||||
@@ -351,8 +353,8 @@ cubic, quadratic and linear (secant) interpolation to locate the root of
|
||||
[[max_iter] [The maximum number of function invocations to perform in the search
|
||||
for the root. On exit, ['max_iter] is set to actual number of function
|
||||
invocations used.]]
|
||||
[[T] [Floating-point type, typically `double`, often deduced by __ADL]]
|
||||
[[F] [Floating-point types of the functor, usually deduced from T by __ADL, so it is rarely necessary to define F.]]
|
||||
[[T] [Floating-point type, typically `double`, ]]
|
||||
[[F] [Unary Functor that returns any suitable __tuple_type, of type T. ]]
|
||||
]
|
||||
|
||||
[optional_policy]
|
||||
|
||||
18
doc/roots/type_info_table_100_msvc.qbk
Normal file
18
doc/roots/type_info_table_100_msvc.qbk
Normal file
@@ -0,0 +1,18 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/type_info_table_100_msvc.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
[h6 Fraction of maximum possible bits of accuracy required is 1.0.]
|
||||
|
||||
[table:type_info_100_msvc Digits for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][24]]
|
||||
[[float][17][53][53]]
|
||||
[[long double][17][53][53]]
|
||||
[[cpp_bin_float_50][52][168][168]]
|
||||
] [/table table_id_msvc]
|
||||
|
||||
18
doc/roots/type_info_table_75_msvc.qbk
Normal file
18
doc/roots/type_info_table_75_msvc.qbk
Normal file
@@ -0,0 +1,18 @@
|
||||
[/i:/modular-boost/libs/math/doc/roots/type_info_table_75_msvc.qbk
|
||||
Copyright 2015 Paul A. Bristow.
|
||||
Copyright 2015 John Maddock.
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
]
|
||||
|
||||
[h6 Fraction of maximum possible bits of accuracy required is 0.75.]
|
||||
|
||||
[table:type_info_75_msvc Digits for float, double, long double and cpp_bin_float_50
|
||||
[[type name] [max_digits10] [binary digits] [required digits]]
|
||||
[[float][9][24][18]]
|
||||
[[float][17][53][39]]
|
||||
[[long double][17][53][39]]
|
||||
[[cpp_bin_float_50][52][168][126]]
|
||||
] [/table table_id_msvc]
|
||||
|
||||
@@ -30,14 +30,13 @@
|
||||
//[brent_minimise_mp_include_0
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp> // For decimal boost::multiprecision::cpp_dec_float_50.
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp> // For binary boost::multiprecision::cpp_bin_float_50;
|
||||
//] [/brent_minimise_mp_include_0]
|
||||
|
||||
//#ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2013.
|
||||
#ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel, and have quadmath.lib or .dll library available.
|
||||
# include <boost/multiprecision/float128.hpp>
|
||||
#endif
|
||||
|
||||
//] [/brent_minimise_mp_include_0]
|
||||
|
||||
#include <iostream>
|
||||
// using std::cout; using std::endl;
|
||||
#include <iomanip>
|
||||
@@ -46,21 +45,19 @@
|
||||
using std::numeric_limits;
|
||||
#include <tuple>
|
||||
#include <utility> // pair, make_pair
|
||||
#include <type_traits>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
//typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
|
||||
// boost::multiprecision::et_off>
|
||||
// cpp_dec_float_50_et_off;
|
||||
//
|
||||
//
|
||||
// typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>,
|
||||
// boost::multiprecision::et_off>
|
||||
// cpp_bin_float_50_et_off;
|
||||
|
||||
|
||||
// http://en.wikipedia.org/wiki/Brent%27s_method Brent's method
|
||||
|
||||
|
||||
double f(double x)
|
||||
{
|
||||
return (x + 3) * (x - 1) * (x - 1);
|
||||
@@ -79,10 +76,10 @@ struct funcdouble
|
||||
//[brent_minimise_T_functor
|
||||
template <class T = double>
|
||||
struct func
|
||||
{
|
||||
{
|
||||
T operator()(T const& x)
|
||||
{ //
|
||||
return (x + 3) * (x - 1) * (x - 1); //
|
||||
return (x + 3) * (x - 1) * (x - 1); //
|
||||
}
|
||||
};
|
||||
//] [/brent_minimise_T_functor]
|
||||
@@ -96,11 +93,11 @@ bool close(T expect, T got, T tolerance)
|
||||
using boost::math::fpc::is_small;
|
||||
|
||||
if (is_small<T>(expect, tolerance))
|
||||
{
|
||||
{
|
||||
return is_small<T>(got, tolerance);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
return is_close_to<T>(expect, got, tolerance);
|
||||
}
|
||||
}
|
||||
@@ -120,11 +117,11 @@ void show_minima()
|
||||
std::streamsize prec = static_cast<int>(2 + sqrt(bits)); // Number of significant decimal digits.
|
||||
std::streamsize precision = std::cout.precision(prec); // Save.
|
||||
|
||||
std::cout << "\n\nFor type " << typeid(T).name()
|
||||
<< ",\n epsilon = " << std::numeric_limits<T>::epsilon()
|
||||
std::cout << "\n\nFor type " << typeid(T).name()
|
||||
<< ",\n epsilon = " << std::numeric_limits<T>::epsilon()
|
||||
// << ", precision of " << bits << " bits"
|
||||
<< ",\n the maximum theoretical precision from Brent minimization is " << sqrt(std::numeric_limits<T>::epsilon())
|
||||
<< "\n Displaying to std::numeric_limits<T>::digits10 " << prec << " significant decimal digits."
|
||||
<< "\n Displaying to std::numeric_limits<T>::digits10 " << prec << " significant decimal digits."
|
||||
<< std::endl;
|
||||
|
||||
const boost::uintmax_t maxit = 20;
|
||||
@@ -157,8 +154,8 @@ void show_minima()
|
||||
std::cout.precision(precision); // Restore.
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{ // Always useful to include try & catch blocks because default policies
|
||||
// are to throw exceptions on arguments that cause errors like underflow, overflow.
|
||||
{ // Always useful to include try & catch blocks because default policies
|
||||
// are to throw exceptions on arguments that cause errors like underflow, overflow.
|
||||
// Lacking try & catch blocks, the program will abort without a message below,
|
||||
// which may give some helpful clues as to the cause of the exception.
|
||||
std::cout <<
|
||||
@@ -172,8 +169,8 @@ int main()
|
||||
{
|
||||
std::cout << "Brent's minimisation example." << std::endl;
|
||||
std::cout << std::boolalpha << std::endl;
|
||||
|
||||
// Tip - using
|
||||
|
||||
// Tip - using
|
||||
// std::cout.precision(std::numeric_limits<T>::digits10);
|
||||
// during debugging is wise because it shows if construction of multiprecision involves conversion from double
|
||||
// by finding random or zero digits after 17.
|
||||
@@ -190,7 +187,7 @@ int main()
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
|
||||
// x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018
|
||||
//] [/brent_minimise_double_1]
|
||||
|
||||
|
||||
std::cout << "x at minimum = " << (r.first - 1.) /r.first << std::endl;
|
||||
|
||||
double uncertainty = sqrt(std::numeric_limits<double>::epsilon());
|
||||
@@ -203,7 +200,7 @@ int main()
|
||||
|
||||
std::cout << is_close_to(1., r.first, uncertainty) << std::endl;
|
||||
std::cout << is_small(r.second, uncertainty) << std::endl;
|
||||
|
||||
|
||||
std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " << close(1., r.first, uncertainty) << std::endl;
|
||||
std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " << close(0., r.second, uncertainty) << std::endl;
|
||||
|
||||
@@ -233,9 +230,8 @@ int main()
|
||||
// Showing 53 bits precision with 9 decimal digits from tolerance 1.49011611938477e-008
|
||||
// x at minimum = 1, f(1) = 5.04852568e-018
|
||||
|
||||
|
||||
//[brent_minimise_double_4
|
||||
{
|
||||
//[brent_minimise_double_4
|
||||
bits /= 2; // Half digits precision (effective maximum).
|
||||
double epsilon_2 = boost::math::pow<-(std::numeric_limits<double>::digits/2 - 1), double>(2);
|
||||
|
||||
@@ -248,12 +244,12 @@ int main()
|
||||
r = brent_find_minima(funcdouble(), -4., 4. / 3, bits, it);
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl;
|
||||
std::cout << it << " iterations. " << std::endl;
|
||||
}
|
||||
//] [/brent_minimise_double_4]
|
||||
}
|
||||
// x at minimum = 1, f(1) = 5.04852568e-018
|
||||
|
||||
//[brent_minimise_double_5
|
||||
{
|
||||
//[brent_minimise_double_5
|
||||
bits /= 2; // Quarter precision.
|
||||
double epsilon_4 = boost::math::pow<-(std::numeric_limits<double>::digits / 4 - 1), double>(2);
|
||||
|
||||
@@ -266,15 +262,15 @@ int main()
|
||||
r = brent_find_minima(funcdouble(), -4., 4. / 3, bits, it);
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
|
||||
<< ", after " << it << " iterations. " << std::endl;
|
||||
}
|
||||
//] [/brent_minimise_double_5]
|
||||
}
|
||||
|
||||
// Showing 13 bits precision with 9 decimal digits from tolerance 0.015625
|
||||
// x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009
|
||||
// 7 iterations.
|
||||
|
||||
//[brent_minimise_template_1
|
||||
{
|
||||
//[brent_minimise_template_1
|
||||
std::cout.precision(std::numeric_limits<long double>::digits10);
|
||||
long double bracket_min = -4.;
|
||||
long double bracket_max = 4. / 3;
|
||||
@@ -285,7 +281,7 @@ int main()
|
||||
std::pair<long double, long double> r = brent_find_minima(func<long double>(), bracket_min, bracket_max, bits, it);
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
|
||||
<< ", after " << it << " iterations. " << std::endl;
|
||||
//] [/brent_minimise_template_1]
|
||||
//] [/brent_minimise_template_1]
|
||||
}
|
||||
|
||||
// Show use of built-in type Template versions.
|
||||
@@ -297,16 +293,15 @@ int main()
|
||||
show_minima<long double>();
|
||||
//] [/brent_minimise_template_fd]
|
||||
|
||||
//[brent_minimise_mp_include_1
|
||||
using boost::multiprecision::cpp_bin_float_50; // binary.
|
||||
|
||||
//[brent_minimise_mp_include_1
|
||||
#ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel and have quadmath.lib or .dll library available.
|
||||
using boost::multiprecision::float128;
|
||||
#endif
|
||||
//] [/brent_minimise_mp_include_1]
|
||||
|
||||
//[brent_minimise_template_quad
|
||||
|
||||
// #ifndef _MSC_VER
|
||||
#ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel and have quadmath.lib or .dll library available.
|
||||
show_minima<float128>(); // Needs quadmath_snprintf, sqrtQ, fabsq that are in in quadmath library.
|
||||
@@ -335,7 +330,6 @@ int main()
|
||||
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>,
|
||||
boost::multiprecision::et_off>
|
||||
cpp_dec_float_50_et_off;
|
||||
|
||||
//] [/brent_minimise_mp_typedefs]
|
||||
|
||||
{ // binary ET on by default.
|
||||
@@ -359,7 +353,7 @@ int main()
|
||||
boost::uintmax_t it = maxit;
|
||||
std::pair<cpp_bin_float_50, cpp_bin_float_50> r = brent_find_minima(func<cpp_bin_float_50>(), bracket_min, bracket_max, bits, it);
|
||||
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
|
||||
std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second
|
||||
// x at minimum = 1, f(1) = 5.04853e-018
|
||||
<< ", after " << it << " iterations. " << std::endl;
|
||||
|
||||
@@ -378,13 +372,13 @@ int main()
|
||||
//] [/brent_minimise_mp_output_1]
|
||||
*/
|
||||
//[brent_minimise_mp_2
|
||||
show_minima<cpp_bin_float_50_et_on>(); //
|
||||
show_minima<cpp_bin_float_50_et_on>(); //
|
||||
//] [/brent_minimise_mp_2]
|
||||
|
||||
/*
|
||||
/*
|
||||
//[brent_minimise_mp_output_2
|
||||
For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50, 10, void, int, 0, 0>, 1>,
|
||||
|
||||
|
||||
//] [/brent_minimise_mp_output_1]
|
||||
*/
|
||||
}
|
||||
@@ -406,7 +400,7 @@ int main()
|
||||
// x at minimum = 1, f(1) = 5.04853e-018
|
||||
std::cout << it << " iterations. " << std::endl;
|
||||
|
||||
show_minima<cpp_bin_float_50_et_on>(); //
|
||||
show_minima<cpp_bin_float_50_et_on>(); //
|
||||
|
||||
}
|
||||
return 0;
|
||||
@@ -427,7 +421,7 @@ int main()
|
||||
// x at minimum = 1, f(1) = 5.04853e-018
|
||||
std::cout << it << " iterations. " << std::endl;
|
||||
|
||||
show_minima<cpp_bin_float_50_et_off>(); //
|
||||
show_minima<cpp_bin_float_50_et_off>(); //
|
||||
}
|
||||
|
||||
{ // decimal ET on by default
|
||||
@@ -450,7 +444,7 @@ int main()
|
||||
show_minima<cpp_dec_float_50>();
|
||||
}
|
||||
|
||||
{ // decimal ET on
|
||||
{ // decimal ET on
|
||||
std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_on>::digits10);
|
||||
|
||||
int bits = std::numeric_limits<cpp_dec_float_50_et_on>::digits / 2 - 2;
|
||||
@@ -497,9 +491,9 @@ int main()
|
||||
/*
|
||||
|
||||
|
||||
|
||||
// GCC 4.9.1 with quadmath
|
||||
|
||||
|
||||
// GCC 4.9.1 with quadmath
|
||||
|
||||
Brent's minimisation example.
|
||||
x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018
|
||||
x at minimum = 1.12344622367552e-009
|
||||
@@ -507,15 +501,15 @@ Uncertainty sqrt(epsilon) = 1.49011611938477e-008
|
||||
x == 1 (compared to uncertainty 1.49011611938477e-008) is true
|
||||
f(x) == (0 compared to uncertainty 1.49011611938477e-008) is true
|
||||
Precision bits = 53
|
||||
x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 after 10 iterations.
|
||||
x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 after 10 iterations.
|
||||
Showing 53 bits precision with 9 decimal digits from tolerance 1.49011611938477e-008
|
||||
x at minimum = 1, f(1) = 5.04852568e-018 after 10 iterations.
|
||||
x at minimum = 1, f(1) = 5.04852568e-018 after 10 iterations.
|
||||
Showing 26 bits precision with 9 decimal digits from tolerance 0.000172633492
|
||||
x at minimum = 1, f(1) = 5.04852568e-018
|
||||
10 iterations.
|
||||
10 iterations.
|
||||
Showing 13 bits precision with 9 decimal digits from tolerance 0.015625
|
||||
x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009, after 7 iterations.
|
||||
x at minimum = 1.00000000000137302, f(1.00000000000137302) = 7.5407901369731193e-024, after 10 iterations.
|
||||
x at minimum = 0.9999776, f(0.9999776) = 2.0069572e-009, after 7 iterations.
|
||||
x at minimum = 1.00000000000137302, f(1.00000000000137302) = 7.5407901369731193e-024, after 10 iterations.
|
||||
|
||||
|
||||
For type f,
|
||||
@@ -557,7 +551,7 @@ For type N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26
|
||||
x == 1 (compared to uncertainty 1.38777878e-17) is true
|
||||
f(x) == (0 compared to uncertainty 1.38777878e-17) is true
|
||||
-4 1.3333333333333333333333333333333333333333333333333
|
||||
x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations.
|
||||
x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations.
|
||||
|
||||
|
||||
For type N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE,
|
||||
@@ -570,7 +564,7 @@ x == 1 (compared to uncertainty 7.311312755e-26) is true
|
||||
f(x) == (0 compared to uncertainty 7.311312755e-26) is true
|
||||
-4 1.3333333333333333333333333333333333333333333333333
|
||||
x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58
|
||||
14 iterations.
|
||||
14 iterations.
|
||||
|
||||
|
||||
For type N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE,
|
||||
|
||||
@@ -57,7 +57,7 @@ The constructor sets the [*fractional] tolerance and the equality strength.
|
||||
|
||||
Two member functions allow access to the chosen tolerance and strength.
|
||||
|
||||
FPT fraction_tolerance() const;
|
||||
FPT fraction_tolerance() const;
|
||||
strength strength() const; // weak or strong.
|
||||
|
||||
the `operator()` functor carries out the comparison,
|
||||
@@ -92,7 +92,7 @@ that failed the test.
|
||||
|
||||
using namespace boost::math::fpc;
|
||||
|
||||
//`or
|
||||
//`or
|
||||
|
||||
using boost::math::fpc::close_at_tolerance;
|
||||
using boost::math::fpc::small_with_tolerance;
|
||||
@@ -182,8 +182,8 @@ A class that stores a tolerance of three epsilon (and the default ['strong] test
|
||||
|
||||
std::cout << "failed_fraction = " << three_rounds.failed_fraction() << std::endl;
|
||||
|
||||
/*`To get some nearby values, it is convenient to use the Boost.Math next functions,
|
||||
for which we need an include
|
||||
/*`To get some nearby values, it is convenient to use the Boost.Math __next_float functions,
|
||||
for which we need an include
|
||||
|
||||
#include <boost/math/special_functions/next.hpp>
|
||||
|
||||
|
||||
220
example/handle_test_result.hpp
Normal file
220
example/handle_test_result.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
// (C) Copyright John Maddock 2006-7.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_HANDLE_TEST_RESULT
|
||||
#define BOOST_MATH_HANDLE_TEST_RESULT
|
||||
|
||||
#include <boost/math/tools/stats.hpp>
|
||||
#include <boost/math/tools/test.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#if defined(BOOST_INTEL)
|
||||
# pragma warning(disable:239)
|
||||
# pragma warning(disable:264)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Every client of this header has to define this function,
|
||||
// and initialise the table of expected results:
|
||||
//
|
||||
void expected_results();
|
||||
|
||||
typedef std::pair<boost::regex, std::pair<boost::uintmax_t, boost::uintmax_t> > expected_data_type;
|
||||
typedef std::list<expected_data_type> list_type;
|
||||
|
||||
inline list_type&
|
||||
get_expected_data()
|
||||
{
|
||||
static list_type data;
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void add_expected_result(
|
||||
const char* compiler,
|
||||
const char* library,
|
||||
const char* platform,
|
||||
const char* type_name,
|
||||
const char* test_name,
|
||||
const char* group_name,
|
||||
boost::uintmax_t max_peek_error,
|
||||
boost::uintmax_t max_mean_error)
|
||||
{
|
||||
std::string re("(?:");
|
||||
re += compiler;
|
||||
re += ")";
|
||||
re += "\\|";
|
||||
re += "(?:";
|
||||
re += library;
|
||||
re += ")";
|
||||
re += "\\|";
|
||||
re += "(?:";
|
||||
re += platform;
|
||||
re += ")";
|
||||
re += "\\|";
|
||||
re += "(?:";
|
||||
re += type_name;
|
||||
re += ")";
|
||||
re += "\\|";
|
||||
re += "(?:";
|
||||
re += test_name;
|
||||
re += ")";
|
||||
re += "\\|";
|
||||
re += "(?:";
|
||||
re += group_name;
|
||||
re += ")";
|
||||
get_expected_data().push_back(
|
||||
std::make_pair(boost::regex(re, boost::regex::perl | boost::regex::icase),
|
||||
std::make_pair(max_peek_error, max_mean_error)));
|
||||
}
|
||||
|
||||
inline std::string build_test_name(const char* type_name, const char* test_name, const char* group_name)
|
||||
{
|
||||
std::string result(BOOST_COMPILER);
|
||||
result += "|";
|
||||
result += BOOST_STDLIB;
|
||||
result += "|";
|
||||
result += BOOST_PLATFORM;
|
||||
result += "|";
|
||||
result += type_name;
|
||||
result += "|";
|
||||
result += group_name;
|
||||
result += "|";
|
||||
result += test_name;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const std::pair<boost::uintmax_t, boost::uintmax_t>&
|
||||
get_max_errors(const char* type_name, const char* test_name, const char* group_name)
|
||||
{
|
||||
static const std::pair<boost::uintmax_t, boost::uintmax_t> defaults(1, 1);
|
||||
std::string name = build_test_name(type_name, test_name, group_name);
|
||||
list_type& l = get_expected_data();
|
||||
list_type::const_iterator a(l.begin()), b(l.end());
|
||||
while(a != b)
|
||||
{
|
||||
if(regex_match(name, a->first))
|
||||
{
|
||||
#if 0
|
||||
std::cout << name << std::endl;
|
||||
std::cout << a->first.str() << std::endl;
|
||||
#endif
|
||||
return a->second;
|
||||
}
|
||||
++a;
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
|
||||
template <class T, class Seq>
|
||||
void handle_test_result(const boost::math::tools::test_result<T>& result,
|
||||
const Seq& worst, int row,
|
||||
const char* type_name,
|
||||
const char* test_name,
|
||||
const char* group_name)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
using namespace std; // To aid selection of the right pow.
|
||||
T eps = boost::math::tools::epsilon<T>();
|
||||
std::cout << std::setprecision(4);
|
||||
|
||||
T max_error_found = (result.max)()/eps;
|
||||
T mean_error_found = result.rms()/eps;
|
||||
//
|
||||
// Begin by printing the main tag line with the results:
|
||||
//
|
||||
std::cout << test_name << "<" << type_name << "> Max = " << max_error_found
|
||||
<< " RMS Mean=" << mean_error_found;
|
||||
//
|
||||
// If the max error is non-zero, give the row of the table that
|
||||
// produced the worst error:
|
||||
//
|
||||
if((result.max)() != 0)
|
||||
{
|
||||
std::cout << "\n worst case at row: "
|
||||
<< row << "\n { ";
|
||||
if(std::numeric_limits<T>::digits10)
|
||||
{
|
||||
std::cout << std::setprecision(std::numeric_limits<T>::digits10 + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 2);
|
||||
}
|
||||
for(unsigned i = 0; i < worst.size(); ++i)
|
||||
{
|
||||
if(i)
|
||||
std::cout << ", ";
|
||||
#if defined(__SGI_STL_PORT)
|
||||
std::cout << boost::math::tools::real_cast<double>(worst[i]);
|
||||
#else
|
||||
std::cout << worst[i];
|
||||
#endif
|
||||
}
|
||||
std::cout << " }";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
//
|
||||
// Now verify that the results are within our expected bounds:
|
||||
//
|
||||
std::pair<boost::uintmax_t, boost::uintmax_t> const& bounds = get_max_errors(type_name, test_name, group_name);
|
||||
if(bounds.first < max_error_found)
|
||||
{
|
||||
std::cerr << "Peak error greater than expected value of " << bounds.first << std::endl;
|
||||
BOOST_CHECK(bounds.first >= max_error_found);
|
||||
}
|
||||
if(bounds.second < mean_error_found)
|
||||
{
|
||||
std::cerr << "Mean error greater than expected value of " << bounds.second << std::endl;
|
||||
BOOST_CHECK(bounds.second >= mean_error_found);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class Seq>
|
||||
void print_test_result(const boost::math::tools::test_result<T>& result,
|
||||
const Seq& worst, int row, const char* name, const char* test)
|
||||
{
|
||||
using namespace std; // To aid selection of the right pow.
|
||||
T eps = boost::math::tools::epsilon<T>();
|
||||
std::cout << std::setprecision(4);
|
||||
|
||||
T max_error_found = (result.max)()/eps;
|
||||
T mean_error_found = result.rms()/eps;
|
||||
//
|
||||
// Begin by printing the main tag line with the results:
|
||||
//
|
||||
std::cout << test << "(" << name << ") Max = " << max_error_found
|
||||
<< " RMS Mean=" << mean_error_found;
|
||||
//
|
||||
// If the max error is non-zero, give the row of the table that
|
||||
// produced the worst error:
|
||||
//
|
||||
if((result.max)() != 0)
|
||||
{
|
||||
std::cout << "\n worst case at row: "
|
||||
<< row << "\n { ";
|
||||
for(unsigned i = 0; i < worst.size(); ++i)
|
||||
{
|
||||
if(i)
|
||||
std::cout << ", ";
|
||||
std::cout << worst[i];
|
||||
}
|
||||
std::cout << " }";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
#endif // BOOST_MATH_HANDLE_TEST_RESULT
|
||||
|
||||
855
example/root_finding_algorithms.cpp
Normal file
855
example/root_finding_algorithms.cpp
Normal file
@@ -0,0 +1,855 @@
|
||||
// Copyright Paul A. Bristow 2015
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Comparison of finding roots using TOMS748, Newton-Raphson, Schroeder & Halley algorithms.
|
||||
|
||||
// Note that this file contains Quickbook mark-up as well as code
|
||||
// and comments, don't change any of the special comment mark-ups!
|
||||
|
||||
// root_finding_algorithms.cpp
|
||||
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/concepts/real_concept.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "table_type.hpp"
|
||||
// Copy of i:\modular-boost\libs\math\test\table_type.hpp
|
||||
// #include "handle_test_result.hpp"
|
||||
// Copy of i:\modular - boost\libs\math\test\handle_test_result.hpp
|
||||
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
//using boost::math::policies::policy;
|
||||
//using boost::math::tools::newton_raphson_iterate;
|
||||
//using boost::math::tools::halley_iterate; //
|
||||
//using boost::math::tools::eps_tolerance; // Binary functor for specified number of bits.
|
||||
//using boost::math::tools::bracket_and_solve_root;
|
||||
//using boost::math::tools::toms748_solve;
|
||||
//using boost::math::tools::schroeder_iterate;
|
||||
|
||||
#include <boost/math/special_functions/next.hpp> // For float_distance.
|
||||
#include <boost/math/tools/tuple.hpp> // for tuple and make_tuple.
|
||||
#include <boost/math/special_functions/cbrt.hpp> // For boost::math::cbrt.
|
||||
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp> // is binary.
|
||||
//#include <boost/multiprecision/cpp_dec_float.hpp> // is decimal.
|
||||
using boost::multiprecision::cpp_bin_float_100;
|
||||
using boost::multiprecision::cpp_bin_float_50;
|
||||
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/multiprecision/cpp_bin_float/io.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <fstream> // std::ofstream
|
||||
#include <cmath>
|
||||
#include <typeinfo> // for type name using typid(thingy).name();
|
||||
|
||||
#ifndef BOOST_ROOT
|
||||
# define BOOST_ROOT i:/modular-boost/
|
||||
#endif
|
||||
// Need to find this
|
||||
|
||||
#ifdef __FILE__
|
||||
std::string sourcefilename = __FILE__;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_ROOT
|
||||
std::string boost_root = BOOST_STRINGIZE(BOOST_ROOT);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
std::string filename = boost_root.append("libs/math/doc/roots/root_comparison_tables_msvc.qbk");
|
||||
#else // assume GCC
|
||||
std::string filename = boost_root.append("libs/math/doc/roots/root_comparison_tables_gcc.qbk");
|
||||
#endif
|
||||
|
||||
std::ofstream fout (filename.c_str(), std::ios_base::out);
|
||||
|
||||
//std::array<std::string, 6> float_type_names =
|
||||
//{
|
||||
// "float", "double", "long double", "cpp_bin_128", "cpp_dec_50", "cpp_dec_100"
|
||||
//};
|
||||
|
||||
std::vector<std::string> algo_names =
|
||||
{
|
||||
"cbrt", "TOMS748", "Newton", "Halley", "Schroeder"
|
||||
};
|
||||
|
||||
std::vector<int> max_digits10s;
|
||||
std::vector<std::string> typenames; // Full computer generated type name.
|
||||
std::vector<std::string> names; // short name.
|
||||
|
||||
uintmax_t iters; // Global as iterations is not returned by rooting function.
|
||||
|
||||
const int convert = 1000; // convert nanoseconds to microseconds (assuming this is resolution).
|
||||
|
||||
const int count = 1000000; // Number of iterations to average.
|
||||
|
||||
struct root_info
|
||||
{ // for a floating-point type, float, double ...
|
||||
std::size_t max_digits10; // for type.
|
||||
std::string full_typename; // for type from type_id.name().
|
||||
std::string short_typename; // for type "float", "double", "cpp_bin_float_50" ....
|
||||
|
||||
std::size_t bin_digits; // binary in floating-point type numeric_limits<T>::digits;
|
||||
int get_digits; // fraction of maximum possible accuracy required.
|
||||
// = digits * digits_accuracy
|
||||
// Vector of values for each algorithm, std::cbrt, boost::math::cbrt, TOMS748, Newton, Halley.
|
||||
//std::vector< boost::int_least64_t> times; converted to int.
|
||||
std::vector<int> times;
|
||||
//boost::int_least64_t min_time = std::numeric_limits<boost::int_least64_t>::max(); // Used to normalize times (as int).
|
||||
std::vector<double> normed_times;
|
||||
boost::int_least64_t min_time = std::numeric_limits<boost::int_least64_t>::max(); // Used to normalize times.
|
||||
std::vector<uintmax_t> iterations;
|
||||
std::vector<long int> distances;
|
||||
std::vector<cpp_bin_float_100> full_results;
|
||||
}; // struct root_info
|
||||
|
||||
std::vector<root_info> root_infos; // One element for each type used.
|
||||
|
||||
int type_no = -1; // float = 0, double = 1, ... indexing root_infos.
|
||||
|
||||
inline std::string build_test_name(const char* type_name, const char* test_name)
|
||||
{
|
||||
std::string result(BOOST_COMPILER);
|
||||
result += "|";
|
||||
result += BOOST_STDLIB;
|
||||
result += "|";
|
||||
result += BOOST_PLATFORM;
|
||||
result += "|";
|
||||
result += type_name;
|
||||
result += "|";
|
||||
result += test_name;
|
||||
#ifdef _DEBUG
|
||||
#if (_DEBUG == 0)
|
||||
result += "|";
|
||||
result += " debug";
|
||||
#else
|
||||
result += "|";
|
||||
result += " release";
|
||||
#endif
|
||||
#endif
|
||||
result += "|";
|
||||
return result;
|
||||
}
|
||||
|
||||
double digits_accuracy = 1. ; // 1 == maximum possible accuracy.
|
||||
|
||||
// No derivatives - using TOMS748 internally.
|
||||
template <class T>
|
||||
struct cbrt_functor_noderiv
|
||||
{ // cube root of x using only function - no derivatives.
|
||||
cbrt_functor_noderiv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor just stores value a to find root of.
|
||||
}
|
||||
T operator()(T const& x)
|
||||
{
|
||||
T fx = x*x*x - a; // Difference (estimate x^3 - a).
|
||||
return fx;
|
||||
}
|
||||
private:
|
||||
T a; // to be 'cube_rooted'.
|
||||
}; // template <class T> struct cbrt_functor_noderiv
|
||||
|
||||
template <class T>
|
||||
T cbrt_noderiv(T x)
|
||||
{ // return cube root of x using bracket_and_solve (using NO derivatives).
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools; // For bracket_and_solve_root.
|
||||
|
||||
// Maybe guess should be double, or use enable_if to avoid warning about conversion double to float here?
|
||||
T guess;
|
||||
if (boost::is_fundamental<T>::value)
|
||||
{
|
||||
int exponent;
|
||||
frexp(x, &exponent); // Get exponent of z (ignore mantissa).
|
||||
guess = ldexp((T)1., exponent / 3); // Rough guess is to divide the exponent by three.
|
||||
}
|
||||
else
|
||||
{ // (boost::is_class<T>)
|
||||
double dx = static_cast<double>(x);
|
||||
guess = boost::math::cbrt<T>(dx); // Get guess using double.
|
||||
}
|
||||
|
||||
T factor = 2; // How big steps to take when searching.
|
||||
|
||||
const boost::uintmax_t maxit = 50; // Limit to maximum iterations.
|
||||
boost::uintmax_t it = maxit; // Initally our chosen max iterations, but updated with actual.
|
||||
bool is_rising = true; // So if result if guess^3 is too low, then try increasing guess.
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
// Some fraction of digits is used to control how accurate to try to make the result.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
|
||||
eps_tolerance<T> tol(get_digits); // Set the tolerance.
|
||||
std::pair<T, T> r =
|
||||
bracket_and_solve_root(cbrt_functor_noderiv<T>(x), guess, factor, is_rising, tol, it);
|
||||
iters = it;
|
||||
T result = r.first + (r.second - r.first) / 2; // Midway between brackets.
|
||||
return result;
|
||||
} // template <class T> T cbrt_noderiv(T x)
|
||||
|
||||
|
||||
// Using 1st derivative only Newton-Raphson
|
||||
|
||||
template <class T>
|
||||
struct cbrt_functor_deriv
|
||||
{ // Functor also returning 1st derviative.
|
||||
cbrt_functor_deriv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of,
|
||||
// for example: calling cbrt_functor_deriv<T>(x) to use to get cube root of x.
|
||||
}
|
||||
std::pair<T, T> operator()(T const& x)
|
||||
{ // Return both f(x) and f'(x).
|
||||
T fx = x*x*x - a; // Difference (estimate x^3 - value).
|
||||
T dx = 3 * x*x; // 1st derivative = 3x^2.
|
||||
return std::make_pair(fx, dx); // 'return' both fx and dx.
|
||||
}
|
||||
private:
|
||||
T a; // to be 'cube_rooted'.
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T cbrt_deriv(T x)
|
||||
{ // return cube root of x using 1st derivative and Newton_Raphson.
|
||||
using namespace boost::math::tools;
|
||||
int exponent;
|
||||
frexp(x, &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three.
|
||||
T min = ldexp(static_cast<T>(0.5), exponent / 3); // Minimum possible value is half our guess.
|
||||
T max = ldexp(static_cast<T>(2), exponent / 3); // Maximum possible value is twice our guess.
|
||||
const int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = newton_raphson_iterate(cbrt_functor_deriv<T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Using 1st and 2nd derivatives with Halley algorithm.
|
||||
|
||||
template <class T>
|
||||
struct cbrt_functor_2deriv
|
||||
{ // Functor returning both 1st and 2nd derivatives.
|
||||
cbrt_functor_2deriv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of, for example:
|
||||
// calling cbrt_functor_2deriv<T>(x) to get cube root of x,
|
||||
}
|
||||
boost::math::tuple<T, T, T> operator()(T const& x)
|
||||
{ // Return both f(x) and f'(x) and f''(x).
|
||||
using boost::math::make_tuple;
|
||||
T fx = x*x*x - a; // Difference (estimate x^3 - value).
|
||||
T dx = 3 * x*x; // 1st derivative = 3x^2.
|
||||
T d2x = 6 * x; // 2nd derivative = 6x.
|
||||
return make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x.
|
||||
}
|
||||
private:
|
||||
T a; // to be 'cube_rooted'.
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T cbrt_2deriv(T x)
|
||||
{ // return cube root of x using 1st and 2nd derivatives and Halley.
|
||||
//using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools;
|
||||
int exponent;
|
||||
frexp(x, &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three.
|
||||
T min = ldexp(static_cast<T>(0.5), exponent / 3); // Minimum possible value is half our guess.
|
||||
T max = ldexp(static_cast<T>(2), exponent / 3);// Maximum possible value is twice our guess.
|
||||
const int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
// digits used to control how accurate to try to make the result.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = halley_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Using 1st and 2nd derivatives using Schroeder algorithm.
|
||||
|
||||
template <class T>
|
||||
T cbrt_2deriv_s(T x)
|
||||
{ // return cube root of x using 1st and 2nd derivatives and Schroeder algorithm.
|
||||
//using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools;
|
||||
int exponent;
|
||||
frexp(x, &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three.
|
||||
T min = ldexp(static_cast<T>(0.5), exponent / 3); // Minimum possible value is half our guess.
|
||||
T max = ldexp(static_cast<T>(2), exponent / 3);// Maximum possible value is twice our guess.
|
||||
const int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
// digits used to control how accurate to try to make the result.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = schroeder_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
return result;
|
||||
} // template <class T> T cbrt_2deriv_s(T x)
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
int test_root(cpp_bin_float_100 big_value, cpp_bin_float_100 answer, const char* type_name)
|
||||
{
|
||||
//T value = 28.; // integer (exactly representable as floating-point)
|
||||
// whose cube root is *not* exactly representable.
|
||||
// Wolfram Alpha command N[28 ^ (1 / 3), 100] computes cube root to 100 decimal digits.
|
||||
// 3.036588971875662519420809578505669635581453977248111123242141654169177268411884961770250390838097895
|
||||
|
||||
std::size_t max_digits = 2 + std::numeric_limits<T>::digits * 3010 / 10000;
|
||||
// For new versions use max_digits10
|
||||
// std::cout.precision(std::numeric_limits<T>::max_digits10);
|
||||
std::cout.precision(max_digits);
|
||||
std::cout << std::showpoint << std::endl; // Trailing zeros too.
|
||||
|
||||
root_infos.push_back(root_info());
|
||||
type_no++; // Another type.
|
||||
|
||||
root_infos[type_no].max_digits10 = max_digits;
|
||||
root_infos[type_no].full_typename = typeid(T).name(); // Full typename.
|
||||
root_infos[type_no].short_typename = type_name; // Short typename.
|
||||
|
||||
root_infos[type_no].bin_digits = std::numeric_limits<T>::digits;
|
||||
|
||||
root_infos[type_no].get_digits = static_cast<int>(std::numeric_limits<T>::digits * digits_accuracy);
|
||||
|
||||
T to_root = static_cast<T>(big_value);
|
||||
T result; // root
|
||||
T ans = static_cast<T>(answer);
|
||||
int algo = 0; // Count of algorithms used.
|
||||
|
||||
using boost::timer::nanosecond_type;
|
||||
using boost::timer::cpu_times;
|
||||
using boost::timer::cpu_timer;
|
||||
|
||||
cpu_times now; // Holds wall, user and system times.
|
||||
|
||||
// std::cbrt is much the fastest, but not useful for this comparison because it only handles fundamental types.
|
||||
// Using enable_if allows us to avoid a compile fail with multiprecision types, but still distorts the results too much.
|
||||
|
||||
//{
|
||||
// algorithm_names.push_back("std::cbrt");
|
||||
// cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
// ti.start();
|
||||
// for (long i = 0; i < count; ++i)
|
||||
// {
|
||||
// stdcbrt(big_value);
|
||||
// }
|
||||
// now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
// root_infos[type_no].times.push_back(time); // CPU time taken per root.
|
||||
// if (time < root_infos[type_no].min_time)
|
||||
// {
|
||||
// root_infos[type_no].min_time = time;
|
||||
// }
|
||||
// ti.stop();
|
||||
// long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
// root_infos[type_no].distances.push_back(distance);
|
||||
// root_infos[type_no].iterations.push_back(0); // Not known.
|
||||
// root_infos[type_no].full_results.push_back(result);
|
||||
// algo++;
|
||||
//}
|
||||
//{
|
||||
// //algorithm_names.push_back("boost::math::cbrt"); // .
|
||||
// cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
// ti.start();
|
||||
// for (long i = 0; i < count; ++i)
|
||||
// {
|
||||
// result = boost::math::cbrt(to_root); //
|
||||
// }
|
||||
// now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
// root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
// ti.stop();
|
||||
// if (time < root_infos[type_no].min_time)
|
||||
// {
|
||||
// root_infos[type_no].min_time = time;
|
||||
// }
|
||||
// long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
// root_infos[type_no].distances.push_back(distance);
|
||||
// root_infos[type_no].iterations.push_back(0); // Iterations not knowable.
|
||||
// root_infos[type_no].full_results.push_back(result);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
{
|
||||
//algorithm_names.push_back("boost::math::cbrt"); // .
|
||||
result = 0;
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < count; ++i)
|
||||
{
|
||||
result += boost::math::cbrt(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
boost:int_least64_t n = now.user;
|
||||
|
||||
long time = static_cast<long>(now.user/1000); // convert nanoseconds to microseconds (assuming this is resolution).
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
ti.stop();
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
result = boost::math::cbrt(to_root);
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(0); // Iterations not knowable.
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
//algorithm_names.push_back("TOMS748"); //
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < count; ++i)
|
||||
{
|
||||
result = cbrt_noderiv<T>(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
long time = static_cast<long>(now.user/1000);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
// algorithm_names.push_back("Newton"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < count; ++i)
|
||||
{
|
||||
result = cbrt_deriv(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
long time = static_cast<long>(now.user/1000);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
//algorithm_names.push_back("Halley"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < count; ++i)
|
||||
{
|
||||
result = cbrt_2deriv(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
long time = static_cast<long>(now.user/1000);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
ti.stop();
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
|
||||
{
|
||||
// algorithm_names.push_back("Shroeder"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < count; ++i)
|
||||
{
|
||||
result = cbrt_2deriv_s(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
// int time = static_cast<int>(now.user / count);
|
||||
long time = static_cast<long>(now.user/1000);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
for (size_t i = 0; i != root_infos[type_no].times.size(); i++)
|
||||
{ // Normalize times.
|
||||
double normed_time = static_cast<double>(root_infos[type_no].times[i]);
|
||||
normed_time /= root_infos[type_no].min_time;
|
||||
root_infos[type_no].normed_times.push_back(normed_time);
|
||||
}
|
||||
algo++;
|
||||
return algo; // Count of how many algorithms used.
|
||||
} // test_root
|
||||
|
||||
void table_root_info(cpp_bin_float_100 full_value, cpp_bin_float_100 full_answer)
|
||||
{
|
||||
// Fill the elements.
|
||||
int type_count = 0;
|
||||
type_count = test_root<float>(full_value, full_answer, "float");
|
||||
type_count = test_root<double>(full_value, full_answer, "double");
|
||||
type_count = test_root<long double>(full_value, full_answer, "long double");
|
||||
type_count = test_root<cpp_bin_float_50>(full_value, full_answer, "cpp_bin_float_50");
|
||||
//type_count = test_root<cpp_bin_float_100>(full_value, full_answer, "cpp_bin_float_100");
|
||||
|
||||
std::cout << root_infos.size() << " floating-point types tested:" << std::endl;
|
||||
#ifndef NDEBUG
|
||||
std::cout << "Compiled in debug mode." << std::endl;
|
||||
#else
|
||||
std::cout << "Compiled in optimise mode." << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
for (size_t tp = 0; tp != root_infos.size(); tp++)
|
||||
{ // For all types:
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Floating-point type = " << root_infos[tp].short_typename << std::endl;
|
||||
std::cout << "Floating-point type = " << root_infos[tp].full_typename << std::endl;
|
||||
std::cout << "Max_digits10 = " << root_infos[tp].max_digits10 << std::endl;
|
||||
std::cout << "Binary digits = " << root_infos[tp].bin_digits << std::endl;
|
||||
std::cout << "Accuracy digits = " << root_infos[tp].get_digits << std::endl;
|
||||
std::cout << "min_time = " << root_infos[tp].min_time << std::endl;
|
||||
|
||||
std::cout << std::setprecision(root_infos[tp].max_digits10 ) << "Roots = ";
|
||||
std::copy(root_infos[tp].full_results.begin(), root_infos[tp].full_results.end(), std::ostream_iterator<cpp_bin_float_100>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Header row.
|
||||
std::cout << "Algorithm " << "Iterations " << "Times " << "Norm_times " << "Distance" << std::endl;
|
||||
std::vector<std::string>::iterator al_iter = algo_names.begin();
|
||||
|
||||
// Row for all algorithms.
|
||||
for (int algo = 0; algo != algo_names.size(); algo++)
|
||||
{
|
||||
std::cout
|
||||
<< std::left << std::setw(20) << algo_names[algo] << " "
|
||||
<< std::setw(8) << std::setprecision(2) << root_infos[tp].iterations[algo] << " "
|
||||
<< std::setw(8) << std::setprecision(5) << root_infos[tp].times[algo] << " "
|
||||
<< std::setw(8) << std::setprecision(3) << root_infos[tp].normed_times[algo] << " "
|
||||
<< std::setw(8) << std::setprecision(2) << root_infos[tp].distances[algo]
|
||||
<< std::endl;
|
||||
} // for algo
|
||||
} // for tp
|
||||
|
||||
// Print info as Quickbook table.
|
||||
|
||||
fout << "[table:cbrt_5 Info for float, double, long double and cpp_bin_float_50\n"
|
||||
<< "[[type name] [max_digits10] [binary digits] [required digits]]\n";// header.
|
||||
|
||||
for (size_t tp = 0; tp != root_infos.size(); tp++)
|
||||
{ // For all types:
|
||||
fout << "["
|
||||
<< "[" << root_infos[tp].short_typename << "]"
|
||||
<< "[" << root_infos[tp].max_digits10 << "]" // max_digits10
|
||||
<< "[" << root_infos[tp].bin_digits << "]"// < "Binary digits
|
||||
<< "[" << root_infos[tp].get_digits << "]]\n"; // Accuracy digits.
|
||||
} // tp
|
||||
fout << "] [/table cbrt_5] \n" << std::endl;
|
||||
|
||||
// Prepare Quickbook table of floating-point types.
|
||||
fout << "[table:cbrt_4 Cube root(28) for float, double, long double and cpp_bin_float_50\n"
|
||||
<< "[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]\n"
|
||||
<< "[[Algorithm]";
|
||||
for (size_t tp = 0; tp != root_infos.size(); tp++)
|
||||
{ // For all types:
|
||||
fout << "[Its]" << "[Times]" << "[Norm]" << "[Dis]" << "[ ]";
|
||||
}
|
||||
fout << "]" << std::endl;
|
||||
|
||||
// Row for all algorithms.
|
||||
for (int algo = 0; algo != algo_names.size(); algo++)
|
||||
{
|
||||
fout << "[[" << std::left << std::setw(9) << algo_names[algo] << "]";
|
||||
for (size_t tp = 0; tp != root_infos.size(); tp++)
|
||||
{ // For all types:
|
||||
|
||||
fout
|
||||
<< "[" << std::right << std::showpoint
|
||||
<< std::setw(3) << std::setprecision(2) << root_infos[tp].iterations[algo] << "]["
|
||||
<< std::setw(5) << std::setprecision(5) << root_infos[tp].times[algo] << "]["
|
||||
<< std::setw(3) << std::setprecision(2) << root_infos[tp].normed_times[algo] << "]["
|
||||
<< std::setw(3) << std::setprecision(2) << root_infos[tp].distances[algo] << "][ ]";
|
||||
} // tp
|
||||
fout <<"]" << std::endl;
|
||||
} // for algo
|
||||
fout << "] [/end of table cbrt_4]\n";
|
||||
} // void table_root_info
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
using namespace boost::math;
|
||||
|
||||
try
|
||||
{
|
||||
std::cout << "Tests run with " << BOOST_COMPILER << ", "
|
||||
<< BOOST_STDLIB << ", " << BOOST_PLATFORM << ", ";
|
||||
|
||||
if (fout.is_open())
|
||||
{
|
||||
std::cout << "\nOutput to " << filename << std::endl;
|
||||
}
|
||||
else
|
||||
{ // Failed to open.
|
||||
std::cout << " Open file " << filename << " for output failed!" << std::endl;
|
||||
std::cout << "error" << errno << std::endl;
|
||||
return boost::exit_failure;
|
||||
}
|
||||
|
||||
fout <<
|
||||
"[/""\n"
|
||||
"Copyright 2015 Paul A. Bristow.""\n"
|
||||
"Copyright 2015 John Maddock.""\n"
|
||||
"Distributed under the Boost Software License, Version 1.0.""\n"
|
||||
"(See accompanying file LICENSE_1_0.txt or copy at""\n"
|
||||
"http://www.boost.org/LICENSE_1_0.txt).""\n"
|
||||
"]""\n"
|
||||
<< std::endl;
|
||||
std::string debug_or_optimize;
|
||||
#ifdef _DEBUG
|
||||
#if (_DEBUG == 0)
|
||||
debug_or_optimize = "Compiled in debug mode.";
|
||||
#else
|
||||
debug_or_optimize = "Compiled in optimise mode.";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Print out the program/compiler/stdlib/platform names as a Quickbook comment:
|
||||
fout << "\n[h5 Program " << sourcefilename << ", "
|
||||
<< BOOST_COMPILER << ", "
|
||||
<< BOOST_STDLIB << ", "
|
||||
<< BOOST_PLATFORM << ", "
|
||||
<< debug_or_optimize << "[br]"
|
||||
<< count << " evaluations of each of " << algo_names.size() << " root_finding algorithms.[br]"
|
||||
<< "Fraction of maximum possible bits of accuracy required is " << digits_accuracy
|
||||
<< "]"
|
||||
<< std::endl;
|
||||
|
||||
std::cout << count << " evaluations of root_finding." << std::endl;
|
||||
|
||||
BOOST_MATH_CONTROL_FP;
|
||||
|
||||
cpp_bin_float_100 full_value("28");
|
||||
|
||||
cpp_bin_float_100 full_answer ("3.036588971875662519420809578505669635581453977248111123242141654169177268411884961770250390838097895");
|
||||
|
||||
std::copy(max_digits10s.begin(), max_digits10s.end(), std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
table_root_info(full_value, full_answer);
|
||||
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
catch (std::exception ex)
|
||||
{
|
||||
std::cout << "exception thrown: " << ex.what() << std::endl;
|
||||
return boost::exit_failure;
|
||||
}
|
||||
} // int main()
|
||||
|
||||
/*
|
||||
debug
|
||||
|
||||
1> float, maxdigits10 = 9
|
||||
1> 6 algorithms used.
|
||||
1> Digits required = 24.0000000
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1> Times 156 312 18750 4375 3437 3906
|
||||
1> Iterations: 0 0 8 6 4 5
|
||||
1> Distance: 0 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
|
||||
release
|
||||
|
||||
1> float, maxdigits10 = 9
|
||||
1> 6 algorithms used.
|
||||
1> Digits required = 24.0000000
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1> Times 0 312 6875 937 937 937
|
||||
1> Iterations: 0 0 8 6 4 5
|
||||
1> Distance: 0 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
|
||||
|
||||
1>
|
||||
1> 5 algorithms used:
|
||||
1> 10 algorithms used:
|
||||
1> boost::math::cbrt TOMS748 Newton Halley Shroeder boost::math::cbrt TOMS748 Newton Halley Shroeder
|
||||
1> 2 types compared.
|
||||
1> Precision of full type = 102 decimal digits
|
||||
1> Find root of 28.000000000000000,
|
||||
1> Expected answer = 3.0365889718756625
|
||||
1> typeid(T).name()float, maxdigits10 = 9
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1>
|
||||
1> Iterations: 0 8 6 4 5
|
||||
1> Times 468 8437 4375 3593 4062
|
||||
1> Min Time 468
|
||||
1> Normalized Times 1.00 18.0 9.35 7.68 8.68
|
||||
1> Distance: 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
1> ==================================================================
|
||||
1> typeid(T).name()double, maxdigits10 = 17
|
||||
1> find root of 28.000000000000000, expected answer = 3.0365889718756625
|
||||
1>
|
||||
1> Iterations: 0 11 7 5 6
|
||||
1> Times 312 15000 4531 3906 4375
|
||||
1> Min Time 312
|
||||
1> Normalized Times 1.00 48.1 14.5 12.5 14.0
|
||||
1> Distance: 1 2 0 0 0
|
||||
1> Roots: 3.0365889718756622 3.0365889718756618 3.0365889718756627 3.0365889718756627 3.0365889718756627
|
||||
1> ==================================================================
|
||||
|
||||
|
||||
Release
|
||||
|
||||
1> 5 algorithms used:
|
||||
1> 10 algorithms used:
|
||||
1> boost::math::cbrt TOMS748 Newton Halley Shroeder boost::math::cbrt TOMS748 Newton Halley Shroeder
|
||||
1> 2 types compared.
|
||||
1> Precision of full type = 102 decimal digits
|
||||
1> Find root of 28.000000000000000,
|
||||
1> Expected answer = 3.0365889718756625
|
||||
1> typeid(T).name()float, maxdigits10 = 9
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1>
|
||||
1> Iterations: 0 8 6 4 5
|
||||
1> Times 312 781 937 937 937
|
||||
1> Min Time 312
|
||||
1> Normalized Times 1.00 2.50 3.00 3.00 3.00
|
||||
1> Distance: 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
1> ==================================================================
|
||||
1> typeid(T).name()double, maxdigits10 = 17
|
||||
1> find root of 28.000000000000000, expected answer = 3.0365889718756625
|
||||
1>
|
||||
1> Iterations: 0 11 7 5 6
|
||||
1> Times 312 1093 937 937 937
|
||||
1> Min Time 312
|
||||
1> Normalized Times 1.00 3.50 3.00 3.00 3.00
|
||||
1> Distance: 1 2 0 0 0
|
||||
1> Roots: 3.0365889718756622 3.0365889718756618 3.0365889718756627 3.0365889718756627 3.0365889718756627
|
||||
1> ==================================================================
|
||||
|
||||
|
||||
|
||||
1> 5 algorithms used:
|
||||
1> 15 algorithms used:
|
||||
1> boost::math::cbrt TOMS748 Newton Halley Shroeder boost::math::cbrt TOMS748 Newton Halley Shroeder boost::math::cbrt TOMS748 Newton Halley Shroeder
|
||||
1> 3 types compared.
|
||||
1> Precision of full type = 102 decimal digits
|
||||
1> Find root of 28.00000000000000000000000000000000000000000000000000,
|
||||
1> Expected answer = 3.036588971875662519420809578505669635581453977248111
|
||||
1> typeid(T).name()float, maxdigits10 = 9
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1>
|
||||
1> Iterations: 0 8 6 4 5
|
||||
1> Times 156 781 937 1093 937
|
||||
1> Min Time 156
|
||||
1> Normalized Times 1.00 5.01 6.01 7.01 6.01
|
||||
1> Distance: 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
1> ==================================================================
|
||||
1> typeid(T).name()double, maxdigits10 = 17
|
||||
1> find root of 28.000000000000000, expected answer = 3.0365889718756625
|
||||
1>
|
||||
1> Iterations: 0 11 7 5 6
|
||||
1> Times 312 1093 937 937 937
|
||||
1> Min Time 312
|
||||
1> Normalized Times 1.00 3.50 3.00 3.00 3.00
|
||||
1> Distance: 1 2 0 0 0
|
||||
1> Roots: 3.0365889718756622 3.0365889718756618 3.0365889718756627 3.0365889718756627 3.0365889718756627
|
||||
1> ==================================================================
|
||||
1> typeid(T).name()class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,0>, maxdigits10 = 52
|
||||
1> find root of 28.00000000000000000000000000000000000000000000000000, expected answer = 3.036588971875662519420809578505669635581453977248111
|
||||
1>
|
||||
1> Iterations: 0 13 9 6 7
|
||||
1> Times 8750 177343 30312 52968 58125
|
||||
1> Min Time 8750
|
||||
1> Normalized Times 1.00 20.3 3.46 6.05 6.64
|
||||
1> Distance: 0 0 -1 0 0
|
||||
1> Roots: 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248117 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248106
|
||||
1> ==================================================================
|
||||
|
||||
Reduce accuracy required to 0.5
|
||||
|
||||
1> 5 algorithms used:
|
||||
1> 15 algorithms used:
|
||||
1> boost::math::cbrt TOMS748 Newton Halley Shroeder
|
||||
1> 3 floating_point types compared.
|
||||
1> Precision of full type = 102 decimal digits
|
||||
1> Find root of 28.00000000000000000000000000000000000000000000000000,
|
||||
1> Expected answer = 3.036588971875662519420809578505669635581453977248111
|
||||
1> typeid(T).name() = float, maxdigits10 = 9
|
||||
1> Digits accuracy fraction required = 0.500000000
|
||||
1> find root of 28.0000000, expected answer = 3.03658897
|
||||
1>
|
||||
1> Iterations: 0 8 5 3 4
|
||||
1> Times 156 5937 1406 1250 1250
|
||||
1> Min Time 156
|
||||
1> Normalized Times 1.0 38. 9.0 8.0 8.0
|
||||
1> Distance: 0 -1 0 0 0
|
||||
1> Roots: 3.03658891 3.03658915 3.03658891 3.03658891 3.03658891
|
||||
1> ==================================================================
|
||||
1> typeid(T).name() = double, maxdigits10 = 17
|
||||
1> Digits accuracy fraction required = 0.50000000000000000
|
||||
1> find root of 28.000000000000000, expected answer = 3.0365889718756625
|
||||
1>
|
||||
1> Iterations: 0 8 6 4 5
|
||||
1> Times 156 6250 1406 1406 1250
|
||||
1> Min Time 156
|
||||
1> Normalized Times 1.0 40. 9.0 9.0 8.0
|
||||
1> Distance: 1 3695766 0 0 0
|
||||
1> Roots: 3.0365889718756622 3.0365889702344129 3.0365889718756627 3.0365889718756627 3.0365889718756627
|
||||
1> ==================================================================
|
||||
1> typeid(T).name() = class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,0>, maxdigits10 = 52
|
||||
1> Digits accuracy fraction required = 0.5000000000000000000000000000000000000000000000000000
|
||||
1> find root of 28.00000000000000000000000000000000000000000000000000, expected answer = 3.036588971875662519420809578505669635581453977248111
|
||||
1>
|
||||
1> Iterations: 0 11 8 5 6
|
||||
1> Times 11562 239843 34843 47500 47812
|
||||
1> Min Time 11562
|
||||
1> Normalized Times 1.0 21. 3.0 4.1 4.1
|
||||
1> Distance: 0 0 -1 0 0
|
||||
1> Roots: 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248117 3.036588971875662519420809578505669635581453977248106 3.036588971875662519420809578505669635581453977248106
|
||||
1> ==================================================================
|
||||
|
||||
|
||||
|
||||
*/
|
||||
@@ -12,10 +12,6 @@
|
||||
// Note that this file contains Quickbook mark-up as well as code
|
||||
// and comments, don't change any of the special comment mark-ups!
|
||||
|
||||
//#ifdef _MSC_VER
|
||||
//# pragma warning(disable: 4180) // qualifier has no effect (in Fusion).
|
||||
//#endif
|
||||
|
||||
//#define BOOST_MATH_INSTRUMENT
|
||||
|
||||
/*
|
||||
@@ -27,8 +23,8 @@ It shows how use of derivatives can improve the speed.
|
||||
implementation of `boost::math::cbrt`, mainly by using a better computed initial 'guess'
|
||||
at `<boost/math/special_functions/cbrt.hpp>`).
|
||||
|
||||
Then we show how a high roots (fifth) can be computed,
|
||||
and in root_finding_n_example.cpp a generic method
|
||||
Then we show how a higher root (fifth) can be computed,
|
||||
and in `root_finding_n_example.cpp` a generic method
|
||||
for the ['n]th root that constructs the derivatives at compile-time,
|
||||
|
||||
These methods should be applicable to other functions that can be differentiated easily.
|
||||
@@ -135,7 +131,7 @@ T cbrt_noderiv(T x)
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
// Some fraction of digits is used to control how accurate to try to make the result.
|
||||
int get_digits = (digits * 3) /4; // Near maximum (3/4) possible accuracy.
|
||||
eps_tolerance<double> tol(get_digits); // Set the tolerance.
|
||||
eps_tolerance<T> tol(get_digits); // Set the tolerance.
|
||||
std::pair<T, T> r =
|
||||
bracket_and_solve_root(cbrt_functor_noderiv<T>(x), guess, factor, is_rising, tol, it);
|
||||
return r.first + (r.second - r.first)/2; // Midway between brackets.
|
||||
@@ -156,12 +152,12 @@ So it may be wise to chose some reasonable estimate of how many iterations may b
|
||||
|
||||
if (it >= maxit)
|
||||
{
|
||||
std::cout << "Unable to locate solution in " << maxit << " iterations:"
|
||||
" Current best guess is between " << r.first << " and " << r.second << std::endl;
|
||||
std::cout << "Unable to locate solution in " << maxit << " iterations:"
|
||||
" Current best guess is between " << r.first << " and " << r.second << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Converged after " << it << " (from maximum of " << maxit << " iterations)." << std::endl;
|
||||
std::cout << "Converged after " << it << " (from maximum of " << maxit << " iterations)." << std::endl;
|
||||
}
|
||||
|
||||
for output like
|
||||
@@ -200,10 +196,10 @@ To \'return\' two values, we use a `std::pair` of floating-point values:
|
||||
|
||||
template <class T>
|
||||
struct cbrt_functor_deriv
|
||||
{ // Functor also returning 1st derviative.
|
||||
{ // Functor also returning 1st derivative.
|
||||
cbrt_functor_deriv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of,
|
||||
// for example: calling cbrt_functor_deriv<T>(x) to use to get cube root of x.
|
||||
// for example: calling cbrt_functor_deriv<T>(a) to use to get cube root of a.
|
||||
}
|
||||
std::pair<T, T> operator()(T const& x)
|
||||
{ // Return both f(x) and f'(x).
|
||||
@@ -212,7 +208,7 @@ struct cbrt_functor_deriv
|
||||
return std::make_pair(fx, dx); // 'return' both fx and dx.
|
||||
}
|
||||
private:
|
||||
T a; // to be 'cube_rooted'.
|
||||
T a; // Store value to be 'cube_rooted'.
|
||||
};
|
||||
|
||||
/*`Our cube root function is now:*/
|
||||
@@ -404,8 +400,8 @@ int main()
|
||||
//[root_finding_main_1
|
||||
try
|
||||
{
|
||||
double threecubed = 27.; // value that has an exactly representable integer cube root.
|
||||
double threecubedp1 = 28.; // whose cube root is *not* exactly representable.
|
||||
double threecubed = 27.; // Value that has an *exactly representable* integer cube root.
|
||||
double threecubedp1 = 28.; // Value whose cube root is *not* exactly representable.
|
||||
|
||||
std::cout << "cbrt(28) " << boost::math::cbrt(28.) << std::endl; // boost::math:: version of cbrt.
|
||||
std::cout << "std::cbrt(28) " << std::cbrt(28.) << std::endl; // std:: version of cbrt.
|
||||
|
||||
@@ -162,7 +162,7 @@ template <class T>
|
||||
T fifth_noderiv(T x)
|
||||
{ //! \returns fifth root of x using bracket_and_solve (no derivatives).
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math; // For bracket_and_solve_root.
|
||||
using namespace boost::math::tools; // For bracket_and_solve_root.
|
||||
|
||||
int exponent;
|
||||
frexp(x, &exponent); // Get exponent of z (ignore mantissa).
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <tuple>
|
||||
#include <utility> // pair, make_pair
|
||||
|
||||
// #define BUILTIN_POW_GUESS // define to use std::pow function to obtain a guess.
|
||||
|
||||
template <class T>
|
||||
T cbrt_2deriv(T x)
|
||||
{ // return cube root of x using 1st and 2nd derivatives and Halley.
|
||||
@@ -46,21 +48,32 @@ T cbrt_2deriv(T x)
|
||||
using namespace boost::math::tools; // For halley_iterate.
|
||||
|
||||
// If T is not a binary floating-point type, for example, cpp_dec_float_50
|
||||
// then frexp is not defined, so it is necessary to compute the guess using a built-in type,
|
||||
// then frexp may not be defined,
|
||||
// so it may be necessary to compute the guess using a built-in type,
|
||||
// probably quickest using double, but perhaps with float or long double.
|
||||
typedef double guess_type;
|
||||
// Note that the range of exponent may be restricted by a built-in-type for guess.
|
||||
|
||||
typedef long double guess_type;
|
||||
|
||||
#ifdef BUILTIN_POW_GUESS
|
||||
guess_type pow_guess = std::pow(static_cast<guess_type>(x), static_cast<guess_type>(1) / 3);
|
||||
T guess = pow_guess;
|
||||
T min = pow_guess /2;
|
||||
T max = pow_guess * 2;
|
||||
#else
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = ldexp(static_cast<guess_type>(1.), exponent / 3); // Rough guess is to divide the exponent by three.
|
||||
T min = ldexp(static_cast<guess_type>(1.) / 2, exponent / 3); // Minimum possible value is half our guess.
|
||||
T max = ldexp(static_cast<guess_type>(2.), exponent / 3); // Maximum possible value is twice our guess.
|
||||
#endif
|
||||
|
||||
int digits = std::numeric_limits<T>::digits / 2; // Half maximum possible binary digits accuracy for type T.
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = halley_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, digits, it);
|
||||
// Can show how many iterations (updated by halley_iterate).
|
||||
// std::cout << "Iterations " << maxit << std::endl;
|
||||
// std::cout << "Iterations " << it << " (from max of "<< maxit << ")." << std::endl;
|
||||
return result;
|
||||
} // cbrt_2deriv(x)
|
||||
|
||||
@@ -76,6 +89,7 @@ struct cbrt_functor_2deriv
|
||||
std::tuple<T, T, T> operator()(T const& x)
|
||||
{ // Return both f(x) and f'(x) and f''(x).
|
||||
T fx = x*x*x - a; // Difference (estimate x^3 - value).
|
||||
// std::cout << "x = " << x << "\nfx = " << fx << std::endl;
|
||||
T dx = 3 * x*x; // 1st derivative = 3x^2.
|
||||
T d2x = 6 * x; // 2nd derivative = 6x.
|
||||
return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x.
|
||||
@@ -124,7 +138,7 @@ T nth_2deriv(T x)
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = halley_iterate(nth_functor_2deriv<n, T>(x), guess, min, max, digits, it);
|
||||
// Can show how many iterations (updated by halley_iterate).
|
||||
cout << it << " iterations (from max of " << maxit << ")" << endl;
|
||||
std::cout << it << " iterations (from max of " << maxit << ")" << std::endl;
|
||||
|
||||
return result;
|
||||
} // nth_2deriv(x)
|
||||
@@ -203,6 +217,15 @@ int main()
|
||||
|
||||
/*
|
||||
|
||||
Description: Autorun "J:\Cpp\MathToolkit\test\Math_test\Release\root_finding_multiprecision.exe"
|
||||
Multiprecision Root finding Example.
|
||||
cbrt(2) = 1.2599210498948731647672106072782283505702514647015
|
||||
cbrt(2) = 1.2599210498948731906665443602832965552806854248047
|
||||
cbrt(2) = 1.2599210498948731647672106072782283505702514647015
|
||||
cbrt(2) = 1.2599210498948731647672106072782283505702514647015
|
||||
value = 2, cube root =1.25992104989487
|
||||
value = 2, cube root =1.25992104989487
|
||||
value = 2, cube root =1.2599210498948731647672106072782283505702514647015
|
||||
|
||||
|
||||
*/
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp> // For cpp_dec_float_50.
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp> // using boost::multiprecision::cpp_bin_float_50;
|
||||
#ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2013.
|
||||
#include <boost/multiprecision/float128.hpp>
|
||||
# include <boost/multiprecision/float128.hpp>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
@@ -73,14 +73,14 @@ std::cout << " x = " << x << ", fx = " << fx << ", dx = " << dx << ", dx2 = " <<
|
||||
#endif
|
||||
*/
|
||||
|
||||
// If T is a floating-point type, might be quick to compute the guess using a built-in type,
|
||||
// If T is a floating-point type, might be quicker to compute the guess using a built-in type,
|
||||
// probably quickest using double, but perhaps with float or long double, T.
|
||||
|
||||
// If T is not a floating-point type for which frexp and ldexp are not defined,
|
||||
// If T is a type for which frexp and ldexp are not defined,
|
||||
// then it is necessary to compute the guess using a built-in type,
|
||||
// probably quickest (but limited range) using double,
|
||||
// but perhaps with float or long double or a multiprecision T for greater range.
|
||||
// typedef double guess_type;
|
||||
// but perhaps with float or long double, or a multiprecision T for the full range of T.
|
||||
// typedef double guess_type; is used to specify the this.
|
||||
|
||||
//[root_finding_nth_function_2deriv
|
||||
|
||||
@@ -95,7 +95,7 @@ T nth_2deriv(T x)
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 1000) == false, "root N is too big!");
|
||||
|
||||
typedef double guess_type;
|
||||
typedef double guess_type; // double may restrict (exponent) range for a multiprecision T?
|
||||
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
@@ -154,7 +154,7 @@ int main()
|
||||
show_nth_root<5, double>(2.);
|
||||
show_nth_root<5, long double>(2.);
|
||||
#ifndef _MSC_VER // float128 is not supported by Microsoft compiler 2013.
|
||||
show_nth_root<float128, 5>(2);
|
||||
show_nth_root<5, float128>(2);
|
||||
#endif
|
||||
show_nth_root<5, cpp_dec_float_50>(2); // dec
|
||||
show_nth_root<5, cpp_bin_float_50>(2); // bin
|
||||
@@ -178,6 +178,7 @@ int main()
|
||||
|
||||
/*
|
||||
//[root_finding_example_output_1
|
||||
Using MSVC 2013
|
||||
|
||||
nth Root finding Example.
|
||||
Type double value = 2, 5th root = 1.14869835499704
|
||||
@@ -188,4 +189,24 @@ Type class boost::multiprecision::number<class boost::multiprecision::backends::
|
||||
5th root = 1.1486983549970350067986269467779275894438508890978
|
||||
|
||||
//] [/root_finding_example_output_1]
|
||||
*/
|
||||
|
||||
//[root_finding_example_output_2
|
||||
|
||||
Using GCC 4.91 (includes float_128 type)
|
||||
|
||||
nth Root finding Example.
|
||||
Type d value = 2, 5th root = 1.14869835499704
|
||||
Type e value = 2, 5th root = 1.14869835499703501
|
||||
Type N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE value = 2, 5th root = 1.148698354997035006798626946777928
|
||||
Type N5boost14multiprecision6numberINS0_8backends13cpp_dec_floatILj50EivEELNS0_26expression_template_optionE1EEE value = 2, 5th root = 1.1486983549970350067986269467779275894438508890978
|
||||
Type N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE0EEE value = 2, 5th root = 1.1486983549970350067986269467779275894438508890978
|
||||
|
||||
RUN SUCCESSFUL (total time: 63ms)
|
||||
|
||||
//] [/root_finding_example_output_2]
|
||||
*/
|
||||
|
||||
/*
|
||||
Throw out of range using GCC release mode :-(
|
||||
|
||||
*/
|
||||
874
example/root_n_finding_algorithms.cpp
Normal file
874
example/root_n_finding_algorithms.cpp
Normal file
@@ -0,0 +1,874 @@
|
||||
// Copyright Paul A. Bristow 2015
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Comparison of finding roots using TOMS748, Newton-Raphson, Halley & Schroeder algorithms.
|
||||
// root_n_finding_algorithms.cpp Generalised for nth root version.
|
||||
|
||||
// http://en.wikipedia.org/wiki/Cube_root
|
||||
|
||||
// Note that this file contains Quickbook mark-up as well as code
|
||||
// and comments, don't change any of the special comment mark-ups!
|
||||
// This program also writes files in Quickbook tables mark-up format.
|
||||
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/math/special_functions/math_fwd.hpp>
|
||||
#include <boost/math/concepts/real_concept.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <boost/math/tools/roots.hpp>
|
||||
//using boost::math::policies::policy;
|
||||
|
||||
//using boost::math::tools::eps_tolerance; // Binary functor for specified number of bits.
|
||||
//using boost::math::tools::bracket_and_solve_root;
|
||||
//using boost::math::tools::toms748_solve;
|
||||
//using boost::math::tools::halley_iterate;
|
||||
//using boost::math::tools::newton_raphson_iterate;
|
||||
//using boost::math::tools::schroeder_iterate;
|
||||
|
||||
#include <boost/math/special_functions/next.hpp> // For float_distance.
|
||||
#include <boost/math/special_functions/pow.hpp> // For float_distance.
|
||||
#include <boost/math/tools/tuple.hpp> // for tuple and make_tuple.
|
||||
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp> // is binary.
|
||||
using boost::multiprecision::cpp_bin_float_100;
|
||||
using boost::multiprecision::cpp_bin_float_50;
|
||||
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/multiprecision/cpp_bin_float/io.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <fstream> // std::ofstream
|
||||
#include <cmath>
|
||||
#include <typeinfo> // for type name using typid(thingy).name();
|
||||
|
||||
#ifdef __FILE__
|
||||
std::string sourcefilename = __FILE__;
|
||||
#else
|
||||
std::string sourcefilename("");
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
std::string root = BOOST_STRINGIZE($(BOOST_ROOT));
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ROOT
|
||||
# define BOOST_ROOT i:/modular-boost/
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_ROOT
|
||||
std::string boost_root = BOOST_STRINGIZE(BOOST_ROOT);
|
||||
#endif
|
||||
|
||||
std::string fp_hardware; // Any hardware features like SEE or AVX
|
||||
|
||||
const std::string roots_name = "libs/math/doc/roots/";
|
||||
|
||||
const std::string full_roots_name(boost_root + "libs/math/doc/roots/");
|
||||
|
||||
const std::size_t nooftypes = 4;
|
||||
const std::size_t noofalgos = 4;
|
||||
const std::size_t noofroots = 3;
|
||||
|
||||
double digits_accuracy = 1.0; // 1 == maximum possible accuracy.
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
std::ofstream fout;
|
||||
|
||||
std::vector<std::string> algo_names =
|
||||
{
|
||||
"TOMS748", "Newton", "Halley", "Schroeder"
|
||||
};
|
||||
|
||||
std::vector<std::string> names =
|
||||
{
|
||||
"float", "double", "long double", "cpp_bin_float50"
|
||||
};
|
||||
|
||||
uintmax_t iters; // Global as value of iterations is not returned.
|
||||
|
||||
struct root_info
|
||||
{ // for a floating-point type, float, double ...
|
||||
std::size_t max_digits10; // for type.
|
||||
std::string full_typename; // for type from type_id.name().
|
||||
std::string short_typename; // for type "float", "double", "cpp_bin_float_50" ....
|
||||
std::size_t bin_digits; // binary in floating-point type numeric_limits<T>::digits;
|
||||
int get_digits; // fraction of maximum possible accuracy required.
|
||||
// = digits * digits_accuracy
|
||||
// Vector of values (4) for each algorithm, TOMS748, Newton, Halley & Schroeder.
|
||||
//std::vector< boost::int_least64_t> times; converted to int.
|
||||
std::vector<int> times; // arbirary units (ticks).
|
||||
//boost::int_least64_t min_time = std::numeric_limits<boost::int_least64_t>::max(); // Used to normalize times (as int).
|
||||
std::vector<double> normed_times;
|
||||
int min_time = std::numeric_limits<int>::max(); // Used to normalize times.
|
||||
std::vector<uintmax_t> iterations;
|
||||
std::vector<long int> distances;
|
||||
std::vector<cpp_bin_float_100> full_results;
|
||||
}; // struct root_info
|
||||
|
||||
std::vector<root_info> root_infos; // One element for each floating-point type used.
|
||||
|
||||
inline std::string build_test_name(const char* type_name, const char* test_name)
|
||||
{
|
||||
std::string result(BOOST_COMPILER);
|
||||
result += "|";
|
||||
result += BOOST_STDLIB;
|
||||
result += "|";
|
||||
result += BOOST_PLATFORM;
|
||||
result += "|";
|
||||
result += type_name;
|
||||
result += "|";
|
||||
result += test_name;
|
||||
#ifdef _DEBUG
|
||||
// Assume preprocessor defines provided for MSVC and added for GCC -D_DEBUG=1 or
|
||||
#if (_DEBUG == 0)
|
||||
result += "|";
|
||||
result += " debug";
|
||||
#else // for GCC -D_DEBUG=1
|
||||
result += "|";
|
||||
result += " release";
|
||||
#endif
|
||||
#endif
|
||||
result += "|";
|
||||
return result;
|
||||
} // std::string build_test_name
|
||||
|
||||
// Algorithms //////////////////////////////////////////////
|
||||
|
||||
// No derivatives - using TOMS748 internally.
|
||||
|
||||
template <int N, typename T = double>
|
||||
struct nth_root_functor_noderiv
|
||||
{ // Nth root of x using only function - no derivatives.
|
||||
nth_root_functor_noderiv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor just stores value a to find root of.
|
||||
}
|
||||
T operator()(T const& x)
|
||||
{
|
||||
using boost::math::pow;
|
||||
T fx = pow<N>(x) -a; // Difference (estimate x^n - a).
|
||||
return fx;
|
||||
}
|
||||
private:
|
||||
T a; // to be 'cube_rooted'.
|
||||
}; // template <int N, class T> struct nth_root_functor_noderiv
|
||||
|
||||
template <int N, class T = double>
|
||||
T nth_root_noderiv(T x)
|
||||
{ // return Nth root of x using bracket_and_solve (using NO derivatives).
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools; // For bracket_and_solve_root.
|
||||
|
||||
typedef double guess_type;
|
||||
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = static_cast<T>(ldexp(static_cast<guess_type>(1.), exponent / N)); // Rough guess is to divide the exponent by n.
|
||||
//T min = static_cast<T>(ldexp(static_cast<guess_type>(1.) / 2, exponent / N)); // Minimum possible value is half our guess.
|
||||
//T max = static_cast<T>(ldexp(static_cast<guess_type>(2.), exponent / N)); // Maximum possible value is twice our guess.
|
||||
|
||||
T factor = 2; // How big steps to take when searching.
|
||||
|
||||
const boost::uintmax_t maxit = 50; // Limit to maximum iterations.
|
||||
boost::uintmax_t it = maxit; // Initally our chosen max iterations, but updated with actual.
|
||||
bool is_rising = true; // So if result if guess^3 is too low, then try increasing guess.
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
// Some fraction of digits is used to control how accurate to try to make the result.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
eps_tolerance<T> tol(get_digits); // Set the tolerance.
|
||||
std::pair<T, T> r;
|
||||
r = bracket_and_solve_root(nth_root_functor_noderiv<N, T>(x), guess, factor, is_rising, tol, it);
|
||||
iters = it;
|
||||
T result = r.first + (r.second - r.first) / 2; // Midway between brackets.
|
||||
return result;
|
||||
} // template <class T> T nth_root_noderiv(T x)
|
||||
|
||||
// Using 1st derivative only Newton-Raphson
|
||||
|
||||
template <int N, class T = double>
|
||||
struct nth_root_functor_1deriv
|
||||
{ // Functor also returning 1st derviative.
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
|
||||
nth_root_functor_1deriv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of, for example:
|
||||
}
|
||||
std::pair<T, T> operator()(T const& x)
|
||||
{ // Return both f(x) and f'(x).
|
||||
using boost::math::pow; // // Compile-time integral power.
|
||||
T fx = pow<N>(x) - a; // Difference (estimate x^n - a).
|
||||
T dx = N * pow<N - 1>(x); // 1st derivative f'(x).
|
||||
return std::make_pair(fx, dx); // 'return' both fx and dx.
|
||||
}
|
||||
|
||||
private:
|
||||
T a; // to be 'nth_rooted'.
|
||||
}; // struct nthroot__functor_1deriv
|
||||
|
||||
template <int N, class T = double>
|
||||
T nth_root_1deriv(T x)
|
||||
{ // return nth root of x using 1st derivative and Newton_Raphson.
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools; // For newton_raphson_iterate.
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 1000) == false, "root N is too big!");
|
||||
|
||||
typedef double guess_type;
|
||||
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = static_cast<T>(ldexp(static_cast<guess_type>(1.), exponent / N)); // Rough guess is to divide the exponent by n.
|
||||
T min = static_cast<T>(ldexp(static_cast<guess_type>(1.) / 2, exponent / N)); // Minimum possible value is half our guess.
|
||||
T max = static_cast<T>(ldexp(static_cast<guess_type>(2.), exponent / N)); // Maximum possible value is twice our guess.
|
||||
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = newton_raphson_iterate(nth_root_functor_1deriv<N, T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
return result;
|
||||
} // T nth_root_1_deriv Newton-Raphson
|
||||
|
||||
// Using 1st and 2nd derivatives with Halley algorithm.
|
||||
|
||||
template <int N, class T = double>
|
||||
struct nth_root_functor_2deriv
|
||||
{ // Functor returning both 1st and 2nd derivatives.
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
|
||||
nth_root_functor_2deriv(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of, for example:
|
||||
}
|
||||
|
||||
// using boost::math::tuple; // to return three values.
|
||||
std::tuple<T, T, T> operator()(T const& x)
|
||||
{ // Return f(x), f'(x) and f''(x).
|
||||
using boost::math::pow; // Compile-time integral power.
|
||||
T fx = pow<N, T>(x) - a; // Difference (estimate x^n - a).
|
||||
T dx = N * pow<N - 1, T>(x); // 1st derivative f'(x).
|
||||
T d2x = N * (N - 1) * pow<N - 2, T>(x); // 2nd derivative f''(x).
|
||||
|
||||
return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x.
|
||||
}
|
||||
private:
|
||||
T a; // to be 'nth_rooted'.
|
||||
};
|
||||
|
||||
template <int N, class T = double>
|
||||
T nth_root_2deriv(T x)
|
||||
{ // return nth root of x using 1st and 2nd derivatives and Halley.
|
||||
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools; // For halley_iterate.
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 1000) == false, "root N is too big!");
|
||||
|
||||
typedef double guess_type;
|
||||
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = static_cast<T>(ldexp(static_cast<guess_type>(1.), exponent / N)); // Rough guess is to divide the exponent by n.
|
||||
T min = static_cast<T>(ldexp(static_cast<guess_type>(1.) / 2, exponent / N)); // Minimum possible value is half our guess.
|
||||
T max = static_cast<T>(ldexp(static_cast<guess_type>(2.), exponent / N)); // Maximum possible value is twice our guess.
|
||||
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = halley_iterate(nth_root_functor_2deriv<N, T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
|
||||
return result;
|
||||
} // nth_2deriv Halley
|
||||
|
||||
// Using 1st and 2nd derivatives using Schroeder algorithm.
|
||||
|
||||
template <int N, class T = double>
|
||||
struct nth_root_functor_2deriv_s
|
||||
{ // Functor returning nth root using both 1st and 2nd derivatives.
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
|
||||
nth_root_functor_2deriv_s(T const& to_find_root_of) : a(to_find_root_of)
|
||||
{ // Constructor stores value a to find root of, for example:
|
||||
}
|
||||
|
||||
// using boost::math::tuple; // to return three values.
|
||||
std::tuple<T, T, T> operator()(T const& x)
|
||||
{ // Return f(x), f'(x) and f''(x).
|
||||
using boost::math::pow;
|
||||
T fx = pow<N>(x) -a; // Difference (estimate x^n - a).
|
||||
T dx = N * pow<N - 1>(x); // 1st derivative f'(x).
|
||||
T d2x = N * (N - 1) * pow<N - 2 >(x); // 2nd derivative f''(x).
|
||||
|
||||
return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x.
|
||||
}
|
||||
private:
|
||||
T a; // to be 'nth_rooted'.
|
||||
}; // template <int N, class T = double> struct nth_root_functor_2deriv_s
|
||||
|
||||
template <int N, class T = double>
|
||||
T nth_root_2deriv_s(T x)
|
||||
{ // return nth root of x using 1st and 2nd derivatives and Schroeder.
|
||||
|
||||
using namespace std; // Help ADL of std functions.
|
||||
using namespace boost::math::tools; // For schroeder_iterate.
|
||||
|
||||
BOOST_STATIC_ASSERT_MSG(boost::is_integral<T>::value == false, "Only floating-point type types can be used!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 0) == true, "root N must be > 0!");
|
||||
BOOST_STATIC_ASSERT_MSG((N > 1000) == false, "root N is too big!");
|
||||
|
||||
typedef double guess_type;
|
||||
|
||||
int exponent;
|
||||
frexp(static_cast<guess_type>(x), &exponent); // Get exponent of z (ignore mantissa).
|
||||
T guess = static_cast<T>(ldexp(static_cast<guess_type>(1.), exponent / N)); // Rough guess is to divide the exponent by n.
|
||||
T min = static_cast<T>(ldexp(static_cast<guess_type>(1.) / 2, exponent / N)); // Minimum possible value is half our guess.
|
||||
T max = static_cast<T>(ldexp(static_cast<guess_type>(2.), exponent / N)); // Maximum possible value is twice our guess.
|
||||
|
||||
int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T.
|
||||
int get_digits = static_cast<int>(digits * digits_accuracy);
|
||||
const boost::uintmax_t maxit = 20;
|
||||
boost::uintmax_t it = maxit;
|
||||
T result = schroeder_iterate(nth_root_functor_2deriv_s<N, T>(x), guess, min, max, get_digits, it);
|
||||
iters = it;
|
||||
|
||||
return result;
|
||||
} // T nth_root_2deriv_s Schroder
|
||||
|
||||
//////////////////////////////////////////////////////// end of algorithms - perhaps in a separate .hpp?
|
||||
|
||||
//! Print 4 floating-point types info: max_digits10, digits and required accuracy digits as a Quickbook table.
|
||||
int table_type_info(double digits_accuracy)
|
||||
{
|
||||
std::string qbk_name = full_roots_name; // Prefix by boost_root file.
|
||||
|
||||
qbk_name += "type_info_table";
|
||||
std::stringstream ss;
|
||||
ss.precision(3);
|
||||
ss << "_" << digits_accuracy * 100;
|
||||
qbk_name += ss.str();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
qbk_name += "_msvc.qbk";
|
||||
#else // assume GCC
|
||||
qbk_name += "_gcc.qbk";
|
||||
#endif
|
||||
|
||||
// Example: type_info_table_100_msvc.qbk
|
||||
fout.open(qbk_name, std::ios_base::out);
|
||||
|
||||
if (fout.is_open())
|
||||
{
|
||||
std::cout << "Output type table to " << qbk_name << std::endl;
|
||||
}
|
||||
else
|
||||
{ // Failed to open.
|
||||
std::cout << " Open file " << qbk_name << " for output failed!" << std::endl;
|
||||
std::cout << "errno " << errno << std::endl;
|
||||
return errno;
|
||||
}
|
||||
|
||||
fout <<
|
||||
"[/"
|
||||
<< qbk_name
|
||||
<< "\n"
|
||||
"Copyright 2015 Paul A. Bristow.""\n"
|
||||
"Copyright 2015 John Maddock.""\n"
|
||||
"Distributed under the Boost Software License, Version 1.0.""\n"
|
||||
"(See accompanying file LICENSE_1_0.txt or copy at""\n"
|
||||
"http://www.boost.org/LICENSE_1_0.txt).""\n"
|
||||
"]""\n"
|
||||
<< std::endl;
|
||||
|
||||
fout << "[h6 Fraction of maximum possible bits of accuracy required is " << digits_accuracy << ".]\n" << std::endl;
|
||||
|
||||
std::string table_id("type_info");
|
||||
table_id += ss.str(); // Fraction digits accuracy.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
table_id += "_msvc";
|
||||
#else // assume GCC
|
||||
table_id += "_gcc";
|
||||
#endif
|
||||
|
||||
fout << "[table:" << table_id << " Digits for float, double, long double and cpp_bin_float_50\n"
|
||||
<< "[[type name] [max_digits10] [binary digits] [required digits]]\n";// header.
|
||||
|
||||
// For all fout types:
|
||||
|
||||
fout << "[[" << "float" << "]"
|
||||
<< "[" << std::numeric_limits<float>::max_digits10 << "]" // max_digits10
|
||||
<< "[" << std::numeric_limits<float>::digits << "]"// < "Binary digits
|
||||
<< "[" << static_cast<int>(std::numeric_limits<float>::digits * digits_accuracy) << "]]\n"; // Accuracy digits.
|
||||
|
||||
fout << "[[" << "float" << "]"
|
||||
<< "[" << std::numeric_limits<double>::max_digits10 << "]" // max_digits10
|
||||
<< "[" << std::numeric_limits<double>::digits << "]"// < "Binary digits
|
||||
<< "[" << static_cast<int>(std::numeric_limits<double>::digits * digits_accuracy) << "]]\n"; // Accuracy digits.
|
||||
|
||||
fout << "[[" << "long double" << "]"
|
||||
<< "[" << std::numeric_limits<long double>::max_digits10 << "]" // max_digits10
|
||||
<< "[" << std::numeric_limits<long double>::digits << "]"// < "Binary digits
|
||||
<< "[" << static_cast<int>(std::numeric_limits<long double>::digits * digits_accuracy) << "]]\n"; // Accuracy digits.
|
||||
|
||||
fout << "[[" << "cpp_bin_float_50" << "]"
|
||||
<< "[" << std::numeric_limits<cpp_bin_float_50>::max_digits10 << "]" // max_digits10
|
||||
<< "[" << std::numeric_limits<cpp_bin_float_50>::digits << "]"// < "Binary digits
|
||||
<< "[" << static_cast<int>(std::numeric_limits<cpp_bin_float_50>::digits * digits_accuracy) << "]]\n"; // Accuracy digits.
|
||||
|
||||
fout << "] [/table table_id_msvc] \n" << std::endl; // End of table.
|
||||
|
||||
fout.close();
|
||||
return 0;
|
||||
} // type_table
|
||||
|
||||
//! Evaluate root N timing for each algorithm, and for one floating-point type T.
|
||||
template <int N, typename T>
|
||||
int test_root(cpp_bin_float_100 big_value, cpp_bin_float_100 answer, const char* type_name, std::size_t type_no)
|
||||
{
|
||||
std::size_t max_digits = 2 + std::numeric_limits<T>::digits * 3010 / 10000;
|
||||
// For new versions use max_digits10
|
||||
// std::cout.precision(std::numeric_limits<T>::max_digits10);
|
||||
std::cout.precision(max_digits);
|
||||
std::cout << std::showpoint << std::endl; // Show trailing zeros too.
|
||||
|
||||
root_infos.push_back(root_info());
|
||||
|
||||
root_infos[type_no].max_digits10 = max_digits;
|
||||
root_infos[type_no].full_typename = typeid(T).name(); // Full typename.
|
||||
root_infos[type_no].short_typename = type_name; // Short typename.
|
||||
root_infos[type_no].bin_digits = std::numeric_limits<T>::digits;
|
||||
root_infos[type_no].get_digits = static_cast<int>(std::numeric_limits<T>::digits * digits_accuracy);
|
||||
|
||||
T to_root = static_cast<T>(big_value);
|
||||
|
||||
T result; // root
|
||||
T ans = static_cast<T>(answer);
|
||||
|
||||
using boost::timer::nanosecond_type;
|
||||
using boost::timer::cpu_times;
|
||||
using boost::timer::cpu_timer;
|
||||
|
||||
int eval_count = 1000000; // To give a sufficiently stable timing for the fast built-in types,
|
||||
//int eval_count = 1000000; // To give a sufficiently stable timing for the fast built-in types,
|
||||
// This takes an inconveniently long time for multiprecision cpp_bin_float_50 etc types.
|
||||
|
||||
cpu_times now; // Holds wall, user and system times.
|
||||
|
||||
{ // Evaluate times etc for each algorithm.
|
||||
//algorithm_names.push_back("TOMS748"); //
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < eval_count; ++i)
|
||||
{
|
||||
result = nth_root_noderiv<N, T>(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
int time = static_cast<int>(now.user / eval_count);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
// algorithm_names.push_back("Newton"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < eval_count; ++i)
|
||||
{
|
||||
result = nth_root_1deriv<N, T>(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
int time = static_cast<int>(now.user / eval_count);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
//algorithm_names.push_back("Halley"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < eval_count; ++i)
|
||||
{
|
||||
result = nth_root_2deriv<N>(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
int time = static_cast<int>(now.user / eval_count);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
ti.stop();
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
{
|
||||
// algorithm_names.push_back("Schroeder"); // algorithm
|
||||
cpu_timer ti; // Can start, pause, resume and stop, and read elapsed.
|
||||
ti.start();
|
||||
for (long i = 0; i < eval_count; ++i)
|
||||
{
|
||||
result = nth_root_2deriv_s<N>(to_root); //
|
||||
}
|
||||
now = ti.elapsed();
|
||||
int time = static_cast<int>(now.user / eval_count);
|
||||
root_infos[type_no].times.push_back(time); // CPU time taken.
|
||||
if (time < root_infos[type_no].min_time)
|
||||
{
|
||||
root_infos[type_no].min_time = time;
|
||||
}
|
||||
ti.stop();
|
||||
long int distance = static_cast<int>(boost::math::float_distance<T>(result, ans));
|
||||
root_infos[type_no].distances.push_back(distance);
|
||||
root_infos[type_no].iterations.push_back(iters); //
|
||||
root_infos[type_no].full_results.push_back(result);
|
||||
}
|
||||
for (size_t i = 0; i != root_infos[type_no].times.size(); i++) // For each time.
|
||||
{ // Normalize times.
|
||||
root_infos[type_no].normed_times.push_back(static_cast<double>(root_infos[type_no].times[i]) / root_infos[type_no].min_time);
|
||||
}
|
||||
|
||||
return 4; // eval_count of how many algorithms used.
|
||||
} // test_root
|
||||
|
||||
/*! Fill array of times, interations, etc for Nth root for all 4 types,
|
||||
and write a table of results in Quickbook format.
|
||||
*/
|
||||
template <int N>
|
||||
void table_root_info(cpp_bin_float_100 full_value)
|
||||
{
|
||||
|
||||
std::cout << nooftypes << " floating-point types tested:" << std::endl;
|
||||
#ifdef _DEBUG
|
||||
#if (_DEBUG == 0)
|
||||
std::cout << "Compiled in debug mode." << std::endl;
|
||||
#else
|
||||
std::cout << "Compiled in optimise mode." << std::endl;
|
||||
#endif
|
||||
#endif
|
||||
std::cout << "FP hardware " << fp_hardware << std::endl;
|
||||
// Compute the 'right' answer for root N at 100 decimal digits.
|
||||
cpp_bin_float_100 full_answer = nth_root_noderiv<N, cpp_bin_float_100>(full_value);
|
||||
|
||||
int type_count = 0;
|
||||
root_infos.clear(); // Erase any previous data.
|
||||
// Fill the elements of the array for each floating-point type.
|
||||
|
||||
type_count = test_root<N, float>(full_value, full_answer, "float", 0);
|
||||
type_count = test_root<N, double>(full_value, full_answer, "double", 1);
|
||||
type_count = test_root<N, long double>(full_value, full_answer, "long double", 2);
|
||||
type_count = test_root<N, cpp_bin_float_50>(full_value, full_answer, "cpp_bin_float_50", 3);
|
||||
|
||||
// Use info from 4 floating point types to
|
||||
|
||||
// Prepare Quickbook table for a single root
|
||||
// with columns of times, iterations, distances repeated for various floating-point types,
|
||||
// and 4 rows for each algorithm.
|
||||
|
||||
std::stringstream table_info;
|
||||
table_info.precision(3);
|
||||
table_info << "[table:root_" << N << " " << N << "th root(" << static_cast<float>(full_value) << ") for float, double, long double and cpp_bin_float_50 types";
|
||||
if (fp_hardware != "")
|
||||
{
|
||||
table_info << ", using " << fp_hardware;
|
||||
}
|
||||
table_info << std::endl;
|
||||
|
||||
fout << table_info.str()
|
||||
<< "[[][float][][][] [][double][][][] [][long d][][][] [][cpp50][][]]\n"
|
||||
<< "[[Algo ]";
|
||||
for (size_t tp = 0; tp != nooftypes; tp++)
|
||||
{ // For all types:
|
||||
fout << "[Its]" << "[Times]" << "[Norm]" << "[Dis]" << "[ ]";
|
||||
}
|
||||
fout << "]" << std::endl;
|
||||
|
||||
// Row for all algorithms.
|
||||
for (std::size_t algo = 0; algo != noofalgos; algo++)
|
||||
{
|
||||
fout << "[[" << std::left << std::setw(9) << algo_names[algo] << "]";
|
||||
for (size_t tp = 0; tp != nooftypes; tp++)
|
||||
{ // For all types:
|
||||
fout
|
||||
<< "[" << std::right << std::showpoint
|
||||
<< std::setw(3) << std::setprecision(2) << root_infos[tp].iterations[algo] << "]["
|
||||
<< std::setw(5) << std::setprecision(5) << root_infos[tp].times[algo] << "][";
|
||||
fout << std::setw(3) << std::setprecision(3);
|
||||
double normed_time = root_infos[tp].normed_times[algo];
|
||||
if (abs(normed_time - 1.00) <= 0.05)
|
||||
{ // At or near the best time, so show as blue.
|
||||
fout << "[role blue " << normed_time << "]";
|
||||
}
|
||||
else if (abs(normed_time) > 4.)
|
||||
{ // markedly poor so show as red.
|
||||
fout << "[role red " << normed_time << "]";
|
||||
}
|
||||
else
|
||||
{ // Not the best, so normal black.
|
||||
fout << normed_time;
|
||||
}
|
||||
fout << "]["
|
||||
<< std::setw(3) << std::setprecision(2) << root_infos[tp].distances[algo] << "][ ]";
|
||||
} // tp
|
||||
fout << "]" << std::endl;
|
||||
} // for algo
|
||||
fout << "] [/end of table root]\n";
|
||||
} // void table_root_info
|
||||
|
||||
/*! Output program header, table of type info, and tables for 4 algorithms and 4 floating-point types,
|
||||
for Nth root required digits_accuracy.
|
||||
*/
|
||||
|
||||
int roots_tables(cpp_bin_float_100 full_value, double digits_accuracy)
|
||||
{
|
||||
::digits_accuracy = digits_accuracy;
|
||||
// Save globally so that it is available to root-finding algorithms. Ugly :-(
|
||||
|
||||
#ifdef _DEBUG
|
||||
# if (_DEBUG == 0)
|
||||
std::string debug_or_optimize("Compiled in debug mode.");
|
||||
# elif (_DEBUG == 1)
|
||||
std::string debug_or_optimize("Compiled in optimise mode.");
|
||||
# endif
|
||||
#else
|
||||
# error _DEBUG is not defined in program run. Add _DEBUG=1 to preprocessor defines for GCC?
|
||||
#endif
|
||||
|
||||
// Create filename for roots_table
|
||||
std::string qbk_name = full_roots_name;
|
||||
qbk_name += "roots_table";
|
||||
|
||||
std::stringstream ss;
|
||||
ss.precision(3);
|
||||
// ss << "_" << N // now put all the tables in one .qbk file?
|
||||
ss << "_" << digits_accuracy * 100
|
||||
<< std::flush;
|
||||
// Assume only save optimize mode runs, so don't add any _DEBUG info.
|
||||
qbk_name += ss.str();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
qbk_name += "_msvc";
|
||||
#else // assume GCC
|
||||
qbk_name += "_gcc";
|
||||
#endif
|
||||
if (fp_hardware != "")
|
||||
{
|
||||
qbk_name += fp_hardware;
|
||||
}
|
||||
qbk_name += ".qbk";
|
||||
|
||||
fout.open(qbk_name, std::ios_base::out);
|
||||
|
||||
if (fout.is_open())
|
||||
{
|
||||
std::cout << "Output root table to " << qbk_name << std::endl;
|
||||
}
|
||||
else
|
||||
{ // Failed to open.
|
||||
std::cout << " Open file " << qbk_name << " for output failed!" << std::endl;
|
||||
std::cout << "errno " << errno << std::endl;
|
||||
return errno;
|
||||
}
|
||||
|
||||
fout <<
|
||||
"[/"
|
||||
<< qbk_name
|
||||
<< "\n"
|
||||
"Copyright 2015 Paul A. Bristow.""\n"
|
||||
"Copyright 2015 John Maddock.""\n"
|
||||
"Distributed under the Boost Software License, Version 1.0.""\n"
|
||||
"(See accompanying file LICENSE_1_0.txt or copy at""\n"
|
||||
"http://www.boost.org/LICENSE_1_0.txt).""\n"
|
||||
"]""\n"
|
||||
<< std::endl;
|
||||
|
||||
// Print out the program/compiler/stdlib/platform names as a Quickbook comment:
|
||||
fout << "\n[h6 Program " << sourcefilename << ",\n "
|
||||
<< BOOST_COMPILER << ", "
|
||||
<< BOOST_STDLIB << ", "
|
||||
<< BOOST_PLATFORM << "\n"
|
||||
<< debug_or_optimize
|
||||
<< ((fp_hardware != "") ? ", " + fp_hardware : "")
|
||||
<< "]" // [h6 close].
|
||||
<< std::endl;
|
||||
|
||||
fout << "Fraction of full accuracy " << digits_accuracy << std::endl;
|
||||
|
||||
table_root_info<5>(full_value);
|
||||
table_root_info<7>(full_value);
|
||||
table_root_info<11>(full_value);
|
||||
|
||||
fout.close();
|
||||
|
||||
// table_type_info(digits_accuracy);
|
||||
|
||||
return 0;
|
||||
} // roots_tables
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
using namespace boost::math;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
std::cout << "Tests run with " << BOOST_COMPILER << ", "
|
||||
<< BOOST_STDLIB << ", " << BOOST_PLATFORM << ", ";
|
||||
|
||||
// How to: Configure Visual C++ Projects to Target 64-Bit Platforms
|
||||
// https://msdn.microsoft.com/en-us/library/9yb4317s.aspx
|
||||
|
||||
#ifdef _M_X64 // Defined for compilations that target x64 processors.
|
||||
std::cout << "X64 " << std::endl;
|
||||
fp_hardware += "_X64";
|
||||
#else
|
||||
# ifdef _M_IX86
|
||||
std::cout << "X32 " << std::endl;
|
||||
fp_hardware += "_X86";
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _M_AMD64
|
||||
std::cout << "AMD64 " << std::endl;
|
||||
// fp_hardware += "_AMD64";
|
||||
#endif
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/7t5yh4fd.aspx
|
||||
// /arch (x86) options /arch:[IA32|SSE|SSE2|AVX|AVX2]
|
||||
// default is to use SSE and SSE2 instructions by default.
|
||||
// https://msdn.microsoft.com/en-us/library/jj620901.aspx
|
||||
// /arch (x64) options /arch:AVX and /arch:AVX2
|
||||
|
||||
// MSVC doesn't bother to set these SSE macros!
|
||||
// http://stackoverflow.com/questions/18563978/sse-sse2-is-enabled-control-in-visual-studio
|
||||
// https://msdn.microsoft.com/en-us/library/b0084kay.aspx predefined macros.
|
||||
|
||||
// But some of these macros are *not* defined by MSVC,
|
||||
// unlike AVX (but *are* defined by GCC and Clang).
|
||||
// So the macro code above does define them.
|
||||
#if (defined(_M_AMD64) || defined (_M_X64))
|
||||
# define _M_X64
|
||||
# define __SSE2__
|
||||
#else
|
||||
# ifdef _M_IX86_FP // Expands to an integer literal value indicating which /arch compiler option was used:
|
||||
std::cout << "Floating-point _M_IX86_FP = " << _M_IX86_FP << std::endl;
|
||||
# if (_M_IX86_FP == 2) // 2 if /arch:SSE2, /arch:AVX or /arch:AVX2
|
||||
# define __SSE2__ // x32
|
||||
# elif (_M_IX86_FP == 1) // 1 if /arch:SSE was used.
|
||||
# define __SSE__ // x32
|
||||
# elif (_M_IX86_FP == 0) // 0 if /arch:IA32 was used.
|
||||
# define _X32 // No special FP instructions.
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
// Set the fp_hardware that is used in the .qbk filename.
|
||||
#ifdef __AVX2__
|
||||
std::cout << "Floating-point AVX2 " << std::endl;
|
||||
fp_hardware += "_AVX2";
|
||||
# else
|
||||
# ifdef __AVX__
|
||||
std::cout << "Floating-point AVX " << std::endl;
|
||||
fp_hardware += "_AVX";
|
||||
# else
|
||||
# ifdef __SSE2__
|
||||
std::cout << "Floating-point SSE2 " << std::endl;
|
||||
fp_hardware += "_SSE2 ";
|
||||
# else
|
||||
# ifdef __SSE__
|
||||
std::cout << "Floating-point SSE " << std::endl;
|
||||
fp_hardware += "_SSE";
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
std::cout << "Floating-point X86 _M_IX86 = " << _M_IX86 << std::endl;
|
||||
// https://msdn.microsoft.com/en-us/library/aa273918%28v=vs.60%29.aspx#_predir_table_1..3
|
||||
// 600 = Pentium Pro
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_FULL_VER
|
||||
std::cout << "Floating-point _MSC_FULL_VER " << _MSC_FULL_VER << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef __MSVC_RUNTIME_CHECKS
|
||||
std::cout << "Runtime __MSVC_RUNTIME_CHECKS " << std::endl;
|
||||
#endif
|
||||
|
||||
BOOST_MATH_CONTROL_FP;
|
||||
|
||||
cpp_bin_float_100 full_value("28.");
|
||||
// Compute full answer to more than precision of tests.
|
||||
//T value = 28.; // integer (exactly representable as floating-point)
|
||||
// whose cube root is *not* exactly representable.
|
||||
// Wolfram Alpha command N[28 ^ (1 / 3), 100] computes cube root to 100 decimal digits.
|
||||
// 3.036588971875662519420809578505669635581453977248111123242141654169177268411884961770250390838097895
|
||||
|
||||
std::cout.precision(100);
|
||||
std::cout << "value " << full_value << std::endl;
|
||||
// std::cout << ",\n""answer = " << full_answer << std::endl;
|
||||
std::cout.precision(6);
|
||||
// cbrt cpp_bin_float_100 full_answer("3.036588971875662519420809578505669635581453977248111123242141654169177268411884961770250390838097895");
|
||||
|
||||
// Output the table of types, maxdigits10 and digits and required digits for some accuracies.
|
||||
|
||||
// Output tables for some roots at full accuracy.
|
||||
roots_tables(full_value, 1.);
|
||||
|
||||
// Output tables for some roots at less accuracy.
|
||||
roots_tables(full_value, 0.75);
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
catch (std::exception ex)
|
||||
{
|
||||
std::cout << "exception thrown: " << ex.what() << std::endl;
|
||||
return boost::exit_failure;
|
||||
}
|
||||
} // int main()
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
29
example/table_type.hpp
Normal file
29
example/table_type.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright John Maddock 2012.
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_TEST_TABLE_TYPE_HPP
|
||||
#define BOOST_MATH_TEST_TABLE_TYPE_HPP
|
||||
|
||||
template <class T>
|
||||
struct table_type
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
namespace boost{ namespace math{ namespace concepts{
|
||||
|
||||
class real_concept;
|
||||
|
||||
}}}
|
||||
|
||||
template <>
|
||||
struct table_type<boost::math::concepts::real_concept>
|
||||
{
|
||||
typedef long double type;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp>
|
||||
|
||||
/*`To define a 50 decimal digit type using `cpp_dec_float`,
|
||||
/*`To define a 50 decimal digit type using `cpp_dec_float`,
|
||||
you must pass two template parameters to `boost::multiprecision::number`.
|
||||
|
||||
It may be more legible to use a two-staged type definition such as this:
|
||||
@@ -38,7 +38,7 @@ Here, we first define `mp_backend` as `cpp_dec_float` with 50 digits.
|
||||
The second step passes this backend to `boost::multiprecision::number`
|
||||
with `boost::multiprecision::et_off`, an enumerated type.
|
||||
|
||||
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off>
|
||||
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off>
|
||||
cpp_dec_float_50_noet;
|
||||
|
||||
You can reduce typing with a `using` directive `using namespace boost::multiprecision;`
|
||||
@@ -46,19 +46,21 @@ if desired, as shown below.
|
||||
*/
|
||||
|
||||
using namespace boost::multiprecision;
|
||||
|
||||
typedef number<cpp_dec_float<50>, et_off> cpp_dec_float_50_noet;
|
||||
|
||||
//`Now `cpp_dec_float_50_noet` can be used as a direct replacement for built-in types like `double` etc.
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
|
||||
{
|
||||
/*`Now `cpp_dec_float_50_noet` or `cpp_dec_float_50_et`
|
||||
can be used as a direct replacement for built-in types like `double` etc.
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_noet)
|
||||
{ // No expression templates/
|
||||
typedef number<cpp_dec_float<50>, et_off> cpp_dec_float_50_noet;
|
||||
|
||||
std::cout.precision(std::numeric_limits<cpp_dec_float_50_noet>::digits10); // All significant digits.
|
||||
std::cout << std::showpoint << std::endl; // Show trailing zeros.
|
||||
|
||||
cpp_dec_float_50_noet a ("1.");
|
||||
cpp_dec_float_50_noet b ("1.");
|
||||
cpp_dec_float_50_noet a ("1.0");
|
||||
cpp_dec_float_50_noet b ("1.0");
|
||||
b += std::numeric_limits<cpp_dec_float_50_noet>::epsilon(); // Increment least significant decimal digit.
|
||||
|
||||
cpp_dec_float_50_noet eps = std::numeric_limits<cpp_dec_float_50_noet>::epsilon();
|
||||
@@ -68,12 +70,33 @@ BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
|
||||
BOOST_CHECK_CLOSE(a, b, eps * 100); // Expected to pass (because tolerance is as percent).
|
||||
BOOST_CHECK_CLOSE_FRACTION(a, b, eps); // Expected to pass (because tolerance is as fraction).
|
||||
|
||||
/*`Using `cpp_dec_float_50` with the default expression template use switched on,
|
||||
|
||||
|
||||
} // BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_et)
|
||||
{ // Using expression templates.
|
||||
typedef number<cpp_dec_float<50>, et_on> cpp_dec_float_50_et;
|
||||
|
||||
std::cout.precision(std::numeric_limits<cpp_dec_float_50_et>::digits10); // All significant digits.
|
||||
std::cout << std::showpoint << std::endl; // Show trailing zeros.
|
||||
|
||||
cpp_dec_float_50_et a("1.0");
|
||||
cpp_dec_float_50_et b("1.0");
|
||||
b += std::numeric_limits<cpp_dec_float_50_et>::epsilon(); // Increment least significant decimal digit.
|
||||
|
||||
cpp_dec_float_50_et eps = std::numeric_limits<cpp_dec_float_50_et>::epsilon();
|
||||
|
||||
std::cout << "a = " << a << ",\nb = " << b << ",\neps = " << eps << std::endl;
|
||||
|
||||
BOOST_CHECK_CLOSE(a, b, eps * 100); // Expected to pass (because tolerance is as percent).
|
||||
BOOST_CHECK_CLOSE_FRACTION(a, b, eps); // Expected to pass (because tolerance is as fraction).
|
||||
|
||||
/*`Using `cpp_dec_float_50` with the default expression template use switched on,
|
||||
the compiler error message for `BOOST_CHECK_CLOSE_FRACTION(a, b, eps); would be:
|
||||
*/
|
||||
*/
|
||||
// failure floating_point_comparison.hpp(59): error C2440: 'static_cast' :
|
||||
// cannot convert from 'int' to 'boost::multiprecision::detail::expression<tag,Arg1,Arg2,Arg3,Arg4>'
|
||||
|
||||
//] [/expression_template_1]
|
||||
|
||||
} // BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
|
||||
@@ -84,11 +107,11 @@ Output:
|
||||
|
||||
Description: Autorun "J:\Cpp\big_number\Debug\test_cpp_float_close_fraction.exe"
|
||||
Running 1 test case...
|
||||
|
||||
|
||||
a = 1.0000000000000000000000000000000000000000000000000,
|
||||
b = 1.0000000000000000000000000000000000000000000000001,
|
||||
eps = 1.0000000000000000000000000000000000000000000000000e-49
|
||||
|
||||
|
||||
*** No errors detected
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <pch_light.hpp> // include /libs/math/src/
|
||||
#include "test_cbrt.hpp"
|
||||
|
||||
#include <boost/math/special_functions/cbrt.hpp> // Added to avoid link failure missing cbrt variants.
|
||||
// Assumes special functions library built rather than included?
|
||||
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// ~~~~~~~~~~~~
|
||||
|
||||
Reference in New Issue
Block a user