diff options
Diffstat (limited to 'src/boost/libs/math/example')
203 files changed, 37864 insertions, 0 deletions
diff --git a/src/boost/libs/math/example/CMakeLists.txt b/src/boost/libs/math/example/CMakeLists.txt new file mode 100644 index 000000000..cb38cc955 --- /dev/null +++ b/src/boost/libs/math/example/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2021 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +file(GLOB SOURCES "*.cpp") +add_library(examples ${SOURCES}) +target_compile_features(examples PRIVATE cxx_std_17) +target_include_directories(compile_tests PUBLIC ${CMAKE_SOURCE_DIR}/include) diff --git a/src/boost/libs/math/example/HSO3.hpp b/src/boost/libs/math/example/HSO3.hpp new file mode 100644 index 000000000..4e4ead7ab --- /dev/null +++ b/src/boost/libs/math/example/HSO3.hpp @@ -0,0 +1,509 @@ + +/********************************************************************************************/ +/* */ +/* HSO3.hpp header file */ +/* */ +/* This file is not currently part of the Boost library. It is simply an example of the use */ +/* quaternions can be put to. Hopefully it will be useful too. */ +/* */ +/* This file provides tools to convert between quaternions and R^3 rotation matrices. */ +/* */ +/********************************************************************************************/ + +// (C) Copyright Hubert Holin 2001. +// 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) + +#ifndef TEST_HSO3_HPP +#define TEST_HSO3_HPP + +#include <algorithm> + +#if defined(__GNUC__) && (__GNUC__ < 3) +#include <boost/limits.hpp> +#else +#include <limits> +#endif + +#include <stdexcept> +#include <string> + +#include <boost/math/quaternion.hpp> + + +#if defined(__GNUC__) && (__GNUC__ < 3) +// gcc 2.x ignores function scope using declarations, put them here instead: +using namespace ::std; +using namespace ::boost::math; +#endif + +template<typename TYPE_FLOAT> +struct R3_matrix +{ + TYPE_FLOAT a11, a12, a13; + TYPE_FLOAT a21, a22, a23; + TYPE_FLOAT a31, a32, a33; +}; + + +// Note: the input quaternion need not be of norm 1 for the following function + +template<typename TYPE_FLOAT> +R3_matrix<TYPE_FLOAT> quaternion_to_R3_rotation(::boost::math::quaternion<TYPE_FLOAT> const & q) +{ + using ::std::numeric_limits; + + TYPE_FLOAT a = q.R_component_1(); + TYPE_FLOAT b = q.R_component_2(); + TYPE_FLOAT c = q.R_component_3(); + TYPE_FLOAT d = q.R_component_4(); + + TYPE_FLOAT aa = a*a; + TYPE_FLOAT ab = a*b; + TYPE_FLOAT ac = a*c; + TYPE_FLOAT ad = a*d; + TYPE_FLOAT bb = b*b; + TYPE_FLOAT bc = b*c; + TYPE_FLOAT bd = b*d; + TYPE_FLOAT cc = c*c; + TYPE_FLOAT cd = c*d; + TYPE_FLOAT dd = d*d; + + TYPE_FLOAT norme_carre = aa+bb+cc+dd; + + if (norme_carre <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Argument to quaternion_to_R3_rotation is too small!"); + ::std::underflow_error bad_argument(error_reporting); + + throw(bad_argument); + } + + R3_matrix<TYPE_FLOAT> out_matrix; + + out_matrix.a11 = (aa+bb-cc-dd)/norme_carre; + out_matrix.a12 = 2*(-ad+bc)/norme_carre; + out_matrix.a13 = 2*(ac+bd)/norme_carre; + out_matrix.a21 = 2*(ad+bc)/norme_carre; + out_matrix.a22 = (aa-bb+cc-dd)/norme_carre; + out_matrix.a23 = 2*(-ab+cd)/norme_carre; + out_matrix.a31 = 2*(-ac+bd)/norme_carre; + out_matrix.a32 = 2*(ab+cd)/norme_carre; + out_matrix.a33 = (aa-bb-cc+dd)/norme_carre; + + return(out_matrix); +} + + + template<typename TYPE_FLOAT> + void find_invariant_vector( R3_matrix<TYPE_FLOAT> const & rot, + TYPE_FLOAT & x, + TYPE_FLOAT & y, + TYPE_FLOAT & z) + { + using ::std::sqrt; + + using ::std::numeric_limits; + + TYPE_FLOAT b11 = rot.a11 - static_cast<TYPE_FLOAT>(1); + TYPE_FLOAT b12 = rot.a12; + TYPE_FLOAT b13 = rot.a13; + TYPE_FLOAT b21 = rot.a21; + TYPE_FLOAT b22 = rot.a22 - static_cast<TYPE_FLOAT>(1); + TYPE_FLOAT b23 = rot.a23; + TYPE_FLOAT b31 = rot.a31; + TYPE_FLOAT b32 = rot.a32; + TYPE_FLOAT b33 = rot.a33 - static_cast<TYPE_FLOAT>(1); + + TYPE_FLOAT minors[9] = + { + b11*b22-b12*b21, + b11*b23-b13*b21, + b12*b23-b13*b22, + b11*b32-b12*b31, + b11*b33-b13*b31, + b12*b33-b13*b32, + b21*b32-b22*b31, + b21*b33-b23*b31, + b22*b33-b23*b32 + }; + + TYPE_FLOAT * where = ::std::max_element(minors, minors+9); + + TYPE_FLOAT det = *where; + + if (det <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Underflow error in find_invariant_vector!"); + ::std::underflow_error processing_error(error_reporting); + + throw(processing_error); + } + + switch (where-minors) + { + case 0: + + z = static_cast<TYPE_FLOAT>(1); + + x = (-b13*b22+b12*b23)/det; + y = (-b11*b23+b13*b21)/det; + + break; + + case 1: + + y = static_cast<TYPE_FLOAT>(1); + + x = (-b12*b23+b13*b22)/det; + z = (-b11*b22+b12*b21)/det; + + break; + + case 2: + + x = static_cast<TYPE_FLOAT>(1); + + y = (-b11*b23+b13*b21)/det; + z = (-b12*b21+b11*b22)/det; + + break; + + case 3: + + z = static_cast<TYPE_FLOAT>(1); + + x = (-b13*b32+b12*b33)/det; + y = (-b11*b33+b13*b31)/det; + + break; + + case 4: + + y = static_cast<TYPE_FLOAT>(1); + + x = (-b12*b33+b13*b32)/det; + z = (-b11*b32+b12*b31)/det; + + break; + + case 5: + + x = static_cast<TYPE_FLOAT>(1); + + y = (-b11*b33+b13*b31)/det; + z = (-b12*b31+b11*b32)/det; + + break; + + case 6: + + z = static_cast<TYPE_FLOAT>(1); + + x = (-b23*b32+b22*b33)/det; + y = (-b21*b33+b23*b31)/det; + + break; + + case 7: + + y = static_cast<TYPE_FLOAT>(1); + + x = (-b22*b33+b23*b32)/det; + z = (-b21*b32+b22*b31)/det; + + break; + + case 8: + + x = static_cast<TYPE_FLOAT>(1); + + y = (-b21*b33+b23*b31)/det; + z = (-b22*b31+b21*b32)/det; + + break; + + default: + + ::std::string error_reporting("Impossible condition in find_invariant_vector"); + ::std::logic_error processing_error(error_reporting); + + throw(processing_error); + + break; + } + + TYPE_FLOAT vecnorm = sqrt(x*x+y*y+z*z); + + if (vecnorm <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Overflow error in find_invariant_vector!"); + ::std::overflow_error processing_error(error_reporting); + + throw(processing_error); + } + + x /= vecnorm; + y /= vecnorm; + z /= vecnorm; + } + + + template<typename TYPE_FLOAT> + void find_orthogonal_vector( TYPE_FLOAT x, + TYPE_FLOAT y, + TYPE_FLOAT z, + TYPE_FLOAT & u, + TYPE_FLOAT & v, + TYPE_FLOAT & w) + { + using ::std::abs; + using ::std::sqrt; + + using ::std::numeric_limits; + + TYPE_FLOAT vecnormsqr = x*x+y*y+z*z; + + if (vecnormsqr <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Underflow error in find_orthogonal_vector!"); + ::std::underflow_error processing_error(error_reporting); + + throw(processing_error); + } + + TYPE_FLOAT lambda; + + TYPE_FLOAT components[3] = + { + abs(x), + abs(y), + abs(z) + }; + + TYPE_FLOAT * where = ::std::min_element(components, components+3); + + switch (where-components) + { + case 0: + + if (*where <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + v = + w = static_cast<TYPE_FLOAT>(0); + u = static_cast<TYPE_FLOAT>(1); + } + else + { + lambda = -x/vecnormsqr; + + u = static_cast<TYPE_FLOAT>(1) + lambda*x; + v = lambda*y; + w = lambda*z; + } + + break; + + case 1: + + if (*where <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + u = + w = static_cast<TYPE_FLOAT>(0); + v = static_cast<TYPE_FLOAT>(1); + } + else + { + lambda = -y/vecnormsqr; + + u = lambda*x; + v = static_cast<TYPE_FLOAT>(1) + lambda*y; + w = lambda*z; + } + + break; + + case 2: + + if (*where <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + u = + v = static_cast<TYPE_FLOAT>(0); + w = static_cast<TYPE_FLOAT>(1); + } + else + { + lambda = -z/vecnormsqr; + + u = lambda*x; + v = lambda*y; + w = static_cast<TYPE_FLOAT>(1) + lambda*z; + } + + break; + + default: + + ::std::string error_reporting("Impossible condition in find_invariant_vector"); + ::std::logic_error processing_error(error_reporting); + + throw(processing_error); + + break; + } + + TYPE_FLOAT vecnorm = sqrt(u*u+v*v+w*w); + + if (vecnorm <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Underflow error in find_orthogonal_vector!"); + ::std::underflow_error processing_error(error_reporting); + + throw(processing_error); + } + + u /= vecnorm; + v /= vecnorm; + w /= vecnorm; + } + + + // Note: we want [[v, v, w], [r, s, t], [x, y, z]] to be a direct orthogonal basis + // of R^3. It might not be orthonormal, however, and we do not check if the + // two input vectors are colinear or not. + + template<typename TYPE_FLOAT> + void find_vector_for_BOD(TYPE_FLOAT x, + TYPE_FLOAT y, + TYPE_FLOAT z, + TYPE_FLOAT u, + TYPE_FLOAT v, + TYPE_FLOAT w, + TYPE_FLOAT & r, + TYPE_FLOAT & s, + TYPE_FLOAT & t) + { + r = +y*w-z*v; + s = -x*w+z*u; + t = +x*v-y*u; + } + + + +template<typename TYPE_FLOAT> +inline bool is_R3_rotation_matrix(R3_matrix<TYPE_FLOAT> const & mat) +{ + using ::std::abs; + + using ::std::numeric_limits; + + return ( + !( + (abs(mat.a11*mat.a11+mat.a21*mat.a21+mat.a31*mat.a31 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a12*mat.a12+mat.a22*mat.a22+mat.a32*mat.a32 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a13*mat.a13+mat.a23*mat.a23+mat.a33*mat.a33 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon()) + ) + ); +} + + +template<typename TYPE_FLOAT> +::boost::math::quaternion<TYPE_FLOAT> R3_rotation_to_quaternion( R3_matrix<TYPE_FLOAT> const & rot, + ::boost::math::quaternion<TYPE_FLOAT> const * hint = 0) +{ + using ::boost::math::abs; + + using ::std::abs; + using ::std::sqrt; + + using ::std::numeric_limits; + + if (!is_R3_rotation_matrix(rot)) + { + ::std::string error_reporting("Argument to R3_rotation_to_quaternion is not an R^3 rotation matrix!"); + ::std::range_error bad_argument(error_reporting); + + throw(bad_argument); + } + + ::boost::math::quaternion<TYPE_FLOAT> q; + + if ( + (abs(rot.a11 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon())&& + (abs(rot.a22 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon())&& + (abs(rot.a33 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon()) + ) + { + q = ::boost::math::quaternion<TYPE_FLOAT>(1); + } + else + { + TYPE_FLOAT cos_theta = (rot.a11+rot.a22+rot.a33-static_cast<TYPE_FLOAT>(1))/static_cast<TYPE_FLOAT>(2); + TYPE_FLOAT stuff = (cos_theta+static_cast<TYPE_FLOAT>(1))/static_cast<TYPE_FLOAT>(2); + TYPE_FLOAT cos_theta_sur_2 = sqrt(stuff); + TYPE_FLOAT sin_theta_sur_2 = sqrt(1-stuff); + + TYPE_FLOAT x; + TYPE_FLOAT y; + TYPE_FLOAT z; + + find_invariant_vector(rot, x, y, z); + + TYPE_FLOAT u; + TYPE_FLOAT v; + TYPE_FLOAT w; + + find_orthogonal_vector(x, y, z, u, v, w); + + TYPE_FLOAT r; + TYPE_FLOAT s; + TYPE_FLOAT t; + + find_vector_for_BOD(x, y, z, u, v, w, r, s, t); + + TYPE_FLOAT ru = rot.a11*u+rot.a12*v+rot.a13*w; + TYPE_FLOAT rv = rot.a21*u+rot.a22*v+rot.a23*w; + TYPE_FLOAT rw = rot.a31*u+rot.a32*v+rot.a33*w; + + TYPE_FLOAT angle_sign_determinator = r*ru+s*rv+t*rw; + + if (angle_sign_determinator > +numeric_limits<TYPE_FLOAT>::epsilon()) + { + q = ::boost::math::quaternion<TYPE_FLOAT>(cos_theta_sur_2, +x*sin_theta_sur_2, +y*sin_theta_sur_2, +z*sin_theta_sur_2); + } + else if (angle_sign_determinator < -numeric_limits<TYPE_FLOAT>::epsilon()) + { + q = ::boost::math::quaternion<TYPE_FLOAT>(cos_theta_sur_2, -x*sin_theta_sur_2, -y*sin_theta_sur_2, -z*sin_theta_sur_2); + } + else + { + TYPE_FLOAT desambiguator = u*ru+v*rv+w*rw; + + if (desambiguator >= static_cast<TYPE_FLOAT>(1)) + { + q = ::boost::math::quaternion<TYPE_FLOAT>(0, +x, +y, +z); + } + else + { + q = ::boost::math::quaternion<TYPE_FLOAT>(0, -x, -y, -z); + } + } + } + + if ((hint != 0) && (abs(*hint+q) < abs(*hint-q))) + { + return(-q); + } + + return(q); +} + +#endif /* TEST_HSO3_HPP */ + diff --git a/src/boost/libs/math/example/HSO3SO4.cpp b/src/boost/libs/math/example/HSO3SO4.cpp new file mode 100644 index 000000000..c4462c793 --- /dev/null +++ b/src/boost/libs/math/example/HSO3SO4.cpp @@ -0,0 +1,445 @@ +// test file for HSO3.hpp and HSO4.hpp + +// (C) Copyright Hubert Holin 2001. +// 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) + + +#include <iostream> + +#include <boost/math/quaternion.hpp> + +#include "HSO3.hpp" +#include "HSO4.hpp" + + +const int number_of_intervals = 5; + +const float pi = ::std::atan(1.0f)*4; + + + +void test_SO3(); + +void test_SO4(); + + +int main() + +{ + test_SO3(); + + test_SO4(); + + ::std::cout << "That's all folks!" << ::std::endl; +} + + +// +// Test of quaternion and R^3 rotation relationship +// + +void test_SO3_spherical() +{ + ::std::cout << "Testing spherical:" << ::std::endl; + ::std::cout << ::std::endl; + + const float rho = 1.0f; + + float theta; + float phi1; + float phi2; + + for (int idxphi2 = 0; idxphi2 <= number_of_intervals; idxphi2++) + { + phi2 = (-pi/2)+(idxphi2*pi)/number_of_intervals; + + for (int idxphi1 = 0; idxphi1 <= number_of_intervals; idxphi1++) + { + phi1 = (-pi/2)+(idxphi1*pi)/number_of_intervals; + + for (int idxtheta = 0; idxtheta <= number_of_intervals; idxtheta++) + { + theta = -pi+(idxtheta*(2*pi))/number_of_intervals; + + ::std::cout << "theta = " << theta << " ; "; + ::std::cout << "phi1 = " << phi1 << " ; "; + ::std::cout << "phi2 = " << phi2; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> q = ::boost::math::spherical(rho, theta, phi1, phi2); + + ::std::cout << "q = " << q << ::std::endl; + + R3_matrix<float> rot = quaternion_to_R3_rotation(q); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << ::std::endl; + + ::boost::math::quaternion<float> p = R3_rotation_to_quaternion(rot, &q); + + ::std::cout << "p = " << p << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::boost::math::abs(q-p) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO3_semipolar() +{ + ::std::cout << "Testing semipolar:" << ::std::endl; + ::std::cout << ::std::endl; + + const float rho = 1.0f; + + float alpha; + float theta1; + float theta2; + + for (int idxalpha = 0; idxalpha <= number_of_intervals; idxalpha++) + { + alpha = (idxalpha*(pi/2))/number_of_intervals; + + for (int idxtheta1 = 0; idxtheta1 <= number_of_intervals; idxtheta1++) + { + theta1 = -pi+(idxtheta1*(2*pi))/number_of_intervals; + + for (int idxtheta2 = 0; idxtheta2 <= number_of_intervals; idxtheta2++) + { + theta2 = -pi+(idxtheta2*(2*pi))/number_of_intervals; + + ::std::cout << "alpha = " << alpha << " ; "; + ::std::cout << "theta1 = " << theta1 << " ; "; + ::std::cout << "theta2 = " << theta2; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> q = ::boost::math::semipolar(rho, alpha, theta1, theta2); + + ::std::cout << "q = " << q << ::std::endl; + + R3_matrix<float> rot = quaternion_to_R3_rotation(q); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << ::std::endl; + + ::boost::math::quaternion<float> p = R3_rotation_to_quaternion(rot, &q); + + ::std::cout << "p = " << p << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::boost::math::abs(q-p) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO3_multipolar() +{ + ::std::cout << "Testing multipolar:" << ::std::endl; + ::std::cout << ::std::endl; + + float rho1; + float rho2; + + float theta1; + float theta2; + + for (int idxrho = 0; idxrho <= number_of_intervals; idxrho++) + { + rho1 = (idxrho*1.0f)/number_of_intervals; + rho2 = ::std::sqrt(1.0f-rho1*rho1); + + for (int idxtheta1 = 0; idxtheta1 <= number_of_intervals; idxtheta1++) + { + theta1 = -pi+(idxtheta1*(2*pi))/number_of_intervals; + + for (int idxtheta2 = 0; idxtheta2 <= number_of_intervals; idxtheta2++) + { + theta2 = -pi+(idxtheta2*(2*pi))/number_of_intervals; + + ::std::cout << "rho1 = " << rho1 << " ; "; + ::std::cout << "theta1 = " << theta1 << " ; "; + ::std::cout << "theta2 = " << theta2; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> q = ::boost::math::multipolar(rho1, theta1, rho2, theta2); + + ::std::cout << "q = " << q << ::std::endl; + + R3_matrix<float> rot = quaternion_to_R3_rotation(q); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << ::std::endl; + + ::boost::math::quaternion<float> p = R3_rotation_to_quaternion(rot, &q); + + ::std::cout << "p = " << p << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::boost::math::abs(q-p) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO3_cylindrospherical() +{ + ::std::cout << "Testing cylindrospherical:" << ::std::endl; + ::std::cout << ::std::endl; + + float t; + + float radius; + float longitude; + float latitude; + + for (int idxt = 0; idxt <= number_of_intervals; idxt++) + { + t = -1.0f+(idxt*2.0f)/number_of_intervals; + radius = ::std::sqrt(1.0f-t*t); + + for (int idxlatitude = 0; idxlatitude <= number_of_intervals; idxlatitude++) + { + latitude = (-pi/2)+(idxlatitude*pi)/number_of_intervals; + + for (int idxlongitude = 0; idxlongitude <= number_of_intervals; idxlongitude++) + { + longitude = -pi+(idxlongitude*(2*pi))/number_of_intervals; + + ::std::cout << "t = " << t << " ; "; + ::std::cout << "longitude = " << longitude; + ::std::cout << "latitude = " << latitude; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> q = ::boost::math::cylindrospherical(t, radius, longitude, latitude); + + ::std::cout << "q = " << q << ::std::endl; + + R3_matrix<float> rot = quaternion_to_R3_rotation(q); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << ::std::endl; + + ::boost::math::quaternion<float> p = R3_rotation_to_quaternion(rot, &q); + + ::std::cout << "p = " << p << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::boost::math::abs(q-p) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO3_cylindrical() +{ + ::std::cout << "Testing cylindrical:" << ::std::endl; + ::std::cout << ::std::endl; + + float r; + float angle; + + float h1; + float h2; + + for (int idxh2 = 0; idxh2 <= number_of_intervals; idxh2++) + { + h2 = -1.0f+(idxh2*2.0f)/number_of_intervals; + + for (int idxh1 = 0; idxh1 <= number_of_intervals; idxh1++) + { + h1 = ::std::sqrt(1.0f-h2*h2)*(-1.0f+(idxh2*2.0f)/number_of_intervals); + r = ::std::sqrt(1.0f-h1*h1-h2*h2); + + for (int idxangle = 0; idxangle <= number_of_intervals; idxangle++) + { + angle = -pi+(idxangle*(2*pi))/number_of_intervals; + + ::std::cout << "angle = " << angle << " ; "; + ::std::cout << "h1 = " << h1; + ::std::cout << "h2 = " << h2; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> q = ::boost::math::cylindrical(r, angle, h1, h2); + + ::std::cout << "q = " << q << ::std::endl; + + R3_matrix<float> rot = quaternion_to_R3_rotation(q); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << ::std::endl; + + ::boost::math::quaternion<float> p = R3_rotation_to_quaternion(rot, &q); + + ::std::cout << "p = " << p << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::boost::math::abs(q-p) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO3() +{ + ::std::cout << "Testing SO3:" << ::std::endl; + ::std::cout << ::std::endl; + + test_SO3_spherical(); + + test_SO3_semipolar(); + + test_SO3_multipolar(); + + test_SO3_cylindrospherical(); + + test_SO3_cylindrical(); +} + + +// +// Test of quaternion and R^4 rotation relationship +// + +void test_SO4_spherical() +{ + ::std::cout << "Testing spherical:" << ::std::endl; + ::std::cout << ::std::endl; + + const float rho1 = 1.0f; + const float rho2 = 1.0f; + + float theta1; + float phi11; + float phi21; + + float theta2; + float phi12; + float phi22; + + for (int idxphi21 = 0; idxphi21 <= number_of_intervals; idxphi21++) + { + phi21 = (-pi/2)+(idxphi21*pi)/number_of_intervals; + + for (int idxphi22 = 0; idxphi22 <= number_of_intervals; idxphi22++) + { + phi22 = (-pi/2)+(idxphi22*pi)/number_of_intervals; + + for (int idxphi11 = 0; idxphi11 <= number_of_intervals; idxphi11++) + { + phi11 = (-pi/2)+(idxphi11*pi)/number_of_intervals; + + for (int idxphi12 = 0; idxphi12 <= number_of_intervals; idxphi12++) + { + phi12 = (-pi/2)+(idxphi12*pi)/number_of_intervals; + + for (int idxtheta1 = 0; idxtheta1 <= number_of_intervals; idxtheta1++) + { + theta1 = -pi+(idxtheta1*(2*pi))/number_of_intervals; + + for (int idxtheta2 = 0; idxtheta2 <= number_of_intervals; idxtheta2++) + { + theta2 = -pi+(idxtheta2*(2*pi))/number_of_intervals; + + ::std::cout << "theta1 = " << theta1 << " ; "; + ::std::cout << "phi11 = " << phi11 << " ; "; + ::std::cout << "phi21 = " << phi21; + ::std::cout << "theta2 = " << theta2 << " ; "; + ::std::cout << "phi12 = " << phi12 << " ; "; + ::std::cout << "phi22 = " << phi22; + ::std::cout << ::std::endl; + + ::boost::math::quaternion<float> p1 = ::boost::math::spherical(rho1, theta1, phi11, phi21); + + ::std::cout << "p1 = " << p1 << ::std::endl; + + ::boost::math::quaternion<float> q1 = ::boost::math::spherical(rho2, theta2, phi12, phi22); + + ::std::cout << "q1 = " << q1 << ::std::endl; + + ::std::pair< ::boost::math::quaternion<float> , ::boost::math::quaternion<float> > pq1 = + ::std::make_pair(p1,q1); + + R4_matrix<float> rot = quaternions_to_R4_rotation(pq1); + + ::std::cout << "rot = "; + ::std::cout << "\t" << rot.a11 << "\t" << rot.a12 << "\t" << rot.a13 << "\t" << rot.a14 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a21 << "\t" << rot.a22 << "\t" << rot.a23 << "\t" << rot.a24 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a31 << "\t" << rot.a32 << "\t" << rot.a33 << "\t" << rot.a34 << ::std::endl; + ::std::cout << "\t"; + ::std::cout << "\t" << rot.a41 << "\t" << rot.a42 << "\t" << rot.a43 << "\t" << rot.a44 << ::std::endl; + + ::std::pair< ::boost::math::quaternion<float> , ::boost::math::quaternion<float> > pq2 = + R4_rotation_to_quaternions(rot, &pq1); + + ::std::cout << "p1 = " << pq2.first << ::std::endl; + ::std::cout << "p2 = " << pq2.second << ::std::endl; + + ::std::cout << "round trip discrepancy: " << ::std::sqrt(::boost::math::norm(pq1.first-pq2.first)+::boost::math::norm(pq1.second-pq2.second)) << ::std::endl; + + ::std::cout << ::std::endl; + } + } + } + } + } + } + + ::std::cout << ::std::endl; +} + + +void test_SO4() +{ + ::std::cout << "Testing SO4:" << ::std::endl; + ::std::cout << ::std::endl; + + test_SO4_spherical(); +} + + diff --git a/src/boost/libs/math/example/HSO4.hpp b/src/boost/libs/math/example/HSO4.hpp new file mode 100644 index 000000000..e7171b815 --- /dev/null +++ b/src/boost/libs/math/example/HSO4.hpp @@ -0,0 +1,183 @@ + +/********************************************************************************************/ +/* */ +/* HSO4.hpp header file */ +/* */ +/* This file is not currently part of the Boost library. It is simply an example of the use */ +/* quaternions can be put to. Hopefully it will be useful too. */ +/* */ +/* This file provides tools to convert between quaternions and R^4 rotation matrices. */ +/* */ +/********************************************************************************************/ + +// (C) Copyright Hubert Holin 2001. +// 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) + +#ifndef TEST_HSO4_HPP +#define TEST_HSO4_HPP + +#include <utility> + +#include "HSO3.hpp" + + +template<typename TYPE_FLOAT> +struct R4_matrix +{ + TYPE_FLOAT a11, a12, a13, a14; + TYPE_FLOAT a21, a22, a23, a24; + TYPE_FLOAT a31, a32, a33, a34; + TYPE_FLOAT a41, a42, a43, a44; +}; + + +// Note: the input quaternions need not be of norm 1 for the following function + +template<typename TYPE_FLOAT> +R4_matrix<TYPE_FLOAT> quaternions_to_R4_rotation(::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > const & pq) +{ + using ::std::numeric_limits; + + TYPE_FLOAT a0 = pq.first.R_component_1(); + TYPE_FLOAT b0 = pq.first.R_component_2(); + TYPE_FLOAT c0 = pq.first.R_component_3(); + TYPE_FLOAT d0 = pq.first.R_component_4(); + + TYPE_FLOAT norme_carre0 = a0*a0+b0*b0+c0*c0+d0*d0; + + if (norme_carre0 <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Argument to quaternions_to_R4_rotation is too small!"); + ::std::underflow_error bad_argument(error_reporting); + + throw(bad_argument); + } + + TYPE_FLOAT a1 = pq.second.R_component_1(); + TYPE_FLOAT b1 = pq.second.R_component_2(); + TYPE_FLOAT c1 = pq.second.R_component_3(); + TYPE_FLOAT d1 = pq.second.R_component_4(); + + TYPE_FLOAT norme_carre1 = a1*a1+b1*b1+c1*c1+d1*d1; + + if (norme_carre1 <= numeric_limits<TYPE_FLOAT>::epsilon()) + { + ::std::string error_reporting("Argument to quaternions_to_R4_rotation is too small!"); + ::std::underflow_error bad_argument(error_reporting); + + throw(bad_argument); + } + + TYPE_FLOAT prod_norm = norme_carre0*norme_carre1; + + TYPE_FLOAT a0a1 = a0*a1; + TYPE_FLOAT a0b1 = a0*b1; + TYPE_FLOAT a0c1 = a0*c1; + TYPE_FLOAT a0d1 = a0*d1; + TYPE_FLOAT b0a1 = b0*a1; + TYPE_FLOAT b0b1 = b0*b1; + TYPE_FLOAT b0c1 = b0*c1; + TYPE_FLOAT b0d1 = b0*d1; + TYPE_FLOAT c0a1 = c0*a1; + TYPE_FLOAT c0b1 = c0*b1; + TYPE_FLOAT c0c1 = c0*c1; + TYPE_FLOAT c0d1 = c0*d1; + TYPE_FLOAT d0a1 = d0*a1; + TYPE_FLOAT d0b1 = d0*b1; + TYPE_FLOAT d0c1 = d0*c1; + TYPE_FLOAT d0d1 = d0*d1; + + R4_matrix<TYPE_FLOAT> out_matrix; + + out_matrix.a11 = (+a0a1+b0b1+c0c1+d0d1)/prod_norm; + out_matrix.a12 = (+a0b1-b0a1-c0d1+d0c1)/prod_norm; + out_matrix.a13 = (+a0c1+b0d1-c0a1-d0b1)/prod_norm; + out_matrix.a14 = (+a0d1-b0c1+c0b1-d0a1)/prod_norm; + out_matrix.a21 = (-a0b1+b0a1-c0d1+d0c1)/prod_norm; + out_matrix.a22 = (+a0a1+b0b1-c0c1-d0d1)/prod_norm; + out_matrix.a23 = (-a0d1+b0c1+c0b1-d0a1)/prod_norm; + out_matrix.a24 = (+a0c1+b0d1+c0a1+d0b1)/prod_norm; + out_matrix.a31 = (-a0c1+b0d1+c0a1-d0b1)/prod_norm; + out_matrix.a32 = (+a0d1+b0c1+c0b1+d0a1)/prod_norm; + out_matrix.a33 = (+a0a1-b0b1+c0c1-d0d1)/prod_norm; + out_matrix.a34 = (-a0b1-b0a1+c0d1+d0c1)/prod_norm; + out_matrix.a41 = (-a0d1-b0c1+c0b1+d0a1)/prod_norm; + out_matrix.a42 = (-a0c1+b0d1-c0a1+d0b1)/prod_norm; + out_matrix.a43 = (+a0b1+b0a1+c0d1+d0c1)/prod_norm; + out_matrix.a44 = (+a0a1-b0b1-c0c1+d0d1)/prod_norm; + + return(out_matrix); +} + + +template<typename TYPE_FLOAT> +inline bool is_R4_rotation_matrix(R4_matrix<TYPE_FLOAT> const & mat) +{ + using ::std::abs; + + using ::std::numeric_limits; + + return ( + !( + (abs(mat.a11*mat.a11+mat.a21*mat.a21+mat.a31*mat.a31+mat.a41*mat.a41 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32+mat.a41*mat.a42 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33+mat.a41*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a11*mat.a14+mat.a21*mat.a24+mat.a31*mat.a34+mat.a41*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32+mat.a41*mat.a42 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a12*mat.a12+mat.a22*mat.a22+mat.a32*mat.a32+mat.a42*mat.a42 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33+mat.a42*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a12*mat.a14+mat.a22*mat.a24+mat.a32*mat.a34+mat.a42*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33+mat.a41*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33+mat.a42*mat.a43 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a13*mat.a13+mat.a23*mat.a23+mat.a33*mat.a33+mat.a43*mat.a43 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a13*mat.a14+mat.a23*mat.a24+mat.a33*mat.a34+mat.a43*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a11*mat.a14+mat.a21*mat.a24+mat.a31*mat.a34+mat.a41*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a12*mat.a14+mat.a22*mat.a24+mat.a32*mat.a34+mat.a42*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + //(abs(mat.a13*mat.a14+mat.a23*mat.a24+mat.a33*mat.a34+mat.a43*mat.a44 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())|| + (abs(mat.a14*mat.a14+mat.a24*mat.a24+mat.a34*mat.a34+mat.a44*mat.a44 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon()) + ) + ); +} + + +template<typename TYPE_FLOAT> +::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > R4_rotation_to_quaternions( R4_matrix<TYPE_FLOAT> const & rot, + ::std::pair< ::boost::math::quaternion<TYPE_FLOAT> , ::boost::math::quaternion<TYPE_FLOAT> > const * hint = 0) +{ + if (!is_R4_rotation_matrix(rot)) + { + ::std::string error_reporting("Argument to R4_rotation_to_quaternions is not an R^4 rotation matrix!"); + ::std::range_error bad_argument(error_reporting); + + throw(bad_argument); + } + + R3_matrix<TYPE_FLOAT> mat; + + mat.a11 = -rot.a31*rot.a42+rot.a32*rot.a41+rot.a22*rot.a11-rot.a21*rot.a12; + mat.a12 = -rot.a31*rot.a43+rot.a33*rot.a41+rot.a23*rot.a11-rot.a21*rot.a13; + mat.a13 = -rot.a31*rot.a44+rot.a34*rot.a41+rot.a24*rot.a11-rot.a21*rot.a14; + mat.a21 = -rot.a31*rot.a12-rot.a22*rot.a41+rot.a32*rot.a11+rot.a21*rot.a42; + mat.a22 = -rot.a31*rot.a13-rot.a23*rot.a41+rot.a33*rot.a11+rot.a21*rot.a43; + mat.a23 = -rot.a31*rot.a14-rot.a24*rot.a41+rot.a34*rot.a11+rot.a21*rot.a44; + mat.a31 = +rot.a31*rot.a22-rot.a12*rot.a41+rot.a42*rot.a11-rot.a21*rot.a32; + mat.a32 = +rot.a31*rot.a23-rot.a13*rot.a41+rot.a43*rot.a11-rot.a21*rot.a33; + mat.a33 = +rot.a31*rot.a24-rot.a14*rot.a41+rot.a44*rot.a11-rot.a21*rot.a34; + + ::boost::math::quaternion<TYPE_FLOAT> q = R3_rotation_to_quaternion(mat); + + ::boost::math::quaternion<TYPE_FLOAT> p = + ::boost::math::quaternion<TYPE_FLOAT>(rot.a11,rot.a12,rot.a13,rot.a14)*q; + + if ((hint != 0) && (abs(hint->second+q) < abs(hint->second-q))) + { + return(::std::make_pair(-p,-q)); + } + + return(::std::make_pair(p,q)); +} + +#endif /* TEST_HSO4_HPP */ + diff --git a/src/boost/libs/math/example/Jamfile.v2 b/src/boost/libs/math/example/Jamfile.v2 new file mode 100644 index 000000000..c4038e031 --- /dev/null +++ b/src/boost/libs/math/example/Jamfile.v2 @@ -0,0 +1,162 @@ +# \libs\math\example\jamfile.v2 +# Runs statistics and floating-point examples. +# Copyright 2007 John Maddock +# Copyright Paul A. Bristow 2007, 2010, 2011. +# 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) + +# bring in the rules for testing +import testing ; +import ../../config/checks/config : requires ; + +project + : requirements + <toolset>gcc:<cxxflags>-Wno-missing-braces + <toolset>darwin:<cxxflags>-Wno-missing-braces + <toolset>acc:<cxxflags>+W2068,2461,2236,4070 + <toolset>intel:<cxxflags>-Qwd264,239 + <toolset>msvc:<warnings>all + <toolset>msvc:<asynch-exceptions>on + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS + <toolset>msvc:<cxxflags>/wd4996 + <toolset>msvc:<cxxflags>/wd4512 + <toolset>msvc:<cxxflags>/wd4610 + <toolset>msvc:<cxxflags>/wd4510 + <toolset>msvc:<cxxflags>/wd4127 + <toolset>msvc:<cxxflags>/wd4701 + <toolset>msvc:<cxxflags>/wd4127 + <toolset>msvc:<cxxflags>/wd4305 + <toolset>msvc:<cxxflags>/wd4459 + <toolset>msvc:<cxxflags>/wd4456 # declaration of hides previous local declaration. + #-<toolset>msvc:<cxxflags>/Za # nonfinite Serialization examples fail link if disable MS extensions, + # because serialization library is built with MS extensions enabled (default). + <toolset>clang:<cxxflags>-Wno-unknown-pragmas + <toolset>clang:<cxxflags>-Wno-language-extension-token + + <include>../../.. + <include>../include_private + <exception-handling>off:<source>../test//no_eh + [ requires cxx11_noexcept cxx11_rvalue_references sfinae_expr cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_hdr_initializer_list cxx11_hdr_chrono cxx11_thread_local cxx11_constexpr cxx11_nullptr cxx11_numeric_limits cxx11_decltype cxx11_hdr_array cxx11_hdr_atomic cxx11_hdr_type_traits cxx11_allocator cxx11_explicit_conversion_operators ] + ; + +test-suite examples : + [ run bessel_zeros_example_1.cpp : : : [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : <build>no ] <exception-handling>off:<build>no ] + [ run bessel_zeros_interator_example.cpp : : : <exception-handling>off:<build>no ] + [ run neumann_zeros_example_1.cpp : : : [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : <build>no ] <exception-handling>off:<build>no ] + + [ run test_cpp_float_close_fraction.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <exception-handling>off:<build>no ] + [ run binomial_coinflip_example.cpp : : : <exception-handling>off:<build>no ] + [ run binomial_confidence_limits.cpp ] + [ run binomial_example_nag.cpp ] + [ run binomial_quiz_example.cpp : : : <exception-handling>off:<build>no ] + [ run binomial_sample_sizes.cpp ] + [ run brent_minimise_example.cpp : : : [ requires cxx11_hdr_tuple ] ] + + [ run c_error_policy_example.cpp ] + [ run chi_square_std_dev_test.cpp : : : <exception-handling>off:<build>no ] + [ run distribution_construction.cpp : : : <exception-handling>off:<build>no ] + [ run error_handling_example.cpp : : : <exception-handling>off:<build>no ] + [ run error_policies_example.cpp ] + [ run error_policy_example.cpp : : : <exception-handling>off:<build>no ] + [ run f_test.cpp ] + # [ run fft_sines_table.cpp : : : [ requires cxx11_numeric_limits ] ] + # No need to re-run this routinely as it only creates a table of sines for a documentation example. + + [ run find_location_example.cpp : : : <exception-handling>off:<build>no ] + [ run find_mean_and_sd_normal.cpp : : : <exception-handling>off:<build>no ] + [ run find_root_example.cpp : : : <exception-handling>off:<build>no ] + [ run find_scale_example.cpp : : : <exception-handling>off:<build>no ] + [ run geometric_examples.cpp : : : <exception-handling>off:<build>no ] + [ run hyperexponential_snips.cpp ] + [ run hyperexponential_more_snips.cpp ] + [ run inverse_chi_squared_example.cpp ] + [ run legendre_stieltjes_example.cpp : : : [ requires cxx11_auto_declarations cxx11_defaulted_functions cxx11_lambdas ] ] + [ run airy_ulps_plot.cpp : : : [ requires cxx17_std_apply cxx17_if_constexpr ] ] + [ run agm_example.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : <linkflags>-lquadmath ] [ requires cxx17_std_apply cxx17_if_constexpr ] ] + #[ # run inverse_chi_squared_find_df_example.cpp ] + #[ run lambert_w_basic_example.cpp ] + [ run lambert_w_basic_example.cpp : : : [ requires cxx11_numeric_limits ] ] + [ run lambert_w_simple_examples.cpp : : : [ requires cxx11_numeric_limits ] [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : <linkflags>-lquadmath ] ] + [ run lambert_w_precision_example.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : <linkflags>-lquadmath ] [ requires cxx11_numeric_limits cxx11_explicit_conversion_operators ] ] + + [ run inverse_gamma_example.cpp ] + [ run inverse_gamma_distribution_example.cpp : : : <exception-handling>off:<build>no ] + [ run laplace_example.cpp : : : <exception-handling>off:<build>no ] + [ run nc_chi_sq_example.cpp ] + [ run neg_binom_confidence_limits.cpp ] + [ run neg_binomial_sample_sizes.cpp ] + [ run negative_binomial_example1.cpp : : : <exception-handling>off:<build>no ] + [ run negative_binomial_example2.cpp ] + + [ run nonfinite_num_facet.cpp ] + [ run nonfinite_facet_simple.cpp ] + [ run nonfinite_num_facet_serialization.cpp ../../serialization/build//boost_serialization : : : <exception-handling>off:<build>no <toolset>gcc-mingw:<link>static ] + #[ # run lexical_cast_native.cpp ] # Expected to fail on some (but not all) platforms. + [ run lexical_cast_nonfinite_facets.cpp ] + [ run nonfinite_loopback_ok.cpp ] + [ run nonfinite_serialization_archives.cpp ../../serialization/build//boost_serialization : : : <exception-handling>off:<build>no <toolset>gcc-mingw:<link>static ] + [ run nonfinite_facet_sstream.cpp ] + + [ run constants_eg1.cpp ] + + [ run normal_misc_examples.cpp : : : <exception-handling>off:<build>no ] + [ run owens_t_example.cpp ] + [ run policy_eg_1.cpp ] + [ run policy_eg_10.cpp : : : <target-os>vxworks:<build>no ] # VxWorks' complex.h has conflicting declaration of real + [ run policy_eg_2.cpp ] + [ run policy_eg_3.cpp ] + [ run policy_eg_4.cpp ] + [ run policy_eg_5.cpp ] + [ run policy_eg_6.cpp ] + [ run policy_eg_7.cpp ] + [ run policy_eg_8.cpp ] + [ run policy_eg_9.cpp ] + [ run policy_ref_snip1.cpp : : : <exception-handling>off:<build>no ] + [ run policy_ref_snip10.cpp ] + [ run policy_ref_snip11.cpp ] + [ run policy_ref_snip12.cpp ] + [ run policy_ref_snip13.cpp : : : <exception-handling>off:<build>no ] # Fails clang-win - thrown exception from no Cauchy mean. + [ run policy_ref_snip2.cpp ] + [ run policy_ref_snip3.cpp : : : <exception-handling>off:<build>no ] + [ run policy_ref_snip4.cpp ] + [ run policy_ref_snip5.cpp : : : <target-os>vxworks:<build>no ] + [ run policy_ref_snip6.cpp ] + [ run policy_ref_snip7.cpp ] + [ run policy_ref_snip8.cpp ] + [ run policy_ref_snip9.cpp ] + [ run skew_normal_example.cpp ] + [ run students_t_example1.cpp ] + [ run students_t_example2.cpp ] + [ run students_t_example3.cpp ] + [ run students_t_single_sample.cpp ] + [ run students_t_two_samples.cpp ] + [ run HSO3SO4.cpp ] + [ run series.cpp ] + [ run continued_fractions.cpp ] + + [ run barycentric_interpolation_example.cpp : : : [ requires cxx11_smart_ptr cxx11_function_template_default_args cxx11_unified_initialization_syntax cxx11_defaulted_functions cxx11_allocator cxx11_auto_declarations cxx11_lambdas ] ] + [ run barycentric_interpolation_example_2.cpp : : : [ requires cxx11_smart_ptr cxx11_function_template_default_args cxx11_unified_initialization_syntax cxx11_defaulted_functions cxx11_allocator cxx11_auto_declarations cxx11_lambdas ] ] + [ run cardinal_cubic_b_spline_example.cpp : : : [ requires cxx11_smart_ptr cxx11_hdr_random cxx11_defaulted_functions ] ] + [ compile naive_monte_carlo_example.cpp : [ requires cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_thread cxx11_hdr_atomic cxx11_decltype cxx11_hdr_future cxx11_hdr_chrono cxx11_hdr_random cxx11_allocator ] ] # requires user input, can't run it, take a long time too! + [ run catmull_rom_example.cpp : : : [ requires cxx17_if_constexpr cxx11_auto_declarations cxx17_std_apply ] ] # Actually the C++17 features used is std::size, not if constexpr; looks like there isn't yet a test for it. + [ run autodiff_black_scholes_brief.cpp : : : [ requires cxx11_inline_namespaces ] ] + [ run autodiff_black_scholes.cpp : : : [ requires cxx11_inline_namespaces ] ] + [ run autodiff_fourth_power.cpp : : : [ requires cxx11_inline_namespaces ] ] + [ run autodiff_mixed_partials.cpp : : : [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : <build>no ] [ requires cxx11_inline_namespaces ] ] + [ run autodiff_multiprecision.cpp : : : [ check-target-builds ../config//is_ci_standalone_run "Standalone CI run" : <build>no ] [ requires cxx11_inline_namespaces ] ] + [ run ooura_fourier_integrals_example.cpp : : : [ requires cxx11_hdr_mutex cxx11_lambdas cxx11_inline_namespaces cxx11_auto_declarations ] ] + [ run ooura_fourier_integrals_cosine_example.cpp : : : [ requires cxx11_hdr_mutex cxx11_inline_namespaces cxx11_auto_declarations cxx17_std_apply ] ] + [ run ooura_fourier_integrals_multiprecision_example.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : <linkflags>-lquadmath ] [ requires cxx11_hdr_mutex cxx11_inline_namespaces cxx11_auto_declarations cxx17_std_apply ] ] + [ run reciprocal_fibonacci_constant.cpp : : : [ check-target-builds ../config//has_mpfr "MPFR Support" : <linkflags>"-lmpfr -lgmp" : <build>no ] ] +; + +run root_elliptic_finding.cpp /boost/timer : : : release <link>static [ requires cxx11_unified_initialization_syntax cxx11_defaulted_functions ] <target-os>freebsd:<linkflags>"-lrt" <target-os>linux:<linkflags>"-lrt -lpthread" ; +run root_finding_algorithms.cpp /boost/timer : : : release <link>static [ requires cxx11_hdr_tuple cxx11_unified_initialization_syntax ] <target-os>freebsd:<linkflags>"-lrt" <target-os>linux:<linkflags>"-lrt -lpthread" ; +run root_n_finding_algorithms.cpp /boost/timer : : : release <link>static [ requires cxx11_unified_initialization_syntax cxx11_defaulted_functions ] <target-os>freebsd:<linkflags>"-lrt" <target-os>linux:<linkflags>"-lrt -lpthread" ; + +explicit root_elliptic_finding ; +explicit root_finding_algorithms ; +explicit root_n_finding_algorithms ; diff --git a/src/boost/libs/math/example/agm_example.cpp b/src/boost/libs/math/example/agm_example.cpp new file mode 100644 index 000000000..a8a5f90ff --- /dev/null +++ b/src/boost/libs/math/example/agm_example.cpp @@ -0,0 +1,32 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +#include <cmath> +#include <iostream> +#include <iomanip> +#include <boost/math/tools/agm.hpp> +#include <boost/math/constants/constants.hpp> + +#ifndef BOOST_MATH_STANDALONE +#include <boost/multiprecision/cpp_bin_float.hpp> +#endif + +// This example computes the lemniscate constant to high precision using the agm: +using boost::math::tools::agm; +using boost::math::constants::pi; + +int main() { + using std::sqrt; + + #ifndef BOOST_MATH_STANDALONE + using Real = boost::multiprecision::cpp_bin_float_100; + #else + using Real = long double; + #endif + + Real G = agm(sqrt(Real(2)), Real(1)); + std::cout << std::setprecision(std::numeric_limits<Real>::max_digits10); + std::cout << " Gauss's lemniscate constant = " << pi<Real>()/G << "\n"; + std::cout << "Expected lemniscate constant = " << "2.62205755429211981046483958989111941368275495143162316281682170380079058707041425023029553296142909344613\n"; +} diff --git a/src/boost/libs/math/example/airy_ulps_plot.cpp b/src/boost/libs/math/example/airy_ulps_plot.cpp new file mode 100644 index 000000000..1beccadb9 --- /dev/null +++ b/src/boost/libs/math/example/airy_ulps_plot.cpp @@ -0,0 +1,65 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +// +// Deliberately contains some unicode characters: +// +// boost-no-inspect + +#include <iostream> +#include <boost/math/tools/ulps_plot.hpp> +#include <boost/core/demangle.hpp> +#include <boost/math/special_functions/airy.hpp> + +using boost::math::tools::ulps_plot; + +int main() { + using PreciseReal = long double; + using CoarseReal = float; + + typedef boost::math::policies::policy< + boost::math::policies::promote_float<false>, + boost::math::policies::promote_double<false> > + no_promote_policy; + + auto ai_coarse = [](CoarseReal x) { + return boost::math::airy_ai<CoarseReal>(x, no_promote_policy()); + }; + auto ai_precise = [](PreciseReal x) { + return boost::math::airy_ai<PreciseReal>(x, no_promote_policy()); + }; + + std::string filename = "airy_ai_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg"; + int samples = 10000; + // How many pixels wide do you want your .svg? + int width = 700; + // Near a root, we have unbounded relative error. So for functions with roots, we define an ULP clip: + PreciseReal clip = 2.5; + // Should we perturb the abscissas? i.e., should we compute the high precision function f at x, + // and the low precision function at the nearest representable x̂ to x? + // Or should we compute both the high precision and low precision function at a low precision representable x̂? + bool perturb_abscissas = false; + auto plot = ulps_plot<decltype(ai_precise), PreciseReal, CoarseReal>(ai_precise, CoarseReal(-3), CoarseReal(3), samples, perturb_abscissas); + // Note the argument chaining: + plot.clip(clip).width(width); + // Sometimes it's useful to set a title, but in many cases it's more useful to just use a caption. + //std::string title = "Airy Ai ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; + //plot.title(title); + plot.vertical_lines(6); + plot.add_fn(ai_coarse); + // You can write the plot to a stream: + //std::cout << plot; + // Or to a file: + plot.write(filename); + + // Don't like the default dark theme? + plot.background_color("white").font_color("black"); + filename = "airy_ai_" + boost::core::demangle(typeid(CoarseReal).name()) + "_white.svg"; + plot.write(filename); + + // Don't like the envelope? + plot.ulp_envelope(false); + filename = "airy_ai_" + boost::core::demangle(typeid(CoarseReal).name()) + "_white_no_envelope.svg"; + plot.write(filename); +} diff --git a/src/boost/libs/math/example/airy_zeros_example.cpp b/src/boost/libs/math/example/airy_zeros_example.cpp new file mode 100644 index 000000000..3ab2c77d5 --- /dev/null +++ b/src/boost/libs/math/example/airy_zeros_example.cpp @@ -0,0 +1,165 @@ + +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> + +// Weisstein, Eric W. "Bessel Function Zeros." From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/BesselFunctionZeros.html +// Test values can be calculated using [@wolframalpha.com WolframAplha] +// See also http://dlmf.nist.gov/10.21 + +//[airy_zeros_example_1 + +/*`This example demonstrates calculating zeros of the Airy functions. +It also shows how Boost.Math and Boost.Multiprecision can be combined to provide +a many decimal digit precision. For 50 decimal digit precision we need to include +*/ + + #include <boost/multiprecision/cpp_dec_float.hpp> + +/*`and a `typedef` for `float_type` may be convenient +(allowing a quick switch to re-compute at built-in `double` or other precision) +*/ + typedef boost::multiprecision::cpp_dec_float_50 float_type; + +//`To use the functions for finding zeros of the functions we need + + #include <boost/math/special_functions/airy.hpp> + +/*`This example shows obtaining both a single zero of the Airy functions, +and then placing multiple zeros into a container like `std::vector` by providing an iterator. +The signature of the single-value Airy Ai function is: + + template <class T> + T airy_ai_zero(unsigned m); // 1-based index of the zero. + +The signature of multiple zeros Airy Ai function is: + + template <class T, class OutputIterator> + OutputIterator airy_ai_zero( + unsigned start_index, // 1-based index of the zero. + unsigned number_of_zeros, // How many zeros to generate. + OutputIterator out_it); // Destination for zeros. + +There are also versions which allows control of the __policy_section for error handling and precision. + + template <class T, class OutputIterator, class Policy> + OutputIterator airy_ai_zero( + unsigned start_index, // 1-based index of the zero. + unsigned number_of_zeros, // How many zeros to generate. + OutputIterator out_it, // Destination for zeros. + const Policy& pol); // Policy to use. +*/ +//] [/airy_zeros_example_1] + +int main() +{ + try + { +//[airy_zeros_example_2 + +/*`[tip It is always wise to place code using Boost.Math inside `try'n'catch` blocks; +this will ensure that helpful error messages are shown when exceptional conditions arise.] + +First, evaluate a single Airy zero. + +The precision is controlled by the template parameter `T`, +so this example has `double` precision, at least 15 but up to 17 decimal digits +(for the common 64-bit double). +*/ + double aiz1 = boost::math::airy_ai_zero<double>(1); + std::cout << "boost::math::airy_ai_zero<double>(1) = " << aiz1 << std::endl; + double aiz2 = boost::math::airy_ai_zero<double>(2); + std::cout << "boost::math::airy_ai_zero<double>(2) = " << aiz2 << std::endl; + double biz3 = boost::math::airy_bi_zero<double>(3); + std::cout << "boost::math::airy_bi_zero<double>(3) = " << biz3 << std::endl; + +/*`Other versions of `airy_ai_zero` and `airy_bi_zero` +allow calculation of multiple zeros with one call, +placing the results in a container, often `std::vector`. +For example, generate and display the first five `double` roots +[@http://mathworld.wolfram.com/AiryFunctionZeros.html Wolfram Airy Functions Zeros]. +*/ + unsigned int n_roots = 5U; + std::vector<double> roots; + boost::math::airy_ai_zero<double>(1U, n_roots, std::back_inserter(roots)); + std::cout << "airy_ai_zeros:" << std::endl; + std::copy(roots.begin(), + roots.end(), + std::ostream_iterator<double>(std::cout, "\n")); + +/*`The first few real roots of Ai(x) are approximately -2.33811, -4.08795, -5.52056, -6.7867144, -7.94413, -9.02265 ... + +Or we can use Boost.Multiprecision to generate 50 decimal digit roots. + +We set the precision of the output stream, and show trailing zeros to display a fixed 50 decimal digits. +*/ + std::cout.precision(std::numeric_limits<float_type>::digits10); // float_type has 50 decimal digits. + std::cout << std::showpoint << std::endl; // Show trailing zeros too. + + unsigned int m = 1U; + float_type r = boost::math::airy_ai_zero<float_type>(1U); // 1st root. + std::cout << "boost::math::airy_bi_zero<float_type>(" << m << ") = " << r << std::endl; + m = 2; + r = boost::math::airy_ai_zero<float_type>(2U); // 2nd root. + std::cout << "boost::math::airy_bi_zero<float_type>(" << m << ") = " << r << std::endl; + m = 7U; + r = boost::math::airy_bi_zero<float_type>(7U); // 7th root. + std::cout << "boost::math::airy_bi_zero<float_type>(" << m << ") = " << r << std::endl; + + std::vector<float_type> zeros; + boost::math::airy_ai_zero<float_type>(1U, 3, std::back_inserter(zeros)); + std::cout << "airy_ai_zeros:" << std::endl; + // Print the roots to the output stream. + std::copy(zeros.begin(), zeros.end(), + std::ostream_iterator<float_type>(std::cout, "\n")); +//] [/airy_zeros_example_2] + } + catch (std::exception ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + } // int main() + +/* + + Output: + + Description: Autorun "J:\Cpp\big_number\Debug\airy_zeros_example.exe" + boost::math::airy_ai_zero<double>(1) = -2.33811 + boost::math::airy_ai_zero<double>(2) = -4.08795 + boost::math::airy_bi_zero<double>(3) = -4.83074 + airy_ai_zeros: + -2.33811 + -4.08795 + -5.52056 + -6.78671 + -7.94413 + + boost::math::airy_bi_zero<float_type>(1) = -2.3381074104597670384891972524467354406385401456711 + boost::math::airy_bi_zero<float_type>(2) = -4.0879494441309706166369887014573910602247646991085 + boost::math::airy_bi_zero<float_type>(7) = -9.5381943793462388866329885451560196208390720763825 + airy_ai_zeros: + -2.3381074104597670384891972524467354406385401456711 + -4.0879494441309706166369887014573910602247646991085 + -5.5205598280955510591298555129312935737972142806175 + +*/ + diff --git a/src/boost/libs/math/example/arcsine_example.cpp b/src/boost/libs/math/example/arcsine_example.cpp new file mode 100644 index 000000000..3bea6d0ed --- /dev/null +++ b/src/boost/libs/math/example/arcsine_example.cpp @@ -0,0 +1,89 @@ +// arcsine_example.cpp + +// Copyright John Maddock 2014. +// Copyright Paul A. Bristow 2014. + +// 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) + +// Example for the arcsine Distribution. + +// Note: Contains Quickbook snippets in comments. + +//[arcsine_snip_1 +#include <boost/math/distributions/arcsine.hpp> // For arcsine_distribution. +//] [/arcsine_snip_1] + +#include <iostream> +#include <exception> +#include <boost/math/tools/assert.hpp> + +int main() +{ + std::cout << "Examples of Arcsine distribution." << std::endl; + std::cout.precision(3); // Avoid uninformative decimal digits. + + using boost::math::arcsine; + + arcsine as; // Construct a default `double` standard [0, 1] arcsine distribution. + +//[arcsine_snip_2 + std::cout << pdf(as, 1. / 2) << std::endl; // 0.637 + // pdf has a minimum at x = 0.5 +//] [/arcsine_snip_2] + +//[arcsine_snip_3 + std::cout << pdf(as, 1. / 4) << std::endl; // 0.735 +//] [/arcsine_snip_3] + + +//[arcsine_snip_4 + std::cout << cdf(as, 0.05) << std::endl; // 0.144 +//] [/arcsine_snip_4] + +//[arcsine_snip_5 + std::cout << 2 * cdf(as, 1 - 0.975) << std::endl; // 0.202 +//] [/arcsine_snip_5] + + +//[arcsine_snip_6 + std::cout << 2 * cdf(complement(as, 0.975)) << std::endl; // 0.202 +//] [/arcsine_snip_6] + +//[arcsine_snip_7 + std::cout << quantile(as, 1 - 0.2 / 2) << std::endl; // 0.976 + + std::cout << quantile(complement(as, 0.2 / 2)) << std::endl; // 0.976 +//] [/arcsine_snip_7] + +{ +//[arcsine_snip_8 + using boost::math::arcsine_distribution; + + arcsine_distribution<> as(2, 5); // Constructs a double arcsine distribution. + BOOST_MATH_ASSERT(as.x_min() == 2.); // as.x_min() returns 2. + BOOST_MATH_ASSERT(as.x_max() == 5.); // as.x_max() returns 5. +//] [/arcsine_snip_8] +} + return 0; + +} // int main() + +/* +[arcsine_output + +Example of Arcsine distribution +0.637 +0.735 +0.144 +0.202 +0.202 +0.976 +0.976 + +] [/arcsine_output] +*/ + + diff --git a/src/boost/libs/math/example/autodiff_black_scholes.cpp b/src/boost/libs/math/example/autodiff_black_scholes.cpp new file mode 100644 index 000000000..b7fcd9c0a --- /dev/null +++ b/src/boost/libs/math/example/autodiff_black_scholes.cpp @@ -0,0 +1,195 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include <boost/math/differentiation/autodiff.hpp> +#include <iostream> +#include <stdexcept> + +using namespace boost::math::constants; +using namespace boost::math::differentiation; + +// Equations and function/variable names are from +// https://en.wikipedia.org/wiki/Greeks_(finance)#Formulas_for_European_option_Greeks + +// Standard normal probability density function +template <typename X> +X phi(X const& x) { + return one_div_root_two_pi<X>() * exp(-0.5 * x * x); +} + +// Standard normal cumulative distribution function +template <typename X> +X Phi(X const& x) { + return 0.5 * erfc(-one_div_root_two<X>() * x); +} + +enum class CP { call, put }; + +// Assume zero annual dividend yield (q=0). +template <typename Price, typename Sigma, typename Tau, typename Rate> +promote<Price, Sigma, Tau, Rate> black_scholes_option_price(CP cp, + double K, + Price const& S, + Sigma const& sigma, + Tau const& tau, + Rate const& r) { + using namespace std; + auto const d1 = (log(S / K) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt(tau)); + auto const d2 = (log(S / K) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt(tau)); + switch (cp) { + case CP::call: + return S * Phi(d1) - exp(-r * tau) * K * Phi(d2); + case CP::put: + return exp(-r * tau) * K * Phi(-d2) - S * Phi(-d1); + default: + throw std::runtime_error("Invalid CP value."); + } +} + +int main() { + double const K = 100.0; // Strike price. + auto const variables = make_ftuple<double, 3, 3, 1, 1>(105, 5, 30.0 / 365, 1.25 / 100); + auto const& S = std::get<0>(variables); // Stock price. + auto const& sigma = std::get<1>(variables); // Volatility. + auto const& tau = std::get<2>(variables); // Time to expiration in years. (30 days). + auto const& r = std::get<3>(variables); // Interest rate. + auto const call_price = black_scholes_option_price(CP::call, K, S, sigma, tau, r); + auto const put_price = black_scholes_option_price(CP::put, K, S, sigma, tau, r); + + double const d1 = static_cast<double>((log(S / K) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt(tau))); + double const d2 = static_cast<double>((log(S / K) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt(tau))); + double const formula_call_delta = +Phi(+d1); + double const formula_put_delta = -Phi(-d1); + double const formula_vega = static_cast<double>(S * phi(d1) * sqrt(tau)); + double const formula_call_theta = + static_cast<double>(-S * phi(d1) * sigma / (2 * sqrt(tau)) - r * K * exp(-r * tau) * Phi(+d2)); + double const formula_put_theta = + static_cast<double>(-S * phi(d1) * sigma / (2 * sqrt(tau)) + r * K * exp(-r * tau) * Phi(-d2)); + double const formula_call_rho = static_cast<double>(+K * tau * exp(-r * tau) * Phi(+d2)); + double const formula_put_rho = static_cast<double>(-K * tau * exp(-r * tau) * Phi(-d2)); + double const formula_gamma = static_cast<double>(phi(d1) / (S * sigma * sqrt(tau))); + double const formula_vanna = static_cast<double>(-phi(d1) * d2 / sigma); + double const formula_charm = + static_cast<double>(phi(d1) * (d2 * sigma * sqrt(tau) - 2 * r * tau) / (2 * tau * sigma * sqrt(tau))); + double const formula_vomma = static_cast<double>(S * phi(d1) * sqrt(tau) * d1 * d2 / sigma); + double const formula_veta = static_cast<double>(-S * phi(d1) * sqrt(tau) * + (r * d1 / (sigma * sqrt(tau)) - (1 + d1 * d2) / (2 * tau))); + double const formula_speed = + static_cast<double>(-phi(d1) * (d1 / (sigma * sqrt(tau)) + 1) / (S * S * sigma * sqrt(tau))); + double const formula_zomma = static_cast<double>(phi(d1) * (d1 * d2 - 1) / (S * sigma * sigma * sqrt(tau))); + double const formula_color = + static_cast<double>(-phi(d1) / (2 * S * tau * sigma * sqrt(tau)) * + (1 + (2 * r * tau - d2 * sigma * sqrt(tau)) * d1 / (sigma * sqrt(tau)))); + double const formula_ultima = + -formula_vega * static_cast<double>((d1 * d2 * (1 - d1 * d2) + d1 * d1 + d2 * d2) / (sigma * sigma)); + + std::cout << std::setprecision(std::numeric_limits<double>::digits10) + << "autodiff black-scholes call price = " << call_price.derivative(0, 0, 0, 0) << '\n' + << "autodiff black-scholes put price = " << put_price.derivative(0, 0, 0, 0) << '\n' + << "\n## First-order Greeks\n" + << "autodiff call delta = " << call_price.derivative(1, 0, 0, 0) << '\n' + << " formula call delta = " << formula_call_delta << '\n' + << "autodiff call vega = " << call_price.derivative(0, 1, 0, 0) << '\n' + << " formula call vega = " << formula_vega << '\n' + << "autodiff call theta = " << -call_price.derivative(0, 0, 1, 0) + << '\n' // minus sign due to tau = T-time + << " formula call theta = " << formula_call_theta << '\n' + << "autodiff call rho = " << call_price.derivative(0, 0, 0, 1) << '\n' + << " formula call rho = " << formula_call_rho << '\n' + << '\n' + << "autodiff put delta = " << put_price.derivative(1, 0, 0, 0) << '\n' + << " formula put delta = " << formula_put_delta << '\n' + << "autodiff put vega = " << put_price.derivative(0, 1, 0, 0) << '\n' + << " formula put vega = " << formula_vega << '\n' + << "autodiff put theta = " << -put_price.derivative(0, 0, 1, 0) << '\n' + << " formula put theta = " << formula_put_theta << '\n' + << "autodiff put rho = " << put_price.derivative(0, 0, 0, 1) << '\n' + << " formula put rho = " << formula_put_rho << '\n' + << "\n## Second-order Greeks\n" + << "autodiff call gamma = " << call_price.derivative(2, 0, 0, 0) << '\n' + << "autodiff put gamma = " << put_price.derivative(2, 0, 0, 0) << '\n' + << " formula gamma = " << formula_gamma << '\n' + << "autodiff call vanna = " << call_price.derivative(1, 1, 0, 0) << '\n' + << "autodiff put vanna = " << put_price.derivative(1, 1, 0, 0) << '\n' + << " formula vanna = " << formula_vanna << '\n' + << "autodiff call charm = " << -call_price.derivative(1, 0, 1, 0) << '\n' + << "autodiff put charm = " << -put_price.derivative(1, 0, 1, 0) << '\n' + << " formula charm = " << formula_charm << '\n' + << "autodiff call vomma = " << call_price.derivative(0, 2, 0, 0) << '\n' + << "autodiff put vomma = " << put_price.derivative(0, 2, 0, 0) << '\n' + << " formula vomma = " << formula_vomma << '\n' + << "autodiff call veta = " << call_price.derivative(0, 1, 1, 0) << '\n' + << "autodiff put veta = " << put_price.derivative(0, 1, 1, 0) << '\n' + << " formula veta = " << formula_veta << '\n' + << "\n## Third-order Greeks\n" + << "autodiff call speed = " << call_price.derivative(3, 0, 0, 0) << '\n' + << "autodiff put speed = " << put_price.derivative(3, 0, 0, 0) << '\n' + << " formula speed = " << formula_speed << '\n' + << "autodiff call zomma = " << call_price.derivative(2, 1, 0, 0) << '\n' + << "autodiff put zomma = " << put_price.derivative(2, 1, 0, 0) << '\n' + << " formula zomma = " << formula_zomma << '\n' + << "autodiff call color = " << call_price.derivative(2, 0, 1, 0) << '\n' + << "autodiff put color = " << put_price.derivative(2, 0, 1, 0) << '\n' + << " formula color = " << formula_color << '\n' + << "autodiff call ultima = " << call_price.derivative(0, 3, 0, 0) << '\n' + << "autodiff put ultima = " << put_price.derivative(0, 3, 0, 0) << '\n' + << " formula ultima = " << formula_ultima << '\n'; + return 0; +} +/* +Output: +autodiff black-scholes call price = 56.5136030677739 +autodiff black-scholes put price = 51.4109161009333 + +## First-order Greeks +autodiff call delta = 0.773818444921273 + formula call delta = 0.773818444921274 +autodiff call vega = 9.05493427705736 + formula call vega = 9.05493427705736 +autodiff call theta = -275.73013426444 + formula call theta = -275.73013426444 +autodiff call rho = 2.03320550539396 + formula call rho = 2.03320550539396 + +autodiff put delta = -0.226181555078726 + formula put delta = -0.226181555078726 +autodiff put vega = 9.05493427705736 + formula put vega = 9.05493427705736 +autodiff put theta = -274.481417851526 + formula put theta = -274.481417851526 +autodiff put rho = -6.17753255212599 + formula put rho = -6.17753255212599 + +## Second-order Greeks +autodiff call gamma = 0.00199851912993254 +autodiff put gamma = 0.00199851912993254 + formula gamma = 0.00199851912993254 +autodiff call vanna = 0.0410279463126531 +autodiff put vanna = 0.0410279463126531 + formula vanna = 0.0410279463126531 +autodiff call charm = -1.2505564233679 +autodiff put charm = -1.2505564233679 + formula charm = -1.2505564233679 +autodiff call vomma = -0.928114149313108 +autodiff put vomma = -0.928114149313108 + formula vomma = -0.928114149313107 +autodiff call veta = 26.7947073115641 +autodiff put veta = 26.7947073115641 + formula veta = 26.7947073115641 + +## Third-order Greeks +autodiff call speed = -2.90117322380992e-05 +autodiff put speed = -2.90117322380992e-05 + formula speed = -2.90117322380992e-05 +autodiff call zomma = -0.000604548369901419 +autodiff put zomma = -0.000604548369901419 + formula zomma = -0.000604548369901419 +autodiff call color = -0.0184014426606065 +autodiff put color = -0.0184014426606065 + formula color = -0.0184014426606065 +autodiff call ultima = -0.0922426864775683 +autodiff put ultima = -0.0922426864775683 + formula ultima = -0.0922426864775685 +**/ diff --git a/src/boost/libs/math/example/autodiff_black_scholes_brief.cpp b/src/boost/libs/math/example/autodiff_black_scholes_brief.cpp new file mode 100644 index 000000000..7078217b6 --- /dev/null +++ b/src/boost/libs/math/example/autodiff_black_scholes_brief.cpp @@ -0,0 +1,70 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include <boost/math/differentiation/autodiff.hpp> +#include <iostream> +#include <stdexcept> + +using namespace boost::math::constants; +using namespace boost::math::differentiation; + +// Equations and function/variable names are from +// https://en.wikipedia.org/wiki/Greeks_(finance)#Formulas_for_European_option_Greeks + +// Standard normal cumulative distribution function +template <typename X> +X Phi(X const& x) { + return 0.5 * erfc(-one_div_root_two<X>() * x); +} + +enum class CP { call, put }; + +// Assume zero annual dividend yield (q=0). +template <typename Price, typename Sigma, typename Tau, typename Rate> +promote<Price, Sigma, Tau, Rate> black_scholes_option_price(CP cp, + double K, + Price const& S, + Sigma const& sigma, + Tau const& tau, + Rate const& r) { + using namespace std; + auto const d1 = (log(S / K) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt(tau)); + auto const d2 = (log(S / K) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt(tau)); + switch (cp) { + case CP::call: + return S * Phi(d1) - exp(-r * tau) * K * Phi(d2); + case CP::put: + return exp(-r * tau) * K * Phi(-d2) - S * Phi(-d1); + default: + throw std::runtime_error("Invalid CP value."); + } +} + +int main() { + double const K = 100.0; // Strike price. + auto const S = make_fvar<double, 2>(105); // Stock price. + double const sigma = 5; // Volatility. + double const tau = 30.0 / 365; // Time to expiration in years. (30 days). + double const r = 1.25 / 100; // Interest rate. + auto const call_price = black_scholes_option_price(CP::call, K, S, sigma, tau, r); + auto const put_price = black_scholes_option_price(CP::put, K, S, sigma, tau, r); + + std::cout << "black-scholes call price = " << call_price.derivative(0) << '\n' + << "black-scholes put price = " << put_price.derivative(0) << '\n' + << "call delta = " << call_price.derivative(1) << '\n' + << "put delta = " << put_price.derivative(1) << '\n' + << "call gamma = " << call_price.derivative(2) << '\n' + << "put gamma = " << put_price.derivative(2) << '\n'; + return 0; +} +/* +Output: +black-scholes call price = 56.5136 +black-scholes put price = 51.4109 +call delta = 0.773818 +put delta = -0.226182 +call gamma = 0.00199852 +put gamma = 0.00199852 +**/ diff --git a/src/boost/libs/math/example/autodiff_fourth_power.cpp b/src/boost/libs/math/example/autodiff_fourth_power.cpp new file mode 100644 index 000000000..50f280b6b --- /dev/null +++ b/src/boost/libs/math/example/autodiff_fourth_power.cpp @@ -0,0 +1,34 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include <boost/math/differentiation/autodiff.hpp> +#include <iostream> + +template <typename T> +T fourth_power(T const& x) { + T x4 = x * x; // retval in operator*() uses x4's memory via NRVO. + x4 *= x4; // No copies of x4 are made within operator*=() even when squaring. + return x4; // x4 uses y's memory in main() via NRVO. +} + +int main() { + using namespace boost::math::differentiation; + + constexpr unsigned Order = 5; // Highest order derivative to be calculated. + auto const x = make_fvar<double, Order>(2.0); // Find derivatives at x=2. + auto const y = fourth_power(x); + for (unsigned i = 0; i <= Order; ++i) + std::cout << "y.derivative(" << i << ") = " << y.derivative(i) << std::endl; + return 0; +} +/* +Output: +y.derivative(0) = 16 +y.derivative(1) = 32 +y.derivative(2) = 48 +y.derivative(3) = 48 +y.derivative(4) = 24 +y.derivative(5) = 0 +**/ diff --git a/src/boost/libs/math/example/autodiff_mixed_partials.cpp b/src/boost/libs/math/example/autodiff_mixed_partials.cpp new file mode 100644 index 000000000..551429e01 --- /dev/null +++ b/src/boost/libs/math/example/autodiff_mixed_partials.cpp @@ -0,0 +1,293 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include <boost/lexical_cast.hpp> +#include <boost/math/differentiation/autodiff.hpp> +#include <boost/mp11/tuple.hpp> +#include <boost/mp11/utility.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <iostream> + +using namespace boost::math::differentiation; + +struct f { + template <typename W, typename X, typename Y, typename Z> + promote<W, X, Y, Z> operator()(W const& w, X const& x, Y const& y, Z const& z) const { + return exp(w * sin(x * log(y) / z) + sqrt(w * z / (x * y))) + w * w / tan(z); + } +}; + +// Derivatives calculated from symbolic differentiation by Mathematica for comparison. Script: +// mixed_partials.nb +static constexpr std::array<char const*, 240> answers{ + {"19878.40628980434922342465374997798674242532797789489", + "20731.74838274939517275508122761443159515217855975002", + "14667.60767623939014840117674691707821648144188283774", + "1840.559936449813118734351750381849294157477519107602", + "-9219.318005237072129605008516120710807803827373819700", + "-7272.300634012811783845589472196110804386170683300081", + "-2135.296370062283924160196772166043360841114107521292", + "3095.081027251846799545897828297310835169325417217168", + "4249.026762908615627428402369471953790564918480025345", + "2063.989061062734416582172072883742097425754355167541", + "-885.5284114876496084068555333811894392182458751895290", + "-1962.133420441743158021558423645064067562765178375508", + "-1846.899830787084518564013512948598850243350915531775", + "-160.9590127603295755195950112199107484483554942817846", + "1091.039412341633994110997652976585409621806446647794", + "452.4395574345229946707651998323417632800605985181691", + "666.4013922727704990031159406121675703174518834914461", + "-415.6464114333629107803309520898363153301435468382605", + "-625.1464179039986361267627631122900331946746137220517", + "369.9491669772617110087494756677334192842413470837587", + "-24330.89613849389343130420303653062335840497802221681", + "-18810.41605175626752065686192937776868736029049989926", + "-4890.406122702359099863022925593448420259414896197252", + "8833.005054768976417065486877649473665597894570245307", + "8484.350739681613747819854384228795938450532463850094", + "3097.204151240398893507362023543393154680147349049848", + "-3255.045136783440612110181337652522080890693968833148", + "-4342.778553332193097878812792875447018366988006584840", + "-2407.987237906523486012534085031032446996713414362131", + "861.1173916470300084261504495377425043024739914571554", + "2436.743725763308619092960749816106318692933687303014", + "-19.24649610733827783846392798978023489104363382129689", + "187.7855148870511714395275130898958731897480766620821", + "-1259.466063335212195169531010871023748854744563232277", + "-709.6860523972158261343923419671629587637051060458295", + "1423.000558608604536932163648918899935569543711292466", + "484.9208133389233959103861107714757012185008046446372", + "763.9746885074453180462508029718247316712990115789154", + "-327.4162918228055568224139277603073169658358026440432", + "-1122.337707248494521123614369562896901904418640152220", + "23973.06007192346989337502250398494874845408708506720", + "8840.543151778796869949670401421984604862699128880003", + "-9082.571033221549378277312292526023838132689941236879", + "-12270.27378289258717737657881957466807305650429436397", + "-4320.434071420599854743576892819691675331049612545664", + "3281.351967707280898543984556670710235259118405463698", + "5880.336263083418767219493592767818708317492833223933", + "-1288.482785219706549809211085113790275109642879331959", + "-803.9713537626580526627976840414468844364935388365037", + "-2986.387245331698390346145949708414455858834967096376", + "-586.7316859822658306283656047992829723003491823675739", + "3929.073189280739356198769778905960586080418779863615", + "1453.728280983826630077825553258703050898056317382483", + "1037.878071685953829685046234106860743366780050925514", + "-1482.745805277401336553926171580259185140208053329753", + "-1877.134792933828810602377451370316364621357891989679", + "-931.7138710369298207131581126980851620513905805624544", + "254.6565590420322632851077818917210811815919344882311", + "1391.248064745611663849820246430123214796614030838600", + "-431.4820563154137955051720207563800896297257103310465", + "16975.34005365179555009050533000516107937041784876054", + "19662.60356303341709846238790020024593550984564081068", + "15765.85130704020004301064240357947656083104783442825", + "3972.155036195937013764185795634749937308876197976202", + "-8681.748539789720512499473840242996096730194203989543", + "-7703.183042460387656743498394861780784700076575106134", + "-3049.708696569518774040135942468704911634779352213044", + "2971.469685992270876159892302788930292108129670398058", + "4370.196499857550025657084783894747734031876677385611", + "2524.632473357435670756946837415389227139966527203701", + "-656.6080000236679071742450437463693211275208125750923", + "-2423.452917325258132591368397957959217829861665178601", + "-2074.987664204263204162199830716851483704870169031179", + "-381.2253794988132984501358802316138392247470857452486", + "1219.507245791997351017860252538035146744682380716428", + "805.3802239840836877339667281819652171888443003165988", + "838.4004190058912380470543219448821914235443115661655", + "-390.6125197108983831575656956558201636111305409512701", + "-828.2085489298235758253219930356006757081473789845849", + "293.8999854454994790079171865082094494146506490533363", + "-22965.85985843951977785883587223006628792405076928067", + "-20026.69101529929621743747554537576887048069629325374", + "-7316.092745063355996548975300169565482331369744607021", + "8632.466133972614659252310985982644793465043032940318", + "8987.046882870452266200748127338744248816756004290490", + "4199.925399536137541108783465785304128965582292174062", + "-2958.429850896062893179851696175634522187021390095560", + "-5665.563891218624062243686482808197054863235184904433", + "-2945.404552250341615883104643651287431663294281737652", + "555.6566272478262524735403145861484390537770707372992", + "2936.796403550079139218970638242013974322758744804216", + "651.5191650747110008135060635556227666232180743487328", + "444.7629427486155148584918602702161457622049333694568", + "-1390.989671799095801316658971275073184600067187023729", + "-1142.861468946763860859271224968631944511098747155437", + "1541.978723117340843491920690654997335632919116206279", + "455.7146063293814470171599782651235242129856311098151", + "998.7943503940357037260061331795191352937661538946216", + "-204.8485581981121295383497187536442450324011940647949", + "-1560.354115460478786113711476250386112014306509906244", + "25278.29450605247223516529112562423587288781657290275", + "11873.22337179046469888005044109378787446671408425048", + "-8242.187303368878103323785658604027555126374435611949", + "-15939.98056417465751946455567789306872745912255628512", + "-5648.833539698031486810309720694416837861242341227280", + "2751.513926122717118525029734574022921057261239749143", + "7349.432002479077129245930487320138527887196396579062", + "194.9972545980371127390142753318206783334452047502143", + "-402.8156857682688265622049800462325595907987257153782", + "-3518.871908683063371167722463713374376552181380727802", + "-1494.304793474682619087166400375396721307777439607909", + "4640.927509426080087451995953783429589632369803588940", + "1585.757705203227141964561144798400703219894640413562", + "1565.169992404407137888592924342582799362959736185298", + "-1513.259809733540018859089666188672238777297615451800", + "-2974.437872674680092826212901753475972242208819679978", + "-1203.236292653823441598437153564865951527142648802876", + "72.52425949879153384040698301599842998884036742649047", + "1871.625274253419949517250818647194858608124560073483", + "-2.489984337379681666361341362948045621969765070197429", + "14462.74423518633102580192225823524237502860825596609", + "18367.74740916432711689913219912502810575714860430297", + "16565.76324499673961400925630526921000337443450249297", + "6054.315252651102952034254100792777051580892954459740", + "-8084.981271982030146065497115893934803061545998433631", + "-7988.314359128201297240919364015959817416101519999194", + "-3989.319346941492698525859335371231602272119870228687", + "2616.721186534649016680934493970036169897788778926434", + "4420.859270970486562095630193355634655337290952862363", + "2973.033519764547909146474824627687039969488363657908", + "-324.1453016982713707989332262410969595194473127209825", + "-2843.242039958969221918101261762794653424879358390111", + "-2281.461806143289517702658392470195144560150025832652", + "-642.9353229582055924928927665183236308235598082837497", + "1299.287274176955358490409470855361289523321919337117", + "1238.597083372069762230817383681570828675426312803376", + "1021.334042770848165110529668635291528449691525937968", + "-329.0529345069271079573348500899329811170455711610811", + "-1046.254301544052075124857362060924818517694048905299", + "134.7343039554480655186788228552325941588620079791654", + "-21431.41643507661192392650726158493697457993678274754", + "-20856.88281479015784660571401663659059349708627445067", + "-9829.261970591930907585958999196966814861251125275804", + "7806.858647077811827981774785577363365546600234846335", + "9319.700085649568180114405924685286453652118439999060", + "5319.898768025758256383579171601100187435481641933401", + "-2387.954826466841736373447020403170264502066930376059", + "-6958.298525165359760665355886221309296550746152109847", + "-3468.539106391972560670887295398968213297736424267559", + "130.4167253342709401698825285623058661085645012029873", + "3371.139930235175987370940343096776588915600470241960", + "1569.232678004908105313880673484968847566948896728142", + "750.0912101179065245750415609380442359608197763310413", + "-1462.257209626597452197736652121394535208578921869658", + "-1661.577809630240615684355192771059515041884351493459", + "1509.628528603869133250456671040505284128185908768108", + "383.8950902580816259502239917715884779698864996879279", + "1248.051096343638013308778159911906703363730187986273", + "17.18569564265260274901760034571610990094333217519021", + "-2038.024598002604853054532645991188063394308018947374", + "26118.98132017823514803387529120810044029492871875474", + "14943.61943482227903328457116850255971625430735856355", + "-6650.686262276131072415580833374348889422387492668440", + "-19519.81529547404067945704333355155941895199228108631", + "-6983.190236500848647457042860591724089812405118922223", + "1899.297502873688983038424995203515277346497811783168", + "8715.003652642963488202943622358986745434720576722170", + "2368.150690681864301926962120618658083737878227231428", + "136.8920793093482831910443246272238406481527839521448", + "-3954.732706163417141961077488373290331419627965482785", + "-2673.556440231186786375595871506657802723673830409989", + "5078.483935249043594670125721926702845818403229980691", + "1643.459143721204817182772630730123271413273760820347", + "2182.216979506380293664703833586468523416961563720645", + "-1345.838830963620501537777318021157952722412472356094", + "-4309.285350629108413525304135326225818270616857298235", + "-1488.050869922417817689426519211523527088509094291312", + "-228.0584943070343720919835603886532454450555855354340", + "2373.398940425709177876367020236623713151456855728138", + "773.8481328103928058186643458500631723389600248582833", + "12294.40387737855548614823173849184004455244840062464", + "16977.34966571858301862913845572077593071467784570724", + "17057.17475622503175013658695220988017704387344177727", + "8121.189758511830935868344768490586007624092305459885", + "-7458.443541406284389918808653948439156033975014107187", + "-8134.131160882738058651976911725365291142418949378248", + "-4912.881158613784419581465435995807691111897279859302", + "2030.653136098933717888434825960516061206391833398177", + "4407.490527709412730881592594976776779312299897714205", + "3392.434568825892752350943548729559313328141534290860", + "104.0372355841506198680609232049783930050635078746762", + "-3180.817620484463214391157460812371170723810181051096", + "-2460.523987075069437321629265332968914260047631079537", + "-938.2209314069133432825590545267820890922150850657831", + "1315.246905571876456706320919211807375254975062430487", + "1735.862392405992188189147617586418269768276241147998", + "1209.759657223166954850207025399731503326968841680649", + "-227.3320054566642297128407910803774238020746116287390", + "-1266.126209991929259396966729664100401813091860201682", + "-123.0794572338149156803989321165094334755661021559442", + "-19806.90794333834685506732819834090525250045748665845", + "-21314.81635440575229337844631555492486744407550254908", + "-12317.58384430130805020250005527399703840208659666608", + "6349.418659888281474363154227419204673663621492760982", + "9489.819687696527735093973063679592839666155440941289", + "6409.538948456309994399374417972222747225748405617373", + "-1550.281799013125267606263057621300789555474258987989", + "-8109.711199785217512061886243157800006692908759687186", + "-3957.840330296874877742767473517819198882831790006004", + "-404.0796555836667858753163727999380679499192203780272", + "3693.614351301181980145006883746936633676934626580499", + "2716.146658322790064799415509615557123789406209068981", + "1094.591086641398900496318896947912437274250932576747", + "-1456.269645549946420883827817869876763706452982413420", + "-2244.380608735636962338392373719455877272151458411079", + "1268.593891556261871090883000459505759446497182073132", + "265.2206730327749346649809229271069944357537135668622", + "1496.091578778639488439197917198148587432113387871024", + "354.6137351047722781932932090799444060236757625488818", + "-2508.477110048684129181005769771219369377836598443263", + "26517.86140875157324686379805134248778305979287686214", + "17922.98387741915144079932445041215068937644694653527", + "-4328.259142127668040873054918170572859673703425721293", + "-22704.70245940080949074466622805971940616027152354999", + "-8268.613747173738971390434576274225941735552759965376", + "740.4056074392611464740778308961471299437619012164253", + "9848.900182836035080973766381422758538530595451048714", + "5213.598341476210337710365441072904970861063876340963", + "801.2462923723508233330997243930793458484750729415321", + "-4241.870133920767845856621968904769727964770527614244", + "-4092.241355868550570635569815488217469506874233892269", + "5074.435909206083943809967780457349942315503368249477", + "1607.765329254820915989772546102530187884674235100928", + "2861.155651116567526208762405651011317435252198548496", + "-918.9310546317296090214320737728927500362088478158839", + "-5803.211323646092019259074499814222806376618363553826", + "-1767.541897994477314401145980308432268207111761980100", + "-663.0646207520075726320417301262932382663072876188661", + "2837.903194613938414496183429129769829434890424213252", + "1976.319600747797717779881875290418720908121189218755"}}; + +int main() { + using float50 = boost::multiprecision::cpp_bin_float_50; + constexpr std::size_t Nw = 3; // Max order of derivative to calculate for w + constexpr std::size_t Nx = 2; // Max order of derivative to calculate for x + constexpr std::size_t Ny = 4; // Max order of derivative to calculate for y + constexpr std::size_t Nz = 3; // Max order of derivative to calculate for z + auto const variables = make_ftuple<float50, Nw, Nx, Ny, Nz>(11, 12, 13, 14); + auto const v = boost::mp11::tuple_apply(f{}, variables); + std::size_t ia = 0; + double max_relative_error = 0; + for (std::size_t iw = 0; iw <= Nw; ++iw) + for (std::size_t ix = 0; ix <= Nx; ++ix) + for (std::size_t iy = 0; iy <= Ny; ++iy) + for (std::size_t iz = 0; iz <= Nz; ++iz) { + float50 const value = v.derivative(iw, ix, iy, iz); + float50 const answer = boost::lexical_cast<float50>(answers[ia++]); + double const error = static_cast<double>(fabs(value / answer - 1)); + max_relative_error = (std::max)(error, max_relative_error); + } + std::cout << "max_relative_error = " << std::setprecision(3) << max_relative_error << " out of " << ia + << " calculated values." << std::endl; + return 0; +} +/* +Output: +max_relative_error = 6.82e-13 out of 240 calculated values. (for double) +max_relative_error = 3.36e-47 out of 240 calculated values. (for cpp_bin_float_50) +**/ diff --git a/src/boost/libs/math/example/autodiff_multiprecision.cpp b/src/boost/libs/math/example/autodiff_multiprecision.cpp new file mode 100644 index 000000000..81c7c27c5 --- /dev/null +++ b/src/boost/libs/math/example/autodiff_multiprecision.cpp @@ -0,0 +1,46 @@ +// Copyright Matthew Pulver 2018 - 2019. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include <boost/math/differentiation/autodiff.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <iostream> + +using namespace boost::math::differentiation; + +template <typename W, typename X, typename Y, typename Z> +promote<W, X, Y, Z> f(const W& w, const X& x, const Y& y, const Z& z) { + using namespace std; + return exp(w * sin(x * log(y) / z) + sqrt(w * z / (x * y))) + w * w / tan(z); +} + +int main() { + using float50 = boost::multiprecision::cpp_bin_float_50; + + constexpr unsigned Nw = 3; // Max order of derivative to calculate for w + constexpr unsigned Nx = 2; // Max order of derivative to calculate for x + constexpr unsigned Ny = 4; // Max order of derivative to calculate for y + constexpr unsigned Nz = 3; // Max order of derivative to calculate for z + // Declare 4 independent variables together into a std::tuple. + auto const variables = make_ftuple<float50, Nw, Nx, Ny, Nz>(11, 12, 13, 14); + auto const& w = std::get<0>(variables); // Up to Nw derivatives at w=11 + auto const& x = std::get<1>(variables); // Up to Nx derivatives at x=12 + auto const& y = std::get<2>(variables); // Up to Ny derivatives at y=13 + auto const& z = std::get<3>(variables); // Up to Nz derivatives at z=14 + auto const v = f(w, x, y, z); + // Calculated from Mathematica symbolic differentiation. + float50 const answer("1976.319600747797717779881875290418720908121189218755"); + std::cout << std::setprecision(std::numeric_limits<float50>::digits10) + << "mathematica : " << answer << '\n' + << "autodiff : " << v.derivative(Nw, Nx, Ny, Nz) << '\n' + << std::setprecision(3) + << "relative error: " << (v.derivative(Nw, Nx, Ny, Nz) / answer - 1) << '\n'; + return 0; +} +/* +Output: +mathematica : 1976.3196007477977177798818752904187209081211892188 +autodiff : 1976.3196007477977177798818752904187209081211892188 +relative error: 2.67e-50 +**/ diff --git a/src/boost/libs/math/example/barycentric_interpolation_example.cpp b/src/boost/libs/math/example/barycentric_interpolation_example.cpp new file mode 100644 index 000000000..2da3ad9e5 --- /dev/null +++ b/src/boost/libs/math/example/barycentric_interpolation_example.cpp @@ -0,0 +1,92 @@ + +// Copyright Nick Thompson, 2017 + +// 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). + +#include <iostream> +#include <limits> +#include <vector> + +//[barycentric_rational_example + +/*` +This example shows how to use barycentric rational interpolation, using Walter Kohn's classic paper +"Solution of the Schrodinger Equation in Periodic Lattices with an Application to Metallic Lithium" +In this paper, Kohn needs to repeatedly solve an ODE (the radial Schrodinger equation) given a potential +which is only known at non-equally samples data. + +If he'd only had the barycentric rational interpolant of Boost.Math! + +References: Kohn, W., and N. Rostoker. "Solution of the Schrodinger equation in periodic lattices with an application to metallic lithium." Physical Review 94.5 (1954): 1111. +*/ + +#include <boost/math/interpolators/barycentric_rational.hpp> + +int main() +{ + // The lithium potential is given in Kohn's paper, Table I: + std::vector<double> r(45); + std::vector<double> mrV(45); + + // We'll skip the code for filling the above vectors with data for now... + //<- + + r[0] = 0.02; mrV[0] = 5.727; + r[1] = 0.04, mrV[1] = 5.544; + r[2] = 0.06, mrV[2] = 5.450; + r[3] = 0.08, mrV[3] = 5.351; + r[4] = 0.10, mrV[4] = 5.253; + r[5] = 0.12, mrV[5] = 5.157; + r[6] = 0.14, mrV[6] = 5.058; + r[7] = 0.16, mrV[7] = 4.960; + r[8] = 0.18, mrV[8] = 4.862; + r[9] = 0.20, mrV[9] = 4.762; + r[10] = 0.24, mrV[10] = 4.563; + r[11] = 0.28, mrV[11] = 4.360; + r[12] = 0.32, mrV[12] = 4.1584; + r[13] = 0.36, mrV[13] = 3.9463; + r[14] = 0.40, mrV[14] = 3.7360; + r[15] = 0.44, mrV[15] = 3.5429; + r[16] = 0.48, mrV[16] = 3.3797; + r[17] = 0.52, mrV[17] = 3.2417; + r[18] = 0.56, mrV[18] = 3.1209; + r[19] = 0.60, mrV[19] = 3.0138; + r[20] = 0.68, mrV[20] = 2.8342; + r[21] = 0.76, mrV[21] = 2.6881; + r[22] = 0.84, mrV[22] = 2.5662; + r[23] = 0.92, mrV[23] = 2.4242; + r[24] = 1.00, mrV[24] = 2.3766; + r[25] = 1.08, mrV[25] = 2.3058; + r[26] = 1.16, mrV[26] = 2.2458; + r[27] = 1.24, mrV[27] = 2.2035; + r[28] = 1.32, mrV[28] = 2.1661; + r[29] = 1.40, mrV[29] = 2.1350; + r[30] = 1.48, mrV[30] = 2.1090; + r[31] = 1.64, mrV[31] = 2.0697; + r[32] = 1.80, mrV[32] = 2.0466; + r[33] = 1.96, mrV[33] = 2.0325; + r[34] = 2.12, mrV[34] = 2.0288; + r[35] = 2.28, mrV[35] = 2.0292; + r[36] = 2.44, mrV[36] = 2.0228; + r[37] = 2.60, mrV[37] = 2.0124; + r[38] = 2.76, mrV[38] = 2.0065; + r[39] = 2.92, mrV[39] = 2.0031; + r[40] = 3.08, mrV[40] = 2.0015; + r[41] = 3.24, mrV[41] = 2.0008; + r[42] = 3.40, mrV[42] = 2.0004; + r[43] = 3.56, mrV[43] = 2.0002; + r[44] = 3.72, mrV[44] = 2.0001; + //-> + + // Now we want to interpolate this potential at any r: + boost::math::interpolators::barycentric_rational<double> b(r.data(), mrV.data(), r.size()); + + for (size_t i = 1; i < 8; ++i) + { + double r = i*0.5; + std::cout << "(r, V) = (" << r << ", " << -b(r)/r << ")\n"; + } +} +//] [/barycentric_rational_example] diff --git a/src/boost/libs/math/example/barycentric_interpolation_example_2.cpp b/src/boost/libs/math/example/barycentric_interpolation_example_2.cpp new file mode 100644 index 000000000..23ba80ad7 --- /dev/null +++ b/src/boost/libs/math/example/barycentric_interpolation_example_2.cpp @@ -0,0 +1,108 @@ + +// Copyright Nick Thompson, 2017 + +// 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). + +#include <iostream> +#include <limits> +#include <map> + +//[barycentric_rational_example2 + +/*`This further example shows how to use the iterator based constructor, and then uses the +function object in our root finding algorithms to locate the points where the potential +achieves a specific value. +*/ + +#include <boost/math/interpolators/barycentric_rational.hpp> +#include <boost/range/adaptors.hpp> +#include <boost/math/tools/roots.hpp> + +int main() +{ + // The lithium potential is given in Kohn's paper, Table I. + // (We could equally easily use an unordered_map, a list of tuples or pairs, or a 2-dimensional array). + std::map<double, double> r; + + r[0.02] = 5.727; + r[0.04] = 5.544; + r[0.06] = 5.450; + r[0.08] = 5.351; + r[0.10] = 5.253; + r[0.12] = 5.157; + r[0.14] = 5.058; + r[0.16] = 4.960; + r[0.18] = 4.862; + r[0.20] = 4.762; + r[0.24] = 4.563; + r[0.28] = 4.360; + r[0.32] = 4.1584; + r[0.36] = 3.9463; + r[0.40] = 3.7360; + r[0.44] = 3.5429; + r[0.48] = 3.3797; + r[0.52] = 3.2417; + r[0.56] = 3.1209; + r[0.60] = 3.0138; + r[0.68] = 2.8342; + r[0.76] = 2.6881; + r[0.84] = 2.5662; + r[0.92] = 2.4242; + r[1.00] = 2.3766; + r[1.08] = 2.3058; + r[1.16] = 2.2458; + r[1.24] = 2.2035; + r[1.32] = 2.1661; + r[1.40] = 2.1350; + r[1.48] = 2.1090; + r[1.64] = 2.0697; + r[1.80] = 2.0466; + r[1.96] = 2.0325; + r[2.12] = 2.0288; + r[2.28] = 2.0292; + r[2.44] = 2.0228; + r[2.60] = 2.0124; + r[2.76] = 2.0065; + r[2.92] = 2.0031; + r[3.08] = 2.0015; + r[3.24] = 2.0008; + r[3.40] = 2.0004; + r[3.56] = 2.0002; + r[3.72] = 2.0001; + + // Let's discover the absissa that will generate a potential of exactly 3.0, + // start by creating 2 ranges for the x and y values: + auto x_range = boost::adaptors::keys(r); + auto y_range = boost::adaptors::values(r); + boost::math::interpolators::barycentric_rational<double> b(x_range.begin(), x_range.end(), y_range.begin()); + // + // We'll use a lambda expression to provide the functor to our root finder, since we want + // the abscissa value that yields 3, not zero. We pass the functor b by value to the + // lambda expression since barycentric_rational is trivial to copy. + // Here we're using simple bisection to find the root: + std::uintmax_t iterations = (std::numeric_limits<std::uintmax_t>::max)(); + double abscissa_3 = boost::math::tools::bisect([=](double x) { return b(x) - 3; }, 0.44, 1.24, boost::math::tools::eps_tolerance<double>(), iterations).first; + std::cout << "Abscissa value that yields a potential of 3 = " << abscissa_3 << std::endl; + std::cout << "Root was found in " << iterations << " iterations." << std::endl; + // + // However, we have a more efficient root finding algorithm than simple bisection: + iterations = (std::numeric_limits<std::uintmax_t>::max)(); + abscissa_3 = boost::math::tools::bracket_and_solve_root([=](double x) { return b(x) - 3; }, 0.6, 1.2, false, boost::math::tools::eps_tolerance<double>(), iterations).first; + std::cout << "Abscissa value that yields a potential of 3 = " << abscissa_3 << std::endl; + std::cout << "Root was found in " << iterations << " iterations." << std::endl; +} +//] [/barycentric_rational_example2] + + +//[barycentric_rational_example2_out +/*` Program output is: +[pre +Abscissa value that yields a potential of 3 = 0.604728 +Root was found in 54 iterations. +Abscissa value that yields a potential of 3 = 0.604728 +Root was found in 10 iterations. +] +*/ +//] diff --git a/src/boost/libs/math/example/bernoulli_example.cpp b/src/boost/libs/math/example/bernoulli_example.cpp new file mode 100644 index 000000000..5a2c58969 --- /dev/null +++ b/src/boost/libs/math/example/bernoulli_example.cpp @@ -0,0 +1,207 @@ +// Copyright Paul A. Bristow 2013. +// Copyright Nakhar Agrawal 2013. +// Copyright John Maddock 2013. +// Copyright Christopher Kormanyos 2013. + +// 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) + +#pragma warning (disable : 4100) // unreferenced formal parameter. +#pragma warning (disable : 4127) // conditional expression is constant. + +//#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error + +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/special_functions/bernoulli.hpp> + +#include <iostream> + +/* First 50 from 2 to 100 inclusive: */ +/* TABLE[N[BernoulliB[n], 200], {n,2,100,2}] */ + +//SC_(0.1666666666666666666666666666666666666666), +//SC_(-0.0333333333333333333333333333333333333333), +//SC_(0.0238095238095238095238095238095238095238), +//SC_(-0.0333333333333333333333333333333333333333), +//SC_(0.0757575757575757575757575757575757575757), +//SC_(-0.2531135531135531135531135531135531135531), +//SC_(1.1666666666666666666666666666666666666666), +//SC_(-7.0921568627450980392156862745098039215686), +//SC_(54.9711779448621553884711779448621553884711), + +int main() +{ + //[bernoulli_example_1 + +/*`A simple example computes the value of B[sub 4] where the return type is `double`, +note that the argument to bernoulli_b2n is ['2] not ['4] since it computes B[sub 2N]. + + +*/ + try + { // It is always wise to use try'n'catch blocks around Boost.Math functions + // so that any informative error messages can be displayed in the catch block. + std::cout + << std::setprecision(std::numeric_limits<double>::digits10) + << boost::math::bernoulli_b2n<double>(2) << std::endl; + +/*`So B[sub 4] == -1/30 == -0.0333333333333333 + +If we use Boost.Multiprecision and its 50 decimal digit floating-point type `cpp_dec_float_50`, +we can calculate the value of much larger numbers like B[sub 200] +and also obtain much higher precision. +*/ + + std::cout + << std::setprecision(std::numeric_limits<boost::multiprecision::cpp_dec_float_50>::digits10) + << boost::math::bernoulli_b2n<boost::multiprecision::cpp_dec_float_50>(100) << std::endl; + +//] //[/bernoulli_example_1] + +//[bernoulli_example_2 +/*`We can compute and save all the float-precision Bernoulli numbers from one call. +*/ + std::vector<float> bn; // Space for 32-bit `float` precision Bernoulli numbers. + + // Start with Bernoulli number 0. + boost::math::bernoulli_b2n<float>(0, 32, std::back_inserter(bn)); // Fill vector with even Bernoulli numbers. + + for(size_t i = 0; i < bn.size(); i++) + { // Show vector of even Bernoulli numbers, showing all significant decimal digits. + std::cout << std::setprecision(std::numeric_limits<float>::digits10) + << i*2 << ' ' + << bn[i] + << std::endl; + } +//] //[/bernoulli_example_2] + + } + catch(const std::exception& ex) + { + std::cout << "Thrown Exception caught: " << ex.what() << std::endl; + } + + +//[bernoulli_example_3 +/*`Of course, for any floating-point type, there is a maximum Bernoulli number that can be computed + before it overflows the exponent. + By default policy, if we try to compute too high a Bernoulli number, an exception will be thrown. +*/ + try + { + std::cout + << std::setprecision(std::numeric_limits<float>::digits10) + << "Bernoulli number " << 33 * 2 <<std::endl; + + std::cout << boost::math::bernoulli_b2n<float>(33) << std::endl; + } + catch (std::exception ex) + { + std::cout << "Thrown Exception caught: " << ex.what() << std::endl; + } + +/*` +and we will get a helpful error message (provided try'n'catch blocks are used). +*/ + +//] //[/bernoulli_example_3] + +//[bernoulli_example_4 +/*For example: +*/ + std::cout << "boost::math::max_bernoulli_b2n<float>::value = " << boost::math::max_bernoulli_b2n<float>::value << std::endl; + std::cout << "Maximum Bernoulli number using float is " << boost::math::bernoulli_b2n<float>( boost::math::max_bernoulli_b2n<float>::value) << std::endl; + std::cout << "boost::math::max_bernoulli_b2n<double>::value = " << boost::math::max_bernoulli_b2n<double>::value << std::endl; + std::cout << "Maximum Bernoulli number using double is " << boost::math::bernoulli_b2n<double>( boost::math::max_bernoulli_b2n<double>::value) << std::endl; + //] //[/bernoulli_example_4] + +//[tangent_example_1 + +/*`We can compute and save a few Tangent numbers. +*/ + std::vector<float> tn; // Space for some `float` precision Tangent numbers. + + // Start with Bernoulli number 0. + boost::math::tangent_t2n<float>(1, 6, std::back_inserter(tn)); // Fill vector with even Tangent numbers. + + for(size_t i = 0; i < tn.size(); i++) + { // Show vector of even Tangent numbers, showing all significant decimal digits. + std::cout << std::setprecision(std::numeric_limits<float>::digits10) + << " " + << tn[i]; + } + std::cout << std::endl; + +//] [/tangent_example_1] + +// 1, 2, 16, 272, 7936, 353792, 22368256, 1903757312 + + + +} // int main() + +/* + +//[bernoulli_output_1 + -3.6470772645191354362138308865549944904868234686191e+215 +//] //[/bernoulli_output_1] + +//[bernoulli_output_2 + + 0 1 + 2 0.166667 + 4 -0.0333333 + 6 0.0238095 + 8 -0.0333333 + 10 0.0757576 + 12 -0.253114 + 14 1.16667 + 16 -7.09216 + 18 54.9712 + 20 -529.124 + 22 6192.12 + 24 -86580.3 + 26 1.42552e+006 + 28 -2.72982e+007 + 30 6.01581e+008 + 32 -1.51163e+010 + 34 4.29615e+011 + 36 -1.37117e+013 + 38 4.88332e+014 + 40 -1.92966e+016 + 42 8.41693e+017 + 44 -4.03381e+019 + 46 2.11507e+021 + 48 -1.20866e+023 + 50 7.50087e+024 + 52 -5.03878e+026 + 54 3.65288e+028 + 56 -2.84988e+030 + 58 2.38654e+032 + 60 -2.14e+034 + 62 2.0501e+036 +//] //[/bernoulli_output_2] + +//[bernoulli_output_3 + Bernoulli number 66 + Thrown Exception caught: Error in function boost::math::bernoulli_b2n<float>(n): + Overflow evaluating function at 33 +//] //[/bernoulli_output_3] +//[bernoulli_output_4 + boost::math::max_bernoulli_b2n<float>::value = 32 + Maximum Bernoulli number using float is -2.0938e+038 + boost::math::max_bernoulli_b2n<double>::value = 129 + Maximum Bernoulli number using double is 1.33528e+306 +//] //[/bernoulli_output_4] + + +//[tangent_output_1 + 1 2 16 272 7936 353792 +//] [/tangent_output_1] + + + +*/ + + diff --git a/src/boost/libs/math/example/bessel_errors_example.cpp b/src/boost/libs/math/example/bessel_errors_example.cpp new file mode 100644 index 000000000..1b7729269 --- /dev/null +++ b/src/boost/libs/math/example/bessel_errors_example.cpp @@ -0,0 +1,171 @@ +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <exception> + +// Weisstein, Eric W. "Bessel Function Zeros." From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/BesselFunctionZeros.html +// Test values can be calculated using [@wolframalpha.com WolframAplha] +// See also http://dlmf.nist.gov/10.21 + +//[bessel_errors_example_1 + +/*`[h5 Error messages from 'bad' input] + +Another example demonstrates calculating zeros of the Bessel functions +showing the error messages from 'bad' input is handled by throwing exceptions. + +To use the functions for finding zeros of the functions we need: +*/ + #include <boost/math/special_functions/bessel.hpp> + #include <boost/math/special_functions/airy.hpp> + +//] [/bessel_errors_example_1] + +int main() +{ +//[bessel_errors_example_2 + +/*`[tip It is always wise to place all code using Boost.Math inside try'n'catch blocks; +this will ensure that helpful error messages can be shown when exceptional conditions arise.] + +Examples below show messages from several 'bad' arguments that throw a `domain_error` exception. +*/ + try + { // Try a zero order v. + float dodgy_root = boost::math::cyl_bessel_j_zero(0.F, 0); + std::cout << "boost::math::cyl_bessel_j_zero(0.F, 0) " << dodgy_root << std::endl; + // Thrown exception Error in function boost::math::cyl_bessel_j_zero<double>(double, int): + // Requested the 0'th zero of J0, but the rank must be > 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + +/*`[note The type shown in the error message is the type [*after promotion], +using __precision_policy and __promotion_policy, from `float` to `double` in this case.] + +In this example the promotion goes: + +# Arguments are `float` and `int`. +# Treat `int` "as if" it were a `double`, so arguments are `float` and `double`. +# Common type is `double` - so that's the precision we want (and the type that will be returned). +# Evaluate internally as `double` for full `float` precision. + +See full code for other examples that promote from `double` to `long double`. + +Other examples of 'bad' inputs like infinity and NaN are below. +Some compiler warnings indicate that 'bad' values are detected at compile time. +*/ + + try + { // order v = inf + std::cout << "boost::math::cyl_bessel_j_zero(inf, 1) " << std::endl; + double inf = std::numeric_limits<double>::infinity(); + double inf_root = boost::math::cyl_bessel_j_zero(inf, 1); + std::cout << "boost::math::cyl_bessel_j_zero(inf, 1) " << inf_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, unsigned): + // Order argument is 1.#INF, but must be finite >= 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // order v = NaN, rank m = 1 + std::cout << "boost::math::cyl_bessel_j_zero(nan, 1) " << std::endl; + double nan = std::numeric_limits<double>::quiet_NaN(); + double nan_root = boost::math::cyl_bessel_j_zero(nan, 1); + std::cout << "boost::math::cyl_bessel_j_zero(nan, 1) " << nan_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, unsigned): + // Order argument is 1.#QNAN, but must be finite >= 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + +/*`The output from other examples are shown appended to the full code listing. +*/ +//] [/bessel_errors_example_2] + try + { // Try a zero rank m. + std::cout << "boost::math::cyl_neumann_zero(0.0, 0) " << std::endl; + double dodgy_root = boost::math::cyl_bessel_j_zero(0.0, 0); + // warning C4146: unary minus operator applied to unsigned type, result still unsigned. + std::cout << "boost::math::cyl_neumann_zero(0.0, -1) " << dodgy_root << std::endl; + // boost::math::cyl_neumann_zero(0.0, -1) 6.74652e+009 + // This *should* fail because m is unreasonably large. + + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // m = inf + std::cout << "boost::math::cyl_bessel_j_zero(0.0, inf) " << std::endl; + double inf = std::numeric_limits<double>::infinity(); + double inf_root = boost::math::cyl_bessel_j_zero(0.0, inf); + // warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data. + std::cout << "boost::math::cyl_bessel_j_zero(0.0, inf) " << inf_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): + // Requested the 0'th zero, but must be > 0 ! + + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // m = NaN + double nan = std::numeric_limits<double>::quiet_NaN(); + double nan_root = boost::math::airy_ai_zero<double>(nan); + // warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data. + std::cout << "boost::math::airy_ai_zero<double>(nan) " << nan_root << std::endl; + // Thrown exception Error in function boost::math::airy_ai_zero<double>(double,double): + // The requested rank of the zero is 0, but must be 1 or more ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + } // int main() + +/* +Output: + + Description: Autorun "J:\Cpp\big_number\Debug\bessel_errors_example.exe" + Thrown exception Error in function boost::math::cyl_bessel_j_zero<double>(double, int): Requested the 0'th zero of J0, but the rank must be > 0 ! + boost::math::cyl_bessel_j_zero(inf, 1) + Thrown exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Order argument is 1.#INF, but must be finite >= 0 ! + boost::math::cyl_bessel_j_zero(nan, 1) + Thrown exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Order argument is 1.#QNAN, but must be finite >= 0 ! + boost::math::cyl_neumann_zero(0.0, 0) + Thrown exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Requested the 0'th zero of J0, but the rank must be > 0 ! + boost::math::cyl_bessel_j_zero(0.0, inf) + Thrown exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Requested the -2147483648'th zero, but the rank must be positive ! + Thrown exception Error in function boost::math::airy_ai_zero<double>(double,double): The requested rank of the zero is 0, but must be 1 or more ! + + +*/ + diff --git a/src/boost/libs/math/example/bessel_zeros_example.cpp b/src/boost/libs/math/example/bessel_zeros_example.cpp new file mode 100644 index 000000000..0d3ec3ccc --- /dev/null +++ b/src/boost/libs/math/example/bessel_zeros_example.cpp @@ -0,0 +1,447 @@ +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> + +// Weisstein, Eric W. "Bessel Function Zeros." From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/BesselFunctionZeros.html +// Test values can be calculated using [@wolframalpha.com WolframAplha] +// See also http://dlmf.nist.gov/10.21 + +//[bessel_zero_example_1 + +/*`This example demonstrates calculating zeros of the Bessel, Neumann and Airy functions. +It also shows how Boost.Math and Boost.Multiprecision can be combined to provide +a many decimal digit precision. For 50 decimal digit precision we need to include +*/ + + #include <boost/multiprecision/cpp_dec_float.hpp> + +/*`and a `typedef` for `float_type` may be convenient +(allowing a quick switch to re-compute at built-in `double` or other precision) +*/ + typedef boost::multiprecision::cpp_dec_float_50 float_type; + +//`To use the functions for finding zeros of the functions we need + + #include <boost/math/special_functions/bessel.hpp> + +//`This file includes the forward declaration signatures for the zero-finding functions: + +// #include <boost/math/special_functions/math_fwd.hpp> + +/*`but more details are in the full documentation, for example at +[@http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/bessel/bessel_over.html Boost.Math Bessel functions] +*/ + +/*`This example shows obtaining both a single zero of the Bessel function, +and then placing multiple zeros into a container like `std::vector` by providing an iterator. +The signature of the single value function is: + + template <class T> + inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type + cyl_bessel_j_zero(T v, // Floating-point value for Jv. + int m); // start index. + +The result type is controlled by the floating-point type of parameter `v` +(but subject to the usual __precision_policy and __promotion_policy). + +The signature of multiple zeros function is: + + template <class T, class OutputIterator> + inline OutputIterator cyl_bessel_j_zero(T v, // Floating-point value for Jv. + int start_index, // 1-based start index. + unsigned number_of_zeros, + OutputIterator out_it); // iterator into container for zeros. + +There is also a version which allows control of the __policy_section for error handling and precision. + + template <class T, class OutputIterator, class Policy> + inline OutputIterator cyl_bessel_j_zero(T v, // Floating-point value for Jv. + int start_index, // 1-based start index. + unsigned number_of_zeros, + OutputIterator out_it, + const Policy& pol); // iterator into container for zeros. + +*/ +//] [/bessel_zero_example_1] + +//[bessel_zero_example_iterator_1] +/*`We use the `cyl_bessel_j_zero` output iterator parameter `out_it` +to create a sum of 1/zeros[super 2] by defining a custom output iterator: +*/ + +template <class T> +struct output_summation_iterator +{ + output_summation_iterator(T* p) : p_sum(p) + {} + output_summation_iterator& operator*() + { return *this; } + output_summation_iterator& operator++() + { return *this; } + output_summation_iterator& operator++(int) + { return *this; } + output_summation_iterator& operator = (T const& val) + { + *p_sum += 1./ (val * val); // Summing 1/zero^2. + return *this; + } +private: + T* p_sum; +}; + + +//] [/bessel_zero_example_iterator_1] + +int main() +{ + try + { +//[bessel_zero_example_2] + +/*`[tip It is always wise to place code using Boost.Math inside try'n'catch blocks; +this will ensure that helpful error messages can be shown when exceptional conditions arise.] + +First, evaluate a single Bessel zero. + +The precision is controlled by the float-point type of template parameter `T` of `v` +so this example has `double` precision, at least 15 but up to 17 decimal digits (for the common 64-bit double). +*/ + double root = boost::math::cyl_bessel_j_zero(0.0, 1); + // Displaying with default precision of 6 decimal digits: + std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1) " << root << std::endl; // 2.40483 + // And with all the guaranteed (15) digits: + std::cout.precision(std::numeric_limits<double>::digits10); + std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1) " << root << std::endl; // 2.40482555769577 +/*`But note that because the parameter `v` controls the precision of the result, +`v` [*must be a floating-point type]. +So if you provide an integer type, say 0, rather than 0.0, then it will fail to compile thus: +`` + root = boost::math::cyl_bessel_j_zero(0, 1); +`` +with this error message +`` + error C2338: Order must be a floating-point type. +`` + +Optionally, we can use a policy to ignore errors, C-style, returning some value +perhaps infinity or NaN, or the best that can be done. (See __user_error_handling). + +To create a (possibly unwise!) policy that ignores all errors: +*/ + + typedef boost::math::policies::policy + < + boost::math::policies::domain_error<boost::math::policies::ignore_error>, + boost::math::policies::overflow_error<boost::math::policies::ignore_error>, + boost::math::policies::underflow_error<boost::math::policies::ignore_error>, + boost::math::policies::denorm_error<boost::math::policies::ignore_error>, + boost::math::policies::pole_error<boost::math::policies::ignore_error>, + boost::math::policies::evaluation_error<boost::math::policies::ignore_error> + > ignore_all_policy; + + double inf = std::numeric_limits<double>::infinity(); + double nan = std::numeric_limits<double>::quiet_NaN(); + + std::cout << "boost::math::cyl_bessel_j_zero(-1.0, 0) " << std::endl; + double dodgy_root = boost::math::cyl_bessel_j_zero(-1.0, 0, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(-1.0, 1) " << dodgy_root << std::endl; // 1.#QNAN + double inf_root = boost::math::cyl_bessel_j_zero(inf, 1, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(inf, 1) " << inf_root << std::endl; // 1.#QNAN + double nan_root = boost::math::cyl_bessel_j_zero(nan, 1, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(nan, 1) " << nan_root << std::endl; // 1.#QNAN + +/*`Another version of `cyl_bessel_j_zero` allows calculation of multiple zeros with one call, +placing the results in a container, often `std::vector`. +For example, generate five `double` roots of J[sub v] for integral order 2. + +showing the same results as column J[sub 2](x) in table 1 of +[@ http://mathworld.wolfram.com/BesselFunctionZeros.html Wolfram Bessel Function Zeros]. + +*/ + unsigned int n_roots = 5U; + std::vector<double> roots; + boost::math::cyl_bessel_j_zero(2.0, 1, n_roots, std::back_inserter(roots)); + std::copy(roots.begin(), + roots.end(), + std::ostream_iterator<double>(std::cout, "\n")); + +/*`Or generate 50 decimal digit roots of J[sub v] for non-integral order `v = 71/19`. + +We set the precision of the output stream and show trailing zeros to display a fixed 50 decimal digits. +*/ + std::cout.precision(std::numeric_limits<float_type>::digits10); // 50 decimal digits. + std::cout << std::showpoint << std::endl; // Show trailing zeros. + + float_type x = float_type(71) / 19; + float_type r = boost::math::cyl_bessel_j_zero(x, 1); // 1st root. + std::cout << "x = " << x << ", r = " << r << std::endl; + + r = boost::math::cyl_bessel_j_zero(x, 20U); // 20th root. + std::cout << "x = " << x << ", r = " << r << std::endl; + + std::vector<float_type> zeros; + boost::math::cyl_bessel_j_zero(x, 1, 3, std::back_inserter(zeros)); + + std::cout << "cyl_bessel_j_zeros" << std::endl; + // Print the roots to the output stream. + std::copy(zeros.begin(), zeros.end(), + std::ostream_iterator<float_type>(std::cout, "\n")); + +/*`The Neumann function zeros are evaluated very similarly: +*/ + using boost::math::cyl_neumann_zero; + + double zn = cyl_neumann_zero(2., 1); + + std::cout << "cyl_neumann_zero(2., 1) = " << std::endl; + //double zn0 = zn; + // std::cout << "zn0 = " << std::endl; + // std::cout << zn0 << std::endl; + // + std::cout << zn << std::endl; + // std::cout << cyl_neumann_zero(2., 1) << std::endl; + + std::vector<float> nzeros(3); // Space for 3 zeros. + cyl_neumann_zero<float>(2.F, 1, nzeros.size(), nzeros.begin()); + + std::cout << "cyl_neumann_zero<float>(2.F, 1, " << std::endl; + // Print the zeros to the output stream. + std::copy(nzeros.begin(), nzeros.end(), + std::ostream_iterator<float>(std::cout, "\n")); + + std::cout << cyl_neumann_zero(static_cast<float_type>(220)/100, 1) << std::endl; + // 3.6154383428745996706772556069431792744372398748422 + +/*`Finally we show how the output iterator can be used to compute a sum of zeros. + +(See [@https://doi.org/10.1017/S2040618500034067 Ian N. Sneddon, Infinite Sums of Bessel Zeros], +page 150 equation 40). +*/ +//] [/bessel_zero_example_2] + + { +//[bessel_zero_example_iterator_2] +/*`The sum is calculated for many values, converging on the analytical exact value of `1/8`. +*/ + using boost::math::cyl_bessel_j_zero; + double nu = 1.; + double sum = 0; + output_summation_iterator<double> it(&sum); // sum of 1/zeros^2 + cyl_bessel_j_zero(nu, 1, 10000, it); + + double s = 1/(4 * (nu + 1)); // 0.125 = 1/8 is exact analytical solution. + std::cout << std::setprecision(6) << "nu = " << nu << ", sum = " << sum + << ", exact = " << s << std::endl; + // nu = 1.00000, sum = 0.124990, exact = 0.125000 +//] [/bessel_zero_example_iterator_2] + } + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + +//[bessel_zero_example_iterator_3] + +/*`Examples below show effect of 'bad' arguments that throw a `domain_error` exception. +*/ + try + { // Try a negative rank m. + std::cout << "boost::math::cyl_bessel_j_zero(-1.F, -1) " << std::endl; + float dodgy_root = boost::math::cyl_bessel_j_zero(-1.F, -1); + std::cout << "boost::math::cyl_bessel_j_zero(-1.F, -1) " << dodgy_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<double>(double, int): + // Order argument is -1, but must be >= 0 ! + } + catch (std::exception& ex) + { + std::cout << "Throw exception " << ex.what() << std::endl; + } + +/*`[note The type shown is the type [*after promotion], +using __precision_policy and __promotion_policy, from `float` to `double` in this case.] + +In this example the promotion goes: + +# Arguments are `float` and `int`. +# Treat `int` "as if" it were a `double`, so arguments are `float` and `double`. +# Common type is `double` - so that's the precision we want (and the type that will be returned). +# Evaluate internally as `long double` for full `double` precision. + +See full code for other examples that promote from `double` to `long double`. + +*/ + +//] [/bessel_zero_example_iterator_3] + try + { // order v = inf + std::cout << "boost::math::cyl_bessel_j_zero(infF, 1) " << std::endl; + float infF = std::numeric_limits<float>::infinity(); + float inf_root = boost::math::cyl_bessel_j_zero(infF, 1); + std::cout << "boost::math::cyl_bessel_j_zero(infF, 1) " << inf_root << std::endl; + // boost::math::cyl_bessel_j_zero(-1.F, -1) + //Thrown exception Error in function boost::math::cyl_bessel_j_zero<double>(double, int): + // Requested the -1'th zero, but the rank must be positive ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + try + { // order v = inf + double inf = std::numeric_limits<double>::infinity(); + double inf_root = boost::math::cyl_bessel_j_zero(inf, 1); + std::cout << "boost::math::cyl_bessel_j_zero(inf, 1) " << inf_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, unsigned): + // Order argument is 1.#INF, but must be finite >= 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // order v = NaN + double nan = std::numeric_limits<double>::quiet_NaN(); + double nan_root = boost::math::cyl_bessel_j_zero(nan, 1); + std::cout << "boost::math::cyl_bessel_j_zero(nan, 1) " << nan_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, unsigned): + // Order argument is 1.#QNAN, but must be finite >= 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // Try a negative m. + double dodgy_root = boost::math::cyl_bessel_j_zero(0.0, -1); + // warning C4146: unary minus operator applied to unsigned type, result still unsigned. + std::cout << "boost::math::cyl_bessel_j_zero(0.0, -1) " << dodgy_root << std::endl; + // boost::math::cyl_bessel_j_zero(0.0, -1) 6.74652e+009 + // This *should* fail because m is unreasonably large. + + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // m = inf + double inf = std::numeric_limits<double>::infinity(); + double inf_root = boost::math::cyl_bessel_j_zero(0.0, inf); + // warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data. + std::cout << "boost::math::cyl_bessel_j_zero(0.0, inf) " << inf_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): + // Requested the 0'th zero, but must be > 0 ! + + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + try + { // m = NaN + std::cout << "boost::math::cyl_bessel_j_zero(0.0, nan) " << std::endl ; + double nan = std::numeric_limits<double>::quiet_NaN(); + double nan_root = boost::math::cyl_bessel_j_zero(0.0, nan); + // warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data. + std::cout << nan_root << std::endl; + // Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): + // Requested the 0'th zero, but must be > 0 ! + } + catch (std::exception& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + } // int main() + +/* +Mathematica: Table[N[BesselJZero[71/19, n], 50], {n, 1, 20, 1}] + +7.2731751938316489503185694262290765588963196701623 +10.724858308883141732536172745851416647110749599085 +14.018504599452388106120459558042660282427471931581 +17.25249845917041718216248716654977734919590383861 +20.456678874044517595180234083894285885460502077814 +23.64363089714234522494551422714731959985405172504 +26.819671140255087745421311470965019261522390519297 +29.988343117423674742679141796661432043878868194142 +33.151796897690520871250862469973445265444791966114 +36.3114160002162074157243540350393860813165201842 +39.468132467505236587945197808083337887765967032029 +42.622597801391236474855034831297954018844433480227 +45.775281464536847753390206207806726581495950012439 +48.926530489173566198367766817478553992471739894799 +52.076607045343002794279746041878924876873478063472 +55.225712944912571393594224327817265689059002890192 +58.374006101538886436775188150439025201735151418932 +61.521611873000965273726742659353136266390944103571 +64.66863105379093036834648221487366079456596628716 +67.815145619696290925556791375555951165111460585458 + +Mathematica: Table[N[BesselKZero[2, n], 50], {n, 1, 5, 1}] +n | +1 | 3.3842417671495934727014260185379031127323883259329 +2 | 6.7938075132682675382911671098369487124493222183854 +3 | 10.023477979360037978505391792081418280789658279097 + + +*/ + + /* +[bessel_zero_output] + + boost::math::cyl_bessel_j_zero(0.0, 1) 2.40483 + boost::math::cyl_bessel_j_zero(0.0, 1) 2.40482555769577 + boost::math::cyl_bessel_j_zero(-1.0, 1) 1.#QNAN + boost::math::cyl_bessel_j_zero(inf, 1) 1.#QNAN + boost::math::cyl_bessel_j_zero(nan, 1) 1.#QNAN + 5.13562230184068 + 8.41724414039986 + 11.6198411721491 + 14.7959517823513 + 17.9598194949878 + + x = 3.7368421052631578947368421052631578947368421052632, r = 7.2731751938316489503185694262290765588963196701623 + x = 3.7368421052631578947368421052631578947368421052632, r = 67.815145619696290925556791375555951165111460585458 + 7.2731751938316489503185694262290765588963196701623 + 10.724858308883141732536172745851416647110749599085 + 14.018504599452388106120459558042660282427471931581 + cyl_neumann_zero(2., 1) = 3.3842417671495935000000000000000000000000000000000 + 3.3842418193817139000000000000000000000000000000000 + 6.7938075065612793000000000000000000000000000000000 + 10.023477554321289000000000000000000000000000000000 + 3.6154383428745996706772556069431792744372398748422 + nu = 1.00000, sum = 0.124990, exact = 0.125000 + Throw exception Error in function boost::math::cyl_bessel_j_zero<double>(double, int): Order argument is -1, but must be >= 0 ! + Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Order argument is 1.#INF, but must be finite >= 0 ! + Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Order argument is 1.#QNAN, but must be finite >= 0 ! + Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Requested the -1'th zero, but must be > 0 ! + Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Requested the -2147483648'th zero, but must be > 0 ! + Throw exception Error in function boost::math::cyl_bessel_j_zero<long double>(long double, int): Requested the -2147483648'th zero, but must be > 0 ! + + +] [/bessel_zero_output] +*/ + diff --git a/src/boost/libs/math/example/bessel_zeros_example_1.cpp b/src/boost/libs/math/example/bessel_zeros_example_1.cpp new file mode 100644 index 000000000..59172cd02 --- /dev/null +++ b/src/boost/libs/math/example/bessel_zeros_example_1.cpp @@ -0,0 +1,213 @@ + +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> + +// Weisstein, Eric W. "Bessel Function Zeros." From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/BesselFunctionZeros.html +// Test values can be calculated using [@wolframalpha.com WolframAplha] +// See also http://dlmf.nist.gov/10.21 + +//[bessel_zeros_example_1 + +/*`This example demonstrates calculating zeros of the Bessel and Neumann functions. +It also shows how Boost.Math and Boost.Multiprecision can be combined to provide +a many decimal digit precision. For 50 decimal digit precision we need to include +*/ + + #include <boost/multiprecision/cpp_dec_float.hpp> + +/*`and a `typedef` for `float_type` may be convenient +(allowing a quick switch to re-compute at built-in `double` or other precision) +*/ + typedef boost::multiprecision::cpp_dec_float_50 float_type; + +//`To use the functions for finding zeros of the functions we need + + #include <boost/math/special_functions/bessel.hpp> + +//`This file includes the forward declaration signatures for the zero-finding functions: + +// #include <boost/math/special_functions/math_fwd.hpp> + +/*`but more details are in the full documentation, for example at +[@http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/bessel/bessel_over.html Boost.Math Bessel functions]. +*/ + +/*`This example shows obtaining both a single zero of the Bessel function, +and then placing multiple zeros into a container like `std::vector` by providing an iterator. +*/ +//] [/bessel_zeros_example_1] + +/*The signature of the single value function is: + + template <class T> + inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type + cyl_bessel_j_zero( + T v, // Floating-point value for Jv. + int m); // start index. + +The result type is controlled by the floating-point type of parameter `v` +(but subject to the usual __precision_policy and __promotion_policy). + +The signature of multiple zeros function is: + + template <class T, class OutputIterator> + inline OutputIterator cyl_bessel_j_zero( + T v, // Floating-point value for Jv. + int start_index, // 1-based start index. + unsigned number_of_zeros, // How many zeros to generate + OutputIterator out_it); // Destination for zeros. + +There is also a version which allows control of the __policy_section for error handling and precision. + + template <class T, class OutputIterator, class Policy> + inline OutputIterator cyl_bessel_j_zero( + T v, // Floating-point value for Jv. + int start_index, // 1-based start index. + unsigned number_of_zeros, // How many zeros to generate + OutputIterator out_it, // Destination for zeros. + const Policy& pol); // Policy to use. +*/ + +int main() +{ + try + { +//[bessel_zeros_example_2 + +/*`[tip It is always wise to place code using Boost.Math inside try'n'catch blocks; +this will ensure that helpful error messages are shown when exceptional conditions arise.] + +First, evaluate a single Bessel zero. + +The precision is controlled by the float-point type of template parameter `T` of `v` +so this example has `double` precision, at least 15 but up to 17 decimal digits (for the common 64-bit double). +*/ +// double root = boost::math::cyl_bessel_j_zero(0.0, 1); +// // Displaying with default precision of 6 decimal digits: +// std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1) " << root << std::endl; // 2.40483 +// // And with all the guaranteed (15) digits: +// std::cout.precision(std::numeric_limits<double>::digits10); +// std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1) " << root << std::endl; // 2.40482555769577 +/*`But note that because the parameter `v` controls the precision of the result, +`v` [*must be a floating-point type]. +So if you provide an integer type, say 0, rather than 0.0, then it will fail to compile thus: +`` + root = boost::math::cyl_bessel_j_zero(0, 1); +`` +with this error message +`` + error C2338: Order must be a floating-point type. +`` + +Optionally, we can use a policy to ignore errors, C-style, returning some value, +perhaps infinity or NaN, or the best that can be done. (See __user_error_handling). + +To create a (possibly unwise!) policy `ignore_all_policy` that ignores all errors: +*/ + + typedef boost::math::policies::policy< + boost::math::policies::domain_error<boost::math::policies::ignore_error>, + boost::math::policies::overflow_error<boost::math::policies::ignore_error>, + boost::math::policies::underflow_error<boost::math::policies::ignore_error>, + boost::math::policies::denorm_error<boost::math::policies::ignore_error>, + boost::math::policies::pole_error<boost::math::policies::ignore_error>, + boost::math::policies::evaluation_error<boost::math::policies::ignore_error> + > ignore_all_policy; + //`Examples of use of this `ignore_all_policy` are + + double inf = std::numeric_limits<double>::infinity(); + double nan = std::numeric_limits<double>::quiet_NaN(); + + double dodgy_root = boost::math::cyl_bessel_j_zero(-1.0, 1, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(-1.0, 1) " << dodgy_root << std::endl; // 1.#QNAN + double inf_root = boost::math::cyl_bessel_j_zero(inf, 1, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(inf, 1) " << inf_root << std::endl; // 1.#QNAN + double nan_root = boost::math::cyl_bessel_j_zero(nan, 1, ignore_all_policy()); + std::cout << "boost::math::cyl_bessel_j_zero(nan, 1) " << nan_root << std::endl; // 1.#QNAN + +/*`Another version of `cyl_bessel_j_zero` allows calculation of multiple zeros with one call, +placing the results in a container, often `std::vector`. +For example, generate and display the first five `double` roots of J[sub v] for integral order 2, +as column ['J[sub 2](x)] in table 1 of +[@ http://mathworld.wolfram.com/BesselFunctionZeros.html Wolfram Bessel Function Zeros]. +*/ + unsigned int n_roots = 5U; + std::vector<double> roots; + boost::math::cyl_bessel_j_zero(2.0, 1, n_roots, std::back_inserter(roots)); + std::copy(roots.begin(), + roots.end(), + std::ostream_iterator<double>(std::cout, "\n")); + +/*`Or we can use Boost.Multiprecision to generate 50 decimal digit roots of ['J[sub v]] +for non-integral order `v= 71/19 == 3.736842`, expressed as an exact-integer fraction +to generate the most accurate value possible for all floating-point types. + +We set the precision of the output stream, and show trailing zeros to display a fixed 50 decimal digits. +*/ + std::cout.precision(std::numeric_limits<float_type>::digits10); // 50 decimal digits. + std::cout << std::showpoint << std::endl; // Show trailing zeros. + + float_type x = float_type(71) / 19; + float_type r = boost::math::cyl_bessel_j_zero(x, 1); // 1st root. + std::cout << "x = " << x << ", r = " << r << std::endl; + + r = boost::math::cyl_bessel_j_zero(x, 20U); // 20th root. + std::cout << "x = " << x << ", r = " << r << std::endl; + + std::vector<float_type> zeros; + boost::math::cyl_bessel_j_zero(x, 1, 3, std::back_inserter(zeros)); + + std::cout << "cyl_bessel_j_zeros" << std::endl; + // Print the roots to the output stream. + std::copy(zeros.begin(), zeros.end(), + std::ostream_iterator<float_type>(std::cout, "\n")); +//] [/bessel_zeros_example_2] + } + catch (std::exception const& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + + } // int main() + + /* + + Output: + + Description: Autorun "J:\Cpp\big_number\Debug\bessel_zeros_example_1.exe" + boost::math::cyl_bessel_j_zero(-1.0, 1) 3.83171 + boost::math::cyl_bessel_j_zero(inf, 1) 1.#QNAN + boost::math::cyl_bessel_j_zero(nan, 1) 1.#QNAN + 5.13562 + 8.41724 + 11.6198 + 14.796 + 17.9598 + + x = 3.7368421052631578947368421052631578947368421052632, r = 7.2731751938316489503185694262290765588963196701623 + x = 3.7368421052631578947368421052631578947368421052632, r = 67.815145619696290925556791375555951165111460585458 + cyl_bessel_j_zeros + 7.2731751938316489503185694262290765588963196701623 + 10.724858308883141732536172745851416647110749599085 + 14.018504599452388106120459558042660282427471931581 + +*/ + diff --git a/src/boost/libs/math/example/bessel_zeros_interator_example.cpp b/src/boost/libs/math/example/bessel_zeros_interator_example.cpp new file mode 100644 index 000000000..a92a2704a --- /dev/null +++ b/src/boost/libs/math/example/bessel_zeros_interator_example.cpp @@ -0,0 +1,88 @@ +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> + +//[bessel_zeros_iterator_example_1 + +/*`[h5 Using Output Iterator to sum zeros of Bessel Functions] + +This example demonstrates summing zeros of the Bessel functions. +To use the functions for finding zeros of the functions we need + */ + +#include <boost/math/special_functions/bessel.hpp> + +/*`We use the `cyl_bessel_j_zero` output iterator parameter `out_it` +to create a sum of ['1/zeros[super 2]] by defining a custom output iterator: +*/ + +template <class T> +struct output_summation_iterator +{ + output_summation_iterator(T* p) : p_sum(p) + {} + output_summation_iterator& operator*() + { return *this; } + output_summation_iterator& operator++() + { return *this; } + output_summation_iterator& operator++(int) + { return *this; } + output_summation_iterator& operator = (T const& val) + { + *p_sum += 1./ (val * val); // Summing 1/zero^2. + return *this; + } +private: + T* p_sum; +}; + +//] [/bessel_zeros_iterator_example_1] + +int main() +{ + try + { +//[bessel_zeros_iterator_example_2 + +/*`The sum is calculated for many values, converging on the analytical exact value of `1/8`. +*/ + using boost::math::cyl_bessel_j_zero; + double nu = 1.; + double sum = 0; + output_summation_iterator<double> it(&sum); // sum of 1/zeros^2 + cyl_bessel_j_zero(nu, 1, 10000, it); + + double s = 1/(4 * (nu + 1)); // 0.125 = 1/8 is exact analytical solution. + std::cout << std::setprecision(6) << "nu = " << nu << ", sum = " << sum + << ", exact = " << s << std::endl; + // nu = 1.00000, sum = 0.124990, exact = 0.125000 +//] [/bessel_zeros_iterator_example_2] + } + catch (std::exception const& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } + return 0; + } // int_main() + +/* + Output: + + nu = 1, sum = 0.12499, exact = 0.125 +*/ diff --git a/src/boost/libs/math/example/big_seventh.cpp b/src/boost/libs/math/example/big_seventh.cpp new file mode 100644 index 000000000..bf9835afb --- /dev/null +++ b/src/boost/libs/math/example/big_seventh.cpp @@ -0,0 +1,203 @@ +// 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) + +// Copyright Paul A. Bristow 2019. +// Copyright Christopher Kormanyos 2012. +// Copyright John Maddock 2012. + +// This file is written to be included from a Quickbook .qbk document. +// It can be compiled by the C++ compiler, and run. Any output can +// also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +#ifdef _MSC_VER +#pragma warning(disable : 4512) // assignment operator could not be generated. +#pragma warning(disable : 4996) +#endif + +//[big_seventh_example_1 + +/*`[h5 Using Boost.Multiprecision `cpp_float` types for numerical calculations with higher precision than built-in `long double`.] + +The Boost.Multiprecision library can be used for computations requiring precision +exceeding that of standard built-in types such as `float`, `double` +and `long double`. For extended-precision calculations, Boost.Multiprecision +supplies several template data types called `cpp_bin_float_`. + +The number of decimal digits of precision is fixed at compile-time via template parameter. + +To use these floating-point types and +[@https://www.boost.org/doc/libs/release/libs/math/doc/html/constants.html Boost.Math collection of high-precision constants], +we need some includes: +*/ + +#include <boost/math/constants/constants.hpp> + +#include <boost/multiprecision/cpp_bin_float.hpp> +// that includes some predefined typedefs that can be used thus: +// using boost::multiprecision::cpp_bin_float_quad; +// using boost::multiprecision::cpp_bin_float_50; +// using boost::multiprecision::cpp_bin_float_100; + +#include <iostream> +#include <limits> +#include <type_traits> + +/*` So now we can demonstrate with some trivial calculations: +*/ + +//] //[big_seventh_example_1] + +void no_et() +{ + using namespace boost::multiprecision; + + std::cout.setf(std::ios_base::boolalpha); + + typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, std::int16_t, -16382, 16383>, et_on> cpp_bin_float_quad_et_on; + typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, std::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad_et_off; + + typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, std::int16_t, -16382, 16383>, et_off> cpp_bin_float_oct; + + + cpp_bin_float_quad x("42."); + std::cout << "cpp_bin_float_quad x = " << x << std::endl; + + cpp_bin_float_quad_et_on q("42."); + + std::cout << "std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_off>::value is " << std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_off>::value << std::endl; + std::cout << "std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_on>::value is " << std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_on>::value << std::endl; + + std::cout << "cpp_bin_float_quad_et_on q = " << q << std::endl; + cpp_bin_float_50 y("42."); // typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50; + + std::cout << "cpp_bin_float_50 y = " << y << std::endl; + + typedef number<backends::cpp_bin_float<50>, et_off > cpp_bin_float_50_no_et; + typedef number<backends::cpp_bin_float<50>, et_on > cpp_bin_float_50_et; + + cpp_bin_float_50_no_et z("42."); // typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50; + + std::cout << "cpp_bin_float_50_no_et z = " << z << std::endl; + + std::cout << " std::is_same<cpp_bin_float_50, cpp_bin_float_50_no_et>::value is " << std::is_same<cpp_bin_float_50, cpp_bin_float_50_no_et>::value << std::endl; + std::cout << " std::is_same<cpp_bin_float_50_et, cpp_bin_float_50_no_et>::value is " << std::is_same<cpp_bin_float_50_et, cpp_bin_float_50_no_et>::value << std::endl; + +} // void no_et() + +int main() +{ + + no_et(); + + return 0; + + + //[big_seventh_example_2 + /*`Using `typedef cpp_bin_float_50` hides the complexity of multiprecision, +allows us to define variables with 50 decimal digit precision just like built-in `double`. +*/ + using boost::multiprecision::cpp_bin_float_50; + + cpp_bin_float_50 seventh = cpp_bin_float_50(1) / 7; // 1 / 7 + + /*`By default, output would only show the standard 6 decimal digits, + so set precision to show all 50 significant digits, including any trailing zeros. +*/ + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); + std::cout << std::showpoint << std::endl; // Append any trailing zeros. + std::cout << seventh << std::endl; + /*`which outputs: + + 0.14285714285714285714285714285714285714285714285714 + +We can also use __math_constants like [pi], +guaranteed to be initialized with the very last bit of precision (__ULP) for the floating-point type. +*/ + std::cout << "pi = " << boost::math::constants::pi<cpp_bin_float_50>() << std::endl; + cpp_bin_float_50 circumference = boost::math::constants::pi<cpp_bin_float_50>() * 2 * seventh; + std::cout << "c = " << circumference << std::endl; + + /*`which outputs + + pi = 3.1415926535897932384626433832795028841971693993751 + + c = 0.89759790102565521098932668093700082405633411410717 +*/ + //] [/big_seventh_example_2] + + //[big_seventh_example_3 + /*`So using `cpp_bin_float_50` looks like a simple 'drop-in' for the __fundamental_type like 'double', +but beware of loss of precision from construction or conversion from `double` or other lower precision types. +This is a mistake that is very easy to make, +and very difficult to detect because the loss of precision is only visible after the 17th decimal digit. + +We can show this by constructing from `double`, (avoiding the schoolboy-error `double d7 = 1 / 7;` giving zero!) +*/ + + double d7 = 1. / 7; // + std::cout << "d7 = " << d7 << std::endl; + + cpp_bin_float_50 seventh_0 = cpp_bin_float_50(1 / 7); // Avoid the schoolboy-error 1 / 7 == 0!) + std::cout << "seventh_0 = " << seventh_0 << std::endl; + // seventh_double0 = 0.0000000000000000000000000000000000000000000000000 + + cpp_bin_float_50 seventh_double = cpp_bin_float_50(1. / 7); // Construct from double! + std::cout << "seventh_double = " << seventh_double << std::endl; // Boost.Multiprecision post-school error! + // seventh_double = 0.14285714285714284921269268124888185411691665649414 + + /*`Did you spot the mistake? After the 17th decimal digit, result is random! + +14285714285714 should be recurring. +*/ + + cpp_bin_float_50 seventh_big(1); // 1 + seventh_big /= 7; + std::cout << "seventh_big = " << seventh_big << std::endl; // + // seventh_big = 0.14285714285714285714285714285714285714285714285714 + /*`Note the recurring 14285714285714 pattern as expected. + +As one would expect, the variable can be `const` (but sadly [*not yet `constexpr`]). +*/ + + const cpp_bin_float_50 seventh_const(cpp_bin_float_50(1) / 7); + std::cout << "seventh_const = " << seventh_const << std::endl; + // seventh_const = 0.14285714285714285714285714285714285714285714285714 + +/*`The full output is: +*/ + +//] [/big_seventh_example_3 + +//[big_seventh_example_constexpr + +// Sadly we cannot (yet) write: +// constexpr cpp_bin_float_50 any_constexpr(0); + +// constexpr cpp_bin_float_50 seventh_constexpr (cpp_bin_float_50(1) / 7); +// std::cout << "seventh_constexpr = " << seventh_constexpr << std::endl; // +// constexpr cpp_bin_float_50 seventh_constexpr(seventh_const); + +//] [/big_seventh_example_constexpr + + return 0; +} // int main() + +/* +//[big_seventh_example_output + +0.14285714285714285714285714285714285714285714285714 +pi = 3.1415926535897932384626433832795028841971693993751 +c = 0.89759790102565521098932668093700082405633411410717 +d7 = 0.14285714285714284921269268124888185411691665649414 +seventh_0 = 0.0000000000000000000000000000000000000000000000000 +seventh_double = 0.14285714285714284921269268124888185411691665649414 +seventh_big = 0.14285714285714285714285714285714285714285714285714 +seventh_const = 0.14285714285714285714285714285714285714285714285714 + +//] //[big_seventh_example_output] + +*/ diff --git a/src/boost/libs/math/example/binomial_coinflip_example.cpp b/src/boost/libs/math/example/binomial_coinflip_example.cpp new file mode 100644 index 000000000..5f1826b94 --- /dev/null +++ b/src/boost/libs/math/example/binomial_coinflip_example.cpp @@ -0,0 +1,243 @@ +// Copyright Paul A. 2007, 2010 +// Copyright John Maddock 2006 + +// 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) + +// Simple example of computing probabilities and quantiles for +// a Bernoulli random variable representing the flipping of a coin. + +// http://mathworld.wolfram.com/CoinTossing.html +// http://en.wikipedia.org/wiki/Bernoulli_trial +// Weisstein, Eric W. "Dice." From MathWorld--A Wolfram Web Resource. +// http://mathworld.wolfram.com/Dice.html +// http://en.wikipedia.org/wiki/Bernoulli_distribution +// http://mathworld.wolfram.com/BernoulliDistribution.html +// +// An idealized coin consists of a circular disk of zero thickness which, +// when thrown in the air and allowed to fall, will rest with either side face up +// ("heads" H or "tails" T) with equal probability. A coin is therefore a two-sided die. +// Despite slight differences between the sides and nonzero thickness of actual coins, +// the distribution of their tosses makes a good approximation to a p==1/2 Bernoulli distribution. + +//[binomial_coinflip_example1 + +/*`An example of a [@http://en.wikipedia.org/wiki/Bernoulli_process Bernoulli process] +is coin flipping. +A variable in such a sequence may be called a Bernoulli variable. + +This example shows using the Binomial distribution to predict the probability +of heads and tails when throwing a coin. + +The number of correct answers (say heads), +X, is distributed as a binomial random variable +with binomial distribution parameters number of trials (flips) n = 10 and probability (success_fraction) of getting a head p = 0.5 (a 'fair' coin). + +(Our coin is assumed fair, but we could easily change the success_fraction parameter p +from 0.5 to some other value to simulate an unfair coin, +say 0.6 for one with chewing gum on the tail, +so it is more likely to fall tails down and heads up). + +First we need some includes and using statements to be able to use the binomial distribution, some std input and output, and get started: +*/ + +#include <boost/math/distributions/binomial.hpp> + using boost::math::binomial; + +#include <iostream> + using std::cout; using std::endl; using std::left; +#include <iomanip> + using std::setw; + +int main() +{ + cout << "Using Binomial distribution to predict how many heads and tails." << endl; + try + { +/*` +See note [link coinflip_eg_catch with the catch block] +about why a try and catch block is always a good idea. + +First, construct a binomial distribution with parameters success_fraction +1/2, and how many flips. +*/ + const double success_fraction = 0.5; // = 50% = 1/2 for a 'fair' coin. + int flips = 10; + binomial flip(flips, success_fraction); + + cout.precision(4); +/*` + Then some examples of using Binomial moments (and echoing the parameters). +*/ + cout << "From " << flips << " one can expect to get on average " + << mean(flip) << " heads (or tails)." << endl; + cout << "Mode is " << mode(flip) << endl; + cout << "Standard deviation is " << standard_deviation(flip) << endl; + cout << "So about 2/3 will lie within 1 standard deviation and get between " + << ceil(mean(flip) - standard_deviation(flip)) << " and " + << floor(mean(flip) + standard_deviation(flip)) << " correct." << endl; + cout << "Skewness is " << skewness(flip) << endl; + // Skewness of binomial distributions is only zero (symmetrical) + // if success_fraction is exactly one half, + // for example, when flipping 'fair' coins. + cout << "Skewness if success_fraction is " << flip.success_fraction() + << " is " << skewness(flip) << endl << endl; // Expect zero for a 'fair' coin. +/*` +Now we show a variety of predictions on the probability of heads: +*/ + cout << "For " << flip.trials() << " coin flips: " << endl; + cout << "Probability of getting no heads is " << pdf(flip, 0) << endl; + cout << "Probability of getting at least one head is " << 1. - pdf(flip, 0) << endl; +/*` +When we want to calculate the probability for a range or values we can sum the PDF's: +*/ + cout << "Probability of getting 0 or 1 heads is " + << pdf(flip, 0) + pdf(flip, 1) << endl; // sum of exactly == probabilities +/*` +Or we can use the cdf. +*/ + cout << "Probability of getting 0 or 1 (<= 1) heads is " << cdf(flip, 1) << endl; + cout << "Probability of getting 9 or 10 heads is " << pdf(flip, 9) + pdf(flip, 10) << endl; +/*` +Note that using +*/ + cout << "Probability of getting 9 or 10 heads is " << 1. - cdf(flip, 8) << endl; +/*` +is less accurate than using the complement +*/ + cout << "Probability of getting 9 or 10 heads is " << cdf(complement(flip, 8)) << endl; +/*` +Since the subtraction may involve +[@http://docs.sun.com/source/806-3568/ncg_goldberg.html cancellation error], +where as `cdf(complement(flip, 8))` +does not use such a subtraction internally, and so does not exhibit the problem. + +To get the probability for a range of heads, we can either add the pdfs for each number of heads +*/ + cout << "Probability of between 4 and 6 heads (4 or 5 or 6) is " + // P(X == 4) + P(X == 5) + P(X == 6) + << pdf(flip, 4) + pdf(flip, 5) + pdf(flip, 6) << endl; +/*` +But this is probably less efficient than using the cdf +*/ + cout << "Probability of between 4 and 6 heads (4 or 5 or 6) is " + // P(X <= 6) - P(X <= 3) == P(X < 4) + << cdf(flip, 6) - cdf(flip, 3) << endl; +/*` +Certainly for a bigger range like, 3 to 7 +*/ + cout << "Probability of between 3 and 7 heads (3, 4, 5, 6 or 7) is " + // P(X <= 7) - P(X <= 2) == P(X < 3) + << cdf(flip, 7) - cdf(flip, 2) << endl; + cout << endl; + +/*` +Finally, print two tables of probability for the /exactly/ and /at least/ a number of heads. +*/ + // Print a table of probability for the exactly a number of heads. + cout << "Probability of getting exactly (==) heads" << endl; + for (int successes = 0; successes <= flips; successes++) + { // Say success means getting a head (or equally success means getting a tail). + double probability = pdf(flip, successes); + cout << left << setw(2) << successes << " " << setw(10) + << probability << " or 1 in " << 1. / probability + << ", or " << probability * 100. << "%" << endl; + } // for i + cout << endl; + + // Tabulate the probability of getting between zero heads and 0 up to 10 heads. + cout << "Probability of getting up to (<=) heads" << endl; + for (int successes = 0; successes <= flips; successes++) + { // Say success means getting a head + // (equally success could mean getting a tail). + double probability = cdf(flip, successes); // P(X <= heads) + cout << setw(2) << successes << " " << setw(10) << left + << probability << " or 1 in " << 1. / probability << ", or " + << probability * 100. << "%"<< endl; + } // for i +/*` +The last (0 to 10 heads) must, of course, be 100% probability. +*/ + double probability = 0.3; + double q = quantile(flip, probability); + std::cout << "Quantile (flip, " << probability << ") = " << q << std::endl; // Quantile (flip, 0.3) = 3 + probability = 0.6; + q = quantile(flip, probability); + std::cout << "Quantile (flip, " << probability << ") = " << q << std::endl; // Quantile (flip, 0.6) = 5 + } + catch(const std::exception& e) + { + // + /*` + [#coinflip_eg_catch] + It is always essential to include try & catch blocks because + default policies are to throw exceptions on arguments that + are out of domain or cause errors like numeric-overflow. + + Lacking try & catch blocks, the program will abort, whereas the + message below from the thrown exception will give some helpful + clues as to the cause of the problem. + */ + std::cout << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } +//] [binomial_coinflip_example1] + return 0; +} // int main() + +// Output: + +//[binomial_coinflip_example_output +/*` + +[pre +Using Binomial distribution to predict how many heads and tails. +From 10 one can expect to get on average 5 heads (or tails). +Mode is 5 +Standard deviation is 1.581 +So about 2/3 will lie within 1 standard deviation and get between 4 and 6 correct. +Skewness is 0 +Skewness if success_fraction is 0.5 is 0 + +For 10 coin flips: +Probability of getting no heads is 0.0009766 +Probability of getting at least one head is 0.999 +Probability of getting 0 or 1 heads is 0.01074 +Probability of getting 0 or 1 (<= 1) heads is 0.01074 +Probability of getting 9 or 10 heads is 0.01074 +Probability of getting 9 or 10 heads is 0.01074 +Probability of getting 9 or 10 heads is 0.01074 +Probability of between 4 and 6 heads (4 or 5 or 6) is 0.6562 +Probability of between 4 and 6 heads (4 or 5 or 6) is 0.6563 +Probability of between 3 and 7 heads (3, 4, 5, 6 or 7) is 0.8906 + +Probability of getting exactly (==) heads +0 0.0009766 or 1 in 1024, or 0.09766% +1 0.009766 or 1 in 102.4, or 0.9766% +2 0.04395 or 1 in 22.76, or 4.395% +3 0.1172 or 1 in 8.533, or 11.72% +4 0.2051 or 1 in 4.876, or 20.51% +5 0.2461 or 1 in 4.063, or 24.61% +6 0.2051 or 1 in 4.876, or 20.51% +7 0.1172 or 1 in 8.533, or 11.72% +8 0.04395 or 1 in 22.76, or 4.395% +9 0.009766 or 1 in 102.4, or 0.9766% +10 0.0009766 or 1 in 1024, or 0.09766% + +Probability of getting up to (<=) heads +0 0.0009766 or 1 in 1024, or 0.09766% +1 0.01074 or 1 in 93.09, or 1.074% +2 0.05469 or 1 in 18.29, or 5.469% +3 0.1719 or 1 in 5.818, or 17.19% +4 0.377 or 1 in 2.653, or 37.7% +5 0.623 or 1 in 1.605, or 62.3% +6 0.8281 or 1 in 1.208, or 82.81% +7 0.9453 or 1 in 1.058, or 94.53% +8 0.9893 or 1 in 1.011, or 98.93% +9 0.999 or 1 in 1.001, or 99.9% +10 1 or 1 in 1, or 100% +] +*/ +//][/binomial_coinflip_example_output] diff --git a/src/boost/libs/math/example/binomial_confidence_limits.cpp b/src/boost/libs/math/example/binomial_confidence_limits.cpp new file mode 100644 index 000000000..56ab48c36 --- /dev/null +++ b/src/boost/libs/math/example/binomial_confidence_limits.cpp @@ -0,0 +1,165 @@ +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2010 + +// 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) + +#ifdef _MSC_VER +# pragma warning(disable: 4512) // assignment operator could not be generated. +# pragma warning(disable: 4510) // default constructor could not be generated. +# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required. +#endif + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::fixed; using std::left; using std::right; using std::right; using std::setw; +using std::setprecision; + +#include <boost/math/distributions/binomial.hpp> + +void confidence_limits_on_frequency(unsigned trials, unsigned successes) +{ + // + // trials = Total number of trials. + // successes = Total number of observed successes. + // + // Calculate confidence limits for an observed + // frequency of occurrence that follows a binomial distribution. + // + //using namespace std; // Avoid + // using namespace boost::math; // potential name ambiguity with std <random> + using boost::math::binomial_distribution; + + // Print out general info: + cout << + "___________________________________________\n" + "2-Sided Confidence Limits For Success Ratio\n" + "___________________________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Number of Observations" << "= " << trials << "\n"; + cout << setw(40) << left << "Number of successes" << "= " << successes << "\n"; + cout << setw(40) << left << "Sample frequency of occurrence" << "= " << double(successes) / trials << "\n"; + // + // Define a table of significance levels: + // + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Print table header: + // + cout << "\n\n" + "_______________________________________________________________________\n" + "Confidence Lower CP Upper CP Lower JP Upper JP\n" + " Value (%) Limit Limit Limit Limit\n" + "_______________________________________________________________________\n"; + // + // Now print out the data for the table rows. + // + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // Calculate Clopper Pearson bounds: + double l = binomial_distribution<>::find_lower_bound_on_p(trials, successes, alpha[i]/2); + double u = binomial_distribution<>::find_upper_bound_on_p(trials, successes, alpha[i]/2); + // Print Clopper Pearson Limits: + cout << fixed << setprecision(5) << setw(15) << right << l; + cout << fixed << setprecision(5) << setw(15) << right << u; + // Calculate Jeffreys Prior Bounds: + l = binomial_distribution<>::find_lower_bound_on_p(trials, successes, alpha[i]/2, binomial_distribution<>::jeffreys_prior_interval); + u = binomial_distribution<>::find_upper_bound_on_p(trials, successes, alpha[i]/2, binomial_distribution<>::jeffreys_prior_interval); + // Print Jeffreys Prior Limits: + cout << fixed << setprecision(5) << setw(15) << right << l; + cout << fixed << setprecision(5) << setw(15) << right << u << std::endl; + } + cout << endl; +} // void confidence_limits_on_frequency() + +int main() +{ + confidence_limits_on_frequency(20, 4); + confidence_limits_on_frequency(200, 40); + confidence_limits_on_frequency(2000, 400); + + return 0; +} // int main() + +/* + +------ Build started: Project: binomial_confidence_limits, Configuration: Debug Win32 ------ +Compiling... +binomial_confidence_limits.cpp +Linking... +Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\binomial_confidence_limits.exe" +___________________________________________ +2-Sided Confidence Limits For Success Ratio +___________________________________________ + +Number of Observations = 20 +Number of successes = 4 +Sample frequency of occurrence = 0.2 + + +_______________________________________________________________________ +Confidence Lower CP Upper CP Lower JP Upper JP + Value (%) Limit Limit Limit Limit +_______________________________________________________________________ + 50.000 0.12840 0.29588 0.14974 0.26916 + 75.000 0.09775 0.34633 0.11653 0.31861 + 90.000 0.07135 0.40103 0.08734 0.37274 + 95.000 0.05733 0.43661 0.07152 0.40823 + 99.000 0.03576 0.50661 0.04655 0.47859 + 99.900 0.01905 0.58632 0.02634 0.55960 + 99.990 0.01042 0.64997 0.01530 0.62495 + 99.999 0.00577 0.70216 0.00901 0.67897 + +___________________________________________ +2-Sided Confidence Limits For Success Ratio +___________________________________________ + +Number of Observations = 200 +Number of successes = 40 +Sample frequency of occurrence = 0.2000000 + + +_______________________________________________________________________ +Confidence Lower CP Upper CP Lower JP Upper JP + Value (%) Limit Limit Limit Limit +_______________________________________________________________________ + 50.000 0.17949 0.22259 0.18190 0.22001 + 75.000 0.16701 0.23693 0.16934 0.23429 + 90.000 0.15455 0.25225 0.15681 0.24956 + 95.000 0.14689 0.26223 0.14910 0.25951 + 99.000 0.13257 0.28218 0.13468 0.27940 + 99.900 0.11703 0.30601 0.11902 0.30318 + 99.990 0.10489 0.32652 0.10677 0.32366 + 99.999 0.09492 0.34485 0.09670 0.34197 + +___________________________________________ +2-Sided Confidence Limits For Success Ratio +___________________________________________ + +Number of Observations = 2000 +Number of successes = 400 +Sample frequency of occurrence = 0.2000000 + + +_______________________________________________________________________ +Confidence Lower CP Upper CP Lower JP Upper JP + Value (%) Limit Limit Limit Limit +_______________________________________________________________________ + 50.000 0.19382 0.20638 0.19406 0.20613 + 75.000 0.18965 0.21072 0.18990 0.21047 + 90.000 0.18537 0.21528 0.18561 0.21503 + 95.000 0.18267 0.21821 0.18291 0.21796 + 99.000 0.17745 0.22400 0.17769 0.22374 + 99.900 0.17150 0.23079 0.17173 0.23053 + 99.990 0.16658 0.23657 0.16681 0.23631 + 99.999 0.16233 0.24169 0.16256 0.24143 + +*/ + + + diff --git a/src/boost/libs/math/example/binomial_example_nag.cpp b/src/boost/libs/math/example/binomial_example_nag.cpp new file mode 100644 index 000000000..152558c76 --- /dev/null +++ b/src/boost/libs/math/example/binomial_example_nag.cpp @@ -0,0 +1,91 @@ +// Copyright Paul A. 2007, 2010 +// Copyright John Maddock 2007 +// 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) + +// Simple example of computing probabilities for a binomial random variable. +// Replication of source nag_binomial_dist (g01bjc). + +// Shows how to replace NAG C library calls by Boost Math Toolkit C++ calls. +// Note that the default policy does not replicate the way that NAG +// library calls handle 'bad' arguments, but you can define policies that do, +// as well as other policies that may suit your application even better. +// See the examples of changing default policies for details. + +#include <boost/math/distributions/binomial.hpp> + +#include <iostream> + using std::cout; using std::endl; using std::ios; using std::showpoint; +#include <iomanip> + using std::fixed; using std::setw; + +int main() +{ + cout << "Using the binomial distribution to replicate a NAG library call." << endl; + using boost::math::binomial_distribution; + + // This replicates the computation of the examples of using nag-binomial_dist + // using g01bjc in section g01 Simple Calculations on Statistical Data. + // http://www.nag.co.uk/numeric/cl/manual/pdf/G01/g01bjc.pdf + // Program results section 8.3 page 3.g01bjc.3 + //8.2. Program Data + //g01bjc Example Program Data + //4 0.50 2 : n, p, k + //19 0.44 13 + //100 0.75 67 + //2000 0.33 700 + //8.3. Program Results + //g01bjc Example Program Results + //n p k plek pgtk peqk + //4 0.500 2 0.68750 0.31250 0.37500 + //19 0.440 13 0.99138 0.00862 0.01939 + //100 0.750 67 0.04460 0.95540 0.01700 + //2000 0.330 700 0.97251 0.02749 0.00312 + + cout.setf(ios::showpoint); // Trailing zeros to show significant decimal digits. + cout.precision(5); // Might calculate this from trials in distribution? + cout << fixed; + // Binomial distribution. + + // Note that cdf(dist, k) is equivalent to NAG library plek probability of <= k + // cdf(complement(dist, k)) is equivalent to NAG library pgtk probability of > k + // pdf(dist, k) is equivalent to NAG library peqk probability of == k + + cout << " n p k plek pgtk peqk " << endl; + binomial_distribution<>my_dist(4, 0.5); + cout << setw(4) << (int)my_dist.trials() << " " << my_dist.success_fraction() + << " " << 2 << " " << cdf(my_dist, 2) << " " + << cdf(complement(my_dist, 2)) << " " << pdf(my_dist, 2) << endl; + + binomial_distribution<>two(19, 0.440); + cout << setw(4) << (int)two.trials() << " " << two.success_fraction() + << " " << 13 << " " << cdf(two, 13) << " " + << cdf(complement(two, 13)) << " " << pdf(two, 13) << endl; + + binomial_distribution<>three(100, 0.750); + cout << setw(4) << (int)three.trials() << " " << three.success_fraction() + << " " << 67 << " " << cdf(three, 67) << " " << cdf(complement(three, 67)) + << " " << pdf(three, 67) << endl; + binomial_distribution<>four(2000, 0.330); + cout << setw(4) << (int)four.trials() << " " << four.success_fraction() + << " " << 700 << " " + << cdf(four, 700) << " " << cdf(complement(four, 700)) + << " " << pdf(four, 700) << endl; + + return 0; +} // int main() + +/* + +Example of using the binomial distribution to replicate a NAG library call. + n p k plek pgtk peqk + 4 0.50000 2 0.68750 0.31250 0.37500 + 19 0.44000 13 0.99138 0.00862 0.01939 + 100 0.75000 67 0.04460 0.95540 0.01700 +2000 0.33000 700 0.97251 0.02749 0.00312 + + + */ + diff --git a/src/boost/libs/math/example/binomial_quiz_example.cpp b/src/boost/libs/math/example/binomial_quiz_example.cpp new file mode 100644 index 000000000..f0b04db45 --- /dev/null +++ b/src/boost/libs/math/example/binomial_quiz_example.cpp @@ -0,0 +1,525 @@ +// Copyright Paul A. Bristow 2007, 2009, 2010 +// Copyright John Maddock 2006 + +// 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) + +// binomial_examples_quiz.cpp + +// Simple example of computing probabilities and quantiles for a binomial random variable +// representing the correct guesses on a multiple-choice test. + +// source http://www.stat.wvu.edu/SRS/Modules/Binomial/test.html + +//[binomial_quiz_example1 +/*` +A multiple choice test has four possible answers to each of 16 questions. +A student guesses the answer to each question, +so the probability of getting a correct answer on any given question is +one in four, a quarter, 1/4, 25% or fraction 0.25. +The conditions of the binomial experiment are assumed to be met: +n = 16 questions constitute the trials; +each question results in one of two possible outcomes (correct or incorrect); +the probability of being correct is 0.25 and is constant if no knowledge about the subject is assumed; +the questions are answered independently if the student's answer to a question +in no way influences his/her answer to another question. + +First, we need to be able to use the binomial distribution constructor +(and some std input/output, of course). +*/ + +#include <boost/math/distributions/binomial.hpp> + using boost::math::binomial; + +#include <iostream> + using std::cout; using std::endl; + using std::ios; using std::flush; using std::left; using std::right; using std::fixed; +#include <iomanip> + using std::setw; using std::setprecision; +#include <exception> + + + +//][/binomial_quiz_example1] + +int main() +{ + try + { + cout << "Binomial distribution example - guessing in a quiz." << endl; +//[binomial_quiz_example2 +/*` +The number of correct answers, X, is distributed as a binomial random variable +with binomial distribution parameters: questions n and success fraction probability p. +So we construct a binomial distribution: +*/ + int questions = 16; // All the questions in the quiz. + int answers = 4; // Possible answers to each question. + double success_fraction = 1. / answers; // If a random guess, p = 1/4 = 0.25. + binomial quiz(questions, success_fraction); +/*` +and display the distribution parameters we used thus: +*/ + cout << "In a quiz with " << quiz.trials() + << " questions and with a probability of guessing right of " + << quiz.success_fraction() * 100 << " %" + << " or 1 in " << static_cast<int>(1. / quiz.success_fraction()) << endl; +/*` +Show a few probabilities of just guessing: +*/ + cout << "Probability of getting none right is " << pdf(quiz, 0) << endl; // 0.010023 + cout << "Probability of getting exactly one right is " << pdf(quiz, 1) << endl; + cout << "Probability of getting exactly two right is " << pdf(quiz, 2) << endl; + int pass_score = 11; + cout << "Probability of getting exactly " << pass_score << " answers right by chance is " + << pdf(quiz, pass_score) << endl; + cout << "Probability of getting all " << questions << " answers right by chance is " + << pdf(quiz, questions) << endl; +/*` +[pre +Probability of getting none right is 0.0100226 +Probability of getting exactly one right is 0.0534538 +Probability of getting exactly two right is 0.133635 +Probability of getting exactly 11 right is 0.000247132 +Probability of getting exactly all 16 answers right by chance is 2.32831e-010 +] +These don't give any encouragement to guessers! + +We can tabulate the 'getting exactly right' ( == ) probabilities thus: +*/ + cout << "\n" "Guessed Probability" << right << endl; + for (int successes = 0; successes <= questions; successes++) + { + double probability = pdf(quiz, successes); + cout << setw(2) << successes << " " << probability << endl; + } + cout << endl; +/*` +[pre +Guessed Probability + 0 0.0100226 + 1 0.0534538 + 2 0.133635 + 3 0.207876 + 4 0.225199 + 5 0.180159 + 6 0.110097 + 7 0.0524273 + 8 0.0196602 + 9 0.00582526 +10 0.00135923 +11 0.000247132 +12 3.43239e-005 +13 3.5204e-006 +14 2.51457e-007 +15 1.11759e-008 +16 2.32831e-010 +] +Then we can add the probabilities of some 'exactly right' like this: +*/ + cout << "Probability of getting none or one right is " << pdf(quiz, 0) + pdf(quiz, 1) << endl; + +/*` +[pre +Probability of getting none or one right is 0.0634764 +] +But if more than a couple of scores are involved, it is more convenient (and may be more accurate) +to use the Cumulative Distribution Function (cdf) instead: +*/ + cout << "Probability of getting none or one right is " << cdf(quiz, 1) << endl; +/*` +[pre +Probability of getting none or one right is 0.0634764 +] +Since the cdf is inclusive, we can get the probability of getting up to 10 right ( <= ) +*/ + cout << "Probability of getting <= 10 right (to fail) is " << cdf(quiz, 10) << endl; +/*` +[pre +Probability of getting <= 10 right (to fail) is 0.999715 +] +To get the probability of getting 11 or more right (to pass), +it is tempting to use ``1 - cdf(quiz, 10)`` to get the probability of > 10 +*/ + cout << "Probability of getting > 10 right (to pass) is " << 1 - cdf(quiz, 10) << endl; +/*` +[pre +Probability of getting > 10 right (to pass) is 0.000285239 +] +But this should be resisted in favor of using the __complements function (see __why_complements). +*/ + cout << "Probability of getting > 10 right (to pass) is " << cdf(complement(quiz, 10)) << endl; +/*` +[pre +Probability of getting > 10 right (to pass) is 0.000285239 +] +And we can check that these two, <= 10 and > 10, add up to unity. +*/ +BOOST_MATH_ASSERT((cdf(quiz, 10) + cdf(complement(quiz, 10))) == 1.); +/*` +If we want a < rather than a <= test, because the CDF is inclusive, we must subtract one from the score. +*/ + cout << "Probability of getting less than " << pass_score + << " (< " << pass_score << ") answers right by guessing is " + << cdf(quiz, pass_score -1) << endl; +/*` +[pre +Probability of getting less than 11 (< 11) answers right by guessing is 0.999715 +] +and similarly to get a >= rather than a > test +we also need to subtract one from the score (and can again check the sum is unity). +This is because if the cdf is /inclusive/, +then its complement must be /exclusive/ otherwise there would be one possible +outcome counted twice! +*/ + cout << "Probability of getting at least " << pass_score + << "(>= " << pass_score << ") answers right by guessing is " + << cdf(complement(quiz, pass_score-1)) + << ", only 1 in " << 1/cdf(complement(quiz, pass_score-1)) << endl; + + BOOST_MATH_ASSERT((cdf(quiz, pass_score -1) + cdf(complement(quiz, pass_score-1))) == 1); + +/*` +[pre +Probability of getting at least 11 (>= 11) answers right by guessing is 0.000285239, only 1 in 3505.83 +] +Finally we can tabulate some probabilities: +*/ + cout << "\n" "At most (<=)""\n""Guessed OK Probability" << right << endl; + for (int score = 0; score <= questions; score++) + { + cout << setw(2) << score << " " << setprecision(10) + << cdf(quiz, score) << endl; + } + cout << endl; +/*` +[pre +At most (<=) +Guessed OK Probability + 0 0.01002259576 + 1 0.0634764398 + 2 0.1971110499 + 3 0.4049871101 + 4 0.6301861752 + 5 0.8103454274 + 6 0.9204427481 + 7 0.9728700437 + 8 0.9925302796 + 9 0.9983555346 +10 0.9997147608 +11 0.9999618928 +12 0.9999962167 +13 0.9999997371 +14 0.9999999886 +15 0.9999999998 +16 1 +] +*/ + cout << "\n" "At least (>)""\n""Guessed OK Probability" << right << endl; + for (int score = 0; score <= questions; score++) + { + cout << setw(2) << score << " " << setprecision(10) + << cdf(complement(quiz, score)) << endl; + } +/*` +[pre +At least (>) +Guessed OK Probability + 0 0.9899774042 + 1 0.9365235602 + 2 0.8028889501 + 3 0.5950128899 + 4 0.3698138248 + 5 0.1896545726 + 6 0.07955725188 + 7 0.02712995629 + 8 0.00746972044 + 9 0.001644465374 +10 0.0002852391917 +11 3.810715862e-005 +12 3.783265129e-006 +13 2.628657967e-007 +14 1.140870154e-008 +15 2.328306437e-010 +16 0 +] +We now consider the probabilities of *ranges* of correct guesses. + +First, calculate the probability of getting a range of guesses right, +by adding the exact probabilities of each from low ... high. +*/ + int low = 3; // Getting at least 3 right. + int high = 5; // Getting as most 5 right. + double sum = 0.; + for (int i = low; i <= high; i++) + { + sum += pdf(quiz, i); + } + cout.precision(4); + cout << "Probability of getting between " + << low << " and " << high << " answers right by guessing is " + << sum << endl; // 0.61323 +/*` +[pre +Probability of getting between 3 and 5 answers right by guessing is 0.6132 +] +Or, usually better, we can use the difference of cdfs instead: +*/ + cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is " + << cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 0.61323 +/*` +[pre +Probability of getting between 3 and 5 answers right by guessing is 0.6132 +] +And we can also try a few more combinations of high and low choices: +*/ + low = 1; high = 6; + cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is " + << cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 1 and 6 P= 0.91042 + low = 1; high = 8; + cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is " + << cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 1 <= x 8 P = 0.9825 + low = 4; high = 4; + cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is " + << cdf(quiz, high) - cdf(quiz, low - 1) << endl; // 4 <= x 4 P = 0.22520 + +/*` +[pre +Probability of getting between 1 and 6 answers right by guessing is 0.9104 +Probability of getting between 1 and 8 answers right by guessing is 0.9825 +Probability of getting between 4 and 4 answers right by guessing is 0.2252 +] +[h4 Using Binomial distribution moments] +Using moments of the distribution, we can say more about the spread of results from guessing. +*/ + cout << "By guessing, on average, one can expect to get " << mean(quiz) << " correct answers." << endl; + cout << "Standard deviation is " << standard_deviation(quiz) << endl; + cout << "So about 2/3 will lie within 1 standard deviation and get between " + << ceil(mean(quiz) - standard_deviation(quiz)) << " and " + << floor(mean(quiz) + standard_deviation(quiz)) << " correct." << endl; + cout << "Mode (the most frequent) is " << mode(quiz) << endl; + cout << "Skewness is " << skewness(quiz) << endl; + +/*` +[pre +By guessing, on average, one can expect to get 4 correct answers. +Standard deviation is 1.732 +So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct. +Mode (the most frequent) is 4 +Skewness is 0.2887 +] +[h4 Quantiles] +The quantiles (percentiles or percentage points) for a few probability levels: +*/ + cout << "Quartiles " << quantile(quiz, 0.25) << " to " + << quantile(complement(quiz, 0.25)) << endl; // Quartiles + cout << "1 standard deviation " << quantile(quiz, 0.33) << " to " + << quantile(quiz, 0.67) << endl; // 1 sd + cout << "Deciles " << quantile(quiz, 0.1) << " to " + << quantile(complement(quiz, 0.1))<< endl; // Deciles + cout << "5 to 95% " << quantile(quiz, 0.05) << " to " + << quantile(complement(quiz, 0.05))<< endl; // 5 to 95% + cout << "2.5 to 97.5% " << quantile(quiz, 0.025) << " to " + << quantile(complement(quiz, 0.025)) << endl; // 2.5 to 97.5% + cout << "2 to 98% " << quantile(quiz, 0.02) << " to " + << quantile(complement(quiz, 0.02)) << endl; // 2 to 98% + + cout << "If guessing then percentiles 1 to 99% will get " << quantile(quiz, 0.01) + << " to " << quantile(complement(quiz, 0.01)) << " right." << endl; +/*` +Notice that these output integral values because the default policy is `integer_round_outwards`. +[pre +Quartiles 2 to 5 +1 standard deviation 2 to 5 +Deciles 1 to 6 +5 to 95% 0 to 7 +2.5 to 97.5% 0 to 8 +2 to 98% 0 to 8 +] +*/ + +//] [/binomial_quiz_example2] + +//[discrete_quantile_real +/*` +Quantiles values are controlled by the __understand_dis_quant quantile policy chosen. +The default is `integer_round_outwards`, +so the lower quantile is rounded down, and the upper quantile is rounded up. + +But we might believe that the real values tell us a little more - see __math_discrete. + +We could control the policy for *all* distributions by + + #define BOOST_MATH_DISCRETE_QUANTILE_POLICY real + + at the head of the program would make this policy apply +to this *one, and only*, translation unit. + +Or we can now create a (typedef for) policy that has discrete quantiles real +(here avoiding any 'using namespaces ...' statements): +*/ + using boost::math::policies::policy; + using boost::math::policies::discrete_quantile; + using boost::math::policies::real; + using boost::math::policies::integer_round_outwards; // Default. + typedef boost::math::policies::policy<discrete_quantile<real> > real_quantile_policy; +/*` +Add a custom binomial distribution called ``real_quantile_binomial`` that uses ``real_quantile_policy`` +*/ + using boost::math::binomial_distribution; + typedef binomial_distribution<double, real_quantile_policy> real_quantile_binomial; +/*` +Construct an object of this custom distribution: +*/ + real_quantile_binomial quiz_real(questions, success_fraction); +/*` +And use this to show some quantiles - that now have real rather than integer values. +*/ + cout << "Quartiles " << quantile(quiz, 0.25) << " to " + << quantile(complement(quiz_real, 0.25)) << endl; // Quartiles 2 to 4.6212 + cout << "1 standard deviation " << quantile(quiz_real, 0.33) << " to " + << quantile(quiz_real, 0.67) << endl; // 1 sd 2.6654 4.194 + cout << "Deciles " << quantile(quiz_real, 0.1) << " to " + << quantile(complement(quiz_real, 0.1))<< endl; // Deciles 1.3487 5.7583 + cout << "5 to 95% " << quantile(quiz_real, 0.05) << " to " + << quantile(complement(quiz_real, 0.05))<< endl; // 5 to 95% 0.83739 6.4559 + cout << "2.5 to 97.5% " << quantile(quiz_real, 0.025) << " to " + << quantile(complement(quiz_real, 0.025)) << endl; // 2.5 to 97.5% 0.42806 7.0688 + cout << "2 to 98% " << quantile(quiz_real, 0.02) << " to " + << quantile(complement(quiz_real, 0.02)) << endl; // 2 to 98% 0.31311 7.7880 + + cout << "If guessing, then percentiles 1 to 99% will get " << quantile(quiz_real, 0.01) + << " to " << quantile(complement(quiz_real, 0.01)) << " right." << endl; +/*` +[pre +Real Quantiles +Quartiles 2 to 4.621 +1 standard deviation 2.665 to 4.194 +Deciles 1.349 to 5.758 +5 to 95% 0.8374 to 6.456 +2.5 to 97.5% 0.4281 to 7.069 +2 to 98% 0.3131 to 7.252 +If guessing then percentiles 1 to 99% will get 0 to 7.788 right. +] +*/ + +//] [/discrete_quantile_real] + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + + + +/* + +Output is: + +BAutorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\binomial_quiz_example.exe" +Binomial distribution example - guessing in a quiz. +In a quiz with 16 questions and with a probability of guessing right of 25 % or 1 in 4 +Probability of getting none right is 0.0100226 +Probability of getting exactly one right is 0.0534538 +Probability of getting exactly two right is 0.133635 +Probability of getting exactly 11 answers right by chance is 0.000247132 +Probability of getting all 16 answers right by chance is 2.32831e-010 +Guessed Probability + 0 0.0100226 + 1 0.0534538 + 2 0.133635 + 3 0.207876 + 4 0.225199 + 5 0.180159 + 6 0.110097 + 7 0.0524273 + 8 0.0196602 + 9 0.00582526 +10 0.00135923 +11 0.000247132 +12 3.43239e-005 +13 3.5204e-006 +14 2.51457e-007 +15 1.11759e-008 +16 2.32831e-010 +Probability of getting none or one right is 0.0634764 +Probability of getting none or one right is 0.0634764 +Probability of getting <= 10 right (to fail) is 0.999715 +Probability of getting > 10 right (to pass) is 0.000285239 +Probability of getting > 10 right (to pass) is 0.000285239 +Probability of getting less than 11 (< 11) answers right by guessing is 0.999715 +Probability of getting at least 11(>= 11) answers right by guessing is 0.000285239, only 1 in 3505.83 +At most (<=) +Guessed OK Probability + 0 0.01002259576 + 1 0.0634764398 + 2 0.1971110499 + 3 0.4049871101 + 4 0.6301861752 + 5 0.8103454274 + 6 0.9204427481 + 7 0.9728700437 + 8 0.9925302796 + 9 0.9983555346 +10 0.9997147608 +11 0.9999618928 +12 0.9999962167 +13 0.9999997371 +14 0.9999999886 +15 0.9999999998 +16 1 +At least (>) +Guessed OK Probability + 0 0.9899774042 + 1 0.9365235602 + 2 0.8028889501 + 3 0.5950128899 + 4 0.3698138248 + 5 0.1896545726 + 6 0.07955725188 + 7 0.02712995629 + 8 0.00746972044 + 9 0.001644465374 +10 0.0002852391917 +11 3.810715862e-005 +12 3.783265129e-006 +13 2.628657967e-007 +14 1.140870154e-008 +15 2.328306437e-010 +16 0 +Probability of getting between 3 and 5 answers right by guessing is 0.6132 +Probability of getting between 3 and 5 answers right by guessing is 0.6132 +Probability of getting between 1 and 6 answers right by guessing is 0.9104 +Probability of getting between 1 and 8 answers right by guessing is 0.9825 +Probability of getting between 4 and 4 answers right by guessing is 0.2252 +By guessing, on average, one can expect to get 4 correct answers. +Standard deviation is 1.732 +So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct. +Mode (the most frequent) is 4 +Skewness is 0.2887 +Quartiles 2 to 5 +1 standard deviation 2 to 5 +Deciles 1 to 6 +5 to 95% 0 to 7 +2.5 to 97.5% 0 to 8 +2 to 98% 0 to 8 +If guessing then percentiles 1 to 99% will get 0 to 8 right. +Quartiles 2 to 4.621 +1 standard deviation 2.665 to 4.194 +Deciles 1.349 to 5.758 +5 to 95% 0.8374 to 6.456 +2.5 to 97.5% 0.4281 to 7.069 +2 to 98% 0.3131 to 7.252 +If guessing, then percentiles 1 to 99% will get 0 to 7.788 right. + +*/ + diff --git a/src/boost/libs/math/example/binomial_sample_sizes.cpp b/src/boost/libs/math/example/binomial_sample_sizes.cpp new file mode 100644 index 000000000..db9f85978 --- /dev/null +++ b/src/boost/libs/math/example/binomial_sample_sizes.cpp @@ -0,0 +1,176 @@ +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2010 + +// 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) + +#ifdef _MSC_VER +# pragma warning(disable: 4512) // assignment operator could not be generated. +# pragma warning(disable: 4510) // default constructor could not be generated. +# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required. +#endif + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::fixed; using std::left; using std::right; using std::right; using std::setw; +using std::setprecision; + +#include <boost/math/distributions/binomial.hpp> + +void find_max_sample_size(double p, unsigned successes) +{ + // + // p = success ratio. + // successes = Total number of observed successes. + // + // Calculate how many trials we can have to ensure the + // maximum number of successes does not exceed "successes". + // A typical use would be failure analysis, where you want + // zero or fewer "successes" with some probability. + // + // using namespace boost::math; + // Avoid potential binomial_distribution name ambiguity with std <random> + using boost::math::binomial_distribution; + + // Print out general info: + cout << + "________________________\n" + "Maximum Number of Trials\n" + "________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Success ratio" << "= " << p << "\n"; + cout << setw(40) << left << "Maximum Number of \"successes\" permitted" << "= " << successes << "\n"; + // + // Define a table of confidence intervals: + // + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Print table header: + // + cout << "\n\n" + "____________________________\n" + "Confidence Max Number\n" + " Value (%) Of Trials \n" + "____________________________\n"; + // + // Now print out the data for the table rows. + // + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // calculate trials: + double t = binomial_distribution<>::find_maximum_number_of_trials(successes, p, alpha[i]); + t = floor(t); + // Print Trials: + cout << fixed << setprecision(0) << setw(15) << right << t << endl; + } + cout << endl; +} + +int main() +{ + find_max_sample_size(1.0/1000, 0); + find_max_sample_size(1.0/10000, 0); + find_max_sample_size(1.0/100000, 0); + find_max_sample_size(1.0/1000000, 0); + + return 0; +} + + +/* + +Output: + + binomial_sample_sizes.cpp + binomial_sample_sizes_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\binomial_sample_sizes_example.exe + ________________________ + Maximum Number of Trials + ________________________ + + Success ratio = 0.001 + Maximum Number of "successes" permitted = 0 + + + ____________________________ + Confidence Max Number + Value (%) Of Trials + ____________________________ + 50.000 692 + 75.000 287 + 90.000 105 + 95.000 51 + 99.000 10 + 99.900 0 + 99.990 0 + 99.999 0 + + ________________________ + Maximum Number of Trials + ________________________ + + Success ratio = 0.0001000 + Maximum Number of "successes" permitted = 0 + + + ____________________________ + Confidence Max Number + Value (%) Of Trials + ____________________________ + 50.000 6931 + 75.000 2876 + 90.000 1053 + 95.000 512 + 99.000 100 + 99.900 10 + 99.990 0 + 99.999 0 + + ________________________ + Maximum Number of Trials + ________________________ + + Success ratio = 0.0000100 + Maximum Number of "successes" permitted = 0 + + + ____________________________ + Confidence Max Number + Value (%) Of Trials + ____________________________ + 50.000 69314 + 75.000 28768 + 90.000 10535 + 95.000 5129 + 99.000 1005 + 99.900 100 + 99.990 10 + 99.999 1 + + ________________________ + Maximum Number of Trials + ________________________ + + Success ratio = 0.0000010 + Maximum Number of "successes" permitted = 0 + + + ____________________________ + Confidence Max Number + Value (%) Of Trials + ____________________________ + 50.000 693146 + 75.000 287681 + 90.000 105360 + 95.000 51293 + 99.000 10050 + 99.900 1000 + 99.990 100 + 99.999 10 + + +*/ diff --git a/src/boost/libs/math/example/brent_minimise_example.cpp b/src/boost/libs/math/example/brent_minimise_example.cpp new file mode 100644 index 000000000..41132ba52 --- /dev/null +++ b/src/boost/libs/math/example/brent_minimise_example.cpp @@ -0,0 +1,730 @@ +//! \file +//! \brief Brent_minimise_example.cpp + +// Copyright Paul A. Bristow 2015, 2018. + +// 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) + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// For some diagnostic information: +//#define BOOST_MATH_INSTRUMENT +// If quadmath float128 is available: +//#define BOOST_HAVE_QUADMATH + +// Example of finding minimum of a function with Brent's method. +//[brent_minimise_include_1 +#include <boost/math/tools/minima.hpp> +//] [/brent_minimise_include_1] + +#include <boost/math/special_functions/next.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/special_functions/pow.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/test/tools/floating_point_comparison.hpp> // For is_close_at)tolerance and is_small + +//[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 2018. +#ifdef BOOST_HAVE_QUADMATH // Define only if GCC or Intel, and have quadmath.lib or .dll library available. +# include <boost/multiprecision/float128.hpp> +#endif + +#include <iostream> +// using std::cout; using std::endl; +#include <iomanip> +// using std::setw; using std::setprecision; +#include <limits> +using std::numeric_limits; +#include <tuple> +#include <utility> // pair, make_pair +#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 + +// An example of a function for which we want to find a minimum. +double f(double x) +{ + return (x + 3) * (x - 1) * (x - 1); +} + +//[brent_minimise_double_functor +struct funcdouble +{ + double operator()(double const& x) + { + return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2 + } +}; +//] [/brent_minimise_double_functor] + +//[brent_minimise_T_functor +struct func +{ + template <class T> + T operator()(T const& x) + { + return (x + 3) * (x - 1) * (x - 1); // (x + 3)(x - 1)^2 + } +}; +//] [/brent_minimise_T_functor] + +//! Test if two values are close within a given tolerance. +template<typename FPT> +inline bool +is_close_to(FPT left, FPT right, FPT tolerance) +{ + return boost::math::fpc::close_at_tolerance<FPT>(tolerance) (left, right); +} + +//[brent_minimise_close + +//! Compare if value got is close to expected, +//! checking first if expected is very small +//! (to avoid divide by tiny or zero during comparison) +//! before comparing expect with value got. + +template <class T> +bool is_close(T expect, T got, T tolerance) +{ + using boost::math::fpc::close_at_tolerance; + using boost::math::fpc::is_small; + using boost::math::fpc::FPC_STRONG; + + if (is_small<T>(expect, tolerance)) + { + return is_small<T>(got, tolerance); + } + + return close_at_tolerance<T>(tolerance, FPC_STRONG) (expect, got); +} // bool is_close(T expect, T got, T tolerance) + +//] [/brent_minimise_close] + +//[brent_minimise_T_show + +//! Example template function to find and show minima. +//! \tparam T floating-point or fixed_point type. +template <class T> +void show_minima() +{ + using boost::math::tools::brent_find_minima; + using std::sqrt; + try + { // Always use try'n'catch blocks with Boost.Math to ensure you get any error messages. + + int bits = std::numeric_limits<T>::digits/2; // Maximum is digits/2; + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits. + std::streamsize precision = std::cout.precision(prec); // Save and set. + + 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's minimization is " + << sqrt(std::numeric_limits<T>::epsilon()) + << "\n Displaying to std::numeric_limits<T>::digits10 " << prec << ", significant decimal digits." + << std::endl; + + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + // Construct using string, not double, avoids loss of precision. + //T bracket_min = static_cast<T>("-4"); + //T bracket_max = static_cast<T>("1.3333333333333333333333333333333333333333333333333"); + + // Construction from double may cause loss of precision for multiprecision types like cpp_bin_float, + // but brackets values are good enough for using Brent minimization. + T bracket_min = static_cast<T>(-4); + T bracket_max = static_cast<T>(1.3333333333333333333333333333333333333333333333333); + + std::pair<T, T> r = brent_find_minima<func, T>(func(), bracket_min, bracket_max, bits, it); + + std::cout << " x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second; + if (it < maxit) + { + std::cout << ",\n met " << bits << " bits precision" << ", after " << it << " iterations." << std::endl; + } + else + { + std::cout << ",\n did NOT meet " << bits << " bits precision" << " after " << it << " iterations!" << std::endl; + } + // Check that result is that expected (compared to theoretical uncertainty). + T uncertainty = sqrt(std::numeric_limits<T>::epsilon()); + std::cout << std::boolalpha << "x == 1 (compared to uncertainty " << uncertainty << ") is " + << is_close(static_cast<T>(1), r.first, uncertainty) << std::endl; + std::cout << std::boolalpha << "f(x) == (0 compared to uncertainty " << uncertainty << ") is " + << is_close(static_cast<T>(0), r.second, uncertainty) << std::endl; + // Problems with this using multiprecision with expression template on? + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } +} // void show_minima() + +//] [/brent_minimise_T_show] + +int main() +{ + using boost::math::tools::brent_find_minima; + using std::sqrt; + std::cout << "Brent's minimisation examples." << std::endl; + std::cout << std::boolalpha << std::endl; + std::cout << std::showpoint << std::endl; // Show trailing zeros. + + // Tip - using + // std::cout.precision(std::numeric_limits<T>::digits10); + // during debugging is wise because it warns + // if construction of multiprecision involves conversion from double + // by finding random or zero digits after 17th decimal digit. + + // Specific type double - unlimited iterations (unwise?). + { + std::cout << "\nType double - unlimited iterations (unwise?)" << std::endl; + //[brent_minimise_double_1 + const int double_bits = std::numeric_limits<double>::digits; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, double_bits); + + std::streamsize precision_1 = std::cout.precision(std::numeric_limits<double>::digits10); + // Show all double precision decimal digits and trailing zeros. + std::cout << "x at minimum = " << r.first + << ", f(" << r.first << ") = " << r.second << std::endl; + //] [/brent_minimise_double_1] + std::cout << "x at minimum = " << (r.first - 1.) / r.first << std::endl; + // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 + double uncertainty = sqrt(std::numeric_limits<double>::epsilon()); + std::cout << "Uncertainty sqrt(epsilon) = " << uncertainty << std::endl; + // sqrt(epsilon) = 1.49011611938477e-008 + // (epsilon is always > 0, so no need to take abs value). + + std::cout.precision(precision_1); // Restore. + //[brent_minimise_double_1a + + using boost::math::fpc::close_at_tolerance; + using boost::math::fpc::is_small; + + std::cout << "x = " << r.first << ", f(x) = " << r.second << std::endl; + std::cout << std::boolalpha << "x == 1 (compared to uncertainty " + << uncertainty << ") is " << is_close(1., r.first, uncertainty) << std::endl; // true + std::cout << std::boolalpha << "f(x) == 0 (compared to uncertainty " + << uncertainty << ") is " << is_close(0., r.second, uncertainty) << std::endl; // true +//] [/brent_minimise_double_1a] + + } + std::cout << "\nType double with limited iterations." << std::endl; + { + const int bits = std::numeric_limits<double>::digits; + // Specific type double - limit maxit to 20 iterations. + std::cout << "Precision bits = " << bits << std::endl; + //[brent_minimise_double_2 + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<double, double> 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_2] + // x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 +//[brent_minimise_double_3 + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits)); // Number of significant decimal digits. + std::streamsize precision_3 = std::cout.precision(prec); // Save and set new precision. + std::cout << "Showing " << bits << " bits " + "precision with " << prec + << " decimal digits from tolerance " << sqrt(std::numeric_limits<double>::epsilon()) + << std::endl; + + std::cout << "x at minimum = " << r.first + << ", f(" << r.first << ") = " << r.second + << " after " << it << " iterations. " << std::endl; + std::cout.precision(precision_3); // Restore. +//] [/brent_minimise_double_3] + // Showing 53 bits precision with 9 decimal digits from tolerance 1.49011611938477e-008 + // x at minimum = 1, f(1) = 5.04852568e-018 + } + + std::cout << "\nType double with limited iterations and half double bits." << std::endl; + { + +//[brent_minimise_double_4 + const int bits_div_2 = std::numeric_limits<double>::digits / 2; // Half digits precision (effective maximum). + double epsilon_2 = boost::math::pow<-(std::numeric_limits<double>::digits/2 - 1), double>(2); + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_2)); // Number of significant decimal digits. + + std::cout << "Showing " << bits_div_2 << " bits precision with " << prec + << " decimal digits from tolerance " << sqrt(epsilon_2) + << std::endl; + std::streamsize precision_4 = std::cout.precision(prec); // Save. + const std::uintmax_t maxit = 20; + std::uintmax_t it_4 = maxit; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_2, it_4); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + std::cout << it_4 << " iterations. " << std::endl; + std::cout.precision(precision_4); // Restore. + +//] [/brent_minimise_double_4] + } + // x at minimum = 1, f(1) = 5.04852568e-018 + + { + std::cout << "\nType double with limited iterations and quarter double bits." << std::endl; + //[brent_minimise_double_5 + const int bits_div_4 = std::numeric_limits<double>::digits / 4; // Quarter precision. + double epsilon_4 = boost::math::pow<-(std::numeric_limits<double>::digits / 4 - 1), double>(2); + std::streamsize prec = static_cast<int>(2 + sqrt((double)bits_div_4)); // Number of significant decimal digits. + std::cout << "Showing " << bits_div_4 << " bits precision with " << prec + << " decimal digits from tolerance " << sqrt(epsilon_4) + << std::endl; + std::streamsize precision_5 = std::cout.precision(prec); // Save & set. + const std::uintmax_t maxit = 20; + + std::uintmax_t it_5 = maxit; + std::pair<double, double> r = brent_find_minima(funcdouble(), -4., 4. / 3, bits_div_4, it_5); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second + << ", after " << it_5 << " iterations. " << std::endl; + std::cout.precision(precision_5); // Restore. + + //] [/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. + + { + std::cout << "\nType long double with limited iterations and all long double bits." << std::endl; +//[brent_minimise_template_1 + std::streamsize precision_t1 = std::cout.precision(std::numeric_limits<long double>::digits10); // Save & set. + long double bracket_min = -4.; + long double bracket_max = 4. / 3; + const int bits = std::numeric_limits<long double>::digits; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + + std::pair<long double, long double> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second + << ", after " << it << " iterations. " << std::endl; + std::cout.precision(precision_t1); // Restore. +//] [/brent_minimise_template_1] + } + + // Show use of built-in type Template versions. + // (Will not work if construct bracket min and max from string). + +//[brent_minimise_template_fd + show_minima<float>(); + show_minima<double>(); + show_minima<long double>(); + + //] [/brent_minimise_template_fd] + +//[brent_minimise_mp_include_1 +#ifdef BOOST_HAVE_QUADMATH // Defined 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 +#ifdef BOOST_HAVE_QUADMATH // Defined 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. +#endif +//] [/brent_minimise_template_quad + + // User-defined floating-point template. + +//[brent_minimise_mp_typedefs + using boost::multiprecision::cpp_bin_float_50; // binary multiprecision typedef. + using boost::multiprecision::cpp_dec_float_50; // decimal multiprecision typedef. + + // One might also need typedefs like these to switch expression templates off and on (default is on). + typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>, + boost::multiprecision::et_on> + cpp_bin_float_50_et_on; // et_on is default so is same as cpp_bin_float_50. + + typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<50>, + boost::multiprecision::et_off> + cpp_bin_float_50_et_off; + + typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, + boost::multiprecision::et_on> // et_on is default so is same as cpp_dec_float_50. + cpp_dec_float_50_et_on; + + 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. +//[brent_minimise_mp_1 + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); + int bits = std::numeric_limits<cpp_bin_float_50>::digits / 2 - 2; + cpp_bin_float_50 bracket_min = static_cast<cpp_bin_float_50>("-4"); + cpp_bin_float_50 bracket_max = static_cast<cpp_bin_float_50>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << "Bracketing " << bracket_min << " to " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; // Will be updated with actual iteration count. + std::pair<cpp_bin_float_50, cpp_bin_float_50> r + = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ",\n f(" << r.first << ") = " << r.second + // x at minimum = 1, f(1) = 5.04853e-018 + << ", after " << it << " iterations. " << std::endl; + + is_close_to(static_cast<cpp_bin_float_50>("1"), r.first, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon())); + is_close_to(static_cast<cpp_bin_float_50>("0"), r.second, sqrt(std::numeric_limits<cpp_bin_float_50>::epsilon())); + +//] [/brent_minimise_mp_1] + +/* +//[brent_minimise_mp_output_1 +For type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent minimization is 7.311312755e-26 +Displaying to std::numeric_limits<T>::digits10 11 significant decimal digits. +x at minimum = 1, f(1) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +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 +//] [/brent_minimise_mp_output_1] +*/ +//[brent_minimise_mp_2 + 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] +*/ + } + + { // binary ET on explicit + std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_on>::digits10); + + int bits = std::numeric_limits<cpp_bin_float_50_et_on>::digits / 2 - 2; + + cpp_bin_float_50_et_on bracket_min = static_cast<cpp_bin_float_50_et_on>("-4"); + cpp_bin_float_50_et_on bracket_max = static_cast<cpp_bin_float_50_et_on>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<cpp_bin_float_50_et_on, cpp_bin_float_50_et_on> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_bin_float_50_et_on>(); // + + } + return 0; + + // Some examples of switching expression templates on and off follow. + + { // binary ET off + std::cout.precision(std::numeric_limits<cpp_bin_float_50_et_off>::digits10); + + int bits = std::numeric_limits<cpp_bin_float_50_et_off>::digits / 2 - 2; + cpp_bin_float_50_et_off bracket_min = static_cast<cpp_bin_float_50_et_off>("-4"); + cpp_bin_float_50_et_off bracket_max = static_cast<cpp_bin_float_50_et_off>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<cpp_bin_float_50_et_off, cpp_bin_float_50_et_off> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_bin_float_50_et_off>(); // + } + + { // decimal ET on by default + std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); + + int bits = std::numeric_limits<cpp_dec_float_50>::digits / 2 - 2; + + cpp_dec_float_50 bracket_min = static_cast<cpp_dec_float_50>("-4"); + cpp_dec_float_50 bracket_max = static_cast<cpp_dec_float_50>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<cpp_dec_float_50, cpp_dec_float_50> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50>(); + } + + { // 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; + + cpp_dec_float_50_et_on bracket_min = static_cast<cpp_dec_float_50_et_on>("-4"); + cpp_dec_float_50_et_on bracket_max = static_cast<cpp_dec_float_50_et_on>("1.3333333333333333333333333333333333333333333333333"); + std::cout << bracket_min << " " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<cpp_dec_float_50_et_on, cpp_dec_float_50_et_on> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50_et_on>(); + + } + + { // decimal ET off + std::cout.precision(std::numeric_limits<cpp_dec_float_50_et_off>::digits10); + + int bits = std::numeric_limits<cpp_dec_float_50_et_off>::digits / 2 - 2; + + cpp_dec_float_50_et_off bracket_min = static_cast<cpp_dec_float_50_et_off>("-4"); + cpp_dec_float_50_et_off bracket_max = static_cast<cpp_dec_float_50_et_off>("1.3333333333333333333333333333333333333333333333333"); + + std::cout << bracket_min << " " << bracket_max << std::endl; + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + std::pair<cpp_dec_float_50_et_off, cpp_dec_float_50_et_off> r = brent_find_minima(func(), bracket_min, bracket_max, bits, it); + + std::cout << "x at minimum = " << r.first << ", f(" << r.first << ") = " << r.second << std::endl; + // x at minimum = 1, f(1) = 5.04853e-018 + std::cout << it << " iterations. " << std::endl; + + show_minima<cpp_dec_float_50_et_off>(); + } + + return 0; +} // int main() + + +/* + +Typical output MSVC 15.7.3 + +brent_minimise_example.cpp +Generating code +7 of 2746 functions ( 0.3%) were compiled, the rest were copied from previous compilation. +0 functions were new in current compilation +1 functions had inline decision re-evaluated but remain unchanged +Finished generating code +brent_minimise_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe +Autorun "J:\Cpp\MathToolkit\test\Math_test\Release\brent_minimise_example.exe" +Brent's minimisation examples. + + + +Type double - unlimited iterations (unwise?) +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18 +x at minimum = 1.12344622367552e-09 +Uncertainty sqrt(epsilon) = 1.49011611938477e-08 +x = 1.00000, f(x) = 5.04853e-18 +x == 1 (compared to uncertainty 1.49012e-08) is true +f(x) == 0 (compared to uncertainty 1.49012e-08) is true + +Type double with limited iterations. +Precision bits = 53 +x at minimum = 1.00000, f(1.00000) = 5.04853e-18 after 10 iterations. +Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-08 +x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-18 after 10 iterations. + +Type double with limited iterations and half double bits. +Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633 +x at minimum = 1.000000, f(1.000000) = 5.048526e-18 +10 iterations. + +Type double with limited iterations and quarter double bits. +Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250 +x at minimum = 0.99998, f(0.99998) = 2.0070e-09, after 7 iterations. + +Type long double with limited iterations and all long double bits. +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-18, after 10 iterations. + + +For type: float, +epsilon = 1.1921e-07, +the maximum theoretical precision from Brent's minimization is 0.00034527 +Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits. +x at minimum = 1.0002, f(1.0002) = 1.9017e-07, +met 12 bits precision, after 7 iterations. +x == 1 (compared to uncertainty 0.00034527) is true +f(x) == (0 compared to uncertainty 0.00034527) is true + + +For type: double, +epsilon = 2.220446e-16, +the maximum theoretical precision from Brent's minimization is 1.490116e-08 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-18, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-08) is true +f(x) == (0 compared to uncertainty 1.490116e-08) is true + + +For type: long double, +epsilon = 2.220446e-16, +the maximum theoretical precision from Brent's minimization is 1.490116e-08 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-18, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-08) is true +f(x) == (0 compared to uncertainty 1.490116e-08) is true +Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, +f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58, after 14 iterations. + + +For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true +-4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58 +14 iterations. + + +For type: class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,1>, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true + + +============================================================================================================ + + // GCC 7.2.0 with quadmath + +Brent's minimisation examples. + +Type double - unlimited iterations (unwise?) +x at minimum = 1.00000000112345, f(1.00000000112345) = 5.04852568272458e-018 +x at minimum = 1.12344622367552e-009 +Uncertainty sqrt(epsilon) = 1.49011611938477e-008 +x = 1.00000, f(x) = 5.04853e-018 +x == 1 (compared to uncertainty 1.49012e-008) is true +f(x) == 0 (compared to uncertainty 1.49012e-008) is true + +Type double with limited iterations. +Precision bits = 53 +x at minimum = 1.00000, f(1.00000) = 5.04853e-018 after 10 iterations. +Showing 53 bits precision with 9 decimal digits from tolerance 1.49011612e-008 +x at minimum = 1.00000000, f(1.00000000) = 5.04852568e-018 after 10 iterations. + +Type double with limited iterations and half double bits. +Showing 26 bits precision with 7 decimal digits from tolerance 0.000172633 +x at minimum = 1.000000, f(1.000000) = 5.048526e-018 +10 iterations. + +Type double with limited iterations and quarter double bits. +Showing 13 bits precision with 5 decimal digits from tolerance 0.0156250 +x at minimum = 0.99998, f(0.99998) = 2.0070e-009, after 7 iterations. + +Type long double with limited iterations and all long double bits. +x at minimum = 1.00000000000137302, f(1.00000000000137302) = 7.54079013697311930e-024, after 10 iterations. + + +For type: f, +epsilon = 1.1921e-007, +the maximum theoretical precision from Brent's minimization is 0.00034527 +Displaying to std::numeric_limits<T>::digits10 5, significant decimal digits. +x at minimum = 1.0002, f(1.0002) = 1.9017e-007, +met 12 bits precision, after 7 iterations. +x == 1 (compared to uncertainty 0.00034527) is true +f(x) == (0 compared to uncertainty 0.00034527) is true + + +For type: d, +epsilon = 2.220446e-016, +the maximum theoretical precision from Brent's minimization is 1.490116e-008 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 5.048526e-018, +met 26 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 1.490116e-008) is true +f(x) == (0 compared to uncertainty 1.490116e-008) is true + + +For type: e, +epsilon = 1.084202e-019, +the maximum theoretical precision from Brent's minimization is 3.292723e-010 +Displaying to std::numeric_limits<T>::digits10 7, significant decimal digits. +x at minimum = 1.000000, f(1.000000) = 7.540790e-024, +met 32 bits precision, after 10 iterations. +x == 1 (compared to uncertainty 3.292723e-010) is true +f(x) == (0 compared to uncertainty 3.292723e-010) is true + + +For type: N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE, +epsilon = 1.92592994e-34, +the maximum theoretical precision from Brent's minimization is 1.38777878e-17 +Displaying to std::numeric_limits<T>::digits10 9, significant decimal digits. +x at minimum = 1.00000000, f(1.00000000) = 1.48695468e-43, +met 56 bits precision, after 12 iterations. +x == 1 (compared to uncertainty 1.38777878e-17) is true +f(x) == (0 compared to uncertainty 1.38777878e-17) is true +Bracketing -4.0000000000000000000000000000000000000000000000000 to 1.3333333333333333333333333333333333333333333333333 +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, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true +-4.0000000000000000000000000000000000000000000000000 1.3333333333333333333333333333333333333333333333333 +x at minimum = 0.99999999999999999999999999998813903221565569205253, f(0.99999999999999999999999999998813903221565569205253) = 5.6273022712501408640665300316078046703496236636624e-58 +14 iterations. + + +For type: N5boost14multiprecision6numberINS0_8backends13cpp_bin_floatILj50ELNS2_15digit_base_typeE10EviLi0ELi0EEELNS0_26expression_template_optionE1EEE, +epsilon = 5.3455294202e-51, +the maximum theoretical precision from Brent's minimization is 7.3113127550e-26 +Displaying to std::numeric_limits<T>::digits10 11, significant decimal digits. +x at minimum = 1.0000000000, f(1.0000000000) = 5.6273022713e-58, +met 84 bits precision, after 14 iterations. +x == 1 (compared to uncertainty 7.3113127550e-26) is true +f(x) == (0 compared to uncertainty 7.3113127550e-26) is true + +*/ diff --git a/src/boost/libs/math/example/c_error_policy_example.cpp b/src/boost/libs/math/example/c_error_policy_example.cpp new file mode 100644 index 000000000..73ae024b0 --- /dev/null +++ b/src/boost/libs/math/example/c_error_policy_example.cpp @@ -0,0 +1,83 @@ +// C_error_policy_example.cpp + +// Copyright Paul A. Bristow 2007, 2010. +// Copyright John Maddock 2007. + +// 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) + +// Suppose we want a call to tgamma to behave in a C-compatible way +// and set global ::errno rather than throw an exception. + +#include <cerrno> // for ::errno + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; + +using boost::math::policies::policy; +// Possible errors +using boost::math::policies::overflow_error; +using boost::math::policies::underflow_error; +using boost::math::policies::domain_error; +using boost::math::policies::pole_error; +using boost::math::policies::denorm_error; +using boost::math::policies::evaluation_error; + +using boost::math::policies::errno_on_error; +using boost::math::policies::ignore_error; + +//using namespace boost::math::policies; +//using namespace boost::math; // avoid potential ambiguity with std:: <random> + +// Define a policy: +typedef policy< + domain_error<errno_on_error>, // 'bad' arguments. + pole_error<errno_on_error>, // argument is pole value. + overflow_error<errno_on_error>, // argument value causes overflow. + evaluation_error<errno_on_error> // evaluation does not converge and may be inaccurate, or worse, + // or there is no way known (yet) to implement this evaluation, + // for example, kurtosis of non-central beta distribution. + > C_error_policy; + +// std +#include <iostream> + using std::cout; + using std::endl; + +int main() +{ + // We can achieve this at the function call site + // with the previously defined policy C_error_policy. + double t = tgamma(4., C_error_policy()); + cout << "tgamma(4., C_error_policy() = " << t << endl; // 6 + + // Alternatively we could use the function make_policy, + // provided for convenience, + // and define everything at the call site: + t = tgamma(4., make_policy( + domain_error<errno_on_error>(), + pole_error<errno_on_error>(), + overflow_error<errno_on_error>(), + evaluation_error<errno_on_error>() + )); + cout << "tgamma(4., make_policy(...) = " << t << endl; // 6 + + return 0; +} // int main() + +/* + +Output + + c_error_policy_example.cpp + Generating code + Finished generating code + c_error_policy_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\c_error_policy_example.exe + tgamma(4., C_error_policy() = 6 + tgamma(4., make_policy(...) = 6 + tgamma(4., C_error_policy() = 6 + tgamma(4., make_policy(...) = 6 + +*/ diff --git a/src/boost/libs/math/example/cardinal_cubic_b_spline_example.cpp b/src/boost/libs/math/example/cardinal_cubic_b_spline_example.cpp new file mode 100644 index 000000000..3a709f449 --- /dev/null +++ b/src/boost/libs/math/example/cardinal_cubic_b_spline_example.cpp @@ -0,0 +1,147 @@ +// Copyright Nicholas Thompson 2017. +// Copyright Paul A. Bristow 2017. +// Copyright John Maddock 2017. + +// 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). + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> +#include <cmath> +#include <random> +#include <cstdint> +#include <boost/random/uniform_real_distribution.hpp> +#include <boost/math/tools/roots.hpp> + +//[cubic_b_spline_example + +/*`This example demonstrates how to use the cubic b spline interpolator for regularly spaced data. +*/ +#include <boost/math/interpolators/cardinal_cubic_b_spline.hpp> + +int main() +{ + // We begin with an array of samples: + std::vector<double> v(500); + // And decide on a stepsize: + double step = 0.01; + + // Initialize the vector with a function we'd like to interpolate: + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = sin(i*step); + } + // We could define an arbitrary start time, but for now we'll just use 0: + boost::math::interpolators::cardinal_cubic_b_spline<double> spline(v.data(), v.size(), 0 /* start time */, step); + + // Now we can evaluate the spline wherever we please. + std::mt19937 gen; + boost::random::uniform_real_distribution<double> absissa(0, v.size()*step); + for (size_t i = 0; i < 10; ++i) + { + double x = absissa(gen); + std::cout << "sin(" << x << ") = " << sin(x) << ", spline interpolation gives " << spline(x) << std::endl; + std::cout << "cos(" << x << ") = " << cos(x) << ", spline derivative interpolation gives " << spline.prime(x) << std::endl; + } + + // The next example is less trivial: + // We will try to figure out when the population of the United States crossed 100 million. + // Since the census is taken every 10 years, the data is equally spaced, so we can use the cubic b spline. + // Data taken from https://en.wikipedia.org/wiki/United_States_Census + // We'll start at the year 1860: + double t0 = 1860; + double time_step = 10; + std::vector<double> population{31443321, /* 1860 */ + 39818449, /* 1870 */ + 50189209, /* 1880 */ + 62947714, /* 1890 */ + 76212168, /* 1900 */ + 92228496, /* 1910 */ + 106021537, /* 1920 */ + 122775046, /* 1930 */ + 132164569, /* 1940 */ + 150697361, /* 1950 */ + 179323175};/* 1960 */ + + // An eyeball estimate indicates that the population crossed 100 million around 1915. + // Let's see what interpolation says: + boost::math::interpolators::cardinal_cubic_b_spline<double> p(population.data(), population.size(), t0, time_step); + + // Now create a function which has a zero at p = 100,000,000: + auto f = [=](double t){ return p(t) - 100000000; }; + + // Boost includes a bisection algorithm, which is robust, though not as fast as some others + // we provide, but let's try that first. We need a termination condition for it, which + // takes the two endpoints of the range and returns either true (stop) or false (keep going), + // we could use a predefined one such as boost::math::tools::eps_tolerance<double>, but that + // won't stop until we have full double precision which is overkill, since we just need the + // endpoint to yield the same month. While we're at it, we'll keep track of the number of + // iterations required too, though this is strictly optional: + + auto termination = [](double left, double right) + { + double left_month = std::round((left - std::floor(left)) * 12 + 1); + double right_month = std::round((right - std::floor(right)) * 12 + 1); + return (left_month == right_month) && (std::floor(left) == std::floor(right)); + }; + std::uintmax_t iterations = 1000; + auto result = boost::math::tools::bisect(f, 1910.0, 1920.0, termination, iterations); + auto time = result.first; // termination condition ensures that both endpoints yield the same result + auto month = std::round((time - std::floor(time))*12 + 1); + auto year = std::floor(time); + std::cout << "The population of the United States surpassed 100 million on the "; + std::cout << month << "th month of " << year << std::endl; + std::cout << "Found in " << iterations << " iterations" << std::endl; + + // Since the cubic B spline offers the first derivative, we could equally have used Newton iterations, + // this takes "number of bits correct" as a termination condition - 20 should be plenty for what we need, + // and once again, we track how many iterations are taken: + + auto f_n = [=](double t) { return std::make_pair(p(t) - 100000000, p.prime(t)); }; + iterations = 1000; + time = boost::math::tools::newton_raphson_iterate(f_n, 1910.0, 1900.0, 2000.0, 20, iterations); + month = std::round((time - std::floor(time))*12 + 1); + year = std::floor(time); + std::cout << "The population of the United States surpassed 100 million on the "; + std::cout << month << "th month of " << year << std::endl; + std::cout << "Found in " << iterations << " iterations" << std::endl; + +} + +//] [/cubic_b_spline_example] + +//[cubic_b_spline_example_out +/*` Program output is: +[pre +sin(4.07362) = -0.802829, spline interpolation gives - 0.802829 +cos(4.07362) = -0.596209, spline derivative interpolation gives - 0.596209 +sin(0.677385) = 0.626758, spline interpolation gives 0.626758 +cos(0.677385) = 0.779214, spline derivative interpolation gives 0.779214 +sin(4.52896) = -0.983224, spline interpolation gives - 0.983224 +cos(4.52896) = -0.182402, spline derivative interpolation gives - 0.182402 +sin(4.17504) = -0.85907, spline interpolation gives - 0.85907 +cos(4.17504) = -0.511858, spline derivative interpolation gives - 0.511858 +sin(0.634934) = 0.593124, spline interpolation gives 0.593124 +cos(0.634934) = 0.805111, spline derivative interpolation gives 0.805111 +sin(4.84434) = -0.991307, spline interpolation gives - 0.991307 +cos(4.84434) = 0.131567, spline derivative interpolation gives 0.131567 +sin(4.56688) = -0.989432, spline interpolation gives - 0.989432 +cos(4.56688) = -0.144997, spline derivative interpolation gives - 0.144997 +sin(1.10517) = 0.893541, spline interpolation gives 0.893541 +cos(1.10517) = 0.448982, spline derivative interpolation gives 0.448982 +sin(3.1618) = -0.0202022, spline interpolation gives - 0.0202022 +cos(3.1618) = -0.999796, spline derivative interpolation gives - 0.999796 +sin(1.54084) = 0.999551, spline interpolation gives 0.999551 +cos(1.54084) = 0.0299566, spline derivative interpolation gives 0.0299566 +The population of the United States surpassed 100 million on the 11th month of 1915 +Found in 12 iterations +The population of the United States surpassed 100 million on the 11th month of 1915 +Found in 3 iterations +] +*/ +//] diff --git a/src/boost/libs/math/example/catmull_rom_example.cpp b/src/boost/libs/math/example/catmull_rom_example.cpp new file mode 100644 index 000000000..69a497070 --- /dev/null +++ b/src/boost/libs/math/example/catmull_rom_example.cpp @@ -0,0 +1,45 @@ +// Copyright Nick Thompson, 2017 + +// 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). + +#include <iostream> +#include <vector> +#include <array> +#include <cmath> +#include <boost/math/interpolators/catmull_rom.hpp> +#include <boost/math/constants/constants.hpp> + +using std::sin; +using std::cos; +using boost::math::catmull_rom; + +int main() +{ + std::cout << "This shows how to use Boost's Catmull-Rom spline to create an Archimedean spiral.\n"; + + // The Archimedean spiral is given by r = a*theta. We have set a = 1. + std::vector<std::array<double, 2>> spiral_points(500); + double theta_max = boost::math::constants::pi<double>(); + for (size_t i = 0; i < spiral_points.size(); ++i) + { + double theta = ((double) i/ (double) spiral_points.size())*theta_max; + spiral_points[i] = {theta*cos(theta), theta*sin(theta)}; + } + + auto archimedean = catmull_rom<std::array<double,2>>(std::move(spiral_points)); + double max_s = archimedean.max_parameter(); + std::cout << "Max s = " << max_s << std::endl; + for (double s = 0; s < max_s; s += 0.01) + { + auto p = archimedean(s); + double x = p[0]; + double y = p[1]; + double r = sqrt(x*x + y*y); + double theta = atan2(y/r, x/r); + std::cout << "r = " << r << ", theta = " << theta << ", r - theta = " << r - theta << std::endl; + } + + return 0; +} diff --git a/src/boost/libs/math/example/centered_continued_fraction.cpp b/src/boost/libs/math/example/centered_continued_fraction.cpp new file mode 100644 index 000000000..6d357d2b9 --- /dev/null +++ b/src/boost/libs/math/example/centered_continued_fraction.cpp @@ -0,0 +1,51 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +// +// Deliberately contains some unicode characters: +// +// boost-no-inspect +// +#include <iostream> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/centered_continued_fraction.hpp> +#include <boost/multiprecision/mpfr.hpp> + +using boost::math::constants::root_two; +using boost::math::constants::phi; +using boost::math::constants::pi; +using boost::math::constants::e; +using boost::math::constants::zeta_three; +using boost::math::tools::centered_continued_fraction; +using boost::multiprecision::mpfr_float; + +int main() +{ + using Real = mpfr_float; + int p = 10000; + mpfr_float::default_precision(p); + auto phi_cfrac = centered_continued_fraction(phi<Real>()); + std::cout << "φ ≈ " << phi_cfrac << "\n"; + std::cout << "Khinchin mean: " << std::setprecision(10) << phi_cfrac.khinchin_geometric_mean() << "\n\n\n"; + + auto pi_cfrac = centered_continued_fraction(pi<Real>()); + std::cout << "π ≈ " << pi_cfrac << "\n"; + std::cout << "Khinchin mean: " << std::setprecision(10) << pi_cfrac.khinchin_geometric_mean() << "\n\n\n"; + + auto rt_cfrac = centered_continued_fraction(root_two<Real>()); + std::cout << "√2 ≈ " << rt_cfrac << "\n"; + std::cout << "Khinchin mean: " << std::setprecision(10) << rt_cfrac.khinchin_geometric_mean() << "\n\n\n"; + + auto e_cfrac = centered_continued_fraction(e<Real>()); + std::cout << "e ≈ " << e_cfrac << "\n"; + std::cout << "Khinchin mean: " << std::setprecision(10) << e_cfrac.khinchin_geometric_mean() << "\n\n\n"; + + auto z_cfrac = centered_continued_fraction(zeta_three<Real>()); + std::cout << "ζ(3) ≈ " << z_cfrac << "\n"; + std::cout << "Khinchin mean: " << std::setprecision(10) << z_cfrac.khinchin_geometric_mean() << "\n\n\n"; + + + // http://jeremiebourdon.free.fr/data/Khintchine.pdf + std::cout << "The expected Khinchin mean for a random centered continued fraction is 5.45451724454\n"; +} diff --git a/src/boost/libs/math/example/chi_square_std_dev_test.cpp b/src/boost/libs/math/example/chi_square_std_dev_test.cpp new file mode 100644 index 000000000..9743240bd --- /dev/null +++ b/src/boost/libs/math/example/chi_square_std_dev_test.cpp @@ -0,0 +1,555 @@ +// Copyright John Maddock 2006, 2007 +// Copyright Paul A. Bristow 2010 + +// 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) + +#include <iostream> +using std::cout; using std::endl; +using std::left; using std::fixed; using std::right; using std::scientific; +#include <iomanip> +using std::setw; +using std::setprecision; + +#include <boost/math/distributions/chi_squared.hpp> + +int error_result = 0; + +void confidence_limits_on_std_deviation( + double Sd, // Sample Standard Deviation + unsigned N) // Sample size +{ + // Calculate confidence intervals for the standard deviation. + // For example if we set the confidence limit to + // 0.95, we know that if we repeat the sampling + // 100 times, then we expect that the true standard deviation + // will be between out limits on 95 occasions. + // Note: this is not the same as saying a 95% + // confidence interval means that there is a 95% + // probability that the interval contains the true standard deviation. + // The interval computed from a given sample either + // contains the true standard deviation or it does not. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda358.htm + + // using namespace boost::math; // potential name ambiguity with std <random> + using boost::math::chi_squared; + using boost::math::quantile; + using boost::math::complement; + + // Print out general info: + cout << + "________________________________________________\n" + "2-Sided Confidence Limits For Standard Deviation\n" + "________________________________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Number of Observations" << "= " << N << "\n"; + cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n"; + // + // Define a table of significance/risk levels: + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Start by declaring the distribution we'll need: + chi_squared dist(N - 1); + // + // Print table header: + // + cout << "\n\n" + "_____________________________________________\n" + "Confidence Lower Upper\n" + " Value (%) Limit Limit\n" + "_____________________________________________\n"; + // + // Now print out the data for the table rows. + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // Calculate limits: + double lower_limit = sqrt((N - 1) * Sd * Sd / quantile(complement(dist, alpha[i] / 2))); + double upper_limit = sqrt((N - 1) * Sd * Sd / quantile(dist, alpha[i] / 2)); + // Print Limits: + cout << fixed << setprecision(5) << setw(15) << right << lower_limit; + cout << fixed << setprecision(5) << setw(15) << right << upper_limit << endl; + } + cout << endl; +} // void confidence_limits_on_std_deviation + +void confidence_limits_on_std_deviation_alpha( + double Sd, // Sample Standard Deviation + double alpha // confidence + ) +{ // Calculate confidence intervals for the standard deviation. + // for the alpha parameter, for a range number of observations, + // from a mere 2 up to a million. + // O. L. Davies, Statistical Methods in Research and Production, ISBN 0 05 002437 X, + // 4.33 Page 68, Table H, pp 452 459. + + // using namespace std; + // using namespace boost::math; + using boost::math::chi_squared; + using boost::math::quantile; + using boost::math::complement; + + // Define a table of numbers of observations: + unsigned int obs[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40 , 50, 60, 100, 120, 1000, 10000, 50000, 100000, 1000000}; + + cout << // Print out heading: + "________________________________________________\n" + "2-Sided Confidence Limits For Standard Deviation\n" + "________________________________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Confidence level (two-sided) " << "= " << alpha << "\n"; + cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n"; + + cout << "\n\n" // Print table header: + "_____________________________________________\n" + "Observations Lower Upper\n" + " Limit Limit\n" + "_____________________________________________\n"; + for(unsigned i = 0; i < sizeof(obs)/sizeof(obs[0]); ++i) + { + unsigned int N = obs[i]; // Observations + // Start by declaring the distribution with the appropriate : + chi_squared dist(N - 1); + + // Now print out the data for the table row. + cout << fixed << setprecision(3) << setw(10) << right << N; + // Calculate limits: (alpha /2 because it is a two-sided (upper and lower limit) test. + double lower_limit = sqrt((N - 1) * Sd * Sd / quantile(complement(dist, alpha / 2))); + double upper_limit = sqrt((N - 1) * Sd * Sd / quantile(dist, alpha / 2)); + // Print Limits: + cout << fixed << setprecision(4) << setw(15) << right << lower_limit; + cout << fixed << setprecision(4) << setw(15) << right << upper_limit << endl; + } + cout << endl; +}// void confidence_limits_on_std_deviation_alpha + +void chi_squared_test( + double Sd, // Sample std deviation + double D, // True std deviation + unsigned N, // Sample size + double alpha) // Significance level +{ + // + // A Chi Squared test applied to a single set of data. + // We are testing the null hypothesis that the true + // standard deviation of the sample is D, and that any variation is down + // to chance. We can also test the alternative hypothesis + // that any difference is not down to chance. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda358.htm + // + // using namespace boost::math; + using boost::math::chi_squared; + using boost::math::quantile; + using boost::math::complement; + using boost::math::cdf; + + // Print header: + cout << + "______________________________________________\n" + "Chi Squared test for sample standard deviation\n" + "______________________________________________\n\n"; + cout << setprecision(5); + cout << setw(55) << left << "Number of Observations" << "= " << N << "\n"; + cout << setw(55) << left << "Sample Standard Deviation" << "= " << Sd << "\n"; + cout << setw(55) << left << "Expected True Standard Deviation" << "= " << D << "\n\n"; + // + // Now we can calculate and output some stats: + // + // test-statistic: + double t_stat = (N - 1) * (Sd / D) * (Sd / D); + cout << setw(55) << left << "Test Statistic" << "= " << t_stat << "\n"; + // + // Finally define our distribution, and get the probability: + // + chi_squared dist(N - 1); + double p = cdf(dist, t_stat); + cout << setw(55) << left << "CDF of test statistic: " << "= " + << setprecision(3) << scientific << p << "\n"; + double ucv = quantile(complement(dist, alpha)); + double ucv2 = quantile(complement(dist, alpha / 2)); + double lcv = quantile(dist, alpha); + double lcv2 = quantile(dist, alpha / 2); + cout << setw(55) << left << "Upper Critical Value at alpha: " << "= " + << setprecision(3) << scientific << ucv << "\n"; + cout << setw(55) << left << "Upper Critical Value at alpha/2: " << "= " + << setprecision(3) << scientific << ucv2 << "\n"; + cout << setw(55) << left << "Lower Critical Value at alpha: " << "= " + << setprecision(3) << scientific << lcv << "\n"; + cout << setw(55) << left << "Lower Critical Value at alpha/2: " << "= " + << setprecision(3) << scientific << lcv2 << "\n\n"; + // + // Finally print out results of alternative hypothesis: + // + cout << setw(55) << left << + "Results for Alternative Hypothesis and alpha" << "= " + << setprecision(4) << fixed << alpha << "\n\n"; + cout << "Alternative Hypothesis Conclusion\n"; + cout << "Standard Deviation != " << setprecision(3) << fixed << D << " "; + if((ucv2 < t_stat) || (lcv2 > t_stat)) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Standard Deviation < " << setprecision(3) << fixed << D << " "; + if(lcv > t_stat) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Standard Deviation > " << setprecision(3) << fixed << D << " "; + if(ucv < t_stat) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << endl << endl; +} // void chi_squared_test + +void chi_squared_sample_sized( + double diff, // difference from variance to detect + double variance) // true variance +{ + using namespace std; + // using boost::math; + using boost::math::chi_squared; + using boost::math::quantile; + using boost::math::complement; + using boost::math::cdf; + + try + { + cout << // Print out general info: + "_____________________________________________________________\n" + "Estimated sample sizes required for various confidence levels\n" + "_____________________________________________________________\n\n"; + cout << setprecision(5); + cout << setw(40) << left << "True Variance" << "= " << variance << "\n"; + cout << setw(40) << left << "Difference to detect" << "= " << diff << "\n"; + // + // Define a table of significance levels: + // + double alpha[] = { 0.5, 0.33333333333333333333333, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Print table header: + // + cout << "\n\n" + "_______________________________________________________________\n" + "Confidence Estimated Estimated\n" + " Value (%) Sample Size Sample Size\n" + " (lower one- (upper one-\n" + " sided test) sided test)\n" + "_______________________________________________________________\n"; + // + // Now print out the data for the table rows. + // + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // Calculate df for a lower single-sided test: + double df = chi_squared::find_degrees_of_freedom( + -diff, alpha[i], alpha[i], variance); + // Convert to integral sample size (df is a floating point value in this implementation): + double size = ceil(df) + 1; + // Print size: + cout << fixed << setprecision(0) << setw(16) << right << size; + // Calculate df for an upper single-sided test: + df = chi_squared::find_degrees_of_freedom( + diff, alpha[i], alpha[i], variance); + // Convert to integral sample size: + size = ceil(df) + 1; + // Print size: + cout << fixed << setprecision(0) << setw(16) << right << size << endl; + } + cout << endl; + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + ++error_result; + } +} // chi_squared_sample_sized + +int main() +{ + // Run tests for Gear data + // see http://www.itl.nist.gov/div898/handbook/eda/section3/eda3581.htm + // Tests measurements of gear diameter. + // + confidence_limits_on_std_deviation(0.6278908E-02, 100); + chi_squared_test(0.6278908E-02, 0.1, 100, 0.05); + chi_squared_sample_sized(0.1 - 0.6278908E-02, 0.1); + // + // Run tests for silicon wafer fabrication data. + // see http://www.itl.nist.gov/div898/handbook/prc/section2/prc23.htm + // A supplier of 100 ohm.cm silicon wafers claims that his fabrication + // process can produce wafers with sufficient consistency so that the + // standard deviation of resistivity for the lot does not exceed + // 10 ohm.cm. A sample of N = 10 wafers taken from the lot has a + // standard deviation of 13.97 ohm.cm + // + confidence_limits_on_std_deviation(13.97, 10); + chi_squared_test(13.97, 10.0, 10, 0.05); + chi_squared_sample_sized(13.97 * 13.97 - 100, 100); + chi_squared_sample_sized(55, 100); + chi_squared_sample_sized(1, 100); + + // List confidence interval multipliers for standard deviation + // for a range of numbers of observations from 2 to a million, + // and for a few alpha values, 0.1, 0.05, 0.01 for confidences 90, 95, 99 % + confidence_limits_on_std_deviation_alpha(1., 0.1); + confidence_limits_on_std_deviation_alpha(1., 0.05); + confidence_limits_on_std_deviation_alpha(1., 0.01); + + return error_result; +} + +/* + +________________________________________________ +2-Sided Confidence Limits For Standard Deviation +________________________________________________ +Number of Observations = 100 +Standard Deviation = 0.006278908 +_____________________________________________ +Confidence Lower Upper + Value (%) Limit Limit +_____________________________________________ + 50.000 0.00601 0.00662 + 75.000 0.00582 0.00685 + 90.000 0.00563 0.00712 + 95.000 0.00551 0.00729 + 99.000 0.00530 0.00766 + 99.900 0.00507 0.00812 + 99.990 0.00489 0.00855 + 99.999 0.00474 0.00895 +______________________________________________ +Chi Squared test for sample standard deviation +______________________________________________ +Number of Observations = 100 +Sample Standard Deviation = 0.00628 +Expected True Standard Deviation = 0.10000 +Test Statistic = 0.39030 +CDF of test statistic: = 1.438e-099 +Upper Critical Value at alpha: = 1.232e+002 +Upper Critical Value at alpha/2: = 1.284e+002 +Lower Critical Value at alpha: = 7.705e+001 +Lower Critical Value at alpha/2: = 7.336e+001 +Results for Alternative Hypothesis and alpha = 0.0500 +Alternative Hypothesis Conclusion +Standard Deviation != 0.100 NOT REJECTED +Standard Deviation < 0.100 NOT REJECTED +Standard Deviation > 0.100 REJECTED +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ +True Variance = 0.10000 +Difference to detect = 0.09372 +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (lower one- (upper one- + sided test) sided test) +_______________________________________________________________ + 50.000 2 2 + 66.667 2 5 + 75.000 2 10 + 90.000 4 32 + 95.000 5 52 + 99.000 8 102 + 99.900 13 178 + 99.990 18 257 + 99.999 23 337 +________________________________________________ +2-Sided Confidence Limits For Standard Deviation +________________________________________________ +Number of Observations = 10 +Standard Deviation = 13.9700000 +_____________________________________________ +Confidence Lower Upper + Value (%) Limit Limit +_____________________________________________ + 50.000 12.41880 17.25579 + 75.000 11.23084 19.74131 + 90.000 10.18898 22.98341 + 95.000 9.60906 25.50377 + 99.000 8.62898 31.81825 + 99.900 7.69466 42.51593 + 99.990 7.04085 55.93352 + 99.999 6.54517 73.00132 +______________________________________________ +Chi Squared test for sample standard deviation +______________________________________________ +Number of Observations = 10 +Sample Standard Deviation = 13.97000 +Expected True Standard Deviation = 10.00000 +Test Statistic = 17.56448 +CDF of test statistic: = 9.594e-001 +Upper Critical Value at alpha: = 1.692e+001 +Upper Critical Value at alpha/2: = 1.902e+001 +Lower Critical Value at alpha: = 3.325e+000 +Lower Critical Value at alpha/2: = 2.700e+000 +Results for Alternative Hypothesis and alpha = 0.0500 +Alternative Hypothesis Conclusion +Standard Deviation != 10.000 REJECTED +Standard Deviation < 10.000 REJECTED +Standard Deviation > 10.000 NOT REJECTED +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ +True Variance = 100.00000 +Difference to detect = 95.16090 +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (lower one- (upper one- + sided test) sided test) +_______________________________________________________________ + 50.000 2 2 + 66.667 2 5 + 75.000 2 10 + 90.000 4 32 + 95.000 5 51 + 99.000 7 99 + 99.900 11 174 + 99.990 15 251 + 99.999 20 330 +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ +True Variance = 100.00000 +Difference to detect = 55.00000 +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (lower one- (upper one- + sided test) sided test) +_______________________________________________________________ + 50.000 2 2 + 66.667 4 10 + 75.000 8 21 + 90.000 23 71 + 95.000 36 115 + 99.000 71 228 + 99.900 123 401 + 99.990 177 580 + 99.999 232 762 +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ +True Variance = 100.00000 +Difference to detect = 1.00000 +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (lower one- (upper one- + sided test) sided test) +_______________________________________________________________ + 50.000 2 2 + 66.667 14696 14993 + 75.000 36033 36761 + 90.000 130079 132707 + 95.000 214283 218612 + 99.000 428628 437287 + 99.900 756333 771612 + 99.990 1095435 1117564 + 99.999 1440608 1469711 +________________________________________________ +2-Sided Confidence Limits For Standard Deviation +________________________________________________ +Confidence level (two-sided) = 0.1000000 +Standard Deviation = 1.0000000 +_____________________________________________ +Observations Lower Upper + Limit Limit +_____________________________________________ + 2 0.5102 15.9472 + 3 0.5778 4.4154 + 4 0.6196 2.9200 + 5 0.6493 2.3724 + 6 0.6720 2.0893 + 7 0.6903 1.9154 + 8 0.7054 1.7972 + 9 0.7183 1.7110 + 10 0.7293 1.6452 + 15 0.7688 1.4597 + 20 0.7939 1.3704 + 30 0.8255 1.2797 + 40 0.8454 1.2320 + 50 0.8594 1.2017 + 60 0.8701 1.1805 + 100 0.8963 1.1336 + 120 0.9045 1.1203 + 1000 0.9646 1.0383 + 10000 0.9885 1.0118 + 50000 0.9948 1.0052 + 100000 0.9963 1.0037 + 1000000 0.9988 1.0012 +________________________________________________ +2-Sided Confidence Limits For Standard Deviation +________________________________________________ +Confidence level (two-sided) = 0.0500000 +Standard Deviation = 1.0000000 +_____________________________________________ +Observations Lower Upper + Limit Limit +_____________________________________________ + 2 0.4461 31.9102 + 3 0.5207 6.2847 + 4 0.5665 3.7285 + 5 0.5991 2.8736 + 6 0.6242 2.4526 + 7 0.6444 2.2021 + 8 0.6612 2.0353 + 9 0.6755 1.9158 + 10 0.6878 1.8256 + 15 0.7321 1.5771 + 20 0.7605 1.4606 + 30 0.7964 1.3443 + 40 0.8192 1.2840 + 50 0.8353 1.2461 + 60 0.8476 1.2197 + 100 0.8780 1.1617 + 120 0.8875 1.1454 + 1000 0.9580 1.0459 + 10000 0.9863 1.0141 + 50000 0.9938 1.0062 + 100000 0.9956 1.0044 + 1000000 0.9986 1.0014 +________________________________________________ +2-Sided Confidence Limits For Standard Deviation +________________________________________________ +Confidence level (two-sided) = 0.0100000 +Standard Deviation = 1.0000000 +_____________________________________________ +Observations Lower Upper + Limit Limit +_____________________________________________ + 2 0.3562 159.5759 + 3 0.4344 14.1244 + 4 0.4834 6.4675 + 5 0.5188 4.3960 + 6 0.5464 3.4848 + 7 0.5688 2.9798 + 8 0.5875 2.6601 + 9 0.6036 2.4394 + 10 0.6177 2.2776 + 15 0.6686 1.8536 + 20 0.7018 1.6662 + 30 0.7444 1.4867 + 40 0.7718 1.3966 + 50 0.7914 1.3410 + 60 0.8065 1.3026 + 100 0.8440 1.2200 + 120 0.8558 1.1973 + 1000 0.9453 1.0609 + 10000 0.9821 1.0185 + 50000 0.9919 1.0082 + 100000 0.9943 1.0058 + 1000000 0.9982 1.0018 +*/ + diff --git a/src/boost/libs/math/example/cohen_acceleration.cpp b/src/boost/libs/math/example/cohen_acceleration.cpp new file mode 100644 index 000000000..e16357d13 --- /dev/null +++ b/src/boost/libs/math/example/cohen_acceleration.cpp @@ -0,0 +1,46 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +#include <iostream> +#include <iomanip> +#include <boost/math/tools/cohen_acceleration.hpp> +#include <boost/math/constants/constants.hpp> + +using boost::math::tools::cohen_acceleration; +using boost::math::constants::pi; + +template<typename Real> +class G { +public: + G(){ + k_ = 0; + } + + Real operator()() { + k_ += 1; + return 1/(k_*k_); + } + +private: + Real k_; +}; + +int main() { + using Real = float; + auto g = G<Real>(); + Real computed = cohen_acceleration(g); + Real expected = pi<Real>()*pi<Real>()/12; + std::cout << std::setprecision(std::numeric_limits<Real>::max_digits10); + + std::cout << "Computed = " << computed << " = " << std::hexfloat << computed << "\n"; + std::cout << std::defaultfloat; + std::cout << "Expected = " << expected << " = " << std::hexfloat << expected << "\n"; + + // Compute with a specified number of terms: + // Make sure to reset g: + g = G<Real>(); + computed = cohen_acceleration(g, 5); + std::cout << std::defaultfloat; + std::cout << "Computed = " << computed << " = " << std::hexfloat << computed << " using 5 terms.\n"; +} diff --git a/src/boost/libs/math/example/color_maps_example.cpp b/src/boost/libs/math/example/color_maps_example.cpp new file mode 100644 index 000000000..22bb0ed78 --- /dev/null +++ b/src/boost/libs/math/example/color_maps_example.cpp @@ -0,0 +1,221 @@ +// (C) Copyright Nick Thompson 2021. +// (C) Copyright Matt Borland 2022. +// 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) + +#include <cmath> +#include <cstdint> +#include <array> +#include <complex> +#include <tuple> +#include <iostream> +#include <vector> +#include <limits> +#include <boost/math/tools/color_maps.hpp> + +#if !__has_include("lodepng.h") + #error "lodepng.h is required to run this example." +#endif +#include "lodepng.h" +#include <iostream> +#include <string> +#include <vector> + + +// In lodepng, the vector is expected to be row major, with the top row +// specified first. Note that this is a bit confusing sometimes as it's more +// natural to let y increase moving *up*. +unsigned write_png(const std::string &filename, + const std::vector<std::uint8_t> &img, std::size_t width, + std::size_t height) { + unsigned error = lodepng::encode(filename, img, width, height, + LodePNGColorType::LCT_RGBA, 8); + if (error) { + std::cerr << "Error encoding png: " << lodepng_error_text(error) << "\n"; + } + return error; +} + + +// Computes ab - cd. +// See: https://pharr.org/matt/blog/2019/11/03/difference-of-floats.html +template <typename Real> +inline Real difference_of_products(Real a, Real b, Real c, Real d) +{ + Real cd = c * d; + Real err = std::fma(-c, d, cd); + Real dop = std::fma(a, b, -cd); + return dop + err; +} + +template<typename Real> +auto fifth_roots(std::complex<Real> z) +{ + std::complex<Real> v = std::pow(z,4); + std::complex<Real> dw = Real(5)*v; + std::complex<Real> w = v*z - Real(1); + return std::make_pair(w, dw); +} + +template<typename Real> +auto g(std::complex<Real> z) +{ + std::complex<Real> z2 = z*z; + std::complex<Real> z3 = z*z2; + std::complex<Real> z4 = z2*z2; + std::complex<Real> w = z4*(z4 + Real(15)) - Real(16); + std::complex<Real> dw = Real(4)*z3*(Real(2)*z4 + Real(15)); + return std::make_pair(w, dw); +} + +template<typename Real> +std::complex<Real> complex_newton(std::function<std::pair<std::complex<Real>,std::complex<Real>>(std::complex<Real>)> f, std::complex<Real> z) +{ + // f(x(1+e)) = f(x) + exf'(x) + bool close = false; + do + { + auto [y, dy] = f(z); + z -= y/dy; + close = (abs(y) <= 1.4*std::numeric_limits<Real>::epsilon()*abs(z*dy)); + } while(!close); + return z; +} + +template<typename Real> +class plane_pixel_map +{ +public: + plane_pixel_map(int64_t image_width, int64_t image_height, Real xmin, Real ymin) + { + image_width_ = image_width; + image_height_ = image_height; + xmin_ = xmin; + ymin_ = ymin; + } + + std::complex<Real> to_complex(int64_t i, int64_t j) const { + Real x = xmin_ + 2*abs(xmin_)*Real(i)/Real(image_width_ - 1); + Real y = ymin_ + 2*abs(ymin_)*Real(j)/Real(image_height_ - 1); + return std::complex<Real>(x,y); + } + + std::pair<int64_t, int64_t> to_pixel(std::complex<Real> z) const { + Real x = z.real(); + Real y = z.imag(); + Real ii = (image_width_ - 1)*(x - xmin_)/(2*abs(xmin_)); + Real jj = (image_height_ - 1)*(y - ymin_)/(2*abs(ymin_)); + + return std::make_pair(std::round(ii), std::round(jj)); + } + +private: + int64_t image_width_; + int64_t image_height_; + Real xmin_; + Real ymin_; +}; + +int main(int argc, char** argv) +{ + using Real = double; + using boost::math::tools::viridis; + using std::sqrt; + + std::function<std::array<Real, 3>(Real)> color_map = viridis<Real>; + std::string requested_color_map = "viridis"; + if (argc == 2) { + requested_color_map = std::string(argv[1]); + if (requested_color_map == "smooth_cool_warm") { + color_map = boost::math::tools::smooth_cool_warm<Real>; + } + else if (requested_color_map == "plasma") { + color_map = boost::math::tools::plasma<Real>; + } + else if (requested_color_map == "black_body") { + color_map = boost::math::tools::black_body<Real>; + } + else if (requested_color_map == "inferno") { + color_map = boost::math::tools::inferno<Real>; + } + else if (requested_color_map == "kindlmann") { + color_map = boost::math::tools::kindlmann<Real>; + } + else if (requested_color_map == "extended_kindlmann") { + color_map = boost::math::tools::extended_kindlmann<Real>; + } + else { + std::cerr << "Could not recognize color map " << argv[1] << "."; + return 1; + } + } + constexpr int64_t image_width = 1024; + constexpr int64_t image_height = 1024; + constexpr const Real two_pi = 6.28318530718; + + std::vector<std::uint8_t> img(4*image_width*image_height, 0); + plane_pixel_map<Real> map(image_width, image_height, Real(-2), Real(-2)); + + for (int64_t j = 0; j < image_height; ++j) + { + std::cout << "j = " << j << "\n"; + for (int64_t i = 0; i < image_width; ++i) + { + std::complex<Real> z0 = map.to_complex(i,j); + auto rt = complex_newton<Real>(g<Real>, z0); + // The root is one of exp(2*pi*ij/5). Therefore, it can be classified by angle. + Real theta = std::atan2(rt.imag(), rt.real()); + // Now theta in [-pi,pi]. Get it into [0,2pi]: + if (theta < 0) { + theta += two_pi; + } + theta /= two_pi; + if (std::isnan(theta)) { + std::cerr << "Theta is a nan!\n"; + } + auto c = boost::math::tools::to_8bit_rgba(color_map(theta)); + int64_t idx = 4 * image_width * (image_height - 1 - j) + 4 * i; + img[idx + 0] = c[0]; + img[idx + 1] = c[1]; + img[idx + 2] = c[2]; + img[idx + 3] = c[3]; + } + } + + std::array<std::complex<Real>, 8> roots; + roots[0] = -Real(1); + roots[1] = Real(1); + roots[2] = {Real(0), Real(1)}; + roots[3] = {Real(0), -Real(1)}; + roots[4] = {sqrt(Real(2)), sqrt(Real(2))}; + roots[5] = {sqrt(Real(2)), -sqrt(Real(2))}; + roots[6] = {-sqrt(Real(2)), -sqrt(Real(2))}; + roots[7] = {-sqrt(Real(2)), sqrt(Real(2))}; + + for (int64_t k = 0; k < 8; ++k) + { + auto [ic, jc] = map.to_pixel(roots[k]); + + int64_t r = 7; + for (int64_t i = ic - r; i < ic + r; ++i) + { + for (int64_t j = jc - r; j < jc + r; ++j) + { + if ((i-ic)*(i-ic) + (j-jc)*(j-jc) > r*r) + { + continue; + } + int64_t idx = 4 * image_width * (image_height - 1 - j) + 4 * i; + img[idx + 0] = 0; + img[idx + 1] = 0; + img[idx + 2] = 0; + img[idx + 3] = 0xff; + } + } + } + + // Requires lodepng.h + // See: https://github.com/lvandeve/lodepng for download and compilation instructions + write_png(requested_color_map + "_newton_fractal.png", img, image_width, image_height); +} diff --git a/src/boost/libs/math/example/color_maps_sf_example.cpp b/src/boost/libs/math/example/color_maps_sf_example.cpp new file mode 100644 index 000000000..f688bd343 --- /dev/null +++ b/src/boost/libs/math/example/color_maps_sf_example.cpp @@ -0,0 +1,606 @@ +// (C) Copyright John Maddock 2022. +// 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) + +// +// This program plots various special functions as color maps, +// run with the "help" option to see the various command line options. +// + +#include <cmath> +#include <cstdint> +#include <array> +#include <complex> +#include <tuple> +#include <iostream> +#include <vector> +#include <limits> +#include <boost/math/tools/color_maps.hpp> +#include <boost/math/special_functions.hpp> + +#if !__has_include("lodepng.h") + #error "lodepng.h is required to run this example." +#endif +#include "lodepng.h" +#include <iostream> +#include <string> +#include <vector> +#include <functional> + +// In lodepng, the vector is expected to be row major, with the top row +// specified first. Note that this is a bit confusing sometimes as it's more +// natural to let y increase moving *up*. +unsigned write_png(const std::string& filename, + const std::vector<std::uint8_t>& img, std::size_t width, + std::size_t height) { + unsigned error = lodepng::encode(filename, img, width, height, + LodePNGColorType::LCT_RGBA, 8); + if (error) { + std::cerr << "Error encoding png: " << lodepng_error_text(error) << "\n"; + } + return error; +} + +double hypergeometric_1F1_at_half(double x, double y) +{ + try + { + return boost::math::hypergeometric_1F1(x, y, -3.5); + } + catch (const std::domain_error&) + { + return 0; + } +} + +void show_help() +{ + std::cout << + "The following command line options are supported:\n" + " gamma_p|gamma_q|gamma_p_inv|gamma_q_inv|cyl_bessel_j|cyl_neumann|cyl_bessel_i|cyl_bessel_k\n" + " |cyl_bessel_d|ellint_1|ellint_2|ellint_3|jacobi_zeta|heuman_lambda|jacobi_theta1|1F1\n" + " Sets the function to be plotted.\n" + " Note that the defaults for the options below change depending on the function selected here,\n" + " so set this option first, and then fine tune with the following options:\n" + " smooth_cool_warm|plasma|black_body|inferno|kindlmann|extended_kindlmann\n" + " Sets the color map used.\n" + " width=XX\n" + " height=XX\n" + " Sets the width and height of the bitmap.\n" + " x_min=XX\n" + " x_max=XX\n" + " y_min=XX\n" + " y_max=XX\n" + " Sets the extent of the x and y variables passed to the function.\n" + " log=false|true|0|1\n" + " Turns logarithmic scale on or off (default off)\n"; +} + +int main(int argc, char** argv) +{ + using Real = double; + using boost::math::tools::viridis; + using std::sqrt; + + std::function<std::array<Real, 3>(Real)> color_map = viridis<Real>; + std::string requested_color_map = "viridis"; + std::string function_name = "gamma_p"; + int64_t image_width = 1024; + int64_t image_height = 1024; + + double x_min{ 0.001 }, x_max{ 20 }; + double y_min{ 0.001 }, y_max{ 20 }; + + Real(*the_function)(Real, Real) = boost::math::gamma_p; + bool log_scale = false; + bool debug = false; + + for(unsigned i = 1; i < argc; ++i) + { + std::string arg = std::string(argv[i]); + if (arg == "smooth_cool_warm") { + requested_color_map = arg; + color_map = boost::math::tools::smooth_cool_warm<Real>; + } + else if (arg == "plasma") { + requested_color_map = arg; + color_map = boost::math::tools::plasma<Real>; + } + else if (arg == "black_body") { + requested_color_map = arg; + color_map = boost::math::tools::black_body<Real>; + } + else if (arg == "inferno") { + requested_color_map = arg; + color_map = boost::math::tools::inferno<Real>; + } + else if (arg == "kindlmann") { + requested_color_map = arg; + color_map = boost::math::tools::kindlmann<Real>; + } + else if (arg == "extended_kindlmann") { + requested_color_map = arg; + color_map = boost::math::tools::extended_kindlmann<Real>; + } + else if (arg.compare(0, 6, "width=") == 0) + { + image_width = std::strtol(arg.c_str() + 6, nullptr, 10); + } + else if (arg.compare(0, 7, "height=") == 0) + { + image_height = std::strtol(arg.c_str() + 7, nullptr, 10); + } + else if (arg.compare(0, 6, "x_min=") == 0) + { + x_min = std::strtod(arg.c_str() + 6, nullptr); + } + else if (arg.compare(0, 6, "x_max=") == 0) + { + x_max = std::strtod(arg.c_str() + 6, nullptr); + } + else if (arg.compare(0, 6, "y_min=") == 0) + { + y_min = std::strtod(arg.c_str() + 6, nullptr); + } + else if (arg.compare(0, 6, "y_max=") == 0) + { + y_max = std::strtod(arg.c_str() + 6, nullptr); + } + else if (arg == "log=1") + { + log_scale = true; + } + else if (arg == "log=0") + { + log_scale = false; + } + else if (arg == "log=true") + { + log_scale = true; + } + else if (arg == "log=false") + { + log_scale = false; + } + else if (arg == "debug") + { + debug = true; + } + else if (arg == "gamma_p") + { + the_function = boost::math::gamma_p; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default gamma_p color map to extended_kindlmann" << std::endl; + requested_color_map = "extended_kindlmann"; + color_map = boost::math::tools::extended_kindlmann<Real>; + } + } + else if (arg == "gamma_q") + { + the_function = boost::math::gamma_q; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default gamma_p color map to extended_kindlmann" << std::endl; + requested_color_map = "extended_kindlmann"; + color_map = boost::math::tools::extended_kindlmann<Real>; + } + } + else if (arg == "gamma_p_inv") + { + the_function = boost::math::gamma_p_inv; + function_name = arg; + if (y_max > 1) + { + std::cout << "Setting y range to [0.01, 0.99] for gamma_p_inv" << std::endl; + y_min = 0.01; + y_max = 0.99; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default gamma_p_inv color map to inferno" << std::endl; + requested_color_map = "inferno"; + color_map = boost::math::tools::inferno<Real>; + } + } + else if (arg == "gamma_q_inv") + { + the_function = boost::math::gamma_q_inv; + function_name = arg; + if (y_max > 1) + { + std::cout << "Setting y range to [0.01, 0.99] for gamma_p_inv" << std::endl; + y_min = 0.01; + y_max = 0.99; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default gamma_p_inv color map to inferno" << std::endl; + requested_color_map = "inferno"; + color_map = boost::math::tools::inferno<Real>; + } + } + else if (arg == "beta") + { + the_function = boost::math::beta; + function_name = arg; + if (log_scale == false) + { + std::cout << "Setting log scale to true for beta" << std::endl; + log_scale = true; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default beta color map to smooth_cool_warm" << std::endl; + requested_color_map = "smooth_cool_warm"; + color_map = boost::math::tools::smooth_cool_warm<Real>; + } + } + else if (arg == "cyl_bessel_j") + { + the_function = boost::math::cyl_bessel_j; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default beta color map to smooth_cool_warm" << std::endl; + requested_color_map = "smooth_cool_warm"; + color_map = boost::math::tools::smooth_cool_warm<Real>; + } + } + else if (arg == "cyl_neumann") + { + the_function = boost::math::cyl_neumann; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default cyl_neumann color map to black_body" << std::endl; + requested_color_map = "black_body"; + color_map = boost::math::tools::black_body<Real>; + } + if (x_max > 1.5) + { + std::cout << "Setting cyl_neumann default x range to [0.5,1.5]" << std::endl; + x_min = 0.5; + x_max = 1.5; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for cyl_neumann" << std::endl; + log_scale = true; + } + } + else if (arg == "cyl_bessel_i") + { + the_function = boost::math::cyl_bessel_i; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default cyl_bessel_i color map to black_body" << std::endl; + requested_color_map = "black_body"; + color_map = boost::math::tools::black_body<Real>; + } + if (x_max > 1.5) + { + std::cout << "Setting cyl_bessel_i default x range to [0.5,1.5]" << std::endl; + x_min = 0.5; + x_max = 1.5; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for cyl_bessel_i" << std::endl; + log_scale = true; + } + } + else if (arg == "cyl_bessel_k") + { + the_function = boost::math::cyl_bessel_k; + function_name = arg; + if (requested_color_map == "viridis") + { + std::cout << "Setting default cyl_bessel_k color map to plasma" << std::endl; + requested_color_map = "plasma"; + color_map = boost::math::tools::plasma<Real>; + } + if (x_max > 1.5) + { + std::cout << "Setting cyl_bessel_k default x range to [0,5]" << std::endl; + x_min = 0.01; + x_max = 5; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for cyl_bessel_k" << std::endl; + log_scale = true; + } + } + else if (arg == "cyl_bessel_d") + { + the_function = boost::math::cyl_bessel_k; + function_name = arg; + if (log_scale == false) + { + std::cout << "Turning on log scale for cyl_bessel_d" << std::endl; + log_scale = true; + } + } + else if (arg == "ellint_1") + { + the_function = boost::math::ellint_1; + function_name = arg; + // x_max=1 y_max=1.5 kindlmann log=true + if (x_max >= 20) + { + std::cout << "Setting ellint_1 x range to [0, 1]" << std::endl; + x_max = 1; + } + if (y_max >= 20) + { + std::cout << "Setting ellint_1 y range to [0, 1.5]" << std::endl; + x_max = 1.5; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for ellint_1" << std::endl; + log_scale = true; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default ellint_1 color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "ellint_2") + { + the_function = boost::math::ellint_2; + function_name = arg; + // x_max=1 y_max=1.5 kindlmann log=true + if (x_max >= 20) + { + std::cout << "Setting ellint_2 x range to [-1, 1]" << std::endl; + x_max = 1; + x_min = -1; + } + if (y_max >= 20) + { + std::cout << "Setting ellint_2 y range to [0, 1.5]" << std::endl; + y_max = 1.5; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for ellint_2" << std::endl; + log_scale = true; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default ellint_1 color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "ellint_3") + { + the_function = boost::math::ellint_3; + function_name = arg; + // x_max=1 y_max=1.5 kindlmann log=true + if (x_max >= 20) + { + std::cout << "Setting ellint_3 x range to [-0.99, 0.99]" << std::endl; + x_max = 0.99; + x_min = -0.99; + } + if (y_max >= 20) + { + std::cout << "Setting ellint_3 y range to [0, 1]" << std::endl; + y_max = 1; + } + if (log_scale == false) + { + std::cout << "Turning on log scale for ellint_3" << std::endl; + log_scale = true; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default ellint_3 color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "jacobi_zeta") + { + the_function = boost::math::jacobi_zeta; + function_name = arg; + // x_max=1 y_max=1.5 kindlmann log=true + if (x_max >= 20) + { + std::cout << "Setting jacobi_zeta x range to [-0.99, 0.99]" << std::endl; + x_max = 0.99; + x_min = -0.99; + } + if (y_max >= 20) + { + std::cout << "Setting jacobi_zeta y range to [0, 1]" << std::endl; + y_max = 0.99; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default jacobi_zeta color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "heuman_lambda") + { + the_function = boost::math::heuman_lambda; + function_name = arg; + // x_max=1 y_max=1.5 kindlmann log=true + if (x_max >= 20) + { + std::cout << "Setting heuman_lambda x range to [-0.99, 0.99]" << std::endl; + x_max = 0.99; + x_min = -0.99; + } + if (y_max >= 20) + { + std::cout << "Setting heuman_lambda y range to [0, 1]" << std::endl; + y_max = 0.99; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default heuman_lambda color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "jacobi_theta1") + { + the_function = boost::math::jacobi_theta1; + function_name = arg; + if (y_max >= 20) + { + std::cout << "Setting jacobi_theta1 y range to [0, 1]" << std::endl; + y_max = 0.99; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default jacobi_theta1 color map to kindlmann" << std::endl; + requested_color_map = "kindlmann"; + color_map = boost::math::tools::kindlmann<Real>; + } + } + else if (arg == "1F1") + { + the_function = hypergeometric_1F1_at_half; + function_name = arg; + if (x_min >= 0) + { + std::cout << "Setting 1F1 x range to [-20,20]" << std::endl; + x_min = -20; + x_max = 20; + } + if (y_min >= 0) + { + std::cout << "Setting 1F1 y range to [-20,20]" << std::endl; + y_min = -20; + y_max = 20; + } + if (requested_color_map == "viridis") + { + std::cout << "Setting default 1F1 color map to extended_kindlmann" << std::endl; + requested_color_map = "extended_kindlmann"; + color_map = boost::math::tools::extended_kindlmann<Real>; + } + if (!log_scale) + { + std::cout << "Turning on logarithmic scale for 1F1" << std::endl; + log_scale = true; + } + } + else if (arg == "help") + { + show_help(); + return 0; + } + else + { + std::cerr << "Could not recognize argument " << argv[i] << ".\n\n"; + show_help(); + return 1; + } + } + + std::vector<std::uint8_t> img(4*image_width*image_height, 0); + std::vector<Real> points(image_width*image_height, 0); + + Real min_value{ std::numeric_limits<Real>::infinity() }, max_value{ -std::numeric_limits<Real>::infinity() }; + // + // Get a matrix of points: + // + for (int64_t i = 0; i < image_width; ++i) + { + for (int64_t j = 0; j < image_height; ++j) + { + double x = x_max - (image_width - i) * (x_max - x_min) / image_width; + double y = y_max - (image_height - j) * (y_max - y_min) / image_height; + + Real p = the_function(x, y); + if (std::isnan(p)) + std::cerr << "Ooops, got a NaN" << std::endl; + if (p < min_value) + min_value = p; + if (p > max_value) + max_value = p; + points[i + image_width * (image_height - j - 1)] = p; + } + } + std::cout << "Function range is: [" << std::setprecision(3) << min_value << "," << max_value << "]\n"; + // + // Handle log scale, the formula differs depending on whether we have found negative values or not: + // + if (log_scale) + { + Real new_max = -std::numeric_limits<Real>::infinity(); + Real new_min = std::numeric_limits<Real>::infinity(); + for (int64_t i = 0; i < points.size(); ++i) + { + Real p = points[i]; + if (min_value <= 0) + p = boost::math::sign(p) * log10(1 + std::fabs(p * boost::math::constants::ln_ten<Real>())); + else + p = log(p); + if (std::isnan(p)) + std::cerr << "Ooops, got a NaN" << std::endl; + if (p < new_min) + new_min = p; + if (p > new_max) + new_max = p; + points[i] = p; + } + max_value = new_max; + min_value = new_min; + std::cout << "Function range is: [" << std::setprecision(3) << min_value << "," << max_value << "]\n"; + } + + // + // Normalize the points so they are all in [0,1] + // + for (int64_t i = 0; i < points.size(); ++i) + { + double p = points[i]; + p -= min_value; + p /= (max_value - min_value); + points[i] = p; + } + // + // debugging, adds an alternating 0 and 1 row on the second half of the zeroth row: + // + if (debug) + { + for (int64_t i = image_width / 2; i < image_width; ++i) + points[image_width * (image_height - 1) + i] = i & 1 ? 1 : 0; + } + + // + // Now calculate the RGB bitmap from the points: + // + for (int64_t i = 0; i < image_width; ++i) + { + for (int64_t j = 0; j < image_height; ++j) + { + double p = points[i + image_width * j]; + auto c = boost::math::tools::to_8bit_rgba(color_map(p)); + int64_t idx = 4 * (image_width * j + i); + img[idx + 0] = c[0]; + img[idx + 1] = c[1]; + img[idx + 2] = c[2]; + img[idx + 3] = c[3]; + } + } + + // Requires lodepng.h + // See: https://github.com/lvandeve/lodepng for download and compilation instructions + write_png(requested_color_map + "_" + function_name + ".png", img, image_width, image_height); +} diff --git a/src/boost/libs/math/example/constants_eg1.cpp b/src/boost/libs/math/example/constants_eg1.cpp new file mode 100644 index 000000000..53516145e --- /dev/null +++ b/src/boost/libs/math/example/constants_eg1.cpp @@ -0,0 +1,192 @@ +// Copyright Paul Bristow 2013. +// Copyright John Maddock 2010. + +// 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) + +/*! \brief Examples of using the enhanced math constants. + \details This allows for access to constants via functions like @c pi(), + and also via namespaces, @c using @c namespace boost::math::double_constants; + called simply @c pi. +*/ + +#include <boost/math/constants/constants.hpp> + +#include <iostream> +using std::cout; +using std::endl; + +#include <limits> +using std::numeric_limits; + +/*! \brief Examples of a template function using constants. + \details This example shows using of constants from function calls like @c pi(), + rather than the 'cute' plain @c pi use in non-template applications. + + \tparam Real radius parameter that can be a built-in like float, double, + or a user-defined type like multiprecision. + \returns Area = pi * radius ^ 2 +*/ + +//[math_constants_eg1 +template<class Real> +Real area(Real r) +{ + using namespace boost::math::constants; + + return pi<Real>() * r * r; +} +//] [/math_constants_eg1] + +int main() +{ + + { // Boost.Math constants using function calls like pi(). + // using namespace boost::math::constants; + + using boost::math::constants::pi; + using boost::math::constants::one_div_two_pi; + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + std::size_t max_digits10 = 2 + std::numeric_limits<double>::digits * 3010/10000; +#else + std::size_t max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + + std::cout.precision(max_digits10); + cout << "double pi = boost::math::double_constants::pi = " << pi<double>() << endl; + // double pi = boost::math::double_constants::pi = 3.1415926535897931 + double r = 1.234567890123456789; + double d = pi<double>() * r * r; + + cout << "d = " << d << ", r = " << r << endl; + + float rf = 0.987654321987654321f; + + float pif = boost::math::constants::pi<float>(); + cout << "pidf = boost::math::constants::pi() = " << pif << endl; + // pidf = boost::math::float_constants::pi = 3.1415927410125732 + + //float df = pi * rf * rf; // conversion from 'const double' to 'float', possible loss of data. + float df = pif * rf * rf; + + cout << "df = " << df << ", rf = " << rf << endl; + + cout << "one_div_two_pi " << one_div_two_pi<double>() << endl; + + using boost::math::constants::one_div_two_pi; + + cout << "one_div_root_two_pi " << one_div_two_pi<double>() << endl; + } + + { // Boost math new constants using namespace selected values, like pi. + + //using namespace boost::math::float_constants; + using namespace boost::math::double_constants; + + double my2pi = two_pi; // Uses boost::math::double_constants::two_pi; + + cout << "double my2pi = " << my2pi << endl; + + using boost::math::float_constants::e; + float my_e = e; + cout << "float my_e " << my_e << endl; + + double my_pi = boost::math::double_constants::pi; + cout << "double my_pi = boost::math::double_constants::pi = " << my_pi << endl; + + // If you try to use two namespaces, this may, of course, create ambiguity: + // it is not too difficult to do this inadvertently. + using namespace boost::math::float_constants; + //cout << pi << endl; // error C2872: 'pi' : ambiguous symbol. + + } + { + +//[math_constants_ambiguity + // If you use more than one namespace, this will, of course, create ambiguity: + using namespace boost::math::double_constants; + using namespace boost::math::constants; + + //double my_pi = pi(); // error C2872: 'pi' : ambiguous symbol + //double my_pi2 = pi; // Context does not allow for disambiguation of overloaded function + + // It is also possible to create ambiguity inadvertently, + // perhaps in other peoples code, + // by making the scope of a namespace declaration wider than necessary, + // therefore is it prudent to avoid this risk by localising the scope of such definitions. +//] [/math_constants_ambiguity] + + } + + { // You can, of course, use both methods of access if both are fully qualified, for examples: + + //cout.precision(std::numeric_limits<double>::max_digits10);// Ideally. + cout.precision(2 + std::numeric_limits<double>::digits * 3010/10000); // If no max_digits10. + + double my_pi1 = boost::math::constants::pi<double>(); + double my_pid = boost::math::double_constants::pi; + cout << "boost::math::constants::pi<double>() = " << my_pi1 << endl + << "boost::math::double_constants::pi = " << my_pid << endl; + + // cout.precision(std::numeric_limits<float>::max_digits10); // Ideally. + cout.precision(2 + std::numeric_limits<double>::digits * 3010/10000); // If no max_digits10. + float my_pif = boost::math::float_constants::pi; + cout << "boost::math::float_constants::pi = " << my_pif << endl; + + } + + { // Use with templates + + // \warning it is important to be very careful with the type provided as parameter. + // For example, naively providing an @b integer instead of a floating-point type can be disastrous. + // cout << "Area = " << area(2) << endl; // warning : 'return' : conversion from 'double' to 'int', possible loss of data + // Failure to heed this warning can lead to very wrong answers! + // Area = 12 !! = 3 * 2 * 2 +//[math_constants_template_integer_type + //cout << "Area = " << area(2) << endl; // Area = 12! + cout << "Area = " << area(2.) << endl; // Area = 12.566371 + + // You can also avoid this by being explicit about the type of @c area. + cout << "Area = " << area<double>(2) << endl; + +//] [/math_constants_template_integer_type] + + + } +/* +{ + using boost::math::constants::pi; + //double my_pi3 = pi<double>(); // OK + //double my_pi4 = pi<>(); cannot find template type. + //double my_pi4 = pi(); // Can't find a function. + + } +*/ + +} // int main() + +/*[constants_eq1_output + +Output: + + double pi = boost::math::double_constants::pi = 3.1415926535897931 + d = 4.7882831840285398, r = 1.2345678901234567 + pidf = boost::math::constants::pi() = 3.1415927410125732 + df = 3.0645015239715576, rf = 0.98765432834625244 + one_div_two_pi 0.15915494309189535 + one_div_root_two_pi 0.15915494309189535 + double my2pi = 6.2831853071795862 + float my_e 2.7182817459106445 + double my_pi = boost::math::double_constants::pi = 3.1415926535897931 + boost::math::constants::pi<double>() = 3.1415926535897931 + boost::math::double_constants::pi = 3.1415926535897931 + boost::math::float_constants::pi = 3.1415927410125732 + Area = 12.566370614359172 + Area = 12.566370614359172 + + +] [/constants_eq1_output] +*/ diff --git a/src/boost/libs/math/example/continued_fractions.cpp b/src/boost/libs/math/example/continued_fractions.cpp new file mode 100644 index 000000000..852a8e672 --- /dev/null +++ b/src/boost/libs/math/example/continued_fractions.cpp @@ -0,0 +1,150 @@ +// (C) Copyright John Maddock 2018. +// 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) + +#include <boost/math/tools/fraction.hpp> +#include <iostream> +#include <complex> +#include <boost/multiprecision/cpp_complex.hpp> + +//[golden_ratio_1 +template <class T> +struct golden_ratio_fraction +{ + typedef T result_type; + + result_type operator()() + { + return 1; + } +}; +//] + +//[cf_tan_fraction +template <class T> +struct tan_fraction +{ +private: + T a, b; +public: + tan_fraction(T v) + : a(-v * v), b(-1) + {} + + typedef std::pair<T, T> result_type; + + std::pair<T, T> operator()() + { + b += 2; + return std::make_pair(a, b); + } +}; +//] +//[cf_tan +template <class T> +T tan(T a) +{ + tan_fraction<T> fract(a); + return a / continued_fraction_b(fract, std::numeric_limits<T>::epsilon()); +} +//] +//[cf_expint_fraction +template <class T> +struct expint_fraction +{ + typedef std::pair<T, T> result_type; + expint_fraction(unsigned n_, T z_) : b(z_ + T(n_)), i(-1), n(n_) {} + std::pair<T, T> operator()() + { + std::pair<T, T> result = std::make_pair(-static_cast<T>((i + 1) * (n + i)), b); + b += 2; + ++i; + return result; + } +private: + T b; + int i; + unsigned n; +}; +//] +//[cf_expint +template <class T> +inline std::complex<T> expint_as_fraction(unsigned n, std::complex<T> const& z) +{ + std::uintmax_t max_iter = 1000; + expint_fraction<std::complex<T> > f(n, z); + std::complex<T> result = boost::math::tools::continued_fraction_b( + f, + std::complex<T>(std::numeric_limits<T>::epsilon()), + max_iter); + result = exp(-z) / result; + return result; +} +//] +//[cf_upper_gamma_fraction +template <class T> +struct upper_incomplete_gamma_fract +{ +private: + typedef typename T::value_type scalar_type; + T z, a; + int k; +public: + typedef std::pair<T, T> result_type; + + upper_incomplete_gamma_fract(T a1, T z1) + : z(z1 - a1 + scalar_type(1)), a(a1), k(0) + { + } + + result_type operator()() + { + ++k; + z += scalar_type(2); + return result_type(scalar_type(k) * (a - scalar_type(k)), z); + } +}; +//] +//[cf_gamma_Q +template <class T> +inline std::complex<T> gamma_Q_as_fraction(const std::complex<T>& a, const std::complex<T>& z) +{ + upper_incomplete_gamma_fract<std::complex<T> > f(a, z); + std::complex<T> eps(std::numeric_limits<T>::epsilon()); + return pow(z, a) / (exp(z) *(z - a + T(1) + boost::math::tools::continued_fraction_a(f, eps))); +} +//] +inline boost::multiprecision::cpp_complex_50 gamma_Q_as_fraction(const boost::multiprecision::cpp_complex_50& a, const boost::multiprecision::cpp_complex_50& z) +{ + upper_incomplete_gamma_fract<boost::multiprecision::cpp_complex_50> f(a, z); + boost::multiprecision::cpp_complex_50 eps(std::numeric_limits<boost::multiprecision::cpp_complex_50::value_type>::epsilon()); + return pow(z, a) / (exp(z) * (z - a + 1 + boost::math::tools::continued_fraction_a(f, eps))); +} + + +int main() +{ + using namespace boost::math::tools; + + //[cf_gr + golden_ratio_fraction<double> func; + double gr = continued_fraction_a( + func, + std::numeric_limits<double>::epsilon()); + std::cout << "The golden ratio is: " << gr << std::endl; + //] + + std::cout << tan(0.5) << std::endl; + + std::complex<double> arg(3, 2); + std::cout << expint_as_fraction(5, arg) << std::endl; + + std::complex<double> a(3, 3), z(3, 2); + std::cout << gamma_Q_as_fraction(a, z) << std::endl; + + boost::multiprecision::cpp_complex_50 am(3, 3), zm(3, 2); + std::cout << gamma_Q_as_fraction(am, zm) << std::endl; + + return 0; +} diff --git a/src/boost/libs/math/example/cstdfloat_example.cpp b/src/boost/libs/math/example/cstdfloat_example.cpp new file mode 100644 index 000000000..29af3a254 --- /dev/null +++ b/src/boost/libs/math/example/cstdfloat_example.cpp @@ -0,0 +1,487 @@ +// Copyright John Maddock 2014 +// Copyright Christopher Kormanyos 2014. +// Copyright Paul A. Bristow 2016. + +// 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) + +// Contains Quickbook snippets as C++ comments - do not remove. + +/* +`This example shows use of a specified-width floating-point typedef +to evaluate a moderately complex math function using +[@http://en.wikipedia.org/wiki/Double-precision_floating-point_format IEEE754 64-bit double-precision]. +about 15 decimal digits `std::numeric_limits<boost::float64_t>::digits10`, +(but never exceeding 17 decimal digits `std::numeric_limits<boost::float64_t>::max_digits10`). + +The Jahnke-Emden lambda function is described at + +Weisstein, Eric W. "Lambda Function." From MathWorld--A Wolfram Web Resource. +http://mathworld.wolfram.com/LambdaFunction.html + +E. Jahnke and F. Emden, "Tables of Functions with Formulae and Curves," +Dover, New York, 4th ed., (1945), pages 180-188. + +*/ + +//[cstdfloat_example_1 +#include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include! +#include <cmath> // for pow function. +#include <boost/math/special_functions.hpp> // For gamma function. +//] [/cstdfloat_example_1] + +#include <iostream> + +/*! +Function max_digits10 +Returns maximum number of possibly significant decimal digits for a floating-point type FPT, +even for older compilers/standard libraries that +lack support for std::numeric_limits<FPT>::max_digits10, +when the Kahan formula 2 + binary_digits * 0.3010 is used instead. +Also provides the correct result for Visual Studio 2010 +(where the value 8 provided for float is wrong). +*/ +namespace boost +{ +template <typename FPT> +const int max_digits10() +{ +// Since max_digits10 is not defined (or wrong) on older systems, define a local max_digits10. + // Usage: int m = max_digits10<boost::float64_t>(); + const int m = +#if (defined BOOST_NO_CXX11_NUMERIC_LIMITS) || (_MSC_VER == 1600) // is wrongly 8 not 9 for VS2010. + 2 + std::numeric_limits<FPT>::digits * 3010/10000; +#else + std::numeric_limits<FPT>::max_digits10; +#endif + return m; +} +} // namespace boost + +//`Define the Jahnke-Emden_lambda function. +//[cstdfloat_example_2 +boost::float64_t jahnke_emden_lambda(boost::float64_t v, boost::float64_t x) +{ + const boost::float64_t gamma_v_plus_one = boost::math::tgamma(v + 1); + const boost::float64_t x_half_pow_v = std::pow(x /2, v); + + return gamma_v_plus_one * boost::math::cyl_bessel_j(x, v) / x_half_pow_v; +} +//] [/cstdfloat_example_2] + +int main() +{ + std::cout.setf(std::ios::showpoint); // show all significant trailing zeros. + + long double p = 1.L; + //std::cout.precision(std::numeric_limits<long double>::digits10); + + std::cout << "pi = " << p << std::endl; + +//[cstdfloat_example_3 +//`Ensure that all possibly significant digits (17) including trailing zeros are shown. + + std::cout.precision(std::numeric_limits<boost::float64_t>::max_digits10); + std::cout.setf(std::ios::showpoint); // Show trailing zeros. + + try + { // Always use try'n'catch blocks to ensure any error messages are displayed. + + // Evaluate and display an evaluation of the Jahnke-Emden lambda function: + boost::float64_t v = 1.; + boost::float64_t x = 1.; + std::cout << jahnke_emden_lambda(v, x) << std::endl; // 0.88010117148986700 +//] [/cstdfloat_example_3] + + // We can show some evaluations with various precisions: + { // float64_t + for (int i = 0; i < 10; i++) + { + std::cout << std::setprecision(2) << boost::float64_t(i) << ' ' + << std::setprecision(std::numeric_limits<boost::float64_t>::max_digits10) + << jahnke_emden_lambda(boost::float64_t(i), v) << std::endl; // + } + } + { // floatmax_t = the maximum available on this platform. + for (int i = 0; i < 10; i++) + { + std::cout << std::setprecision(2) << boost::floatmax_t(i) << ' ' + << std::setprecision(std::numeric_limits<boost::floatmax_t>::max_digits10) + << jahnke_emden_lambda(boost::floatmax_t(i), v) << std::endl; // + } + } + // Show the precision of long double (this might be 64, 80 or 128 bits). + std::cout << "Floating-point type long double is available with:" << std::endl; + std::cout << " std::numeric_limits<long double>::digits10 == " + << std::numeric_limits<long double>::digits10 << std::endl; // 18 + std::cout << " std::numeric_limits<long double>::max_digits10 == " + << std::numeric_limits<long double>::max_digits10 << std::endl; // 21 + long double p = boost::math::constants::pi<double>(); + std::cout.precision(std::numeric_limits<long double>::digits10); + std::cout << "pi = " << p << std::endl; + +//[cstdfloat_constant_2 +//`These allow floating-point [*constants of at least the specified width] to be declared: + + // Declare Archimedes' constant using float32_t with approximately 7 decimal digits of precision. + static const boost::float32_t pi = BOOST_FLOAT32_C(3.1415926536); + + // Declare the Euler-gamma constant with approximately 15 decimal digits of precision. + static const boost::float64_t euler = + BOOST_FLOAT64_C(0.57721566490153286060651209008240243104216); + + // Declare the Golden Ratio constant with the maximum decimal digits of precision that the platform supports. + static const boost::floatmax_t golden_ratio = + BOOST_FLOATMAX_C(1.61803398874989484820458683436563811772); +//] [/cstdfloat_constant_2] + +// http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/float128.html +//[cstdfloat_constant_1 +// Display the constant pi to the maximum available precision. + boost::floatmax_t pi_max = boost::math::constants::pi<boost::floatmax_t>(); + std::cout.precision(std::numeric_limits<boost::floatmax_t>::digits10); + std::cout << "Most precise pi = " << pi_max << std::endl; +// If floatmax_t is float_128_t, then +// Most precise pi = 3.141592653589793238462643383279503 +//] [/cstdfloat_constant_1] + +// Test all the floating-point precisions in turn, and if they are available +// then display how many decimal digits of precision. +#ifdef BOOST_FLOAT16_C + std::cout << "Floating-point type boost::float16_t is available." << std::endl; +#else + std::cout << "Floating-point type boost::float16_t is NOT available." << std::endl; +#endif + +#ifdef BOOST_FLOAT32_C + std::cout << "Floating-point type boost::float32_t is available." << std::endl; + std::cout << " std::numeric_limits<boost::float32_t>::digits10 == " + << std::numeric_limits<boost::float32_t>::digits10 << std::endl; + std::cout << " std::numeric_limits<boost::float32_t>::max_digits10 == " + << std::numeric_limits<boost::float32_t>::max_digits10 << std::endl; +#else + std::cout << "Floating-point type boost::float32_t is NOT available." << std::endl; +#endif + +#ifdef BOOST_FLOAT64_C + std::cout << "Floating-point type boost::float64_t is available." << std::endl; + std::cout << " std::numeric_limits<boost::float64_t>::digits10 == " + << std::numeric_limits<boost::float64_t>::digits10 << std::endl; + std::cout << " std::numeric_limits<boost::float64_t>::max_digits10 == " + << std::numeric_limits<boost::float64_t>::max_digits10 << std::endl; +#else + std::cout << "Floating-point type boost::float64_t is NOT available." << std::endl; +#endif + +#ifdef BOOST_FLOAT80_C + std::cout << "Floating-point type boost::float80_t is available." << std::endl; + std::cout << " std::numeric_limits<boost::float80_t>::digits10 == " + << std::numeric_limits<boost::float80_t>::digits10 << std::endl; + std::cout << " std::numeric_limits<boost::float80_t>::max_digits10 == " + << std::numeric_limits<boost::float80_t>::max_digits10 << std::endl; +#else + std::cout << "Floating-point type boost::float80_t is NOT available." << std::endl; +#endif + +#ifdef BOOST_FLOAT128_C + std::cout << "Floating-point type boost::float128_t is available." << std::endl; + std::cout << " std::numeric_limits<boost::float128_t>::digits10 == " + << std::numeric_limits<boost::float128_t>::digits10 << std::endl; + std::cout << " std::numeric_limits<boost::float128_t>::max_digits10 == " + << std::numeric_limits<boost::float128_t>::max_digits10 << std::endl; +#else + std::cout << "Floating-point type boost::float128_t is NOT available." << std::endl; +#endif + +// Show some constants at a precision depending on the available type(s). +#ifdef BOOST_FLOAT16_C + std::cout.precision(boost::max_digits10<boost::float16_t>()); // Show all significant decimal digits, + std::cout.setf(std::ios::showpoint); // including all significant trailing zeros. + + std::cout << "BOOST_FLOAT16_C(123.456789012345678901234567890) = " + << BOOST_FLOAT16_C(123.456789012345678901234567890) << std::endl; + // BOOST_FLOAT16_C(123.456789012345678901234567890) = 123.45678901234568 +#endif + +//[floatmax_widths_1 +#ifdef BOOST_FLOAT32_C + std::cout.precision(boost::max_digits10<boost::float32_t>()); // Show all significant decimal digits, + std::cout.setf(std::ios::showpoint); // including all significant trailing zeros. + std::cout << "BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = " + << BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) << std::endl; + // BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = 123.456787 +#endif +//] [/floatmax_widths_1] + +#ifdef BOOST_FLOAT64_C + std::cout.precision(boost::max_digits10<boost::float64_t>()); // Show all significant decimal digits, + std::cout.setf(std::ios::showpoint); // including all significant trailing zeros. + std::cout << "BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = " + << BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) << std::endl; + // BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = 123.45678901234568 +#endif + +#ifdef BOOST_FLOAT80_C + std::cout.precision(boost::max_digits10<boost::float80_t>()); // Show all significant decimal digits, + std::cout.setf(std::ios::showpoint); // including all significant trailing zeros. + std::cout << "BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) = " + << BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) << std::endl; + // BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) = 123.456789012345678903 +#endif + +#ifdef BOOST_FLOAT128_C + std::cout.precision(boost::max_digits10<boost::float128_t>()); // Show all significant decimal digits, + std::cout.setf(std::ios::showpoint); // including all significant trailing zeros. + std::cout << "BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) = " + << BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) << std::endl; + // BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) = 123.456789012345678901234567890123453 +#endif + +/* +//[floatmax_widths_2 +BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = 123.456787 +BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = 123.45678901234568 +BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) = 123.456789012345678903 +BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) = 123.456789012345678901234567890123453 +//] [/floatmax_widths_2] +*/ + +// Display the precisions available for floatmax_t + +#ifdef BOOST_FLOATMAX_C + BOOST_MATH_ASSERT(std::numeric_limits<boost::floatmax_t>::is_specialized == true); + BOOST_MATH_ASSERT(std::numeric_limits<boost::floatmax_t>::is_iec559 == true); + BOOST_MATH_ASSERT(BOOST_FLOATMAX_C(0.) == 0); + + std::cout << "floatmax_t " << std::numeric_limits<boost::floatmax_t>::digits << " bits\n" // 113 + << std::numeric_limits<boost::floatmax_t>::digits10 << " decimal digits\n" // 34 + << std::numeric_limits<boost::floatmax_t>::max_digits10 << " max_digits\n" // 36 + << std::numeric_limits<boost::floatmax_t>::radix << " radix\n" + << std::endl; + + int significand_bits = std::numeric_limits<boost::floatmax_t>::digits; + int exponent_max = std::numeric_limits<boost::floatmax_t>::max_exponent; + int exponent_min = std::numeric_limits<boost::floatmax_t>::min_exponent; + int exponent_bits = 1 + static_cast<int>(std::log2(std::numeric_limits<boost::floatmax_t>::max_exponent)); + int sign_bits = std::numeric_limits<boost::floatmax_t>::is_signed; + + std::cout << "significand_bits (including one implicit bit)" << significand_bits + << ", exponent_bits " << exponent_bits + << ", sign_bits " << sign_bits << std::endl; + + // One can compute the total number of bits in the floatmax_t, + // but probably not at compile time. + + std::cout << "bits = " << significand_bits + exponent_bits + sign_bits -1 << std::endl; + // -1 to take account of the implicit bit that is not part of the physical layout. + + // One can compare typedefs (but, of course, only those that are defined for the platform in use.) + std::cout.setf(std::ios::boolalpha); + std::cout << "double, double: " << std::is_same<double, double>::value << std::endl; + bool b = boost::is_same<boost::floatmax_t, boost::float64_t>::value; + std::cout << "boost::is_same<boost::floatmax_t, boost::float64_t>::value; " << b << std::endl; + std::cout << "floatmax_t, float64_t: " + << std::is_same<boost::floatmax_t, boost::float64_t>::value << std::endl; + +/*`So the simplest way of obtaining the total number of bits in the floatmax_t +is to infer it from the std::numeric_limits<>::digits value. +This is possible because the type, must be a IEEE754 layout. */ +//[floatmax_1 + const int fpbits = + (std::numeric_limits<boost::floatmax_t>::digits == 113) ? 128 : + (std::numeric_limits<boost::floatmax_t>::digits == 64) ? 80 : + (std::numeric_limits<boost::floatmax_t>::digits == 53) ? 64 : + (std::numeric_limits<boost::floatmax_t>::digits == 24) ? 32 : + (std::numeric_limits<boost::floatmax_t>::digits == 11) ? 16 : + 0; // Unknown - not IEEE754 format. + std::cout << fpbits << " bits." << std::endl; +//] [/floatmax_1] +#endif + + } + catch (std::exception ex) + { // Display details about why any exceptions are thrown. + std::cout << "Thrown exception " << ex.what() << std::endl; + } + +} // int main() + +/* +[cstdfloat_output + +GCC 4.8.1 with quadmath + + pi = 1.00000 + 0.88010117148986700 + 0.0 0.0000000000000000 + 1.0 0.88010117148986700 + 2.0 4.6137984620549872 + 3.0 16.274830009244951 + 4.0 -25.360637961042869 + 5.0 -1257.9038883512264 + 6.0 -12749.592182518225 + 7.0 -3020.9830849309437 + 8.0 2421897.6013183584 + 9.0 45577595.449204877 + 0.0 0.00000000000000000000000000000000000 + 1.0 0.880101171489866995756301548681221902 + 2.0 4.61379846205498722611082484945654869 + 3.0 16.2748300092449511566883302293717861 + 4.0 -25.3606379610428689375112298876047134 + 5.0 -1257.90388835122644195507746189832687 + 6.0 -12749.5921825182249449426308274269104 + 7.0 -3020.98308493094373261556029319763184 + 8.0 2421897.60131835844367742538452148438 + 9.0 45577595.4492048770189285278320312500 + Floating-point type long double is available with: + std::numeric_limits<long double>::digits10 == 18 + std::numeric_limits<long double>::max_digits10 == 21 + pi = 3.14159265358979312 + Most precise pi = 3.141592653589793238462643383279503 + Floating-point type boost::float16_t is NOT available. + Floating-point type boost::float32_t is available. + std::numeric_limits<boost::float32_t>::digits10 == 6 + std::numeric_limits<boost::float32_t>::max_digits10 == 9 + Floating-point type boost::float64_t is available. + std::numeric_limits<boost::float64_t>::digits10 == 15 + std::numeric_limits<boost::float64_t>::max_digits10 == 17 + Floating-point type boost::float80_t is available. + std::numeric_limits<boost::float80_t>::digits10 == 18 + std::numeric_limits<boost::float80_t>::max_digits10 == 21 + Floating-point type boost::float128_t is available. + std::numeric_limits<boost::float128_t>::digits10 == 34 + std::numeric_limits<boost::float128_t>::max_digits10 == 36 + BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = 123.456787 + BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = 123.45678901234568 + BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) = 123.456789012345678903 + BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) = 123.456789012345678901234567890123453 + floatmax_t 113 bits + 34 decimal digits + 36 max_digits + 2 radix + + significand_bits (including one implicit bit)113, exponent_bits 15, sign_bits 1 + bits = 128 + double, double: true + boost::is_same<boost::floatmax_t, boost::float64_t>::value; false + floatmax_t, float64_t: false + 128 bits. + + RUN SUCCESSFUL (total time: 53ms) + +GCC 6.1.1 + +pi = 1.00000 +0.88010117148986700 +0.0 0.0000000000000000 +1.0 0.88010117148986700 +2.0 4.6137984620549872 +3.0 16.274830009244951 +4.0 -25.360637961042869 +5.0 -1257.9038883512264 +6.0 -12749.592182518225 +7.0 -3020.9830849309437 +8.0 2421897.6013183584 +9.0 45577595.449204877 +0.0 0.00000000000000000000000000000000000 +1.0 0.880101171489866995756301548681221902 +2.0 4.61379846205498722611082484945654869 +3.0 16.2748300092449511566883302293717861 +4.0 -25.3606379610428689375112298876047134 +5.0 -1257.90388835122644195507746189832687 +6.0 -12749.5921825182249449426308274269104 +7.0 -3020.98308493094373261556029319763184 +8.0 2421897.60131835844367742538452148438 +9.0 45577595.4492048770189285278320312500 +Floating-point type long double is available with: + std::numeric_limits<long double>::digits10 == 18 + std::numeric_limits<long double>::max_digits10 == 21 +pi = 3.14159265358979312 +Most precise pi = 3.14159265358979323846264338327950 +Floating-point type boost::float16_t is NOT available. +Floating-point type boost::float32_t is available. + std::numeric_limits<boost::float32_t>::digits10 == 6 + std::numeric_limits<boost::float32_t>::max_digits10 == 9 +Floating-point type boost::float64_t is available. + std::numeric_limits<boost::float64_t>::digits10 == 15 + std::numeric_limits<boost::float64_t>::max_digits10 == 17 +Floating-point type boost::float80_t is available. + std::numeric_limits<boost::float80_t>::digits10 == 18 + std::numeric_limits<boost::float80_t>::max_digits10 == 21 +Floating-point type boost::float128_t is available. + std::numeric_limits<boost::float128_t>::digits10 == 33 + std::numeric_limits<boost::float128_t>::max_digits10 == 36 +BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = 123.456787 +BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = 123.45678901234568 +BOOST_FLOAT80_C(123.4567890123456789012345678901234567890) = 123.456789012345678903 +BOOST_FLOAT128_C(123.4567890123456789012345678901234567890) = 123.456789012345678901234567890123453 +floatmax_t 113 bits +33 decimal digits +36 max_digits +2 radix + +significand_bits (including one implicit bit)113, exponent_bits 15, sign_bits 1 +bits = 128 +double, double: true +boost::is_same<boost::floatmax_t, boost::float64_t>::value; false +floatmax_t, float64_t: false +128 bits. + + + MSVC 2013 64-bit + + 1> pi = 1.00000 + 1> 0.88010117148986700 + 1> 0.00 0.00000000000000000 + 1> 1.0 0.88010117148986700 + 1> 2.0 4.6137984620549854 + 1> 3.0 16.274830009244948 + 1> 4.0 -25.360637961042869 + 1> 5.0 -1257.9038883512258 + 1> 6.0 -12749.592182518225 + 1> 7.0 -3020.9830849309396 + 1> 8.0 2421897.6013183575 + 1> 9.0 45577595.449204892 + 1> 0.00 0.00000000000000000 + 1> 1.0 0.88010117148986700 + 1> 2.0 4.6137984620549854 + 1> 3.0 16.274830009244948 + 1> 4.0 -25.360637961042869 + 1> 5.0 -1257.9038883512258 + 1> 6.0 -12749.592182518225 + 1> 7.0 -3020.9830849309396 + 1> 8.0 2421897.6013183575 + 1> 9.0 45577595.449204892 + 1> Floating-point type long double is available with: + 1> std::numeric_limits<long double>::digits10 == 15 + 1> std::numeric_limits<long double>::max_digits10 == 17 + 1> pi = 3.14159265358979 + 1> Most precise pi = 3.14159265358979 + 1> Floating-point type boost::float16_t is NOT available. + 1> Floating-point type boost::float32_t is available. + 1> std::numeric_limits<boost::float32_t>::digits10 == 6 + 1> std::numeric_limits<boost::float32_t>::max_digits10 == 9 + 1> Floating-point type boost::float64_t is available. + 1> std::numeric_limits<boost::float64_t>::digits10 == 15 + 1> std::numeric_limits<boost::float64_t>::max_digits10 == 17 + 1> Floating-point type boost::float80_t is NOT available. + 1> Floating-point type boost::float128_t is NOT available. + 1> BOOST_FLOAT32_C(123.4567890123456789012345678901234567890) = 123.456787 + 1> BOOST_FLOAT64_C(123.4567890123456789012345678901234567890) = 123.45678901234568 + 1> floatmax_t 53 bits + 1> 15 decimal digits + 1> 17 max_digits + 1> 2 radix + 1> + 1> significand_bits (including one implicit bit)53, exponent_bits 11, sign_bits 1 + 1> bits = 64 + 1> double, double: true + 1> boost::is_same<boost::floatmax_t, boost::float64_t>::value; true + 1> floatmax_t, float64_t: true + 1> 64 bits. +] [/cstdfloat_output] + + +*/ + diff --git a/src/boost/libs/math/example/daubechies_wavelets/bench.cpp b/src/boost/libs/math/example/daubechies_wavelets/bench.cpp new file mode 100644 index 000000000..bdff1dbf8 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/bench.cpp @@ -0,0 +1,541 @@ +/* + * Copyright Nick Thompson, 2020 + * 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) + */ + +#include <cmath> +#include <random> +#include <benchmark/benchmark.h> +#include <boost/random/uniform_real_distribution.hpp> +#include <boost/math/special_functions/daubechies_scaling.hpp> +#include <boost/math/quadrature/wavelet_transforms.hpp> +#include <boost/math/interpolators/cubic_hermite.hpp> +#include <boost/math/interpolators/detail/quintic_hermite_detail.hpp> +#include <boost/math/interpolators/detail/septic_hermite_detail.hpp> + +double exponential(benchmark::IterationCount j) +{ + return std::pow(2, j); +} + + +template<typename Real, int p> +void DyadicGrid(benchmark::State & state) +{ + int j = state.range(0); + size_t s = 0; + for (auto _ : state) + { + auto v = boost::math::daubechies_scaling_dyadic_grid<Real, 4, 0>(j); + benchmark::DoNotOptimize(v[0]); + s = v.size(); + } + + state.counters["RAM"] = s*sizeof(Real); + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(DyadicGrid, double, 4)->DenseRange(3, 22, 1)->Unit(benchmark::kMillisecond)->Complexity(exponential); +//BENCHMARK_TEMPLATE(DyadicGrid, double, 8)->DenseRange(3, 22, 1)->Unit(benchmark::kMillisecond)->Complexity(exponential); +//BENCHMARK_TEMPLATE(DyadicGrid, double, 11)->DenseRange(3,22,1)->Unit(benchmark::kMillisecond)->Complexity(exponential); + +uint64_t s[2] = { 0x41, 0x29837592 }; + +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +uint64_t next(void) { + const uint64_t s0 = s[0]; + uint64_t s1 = s[1]; + const uint64_t result = s0 + s1; + + s1 ^= s0; + s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b + s[1] = rotl(s1, 36); // c + + return result; +} + +double uniform() { + return next()*(1.0/18446744073709551616.0); +} + +template<typename Real, int p> +void ScalingEvaluation(benchmark::State & state) +{ + auto phi = boost::math::daubechies_scaling<Real, p>(); + Real x = 0; + Real step = std::numeric_limits<Real>::epsilon(); + for (auto _ : state) + { + benchmark::DoNotOptimize(phi(x)); + x += step; + } +} + + +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 2); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 3); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 4); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 5); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 6); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 7); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 8); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 9); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 10); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 11); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 12); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 13); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 14); +BENCHMARK_TEMPLATE(ScalingEvaluation, double, 15); + +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 2); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 3); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 4); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 5); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 6); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 7); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 8); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 9); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 10); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 11); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 12); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 13); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 14); +BENCHMARK_TEMPLATE(ScalingEvaluation, float, 15); + + +template<typename Real, int p> +void ScalingConstructor(benchmark::State & state) +{ + for (auto _ : state) + { + benchmark::DoNotOptimize(boost::math::daubechies_scaling<Real, p>()); + } +} + +BENCHMARK_TEMPLATE(ScalingConstructor, float, 2)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, double, 2)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, long double, 2)->Unit(benchmark::kMillisecond); + +BENCHMARK_TEMPLATE(ScalingConstructor, float, 3)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, double, 3)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, long double, 3)->Unit(benchmark::kMillisecond); + +BENCHMARK_TEMPLATE(ScalingConstructor, float, 4)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, double, 4)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, long double, 4)->Unit(benchmark::kMillisecond); + +BENCHMARK_TEMPLATE(ScalingConstructor, float, 5)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, double, 5)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, long double, 5)->Unit(benchmark::kMillisecond); + +BENCHMARK_TEMPLATE(ScalingConstructor, float, 11)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, double, 11)->Unit(benchmark::kMillisecond); +BENCHMARK_TEMPLATE(ScalingConstructor, long double, 11)->Unit(benchmark::kMillisecond); + +template<typename Real> +void CubicHermite(benchmark::State & state) +{ + using boost::math::interpolators::cubic_hermite; + auto n = state.range(0); + std::vector<Real> x(n); + std::vector<Real> y(n); + std::vector<Real> dydx(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + x[0] = dis(rd); + y[0] = dis(rd); + dydx[0] = dis(rd); + for (size_t i = 1; i < y.size(); ++i) + { + x[i] = x[i-1] + dis(rd); + y[i] = dis(rd); + dydx[i] = dis(rd); + } + Real x0 = x.front(); + Real xf = x.back(); + + auto qh = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); + Real t = x0; + Real step = uniform()*(xf-x0)/2048; + for (auto _ : state) + { + benchmark::DoNotOptimize(qh(t)); + t += step; + if (t >= xf) + { + t = x0; + step = uniform()*(xf-x0)/2048; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(CubicHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(benchmark::oLogN); + +template<typename Real> +void CardinalCubicHermite(benchmark::State & state) +{ + using boost::math::interpolators::detail::cardinal_cubic_hermite_detail; + auto n = state.range(0); + std::vector<Real> y(n); + std::vector<Real> dydx(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < y.size(); ++i) + { + y[i] = uniform(); + dydx[i] = uniform(); + } + + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (y.size()-1)*dx; + + auto qh = cardinal_cubic_hermite_detail(std::move(y), std::move(dydx), x0, dx); + Real x = x0; + Real step = uniform()*(xf-x0)/2048; + for (auto _ : state) + { + benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); + x += step; + if (x >= xf) + { + x = x0; + step = uniform()*(xf-x0)/2048; + } + } + state.SetComplexityN(state.range(0)); +} + +template<typename Real> +void CardinalCubicHermiteAOS(benchmark::State & state) +{ + auto n = state.range(0); + std::vector<std::array<Real, 2>> dat(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < dat.size(); ++i) + { + dat[i][0] = uniform(); + dat[i][1] = uniform(); + } + + using boost::math::interpolators::detail::cardinal_cubic_hermite_detail_aos; + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (dat.size()-1)*dx; + auto qh = cardinal_cubic_hermite_detail_aos(std::move(dat), x0, dx); + Real x = 0; + Real step = uniform()*(xf-x0)/2048; + for (auto _ : state) + { + benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); + x += step; + if (x >= xf) + { + x = x0; + step = uniform()*(xf-x0)/2048; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(CardinalCubicHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<21)->Complexity(benchmark::o1); +BENCHMARK_TEMPLATE(CardinalCubicHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<21)->Complexity(benchmark::o1); + +template<class Real> +void SineEvaluation(benchmark::State& state) +{ + std::default_random_engine gen; + std::uniform_real_distribution<Real> x_dis(0, 3.14159); + + Real x = x_dis(gen); + for (auto _ : state) + { + benchmark::DoNotOptimize(std::sin(x)); + x += std::numeric_limits<Real>::epsilon(); + } +} + +BENCHMARK_TEMPLATE(SineEvaluation, float); +BENCHMARK_TEMPLATE(SineEvaluation, double); +BENCHMARK_TEMPLATE(SineEvaluation, long double); + +template<class Real> +void ExpEvaluation(benchmark::State& state) +{ + std::default_random_engine gen; + std::uniform_real_distribution<Real> x_dis(0, 3.14159); + + Real x = x_dis(gen); + for (auto _ : state) + { + benchmark::DoNotOptimize(std::exp(x)); + x += std::numeric_limits<Real>::epsilon(); + } +} + +BENCHMARK_TEMPLATE(ExpEvaluation, float); +BENCHMARK_TEMPLATE(ExpEvaluation, double); +BENCHMARK_TEMPLATE(ExpEvaluation, long double); + +template<class Real> +void PowEvaluation(benchmark::State& state) +{ + std::default_random_engine gen; + std::uniform_real_distribution<Real> x_dis(0, 3.14159); + + Real x = x_dis(gen); + for (auto _ : state) + { + benchmark::DoNotOptimize(std::pow(x, x+1)); + x += std::numeric_limits<Real>::epsilon(); + } +} + +BENCHMARK_TEMPLATE(PowEvaluation, float); +BENCHMARK_TEMPLATE(PowEvaluation, double); +BENCHMARK_TEMPLATE(PowEvaluation, long double); + + +template<typename Real> +void CardinalQuinticHermite(benchmark::State & state) +{ + using boost::math::interpolators::detail::cardinal_quintic_hermite_detail; + auto n = state.range(0); + std::vector<Real> y(n); + std::vector<Real> dydx(n); + std::vector<Real> d2ydx2(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < y.size(); ++i) + { + y[i] = uniform(); + dydx[i] = uniform(); + d2ydx2[i] = uniform(); + } + + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (y.size()-1)*dx; + + auto qh = cardinal_quintic_hermite_detail(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); + Real x = 0; + Real step = uniform()*(xf-x0)/2048; + for (auto _ : state) + { + benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); + x += step; + if (x >= xf) + { + x = x0; + step = uniform()*(xf-x0)/2048; + } + } + state.SetComplexityN(state.range(0)); +} + +template<typename Real> +void CardinalQuinticHermiteAOS(benchmark::State & state) +{ + auto n = state.range(0); + std::vector<std::array<Real, 3>> dat(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < dat.size(); ++i) + { + dat[i][0] = uniform(); + dat[i][1] = uniform(); + dat[i][2] = uniform(); + } + + using boost::math::interpolators::detail::cardinal_quintic_hermite_detail_aos; + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (dat.size()-1)*dx; + auto qh = cardinal_quintic_hermite_detail_aos(std::move(dat), x0, dx); + Real x = x0; + Real step = uniform()*(xf-x0)/2048; + for (auto _ : state) { + benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); + x += step; + if (x >= xf) + { + x = x0; + step = uniform()*(xf-x0)/2048; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(CardinalQuinticHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<22)->Complexity(benchmark::o1); +BENCHMARK_TEMPLATE(CardinalQuinticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<22)->Complexity(benchmark::o1); + +template<typename Real> +void SepticHermite(benchmark::State & state) +{ + using boost::math::interpolators::detail::septic_hermite_detail; + auto n = state.range(0); + std::vector<Real> x(n); + std::vector<Real> y(n); + std::vector<Real> dydx(n); + std::vector<Real> d2ydx2(n); + std::vector<Real> d3ydx3(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + Real x0 = dis(rd); + x[0] = x0; + for (decltype(n) i = 1; i < n; ++i) + { + x[i] = x[i-1] + dis(rd); + } + for (size_t i = 0; i < y.size(); ++i) + { + y[i] = dis(rd); + dydx[i] = dis(rd); + d2ydx2[i] = dis(rd); + d3ydx3[i] = dis(rd); + } + + Real xf = x.back(); + + auto sh = septic_hermite_detail(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); + Real t = x0; + for (auto _ : state) + { + benchmark::DoNotOptimize(sh(t)); + t += xf/128; + if (t >= xf) + { + t = x0; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(SepticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); + + +template<typename Real> +void CardinalSepticHermite(benchmark::State & state) +{ + using boost::math::interpolators::detail::cardinal_septic_hermite_detail; + auto n = state.range(0); + std::vector<Real> y(n); + std::vector<Real> dydx(n); + std::vector<Real> d2ydx2(n); + std::vector<Real> d3ydx3(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < y.size(); ++i) + { + y[i] = dis(rd); + dydx[i] = dis(rd); + d2ydx2[i] = dis(rd); + d3ydx3[i] = dis(rd); + } + + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (y.size()-1)*dx; + + auto sh = cardinal_septic_hermite_detail(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); + Real x = 0; + for (auto _ : state) + { + benchmark::DoNotOptimize(sh.unchecked_evaluation(x)); + x += xf/128; + if (x >= xf) + { + x = x0; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(CardinalSepticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); + +template<typename Real> +void CardinalSepticHermiteAOS(benchmark::State & state) +{ + using boost::math::interpolators::detail::cardinal_septic_hermite_detail_aos; + auto n = state.range(0); + std::vector<std::array<Real, 4>> data(n); + std::random_device rd; + boost::random::uniform_real_distribution<Real> dis(Real(0), Real(1)); + for (size_t i = 0; i < data.size(); ++i) + { + for (size_t j = 0; j < 4; ++j) + { + data[i][j] = dis(rd); + } + } + + Real dx = Real(1)/Real(8); + Real x0 = 0; + Real xf = x0 + (data.size()-1)*dx; + + auto sh = cardinal_septic_hermite_detail_aos(std::move(data), x0, dx); + Real x = 0; + for (auto _ : state) + { + benchmark::DoNotOptimize(sh.unchecked_evaluation(x)); + x += xf/128; + if (x >= xf) + { + x = x0; + } + } + state.SetComplexityN(state.range(0)); +} + +BENCHMARK_TEMPLATE(CardinalSepticHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); + + +template<typename Real, int p> +void WaveletTransform(benchmark::State & state) +{ + auto psi = boost::math::daubechies_wavelet<Real, p>(); + auto f = [](Real t) { + return std::exp(-t*t); + }; + + auto Wf = boost::math::quadrature::daubechies_wavelet_transform(f, psi); + for (auto _ : state) + { + Real s = 1 + uniform(); + Real t = uniform(); + benchmark::DoNotOptimize(Wf(s, t)); + } +} + +BENCHMARK_TEMPLATE(WaveletTransform, float, 3); +BENCHMARK_TEMPLATE(WaveletTransform, float, 4); +BENCHMARK_TEMPLATE(WaveletTransform, float, 5); +BENCHMARK_TEMPLATE(WaveletTransform, float, 6); +BENCHMARK_TEMPLATE(WaveletTransform, float, 7); +BENCHMARK_TEMPLATE(WaveletTransform, float, 8); +BENCHMARK_TEMPLATE(WaveletTransform, float, 9); +BENCHMARK_TEMPLATE(WaveletTransform, float, 10); +BENCHMARK_TEMPLATE(WaveletTransform, float, 11); +BENCHMARK_TEMPLATE(WaveletTransform, float, 12); +BENCHMARK_TEMPLATE(WaveletTransform, float, 13); +BENCHMARK_TEMPLATE(WaveletTransform, float, 14); +BENCHMARK_TEMPLATE(WaveletTransform, float, 15); +BENCHMARK_TEMPLATE(WaveletTransform, float, 16); +BENCHMARK_TEMPLATE(WaveletTransform, float, 17); +BENCHMARK_TEMPLATE(WaveletTransform, float, 18); +BENCHMARK_TEMPLATE(WaveletTransform, float, 19); + +BENCHMARK_TEMPLATE(WaveletTransform, double, 4); +BENCHMARK_TEMPLATE(WaveletTransform, double, 8); +BENCHMARK_TEMPLATE(WaveletTransform, double, 12); +BENCHMARK_TEMPLATE(WaveletTransform, double, 15); +BENCHMARK_TEMPLATE(WaveletTransform, double, 19); + +BENCHMARK_MAIN(); diff --git a/src/boost/libs/math/example/daubechies_wavelets/bootstrap_chebyshev.cpp b/src/boost/libs/math/example/daubechies_wavelets/bootstrap_chebyshev.cpp new file mode 100644 index 000000000..927a15b98 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/bootstrap_chebyshev.cpp @@ -0,0 +1,23 @@ +// (C) Copyright Nick Thompson 2020. +// 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) + +#include <iostream> +#include <boost/math/special_functions/daubechies_scaling.hpp> +#include <boost/math/special_functions/chebyshev_transform.hpp> + +template<typename Real, int p> +void bootstrap() +{ + std::cout << "Computing phi. . .\n"; + auto phi = boost::math::daubechies_scaling<Real, p>(); + std::cout << "Computing Chebyshev transform of phi.\n"; + auto cheb = boost::math::chebyshev_transform(phi, phi.support().first, phi.support().second); + std::cout << "Number of coefficients = " << cheb.coefficients().size() << "\n"; +} + +int main() +{ + bootstrap<long double, 9>(); +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/daubechies_coefficients.cpp b/src/boost/libs/math/example/daubechies_wavelets/daubechies_coefficients.cpp new file mode 100644 index 000000000..f21c96510 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/daubechies_coefficients.cpp @@ -0,0 +1,267 @@ +/* + * Copyright Nick Thompson, 2018 + * 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) + */ +#include <iostream> +#include <fstream> +#include <vector> +#include <string> +#include <complex> +#include <bitset> +#include <boost/math/tools/assert.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/polynomial.hpp> +#include <boost/math/tools/roots.hpp> +#include <boost/math/special_functions/binomial.hpp> +#include <boost/multiprecision/cpp_complex.hpp> +#ifdef BOOST_HAS_FLOAT128 +#include <boost/multiprecision/float128.hpp> + +typedef boost::multiprecision::float128 float128_t; +#else +typedef boost::multiprecision::cpp_bin_float_quad float128_t; +#endif +//#include <boost/multiprecision/complex128.hpp> +#include <boost/math/quadrature/gauss_kronrod.hpp> + +using std::string; +using boost::math::tools::polynomial; +using boost::math::binomial_coefficient; +using boost::math::tools::schroder_iterate; +using boost::math::tools::halley_iterate; +using boost::math::tools::newton_raphson_iterate; +using boost::math::tools::complex_newton; +using boost::math::constants::half; +using boost::math::constants::root_two; +using boost::math::constants::pi; +using boost::math::quadrature::gauss_kronrod; +using boost::multiprecision::cpp_bin_float_100; +using boost::multiprecision::cpp_complex_100; + +template<class Complex> +std::vector<std::pair<Complex, Complex>> find_roots(size_t p) +{ + // Initialize the polynomial; see Mallat, A Wavelet Tour of Signal Processing, equation 7.96 + BOOST_MATH_ASSERT(p>0); + typedef typename Complex::value_type Real; + std::vector<Complex> coeffs(p); + for (size_t k = 0; k < coeffs.size(); ++k) + { + coeffs[k] = Complex(binomial_coefficient<Real>(p-1+k, k), 0); + } + + polynomial<Complex> P(std::move(coeffs)); + polynomial<Complex> Pcopy = P; + polynomial<Complex> Pcopy_prime = P.prime(); + auto orig = [&](Complex z) { return std::make_pair<Complex, Complex>(Pcopy(z), Pcopy_prime(z)); }; + + polynomial<Complex> P_prime = P.prime(); + + // Polynomial is of degree p-1. + + std::vector<Complex> roots(p-1, {std::numeric_limits<Real>::quiet_NaN(),std::numeric_limits<Real>::quiet_NaN()}); + size_t i = 0; + while(P.size() > 1) + { + Complex guess = {0.0, 1.0}; + std::cout << std::setprecision(std::numeric_limits<Real>::digits10+3); + + auto f = [&](Complex x)->std::pair<Complex, Complex> + { + return std::make_pair<Complex, Complex>(P(x), P_prime(x)); + }; + + Complex r = complex_newton(f, guess); + using std::isnan; + if(isnan(r.real())) + { + int i = 50; + do { + // Try a different guess + guess *= Complex(1.0,-1.0); + r = complex_newton(f, guess); + std::cout << "New guess: " << guess << ", result? " << r << std::endl; + + } while (isnan(r.real()) && i-- > 0); + + if (isnan(r.real())) + { + std::cout << "Polynomial that killed the process: " << P << std::endl; + throw std::logic_error("Newton iteration did not converge"); + } + } + // Refine r with the original function. + // We only use the polynomial division to ensure we don't get the same root over and over. + // However, the division induces error which can grow quickly-or slowly! See Numerical Recipes, section 9.5.1. + r = complex_newton(orig, r); + if (isnan(r.real())) + { + throw std::logic_error("Found a root for the deflated polynomial which is not a root for the original. Indicative of catastrophic numerical error."); + } + // Test the root: + using std::sqrt; + Real tol = sqrt(sqrt(std::numeric_limits<Real>::epsilon())); + if (norm(Pcopy(r)) > tol) + { + std::cout << "This is a bad root: P" << r << " = " << Pcopy(r) << std::endl; + std::cout << "Reduced polynomial leading to bad root: " << P << std::endl; + throw std::logic_error("Donezo."); + } + + BOOST_MATH_ASSERT(i < roots.size()); + roots[i] = r; + ++i; + polynomial<Complex> q{-r, {1,0}}; + // This optimization breaks at p = 11. I have no clue why. + // Unfortunate, because I expect it to be considerably more stable than + // repeatedly dividing by the complex root. + /*polynomial<Complex> q; + if (r.imag() > sqrt(std::numeric_limits<Real>::epsilon())) + { + // Then the complex conjugate is also a root: + using std::conj; + using std::norm; + BOOST_MATH_ASSERT(i < roots.size()); + roots[i] = conj(r); + ++i; + q = polynomial<Complex>({{norm(r), 0}, {-2*r.real(),0}, {1,0}}); + } + else + { + // The imaginary part is numerical noise: + r.imag() = 0; + q = polynomial<Complex>({-r, {1,0}}); + }*/ + + + auto PR = quotient_remainder(P, q); + // I should validate that the remainder is small, but . . . + //std::cout << "Remainder = " << PR.second<< std::endl; + + P = PR.first; + P_prime = P.prime(); + } + + std::vector<std::pair<Complex, Complex>> Qroots(p-1); + for (size_t i = 0; i < Qroots.size(); ++i) + { + Complex y = roots[i]; + Complex z1 = static_cast<Complex>(1) - static_cast<Complex>(2)*y + static_cast<Complex>(2)*sqrt(y*(y-static_cast<Complex>(1))); + Complex z2 = static_cast<Complex>(1) - static_cast<Complex>(2)*y - static_cast<Complex>(2)*sqrt(y*(y-static_cast<Complex>(1))); + Qroots[i] = {z1, z2}; + } + + return Qroots; +} + +template<class Complex> +std::vector<typename Complex::value_type> daubechies_coefficients(std::vector<std::pair<Complex, Complex>> const & Qroots) +{ + typedef typename Complex::value_type Real; + size_t p = Qroots.size() + 1; + // Choose the minimum abs root; see Mallat, discussion just after equation 7.98 + std::vector<Complex> chosen_roots(p-1); + for (size_t i = 0; i < p - 1; ++i) + { + if(norm(Qroots[i].first) <= 1) + { + chosen_roots[i] = Qroots[i].first; + } + else + { + BOOST_MATH_ASSERT(norm(Qroots[i].second) <= 1); + chosen_roots[i] = Qroots[i].second; + } + } + + polynomial<Complex> R{1}; + for (size_t i = 0; i < p-1; ++i) + { + Complex ak = chosen_roots[i]; + R *= polynomial<Complex>({-ak/(static_cast<Complex>(1)-ak), static_cast<Complex>(1)/(static_cast<Complex>(1)-ak)}); + } + polynomial<Complex> a{{half<Real>(), 0}, {half<Real>(),0}}; + polynomial<Complex> poly = root_two<Real>()*pow(a, p)*R; + std::vector<Complex> result = poly.data(); + // If we reverse, we get the Numerical Recipes and Daubechies convention. + // If we don't reverse, we get the Pywavelets and Mallat convention. + // I believe this is because of the sign convention on the DFT, which differs between Daubechies and Mallat. + // You implement a dot product in Daubechies/NR convention, and a convolution in PyWavelets/Mallat convention. + std::reverse(result.begin(), result.end()); + std::vector<Real> h(result.size()); + for (size_t i = 0; i < result.size(); ++i) + { + Complex r = result[i]; + BOOST_MATH_ASSERT(r.imag() < sqrt(std::numeric_limits<Real>::epsilon())); + h[i] = r.real(); + } + + // Quick sanity check: We could check all vanishing moments, but that sum is horribly ill-conditioned too! + Real sum = 0; + Real scale = 0; + for (size_t i = 0; i < h.size(); ++i) + { + sum += h[i]; + scale += h[i]*h[i]; + } + BOOST_MATH_ASSERT(abs(scale -1) < sqrt(std::numeric_limits<Real>::epsilon())); + BOOST_MATH_ASSERT(abs(sum - root_two<Real>()) < sqrt(std::numeric_limits<Real>::epsilon())); + return h; +} + +int main() +{ + typedef boost::multiprecision::cpp_complex<500> Complex; + size_t p_max = 20; + std::ofstream fs{"daubechies_filters.hpp"}; + fs << "/*\n" + << " * Copyright Nick Thompson, 2019\n" + << " * Use, modification and distribution are subject to the\n" + << " * Boost Software License, Version 1.0. (See accompanying file\n" + << " * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" + << " */\n" + << "#ifndef BOOST_MATH_FILTERS_DAUBECHIES_HPP\n" + << "#define BOOST_MATH_FILTERS_DAUBECHIES_HPP\n" + << "#include <array>\n" + << "#include <limits>\n" + << "#include <boost/math/tools/big_constant.hpp>\n\n" + << "namespace boost::math::filters {\n\n" + << "template <typename Real, unsigned p>\n" + << "constexpr std::array<Real, 2*p> daubechies_scaling_filter()\n" + << "{\n" + << " static_assert(p < " << p_max << ", \"Filter coefficients only implemented up to " << p_max - 1 << ".\");\n"; + + for(size_t p = 1; p < p_max; ++p) + { + fs << std::setprecision(std::numeric_limits<boost::multiprecision::cpp_bin_float_oct>::max_digits10); + auto roots = find_roots<Complex>(p); + auto h = daubechies_coefficients(roots); + fs << " if constexpr (p == " << p << ") {\n"; + fs << " return {"; + for (size_t i = 0; i < h.size() - 1; ++i) { + fs << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << h[i] << "), "; + } + fs << "BOOST_MATH_BIG_CONSTANT(Real, std::numeric_limits<Real>::digits, " << h[h.size()-1] << ") };\n"; + fs << " }\n"; + } + + fs << "}\n\n"; + + fs << "template<class Real, size_t p>\n"; + fs << "std::array<Real, 2*p> daubechies_wavelet_filter() {\n"; + fs << " std::array<Real, 2*p> g;\n"; + fs << " auto h = daubechies_scaling_filter<Real, p>();\n"; + fs << " for (size_t i = 0; i < g.size(); i += 2)\n"; + fs << " {\n"; + fs << " g[i] = h[g.size() - i - 1];\n"; + fs << " g[i+1] = -h[g.size() - i - 2];\n"; + fs << " }\n"; + fs << " return g;\n"; + fs << "}\n\n"; + fs << "} // namespaces\n"; + fs << "#endif\n"; + fs.close(); +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_integer_grid.cpp b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_integer_grid.cpp new file mode 100644 index 000000000..393823aff --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_integer_grid.cpp @@ -0,0 +1,217 @@ +/* + * Copyright Nick Thompson, John Maddock 2020 + * 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) + * + * We want to use c-style asserts in examples: + * + * boost-no-inspect + */ + +#define BOOST_MATH_GENERATE_DAUBECHIES_GRID + +#include <iostream> +#include <vector> +#include <numeric> +#include <list> +#include <cmath> +#include <cassert> +#include <fstream> +#include <Eigen/Eigenvalues> +#include <boost/hana/for_each.hpp> +#include <boost/hana/ext/std/integer_sequence.hpp> +#include <boost/core/demangle.hpp> +#ifdef BOOST_HAS_FLOAT128 +#include <boost/multiprecision/float128.hpp> +#endif +#include <boost/math/constants/constants.hpp> +#include <boost/math/filters/daubechies.hpp> +#include <boost/math/special_functions/factorials.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> + +typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<237, boost::multiprecision::backends::digit_base_2, std::allocator<char>, std::int32_t, -262142, 262143>, boost::multiprecision::et_off> octuple_type; + +#ifdef BOOST_HAS_FLOAT128 +typedef boost::multiprecision::float128 float128_t; +#else +typedef boost::multiprecision::cpp_bin_float_quad float128_t; +#endif + +template<class Real, int p> +std::list<std::vector<Real>> integer_grid() +{ + std::cout << std::setprecision(std::numeric_limits<Real>::digits10 + 3); + using std::abs; + using std::sqrt; + using std::pow; + std::list<std::vector<Real>> grids; + + auto c = boost::math::filters::daubechies_scaling_filter<Real, p>(); + for (auto & x : c) + { + x *= boost::math::constants::root_two<Real>(); + } + std::cout << "\n\nTaps in filter = " << c.size() << "\n"; + + + Eigen::Matrix<Real, 2*p - 2, 2*p-2> A; + for (int j = 0; j < 2*p-2; ++j) { + for (int k = 0; k < 2*p-2; ++k) { + if ( (2*j-k + 1) < 0 || (2*j - k + 1) >= 2*p) + { + A(j,k) = 0; + } + else { + A(j,k) = c[2*j - k + 1]; + } + } + } + + Eigen::EigenSolver<decltype(A)> es(A); + + auto complex_eigs = es.eigenvalues(); + + std::vector<Real> eigs(complex_eigs.size(), std::numeric_limits<Real>::quiet_NaN()); + + std::cout << "Eigenvalues = {"; + for (long i = 0; i < complex_eigs.size(); ++i) { + assert(abs(complex_eigs[i].imag()) < std::numeric_limits<Real>::epsilon()); + eigs[i] = complex_eigs[i].real(); + std::cout << eigs[i] << ", "; + } + std::cout << "}\n"; + + // Eigen does not sort the eigenpairs by any criteria on the eigenvalues. + // In any case, even if it did, some of the eigenpairs do not correspond to derivatives anyway. + for (size_t j = 0; j < eigs.size(); ++j) { + auto f = [&](Real x) { + return abs(x - Real(1)/Real(1 << j) ) < sqrt(std::numeric_limits<Real>::epsilon()); + }; + auto it = std::find_if(eigs.begin(), eigs.end(), f); + if (it == eigs.end()) { + std::cout << "couldn't find eigenvalue " << Real(1)/Real(1 << j) << "\n"; + continue; + } + size_t idx = std::distance(eigs.begin(), it); + std::cout << "Eigenvector for derivative " << j << " is at index " << idx << "\n"; + auto eigenvector_matrix = es.eigenvectors(); + auto complex_eigenvec = eigenvector_matrix.col(idx); + + std::vector<Real> eigenvec(complex_eigenvec.size() + 2, std::numeric_limits<Real>::quiet_NaN()); + eigenvec[0] = 0; + eigenvec[eigenvec.size()-1] = 0; + for (size_t i = 0; i < eigenvec.size() - 2; ++i) { + assert(abs(complex_eigenvec[i].imag()) < std::numeric_limits<Real>::epsilon()); + eigenvec[i+1] = complex_eigenvec[i].real(); + } + + Real sum = 0; + for(size_t k = 1; k < eigenvec.size(); ++k) { + sum += pow(k, j)*eigenvec[k]; + } + + Real alpha = pow(-1, j)*boost::math::factorial<Real>(j)/sum; + + for (size_t i = 1; i < eigenvec.size(); ++i) { + eigenvec[i] *= alpha; + } + + + std::cout << "Eigenvector = {"; + for (size_t i = 0; i < eigenvec.size() -1; ++i) { + std::cout << eigenvec[i] << ", "; + } + std::cout << eigenvec[eigenvec.size()-1] << "}\n"; + + sum = 0; + for(size_t k = 1; k < eigenvec.size(); ++k) { + sum += pow(k, j)*eigenvec[k]; + } + + std::cout << "Moment sum = " << sum << ", expected = " << pow(-1, j)*boost::math::factorial<Real>(j) << "\n"; + + assert(abs(sum - pow(-1, j)*boost::math::factorial<Real>(j))/abs(pow(-1, j)*boost::math::factorial<Real>(j)) < sqrt(std::numeric_limits<Real>::epsilon())); + + grids.push_back(eigenvec); + } + + + return grids; +} + +template<class Real, int p> +void write_grid(std::ofstream & fs) +{ + auto grids = integer_grid<Real, p>(); + size_t j = 0; + fs << std::setprecision(std::numeric_limits< boost::multiprecision::cpp_bin_float_quad>::max_digits10); + for (auto it = grids.begin(); it != grids.end(); ++it) + { + auto const& grid = *it; + fs << "template <typename Real> struct daubechies_scaling_integer_grid_imp <Real, " << p << ", "; + fs << j << "> { static inline constexpr std::array<Real, " << grid.size() << "> value = { "; + for (size_t i = 0; i < grid.size() -1; ++i){ + fs << "C_(" << static_cast<float128_t>(grid[i]) << "), "; + } + fs << "C_(" << static_cast<float128_t>(grid[grid.size()-1]) << ") }; };\n"; + ++j; + } +} + +int main() +{ + constexpr const size_t p_max = 18; + std::ofstream fs{"daubechies_scaling_integer_grid.hpp"}; + fs << "/*\n" + << " * Copyright Nick Thompson, John Maddock 2020\n" + << " * Use, modification and distribution are subject to the\n" + << " * Boost Software License, Version 1.0. (See accompanying file\n" + << " * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" + << " */\n" + << "// THIS FILE GENERATED BY EXAMPLE/DAUBECHIES_SCALING_INTEGER_GRID.CPP, DO NOT EDIT.\n" + << "#ifndef BOOST_MATH_DAUBECHIES_SCALING_INTEGER_GRID_HPP\n" + << "#define BOOST_MATH_DAUBECHIES_SCALING_INTEGER_GRID_HPP\n" + << "#include <array>\n" + << "#include <float.h>\n" + << "#include <boost/config.hpp>\n" + << "/*\n" + << "In order to keep the character count as small as possible and speed up\n" + << "compiler parsing times, we define a macro C_ which appends an appropriate\n" + << "suffix to each literal, and then casts it to type Real.\n" + << "The suffix is as follows:\n\n" + << "* Q, when we have __float128 support.\n" + << "* L, when we have either 80 or 128 bit long doubles.\n" + << "* Nothing otherwise.\n" + << "*/\n\n" + << "#ifdef BOOST_HAS_FLOAT128\n" + << "# define C_(x) static_cast<Real>(x##Q)\n" + << "#elif (LDBL_MANT_DIG > DBL_MANT_DIG)\n" + << "# define C_(x) static_cast<Real>(x##L)\n" + << "#else\n" + << "# define C_(x) static_cast<Real>(x)\n" + << "#endif\n\n" + << "namespace boost::math::detail {\n\n" + << "template <typename Real, int p, int order> struct daubechies_scaling_integer_grid_imp;\n\n"; + + fs << std::hexfloat << std::setprecision(std::numeric_limits<boost::multiprecision::cpp_bin_float_quad>::max_digits10); + + boost::hana::for_each(std::make_index_sequence<p_max>(), [&](auto idx){ + write_grid<octuple_type, idx+2>(fs); + }); + + fs << "\n\ntemplate <typename Real, unsigned p, unsigned order>\n" + << "constexpr inline std::array<Real, 2*p> daubechies_scaling_integer_grid()\n" + << "{\n" + << " static_assert(sizeof(Real) <= 16, \"Integer grids only computed up to 128 bits of precision.\");\n" + << " static_assert(p <= " << p_max + 1 << ", \"Integer grids only implemented up to " << p_max + 1 << ".\");\n" + << " static_assert(p > 1, \"Integer grids only implemented for p >= 2.\");\n" + << " return daubechies_scaling_integer_grid_imp<Real, p, order>::value;\n" + << "}\n\n"; + + fs << "} // namespaces\n"; + fs << "#endif\n"; + fs.close(); + + return 0; +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_memory_occupation.cpp b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_memory_occupation.cpp new file mode 100644 index 000000000..2ffee3f23 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_memory_occupation.cpp @@ -0,0 +1,64 @@ +// (C) Copyright Nick Thompson 2020. +// 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) + +#include <iostream> +#include <boost/math/special_functions/daubechies_scaling.hpp> +#include <boost/core/demangle.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/ext/std/integer_sequence.hpp> + +int main() +{ + boost::hana::for_each(std::make_index_sequence<18>(), + [](auto i) { + std::cout << std::right; + auto daub = boost::math::daubechies_scaling<float, i+2>(); + std::cout << "The Daubechies " << std::setw(2) << i + 2 << " scaling function occupies " + << std::setw(12) << daub.bytes()/1000.0 << " kilobytes in relative accuracy mode in " + << boost::core::demangle(typeid(float).name()) << " precision\n"; + }); + + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; + + boost::hana::for_each(std::make_index_sequence<18>(), + [](auto i) { + std::cout << std::right; + auto daub = boost::math::daubechies_scaling<float, i+2>(-2); + std::cout << "The Daubechies " << std::setw(2) << i + 2 << " scaling function occupies " + << std::setw(12) << daub.bytes()/1000.0 << " kilobytes in absolute accuracy mode in " + << boost::core::demangle(typeid(float).name()) << " precision\n"; + }); + + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; + + + boost::hana::for_each(std::make_index_sequence<18>(), + [](auto i) { + std::cout << std::right; + auto daub = boost::math::daubechies_scaling<double, i+2>(); + std::cout << "The Daubechies " << std::setw(2) << i + 2 << " scaling function occupies " + << std::setw(12) << daub.bytes()/1000.0 << " kilobytes in relative accuracy mode in " + << boost::core::demangle(typeid(double).name()) << " precision\n"; + }); + + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; + + boost::hana::for_each(std::make_index_sequence<18>(), + [](auto i) { + std::cout << std::right; + auto daub = boost::math::daubechies_scaling<double, i+2>(-2); + std::cout << "The Daubechies " << std::setw(2) << i + 2 << " scaling function occupies " + << std::setw(12) << daub.bytes()/1000.0 << " kilobytes in absolute accuracy mode in " + << boost::core::demangle(typeid(double).name()) << " precision\n"; + }); + + +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_plots.cpp b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_plots.cpp new file mode 100644 index 000000000..d4ef5fde2 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/daubechies_scaling_plots.cpp @@ -0,0 +1,171 @@ +/* + * Copyright Nick Thompson, 2020 + * 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) + */ +#include <iostream> +#include <boost/core/demangle.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/ext/std/integer_sequence.hpp> + +#include <boost/multiprecision/float128.hpp> +#include <boost/math/special_functions/daubechies_scaling.hpp> +#include <boost/math/tools/ulps_plot.hpp> +#include <quicksvg/graph_fn.hpp> + + +using boost::multiprecision::float128; +constexpr const int GRAPH_WIDTH = 300; + +template<typename Real, int p> +void plot_phi(int grid_refinements = -1) +{ + auto phi = boost::math::daubechies_scaling<Real, p>(); + if (grid_refinements >= 0) + { + phi = boost::math::daubechies_scaling<Real, p>(grid_refinements); + } + Real a = 0; + Real b = phi.support().second; + std::string title = "Daubechies " + std::to_string(p) + " scaling function"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_scaling.svg"; + int samples = 1024; + quicksvg::graph_fn daub(a, b, title, filename, samples, GRAPH_WIDTH); + daub.set_gridlines(8, 2*p-1); + daub.set_stroke_width(1); + daub.add_fn(phi); + daub.write_all(); +} + +template<typename Real, int p> +void plot_dphi(int grid_refinements = -1) +{ + auto phi = boost::math::daubechies_scaling<Real, p>(); + if (grid_refinements >= 0) + { + phi = boost::math::daubechies_scaling<Real, p>(grid_refinements); + } + Real a = 0; + Real b = phi.support().second; + std::string title = "Daubechies " + std::to_string(p) + " scaling function derivative"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_scaling_prime.svg"; + int samples = 1024; + quicksvg::graph_fn daub(a, b, title, filename, samples, GRAPH_WIDTH); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + auto dphi = [phi](Real x)->Real { return phi.prime(x); }; + daub.add_fn(dphi); + daub.write_all(); +} + +template<typename Real, int p> +void plot_convergence() +{ + auto phi0 = boost::math::daubechies_scaling<Real, p>(0); + Real a = 0; + Real b = phi0.support().second; + std::string title = "Daubechies " + std::to_string(p) + " scaling at 0 (green), 1 (orange), 2 (red), and 24 (blue) grid refinements"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_scaling_convergence.svg"; + + quicksvg::graph_fn daub(a, b, title, filename, 1024, 900); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + + daub.add_fn(phi0, "green"); + auto phi1 = boost::math::daubechies_scaling<Real, p>(1); + daub.add_fn(phi1, "orange"); + auto phi2 = boost::math::daubechies_scaling<Real, p>(2); + daub.add_fn(phi2, "red"); + + auto phi21 = boost::math::daubechies_scaling<Real, p>(21); + daub.add_fn(phi21); + + daub.write_all(); +} + +template<typename Real, int p> +void plot_condition_number() +{ + using std::abs; + using std::log; + static_assert(p >= 3, "p = 2 is not differentiable, so condition numbers cannot be effectively evaluated."); + auto phi = boost::math::daubechies_scaling<Real, p>(); + Real a = std::sqrt(std::numeric_limits<Real>::epsilon()); + Real b = phi.support().second - 1000*std::sqrt(std::numeric_limits<Real>::epsilon()); + std::string title = "log10 of condition number of function evaluation for Daubechies " + std::to_string(p) + " scaling function."; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_scaling_condition_number.svg"; + + + quicksvg::graph_fn daub(a, b, title, filename, 2048, GRAPH_WIDTH); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + + auto cond = [&phi](Real x) + { + Real y = phi(x); + Real dydx = phi.prime(x); + Real z = abs(x*dydx/y); + using std::isnan; + if (z==0) + { + return Real(-1); + } + if (isnan(z)) + { + // Graphing libraries don't like nan's: + return Real(1); + } + return log10(z); + }; + daub.add_fn(cond); + daub.write_all(); +} + +template<typename CoarseReal, typename PreciseReal, int p, class PhiPrecise> +void do_ulp(int coarse_refinements, PhiPrecise phi_precise) +{ + auto phi_coarse = boost::math::daubechies_scaling<CoarseReal, p>(coarse_refinements); + + std::string title = std::to_string(p) + " vanishing moment ULP plot at " + std::to_string(coarse_refinements) + " refinements and " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; + title = ""; + + std::string filename = "daubechies_" + std::to_string(p) + "_" + boost::core::demangle(typeid(CoarseReal).name()) + "_" + std::to_string(coarse_refinements) + "_refinements.svg"; + int samples = 20000; + int clip = 10; + int horizontal_lines = 8; + int vertical_lines = 2*p - 1; + auto [a, b] = phi_coarse.support(); + auto plot = boost::math::tools::ulps_plot<decltype(phi_precise), PreciseReal, CoarseReal>(phi_precise, a, b, samples); + plot.clip(clip).width(GRAPH_WIDTH).horizontal_lines(horizontal_lines).vertical_lines(vertical_lines).ulp_envelope(false); + + plot.background_color("white").font_color("black"); + plot.add_fn(phi_coarse); + plot.write(filename); +} + + +int main() +{ + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ plot_phi<double, i+2>(); }); + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i){ plot_dphi<double, i+3>(); }); + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i){ plot_condition_number<double, i+3>(); }); + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ plot_convergence<double, i+2>(); }); + + using PreciseReal = float128; + using CoarseReal = double; + int precise_refinements = 23; + constexpr const int p = 8; + std::cout << "Computing precise scaling function in " << boost::core::demangle(typeid(PreciseReal).name()) << " precision.\n"; + auto phi_precise = boost::math::daubechies_scaling<PreciseReal, p>(precise_refinements); + std::cout << "Beginning comparison with functions computed in " << boost::core::demangle(typeid(CoarseReal).name()) << " precision.\n"; + for (int i = 7; i <= precise_refinements-1; ++i) + { + std::cout << "\tCoarse refinement " << i << "\n"; + do_ulp<CoarseReal, PreciseReal, p>(i, phi_precise); + } +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/daubechies_wavelet_plots.cpp b/src/boost/libs/math/example/daubechies_wavelets/daubechies_wavelet_plots.cpp new file mode 100644 index 000000000..4d898ea4e --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/daubechies_wavelet_plots.cpp @@ -0,0 +1,160 @@ +/* + * Copyright Nick Thompson, 2020 + * 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) + */ +#include <iostream> +#include <boost/core/demangle.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/ext/std/integer_sequence.hpp> + +#include <boost/multiprecision/float128.hpp> +#include <boost/math/special_functions/daubechies_wavelet.hpp> +#include <quicksvg/graph_fn.hpp> +#include <quicksvg/ulp_plot.hpp> + + +using boost::multiprecision::float128; +constexpr const int GRAPH_WIDTH = 700; + +template<typename Real, int p> +void plot_psi(int grid_refinements = -1) +{ + auto psi = boost::math::daubechies_wavelet<Real, p>(); + if (grid_refinements >= 0) + { + psi = boost::math::daubechies_wavelet<Real, p>(grid_refinements); + } + auto [a, b] = psi.support(); + std::string title = "Daubechies " + std::to_string(p) + " wavelet"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_wavelet.svg"; + int samples = 1024; + quicksvg::graph_fn daub(a, b, title, filename, samples, GRAPH_WIDTH); + daub.set_gridlines(8, 2*p-1); + daub.set_stroke_width(1); + daub.add_fn(psi); + daub.write_all(); +} + +template<typename Real, int p> +void plot_dpsi(int grid_refinements = -1) +{ + auto psi = boost::math::daubechies_wavelet<Real, p>(); + if (grid_refinements >= 0) + { + psi = boost::math::daubechies_wavelet<Real, p>(grid_refinements); + } + auto [a, b] = psi.support(); + std::string title = "Daubechies " + std::to_string(p) + " wavelet derivative"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_wavelet_prime.svg"; + int samples = 1024; + quicksvg::graph_fn daub(a, b, title, filename, samples, GRAPH_WIDTH); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + auto dpsi = [psi](Real x)->Real { return psi.prime(x); }; + daub.add_fn(dpsi); + daub.write_all(); +} + +template<typename Real, int p> +void plot_convergence() +{ + auto psi1 = boost::math::daubechies_wavelet<Real, p>(1); + auto [a, b] = psi1.support(); + std::string title = "Daubechies " + std::to_string(p) + " wavelet at 1 (orange), 2 (red), and 21 (blue) grid refinements"; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_wavelet_convergence.svg"; + + quicksvg::graph_fn daub(a, b, title, filename, 1024, GRAPH_WIDTH); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + + daub.add_fn(psi1, "orange"); + auto psi2 = boost::math::daubechies_wavelet<Real, p>(2); + daub.add_fn(psi2, "red"); + + auto psi21 = boost::math::daubechies_wavelet<Real, p>(21); + daub.add_fn(psi21); + + daub.write_all(); +} + +template<typename Real, int p> +void plot_condition_number() +{ + using std::abs; + using std::log; + static_assert(p >= 3, "p = 2 is not differentiable, so condition numbers cannot be effectively evaluated."); + auto phi = boost::math::daubechies_wavelet<Real, p>(); + Real a = phi.support().first + 1000*std::sqrt(std::numeric_limits<Real>::epsilon()); + Real b = phi.support().second - 1000*std::sqrt(std::numeric_limits<Real>::epsilon()); + std::string title = "log10 of condition number of function evaluation for Daubechies " + std::to_string(p) + " wavelet function."; + title = ""; + std::string filename = "daubechies_" + std::to_string(p) + "_wavelet_condition_number.svg"; + + + quicksvg::graph_fn daub(a, b, title, filename, 2048, GRAPH_WIDTH); + daub.set_stroke_width(1); + daub.set_gridlines(8, 2*p-1); + + auto cond = [&phi](Real x) + { + Real y = phi(x); + Real dydx = phi.prime(x); + Real z = abs(x*dydx/y); + using std::isnan; + if (z==0) + { + return Real(-1); + } + if (isnan(z)) + { + // Graphing libraries don't like nan's: + return Real(1); + } + return log10(z); + }; + daub.add_fn(cond); + daub.write_all(); +} + +template<typename CoarseReal, typename PreciseReal, int p, class PsiPrecise> +void do_ulp(int coarse_refinements, PsiPrecise psi_precise) +{ + auto psi_coarse = boost::math::daubechies_wavelet<CoarseReal, p>(coarse_refinements); + + std::string title = std::to_string(p) + " vanishing moment ULP plot at " + std::to_string(coarse_refinements) + " refinements and " + boost::core::demangle(typeid(CoarseReal).name()) + " precision"; + title = ""; + + std::string filename = "daubechies_" + std::to_string(p) + "_wavelet_" + boost::core::demangle(typeid(CoarseReal).name()) + "_" + std::to_string(coarse_refinements) + "_refinements.svg"; + int samples = 20000; + int clip = 20; + int horizontal_lines = 8; + int vertical_lines = 2*p - 1; + quicksvg::ulp_plot<decltype(psi_coarse), CoarseReal, decltype(psi_precise), PreciseReal>(psi_coarse, psi_precise, CoarseReal(psi_coarse.support().first), psi_coarse.support().second, title, filename, samples, GRAPH_WIDTH, clip, horizontal_lines, vertical_lines); +} + + +int main() +{ + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ plot_psi<double, i+2>(); }); + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i){ plot_dpsi<double, i+3>(); }); + boost::hana::for_each(std::make_index_sequence<17>(), [&](auto i){ plot_condition_number<double, i+3>(); }); + boost::hana::for_each(std::make_index_sequence<18>(), [&](auto i){ plot_convergence<double, i+2>(); }); + + using PreciseReal = float128; + using CoarseReal = double; + int precise_refinements = 22; + constexpr const int p = 9; + std::cout << "Computing precise wavelet function in " << boost::core::demangle(typeid(PreciseReal).name()) << " precision.\n"; + auto phi_precise = boost::math::daubechies_wavelet<PreciseReal, p>(precise_refinements); + std::cout << "Beginning comparison with functions computed in " << boost::core::demangle(typeid(CoarseReal).name()) << " precision.\n"; + for (int i = 7; i <= precise_refinements-1; ++i) + { + std::cout << "\tCoarse refinement " << i << "\n"; + do_ulp<CoarseReal, PreciseReal, p>(i, phi_precise); + } +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp b/src/boost/libs/math/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp new file mode 100644 index 000000000..56c5ed3cb --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/find_best_daubechies_interpolator.cpp @@ -0,0 +1,535 @@ +// Copyright Nick Thompson, 2020 +// 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) + +#include <iostream> +#include <unordered_map> +#include <string> +#include <future> +#include <thread> +#include <fstream> +#include <boost/hana/for_each.hpp> +#include <boost/hana/ext/std/integer_sequence.hpp> +#include <boost/math/special_functions/daubechies_scaling.hpp> +#include <boost/math/special_functions/detail/daubechies_scaling_integer_grid.hpp> +#include <boost/math/interpolators/cubic_hermite.hpp> +#include <boost/math/interpolators/quintic_hermite.hpp> +#include <boost/math/interpolators/quintic_hermite.hpp> +#include <boost/math/interpolators/septic_hermite.hpp> +#include <boost/math/interpolators/cardinal_quadratic_b_spline.hpp> +#include <boost/math/interpolators/cardinal_cubic_b_spline.hpp> +#include <boost/math/interpolators/cardinal_quintic_b_spline.hpp> +#include <boost/math/interpolators/whittaker_shannon.hpp> +#include <boost/math/interpolators/cardinal_trigonometric.hpp> +#include <boost/math/special_functions/next.hpp> +#include <boost/math/interpolators/makima.hpp> +#include <boost/math/interpolators/pchip.hpp> +#include <boost/multiprecision/float128.hpp> +#include <boost/core/demangle.hpp> + +using boost::multiprecision::float128; + + +template<typename Real, typename PreciseReal, int p> +void choose_refinement() +{ + std::cout << "Choosing refinement for " << boost::core::demangle(typeid(Real).name()) << " precision Daubechies scaling function with " << p << " vanishing moments.\n"; + using std::abs; + int rmax = 22; + auto phi_dense = boost::math::daubechies_scaling_dyadic_grid<PreciseReal, p, 0>(rmax); + Real dx_dense = (2*p-1)/static_cast<Real>(phi_dense.size()-1); + + for (int r = 2; r <= 18; ++r) + { + Real dx = Real(1)/ (1 << r); + std::cout << "\tdx = 1/" << (1/dx) << " = 1/2^" << r << " = " << dx << "\n"; + auto phi = boost::math::daubechies_scaling<Real, p>(r); + Real max_flt_distance = 0; + Real sup = 0; + Real rel_sup = 0; + Real worst_flt_abscissa = 0; + Real worst_flt_value = 0; + Real worst_flt_computed = 0; + + Real worst_rel_abscissa = 0; + Real worst_rel_value = 0; + Real worst_rel_computed = 0; + + Real worst_abs_abscissa = 0; + Real worst_abs_computed = 0; + Real worst_abs_expected = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real t = i*dx_dense; + Real computed = phi(t); + Real expected = Real(phi_dense[i]); + Real abs_diff = abs(computed - expected); + Real rel_diff = abs_diff/abs(expected); + Real flt_distance = abs(boost::math::float_distance(computed, expected)); + if (flt_distance > max_flt_distance) + { + max_flt_distance = flt_distance; + worst_flt_abscissa = t; + worst_flt_value = expected; + worst_flt_computed = computed; + } + if (expected != 0 && rel_diff > rel_sup) + { + rel_sup = rel_diff; + worst_rel_abscissa = t; + worst_rel_value = expected; + worst_rel_computed = computed; + + } + if (abs_diff > sup) + { + sup = abs_diff; + worst_abs_abscissa = t; + worst_abs_computed = computed; + worst_abs_expected = expected; + } + } + std::cout << "\t\tFloat distance at r = " << r << " is " << max_flt_distance << ", sup distance = " << sup << ", max relative error = " << rel_sup << "\n"; + std::cout << "\t\tWorst flt abscissa = " << worst_flt_abscissa << ", worst expected value = " << worst_flt_value << ", computed = " << worst_flt_computed << "\n"; + std::cout << "\t\tWorst rel abscissa = " << worst_rel_abscissa << ", worst expected value = " << worst_rel_value << ", computed = " << worst_rel_computed << "\n"; + std::cout << "\t\tWorst abs abscissa = " << worst_abs_abscissa << ", worst expected value = " << worst_abs_computed << ", worst abs value (expected) = " << worst_abs_expected << "\n"; + } + std::cout << "\n\n\n"; +} + +template<typename Real, typename PreciseReal, int p> +void find_best_interpolator() +{ + std::string filename = "daubechies_" + std::to_string(p) + "_scaling_convergence.csv"; + std::ofstream fs{filename}; + static_assert(sizeof(PreciseReal) >= sizeof(Real), "sizeof(PreciseReal) >= sizeof(Real) is required."); + using std::abs; + int rmax = 18; + std::cout << "Computing phi_dense_precise\n"; + auto phi_dense_precise = boost::math::daubechies_scaling_dyadic_grid<PreciseReal, p, 0>(rmax); + std::vector<Real> phi_dense(phi_dense_precise.size()); + for (size_t i = 0; i < phi_dense.size(); ++i) + { + phi_dense[i] = static_cast<Real>(phi_dense_precise[i]); + } + phi_dense_precise.resize(0); + std::cout << "Done\n"; + + Real dx_dense = (2*p-1)/static_cast<Real>(phi_dense.size()-1); + fs << std::setprecision(std::numeric_limits<Real>::digits10 + 3); + fs << std::fixed; + fs << "r, matched_holder, linear, quadratic_b_spline, cubic_b_spline, quintic_b_spline, cubic_hermite, pchip, makima, fo_taylor"; + if (p==2) + { + fs << "\n"; + } + else + { + fs << ", quintic_hermite, second_order_taylor"; + if (p > 3) + { + fs << ", third_order_taylor, septic_hermite\n"; + } + else + { + fs << "\n"; + } + } + for (int r = 2; r < 13; ++r) + { + fs << r << ", "; + std::map<Real, std::string> m; + auto phi = boost::math::daubechies_scaling_dyadic_grid<Real, p, 0>(r); + auto phi_prime = boost::math::daubechies_scaling_dyadic_grid<Real, p, 1>(r); + + std::vector<Real> x(phi.size()); + Real dx = (2*p-1)/static_cast<Real>(x.size()-1); + std::cout << "dx = 1/" << (1 << r) << " = " << dx << "\n"; + for (size_t i = 0; i < x.size(); ++i) + { + x[i] = i*dx; + } + + { + auto phi_copy = phi; + auto phi_prime_copy = phi_prime; + auto mh = boost::math::detail::matched_holder(std::move(phi_copy), std::move(phi_prime_copy), r, Real(0)); + Real sup = 0; + // call to matched_holder is unchecked, so only go to phi_dense.size() -1. + for (size_t i = 0; i < phi_dense.size() - 1; ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - mh(x)); + if (diff > sup) + { + sup = diff; + } + } + m.insert({sup, "matched_holder"}); + fs << sup << ", "; + } + + + { + auto linear = [&phi, &dx, &r](Real x)->Real { + if (x <= 0 || x >= 2*p-1) + { + return Real(0); + } + using std::floor; + + Real y = (1<<r)*x; + Real k = floor(y); + + size_t kk = static_cast<size_t>(k); + + Real t = y - k; + return (1-t)*phi[kk] + t*phi[kk+1]; + }; + + Real linear_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - linear(x)); + if (diff > linear_sup) + { + linear_sup = diff; + } + } + m.insert({linear_sup, "linear interpolation"}); + fs << linear_sup << ", "; + } + + + { + auto qbs = boost::math::interpolators::cardinal_quadratic_b_spline(phi.data(), phi.size(), Real(0), dx, phi_prime.front(), phi_prime.back()); + Real qbs_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - qbs(x)); + if (diff > qbs_sup) { + qbs_sup = diff; + } + } + m.insert({qbs_sup, "quadratic_b_spline"}); + fs << qbs_sup << ", "; + } + + { + auto cbs = boost::math::interpolators::cardinal_cubic_b_spline(phi.data(), phi.size(), Real(0), dx, phi_prime.front(), phi_prime.back()); + Real cbs_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - cbs(x)); + if (diff > cbs_sup) + { + cbs_sup = diff; + } + } + m.insert({cbs_sup, "cubic_b_spline"}); + fs << cbs_sup << ", "; + } + + { + auto qbs = boost::math::interpolators::cardinal_quintic_b_spline(phi.data(), phi.size(), Real(0), dx, {0,0}, {0,0}); + Real qbs_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - qbs(x)); + if (diff > qbs_sup) + { + qbs_sup = diff; + } + } + m.insert({qbs_sup, "quintic_b_spline"}); + fs << qbs_sup << ", "; + } + + { + auto phi_copy = phi; + auto phi_prime_copy = phi_prime; + auto ch = boost::math::interpolators::cardinal_cubic_hermite(std::move(phi_copy), std::move(phi_prime_copy), Real(0), dx); + Real chs_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - ch(x)); + if (diff > chs_sup) + { + chs_sup = diff; + } + } + m.insert({chs_sup, "cubic_hermite_spline"}); + fs << chs_sup << ", "; + } + + { + auto phi_copy = phi; + auto x_copy = x; + auto phi_prime_copy = phi_prime; + auto pc = boost::math::interpolators::pchip(std::move(x_copy), std::move(phi_copy)); + Real pchip_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - pc(x)); + if (diff > pchip_sup) + { + pchip_sup = diff; + } + } + m.insert({pchip_sup, "pchip"}); + fs << pchip_sup << ", "; + } + + { + auto phi_copy = phi; + auto x_copy = x; + auto pc = boost::math::interpolators::makima(std::move(x_copy), std::move(phi_copy)); + Real makima_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - pc(x)); + if (diff > makima_sup) + { + makima_sup = diff; + } + } + m.insert({makima_sup, "makima"}); + fs << makima_sup << ", "; + } + + // Whittaker-Shannon interpolation has linear complexity; test over all points and it's quadratic. + // I ran this a couple times and found it's not competitive; so comment out for now. + /*{ + auto phi_copy = phi; + auto ws = boost::math::interpolators::whittaker_shannon(std::move(phi_copy), Real(0), dx); + Real sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) { + Real x = i*dx_dense; + using std::abs; + Real diff = abs(phi_dense[i] - ws(x)); + if (diff > sup) { + sup = diff; + } + } + + m.insert({sup, "whittaker_shannon"}); + } + + // Again, linear complexity of evaluation => quadratic complexity of exhaustive checking. + { + auto trig = boost::math::interpolators::cardinal_trigonometric(phi, Real(0), dx); + Real sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) { + Real x = i*dx_dense; + using std::abs; + Real diff = abs(phi_dense[i] - trig(x)); + if (diff > sup) { + sup = diff; + } + } + m.insert({sup, "trig"}); + }*/ + + { + auto fotaylor = [&phi, &phi_prime, &r](Real x)->Real + { + if (x <= 0 || x >= 2*p-1) + { + return 0; + } + using std::floor; + + Real y = (1<<r)*x; + Real k = floor(y); + + size_t kk = static_cast<size_t>(k); + if (y - k < k + 1 - y) + { + Real eps = (y-k)/(1<<r); + return phi[kk] + eps*phi_prime[kk]; + } + else { + Real eps = (y-k-1)/(1<<r); + return phi[kk+1] + eps*phi_prime[kk+1]; + } + }; + Real fo_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - fotaylor(x)); + if (diff > fo_sup) + { + fo_sup = diff; + } + } + m.insert({fo_sup, "First-order Taylor"}); + if (p==2) + { + fs << fo_sup << "\n"; + } + else + { + fs << fo_sup << ", "; + } + } + + if constexpr (p > 2) { + auto phi_dbl_prime = boost::math::daubechies_scaling_dyadic_grid<Real, p, 2>(r); + + { + auto phi_copy = phi; + auto phi_prime_copy = phi_prime; + auto phi_dbl_prime_copy = phi_dbl_prime; + auto qh = boost::math::interpolators::cardinal_quintic_hermite(std::move(phi_copy), std::move(phi_prime_copy), std::move(phi_dbl_prime_copy), Real(0), dx); + Real qh_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - qh(x)); + if (diff > qh_sup) + { + qh_sup = diff; + } + } + m.insert({qh_sup, "quintic_hermite_spline"}); + fs << qh_sup << ", "; + } + + { + auto sotaylor = [&phi, &phi_prime, &phi_dbl_prime, &r](Real x)->Real { + if (x <= 0 || x >= 2*p-1) + { + return 0; + } + using std::floor; + + Real y = (1<<r)*x; + Real k = floor(y); + + size_t kk = static_cast<size_t>(k); + if (y - k < k + 1 - y) + { + Real eps = (y-k)/(1<<r); + return phi[kk] + eps*phi_prime[kk] + eps*eps*phi_dbl_prime[kk]/2; + } + else { + Real eps = (y-k-1)/(1<<r); + return phi[kk+1] + eps*phi_prime[kk+1] + eps*eps*phi_dbl_prime[kk+1]/2; + } + }; + Real so_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - sotaylor(x)); + if (diff > so_sup) + { + so_sup = diff; + } + } + m.insert({so_sup, "Second-order Taylor"}); + if (p > 3) + { + fs << so_sup << ", "; + } + else + { + fs << so_sup << "\n"; + } + + } + } + + if constexpr (p > 3) + { + auto phi_dbl_prime = boost::math::daubechies_scaling_dyadic_grid<Real, p, 2>(r); + auto phi_triple_prime = boost::math::daubechies_scaling_dyadic_grid<Real, p, 3>(r); + + { + auto totaylor = [&phi, &phi_prime, &phi_dbl_prime, &phi_triple_prime, &r](Real x)->Real { + if (x <= 0 || x >= 2*p-1) { + return 0; + } + using std::floor; + + Real y = (1<<r)*x; + Real k = floor(y); + + size_t kk = static_cast<size_t>(k); + if (y - k < k + 1 - y) + { + Real eps = (y-k)/(1<<r); + return phi[kk] + eps*phi_prime[kk] + eps*eps*phi_dbl_prime[kk]/2 + eps*eps*eps*phi_triple_prime[kk]/6; + } + else { + Real eps = (y-k-1)/(1<<r); + return phi[kk+1] + eps*phi_prime[kk+1] + eps*eps*phi_dbl_prime[kk+1]/2 + eps*eps*eps*phi_triple_prime[kk]/6; + } + }; + Real to_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - totaylor(x)); + if (diff > to_sup) + { + to_sup = diff; + } + } + + m.insert({to_sup, "Third-order Taylor"}); + fs << to_sup << ", "; + } + + { + auto phi_copy = phi; + auto phi_prime_copy = phi_prime; + auto phi_dbl_prime_copy = phi_dbl_prime; + auto phi_triple_prime_copy = phi_triple_prime; + auto sh = boost::math::interpolators::cardinal_septic_hermite(std::move(phi_copy), std::move(phi_prime_copy), std::move(phi_dbl_prime_copy), std::move(phi_triple_prime_copy), Real(0), dx); + Real septic_sup = 0; + for (size_t i = 0; i < phi_dense.size(); ++i) + { + Real x = i*dx_dense; + Real diff = abs(phi_dense[i] - sh(x)); + if (diff > septic_sup) + { + septic_sup = diff; + } + } + m.insert({septic_sup, "septic_hermite_spline"}); + fs << septic_sup << "\n"; + } + + + } + std::string best = "none"; + Real best_sup = 1000000000; + std::cout << std::setprecision(std::numeric_limits<Real>::digits10 + 3) << std::fixed; + for (auto & e : m) + { + std::cout << "\t" << e.first << " is error of " << e.second << "\n"; + if (e.first < best_sup) + { + best = e.second; + best_sup = e.first; + } + } + std::cout << "\tThe best method for p = " << p << " is the " << best << "\n"; + } +} + +int main() +{ + //boost::hana::for_each(std::make_index_sequence<4>(), [&](auto i){ choose_refinement<double, float128, i+16>(); }); + boost::hana::for_each(std::make_index_sequence<12>(), [&](auto i){ find_best_interpolator<double, float128, i+2>(); }); +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/regress_daubechies_accuracy.cpp b/src/boost/libs/math/example/daubechies_wavelets/regress_daubechies_accuracy.cpp new file mode 100644 index 000000000..a033f8170 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/regress_daubechies_accuracy.cpp @@ -0,0 +1,154 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +// + + +#include <iostream> +#include <string> +#include <fstream> +#include <map> +#include <cmath> +#include <vector> +#include <iomanip> +#include <boost/algorithm/string.hpp> +#include <boost/math/statistics/linear_regression.hpp> +#include <boost/assert.hpp> + + +int main(int argc, char** argv) +{ + if (argc != 2) + { + std::cout << "Usage: ./regress_accuracy.x foo.csv\n"; + return 1; + } + std::string filename = std::string(argv[1]); + std::ifstream ifs(filename.c_str()); + if (!ifs.good()) + { + std::cerr << "Couldn't find file " << filename << "\n"; + return 1; + } + std::map<std::string, std::vector<double>> m; + + std::string header_line; + std::getline(ifs, header_line); + std::cout << "Header line = " << header_line << "\n"; + std::vector<std::string> header_strs; + boost::split(header_strs, header_line, boost::is_any_of(",")); + for (auto & s : header_strs) { + boost::algorithm::trim(s); + } + + std::string line; + std::vector<double> r; + std::vector<double> matched_holder; + std::vector<double> linear; + std::vector<double> quadratic_b_spline; + std::vector<double> cubic_b_spline; + std::vector<double> quintic_b_spline; + std::vector<double> cubic_hermite; + std::vector<double> pchip; + std::vector<double> makima; + std::vector<double> fotaylor; + std::vector<double> quintic_hermite; + std::vector<double> sotaylor; + std::vector<double> totaylor; + std::vector<double> septic_hermite; + while(std::getline(ifs, line)) + { + std::vector<std::string> strs; + boost::split(strs, line, boost::is_any_of(",")); + for (auto & s : strs) + { + boost::algorithm::trim(s); + } + std::vector<double> v(strs.size(), std::numeric_limits<double>::quiet_NaN()); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = std::stod(strs[i]); + } + r.push_back(v[0]); + matched_holder.push_back(std::log2(v[1])); + linear.push_back(std::log2(v[2])); + quadratic_b_spline.push_back(std::log2(v[3])); + cubic_b_spline.push_back(std::log2(v[4])); + quintic_b_spline.push_back(std::log2(v[5])); + cubic_hermite.push_back(std::log2(v[6])); + pchip.push_back(std::log2(v[7])); + makima.push_back(std::log2(v[8])); + fotaylor.push_back(std::log2(v[9])); + if (v.size() > 10) { + quintic_hermite.push_back(std::log2(v[10])); + sotaylor.push_back(std::log2(v[11])); + } + if (v.size() > 12) { + totaylor.push_back(std::log2(v[12])); + septic_hermite.push_back(std::log2(v[13])); + } + } + + std::cout << std::fixed << std::setprecision(16); + auto q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, matched_holder); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Matched Holder : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, linear); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Linear : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, quadratic_b_spline); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Quadratic B-spline: " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, cubic_b_spline); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Cubic B-spline : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, quintic_b_spline); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Quintic B-spline : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, cubic_hermite); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Cubic Hermite : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, pchip); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "PCHIP : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, makima); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Makima : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, fotaylor); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "First-order Taylor: " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + if (sotaylor.size() > 0) + { + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, quintic_hermite); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Quintic Hermite : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, sotaylor); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "2nd order Taylor : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + } + + if (totaylor.size() > 0) + { + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, totaylor); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "3rd order Taylor : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + q = boost::math::statistics::simple_ordinary_least_squares_with_R_squared(r, septic_hermite); + BOOST_ASSERT(std::get<1>(q) < 0); + std::cout << "Septic Hermite : " << std::get<0>(q) << " - " << std::abs(std::get<1>(q)) << "r, R^2 = " << std::get<2>(q) << "\n"; + + } + +} diff --git a/src/boost/libs/math/example/daubechies_wavelets/wavelet_transform.cpp b/src/boost/libs/math/example/daubechies_wavelets/wavelet_transform.cpp new file mode 100644 index 000000000..40a92b688 --- /dev/null +++ b/src/boost/libs/math/example/daubechies_wavelets/wavelet_transform.cpp @@ -0,0 +1,43 @@ +/* + * Copyright Nick Thompson, 2020 + * 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) + */ +#include <cstdint> +#include <cmath> +#include <boost/math/quadrature/wavelet_transforms.hpp> + + +int main() +{ + using boost::math::quadrature::daubechies_wavelet_transform; + double a = 1.3; + auto f = [&a](double t) { + if(t==0) { + return double(0); + } + return std::sin(a/t); + }; + + auto Wf = daubechies_wavelet_transform<decltype(f), double, 8>(f); + + double s = 7; + double t = 0; + + auto g = [&a](double t)->std::complex<double> { + if (t==0) { + return {0.0, 0.0}; + } + return std::exp(std::complex<double>(0.0, a/t)); + }; + + auto Wg = daubechies_wavelet_transform<decltype(g), double, 8>(g); + std::cout << "W[f](s,t) = " << Wf(s,t) << "\n"; + std::cout << "W[g](s,t) = " << Wg(s, t) << "\n"; + std::cout << Wg(0.0, 3.5) << "\n"; + std::cout << Wf(0.0, 4.8) << "\n"; + std::cout << "W[f](-s,t) = " << Wf(-s, t) << "\n"; + std::cout << "W[g](-s,t) = " << Wg(-s, t) << "\n"; + +} diff --git a/src/boost/libs/math/example/distribution_construction.cpp b/src/boost/libs/math/example/distribution_construction.cpp new file mode 100644 index 000000000..a3d1a635d --- /dev/null +++ b/src/boost/libs/math/example/distribution_construction.cpp @@ -0,0 +1,295 @@ +// distribution_construction.cpp + +// Copyright Paul A. Bristow 2007, 2010, 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) + +// Caution: this file contains Quickbook markup as well as code +// and comments, don't change any of the special comment markups! + +#ifdef _MSC_VER +# pragma warning (disable : 4996) // disable -D_SCL_SECURE_NO_WARNINGS C++ 'Checked Iterators' +#endif + +#include <iostream> +#include <exception> + +//[distribution_construction_1 + +/*` +The structure of distributions is rather different from some other statistical libraries, +for example, those written in less object-oriented language like FORTRAN and C that +provide a few arguments to each free function. + +Boost.Math library instead provides each distribution as a template C++ class. +A distribution is constructed with a few arguments, and then +member and non-member functions are used to find values of the +distribution, often a function of a random variate. + +For this demonstration, first we need some includes to access the +negative binomial distribution (and the binomial, beta and gamma distributions too). + +To demonstrate the use with a high precision User-defined floating-point type +`cpp_bin_float`, we also need an include from Boost.Multiprecision. +(We could equally well have used a `cpp_dec_float` multiprecision type). + +We choose a typedef `cpp_bin_float_50` to provide a 50 decimal digit type, +but we could equally have chosen at 128-bit type `cpp_bin_float_quad`, +or on some platforms `__float128`, providing about 35 decimal digits. +*/ + +#include <boost/math/distributions/negative_binomial.hpp> // for negative_binomial_distribution + using boost::math::negative_binomial_distribution; // default type is double. + using boost::math::negative_binomial; // typedef provides default type is double. +#include <boost/math/distributions/binomial.hpp> // for binomial_distribution. +#include <boost/math/distributions/beta.hpp> // for beta_distribution. +#include <boost/math/distributions/gamma.hpp> // for gamma_distribution. +#include <boost/math/distributions/normal.hpp> // for normal_distribution. + +#include <boost/multiprecision/cpp_bin_float.hpp> // for cpp_bin_float_50 +/*` +Several examples of constructing distributions follow: +*/ +//] [/distribution_construction_1 end of Quickbook in C++ markup] + +int main() +{ + try + { +//[distribution_construction_2 +/*` +First, a negative binomial distribution with 8 successes +and a success fraction 0.25, 25% or 1 in 4, is constructed like this: +*/ + boost::math::negative_binomial_distribution<double> mydist0(8., 0.25); + /*` + But this is inconveniently long, so we might be tempted to write + */ + using namespace boost::math; + /*` + but this might risk ambiguity with names in `std random` so + [*much] better is explicit `using boost::math::` statements, for example: + */ + using boost::math::negative_binomial_distribution; + /*` + and we can still reduce typing. + + Since the vast majority of applications use will be using `double` precision, + the template argument to the distribution (`RealType`) defaults + to type `double`, so we can also write: + */ + + negative_binomial_distribution<> mydist9(8., 0.25); // Uses default `RealType = double`. + + /*` + But the name `negative_binomial_distribution` is still inconveniently long, + so, for most distributions, a convenience `typedef` is provided, for example: + + typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double. + + [caution + This convenience typedef is [*not provided] if a clash would occur + with the name of a function; currently only `beta` and `gamma` + fall into this category. + ] + + So, after a using statement, + */ + + using boost::math::negative_binomial; + + /*` + we have a convenient typedef to `negative_binomial_distribution<double>`: + */ + negative_binomial mydist(8., 0.25); + + /*` + Some more examples using the convenience typedef: + */ + negative_binomial mydist10(5., 0.4); // Both arguments double. + /*` + And automatic conversion of arguments takes place, so you can use integers and floats: + */ + negative_binomial mydist11(5, 0.4); // Using provided typedef of type double, and int and double arguments. + /*` + This is probably the most common usage. + Other combination are possible too: + */ + negative_binomial mydist12(5., 0.4F); // Double and float arguments. + negative_binomial mydist13(5, 1); // Both arguments integer. + + /*` + Similarly for most other distributions like the binomial. + */ + binomial mybinomial(1, 0.5); // is more concise than + binomial_distribution<> mybinomd1(1, 0.5); + + /*` + For cases when the typdef distribution name would clash with a math special function + (currently only beta and gamma) + the typedef is deliberately not provided, and the longer version of the name + must be used, so for example, do not use: + + using boost::math::beta; + beta mybetad0(1, 0.5); // Error beta is a math FUNCTION! + + Which produces the error messages: + + [pre + error C2146: syntax error : missing ';' before identifier 'mybetad0' + warning C4551: function call missing argument list + error C3861: 'mybetad0': identifier not found + ] + + Instead you should use: + */ + using boost::math::beta_distribution; + beta_distribution<> mybetad1(1, 0.5); + /*` + or for the gamma distribution: + */ + gamma_distribution<> mygammad1(1, 0.5); + + /*` + We can, of course, still provide the type explicitly thus: + */ + + // Explicit double precision: both arguments are double: + negative_binomial_distribution<double> mydist1(8., 0.25); + + // Explicit float precision, double arguments are truncated to float: + negative_binomial_distribution<float> mydist2(8., 0.25); + + // Explicit float precision, integer & double arguments converted to float: + negative_binomial_distribution<float> mydist3(8, 0.25); + + // Explicit float precision, float arguments, so no conversion: + negative_binomial_distribution<float> mydist4(8.F, 0.25F); + + // Explicit float precision, integer arguments promoted to float. + negative_binomial_distribution<float> mydist5(8, 1); + + // Explicit double precision: + negative_binomial_distribution<double> mydist6(5., 0.4); + + // Explicit long double precision: + negative_binomial_distribution<long double> mydist7(8., 0.25); + + /*` + And you can use your own template RealType, + for example, `boost::math::cpp_bin_float_50` (an arbitrary 50 decimal digits precision type), + then we can write: + */ + using namespace boost::multiprecision; + negative_binomial_distribution<cpp_bin_float_50> mydist8(8, 0.25); + + // `integer` arguments are promoted to your RealType exactly, but + // `double` argument are converted to RealType, + // most likely losing precision! + + // So DON'T be tempted to write the 'obvious': + negative_binomial_distribution<cpp_bin_float_50> mydist20(8, 0.23456789012345678901234567890); + // to avoid truncation of second parameter to `0.2345678901234567` and loss of precision. + + // Instead pass a quoted decimal digit string: + negative_binomial_distribution<cpp_bin_float_50> mydist21(8, cpp_bin_float_50("0.23456789012345678901234567890") ); + + // Ensure that all potentially significant digits are shown. + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); + // + cpp_bin_float_50 x("1.23456789012345678901234567890"); + std::cout << pdf(mydist8, x) << std::endl; +/*` showing 0.00012630010495970320103876754721976419438231705359935 + 0.00012630010495970320103876754721976419438231528547467 + +[warning When using multiprecision, it is all too easy to get accidental truncation!] + +For example, if you write +*/ + std::cout << pdf(mydist8, 1.23456789012345678901234567890) << std::endl; +/*` +showing 0.00012630010495970318465064569310967179576805651692929, +which is wrong at about the 17th decimal digit! + +This is because the value provided is truncated to a `double`, effectively + `double x = 1.23456789012345678901234567890;` + +Then the now `double x` is passed to function `pdf`, +and this truncated `double` value is finally promoted to `cpp_bin_float_50`. + +Another way of quietly getting the wrong answer is to write: +*/ + std::cout << pdf(mydist8, cpp_bin_float_50(1.23456789012345678901234567890)) << std::endl; +/*` +A correct way from a multi-digit string value is +*/ + std::cout << pdf(mydist8, cpp_bin_float_50("1.23456789012345678901234567890")) << std::endl; +/*` + +[tip Getting about 17 decimal digits followed by many zeros is often a sign of accidental truncation.] +*/ + +/*` +[h4 Default arguments to distribution constructors.] + +Note that default constructor arguments are only provided for some distributions. +So if you wrongly assume a default argument, you will get an error message, for example: + + negative_binomial_distribution<> mydist8; + +[pre error C2512 no appropriate default constructor available.] + +No default constructors are provided for the `negative binomial` distribution, +because it is difficult to chose any sensible default values for this distribution. + +For other distributions, like the normal distribution, +it is obviously very useful to provide 'standard' +defaults for the mean (zero) and standard deviation (unity) thus: + + normal_distribution(RealType mean = 0, RealType sd = 1); + +So in this case we can more tersely write: +*/ + using boost::math::normal; + + normal norm1; // Standard normal distribution N[0,1]. + normal norm2(2); // Mean = 2, std deviation = 1. + normal norm3(2, 3); // Mean = 2, std deviation = 3. + + } + catch(std::exception &ex) + { + std::cout << ex.what() << std::endl; + } + + return 0; +} // int main() + +/*`There is no useful output from this demonstration program, of course. */ + +//] [/end of distribution_construction_2] + +/* +//[distribution_construction_output + + 0.00012630010495970320103876754721976419438231705359935 + 0.00012630010495970318465064569310967179576805651692929 + 0.00012630010495970318465064569310967179576805651692929 + 0.00012630010495970320103876754721976419438231705359935 + +//] [/distribution_construction_output] + + + 0.00012630010495970320103876754721976419438231528547467 + 0.0001263001049597031846506456931096717957680547488046 + 0.0001263001049597031846506456931096717957680547488046 + 0.00012630010495970320103876754721976419438231528547467 + + +*/ + + + diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/AssemblyInfo.cpp b/src/boost/libs/math/example/dot_net_example/boost_math/AssemblyInfo.cpp new file mode 100644 index 000000000..f8bcf1743 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/AssemblyInfo.cpp @@ -0,0 +1,44 @@ +#include "stdafx.h" + +// Copyright Paul A. Bristow & John Maddock 2009, 2010 +// 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) + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +// General Information about an assembly is controlled through the following set of attributes. +// Change these attribute values to modify the information associated with an assembly. + +[assembly:AssemblyTitleAttribute("boost_math")]; +[assembly:AssemblyDescriptionAttribute("Math Toolkit")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("jmc")]; +[assembly:AssemblyProductAttribute("boost_math")]; +[assembly:AssemblyCopyrightAttribute("Copyright (c) jmc 2007 - 2010")]; +[assembly:AssemblyTrademarkAttribute("")]; +[assembly:AssemblyCultureAttribute("")]; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the value or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly:AssemblyVersionAttribute("1.1.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; +// Deprecated: +//[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/ReadMe.txt b/src/boost/libs/math/example/dot_net_example/boost_math/ReadMe.txt new file mode 100644 index 000000000..a7a5a5d73 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/ReadMe.txt @@ -0,0 +1,38 @@ +======================================================================== + DYNAMIC LINK LIBRARY : boost_math Project Overview +======================================================================== + +AppWizard has created this boost_math DLL for you. + +// Copyright Paul A. Bristow & John Maddock 2009 +// 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) + +This file contains a summary of what you will find in each of the files that +make up your boost_math application. + +boost_math.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +boost_math.cpp + This is the main DLL source file. + +boost_math.h + This file contains a class declaration. + +AssemblyInfo.cpp + Contains custom attributes for modifying assembly metadata. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// + diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.cpp b/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.cpp new file mode 100644 index 000000000..f65a89a57 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.cpp @@ -0,0 +1,11 @@ +// stdafx.cpp : source file that includes just the standard includes +// boost_math.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +// Copyright Paul A. Bristow & John Maddock 2009 +// 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) + +#include "stdafx.h" diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.h b/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.h new file mode 100644 index 000000000..f463f27f6 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/Stdafx.h @@ -0,0 +1,54 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently. + +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007, 2009, 2010, 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) + +// Laplace added Aug 2009 PAB, and several others Nov 2010, +// added skew_normal 2012. + +#ifdef _MSC_VER +# pragma once +# pragma warning (disable : 4127) +#endif + +#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false +#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error + +#include <boost/math/distributions/bernoulli.hpp> +#include <boost/math/distributions/beta.hpp> +#include <boost/math/distributions/binomial.hpp> +#include <boost/math/distributions/cauchy.hpp> +#include <boost/math/distributions/chi_squared.hpp> +#include <boost/math/distributions/exponential.hpp> +#include <boost/math/distributions/extreme_value.hpp> +#include <boost/math/distributions/fisher_f.hpp> +#include <boost/math/distributions/gamma.hpp> +#include <boost/math/distributions/geometric.hpp> +#include <boost/math/distributions/hypergeometric.hpp> +#include <boost/math/distributions/inverse_chi_squared.hpp> +#include <boost/math/distributions/inverse_gamma.hpp> +#include <boost/math/distributions/inverse_gaussian.hpp> +#include <boost/math/distributions/laplace.hpp> +#include <boost/math/distributions/logistic.hpp> +#include <boost/math/distributions/lognormal.hpp> +#include <boost/math/distributions/negative_binomial.hpp> +#include <boost/math/distributions/non_central_beta.hpp> +#include <boost/math/distributions/non_central_chi_squared.hpp> +#include <boost/math/distributions/non_central_f.hpp> +#include <boost/math/distributions/non_central_t.hpp> +#include <boost/math/distributions/normal.hpp> +#include <boost/math/distributions/pareto.hpp> +#include <boost/math/distributions/poisson.hpp> +#include <boost/math/distributions/rayleigh.hpp> +#include <boost/math/distributions/students_t.hpp> +#include <boost/math/distributions/skew_normal.hpp> +#include <boost/math/distributions/triangular.hpp> +#include <boost/math/distributions/uniform.hpp> +#include <boost/math/distributions/weibull.hpp> diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/app.ico b/src/boost/libs/math/example/dot_net_example/boost_math/app.ico Binary files differnew file mode 100644 index 000000000..3a5525fd7 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/app.ico diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/app.rc b/src/boost/libs/math/example/dot_net_example/boost_math/app.rc new file mode 100644 index 000000000..0bc391bdc --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/app.rc @@ -0,0 +1,63 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon placed first or with lowest ID value becomes application icon + +LANGUAGE 9, 2 +#pragma code_page(1252) +1 ICON "app.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.cpp b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.cpp new file mode 100644 index 000000000..32c2ca603 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.cpp @@ -0,0 +1,255 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007, 2009, 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) + +// boost_math.cpp This is the main DLL file. + +//#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error +//#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false +// These are now defined in project properties +// to avoid complications with pre-compiled headers: +// "BOOST_MATH_ASSERT_UNDEFINED_POLICY=0" +// "BOOST_MATH_OVERFLOW_ERROR_POLICY="errno_on_error"" +// so command line shows: +// /D "BOOST_MATH_ASSERT_UNDEFINED_POLICY=0" +// /D "BOOST_MATH_OVERFLOW_ERROR_POLICY="errno_on_error"" + +#include "stdafx.h" + +#ifdef _MSC_VER +# pragma warning(disable: 4400) // 'const boost_math::any_distribution ^' : const/volatile qualifiers on this type are not supported +# pragma warning(disable: 4244) // 'argument' : conversion from 'double' to 'unsigned int', possible loss of data +# pragma warning(disable: 4512) // assignment operator could not be generated +// hypergeometric expects integer parameters. +# pragma warning(disable: 4127) // constant +#endif + +#include "boost_math.h" + +namespace boost_math +{ + +any_distribution::any_distribution(int t, double arg1, double arg2, double arg3) +{ + TRANSLATE_EXCEPTIONS_BEGIN + // This is where all the work gets done: + switch(t) // index of distribution to distribution_info distributions[] + { // New entries must match distribution names, parameter name(s) and defaults defined below. + case 0: + this->reset(new concrete_distribution<boost::math::bernoulli>(boost::math::bernoulli(arg1))); + break; + case 1: + this->reset(new concrete_distribution<boost::math::beta_distribution<> >(boost::math::beta_distribution<>(arg1, arg2))); + break; // Note - no typedef, so need explicit type <> but rely on default = double. + case 2: + this->reset(new concrete_distribution<boost::math::binomial_distribution<> >(boost::math::binomial_distribution<>(arg1, arg2))); + break; // Note - no typedef, so need explicit type <> but rely on default = double. + case 3: + this->reset(new concrete_distribution<boost::math::cauchy>(boost::math::cauchy(arg1, arg2))); + break; + case 4: + this->reset(new concrete_distribution<boost::math::chi_squared>(boost::math::chi_squared(arg1))); + break; + case 5: + this->reset(new concrete_distribution<boost::math::exponential>(boost::math::exponential(arg1))); + break; + case 6: + this->reset(new concrete_distribution<boost::math::extreme_value>(boost::math::extreme_value(arg1))); + break; + case 7: + this->reset(new concrete_distribution<boost::math::fisher_f >(boost::math::fisher_f(arg1, arg2))); + break; + case 8: + this->reset(new concrete_distribution<boost::math::gamma_distribution<> >(boost::math::gamma_distribution<>(arg1, arg2))); + break; + case 9: + this->reset(new concrete_distribution<boost::math::geometric_distribution<> >(boost::math::geometric_distribution<>(arg1))); + break; + case 10: + this->reset(new concrete_distribution<boost::math::hypergeometric_distribution<> >(boost::math::hypergeometric_distribution<>(arg1, arg2, arg3))); + break; + case 11: + this->reset(new concrete_distribution<boost::math::inverse_chi_squared_distribution<> >(boost::math::inverse_chi_squared_distribution<>(arg1, arg2))); + break; + case 12: + this->reset(new concrete_distribution<boost::math::inverse_gamma_distribution<> >(boost::math::inverse_gamma_distribution<>(arg1, arg2))); + break; + case 13: + this->reset(new concrete_distribution<boost::math::inverse_gaussian_distribution<> >(boost::math::inverse_gaussian_distribution<>(arg1, arg2))); + break; + case 14: + this->reset(new concrete_distribution<boost::math::laplace_distribution<> >(boost::math::laplace_distribution<>(arg1, arg2))); + break; + case 15: + this->reset(new concrete_distribution<boost::math::logistic_distribution<> >(boost::math::logistic_distribution<>(arg1, arg2))); + break; + case 16: + this->reset(new concrete_distribution<boost::math::lognormal_distribution<> >(boost::math::lognormal_distribution<>(arg1, arg2))); + break; + case 17: + this->reset(new concrete_distribution<boost::math::negative_binomial_distribution<> >(boost::math::negative_binomial_distribution<>(arg1, arg2))); + break; + case 18: + this->reset(new concrete_distribution<boost::math::non_central_beta_distribution<> >(boost::math::non_central_beta_distribution<>(arg1, arg2, arg3))); + break; + case 19: + this->reset(new concrete_distribution<boost::math::non_central_chi_squared_distribution<> >(boost::math::non_central_chi_squared_distribution<>(arg1, arg2))); + break; + case 20: + this->reset(new concrete_distribution<boost::math::non_central_f_distribution<> >(boost::math::non_central_f_distribution<>(arg1, arg2, arg3))); + break; + case 21: + this->reset(new concrete_distribution<boost::math::non_central_t_distribution<> >(boost::math::non_central_t_distribution<>(arg1, arg2))); + break; + case 22: + this->reset(new concrete_distribution<boost::math::normal_distribution<> >(boost::math::normal_distribution<>(arg1, arg2))); + break; + case 23: + this->reset(new concrete_distribution<boost::math::pareto>(boost::math::pareto(arg1, arg2))); + break; + case 24: + this->reset(new concrete_distribution<boost::math::poisson>(boost::math::poisson(arg1))); + break; + case 25: + this->reset(new concrete_distribution<boost::math::rayleigh>(boost::math::rayleigh(arg1))); + break; + case 26: + this->reset(new concrete_distribution<boost::math::skew_normal>(boost::math::skew_normal(arg1, arg2, arg3))); + break; + case 27: + this->reset(new concrete_distribution<boost::math::students_t>(boost::math::students_t(arg1))); + break; + case 28: + this->reset(new concrete_distribution<boost::math::triangular>(boost::math::triangular(arg1, arg2, arg3))); + break; + case 29: + this->reset(new concrete_distribution<boost::math::uniform>(boost::math::uniform(arg1, arg2))); + break; + case 30: + this->reset(new concrete_distribution<boost::math::weibull>(boost::math::weibull(arg1, arg2))); + break; + + + default: + // TODO Need some proper error handling here? + BOOST_MATH_ASSERT(0); + } + TRANSLATE_EXCEPTIONS_END +} // any_distribution constructor. + +struct distribution_info +{ + const char* name; // of distribution. + const char* first_param; // Parameters' name like "degrees of freedom", + const char* second_param; // if required, else "", + const char* third_param; // if required, else "". + // triangular and non-centrals need 3 parameters. + // (Only the Bi-Weibull would need 5 parameters?) + double first_default; // distribution parameter value, often 0, 0.5 or 1. + double second_default; // 0 if there isn't a second argument. + // Note that defaults below follow default argument in constructors, + // if any, but need not be the same. + double third_default; // 0 if there isn't a third argument. +}; + +distribution_info distributions[] = +{ // distribution name, parameter name(s) and default(s) + // Order must match any_distribution constructor above! + // Null string "" and zero default for un-used arguments. + { "Bernoulli", "Probability", "", "",0.5, 0, 0}, // case 0 + { "Beta", "Alpha", "Beta", "", 1, 1, 0}, // case 1 + { "Binomial", "Trials", "Probability of success", "", 1, 0.5, 0}, // case 2 + { "Cauchy", "Location", "Scale", "", 0, 1, 0}, // case 3 + { "Chi_squared", "Degrees of freedom", "", "", 1, 0, 0}, // case 4 + { "Exponential", "lambda", "", "", 1, 0, 0}, // case 5 + { "Extreme value", "Location", "Scale", "", 0, 1, 0}, // case 6 + { "Fisher-F", "Degrees of freedom 1", "Degrees of freedom 2", "", 1, 1, 0}, // case 7 + { "Gamma (Erlang)", "Shape", "Scale", "", 1, 1, 0}, // case 8 + { "Geometric", "Probability", "", "", 1, 0, 0}, // case 9 + { "HyperGeometric", "Defects", "Samples", "Objects", 1, 0, 1}, // case 10 + { "InverseChiSq", "Degrees of Freedom", "Scale", "", 1, 1, 0}, // case 11 + { "InverseGamma", "Shape", "Scale", "", 1, 1, 0}, // case 12 + { "InverseGaussian", "Mean", "Scale", "", 1, 1, 0}, // case 13 + { "Laplace", "Location", "Scale", "", 0, 1, 0}, // case 14 + { "Logistic", "Location", "Scale", "", 0, 1, 0}, // case 15 + { "LogNormal", "Location", "Scale", "", 0, 1, 0}, // case 16 + { "Negative Binomial", "Successes", "Probability of success", "", 1, 0.5, 0}, // case 17 + { "Noncentral Beta", "Shape alpha", "Shape beta", "Non-centrality", 1, 1, 0}, // case 18 + { "Noncentral ChiSquare", "Degrees of Freedom", "Non-centrality", "", 1, 0, 0}, // case 19 + { "Noncentral F", "Degrees of Freedom 1", "Degrees of Freedom 2", "Non-centrality", 1, 1, 0}, // case 20 + { "Noncentral t", "Degrees of Freedom", "Non-centrality", "", 1, 0, 0}, // case 21 + { "Normal (Gaussian)", "Mean", "Standard Deviation", "", 0, 1, 0}, // case 22 + { "Pareto", "Location", "Shape","", 1, 1, 0}, // case 23 + { "Poisson", "Mean", "", "", 1, 0, 0}, // case 24 + { "Rayleigh", "Shape", "", "", 1, 0, 0}, // case 25 + { "Skew Normal", "Location", "Shape", "Skew", 0, 1, 0}, // case 27 (defaults to Gaussian). + { "Student's t", "Degrees of Freedom", "", "", 1, 0, 0}, // case 28 + { "Triangular", "Lower", "Mode", "Upper", -1, 0, +1 }, // case 29 3rd parameter! + // 0, 0.5, 1 also said to be 'standard' but this is most like an approximation to Gaussian distribution. + { "Uniform", "Lower", "Upper", "", 0, 1, 0}, // case 30 + { "Weibull", "Shape", "Scale", "", 1, 1, 0}, // case 31 +}; + +// How many distributions are supported: +int any_distribution::size() +{ + return sizeof(distributions) / sizeof(distributions[0]); +} + +// Display name of i'th distribution: +System::String^ any_distribution::distribution_name(int i) +{ + if(i >= size()) + return ""; + return gcnew System::String(distributions[i].name); +} +// Name of first distribution parameter, or null if not supported: +System::String^ any_distribution::first_param_name(int i) +{ + if(i >= size()) + return ""; + return gcnew System::String(distributions[i].first_param); +} +// Name of second distribution parameter, or null if not supported: +System::String^ any_distribution::second_param_name(int i) +{ + if(i >= size()) + return ""; + return gcnew System::String(distributions[i].second_param); +} +// Name of third distribution parameter, or null if not supported: +System::String^ any_distribution::third_param_name(int i) +{ + if(i >= size()) + return ""; + return gcnew System::String(distributions[i].third_param); +} +// default value for first parameter: +double any_distribution::first_param_default(int i) +{ + if(i >= size()) + return 0; + return distributions[i].first_default; +} +// default value for second parameter: +double any_distribution::second_param_default(int i) +{ + if(i >= size()) + return 0; + return distributions[i].second_default; +} +// default value for third parameter: +double any_distribution::third_param_default(int i) +{ + if(i >= size()) + return 0; + return distributions[i].third_default; +} + +} // namespace boost_math + + diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.h b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.h new file mode 100644 index 000000000..f8132adbd --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.h @@ -0,0 +1,331 @@ +// boost_math.h + +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007. + +// 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) + +//#define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error +//#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false +// These are now defined in project properties +// "BOOST_MATH_ASSERT_UNDEFINED_POLICY=0" +// "BOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error" +// to avoid complications with pre-compiled headers. + +#ifdef _MSC_VER +# pragma once +# pragma warning (disable : 4127) +#endif + +using namespace System; + +#define TRANSLATE_EXCEPTIONS_BEGIN try{ + +#define TRANSLATE_EXCEPTIONS_END \ + }catch(const std::exception& e){ \ + System::String^ s = gcnew System::String(e.what());\ + InvalidOperationException^ se = gcnew InvalidOperationException(s);\ + throw se; \ + } + +namespace boost_math { + + class any_imp + { + public: + // Distribution properties. + virtual double mean()const = 0; + virtual double mode()const = 0; + virtual double median()const = 0; + virtual double variance()const = 0; + virtual double standard_deviation()const = 0; + virtual double skewness()const = 0; + virtual double kurtosis()const = 0; + virtual double kurtosis_excess()const = 0; + virtual double coefficient_of_variation()const = 0; + // Values computed from random variate x. + virtual double hazard(double x)const = 0; + virtual double chf(double x)const = 0; + virtual double cdf(double x)const = 0; + virtual double ccdf(double x)const = 0; + virtual double pdf(double x)const = 0; + virtual double quantile(double x)const = 0; + virtual double quantile_c(double x)const = 0; + // Range & support of x + virtual double lowest()const = 0; + virtual double uppermost()const = 0; + virtual double lower()const = 0; + virtual double upper()const = 0; + }; + + template <class Distribution> + class concrete_distribution : public any_imp + { + public: + concrete_distribution(const Distribution& d) : m_dist(d) {} + // Distribution properties. + virtual double mean()const + { + return boost::math::mean(m_dist); + } + virtual double median()const + { + return boost::math::median(m_dist); + } + virtual double mode()const + { + return boost::math::mode(m_dist); + } + virtual double variance()const + { + return boost::math::variance(m_dist); + } + virtual double skewness()const + { + return boost::math::skewness(m_dist); + } + virtual double standard_deviation()const + { + return boost::math::standard_deviation(m_dist); + } + virtual double coefficient_of_variation()const + { + return boost::math::coefficient_of_variation(m_dist); + } + virtual double kurtosis()const + { + return boost::math::kurtosis(m_dist); + } + virtual double kurtosis_excess()const + { + return boost::math::kurtosis_excess(m_dist); + } + // Range of x for the distribution. + virtual double lowest()const + { + return boost::math::range(m_dist).first; + } + virtual double uppermost()const + { + return boost::math::range(m_dist).second; + } + // Support of x for the distribution. + virtual double lower()const + { + return boost::math::support(m_dist).first; + } + virtual double upper()const + { + return boost::math::support(m_dist).second; + } + + // Values computed from random variate x. + virtual double hazard(double x)const + { + return boost::math::hazard(m_dist, x); + } + virtual double chf(double x)const + { + return boost::math::chf(m_dist, x); + } + virtual double cdf(double x)const + { + return boost::math::cdf(m_dist, x); + } + virtual double ccdf(double x)const + { + return boost::math::cdf(complement(m_dist, x)); + } + virtual double pdf(double x)const + { + return boost::math::pdf(m_dist, x); + } + virtual double quantile(double x)const + { + return boost::math::quantile(m_dist, x); + } + virtual double quantile_c(double x)const + { + return boost::math::quantile(complement(m_dist, x)); + } + private: + Distribution m_dist; + }; + + public ref class any_distribution + { + public: + // Added methods for this class here. + any_distribution(int t, double arg1, double arg2, double arg3); + ~any_distribution() + { + reset(0); + } + // Is it OK for these to be inline? + // Distribution properties as 'pointer-to-implementations'. + double mean() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->mean(); + TRANSLATE_EXCEPTIONS_END + } + double median() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->median(); + TRANSLATE_EXCEPTIONS_END + } + double mode() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->mode(); + TRANSLATE_EXCEPTIONS_END + } + double variance() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->variance(); + TRANSLATE_EXCEPTIONS_END + } + double standard_deviation() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->standard_deviation(); + TRANSLATE_EXCEPTIONS_END + } + double coefficient_of_variation() + { // aka Relative Standard deviation. + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->coefficient_of_variation(); + TRANSLATE_EXCEPTIONS_END + } + double skewness() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->skewness(); + TRANSLATE_EXCEPTIONS_END + } + double kurtosis() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->kurtosis(); + TRANSLATE_EXCEPTIONS_END + } + double kurtosis_excess() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->kurtosis_excess(); + TRANSLATE_EXCEPTIONS_END + } + // Values computed from random variate x. + double hazard(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->hazard(x); + TRANSLATE_EXCEPTIONS_END + } + double chf(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->chf(x); + TRANSLATE_EXCEPTIONS_END + } + double cdf(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->cdf(x); + TRANSLATE_EXCEPTIONS_END + } + double ccdf(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->ccdf(x); + TRANSLATE_EXCEPTIONS_END + } + double pdf(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->pdf(x); + TRANSLATE_EXCEPTIONS_END + } + double quantile(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->quantile(x); + TRANSLATE_EXCEPTIONS_END + } + double quantile_c(double x) + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->quantile_c(x); + TRANSLATE_EXCEPTIONS_END + } + + double lowest() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->lowest(); + TRANSLATE_EXCEPTIONS_END + } + + double uppermost() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->uppermost(); + TRANSLATE_EXCEPTIONS_END + } + + double lower() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->lower(); + TRANSLATE_EXCEPTIONS_END + } + double upper() + { + TRANSLATE_EXCEPTIONS_BEGIN + return pimpl->upper(); + TRANSLATE_EXCEPTIONS_END + } + + // How many distributions are supported: + static int size(); + // Display name of i'th distribution: + static System::String^ distribution_name(int i); + // Name of first distribution parameter, or null if not supported: + static System::String^ first_param_name(int i); + // Name of second distribution parameter, or null if not supported: + static System::String^ second_param_name(int i); + // Name of third distribution parameter, or null if not supported: + static System::String^ third_param_name(int i); + // Default value for first parameter: + static double first_param_default(int i); + // Default value for second parameter: + static double second_param_default(int i); + // Default value for third parameter: + static double third_param_default(int i); + + private: + any_distribution(const any_distribution^) + { // Constructor is private. + } + const any_distribution^ operator=(const any_distribution^ d) + { // Copy Constructor is private too. + return d; + } + // We really should use a shared_ptr here, + // but apparently it's not allowed in a managed class like this :-( + void reset(any_imp* p) + { + if(pimpl) + { // Exists already, so + delete pimpl; + } + pimpl = p; + } + any_imp* pimpl; + }; +} diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.sln b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.sln new file mode 100644 index 000000000..4730d9ef9 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2024 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boost_math", "boost_math.vcxproj", "{80E5F29C-93FB-4C84-A818-D2B8263C7CA1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x64.ActiveCfg = Debug|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x64.Build.0 = Debug|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x86.ActiveCfg = Debug|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x86.Build.0 = Debug|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x64.ActiveCfg = Release|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x64.Build.0 = Release|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x86.ActiveCfg = Release|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3ECDFDBF-9C5F-4C39-B5E5-581C15299AD1} + EndGlobalSection +EndGlobal diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj new file mode 100644 index 000000000..65b7679a7 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{80E5F29C-93FB-4C84-A818-D2B8263C7CA1}</ProjectGuid> + <Keyword>ManagedCProj</Keyword> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CLRSupport>true</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CLRSupport>true</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CLRSupport>true</CLRSupport> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CLRSupport>true</CLRSupport> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;BOOST_MATH_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../../../..</AdditionalIncludeDirectories> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <Link> + <TargetMachine>MachineX86</TargetMachine> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;BOOST_MATH_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <AdditionalIncludeDirectories>../../../..</AdditionalIncludeDirectories> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <Link> + <TargetMachine>MachineX86</TargetMachine> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>../../../..</AdditionalIncludeDirectories> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <AdditionalIncludeDirectories>../../../..</AdditionalIncludeDirectories> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="AssemblyInfo.cpp" /> + <ClCompile Include="boost_math.cpp" /> + <ClCompile Include="Stdafx.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="boost_math.h" /> + <ClInclude Include="resource.h" /> + <ClInclude Include="Stdafx.h" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="app.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj.filters b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj.filters new file mode 100644 index 000000000..001f2489b --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/boost_math.vcxproj.filters @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AssemblyInfo.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="boost_math.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Stdafx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="boost_math.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="resource.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Stdafx.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="app.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/boost_math/resource.h b/src/boost/libs/math/example/dot_net_example/boost_math/resource.h new file mode 100644 index 000000000..c775cb924 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/boost_math/resource.h @@ -0,0 +1,9 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc + +// Copyright Paul A. Bristow & John Maddock 2009 +// 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) diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistEx.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistEx.resx new file mode 100644 index 000000000..804e65e01 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistEx.resx @@ -0,0 +1,322 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="logoPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAARUAAABWCAIAAABuN5XDAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAALWZJREFUeF7tnfuPJNd138n8TyvSNiQIMSDBtCHEgJNAMIQAgmEESKIgCIIktBMBUeAf + iFAGlAB2nMQOaYoUl6ReJHdtSUvxqdeSS1rSkhIpSqQs8xVZj92e6Znurpp8zvnee+t23arq6p7u5VJq + orCc6am6dev0/dY553se98aTk5Mb9v/tJXBDWAashxtvlDjyhcHPdvhf+TP/r+MJ4U832FUnN4TP7Vp+ + 0VUaj1/tyvirfRJGCze78YYbOZt/4725Ez/rav/hxn9g/9rY+jz86Ub/PI6W/0kP4gOe3OAzbz7Zzndu + Itn/90stgRowxKM6OeFYZMf85GR2cnJ8cnLkx/Tk5LCuD+p6cnJyta5/zlHVP63rn3BU9Y/r+v/V9VtV + /WZVv1HVr1f1a7Udf1fVP6qqv63rv63qH9q/1Q/zI/ucE37E+X4VByMwzpuMycg+vm7EHe3WPocJ82FW + PjdNktkyZ2aeP4geLX/YLXzr/krZ//dLKYG6biOnrjuRY+CpaxYoyxTkBNjULOITVvPfV6zsiiUOZl5n + xfvq/1HlUKmqV6rqB358v6peruqXq+p7VfWSH/ygI/5qf+XgTF3ySs0INagTosASg7/Jvbgj9/W7ByAx + qzg95ikItVHkT7eEIpfAqf7b4+dU4nsnXxzAU9daUqZ2In6Szjmua1M4rnN4zV85OblS1z9zJfD3rmqk + Z16r0DCVtIoBpq7BgIDxYlV/d1G9UFUvLKrnF9Xlyo5v+3F5sbB/m1/5pHrez3yBq+xah5mPZnDy8YEl + 2gzV9AZ39zkwE+bzM58bB4pRE2bmSyiKT2cP60+dXh+bf417/Gwuu3folaXacTtHZluDHH+Lm6l2cmLI + cXtJdtqPXQOwfF+rKqwyVMSrQb0IMNV3wIDBo/r2YvHNRfU3i8WzflxaLJ5ZLJ5eVE/bv/kRPuGvnOMn + 21VcK4AxGmMKTq6g7I5gCb0EdN9w7SfTTuoInCejrtRFetLtKKI9ft6hKNh42h1qxzXPvK5ndR38HLfW + OCa1vdRxM1iXpnB8pb5eVWibBBvpme+46hBgnltUAOAZx8k3FouvLaqvzRdfmS+eWiyenC+e9H+fWMTD + f06fP8WZnG9XcS0j2DiM9hwj2/h2F7Ak8y8Bya07m5upI5/tz5k58/dXgCw6TFDUKc+Y/KItKKL18HP1 + YPrs89/Xcd/5r6Tj9bd+uvH3ub/wGkqg5AkatVPXrDAxBEYPSOck5LixxMveFY5ZU+gBg03lsKlQF7bK + HTDV1w0DhhaA8fh88eh88Ygd8y/N51+cz78wX3xhPv9r+1eHfuZz++uXwsmLR7nWRxCivh7h9Cz38jsm + IDET5gOeTR0loy6gKFh0aNFpfMBELXQoonW/i1H4AS23/N5/HTg4Yd0b78+/5hLoINmC2nE/Ibo6LDUx + BKZzKiO+pHNwb16talYqsPnuYiFtg6q5BGzmC2kY1Mhj88WXHS1fdHj81Xxxfj5/eDZ/cG7H5+fzz83m + n53PPzubf0aH/8wnn/O/PuhnPmxX2bWMwDjAjzEZmfG5CwoNvYSl91zUSDhLL/ncsOvgG5xmsJmjM00X + 8UTOLjROUamINnOHRuEHPTOMn2u+FPY3XEsCJUO9rHacXnNW2pBzciKGwOgBd3JYkebhLIJvg0PyTfdS + 0DYsZRb0E65kLszmX5jN/2o2P+cY+LzD49Oz+f2z+X3Hs3tn80/5cc9sdvdsfvfx7JOz2Sft3/nd/sk9 + 4QQ78z6/imtBF+MAKsZkZOB0we/FHdFv2HgACY2EacessCHxkb7vs2XOSRf9xJ+INwJPxzOaOeeaNldE + G7Lbo/Bz/rFLt97+SY6PfOz/lED68H/8H2t9mfuTr60ElhweOKhEsrm3E9RONNiEHHzxt6qK9Ye1Jm6A + dYkT73aacQB4NV81p2X+KBbXzAwwlMxDM9MtAsxZ8AA2jo7/ZHp82+H03x1Mf/9g+sHJ4S2Tw9/04x9e + PXiXDn7WhweHt3AOZ3I+V3GtowtcMZrghI56iHvZHc0a5O4YeMyE+TwT7TrmaShi5j5/ngJFJHaBpwsE + ndg5l4C5Q1Esa/Nyo/CTf9+lLvqjP33g2i6I/d3GS6DXZvPVE+KhzlYFg81XG9waHDF+Dg76S84+47hj + qoEc/JCn5nNMqUcWWFZzrCxggwH2gCsNMHPn9OiPDqb/4uDwt68e/OrVgzNXD24CJFcmZyaHQEU/nLky + uWlyGA7/mU/CCZMJl4ArruKHX2UcRmNMRnYscRfuxR1RcYAWjYSt+Ji7W193ssGMOkN7jZ3J/AnXwi7w + RLk5J47bPCKXQ5tUGG/LrY2fJy4+31JBIGr897k/c2MJIGdZAX9+/4Vxg3RmFTT5BLLZorcjtUN0EoNN + DMH3FlhEFqKBG2BdGnIWOCFz7DQUzjm3rD49m0nV/Mnh9F8fHP6jK5ObWfqTA/BgUOFfsOF4CECKaodf + AYxAohN06BO7qhlB105uZvzp8b/iXm4Ect9Pm8u0wLRDHV1gbjZD5lmZLmLmzN9pOmcXTBElmluJC8GW + KyKtLVtuSNhr46fUPyBq3Ne5P+tUEgA5enN94s6HRwzUCx5/6Sq2I5LNbDa87aqy1AEnCWSwEe6EjL40 + DzrHPJz54q9nZqfx+segwpn5s8Ppv5kcfkCL3tHCQs/x8K4JYDBEmfIBFfx7lWNih/3sP/BJ+ms6PwMV + 5xjYGF9Q5I7cl7v7HJgJ88GuA9UXMOqiLoLYwC+C5yCGK3OOpyOJAUW0ZMsV7lA7OjQg7bXxg7XW0j8v + vfLaiK9zf8qpJEDkIIl9hMLvB4+5ztgtiormNhuvZxg2o9cw2Dz0CR990fku0zm2Og05n4kK57aD6T+N + DowjISiZMwDAgSRgOGDCnxw59uuZKwaqcPCzwS/8SZrKL0dx+Tg2Wjgn/CmO+S7mcDy7LaojyAZHkc0W + CxPW+6I/BYoIExRzjsQI8QpLtpwrIuXO5Vlzo7TQ2vgpKYRTrYv9xeMkAIWT8LMqWjBkttUY/SGHLVEF + Cuy4txPUDsaPKGloLrhjfAwIaMi0sxBl06P/fHD4W64EzlwxbXPTVTfDrrjN5prEfjZ1xDkOEqHF9ZLh + RCpI7tDNN9+cPrG/omfi+f5DHAcsOZD8E362+3J3Nw7PMB9m5SQeRt1nmK3PmZnDLoijI2Tkiih4RLkt + hxzEbivfZz0IrY2flvLBqBi3APZnnUoCyXhD/gPR6iw3J8+kTj6PYqMK74ihFlWAzUYUEm/nW05MfwN2 + 2NitxRdnhGKMVTNu4PDoDyaHv+6mlC1l1yQOD9lgIMSR0wAmmGpRBTkGdBX/ghz9lz7xv0blA9gEswgn + Q45cKfOspJHshKjruMuvM0NxDD5nUATDIXMOgo7n+pYFfOuXIbgjqYAEkINR2ysh1Jlsuh5+ykDqOFv8 + VEtnf3Eu9n/ykf82KBBTPnXMB11OaXPw4DefsFwsMOrpzCRKk5fpNhupN8ZNkz3whJlAFm/5/Gz2wPEM + euDj8MumZAwqWsfgBM0j5Ej/SMnohGCSBSNNvybCWrS1H4YfXRj/dc0W/prGsTEdM8HYMzpB6HK+wSw9 + n5td+5vMljkzc+bPUzi1gCKC/+Dp8OjMlqtrkrt5drlDpHKT79MLIZentHr7v/Xwk1sRUkQjbPH9+j+t + BHLlM6jwHTwhn1qVCMuaJ4LHHQCWDrnMcnigCmSzfcW4acujgV777PHs7NHxnx1M/5mQowXqyAnWV7Po + o+pgfUsFiUWAgtP5AVfSWpEw4Iegf9LnESd+R2kbKTTDp1Rc0ntykwQ2TSxNkjkzc+bPU/iz8ETuES2e + djoRW87yFdwd4iUyAkJNvvbSt7kefkrybZUtftqls7++FTDoJ68bt2e5DCGmtAXwYK5YbNQTxszhoabA + 03CgCsg0I02GHAJCKwQr75ke/aerB+/2ZRpiOLaIAwkWVm3g00Sy5VRBNK7MxJJ2UvzHzwz6R/6Pf5Kf + 4KZaYyIm+sGhYtcGl0nI1GGukeAaZsvMmT9P4c/yoHtEPB0EN6QCMSLyFcTLidp2Um5JCzV0Qiwc6qh3 + WA8/+YtQ+mefObpThMNtYrDlPmenwm+5PR5NN83jGZNLZlsCz8I8acDjPJvZNqSWPTKzeChRHRjh/zuZ + /q5MKZlGhHQSctyJt+hn0C1hEbu6cNIsmHNutomIiyoixXncQov4yUy4oKwciu5oSbc4ldfweMHYUwQJ + 7EXj0OcpIzOMMP1dnoUn8ufi6Qj7kgDO8xovhwScNUkQagw5ZykNQp4iuMRo547QevhpfZerbPGdLq1f + /MFL8ACkHoWvV2NWCReLrlNWmydTBs0DeBYVOZfERp+1dEzj2eB8yYuBZLv3+Pg25dfIYFMcU+Bx/SPf + g5BOiHU6bOxDN94CQhrNkFRE6wcfUPpn4EjjBOfHbx3Plw/m84GOS4oo+kKKF/EsPBHP5dQcEJI79DWe + 3SWAHJYhFDPlVMdamyQTftqO0Br4yUMQeiPmtnirooHXJM7SVkJD3JehsFsUfU8Htzh96HYXgzMmE2N6 + xMrKOSMTTkiP0/cIXN56W0nmXa+NTrdHlTxew1P/rBJh4GabwGPheYrVLKuAEgNy2Jyhnt0zPf639kb3 + V7jbWoEMkLsv8uCKZxiEle2csiw3PydQZCGME0C4hJCGrxN+gmfVPiciJ0A33dGVUlSG5h3ZfEQhhEmK + JZfLFLB0E8/F0/kLAl7uS1YcYc9OEvcShJxW4UVDNatyfFR+15QMZYWr9lWsgZ+SfGMRYL/xb+c3re+b + 7FJW/2bKgjuW4doWgc6tN+MwdjE40oCQHM5V56+5uHLhqLyKx0FofYO0AJl+femVH8V2GdgblttWhwyD + QFU722aEgWsefB4SC4jw4FVDUhMYNYeH3M1AfxkeCLAEulluT1QvjbEUwjjBfQ9+iLyRQLgJGzLDSCDI + iAfpkOD/RNdI5wTnJ2YbBLsx+l2JwIjsn4BnaEnzlI9k83evTLYcT+fsNk9KmJWyCJ4d3XvJS2W/KzrB + pZRIbcoHydKwwrscQuLiZMWtgZ+SPCCWmi8FflZ2Vhlj5ZO1dBELsfS1wJJ0TonYtcbf0eAt+YAB5smH + QAKQgKvOt0xuj62sExlA5mtvkr0W3B5/ZXqc1KpHKYDhT8R5KC+DbcPiN7PNq9wMPJ5VANV752T6Qdc8 + 9i6PKiIyaVG9BGwkSCSF42CI+TUJbFEv6fKkowKdbYyZ4ycQ1s058fxAu0XkNOPH+wpsIQkoMeDuswWP + S8Eiz1g1LE0/yJPyvJ6pYBBCDtGQexH5uJSQFRKjO8oVZJjiqnKElrmEdfAz8GYtlQzLonSWRkKI1da6 + FuS0iApe1S3VxCVjxt/R4EAlLW5m0qlymfNw9kaqE5FWKbUQn3Tpn7tuvf0uKR9PJRZngO1BnJTgOtYI + GQbkIFucxzUPhAHvXcy2AJ7j2V9MLKUgLfGQw2Zujy/l5KArAyClzwS/Xw6S8BMTCzKXJoZEHWP5tU0I + Nfu8TeIllSVGTiRbip/GMUP2g2AsG9JzvR3w7ialpzv8LZ43QcirXJEGvhCMnOJCyAqJyYojKGRVdy5V + OULmCyUrbg39UyqElM7IyigttNL9ZWF1nplfmy9EjT9g/rUgxPIaHn9Hg+cU8zCMmV6OCuA0YNmWAi+c + pUQbpGiPek3lSQYws/CzlPEAnueNqiZCOn98NpfZRnj0Dk8ATavTGQK9ywN4miSDGOhMTk5UO4EoiwgM + JlPGtgVqO7pJ+a8hgBOJh+xPWvRBccXJBOsusgU+VYeojMwmzBrSFxxCIfc0MgofOJ5ByqF1kQAvESCE + LwSpbXEhz06IjPYyl1BacWvgp9N4GPZtynjrcLFQqeKGx2c5tjTVQD7E7gbPIbHS2cuNtGFplPbesoJd + 4txEWHs1ixKr5fYoTgo/SzECGQaA5xvUnM2s6I3EHDyBOykKSMs0BDoVYwkZOkZVi/JaotREMIQkgF7Y + tBRO+WtSU7le6jwtB5KwHZIhGr8oJfWYqeZ5CSlaZRxdHvblqXl2lwDECaV4MHLk+BAHIzvhe141pLiq + snuQJ/rcsuNczonnrMfiB/OpxM+YQpTSCOkLuZZgGzN+iYrOkNTuBm/FN1cyJTkNM8B8lGxnQb4tKZ9k + ubnyCW6PlySQVQ0/S24b6TlkGBAkJc5DzQxM1Ccn09+R5gkpbcEFF38Vl6MzBwFRgRuIplpjdy3VLGTG + Wwc33YLKAKh6xolZ2AlFcVYZyZ74QDlIIX0hf9LD6e8ggbnJ4Zwnm5ImR0U6JQ9UDVEEjtyQnjtCJk/L + 0W5ZcdbEeOX3rRPKsrmRZdulydSpInizlsTaSmOvc2Il6nY6eMvpXynP/E00wL+XbOeysRfAEz3aeW2R + imS5BbfH+7MZZ+Bs9TNejPBlwogOnk9NDj8keirpFtcwiuRYxY77EhmQEkngiGo5KktO0bINNgynlX/t + GTmgKHBuy1ooZsopZc4DRPGJggnq1Nzh4Ye8gghpEBciO4EEH3Lk4FdgWZAbXEJwhELvBCTsdHYiEsbi + p6SGRmaOlsDrjLqWjvVIVnrVOrP1vNPBW17KymnnEx7I3lgl8FaeG5Zbaj0VLDeP9pjbs1gYZyC2mlJN + 71Jwb4jzKDEn0tMCT8iRSQmaiRvIGDYxwlr6pT4ZVillaHUg2Lpq8IbMiOyCVGWe3upPlCAU1akVXxx4 + XMhCq8iE8jsx2vArxiW49BpHKCZoK68nEAlj8VPGYVYuFL2JO3tftRRLaVyhi8Yon77xcyWw08G5Uenl + owAHJp8EMpy9UertTODdtIF/wfBFKB9ahNJxilApVQkUw5EbinFPkgGMLb1s6IZz29WDm4UBJ6zdYQi8 + Vojux0yCFOxX+U3I18x9+tUKRObf6GN17kKGW0+KC5l1OcEd+i7EmwYI2bvAntfpbGHvZq/Auw/JIB9P + TaCFHfVCyA3p4TqaFYdUYxOspYjqWPyUr/CRmaOd+GldW/pI48uKVo6/08HBTx+tr2gV0xv5ImgZfiUs + M6G18NNJG1Cr7JabZbhh1uP2kKGD2wPh9j8nh+8VABKD/Mv5QyRO3otMjNGmqYNl97gjZFEys+Kczu4g + EqSCxuKnJA9GZo52vv5z/HQCYKRy69M/afydDj6gYFviAsPAbK1so36B9ykfaDfRBnTZVT0prTMgrC3a + 462eqOdxt2dqhFtwqfOCgkQBJ0WRApeZ6sg1j/KyW8dI7TFeHbWpv6RSxApmwVmNmXLwsoTXkMMaSPn4 + 1Erw4ZKDKXScOUJeL0TJnSJC0NnGxbkVR1KCEQmtpJ5R+ClX4fjM0c6Yeo6f0lDpz5LscM6Hx9/p4Gk2 + fZGxEgMAaYzeLtnOTOBdyocYX+hnoGgptAFJbvQTpFyMwgSz3LwY7uzh0b8P6W1aeaq1DqlujoTk+jfg + iRzDEitwjZCTw6wHmc1MEpaMM8g5w/hcMQnVnzr2ZnCr7yYk460daOiDlfuElTmY9MTFJSKBMjtL6omV + 3uP0T6lDxttXneZNvoY6c71WsljphOHxdzp4mkNnYsFArs3KGFH5wooCb2i3WB4X8kQ92YSUE16TThtY + 9zPSukhyg3ODsCbK8cDR8Z9ePXhPSOyPRTjxJe0JBKaCFDxJizLljxV6ZjkkupY+Oc3JOYr62AX/vHkE + J99ignbMcI2x4OQIvQf5eFCVBFPobNqPWGqcS9IjqsjWJLykgkbpn/IdPyYyo+XV+W7OXYJynQ1H5VvQ + 6myJms7Z6eCtmfRlTHcCaTjVqF/gpfLxPNFM+XijapSP0Qa0nnJOidbsn6Ok2TPcQqp/zj6HqjjlAWTd + p4zFtvB/h6o5DQDGXxsaJIwmHtLI3pzRmevGFvWMOI+oRgMvZ8DdFJx+EClZJ24rtkNutJKjWJWIKgE0 + KlXFZScVZETcKPyUGBjvn3TaMGnldfonazU0HRh/p4N3akhVQ6ASBxKoy9KPcqhOtjMWyaXgN4FwKZ8U + MHXlU79KG2hv2kTAx6Kl3j3nvqPj/+KMk72GPTEsZjrH1m2N2+A8dZ4rHWP/bwOQVhYILaOx0Zaasz9s + oznTr6HE1eNd1ufRrFlTREjJuTipIIpVaRyJJKlUVVJP8oKgOo2IG4WfMpFkjBHf59zngaNd+Pdp/J0O + vtLCXFmMMMDL9bCdS8rn1tv/Use5R7/qm5Dmno9Sdcjp4iVKWIP2gvdMDn9DmkRMbkpvM7MtpOpkSQYd + 6WpvA3jEEI7XV36mQyhXWXqWhKKYhypnz53AWFJuWus3rOR78Vnk5g1NLS9OKkhekMs5ZPSQjrAaPyMS + SXrXUqf7ntNQp1zineRB8i52Onj+dljJpvDIa72DSqXqIm4S3q5MrqZzHr/4TKDd5PlYPxDLNvBG1fTa + JUUS5fNRVZKGWmin2pRbEJZRtuDSCztLTWiYrkR5rbms14j/5COPwU/yguIPIXkifb5c+BA4kiUJuGQk + H2Tl/boe8sY9cNmmgkI4NVNBntEzAj/lKhyZucMXXr5HW9eujN4Mv+bL8fOlvNPBmViO3pXqqMwh6tPh + 5ZkutDxbdPHs8y8l/Lz2FsmOqs022s1T3ZLnQzNOlM/dk8P3xWhpLIPLU8IcPGGlLuXmNIt+F6z0GASO + wc8wRycrrtE/eneoFMJUUCi8E3jc6nsfErPGPaa63QtaEE41Is4zelKzHsqrpqv1T/mOH0m+leugLEbo + VG4jjcPOlNbcMdvp4AAm91JW4qeMtPY9Zg/buWS8nT3/RMKPF/n8OJSXkmdt2TqUJUO7ETA1z8fb6ETl + E7LdPD3Zq6DxBJo6nFjAk3JzxizxnZ6zLn66JrPUdFsnxArw2MguENxBStOjP4xeECqIpDjkSUYPOxmr + QJWkUutaCnOzGj8lQTySPCid4E5irXS1V9K7WqzlxMr6n2s2+BjMt1IB+/yf8oXlAm/0Dyn0n7jjwchD + 3FGp+7sxB1TIETKnh+hFalpsX0RL66Iq+5bwco1biTg94JlvWWcctSIYMM94N29jNa9nyK11x046u3mi + 5QrwqIKsNCg0vlIjyAnh1Fu88RXbDSFDqoMuIlXvd/WKyxlp0+wKIvtgNX5K8m3M+u60nTpJ25EJ2q0X + fKdyKxfxTgfPvZQx75QcGAMcfYmfhx99JrXX8frheXov/PkD5+sT8MO+I5G2NuaAVFGyiZWt83FbE0r3 + DNRtLI9x6yW8sL2VYYtzy0IoYdGvtZpPr5fyAtWNRmsivw0X1xAJqSGWCSTaeEFWyC1m9HzZ0xECi2By + hsg++cnJSPyUvuzKzOuyrG2gjHQw1t5tFnXGKztX8O4Gb70gxti0uTIcwFuJn2effznix3KuLmXOz+MX + n3ZzQkVyxhzMQ5EPFXJ0PLv38Oj3VM9s/WtizVlwZrzsJ/S1mZgVJx9pYKVeY/xshJk+/ZasOLXpCY3p + XDKxx51LQ9YdcvO8bNIR2NKYMIAy4uhaqtK6YMKt0D+dPgZgGAj/dS7uYZU1mGvcAaHSMhyA9I4GL72U + 4YTA/PzhOvYSP09cvJy1d1vc+vG/1Evtw//hv1tE3DxamDeyRb/rKSd0f3fa2rLd7owJB5goWZ5LYN6W + kv8TNvqsoI3Y5PWsta0CJiM/Ih2fh4NiHsYS2S0p+Z/eQ2U7MhSLgFR9NyFaF5FR6kUNJvkrK/BTVu/o + m8P86Ot5sIHLMR5yrNGScxtOhtjR4OUqHzDJWq0ghhNJS2T62yG0R8yZg3OPfcW3vkoJb+QcPDdffHU+ + J/ZH0+f7j47+0PcXCZ1BQ7eamBjmAdPQYYMYiFrhlCt4IDW7RTS/s5K41fJqKS6UDFrrJncT0kOGLknk + +VXfwTIEglzmlHavwk9rleS+UKtllBrBlXnHYxxrVAwrrAQe6ya91DsbzfEiH5PUvIvBO/OS+LDsE9SS + 4UrvsdP6PfcYLlB137knk4Rvvf0OD+TBXNNvCaOcbGsS3pRzQEG/G2/Tf6wt39Q3xxsGhNdtquSJfFTT + iu0X0n5rYkEpfTtv+uNASlJyFvsM0kOGvkWkmXC+LSTpcMbCucwtkLpC/+SWkkz2FusFivi8czENl5GV + ZhnrpnMccNWZDsNMxpfWbH3wVuO7/MXBUyATdRjNPx+J9r68jfyOH/nY/7oy+XF9QmPRPGfnW55tTW8d + ikxlvP1a6uHkqPCdp2J7p2D6+9LBBxjj24w5Z0c22JaGjZtBZLHjtmSanSN+zZvFIUlMOPqVkpGNhEMu + j0n+5Gcr8JPazOYOxnCiJGudE0ZWB5UoQl8NlwOoL+Fm429x8AQMPezKOXPaeLQLQn1JdOTsXJmY8WAs + qnGpbIBFV1ECfNSZkjD6qLcHeWB6RA1v9HDUK0fdQMOLNrgHqWnbGGyMOWdLC73Xcdo4qVQTU8JOykgI + HlEmGWXQyjtChp6RTV0dRUF0WvRAKm0oY1Hdav66LzLIF8yayA8+2WxZd+qicnxMtTEdEleGMlNmWj75 + dQdP16bb8ezYZtuVCc+L5Xb2/FMcGG84Py/+4NXY4U3bYLnzY/twkPNGkwNVK1jOznT6z8OKCQ0+U5vP + rAGvLLp8N7jBZOfrAT+noTGa5iH+4FlSQtzUKMpKokOGIZdHFQ1WVPcC0naZWzr25vhZuUz3J2xJAnnm + juVchy1J3Pmp6jdsGyxr72bOj+e8eamctdf5gMpgPD6Y1krBEMT20LvWG1sc/3QwjkR2+00RmkIGcYXa + jQ94XSr72NEaIbpAVpQaXKA9fra0yHc4TGi1o8iptyBTh0RL2/FYBH1CPGe0os8BpaZU+5DzdhfOj2+v + m7ryhiadStcPfaqahJ3lnOX1S262CI+VQ22Mn0b/hFCYv1+8oCOW02USM+nhAt3luXBfsNYiSNjkTI/S + EAXa42eHC38bQy8VnHoLZvq8gR+Sr8CPqk0tbcciP9Zkh67W9Dn49NHxH8ecN2usk3WoSpu3eRrYciPp + lQv3OjlhY/yk+acU0uQRedg0VtepPiqkY/8x8kSq3ilbUSCSpGiTbeVAe/xsY5HvcIzOVjvWp4qaBd/7 + 1iKniTxYLNg0m/aI95MBqZZUqvNRo4zULqMFg1SncMpS01N69uPBuRl+rCg1UQilgo3yUZQsluLe5Lmk + RIHOI1tRCC5ti6Ii/z1+drj2tzH0UtlC2JIxFJyqvXUg3zxBi7S3UG16OP2XMbDjeaJpTXiIsClGGGz0 + Pn5BpzM3W9nr3miDu7SSKsTCRX4l5AE27xp1LXWMIclUkYqEXc5Gwamv1R4/21jkOxyjjR8VbJO8SAqj + k9eq+SHzIJFvD85m906mH5qkva+bfXZTCqkvndgJoF2weQrnp29lb7Di+0B1yqRSNVtM1lp8y4hfifs4 + BImdQYZIEnn6DsRqKuIUnO0ea7VAe/zscO1vY+gO/MQO8Z52beTby74BPa12IN/IPKDD6KcODn87kG+h + etnaNTlmwsa6YXV6n411X/8D518D/Gxltq5/UkJg2CbZRvZ9IA1dTl1yGpJEnkjVZGsUHJte0hfuZafg + 3tzjZxuLfIdjLJX9+EaCahJPq0T0D2ULkG9OXlt7+CehWT1zB/y8XyFCo+CUVR3bAOSAyXuGbGVdvlPw + E/RPyuXxvjyOnyArUZdWC3T4fsePUdhI2Mu5rZYOye/xs8OFv6WhM/xAXnvwx/BzQvKBgj8/DJlvVrYA + fqxVlXULOXhv4KnL7hmZeRaYg6KF58ZYauGnM6NUg7/tyabt90ircWTo3YOv+N5YS0dTK/DztLLgXPJv + 7PXPltb5robpCJ7GjU1D8DQL/jxJmGJG8Gd299WDd+sN6uSbKZ+gajLC2sjruN2iewWdfUbXs+6uT/2T + XhOi4NJTN51SYiK2iBZJLGjvg3cjT6TqIaAnUwjILOcx+Gnl0QwncZFvkiewbCXdhpWpjJuRqdydOXW6 + fOWxrQmnOSRppDzxPMdnBOgK/JywVSb2W8i85luM+MF+Y2M5MketYcjVg1+hlCWuA+3ekeyTLPNNSaXL + e5Bs7BENePZb5A820I35E8Wfg3nWjLakfyj6UMY6PtKvIE+XKlmkhFDVEY4QqqUgrNY/LCmWXUq7Hl7E + ytcm8ZHlwplrZUz2LSaWoGp+xtR4dqbSaUraDVuHcpmVPK5DMx/fV3XE0rdTUsZqkhvyVKHHypJvydyL + 59Qz0ZN3Wvgx/yeVnYIf1z+GHxXMRcIt0bU5aRtA1cbPBgt05SXXAD8jo085fpb2IZZklF0a1JHw866I + H+w30jtCCoL7PyPwo4WihPzhb12tN8esjL7FN1Abs/GwIBngtZCs7OlW7ZCANBIY409T/U9+vmq/V6pT + TVKVPzl+zj/2tetT/6xE0a5P6EPp26l/En5Ui9rXXDe1rh1odbByzfW9/lVGvrLyrHP8vAhPJ6Si9Fa2 + uCzVlZNc9wS1882vUoXpylx1TnPwhMpT6Z8Xf/DKOfBD/Ccmj15X/s+uETI8/jB+3O3p83+Cibt9/yfh + R8uur3mi6ltUBrPyzdq5BFVF0/mnkS/szmtLwKfWH63zT+NiDYCKh2o9V6mR+i9v82+fuOPzly6/cN3y + b9cnftKs+vjGVmV75F2UV7oN/k0vZrkN5YsT5MgWksmx7hta56tss/PadRbc0gBMtRxTo5VY3RF+Ssuz + RNQo/NTzS5dfZLRR8Z/p2xP/uc7xk08vj30ZrvriP9NTx39weQUPqZey5YDWqBRUXxsN/soC7SS4+FAj + M44Wces0dEgaVnzGSuNHKxJglxxGH1XQebLmM0yEDJyjPnUtifEaSpZqohbLQfwx6TNm9tvVgwPq57gQ + /Y/+uXT58qXL3/z5hBDE9ZV/sBZ+Rnr848ccz1L05x/4PrCBkNxS/kGqzdSbu/VG14JmsfY5SKLvsObl + YLACcnjoQ+EnUWQtCxDwsOjFXHEXtWPf2FcRmzd8OcuaOXMwE27H3UvfbMw5kkn+vOoqnO7Oi0B12lK/ + ei+kHVAoOxV+AI+ah9D54L5zj913/pGz5y+syH+z+I9SRVPC6M7z38av9RRFXfeSgfPH4Gdk/ltsh72N + /Lf0ZWs1lNZ88pHKdcmCYK3nrj+Lo2yAJnKvz4wRb5G/xYfPHzYgZWQOOGlqN9VSGjx13gRizDlMYyX5 + JqexnEx0+VLnRFTQhGmfPfe4xU9D/s51l3+9Lhi2GG8dzitdlX/t0dJU6xH24dtS/nX+suQrbO1xkF6u + sotKUrjF2mlJtVYMa6jP8JMJ1KIBpK82cLRS498+k0yALxsyatp62DHnaG655Zm/ZXR3aebOmeh2Vw/Y + alP8G3sufM/F+038n83rf7o6vG2r/mdd8CiLp/OqMZpk3dutqP8J9XNeJbXd+p/c1JGxkdyP/E+yizob + oOVLRKqjdVrnktWCE9vbgqWaWm2AH6nQgR17FMIq/bTcdh1zjuYmyzOfZ6KzZbX2PUI8rak/lf32+ls0 + X/7FqT+9lvjJ8bZcf2rZBhZx3lH9aQ6SXMmwFnMYyC4qF4RIMPk2vHEFs/w0EQ/D5FsZAN0sHaGPfEvz + 6XuKHD9jztGA5XNJ0yJGqdA+IiTj6EL/g0/c8RDnj+p/YBvOvTP6H4zMN91usmnTwsqyAb0oNaYFqv91 + pLlj/wPbjm7T/gctVjctIxZ0vuJlr5drGti0fAn0Ruu0VniHJZWvKk5uqQudvxl/kIi+zhd/31Nwcgpt + jTlHg3eGrSQlpKe3Rl/n7uwBgwq69fa7OFL/nUuXv63mo+q/o+ajvf13Yn5kR4fet7X/ztuhfzr674Sd + +aL+8V9Fvp26/w7mU76a0+rh81wnyMpqrYYy5Ufsk05LJpkwme7SumOJN91rs3QE2Z9912pNd2o2PpfF + OOac3PLMpddKpJAdWJIHy6cF/LjcHkolQGfPPbJp/7eYSxp7oCX/Z12P4pTnX/t80/7+b0YeeB2uuuSF + Ll/0f5uznTB7OebFp2v1f2vxtgJA6ZB0UtulnSP3Q6ojKZAWSZUrFt2uNQfBcrNcaU1pgHwDJCWT0eI8 + xpyjB2xZqnr8dPc+KC6z3g1+cIHUAuG1N+mr+JSX0IX+o77BYH//UXYpXNV/9JRg2O7lpV7aVrCoMd48 + Ib2j/2jT9Iv+o2zH/cA89h+l+cF6/UcVnWj5Hp2rR15Nvi619HPTSwETYS83/yLXZJRUK2Og01TbmHxL + 20kMEA/ckTnnD8LPyihPV405R+RBS5WVtLuepaUPl4EX8MOs/uL+L4EfTDhCQFvvf3397NnYB8VtkHLX + qv+10pb1tuaby9cBvm9aXjot7SmiM9Nq4K+sPJ2vuKdWlXpkp+UoXCmAmD5XUoIyhpIJlzdlZ5yR5Qby + xdPjpAH5pC8fgjkzJdEenY3wuXDgHC5JMpFAONIE0szzHSvkFOm0VF7Br7AHorApZPjIx/43ECIE9OIP + 6P9CC8Wh/Rfmg/svyEtOjXhSMsvGxT/b1T9rkdpjcJWeq3nSEfsvIMNT7b+wAUG8v2QHEuiqQo1dELa1 + /4+vsKHN564BQjZLrx6DHx+52YJOvw7t/3Owjf1/drAU9kNuIIGuLnDCz+D+c+ygNn7/uetfBW1M1uXK + p6nZ9veF7+XY1KirYM43fXn3Fvaf2+Cr3l+yAwmUXUiPQhQ1dsHu3//0wwP7n4aOpEYtWMX/da6CRgaL + epRYpnz8eZPy8b3s1RM8MG/wb4dHH97C/qc7WAr7IdeWQHKB8ILURR4K4cQLuWMjxS3sv+27r4XeGikB + +W232fIJrK9/Ntl/Wy+Rgf23aVu1xv7ba3/b+wt2IoGORnDWSMQaWdFIERabdszWSL5ij7TFxfn88Tn9 + LryXFTxoyCb2nrTW18qgop9lvWQ7Ai33ElnKedlqp8V1kTkmWJTstBxp/Bw+n6R0OzPbZMghB9+wRJ1H + rWOE9Xyb3hJ7ViFD2sZfRKomWyTsba9t57KR+9fvZDHsB11bAitMuMo2MvGNgBb0Ury0sI20LswXD9O7 + +ej4D2xZZF0UtVBid5Hl7bSueyuuBN4q/iBZbs2GWW6z6cUBlrwRqctHUkJisef1BSTp8rSeib7PbLN5 + PSb06v47a3/R+wt2IoEWhRB68XgvOLHYb1WVemF/Z7H4m7lt5Gi72Pv2nXcfHL5PZomMNE8xDhZ/ewuT + aMW1lmnuZK+rOq7l+eU8efAlns0Jg6h8ghxCFNUJOmTlDXfCzvVIEnl6eBrZWs9rkzYyN8lP9/jZyWLf + zaBtE85zSVUL9FP2ojHTonq1qrWXlnLhLljuiamgj4btgKy/c6h1MW8nNoVb5qACH5Xl9dgbOllH11uM + qJhYe5+SxLm5kRZ2XhCuwoPbPmKeomHK56MhZ2eO8rE955AnUnXZ2p4/Lm1kjuSP9vjZzVLfyahLJhx7 + aWW52D+nna/5tb4dw8L2Qn2OzWoWroLmlo599+Tw/drex8wVvZKjP6MthIOWaNoARBSFSKuubajea6lV + xtwrbiBnnMHSPMsOxlk3yVjtoxcE19Lt4G4khtyQnsuQDUtswwVkaw3Hfdt6D15TRXL0/wHYXYwXw5hb + FgAAAABJRU5ErkJggg== +</value> + </data> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.Designer.cs new file mode 100644 index 000000000..dc2740ae5 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.Designer.cs @@ -0,0 +1,193 @@ +namespace distribution_explorer +{ + partial class AboutDistributionExplorer + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutDistributionExplorer)); + this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + this.logoPictureBox = new System.Windows.Forms.PictureBox(); + this.labelProductName = new System.Windows.Forms.Label(); + this.labelVersion = new System.Windows.Forms.Label(); + this.labelCopyright = new System.Windows.Forms.Label(); + this.labelCompanyName = new System.Windows.Forms.Label(); + this.textBoxDescription = new System.Windows.Forms.TextBox(); + this.okButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel + // + this.tableLayoutPanel.ColumnCount = 2; + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F)); + this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0); + this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0); + this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1); + this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2); + this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3); + this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4); + this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); + this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel.Location = new System.Drawing.Point(12, 11); + this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tableLayoutPanel.Name = "tableLayoutPanel"; + this.tableLayoutPanel.RowCount = 6; + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.Size = new System.Drawing.Size(556, 326); + this.tableLayoutPanel.TabIndex = 0; + // + // logoPictureBox + // + this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image"))); + this.logoPictureBox.InitialImage = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.InitialImage"))); + this.logoPictureBox.Location = new System.Drawing.Point(4, 4); + this.logoPictureBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.logoPictureBox.Name = "logoPictureBox"; + this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6); + this.logoPictureBox.Size = new System.Drawing.Size(175, 318); + this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.logoPictureBox.TabIndex = 12; + this.logoPictureBox.TabStop = false; + // + // labelProductName + // + this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelProductName.Location = new System.Drawing.Point(191, 0); + this.labelProductName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelProductName.MaximumSize = new System.Drawing.Size(0, 21); + this.labelProductName.Name = "labelProductName"; + this.labelProductName.Size = new System.Drawing.Size(361, 21); + this.labelProductName.TabIndex = 19; + this.labelProductName.Text = "Product Name Distribution Explorer"; + this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelVersion + // + this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelVersion.Location = new System.Drawing.Point(191, 32); + this.labelVersion.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelVersion.MaximumSize = new System.Drawing.Size(0, 21); + this.labelVersion.Name = "labelVersion"; + this.labelVersion.Size = new System.Drawing.Size(361, 21); + this.labelVersion.TabIndex = 0; + this.labelVersion.Text = "Version 1.1"; + this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCopyright + // + this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelCopyright.Location = new System.Drawing.Point(191, 64); + this.labelCopyright.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 21); + this.labelCopyright.Name = "labelCopyright"; + this.labelCopyright.Size = new System.Drawing.Size(361, 21); + this.labelCopyright.TabIndex = 21; + this.labelCopyright.Text = "Copyright John Maddock and Paul A. Bristow 2007"; + this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCompanyName + // + this.labelCompanyName.AutoSize = true; + this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Bottom; + this.labelCompanyName.Location = new System.Drawing.Point(191, 111); + this.labelCompanyName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 21); + this.labelCompanyName.Name = "labelCompanyName"; + this.labelCompanyName.Size = new System.Drawing.Size(361, 17); + this.labelCompanyName.TabIndex = 22; + this.labelCompanyName.Text = "Company Name"; + this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // textBoxDescription + // + this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxDescription.Location = new System.Drawing.Point(191, 132); + this.textBoxDescription.Margin = new System.Windows.Forms.Padding(8, 4, 4, 4); + this.textBoxDescription.Multiline = true; + this.textBoxDescription.Name = "textBoxDescription"; + this.textBoxDescription.ReadOnly = true; + this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBoxDescription.Size = new System.Drawing.Size(361, 155); + this.textBoxDescription.TabIndex = 23; + this.textBoxDescription.TabStop = false; + this.textBoxDescription.Text = resources.GetString("textBoxDescription.Text"); + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.okButton.Location = new System.Drawing.Point(452, 295); + this.okButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(100, 27); + this.okButton.TabIndex = 24; + this.okButton.Text = "&OK"; + // + // AboutDistributionExplorer + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(580, 348); + this.Controls.Add(this.tableLayoutPanel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutDistributionExplorer"; + this.Padding = new System.Windows.Forms.Padding(12, 11, 12, 11); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "AboutDistributionExplorer"; + this.tableLayoutPanel.ResumeLayout(false); + this.tableLayoutPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.PictureBox logoPictureBox; + private System.Windows.Forms.Label labelProductName; + private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label labelCopyright; + private System.Windows.Forms.Label labelCompanyName; + private System.Windows.Forms.TextBox textBoxDescription; + private System.Windows.Forms.Button okButton; + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.cs new file mode 100644 index 000000000..3db49d9fb --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; + +namespace distribution_explorer +{ + partial class AboutDistributionExplorer : Form + { + public AboutDistributionExplorer() + { + InitializeComponent(); + + // Initialize the AboutBox to display the product information from the assembly information. + // Change assembly information settings for your application through either: + // - Project->Properties->Application->Assembly Information + // - AssemblyInfo.cs + this.Text = String.Format("About {0}", AssemblyTitle); + this.labelProductName.Text = AssemblyProduct; + this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion); + this.labelCopyright.Text = AssemblyCopyright; + this.labelCompanyName.Text = AssemblyCompany; + this.textBoxDescription.Text = AssemblyDescription; + } + + #region Assembly Attribute Accessors + + public string AssemblyTitle + { + get + { + // Get all Title attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + // If there is at least one Title attribute + if (attributes.Length > 0) + { + // Select the first one + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + // If it is not an empty string, return it + if (titleAttribute.Title != "") + return titleAttribute.Title; + } + // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name + return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); + } + } + + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + public string AssemblyDescription + { + get + { + // Get all Description attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + // If there aren't any Description attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Description attribute, return its value + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + public string AssemblyProduct + { + get + { + // Get all Product attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + // If there aren't any Product attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Product attribute, return its value + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + + public string AssemblyCopyright + { + get + { + // Get all Copyright attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + // If there aren't any Copyright attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Copyright attribute, return its value + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + + public string AssemblyCompany + { + get + { + // Get all Company attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + // If there aren't any Company attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Company attribute, return its value + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.resx new file mode 100644 index 000000000..8642ec382 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/AboutDistributionExplorer.resx @@ -0,0 +1,781 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="logoPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + Qk02YwAAAAAAADYAAAAoAAAAYAAAAFgAAAABABgAAAAAAAAAAAB0EgAAdBIAAAAAAAAAAAAA//////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////N/X0NvbzNvXyNvbzNvXzNvXzNvTyNvbzNvXzNvXz + NvTzNvXzNvbzNvXzNvXzNvXzNvX0Nvb0N/X0NvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvX0NvXzN/X0Nvb0NvX0NvXzNvXzNvXzNvbzNvXzNvTzNvXzNvXzNvbzNvTyNvXzNvXzNvbz + NvXyNvbzN/X0NvXzN/b0R/b0NvTzNvXzNvX0NvXyNvX0NvXzNvbzNvX0NvXzNvXzNvXzNvTyNvXzNvXz + Nvb0NvXzNvX0N/XzNvXzNvb0NvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvb0 + NvXzN/XzNvX0NvXzNvb0NvXzNvXzNvTyNvXzNvXzNvXzNvX0NvbzNvXzNvb0NvXyNvX0NvXzNvTzNfbz + NvTyNfXzNvXyNvXyNfbzNvXyNvXzNvTyNvX0NvXzNvXzNvXzNvTzNvXyNvb0NvXzNvXzNvXzNvXzNvXz + NvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXz + NvXzNvXzNvb0NvXyNvTzNvXzNvXzNvXzNvX0NvTyNvXzNvXyNfbzNvXyNvXyNvTyNfXzNvb0NvXzN/X0 + NfXzNfXzNvTzNfXyNvXzNvXzNvTzNvTzNvbzNvb0NfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNfXzNvb0 + NvbzNvTzNvTzNvXzNvXzNfXyNvTzNfXzNfXzN/X0NvXzNvbzNfXzNvbyNfTyNvTyN/XyNvXzNvTyNvX0 + NfXzNvXzNvXzNvTzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4NvXzNvXz + NvXzNvXzNvXzNvXzODg4NvXzNvXzNvb0NvXzNvXzODg4NvXzNvXzNvXzODg4Nvb0NvXzNvTzODg4NvXz + NfXzNvX0NvTyNvXzN/XyNvTyNfTyNvXzN/X0NfXzN/XzN/XzNfXzNvXzNfbzNvXzNvXzNvTzNvTyNvXy + Nvb0Nvb0NvXzNvb0N/XzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXz + ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzN/XzNvb0NvXzNvb0Nvb0NvXyNvTyNvTzNvXzNvXzNfbzNvXz + NfXzN/XzN/XzNvXyNvTzNfXzNfTzNvX0NvXzNvTzNvXyNfTzNvTzNfTzNvbzNvb0NfXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzODg4ODg4ODg4ODg4ODg4ODg4ODg4 + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNfXzNvb0NvbzNfTzNvTzNfTzNvXyNvTzNvXzNfXyNfTzNvXy + NvXzNfX0NvXzNvX0NvX0NfXzNvb0NvXzNvXzNvTyNvXyNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvb0NvXzNvXzNvXyNvTyNvXzNvXzNvb0NfXzNvX0NvX0NvXzNvXzNvXzN/TyNvXzNvXz + NvTzNvXyNfXzNvXzNfTzNvbzNvb0NfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNfXzNvb0NvbzNfTzNvXzNfXzNvXyNvTzNvXzNvXzNvbzNvXyNfbzNvX0NvXzNvXzNvb0NvX0NvXz + NvXzNvXyNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXz + NvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXy + NvXzNvXzNvX0Nvb0NvXzNvXzNvX0NvTzNvTyNfXyNfXzNvXzNvbzNvXzNvX0NvXzNvTzNvX0NfXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNfXzNvX0NvTzNvXzNvX0NvXz + NvbzNvXzNfXzN/bzNfXzNvXzNvTzNvTyNvXyNvXzNvXzNvTyNvbzNvb0NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzODg4NvXzNvXzNvXzNvXzNvXzODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvbzNvTyNvXzNvXzNvXyNvTyNvTzNvTy + NvTzNvTyNvXzNvXzNvXzNvTzNvTzNvTzNvb0NvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvb0NvTzNvTzNvTzNvXzNvXzNvXzNvX0Nvb0NfX0NvXzNvXz + NvXzNvXzNvXzNvbzNvb0NfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNfXzNvb0NvbzNvXzNvXzNvXzNvXzNvTyNfXzNvXzNvTzNfTyNvXyN/XzNvTzNvTyNvbz + Nvb0NvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzODg4NvXzNvXzNvXzNvXzODg4ODg4ODg4ODg4ODg4ODg4ODg4NvXzODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + Nvb0NvbzNvTyNvTzN/X0NvX0NvTzNvX0NvXzNfX0NvbzNvb0NvXzNvXzNvTyNvX0NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvTyNvXz + NvXzN/b0NvbzNvXzNvXyNvTzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvX0N/b0NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXz + NvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzN/b0NvX0NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXyNfTzNfbzNvX0NvXzNvXzNvbzNvb0NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4NvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvb0NvbzNvXzNvXzNvX0NvbzNvXzNvX0NvbzNvXyNvXz + NvXzNvTzNvXyNvXzNvb0NvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvX0Nvb0NvXzNvXyNvTzNvXzNvXzNvXyNvTzNfXzNvXzNvb0NfXzNvXzNvXzN/bzNvb0 + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + ODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvb0N/bzNvXzNvXzNfXzNvb0NfTzNvXzN/bzNvb0NvXzNvXzNvXzNvXyNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXyNvXz + NvXzNvXzNvb0NvTzNvXzNvbzNvXyNvXzNvXzNvXzNvb0NvXzNvb0NvXzNvb0NvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4 + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvb0NvXzNvb0NvXzNvXzNvXzNvXyNvbz + NvXzNvXzNvX0NvXzNvXzNvTyNvb0Nvb0Nvb0NvX0N/b0Nvb0NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvb0NvXzNvb0N/b0NvX0Nvb0Nvb0Nvb0NvTyNvXzNvXzN/X0NvTzNvXzNvXyNvXzNvXz + NvXzNvTyNvXzNfXzNvXzNvb0NvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0 + NvXzNvXzNvXzNvb0NvXzNfXzNvXzNvTyNvXzNvXzNvXzNvbzNvXzNvXzNvXzNvXzNvX0NvTzNvXzNfXz + NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0 + NvXzNfXzNvXzNvTzNvX0NvXzNvXzNvbzNvXzNvbzNvXzNvXzNvXzNvTyNvXzNfXzNvXzNvb0NvXzNvXz + NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + ODg4ODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvb0NvXzNfXzNvXzNvTy + NvXzNvXzNvXzNvbzNvXzNvXzNvX0NvXzNvXzNvTyNvb0Nvb0Nvb0NvX0N/b0Nvb0NvXzNvb0NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvb0N/b0NvX0Nvb0Nvb0Nvb0NvTyNvXzNvXzNvX0NvTz + NvXzNvXyNvXyNvXzNvXzNvXzNvb0NvXzNvb0NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzODg4ODg4 + ODg4ODg4ODg4ODg4ODg4NvXzNvXzODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4Nvb0NvXzNvXzNvXzNvXyNvbzNvXzNvXzNvb0NvXz + NvXzNvXzNvXyNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXyNvXzNvXzNvXzNvb0NvTzNvXzNvbzNvb0NfXzNvXzNvXzN/bzNvb0 + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvb0N/bzNvXzNvXzNfXzNvb0NfTzNvXzNfbzNvXyNvXzNvXzNvTzNvXyNvXzNvb0NvX0NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4NvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0Nvb0NvXzNvXyNvTz + NvXzNvXzNvXyNvTzNfXzNvXzNfbzNvX0NvXzNvXzNvbzNvb0NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvb0NvbzNvXzNvXzNvX0NfbzNvXz + NvX0NvbzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvX0N/b0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzN/b0NvX0NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNfTzNvXyNfTzNvbzNvb0 + NvXzNvXzNvTyNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvX0NvTyNvXzNvXzNvb0NvbzNvXzNvXyNvTzNfTyNvXyN/XzNvTzNvTyNvbz + Nvb0NvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4 + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXz + Nvb0NvbzNvTyNvTzN/XzNvXyNfTyNvX0NvXzNfX0NvXzNvXzNvXzNvXzNvXzNvbzNvb0NfXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNfXzNvb0NvbzNvXzNvXz + NvXzNvXzNvXzNfXzNvXzNvTzNfXzNvXzNvXzNvTzNvTzNvTzNvb0ODg4ODg4ODg4NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvb0NvTzNvTzNvTzNvXzNvXzNfXzNvX0 + Nvb0NfX0NvTzNvTyNvXyNvXzNvXzNvTyNvbzNvb0ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvbzNvTyNvXzNvXzNvXyNvTyNvTzNvTyNvTzNvTyNfXzNvXz + NvbzNvXzNvX0NvXzNvTzNvX0ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNfXzNvX0NvTzNvXzNvX0NvXzNvbzNvXzNfXzN/bzNfXzNvXzNvX0NvXzNvXyNvb0NvX0NvXz + NvXzNvXyODg4NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXy + NvXzNvXzNvX0Nvb0NvXzNvXzNvX0NvTzNvTyNfXyNvXzNvXzNvTzNvXyNfXzNvXzNfTzNvbzODg4NfXz + NvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4NvXzNvXzNvXzNvXzODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4NfXzNvXy + NvTzNvXzNvXzNvbzNvXyNfbzNvXzNvX0NvX0NfXzNvb0NvXzNvXzNvTyODg4NvXzNvXzNvb0NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXyNvTyNvXzNvXzNvb0NfXzNvX0NvX0NvXzNvXz + NvXzN/TyNfTzNvX0NvXzNvTzNvb0NfX0NvX0NfTzODg4Nvb0NfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNfXzNvb0NvbzNfTzNvX0NfX0Nvb0NvTzNvXzNvX0NfTzNvTyNvb0NfX0N/XzN/Xz + NfXzNvXzNfbzNvXzNvXzNvTzODg4NvXyNvb0Nvb0NvXzNvb0N/XzNvXzNvXzNvXzNvXzNvXzODg4NvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4ODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzN/XzNvb0NvXzNvb0 + Nvb0NvXyNvTyNvTzNvXzNvXzNfbzNvXzNfXzN/XzN/XzNvXyNvTzNfXzNfTyNvTyN/XyNvXzNvTyNvX0 + NfXzNvXzODg4NvTzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0ODg4NvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvTzNvXzNvXz + NfXzNvX0NvTyNvXzN/XyNvTyNfTyNvXzN/X0NfXzNvXzN/X0NfXzNfXzNvTzNfXyODg4ODg4ODg4NvTz + NvbzNvb0NfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNfXzNvb0NvbzNvTzNvTzNvXzNvXzNfXyNvTzNfXz + NfXzN/X0NvXzNvbzNfXzNvTyNvXyNvXyNfTzNvXyNvXzNvTyNvX0NvXzODg4NvXzNvTzNvXyNvb0NvXz + NvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvX0NvXzNvXzNvXzNvXzNvXzNvb0NvXyNvTzNvXzNvXzNvXzNvX0NvTyNvXzNvXyNfbzNvXyNvXyNvTy + NfXzNvb0NvTzNvXzNvX0NvXyNvX0NvXzNvbzNvX0NvXzNvXzNvXzNvTyNvXzNvXzNvb0NvXzNvX0N/Xz + NvXzNvb0NvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvb0NvXzN/XzNvX0NvXz + Nvb0NvXzNvXzNvTyNvXzNvXzNvXzNvX0NvbzNvXzNvX0NvXyNvX0NvXzNvTzNfXzNvTyNfXzN/X0NvTz + NvX0NvbzNvXzNvXzNvTyNvbzNvXzNvXzNvTzNvXzNvbzNvXzNvXzNvXzNvX0Nvb0N/XzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzN/XzNvb0NvX0NvXzNvXzNvXzNvbzNvXz + NvTzNvXzNvXzNvbzNvTyNvXzNvXzNvbzNvb0NvbzN/X0NvXzN/b0Sfb0NvXyNfTyN/XzNvXyNvbzNfXy + NvXzNvTyNvXyNvXzNvXzNvXzNvTyNvXyNvb0Nvb0NvXzNvb0Nvb0N/XzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzN/XzNvb0Nvb0NvXzNvb0Nvb0NvXyNvTyNvXzNvXzNvXzNvXyNvTy + NvXzNfXyNvbzNvXyN/XzNfTyNvXyN/b0NfXzgvn4N/TzNvXyNvb0NvXzNfXzNvXzNvXyNvTzNvbzNvX0 + NfTzNvXzNvXzNvXzN/XyNvb0N/b0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzODg4ODg4NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzN/b0Nvb0N/XyNvXzNvXzNvXzNfTzNvX0NvbzNvTzNvXyNvXzNfXzNvXz + Nvb0NvXyN/TzNvXzWff0p/r5Nvb0NfXzN/X0NvXzNvX0NvTzNvXzNfXzNvXzNvXyN/X0N/XzN/XzNvXz + NvXzN/XzNvb0Nvb0NvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXz + NvXzNvb0Nvb0N/XzNvXzNvXzN/XzN/XzN/X0NvXyNvXzNfXzNvXzNvTzNvX0NvXzN/X0NfXzNvb0PvXz + mPn4rfv6N/XzNvTyNvXzNvb0NfbzNfXyNfTzNvXyNvX0NvXzNvbzNvXzNvXzNvTzNvXzNvXzN/XyNvb0 + NvXzNvb0NvXzNvXzNvXzN/XzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzN/XzNvXzNvXzNvXzNvb0NvXzNvb0N/XyNvXz + NvXzNvTzNvXzNvXzNvbzNvXzNvX0NvXyNfTzNfXyNfbzNvb0NvXzNvTyN/Xzd/j2qvr6svv6UPf0NvXz + NfTzNvXyNvTzNvbzNvTzNvbzNvX0NvX0NvTzNvXyNvXzNvXzNvTzNvXzNvXzNvXyNvXzNvXzNvXzNvb0 + NvXzNvb0NvXzN/b0NvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXz + NvXzNvXzNvXzNvXzNvXzN/b0NvXzNvb0NvXzNvb0NvXzNvXzNvXzNvXyNvXzNvXzNvTzNvXzNvXzNvXy + NvTzNvX0NvX0NvbzNvTzNvbzNvTzNvXyNfTzNvXzUPf1qPv6r/v6uPv7mfr5QPb0Nvb0NvXzODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4 + ODg4ODg4ODg4NvXzNvb0QPb0mfr5rfv6tvz7vfz7q/v6ivr5OPXzNvb0NfXzN/TyN/bzN/XzNfTzNvTz + N/X0NvXzNvXzNvXyNvXzN/XzNvXzNvXzNvXzNvTyNvXyNvb0NvX0Nvb0NvXzNvb0NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvb0 + NvX0Nvb0NvXyNvTyNvXzNvXzNvXzN/XzNvXzNvXyNvXzNvXzN/X0NvTzNfTzN/XzN/bzN/TyNfXzNvb0 + OPXzivr5q/v6s/z7u/z7w/z8sfv6qfv6c/n3N/XzN/byNvXzNvXyNvTzNvXyN/XzNvTzN/X0NvXzNvTz + NvbzN/X0NfTzNvXzNvTyNvXzNvTyNvXzNvXzNvb0NfXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXz + Nvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNfXzNvb0NvXzNvXzNvTyNvXz + NvTyNvXzNfTzN/X0NvbzNvTzNvXzN/X0NvTzN/XzNvX0NvTzNvXyNvXzN/byN/Xzc/n3qfv6sfv6ufv6 + wfz7yPz7t/v6r/v6qPv6Xfb0N/XzNvb0NvXzNvX0NvXzNvX0N/XzNvTzN/XyNvX0NvXzNvXyNvX0NvX0 + NvXzNvXzNvXzNvTyNvTzNvXyNvb0NvXzNfXzNvXzNvXzNvb0NvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvb0NvXzNvXzNvXzNvb0NvXzNvXzNfXzNvXzNvb0NvXyNvTzNvTyNvXzNvXzNvXzNvX0NvX0NvXy + NvXzNvX0N/XyNvTzN/XzNvX0NvXzNvX0NvXzNvb0N/XzXfb2qPv6r/v6t/v6v/z7xvz7zfz8vvz7tvv6 + r/v6pfv6VPf0NvXzNvTyNvb0NvTyNvXzNvXyNfTzNvbzNvX0NvX0NvXzNvTzNvXyNvXzNvTzNvXzNvTz + NvXzNvTyNvbzNvX0Nvb0NvXzNfXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvb0NvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXz + NvXzNvXzNfXzNvXzNvb0NvX0NvbzNvTyNvXzNvTzNvXzNvTzNvXzNvXyNvTzNvXzNvX0NvX0NvbzNfTz + NvXyNvXzNvTyNvb0NvTyNvXzVPf2pfv6r/v7tvv6vvz7xfz7zPz80vz8w/v7vPv6tfv6rvv7ovv6UPb1 + NvXzNvb0Nvb0NvX0NvTzN/XzNvXzNvTzNvbzNfXzN/XzN/bzNvXzNvX0NvXzNvXzNvXzNvTzNfTzNvTy + NvbzNvX0Nvb0NvXzNvb0Nvb0NvXzNvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXz + NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvXzNvb0Nvb0NvXzNvb0NvX0 + NvbzNvTyNfTzNvTzNvXzNvXzNvXzNvX0NvXzN/bzN/XzNfXzNvbzNvTzNvXzN/XzNvTzNvX0Nvb0Nvb0 + NvXzUPb1ovv6rvv7tfv6vPv6w/v7yvz80Pz81/38yfz8wvv7u/v6tPv6rfv6ofr5Tvb0NvXzNvTyNvXz + NvTyN/TzNvXzNvX0NvbzNvXzNvXyNvX0NvTyNvTzNvX0NvXzNfX0NvXzNvTzNvXzNvXzNvTyNvbzNvXy + NvXzNvb0NvXzNvb0Nvb0NvXzNvXzNvXzNvXzNvb0NvXzNvXzNvXzNvX0Nvb0NvXzNvXzNvXzNvb0NvX0 + NvXzNvXzNvXzNvb0NvXzNvXzNvXzNvXzNvb0Nvb0NvXzNvb0NvXzNvXyNvbzNvTyNvXzNvXzNvTzNvXz + NfX0NvXzNvX0NvTzNvTyNvX0NvXyNvXzNvbzNvX0NvXzN/TzNvTyNvXzNvTyNvXzTvb0oPr5rfv6tPv6 + u/v6wvv7yfz80Pz81v392/39z/z8yPz8wvz8u/z7tPv7rfv6n/r5TPb0NvXzNvb0NvXzN/X0NfTzNvXz + NfTyNvbzNvXzNfXyNvXzNvXzNvTyNfXyNvb0NvXzNvXzNvXzNvX0NvTzNfTyNvXzNvTyNvbzNvb0Nvb0 + NvXzNvXzNvXzNfXzNvXzNvb0NvXzNvXzNvb0NvXzNvXzNvXzODg4ODg4ODg4NvXzNvb0NvXzNvXzNvb0 + NvXzNfXzNvXzNvXzNvXzNvb0Nvb0NvbzNvTyNvXzNfTyNvTzNvX0NvXzNvXzNvXzNvb0NfXyNvTyNvXz + NvXzNfXyNvXzNvbzNfTyNvXzNfTzN/X0NvXzNvb0NvXzTPb0n/r5rfv6tPv7u/z7wvz8yPz8z/z81f39 + 2/394P7+1P39z/39yf38wfz7u/z7tPv7rfv6ovv6Wff0N/XzN/TyNfbzNvTyNvTzNfXzNvX0NfTzNvbz + NvXzNvX0NvXzNvTzNvTzNvbzNvXyNvXzNfX0NvXzNvXzNvXzNvTyNvXzNvXzNvTzNvXyNfXyNvb0NvXz + Nvb0NvXzNvb0NvXzNvX0Nvb0NfXzNfXzNfXzODg4NfXzNvb0NvX0NvXzNvb0NvXzNvb0NvXzNvb0NfXy + NvXyNvTzNvXzNvXzNvTyNvXzNvXzNvXzNfX0NvXzNvXyNvbzNvTzNvTzNvXzNvX0NvXzNvbzNfTzNvX0 + NfXzNvTzNvTyNfb0N/TyN/XzWff0ovv6rfv6tPv7u/z7wfz7yf38z/391P392v393/7+5P7+2f381f39 + zvz8yPz7wfz7u/z7tPv6rvv6p/v6Zvf1NfXzNvb0Nvb0N/XzNvbyNvbzNvXzNvXyNvTzNvXyNvXyNfXz + NvXzNvXzNvTzNvbzNvb0NvX0NfXzNvXzNvXzNvTzNvXzNvTzNfXzNvXzNvTzNvTyNvbzNvXyN/bzNvXy + Nvb0Nvb0NvXzNvXzNvXzODg4NvXzNvb0Nvb0NvXyN/bzNvXyNvbzNvTyNvTzNvXzNfXzNvTzNvXzNvTz + NvXzNvXzNfXzNvX0Nvb0NvbzNvTzNvXzNvXzNfXzNvXyNvXyNvTzNvXyNvXzNvbzNvbyN/XzNvb0Nvb0 + NfXzZvf1p/v6rvv6tPv6u/z7wfz7yPz7zvz81f392f383/794/7+5/793v382f381Pz8zvz8yf38wvz8 + vPz7tfv6r/v6p/r6c/n3N/XzNvTyNfTzNvXyNfX0NvbzNfXzNvX0NvX0NfTzNfbzN/XyNfX0NvX0NvXz + NvTzNfXyNvb0NvXzNvX0NfX0NvXzNvTzNfXzNvXzNvX0NvTyNvXzNvXzNvXzNvXzNvXzNvTyNvTzNvXz + NvXzODg4NvTzNvTyNvXzNvXzNvXzNvXzNvXzNvTyNvX0NvXzNfXzNvTzNvXzNfX0NvX0NvXzNvb0NfXy + NvTzNvXzNfTzNfX0N/XyNfbzNfTzNvX0NvX0NfXzNvbzNfX0NvXyNfTzNvTyN/Xzc/n3p/r6r/v6tfv6 + vPz7wvz8yf38zvz81Pz82f393v394v395v396v794v393v382f381P39z/39yPz7w/z8vfz7t/z7r/v6 + qfv6ivn5Qvb0NvXzNvTyNfXzNvTyNfTyNvTzNvXzNvXyN/TzNvTzN/bzN/X0NfXzNvXzNvXzN/bzNvTz + NvXyNvXyNvXzNvXzNvX0NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvTzNvXzODg4NvXzNvXz + NvXzNvXzNvXzNvXzNvXzNvXzNvXzNvXzNvX0NvXzNvXzNvX0NvXyNvTzN/bzNvXzNvXzNfXzN/X0N/bz + NvTzN/TzNvXyNvXzNvTzNfTyNvTyNfXzNvTyNvXzQvb0ivn5qfv6r/v6t/z7vfz7w/z8yPz8z/391P39 + 2f393v394v395v396v7+7f7+5v394v393v382v791P38z/z8yfz8xPz8vvz7t/v6svz7rPv6oPv6W/f0 + NfXzNvb0NfTzNvTyNfX0NvTzNvXzNvXzNfXyN/XzN/b0NfXzNvX0NvXzNvXzNfXzNvXzNfbzNvTzNfXz + NvXyNvb0NfXzNvb0NvTzNvX0NfXzNvXzNvXzNvXzNvXzNvX0Nvb0ODg4NvXzNvXzNvX0NvXzNfX0NvX0 + NvTzNvb0NfXzNvb0NvXyNfXzNvTzNfbzNvXzNfXzNvXzNvXzNvX0NfXzN/b0N/XzNfXyNvXzNvXzNvTz + NfX0NvTyNfTzNvb0NfXzW/f0oPv6rPv6svz7t/v6vvz7xPz8yfz8z/z81P382v793v394v395v396v7+ + 7f7+8f/+6v7+5v394v393v792v391f380Pz8y/38xfz7v/z7uvz7s/v6rvv7p/v6ffj3PfXzNvXzN/b0 + NvXzNfTyNvXyNvTzNvXzNvXzNvX0NfXzNvb0NvbzNvXzN/X0Nvb0NvXzNfXzNvXzNvXzNvbzNvTyNvbz + NfXyNvXyNvb0Nvb0NvXyN/X0NvXzNvX0Nvb0ODg4NvXzN/X0NvXyNvb0Nvb0NvXyNfXyNvbzNvTyNvbz + NvXzNvXzNfXzNvXzNvb0N/X0NvXzNvbzNvb0NfXzNvX0NvXzNvXzNvTzNvXyNfTyNvXzN/b0NvXzPfXz + ffj3p/v6rvv7s/v6uvz7v/z7xfz7y/380Pz81f392v393v794v395v396v7+7v7+8f/+8//+7f7+6v7+ + 5/7+4/793/792/391v380f38zPz8xvz7wfv7u/v7tvv7sPv7qvr5mvn4X/f1NfXzNvTyNvTyNfXzNfXz + NvX0Nvb0Nvb0NvXzNvX0NvXzNvbzNfbzNvXzNvXyNfXyNvX0NfTzNvXzNfTyNfXzNvX0NvTzNfTzNvTz + NvbzNvTzNvbzNvb0NvTzODg4NvbzNvTzNvbzNvTzNfTzNvTzNvX0NfXzNfTyNvXzNfTzNvX0NfXyNvXy + NvXzNfbzNvbzNvXzNvX0NvXzNvb0Nvb0NvX0NfXzNfXzNvTyNvTyNfXzX/f1mvn4qvr5sPv7tvv7u/v7 + wfv7xvz7zPz80f391v382/393/794/7+5/7+6v7+7f7+8f/+8//+9f//8f/+7f7+6v795/795P7+4P79 + 2/391/380vz8zfz8yfz8w/z7vfv7uPv7svv6rfr6p/r5jvr5S/b0NfXzNvTyNfTzNfbzNfXzN/X0Nvbz + NvTzN/XzNfXzNvXyNvX0NvTzNfTzNvbzNfXzNvbzNvX0NvX0Nvb0NfXzNvXzNvXzNvXzNvX0NvXzNvX0 + NvX0ODg4NvXzNvX0NvXzNvX0NvXzNfXzNvb0NvX0NvX0NvbzNfXzNvbzNfTzNvTzNvX0NvXyNfXzN/Xz + NvTzNvbzN/X0NfXzNfbzNfTzNvTyNfXzS/b0jvr5p/r5rfr6svv6uPv7vfv7w/z8yfz8zfz80vz81/38 + 2/394P7+5P7+5/796v797f7+8f/+8//+9f//9///8/7+8f7+7v7+6/7+6P7+5f7+4f793f792P390/z8 + z/z8yvz8xfz7wPv7u/z7tfv6sfv7q/v6p/v6e/j2Q/b0NfTzNvb0NvTyNvbzNvXzNvX0NvTyNvTzNvXz + NfbzNfXyNvX0NvXyNvX0NvbzNvbzNfTzNvb0NvXzNfbzNvbzNvbzNvXzNvbzODg4ODg4ODg4NvbzNvXz + NvbzNvbzNfbzNvXzNvb0NfTzNvbzNvbzNvX0NvXyNvX0NfXyNfbzNvXzNvTzNvTyNvX0NvXzNvbzNvTy + Nvb0NfTzQ/b0e/j2p/v6q/v6sfv7tfv6u/z7wPv7xfz8yvz8z/z80/z82P393f794f7+5f7+6P7+6/7+ + 7v7+8f7+8/7+9f//9///+f//9f/+8/7+8P7+7v7+7P7+6f7+5v7+4v793v392v391v390f38zPz8yPz7 + w/z7vvz7uvz7tfz7r/v6qvv6pvr6fvj3TPb1NfXzNfb0N/byN/TzN/bzNfXzNfXyNvTyNvbzNfb0NfXy + NvXzNfXyNvX0NvX0NvXyNvX0NfTzNfXzNvbzNvb0NvbzNvb0Nvb0ODg4NvbzNvb0NvbzNfXzNfTzNvX0 + NvXyNvX0NvX0NfXyNvXzNfXyNfb0NvbzNvTyNfXyNfXzN/bzN/TzN/byNfb0NfXzTPb1fvj3pvr6qvv6 + r/v6tfz7uvz7vvz7w/z7yPz8zPz80f381v392v393v394v795v7+6f7+7P7+7v7+8P7+8/7+9f//9/// + +f//+v//9/7+9f7+9P//8f7+7/7+7f7+6v7+5v7+4/7+3/392/391/381P38z/z8y/38xvz7wfz7vfv7 + ufz7tPv7r/v6qvr6p/v6ivr5V/f1NvXzNvXzNvb0Nvb0NvXzNfXzNfXzNvX0NvTyNvb0NvTzNfbzNvb0 + NvXzNfXzNvXzNvbzNvbzNfXzNvXyNvX0NvX0NvX0NvXyNfXzNvbzNvbzNvXzNfXzNvXzNvb0NfbzNvTz + Nvb0NvTyNvX0NfXzNfbzNvXzNvb0Nvb0NvXzNvXzV/f1ivr5p/v6qvr6r/v6tPv7ufz7vfv7wfz7xvz7 + y/38z/z81P381/382/393/394/7+5v7+6v7+7f7+7/7+8f7+9P//9f7+9/7++P//+v//+///+P7++P// + 9v//9P7+8v7+8P7+7v7+6v795/395f7+4f393v792v391v390v38zv38yfz7xfz8wPv7vfz7ufz7tPv6 + sPv6rPv6qPv6mvv6cff2Tvb0NfXzNvXzNvTyN/b0NfTzNvXzNvXzNvXzNvXzNvX0N/X0NvX0Nvb0Nfb0 + Nvb0NvbzNvTzNvTzNvb0NvTzNvTzNvbzNvb0Nfb0Nvb0NvX0N/X0NvX0NvXzNvXzNvXzNvXzNfTzN/b0 + NvTyNvXzNfXzTvb0cff2mvv6qPv6rPv6sPv6tPv6ufz7vfz7wPv7xfz8yfz8zv380v381v392v393v79 + 4f395f7+5/396v797v7+8P7+8v7+9P7+9v//+P//+P7++v//+////P//+v//+f//+P//9v7+9f7+8/// + 8f7+7v7+7P7+6f7+5v394v393/393P392P381Pz80f39zf38yf38xfz8wfz8vfv7ufv6tvz7svv7rvv6 + qvr6p/v6l/r5b/f2UPb1OPTyN/XzNfX0NvTyNfTyNvTyNfb0NvXzNfXzN/XzNvXzNvXzNvXzNfXzNfXz + N/b0NfXzNfXzNvXzNvXzNvXzN/XzNfXzNvXzNfb0NvTyNfTyNvTyNfX0N/XzOPTzUPb1bfn3l/r5p/v6 + qvr6rvv6svv7tvz7ufv6vfv7wfz8xfz8yf38zf380f391Pz82P383P393/394v395v396f7+7P7+7v7+ + 8f7+8///9f7+9v7++P//+f//+v//+////P///P//+/7++v7++f//+P7+9///9v//9P//8f7+7/7+7f7+ + 6v7+6P7+5f7+4v793v392/791/381P390P38zf38yfz8xfz8wfv7vvz7u/z8t/v7tPz7sPv6rfv6q/v6 + p/v6ovr5hvj3a/f1Ufb1OvXzNfXzN/XzNvXzNfTyNvb0Nvb0NfTyNfb0N/TyN/b0N/b0N/b0N/TyNfb0 + NfTyNvb0Nvb0NfT0NvXzN/XzNfXzOvXzUfb1a/f1hvj3ovr5p/v6q/v6rfv6sPv6s/v6t/v7uvv7vvz7 + wfv7xfz8yfz8zf380P381P391/392/793v394v795f7+6P7+6v7+7f7+7/7+8f7+9P//9v//9///+P7+ + +f//+v7++/7+/P///P///f///P7+/P//+///+f7++f//9/7+9v//9P7+8v7+8P7+7v7+7P7+6v7+5v39 + 5P7+4f393v392v391/391P390f39zfz8yvz8x/z8xPz8wPv7vPv7ufv6t/z7tPv7sfv6rvv6rPv6qvv6 + p/v6pfr5l/n4ivn3dff2Zvf1Wff1Svb0S/b0S/b0Qvb0NvXzNvXzNvXzQvb0S/b0S/b0Svb1Wff1Zvf1 + dff2ivn3l/n4pfr5p/v6qvv6rPv6rvv6sfv6tPv7t/z7ufv6vPv7wPv7w/v7x/z8yvz8zfz80f391P39 + 1/392v393v394f395P7+5v396v7+7P7+7v7+8P7+8v7+9P7+9v//9/7++f//+f7++////P///P7+/P7+ + /f///f7+/f///f///P//+///+v//+P7++P/+9v7+9f7+8/7+8f7+8P//7v7+6/7+6f7+5v7+4/394f7+ + 3v392v382P391f390v39z/z8zPz8yPz8xv38w/z7wPz7vfz7uvv6uPv6tvv6s/v6svv7r/v6rvv6rPv6 + q/v6qfr5qPv6qPv6p/v6pvr6pvv6pfr5pfr6pfr5pvv6pvr6p/v6qPv6qPv6qfr6q/v6rPv6rvv6r/v6 + svv7s/v6tvv6uPv6uvv6vfz7wPz7w/z7xfz7yPz8zPz8z/380v391f392P392v383v394f7+4/395v7+ + 6f7+6/7+7v7+8P//8f7+8/7+9f7+9v7++P//+P7++v//+////P///f///f///f///v///v///f///f// + /P///P//+/7++v7++f/++f//9/7+9v//9f//8///8f7+7/7+7f7+6v796f7+5/7+4/394f393/792/39 + 2f391vz81P390Pz8zv38zP38yPz7xvz7xPz7wfz7v/z7vvz7u/v7uvz7uPz7t/z7tfv7s/v6s/v7svv7 + sfv7sPv6sPv7r/v6r/v6r/v6sPv7sPv6sfv7svv7s/v7s/v6tfv7t/z7uPz7uvz7u/z7vvz7v/z7wfz7 + xPz7xvz7yPz7zP38zv380Pz81P391v382f392/393/794f394/395/7+6f7+6v797f7+7/7+8f7+8/// + 9f//9v//9/7++f//+f//+v7++/7+/P///P///f///f///v///v///v///v///f///f///P///f///P// + +///+v//+P7++P7+9///9f//9P7+8v7+8f7+7///7f7+6/7+6f7+5v7+5P794v393/393f392/392P39 + 1v391P390f39z/38zP38yvz8yf38xvz7xfz8w/z8wvz8wPz7vvz7vvz7vPv7u/v7uvv7uvz7ufv7uvz7 + uvz7uvz7ufv7uvz7uvv7u/v7vPv7vvz7vvz7wPz7wvz8w/z8xfz8xvz7yf38yvz8zP38z/380f391P39 + 1v392P392/393f393/394v395P795v7+6f7+6/7+7f7+7///8f7+8v7+9P7+9f//9///+P7++P7++v// + +////P///f///P///f///f///v///v///v///////v///v///f7+/f///f///P///P//+/7++v7++f7+ + +P//+P//9v7+9v//9P//8v/+8f7+7///7f7+6/7+6f395/7+5f394v394f793v393P392/392P391v38 + 1P390vz80P38z/38zf38zP38yvz8yPz8yP38xvz7xfz7xPz8xPz7xPz8w/z7w/z8w/z8w/z8w/z7xPz8 + xPz7xPz8xfz7xvz7yP38yPz8yvz8zP38zf38z/380P380vz81P391v382P392/393P393v394f794v39 + 5f395/7+6f396/7+7f7+7///8f7+8v/+9P//9v//9v7++P//+P//+f7++v7++/7+/P///P///f///f// + /f7+/v///v///v///////////v7+/v///v///v///f///f///P///f///P//+///+v//+f//+f//+P// + 9v//9f7+9P//8v7+8f7+7/7+7v7+7P7+6f396P795v7+5P394v394f793v393f392/392v392P391/39 + 1f391P380vz80f38z/z8z/z8zvz8zfz8zPz8zP38zPz8zPz8zPz8zPz8zPz8zP38zPz8zfz8zvz8z/z8 + z/z80f380vz81P381f391/392P392v392/393f393v394f794v395P395v7+6P796f397P7+7v7+7/7+ + 8f7+8v7+9P//9f7+9v//+P//+f//+f//+v//+////P///f///P///f///f///v///v///v///v7+//// + /////////////////v///v///v///f7+/f///f///P///P7+/P//+///+v//+f//+f//9/7+9v//9v// + 9P7+8v7+8v//8P7+7v7+7f7+6/7+6f7+6P795v795f794/394v394P393/393v7+3P392/392v392f79 + 1/381/391v381f381f391P391P391f391Pz81f391P391P391f391f381v381/391/382f792v392/39 + 3P393v7+3/394P394v394/395f795v796P7+6f7+6/7+7f7+7v7+8P7+8v//8v7+9P7+9v//9v//9/7+ + +f//+f//+v//+////P///P7+/P///f///f///f7+/v///v///v////////////////////////////// + /////v7+/v///v///v///f///f///P7+/P///P///P//+///+v//+f//+f//+P//9v7+9f//9f//8/7+ + 8f7+8f7+7/7+7v/+7f7+6/796f396f7+5/795/7+5f7+5P7+4/794v794P393/393/393v393f393f79 + 3P392/392/393P393P393P392/392/393P393f793f393v393/393/394P394v7+4/795P7+5f7+5/7+ + 5/796f7+6f396/797f7+7v/+7/7+8f7+8f7+8/7+9f//9f//9v7++P//+f//+f//+v//+////P///P// + /P///P7+/f///f///v///v///v///v7+/////////////////////////////////////////////v// + /v///v///v///f///f///P///P///P///P//+///+v//+f//+P//+P//9///9v//9f7+9P7+8///8f7+ + 8f7+7/797v7+7v7+7P796/7+6v7+6f796P795/795v795v7+5f7+5P794/394/7+4v794/7+4v394v39 + 4v394v394v394/7+4v794/7+4/395P795f7+5v7+5v7+5/7+6P796f796v7+6/7+7P797v7+7v7+7/79 + 8f7+8f7+8///9P7+9f7+9v//9///+P//+P//+f//+v//+////P///P///P///P///f///f///v///v// + /v///v///////////////////////////////////////////////////////////////v///v///v// + /f7+/f///f///P///P///P///P//+///+v//+f//+P7++f//+P//9v7+9f7+9f7+9P7+8/7+8v7+8v/+ + 8f/+7/7+7v7+7f7+7f7+7P796/796v796v7+6v7+6f796f7+6P796P7+6P7+6P7+5/396P7+6P7+6P7+ + 6P796f7+6f796v7+6v7+6v796/797P7+7f7+7f7+7v7+7/7+8f/+8v/+8v7+8/7+9P7+9f7+9f7+9v7+ + +P//+f//+P7++f//+v//+////P///P///P///P///f///f///f7+/v///v///v////////////////// + //////////////////////// +</value> + </data> + <data name="logoPictureBox.InitialImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAARUAAABWCAIAAABuN5XDAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAALWZJREFUeF7tnfuPJNd138n8TyvSNiQIMSDBtCHEgJNAMIQAgmEESKIgCIIktBMBUeAf + iFAGlAB2nMQOaYoUl6ReJHdtSUvxqdeSS1rSkhIpSqQs8xVZj92e6Znurpp8zvnee+t23arq6p7u5VJq + orCc6am6dev0/dY553se98aTk5Mb9v/tJXBDWAashxtvlDjyhcHPdvhf+TP/r+MJ4U832FUnN4TP7Vp+ + 0VUaj1/tyvirfRJGCze78YYbOZt/4725Ez/rav/hxn9g/9rY+jz86Ub/PI6W/0kP4gOe3OAzbz7Zzndu + Itn/90stgRowxKM6OeFYZMf85GR2cnJ8cnLkx/Tk5LCuD+p6cnJyta5/zlHVP63rn3BU9Y/r+v/V9VtV + /WZVv1HVr1f1a7Udf1fVP6qqv63rv63qH9q/1Q/zI/ucE37E+X4VByMwzpuMycg+vm7EHe3WPocJ82FW + PjdNktkyZ2aeP4geLX/YLXzr/krZ//dLKYG6biOnrjuRY+CpaxYoyxTkBNjULOITVvPfV6zsiiUOZl5n + xfvq/1HlUKmqV6rqB358v6peruqXq+p7VfWSH/ygI/5qf+XgTF3ySs0INagTosASg7/Jvbgj9/W7ByAx + qzg95ikItVHkT7eEIpfAqf7b4+dU4nsnXxzAU9daUqZ2In6Szjmua1M4rnN4zV85OblS1z9zJfD3rmqk + Z16r0DCVtIoBpq7BgIDxYlV/d1G9UFUvLKrnF9Xlyo5v+3F5sbB/m1/5pHrez3yBq+xah5mPZnDy8YEl + 2gzV9AZ39zkwE+bzM58bB4pRE2bmSyiKT2cP60+dXh+bf417/Gwuu3folaXacTtHZluDHH+Lm6l2cmLI + cXtJdtqPXQOwfF+rKqwyVMSrQb0IMNV3wIDBo/r2YvHNRfU3i8WzflxaLJ5ZLJ5eVE/bv/kRPuGvnOMn + 21VcK4AxGmMKTq6g7I5gCb0EdN9w7SfTTuoInCejrtRFetLtKKI9ft6hKNh42h1qxzXPvK5ndR38HLfW + OCa1vdRxM1iXpnB8pb5eVWibBBvpme+46hBgnltUAOAZx8k3FouvLaqvzRdfmS+eWiyenC+e9H+fWMTD + f06fP8WZnG9XcS0j2DiM9hwj2/h2F7Ak8y8Bya07m5upI5/tz5k58/dXgCw6TFDUKc+Y/KItKKL18HP1 + YPrs89/Xcd/5r6Tj9bd+uvH3ub/wGkqg5AkatVPXrDAxBEYPSOck5LixxMveFY5ZU+gBg03lsKlQF7bK + HTDV1w0DhhaA8fh88eh88Ygd8y/N51+cz78wX3xhPv9r+1eHfuZz++uXwsmLR7nWRxCivh7h9Cz38jsm + IDET5gOeTR0loy6gKFh0aNFpfMBELXQoonW/i1H4AS23/N5/HTg4Yd0b78+/5hLoINmC2nE/Ibo6LDUx + BKZzKiO+pHNwb16talYqsPnuYiFtg6q5BGzmC2kY1Mhj88WXHS1fdHj81Xxxfj5/eDZ/cG7H5+fzz83m + n53PPzubf0aH/8wnn/O/PuhnPmxX2bWMwDjAjzEZmfG5CwoNvYSl91zUSDhLL/ncsOvgG5xmsJmjM00X + 8UTOLjROUamINnOHRuEHPTOMn2u+FPY3XEsCJUO9rHacXnNW2pBzciKGwOgBd3JYkebhLIJvg0PyTfdS + 0DYsZRb0E65kLszmX5jN/2o2P+cY+LzD49Oz+f2z+X3Hs3tn80/5cc9sdvdsfvfx7JOz2Sft3/nd/sk9 + 4QQ78z6/imtBF+MAKsZkZOB0we/FHdFv2HgACY2EacessCHxkb7vs2XOSRf9xJ+INwJPxzOaOeeaNldE + G7Lbo/Bz/rFLt97+SY6PfOz/lED68H/8H2t9mfuTr60ElhweOKhEsrm3E9RONNiEHHzxt6qK9Ye1Jm6A + dYkT73aacQB4NV81p2X+KBbXzAwwlMxDM9MtAsxZ8AA2jo7/ZHp82+H03x1Mf/9g+sHJ4S2Tw9/04x9e + PXiXDn7WhweHt3AOZ3I+V3GtowtcMZrghI56iHvZHc0a5O4YeMyE+TwT7TrmaShi5j5/ngJFJHaBpwsE + ndg5l4C5Q1Esa/Nyo/CTf9+lLvqjP33g2i6I/d3GS6DXZvPVE+KhzlYFg81XG9waHDF+Dg76S84+47hj + qoEc/JCn5nNMqUcWWFZzrCxggwH2gCsNMHPn9OiPDqb/4uDwt68e/OrVgzNXD24CJFcmZyaHQEU/nLky + uWlyGA7/mU/CCZMJl4ArruKHX2UcRmNMRnYscRfuxR1RcYAWjYSt+Ji7W193ssGMOkN7jZ3J/AnXwi7w + RLk5J47bPCKXQ5tUGG/LrY2fJy4+31JBIGr897k/c2MJIGdZAX9+/4Vxg3RmFTT5BLLZorcjtUN0EoNN + DMH3FlhEFqKBG2BdGnIWOCFz7DQUzjm3rD49m0nV/Mnh9F8fHP6jK5ObWfqTA/BgUOFfsOF4CECKaodf + AYxAohN06BO7qhlB105uZvzp8b/iXm4Ect9Pm8u0wLRDHV1gbjZD5lmZLmLmzN9pOmcXTBElmluJC8GW + KyKtLVtuSNhr46fUPyBq3Ne5P+tUEgA5enN94s6HRwzUCx5/6Sq2I5LNbDa87aqy1AEnCWSwEe6EjL40 + DzrHPJz54q9nZqfx+segwpn5s8Ppv5kcfkCL3tHCQs/x8K4JYDBEmfIBFfx7lWNih/3sP/BJ+ms6PwMV + 5xjYGF9Q5I7cl7v7HJgJ88GuA9UXMOqiLoLYwC+C5yCGK3OOpyOJAUW0ZMsV7lA7OjQg7bXxg7XW0j8v + vfLaiK9zf8qpJEDkIIl9hMLvB4+5ztgtiormNhuvZxg2o9cw2Dz0CR990fku0zm2Og05n4kK57aD6T+N + DowjISiZMwDAgSRgOGDCnxw59uuZKwaqcPCzwS/8SZrKL0dx+Tg2Wjgn/CmO+S7mcDy7LaojyAZHkc0W + CxPW+6I/BYoIExRzjsQI8QpLtpwrIuXO5Vlzo7TQ2vgpKYRTrYv9xeMkAIWT8LMqWjBkttUY/SGHLVEF + Cuy4txPUDsaPKGloLrhjfAwIaMi0sxBl06P/fHD4W64EzlwxbXPTVTfDrrjN5prEfjZ1xDkOEqHF9ZLh + RCpI7tDNN9+cPrG/omfi+f5DHAcsOZD8E362+3J3Nw7PMB9m5SQeRt1nmK3PmZnDLoijI2Tkiih4RLkt + hxzEbivfZz0IrY2flvLBqBi3APZnnUoCyXhD/gPR6iw3J8+kTj6PYqMK74ihFlWAzUYUEm/nW05MfwN2 + 2NitxRdnhGKMVTNu4PDoDyaHv+6mlC1l1yQOD9lgIMSR0wAmmGpRBTkGdBX/ghz9lz7xv0blA9gEswgn + Q45cKfOspJHshKjruMuvM0NxDD5nUATDIXMOgo7n+pYFfOuXIbgjqYAEkINR2ysh1Jlsuh5+ykDqOFv8 + VEtnf3Eu9n/ykf82KBBTPnXMB11OaXPw4DefsFwsMOrpzCRKk5fpNhupN8ZNkz3whJlAFm/5/Gz2wPEM + euDj8MumZAwqWsfgBM0j5Ej/SMnohGCSBSNNvybCWrS1H4YfXRj/dc0W/prGsTEdM8HYMzpB6HK+wSw9 + n5td+5vMljkzc+bPUzi1gCKC/+Dp8OjMlqtrkrt5drlDpHKT79MLIZentHr7v/Xwk1sRUkQjbPH9+j+t + BHLlM6jwHTwhn1qVCMuaJ4LHHQCWDrnMcnigCmSzfcW4acujgV777PHs7NHxnx1M/5mQowXqyAnWV7Po + o+pgfUsFiUWAgtP5AVfSWpEw4Iegf9LnESd+R2kbKTTDp1Rc0ntykwQ2TSxNkjkzc+bPU/iz8ETuES2e + djoRW87yFdwd4iUyAkJNvvbSt7kefkrybZUtftqls7++FTDoJ68bt2e5DCGmtAXwYK5YbNQTxszhoabA + 03CgCsg0I02GHAJCKwQr75ke/aerB+/2ZRpiOLaIAwkWVm3g00Sy5VRBNK7MxJJ2UvzHzwz6R/6Pf5Kf + 4KZaYyIm+sGhYtcGl0nI1GGukeAaZsvMmT9P4c/yoHtEPB0EN6QCMSLyFcTLidp2Um5JCzV0Qiwc6qh3 + WA8/+YtQ+mefObpThMNtYrDlPmenwm+5PR5NN83jGZNLZlsCz8I8acDjPJvZNqSWPTKzeChRHRjh/zuZ + /q5MKZlGhHQSctyJt+hn0C1hEbu6cNIsmHNutomIiyoixXncQov4yUy4oKwciu5oSbc4ldfweMHYUwQJ + 7EXj0OcpIzOMMP1dnoUn8ufi6Qj7kgDO8xovhwScNUkQagw5ZykNQp4iuMRo547QevhpfZerbPGdLq1f + /MFL8ACkHoWvV2NWCReLrlNWmydTBs0DeBYVOZfERp+1dEzj2eB8yYuBZLv3+Pg25dfIYFMcU+Bx/SPf + g5BOiHU6bOxDN94CQhrNkFRE6wcfUPpn4EjjBOfHbx3Plw/m84GOS4oo+kKKF/EsPBHP5dQcEJI79DWe + 3SWAHJYhFDPlVMdamyQTftqO0Br4yUMQeiPmtnirooHXJM7SVkJD3JehsFsUfU8Htzh96HYXgzMmE2N6 + xMrKOSMTTkiP0/cIXN56W0nmXa+NTrdHlTxew1P/rBJh4GabwGPheYrVLKuAEgNy2Jyhnt0zPf639kb3 + V7jbWoEMkLsv8uCKZxiEle2csiw3PydQZCGME0C4hJCGrxN+gmfVPiciJ0A33dGVUlSG5h3ZfEQhhEmK + JZfLFLB0E8/F0/kLAl7uS1YcYc9OEvcShJxW4UVDNatyfFR+15QMZYWr9lWsgZ+SfGMRYL/xb+c3re+b + 7FJW/2bKgjuW4doWgc6tN+MwdjE40oCQHM5V56+5uHLhqLyKx0FofYO0AJl+femVH8V2GdgblttWhwyD + QFU722aEgWsefB4SC4jw4FVDUhMYNYeH3M1AfxkeCLAEulluT1QvjbEUwjjBfQ9+iLyRQLgJGzLDSCDI + iAfpkOD/RNdI5wTnJ2YbBLsx+l2JwIjsn4BnaEnzlI9k83evTLYcT+fsNk9KmJWyCJ4d3XvJS2W/KzrB + pZRIbcoHydKwwrscQuLiZMWtgZ+SPCCWmi8FflZ2Vhlj5ZO1dBELsfS1wJJ0TonYtcbf0eAt+YAB5smH + QAKQgKvOt0xuj62sExlA5mtvkr0W3B5/ZXqc1KpHKYDhT8R5KC+DbcPiN7PNq9wMPJ5VANV752T6Qdc8 + 9i6PKiIyaVG9BGwkSCSF42CI+TUJbFEv6fKkowKdbYyZ4ycQ1s058fxAu0XkNOPH+wpsIQkoMeDuswWP + S8Eiz1g1LE0/yJPyvJ6pYBBCDtGQexH5uJSQFRKjO8oVZJjiqnKElrmEdfAz8GYtlQzLonSWRkKI1da6 + FuS0iApe1S3VxCVjxt/R4EAlLW5m0qlymfNw9kaqE5FWKbUQn3Tpn7tuvf0uKR9PJRZngO1BnJTgOtYI + GQbkIFucxzUPhAHvXcy2AJ7j2V9MLKUgLfGQw2Zujy/l5KArAyClzwS/Xw6S8BMTCzKXJoZEHWP5tU0I + Nfu8TeIllSVGTiRbip/GMUP2g2AsG9JzvR3w7ialpzv8LZ43QcirXJEGvhCMnOJCyAqJyYojKGRVdy5V + OULmCyUrbg39UyqElM7IyigttNL9ZWF1nplfmy9EjT9g/rUgxPIaHn9Hg+cU8zCMmV6OCuA0YNmWAi+c + pUQbpGiPek3lSQYws/CzlPEAnueNqiZCOn98NpfZRnj0Dk8ATavTGQK9ywN4miSDGOhMTk5UO4EoiwgM + JlPGtgVqO7pJ+a8hgBOJh+xPWvRBccXJBOsusgU+VYeojMwmzBrSFxxCIfc0MgofOJ5ByqF1kQAvESCE + LwSpbXEhz06IjPYyl1BacWvgp9N4GPZtynjrcLFQqeKGx2c5tjTVQD7E7gbPIbHS2cuNtGFplPbesoJd + 4txEWHs1ixKr5fYoTgo/SzECGQaA5xvUnM2s6I3EHDyBOykKSMs0BDoVYwkZOkZVi/JaotREMIQkgF7Y + tBRO+WtSU7le6jwtB5KwHZIhGr8oJfWYqeZ5CSlaZRxdHvblqXl2lwDECaV4MHLk+BAHIzvhe141pLiq + snuQJ/rcsuNczonnrMfiB/OpxM+YQpTSCOkLuZZgGzN+iYrOkNTuBm/FN1cyJTkNM8B8lGxnQb4tKZ9k + ubnyCW6PlySQVQ0/S24b6TlkGBAkJc5DzQxM1Ccn09+R5gkpbcEFF38Vl6MzBwFRgRuIplpjdy3VLGTG + Wwc33YLKAKh6xolZ2AlFcVYZyZ74QDlIIX0hf9LD6e8ggbnJ4Zwnm5ImR0U6JQ9UDVEEjtyQnjtCJk/L + 0W5ZcdbEeOX3rRPKsrmRZdulydSpInizlsTaSmOvc2Il6nY6eMvpXynP/E00wL+XbOeysRfAEz3aeW2R + imS5BbfH+7MZZ+Bs9TNejPBlwogOnk9NDj8keirpFtcwiuRYxY77EhmQEkngiGo5KktO0bINNgynlX/t + GTmgKHBuy1ooZsopZc4DRPGJggnq1Nzh4Ye8gghpEBciO4EEH3Lk4FdgWZAbXEJwhELvBCTsdHYiEsbi + p6SGRmaOlsDrjLqWjvVIVnrVOrP1vNPBW17KymnnEx7I3lgl8FaeG5Zbaj0VLDeP9pjbs1gYZyC2mlJN + 71Jwb4jzKDEn0tMCT8iRSQmaiRvIGDYxwlr6pT4ZVillaHUg2Lpq8IbMiOyCVGWe3upPlCAU1akVXxx4 + XMhCq8iE8jsx2vArxiW49BpHKCZoK68nEAlj8VPGYVYuFL2JO3tftRRLaVyhi8Yon77xcyWw08G5Uenl + owAHJp8EMpy9UertTODdtIF/wfBFKB9ahNJxilApVQkUw5EbinFPkgGMLb1s6IZz29WDm4UBJ6zdYQi8 + Vojux0yCFOxX+U3I18x9+tUKRObf6GN17kKGW0+KC5l1OcEd+i7EmwYI2bvAntfpbGHvZq/Auw/JIB9P + TaCFHfVCyA3p4TqaFYdUYxOspYjqWPyUr/CRmaOd+GldW/pI48uKVo6/08HBTx+tr2gV0xv5ImgZfiUs + M6G18NNJG1Cr7JabZbhh1uP2kKGD2wPh9j8nh+8VABKD/Mv5QyRO3otMjNGmqYNl97gjZFEys+Kczu4g + EqSCxuKnJA9GZo52vv5z/HQCYKRy69M/afydDj6gYFviAsPAbK1so36B9ykfaDfRBnTZVT0prTMgrC3a + 462eqOdxt2dqhFtwqfOCgkQBJ0WRApeZ6sg1j/KyW8dI7TFeHbWpv6RSxApmwVmNmXLwsoTXkMMaSPn4 + 1Erw4ZKDKXScOUJeL0TJnSJC0NnGxbkVR1KCEQmtpJ5R+ClX4fjM0c6Yeo6f0lDpz5LscM6Hx9/p4Gk2 + fZGxEgMAaYzeLtnOTOBdyocYX+hnoGgptAFJbvQTpFyMwgSz3LwY7uzh0b8P6W1aeaq1DqlujoTk+jfg + iRzDEitwjZCTw6wHmc1MEpaMM8g5w/hcMQnVnzr2ZnCr7yYk460daOiDlfuElTmY9MTFJSKBMjtL6omV + 3uP0T6lDxttXneZNvoY6c71WsljphOHxdzp4mkNnYsFArs3KGFH5wooCb2i3WB4X8kQ92YSUE16TThtY + 9zPSukhyg3ODsCbK8cDR8Z9ePXhPSOyPRTjxJe0JBKaCFDxJizLljxV6ZjkkupY+Oc3JOYr62AX/vHkE + J99ignbMcI2x4OQIvQf5eFCVBFPobNqPWGqcS9IjqsjWJLykgkbpn/IdPyYyo+XV+W7OXYJynQ1H5VvQ + 6myJms7Z6eCtmfRlTHcCaTjVqF/gpfLxPNFM+XijapSP0Qa0nnJOidbsn6Ok2TPcQqp/zj6HqjjlAWTd + p4zFtvB/h6o5DQDGXxsaJIwmHtLI3pzRmevGFvWMOI+oRgMvZ8DdFJx+EClZJ24rtkNutJKjWJWIKgE0 + KlXFZScVZETcKPyUGBjvn3TaMGnldfonazU0HRh/p4N3akhVQ6ASBxKoy9KPcqhOtjMWyaXgN4FwKZ8U + MHXlU79KG2hv2kTAx6Kl3j3nvqPj/+KMk72GPTEsZjrH1m2N2+A8dZ4rHWP/bwOQVhYILaOx0Zaasz9s + oznTr6HE1eNd1ufRrFlTREjJuTipIIpVaRyJJKlUVVJP8oKgOo2IG4WfMpFkjBHf59zngaNd+Pdp/J0O + vtLCXFmMMMDL9bCdS8rn1tv/Use5R7/qm5Dmno9Sdcjp4iVKWIP2gvdMDn9DmkRMbkpvM7MtpOpkSQYd + 6WpvA3jEEI7XV36mQyhXWXqWhKKYhypnz53AWFJuWus3rOR78Vnk5g1NLS9OKkhekMs5ZPSQjrAaPyMS + SXrXUqf7ntNQp1zineRB8i52Onj+dljJpvDIa72DSqXqIm4S3q5MrqZzHr/4TKDd5PlYPxDLNvBG1fTa + JUUS5fNRVZKGWmin2pRbEJZRtuDSCztLTWiYrkR5rbms14j/5COPwU/yguIPIXkifb5c+BA4kiUJuGQk + H2Tl/boe8sY9cNmmgkI4NVNBntEzAj/lKhyZucMXXr5HW9eujN4Mv+bL8fOlvNPBmViO3pXqqMwh6tPh + 5ZkutDxbdPHs8y8l/Lz2FsmOqs022s1T3ZLnQzNOlM/dk8P3xWhpLIPLU8IcPGGlLuXmNIt+F6z0GASO + wc8wRycrrtE/eneoFMJUUCi8E3jc6nsfErPGPaa63QtaEE41Is4zelKzHsqrpqv1T/mOH0m+leugLEbo + VG4jjcPOlNbcMdvp4AAm91JW4qeMtPY9Zg/buWS8nT3/RMKPF/n8OJSXkmdt2TqUJUO7ETA1z8fb6ETl + E7LdPD3Zq6DxBJo6nFjAk3JzxizxnZ6zLn66JrPUdFsnxArw2MguENxBStOjP4xeECqIpDjkSUYPOxmr + QJWkUutaCnOzGj8lQTySPCid4E5irXS1V9K7WqzlxMr6n2s2+BjMt1IB+/yf8oXlAm/0Dyn0n7jjwchD + 3FGp+7sxB1TIETKnh+hFalpsX0RL66Iq+5bwco1biTg94JlvWWcctSIYMM94N29jNa9nyK11x046u3mi + 5QrwqIKsNCg0vlIjyAnh1Fu88RXbDSFDqoMuIlXvd/WKyxlp0+wKIvtgNX5K8m3M+u60nTpJ25EJ2q0X + fKdyKxfxTgfPvZQx75QcGAMcfYmfhx99JrXX8frheXov/PkD5+sT8MO+I5G2NuaAVFGyiZWt83FbE0r3 + DNRtLI9x6yW8sL2VYYtzy0IoYdGvtZpPr5fyAtWNRmsivw0X1xAJqSGWCSTaeEFWyC1m9HzZ0xECi2By + hsg++cnJSPyUvuzKzOuyrG2gjHQw1t5tFnXGKztX8O4Gb70gxti0uTIcwFuJn2effznix3KuLmXOz+MX + n3ZzQkVyxhzMQ5EPFXJ0PLv38Oj3VM9s/WtizVlwZrzsJ/S1mZgVJx9pYKVeY/xshJk+/ZasOLXpCY3p + XDKxx51LQ9YdcvO8bNIR2NKYMIAy4uhaqtK6YMKt0D+dPgZgGAj/dS7uYZU1mGvcAaHSMhyA9I4GL72U + 4YTA/PzhOvYSP09cvJy1d1vc+vG/1Evtw//hv1tE3DxamDeyRb/rKSd0f3fa2rLd7owJB5goWZ5LYN6W + kv8TNvqsoI3Y5PWsta0CJiM/Ih2fh4NiHsYS2S0p+Z/eQ2U7MhSLgFR9NyFaF5FR6kUNJvkrK/BTVu/o + m8P86Ot5sIHLMR5yrNGScxtOhtjR4OUqHzDJWq0ghhNJS2T62yG0R8yZg3OPfcW3vkoJb+QcPDdffHU+ + J/ZH0+f7j47+0PcXCZ1BQ7eamBjmAdPQYYMYiFrhlCt4IDW7RTS/s5K41fJqKS6UDFrrJncT0kOGLknk + +VXfwTIEglzmlHavwk9rleS+UKtllBrBlXnHYxxrVAwrrAQe6ya91DsbzfEiH5PUvIvBO/OS+LDsE9SS + 4UrvsdP6PfcYLlB137knk4Rvvf0OD+TBXNNvCaOcbGsS3pRzQEG/G2/Tf6wt39Q3xxsGhNdtquSJfFTT + iu0X0n5rYkEpfTtv+uNASlJyFvsM0kOGvkWkmXC+LSTpcMbCucwtkLpC/+SWkkz2FusFivi8czENl5GV + ZhnrpnMccNWZDsNMxpfWbH3wVuO7/MXBUyATdRjNPx+J9r68jfyOH/nY/7oy+XF9QmPRPGfnW55tTW8d + ikxlvP1a6uHkqPCdp2J7p2D6+9LBBxjj24w5Z0c22JaGjZtBZLHjtmSanSN+zZvFIUlMOPqVkpGNhEMu + j0n+5Gcr8JPazOYOxnCiJGudE0ZWB5UoQl8NlwOoL+Fm429x8AQMPezKOXPaeLQLQn1JdOTsXJmY8WAs + qnGpbIBFV1ECfNSZkjD6qLcHeWB6RA1v9HDUK0fdQMOLNrgHqWnbGGyMOWdLC73Xcdo4qVQTU8JOykgI + HlEmGWXQyjtChp6RTV0dRUF0WvRAKm0oY1Hdav66LzLIF8yayA8+2WxZd+qicnxMtTEdEleGMlNmWj75 + dQdP16bb8ezYZtuVCc+L5Xb2/FMcGG84Py/+4NXY4U3bYLnzY/twkPNGkwNVK1jOznT6z8OKCQ0+U5vP + rAGvLLp8N7jBZOfrAT+noTGa5iH+4FlSQtzUKMpKokOGIZdHFQ1WVPcC0naZWzr25vhZuUz3J2xJAnnm + juVchy1J3Pmp6jdsGyxr72bOj+e8eamctdf5gMpgPD6Y1krBEMT20LvWG1sc/3QwjkR2+00RmkIGcYXa + jQ94XSr72NEaIbpAVpQaXKA9fra0yHc4TGi1o8iptyBTh0RL2/FYBH1CPGe0os8BpaZU+5DzdhfOj2+v + m7ryhiadStcPfaqahJ3lnOX1S262CI+VQ22Mn0b/hFCYv1+8oCOW02USM+nhAt3luXBfsNYiSNjkTI/S + EAXa42eHC38bQy8VnHoLZvq8gR+Sr8CPqk0tbcciP9Zkh67W9Dn49NHxH8ecN2usk3WoSpu3eRrYciPp + lQv3OjlhY/yk+acU0uQRedg0VtepPiqkY/8x8kSq3ilbUSCSpGiTbeVAe/xsY5HvcIzOVjvWp4qaBd/7 + 1iKniTxYLNg0m/aI95MBqZZUqvNRo4zULqMFg1SncMpS01N69uPBuRl+rCg1UQilgo3yUZQsluLe5Lmk + RIHOI1tRCC5ti6Ii/z1+drj2tzH0UtlC2JIxFJyqvXUg3zxBi7S3UG16OP2XMbDjeaJpTXiIsClGGGz0 + Pn5BpzM3W9nr3miDu7SSKsTCRX4l5AE27xp1LXWMIclUkYqEXc5Gwamv1R4/21jkOxyjjR8VbJO8SAqj + k9eq+SHzIJFvD85m906mH5qkva+bfXZTCqkvndgJoF2weQrnp29lb7Di+0B1yqRSNVtM1lp8y4hfifs4 + BImdQYZIEnn6DsRqKuIUnO0ea7VAe/zscO1vY+gO/MQO8Z52beTby74BPa12IN/IPKDD6KcODn87kG+h + etnaNTlmwsa6YXV6n411X/8D518D/Gxltq5/UkJg2CbZRvZ9IA1dTl1yGpJEnkjVZGsUHJte0hfuZafg + 3tzjZxuLfIdjLJX9+EaCahJPq0T0D2ULkG9OXlt7+CehWT1zB/y8XyFCo+CUVR3bAOSAyXuGbGVdvlPw + E/RPyuXxvjyOnyArUZdWC3T4fsePUdhI2Mu5rZYOye/xs8OFv6WhM/xAXnvwx/BzQvKBgj8/DJlvVrYA + fqxVlXULOXhv4KnL7hmZeRaYg6KF58ZYauGnM6NUg7/tyabt90ircWTo3YOv+N5YS0dTK/DztLLgXPJv + 7PXPltb5robpCJ7GjU1D8DQL/jxJmGJG8Gd299WDd+sN6uSbKZ+gajLC2sjruN2iewWdfUbXs+6uT/2T + XhOi4NJTN51SYiK2iBZJLGjvg3cjT6TqIaAnUwjILOcx+Gnl0QwncZFvkiewbCXdhpWpjJuRqdydOXW6 + fOWxrQmnOSRppDzxPMdnBOgK/JywVSb2W8i85luM+MF+Y2M5MketYcjVg1+hlCWuA+3ekeyTLPNNSaXL + e5Bs7BENePZb5A820I35E8Wfg3nWjLakfyj6UMY6PtKvIE+XKlmkhFDVEY4QqqUgrNY/LCmWXUq7Hl7E + ytcm8ZHlwplrZUz2LSaWoGp+xtR4dqbSaUraDVuHcpmVPK5DMx/fV3XE0rdTUsZqkhvyVKHHypJvydyL + 59Qz0ZN3Wvgx/yeVnYIf1z+GHxXMRcIt0bU5aRtA1cbPBgt05SXXAD8jo085fpb2IZZklF0a1JHw866I + H+w30jtCCoL7PyPwo4WihPzhb12tN8esjL7FN1Abs/GwIBngtZCs7OlW7ZCANBIY409T/U9+vmq/V6pT + TVKVPzl+zj/2tetT/6xE0a5P6EPp26l/En5Ui9rXXDe1rh1odbByzfW9/lVGvrLyrHP8vAhPJ6Si9Fa2 + uCzVlZNc9wS1882vUoXpylx1TnPwhMpT6Z8Xf/DKOfBD/Ccmj15X/s+uETI8/jB+3O3p83+Cibt9/yfh + R8uur3mi6ltUBrPyzdq5BFVF0/mnkS/szmtLwKfWH63zT+NiDYCKh2o9V6mR+i9v82+fuOPzly6/cN3y + b9cnftKs+vjGVmV75F2UV7oN/k0vZrkN5YsT5MgWksmx7hta56tss/PadRbc0gBMtRxTo5VY3RF+Ssuz + RNQo/NTzS5dfZLRR8Z/p2xP/uc7xk08vj30ZrvriP9NTx39weQUPqZey5YDWqBRUXxsN/soC7SS4+FAj + M44Wces0dEgaVnzGSuNHKxJglxxGH1XQebLmM0yEDJyjPnUtifEaSpZqohbLQfwx6TNm9tvVgwPq57gQ + /Y/+uXT58qXL3/z5hBDE9ZV/sBZ+Rnr848ccz1L05x/4PrCBkNxS/kGqzdSbu/VG14JmsfY5SKLvsObl + YLACcnjoQ+EnUWQtCxDwsOjFXHEXtWPf2FcRmzd8OcuaOXMwE27H3UvfbMw5kkn+vOoqnO7Oi0B12lK/ + ei+kHVAoOxV+AI+ah9D54L5zj913/pGz5y+syH+z+I9SRVPC6M7z38av9RRFXfeSgfPH4Gdk/ltsh72N + /Lf0ZWs1lNZ88pHKdcmCYK3nrj+Lo2yAJnKvz4wRb5G/xYfPHzYgZWQOOGlqN9VSGjx13gRizDlMYyX5 + JqexnEx0+VLnRFTQhGmfPfe4xU9D/s51l3+9Lhi2GG8dzitdlX/t0dJU6xH24dtS/nX+suQrbO1xkF6u + sotKUrjF2mlJtVYMa6jP8JMJ1KIBpK82cLRS498+k0yALxsyatp62DHnaG655Zm/ZXR3aebOmeh2Vw/Y + alP8G3sufM/F+038n83rf7o6vG2r/mdd8CiLp/OqMZpk3dutqP8J9XNeJbXd+p/c1JGxkdyP/E+yizob + oOVLRKqjdVrnktWCE9vbgqWaWm2AH6nQgR17FMIq/bTcdh1zjuYmyzOfZ6KzZbX2PUI8rak/lf32+ls0 + X/7FqT+9lvjJ8bZcf2rZBhZx3lH9aQ6SXMmwFnMYyC4qF4RIMPk2vHEFs/w0EQ/D5FsZAN0sHaGPfEvz + 6XuKHD9jztGA5XNJ0yJGqdA+IiTj6EL/g0/c8RDnj+p/YBvOvTP6H4zMN91usmnTwsqyAb0oNaYFqv91 + pLlj/wPbjm7T/gctVjctIxZ0vuJlr5drGti0fAn0Ruu0VniHJZWvKk5uqQudvxl/kIi+zhd/31Nwcgpt + jTlHg3eGrSQlpKe3Rl/n7uwBgwq69fa7OFL/nUuXv63mo+q/o+ajvf13Yn5kR4fet7X/ztuhfzr674Sd + +aL+8V9Fvp26/w7mU76a0+rh81wnyMpqrYYy5Ufsk05LJpkwme7SumOJN91rs3QE2Z9912pNd2o2PpfF + OOac3PLMpddKpJAdWJIHy6cF/LjcHkolQGfPPbJp/7eYSxp7oCX/Z12P4pTnX/t80/7+b0YeeB2uuuSF + Ll/0f5uznTB7OebFp2v1f2vxtgJA6ZB0UtulnSP3Q6ojKZAWSZUrFt2uNQfBcrNcaU1pgHwDJCWT0eI8 + xpyjB2xZqnr8dPc+KC6z3g1+cIHUAuG1N+mr+JSX0IX+o77BYH//UXYpXNV/9JRg2O7lpV7aVrCoMd48 + Ib2j/2jT9Iv+o2zH/cA89h+l+cF6/UcVnWj5Hp2rR15Nvi619HPTSwETYS83/yLXZJRUK2Og01TbmHxL + 20kMEA/ckTnnD8LPyihPV405R+RBS5WVtLuepaUPl4EX8MOs/uL+L4EfTDhCQFvvf3397NnYB8VtkHLX + qv+10pb1tuaby9cBvm9aXjot7SmiM9Nq4K+sPJ2vuKdWlXpkp+UoXCmAmD5XUoIyhpIJlzdlZ5yR5Qby + xdPjpAH5pC8fgjkzJdEenY3wuXDgHC5JMpFAONIE0szzHSvkFOm0VF7Br7AHorApZPjIx/43ECIE9OIP + 6P9CC8Wh/Rfmg/svyEtOjXhSMsvGxT/b1T9rkdpjcJWeq3nSEfsvIMNT7b+wAUG8v2QHEuiqQo1dELa1 + /4+vsKHN564BQjZLrx6DHx+52YJOvw7t/3Owjf1/drAU9kNuIIGuLnDCz+D+c+ygNn7/uetfBW1M1uXK + p6nZ9veF7+XY1KirYM43fXn3Fvaf2+Cr3l+yAwmUXUiPQhQ1dsHu3//0wwP7n4aOpEYtWMX/da6CRgaL + epRYpnz8eZPy8b3s1RM8MG/wb4dHH97C/qc7WAr7IdeWQHKB8ILURR4K4cQLuWMjxS3sv+27r4XeGikB + +W232fIJrK9/Ntl/Wy+Rgf23aVu1xv7ba3/b+wt2IoGORnDWSMQaWdFIERabdszWSL5ij7TFxfn88Tn9 + LryXFTxoyCb2nrTW18qgop9lvWQ7Ai33ElnKedlqp8V1kTkmWJTstBxp/Bw+n6R0OzPbZMghB9+wRJ1H + rWOE9Xyb3hJ7ViFD2sZfRKomWyTsba9t57KR+9fvZDHsB11bAitMuMo2MvGNgBb0Ury0sI20LswXD9O7 + +ej4D2xZZF0UtVBid5Hl7bSueyuuBN4q/iBZbs2GWW6z6cUBlrwRqctHUkJisef1BSTp8rSeib7PbLN5 + PSb06v47a3/R+wt2IoEWhRB68XgvOLHYb1WVemF/Z7H4m7lt5Gi72Pv2nXcfHL5PZomMNE8xDhZ/ewuT + aMW1lmnuZK+rOq7l+eU8efAlns0Jg6h8ghxCFNUJOmTlDXfCzvVIEnl6eBrZWs9rkzYyN8lP9/jZyWLf + zaBtE85zSVUL9FP2ojHTonq1qrWXlnLhLljuiamgj4btgKy/c6h1MW8nNoVb5qACH5Xl9dgbOllH11uM + qJhYe5+SxLm5kRZ2XhCuwoPbPmKeomHK56MhZ2eO8rE955AnUnXZ2p4/Lm1kjuSP9vjZzVLfyahLJhx7 + aWW52D+nna/5tb4dw8L2Qn2OzWoWroLmlo599+Tw/drex8wVvZKjP6MthIOWaNoARBSFSKuubajea6lV + xtwrbiBnnMHSPMsOxlk3yVjtoxcE19Lt4G4khtyQnsuQDUtswwVkaw3Hfdt6D15TRXL0/wHYXYwXw5hb + FgAAAABJRU5ErkJggg== +</value> + </data> + <data name="textBoxDescription.Text" xml:space="preserve"> + <value>Description: Statistical Distribution Explorer. +Allows calculation, display and save to file +of a wide variety of statistical distributions +with given parameters and values of random variate, +Probability Density, Cumulative Distribution, complement, +and quantiles and critical values. +</value> + </data> + <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAIAEBAQAAAABAAoAQAAJgAAACAgEAAAAAQA6AIAAE4BAAAoAAAAEAAAACAAAAABAAQAAAAAAMAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAH//j/j/jwAAf/+P+P+PAAB4iIiIiIgAAH93h3h3 + jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4 + iIiIgAAAAH//j/j39wAAf/+P+PdwAAB3d3d3dwAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMAB + AADAAQAAwAEAAMABAADAAQAAwAEAAMADAADABwAAwA8AACgAAAAgAAAAQAAAAAEABAAAAAAAAAIAAAAA + AAAAAAAAEAAAABAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/ + /wD/AAAA/wD/AP//AAD///8Au7u7u7u7u7u7u7u7RLREu7u7u7u7u7u7u7u7u7S7S7u7u7u7u7u7u7u7 + u7u7u7u7u7u7u7u7u7u7u7u0RERES7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u0RLu7u7u7u7u7 + u7u0u7S7u0u7u7u7u7u7u7u7RLtES7RLu7u7u7u7u7u7u7S7tLu7S7u7u7u7u7u7u7u7u7u7u7u7u7u7 + u7u7u7u0REREREREREu7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u7u7u0RLu7u7u7u7u0u7S7u7u7u0u7 + u7u7u7u7RLtES7u7u7RLu7u7u7u7u7S7tLu7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7RERERERE + RERERERLu0u7u7u7u7u7u7u7u7u7u7tLu0u7u7u7u0RLu7u7u7u7S7REu7u7u7u0u7u7u7u7tEu7S7u7 + u7u7RLu7u7u7u7tLu7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u7u7tERERERERERERERERERES7u7 + u7u7u7u7u7u7u7u7u7u7u7u7u7u7REu7u7u7u7u7u7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7 + u7u7u7u7u7u7tLu7u7u7u7u7u7u7u7u7u0S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7u7sAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +</value> + </data> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/App.config b/src/boost/libs/math/example/dot_net_example/distribution_explorer/App.config new file mode 100644 index 000000000..49cc43e1d --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/App.config @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> +</configuration>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram1.cd b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram1.cd new file mode 100644 index 000000000..b6a6fb0dc --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram1.cd @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<ClassDiagram MajorVersion="1" MinorVersion="1"> + <Font Name="Tahoma" Size="8.4" /> + <Class Name="distribution_explorer.distexSplash" Collapsed="true"> + <Position X="0.5" Y="0.5" Width="1.5" /> + <TypeIdentifier> + <FileName>DistexSplash.cs</FileName> + <HashCode>AAAAAACAACAAABQAAACAAAACAAAAAAAAAAAAAAAAAIA=</HashCode> + </TypeIdentifier> + </Class> +</ClassDiagram>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram2.cd b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram2.cd new file mode 100644 index 000000000..0519ecba6 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ClassDiagram2.cd @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.Designer.cs new file mode 100644 index 000000000..ca25d18e2 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.Designer.cs @@ -0,0 +1,1094 @@ +namespace distribution_explorer +{ + partial class DistexForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DistexForm)); + this.modeLabel = new System.Windows.Forms.Label(); + this.propertiesTab = new System.Windows.Forms.TabControl(); + this.DistributionTab = new System.Windows.Forms.TabPage(); + this.parameter3 = new System.Windows.Forms.TextBox(); + this.parameter3Label = new System.Windows.Forms.Label(); + this.distributionNameLabel = new System.Windows.Forms.Label(); + this.parameter2Label = new System.Windows.Forms.Label(); + this.parameter1Label = new System.Windows.Forms.Label(); + this.parameter2 = new System.Windows.Forms.TextBox(); + this.parameter1 = new System.Windows.Forms.TextBox(); + this.distribution = new System.Windows.Forms.ComboBox(); + this.PropertiesTabPage = new System.Windows.Forms.TabPage(); + this.toLabel2 = new System.Windows.Forms.Label(); + this.toLabel1 = new System.Windows.Forms.Label(); + this.supportUpperLabel = new System.Windows.Forms.Label(); + this.supportLowerLabel = new System.Windows.Forms.Label(); + this.supportLabel = new System.Windows.Forms.Label(); + this.rangeGreatestLabel = new System.Windows.Forms.Label(); + this.rangeLowestLabel = new System.Windows.Forms.Label(); + this.rangeLabel = new System.Windows.Forms.Label(); + this.parameter3ValueLabel = new System.Windows.Forms.Label(); + this.parameter2ValueLabel = new System.Windows.Forms.Label(); + this.parameter1ValueLabel = new System.Windows.Forms.Label(); + this.distributionValueLabel = new System.Windows.Forms.Label(); + this.parameterLabel3 = new System.Windows.Forms.Label(); + this.parameterLabel2 = new System.Windows.Forms.Label(); + this.parameterLabel1 = new System.Windows.Forms.Label(); + this.DistributionLabel = new System.Windows.Forms.Label(); + this.coefficient_of_variation = new System.Windows.Forms.Label(); + this.CVlabel = new System.Windows.Forms.Label(); + this.kurtosis_excess = new System.Windows.Forms.Label(); + this.kurtosisExcessLabel = new System.Windows.Forms.Label(); + this.kurtosis = new System.Windows.Forms.Label(); + this.kurtosisLabel = new System.Windows.Forms.Label(); + this.skewness = new System.Windows.Forms.Label(); + this.skewnessLabel = new System.Windows.Forms.Label(); + this.median = new System.Windows.Forms.Label(); + this.standard_deviation = new System.Windows.Forms.Label(); + this.stddevLabel = new System.Windows.Forms.Label(); + this.variance = new System.Windows.Forms.Label(); + this.varianceLabel = new System.Windows.Forms.Label(); + this.medianLabel = new System.Windows.Forms.Label(); + this.mode = new System.Windows.Forms.Label(); + this.mean = new System.Windows.Forms.Label(); + this.meanLabel = new System.Windows.Forms.Label(); + this.cdfTabPage = new System.Windows.Forms.TabPage(); + this.CDF_data = new System.Windows.Forms.DataGridView(); + this.RandomVariable = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.PDF = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.CDF = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.CCDF = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.QuantileTabPage = new System.Windows.Forms.TabPage(); + this.QuantileData = new System.Windows.Forms.DataGridView(); + this.RiskLevel = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.LowerCriticalValue = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.UpperCriticalValue = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.printToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.printPreviewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.undoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.redoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.cutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pasteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.customizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.saveFileDialog = new System.Windows.Forms.SaveFileDialog(); + this.propertiesTab.SuspendLayout(); + this.DistributionTab.SuspendLayout(); + this.PropertiesTabPage.SuspendLayout(); + this.cdfTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.CDF_data)).BeginInit(); + this.QuantileTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.QuantileData)).BeginInit(); + this.menuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // modeLabel + // + this.modeLabel.AutoSize = true; + this.modeLabel.Location = new System.Drawing.Point(45, 197); + this.modeLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.modeLabel.Name = "modeLabel"; + this.modeLabel.Size = new System.Drawing.Size(44, 18); + this.modeLabel.TabIndex = 0; + this.modeLabel.Text = "Mode"; + // + // propertiesTab + // + this.propertiesTab.AccessibleDescription = "Statistical distribution properties tab"; + this.propertiesTab.AccessibleName = "Properties tab"; + this.propertiesTab.Controls.Add(this.DistributionTab); + this.propertiesTab.Controls.Add(this.PropertiesTabPage); + this.propertiesTab.Controls.Add(this.cdfTabPage); + this.propertiesTab.Controls.Add(this.QuantileTabPage); + this.propertiesTab.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertiesTab.Font = new System.Drawing.Font("Tahoma", 8.400001F); + this.propertiesTab.Location = new System.Drawing.Point(0, 26); + this.propertiesTab.Margin = new System.Windows.Forms.Padding(4); + this.propertiesTab.Name = "propertiesTab"; + this.propertiesTab.SelectedIndex = 0; + this.propertiesTab.ShowToolTips = true; + this.propertiesTab.Size = new System.Drawing.Size(642, 585); + this.propertiesTab.TabIndex = 0; + this.propertiesTab.Deselecting += new System.Windows.Forms.TabControlCancelEventHandler(this.properties_tab_Deselecting); + this.propertiesTab.SelectedIndexChanged += new System.EventHandler(this.properties_tab_SelectedIndexChanged); + // + // DistributionTab + // + this.DistributionTab.AccessibleDescription = "Distribution Tab"; + this.DistributionTab.AccessibleName = "DistributionTab"; + this.DistributionTab.BackColor = System.Drawing.SystemColors.Control; + this.DistributionTab.Controls.Add(this.parameter3); + this.DistributionTab.Controls.Add(this.parameter3Label); + this.DistributionTab.Controls.Add(this.distributionNameLabel); + this.DistributionTab.Controls.Add(this.parameter2Label); + this.DistributionTab.Controls.Add(this.parameter1Label); + this.DistributionTab.Controls.Add(this.parameter2); + this.DistributionTab.Controls.Add(this.parameter1); + this.DistributionTab.Controls.Add(this.distribution); + this.DistributionTab.Location = new System.Drawing.Point(4, 26); + this.DistributionTab.Margin = new System.Windows.Forms.Padding(700, 4, 4, 4); + this.DistributionTab.Name = "DistributionTab"; + this.DistributionTab.Padding = new System.Windows.Forms.Padding(4); + this.DistributionTab.Size = new System.Drawing.Size(634, 555); + this.DistributionTab.TabIndex = 0; + this.DistributionTab.Text = "Distribution"; + this.DistributionTab.ToolTipText = "Choose the Statistical Distribution and provide parameter(s)"; + this.DistributionTab.UseVisualStyleBackColor = true; + this.DistributionTab.Click += new System.EventHandler(this.tabPage1_Click); + // + // parameter3 + // + this.parameter3.Location = new System.Drawing.Point(200, 232); + this.parameter3.Name = "parameter3"; + this.parameter3.Size = new System.Drawing.Size(341, 24); + this.parameter3.TabIndex = 6; + // + // parameter3Label + // + this.parameter3Label.AutoSize = true; + this.parameter3Label.Location = new System.Drawing.Point(31, 232); + this.parameter3Label.Name = "parameter3Label"; + this.parameter3Label.Size = new System.Drawing.Size(170, 18); + this.parameter3Label.TabIndex = 5; + this.parameter3Label.Text = "Parameter 3 (if required)"; + this.parameter3Label.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.toolTip1.SetToolTip(this.parameter3Label, "Enter value of 3nd Parameter of the chosen distribution"); + // + // distributionNameLabel + // + this.distributionNameLabel.AutoSize = true; + this.distributionNameLabel.Location = new System.Drawing.Point(31, 58); + this.distributionNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.distributionNameLabel.Name = "distributionNameLabel"; + this.distributionNameLabel.Size = new System.Drawing.Size(78, 18); + this.distributionNameLabel.TabIndex = 2; + this.distributionNameLabel.Text = "Distribution"; + this.distributionNameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // parameter2Label + // + this.parameter2Label.AutoSize = true; + this.parameter2Label.Location = new System.Drawing.Point(28, 174); + this.parameter2Label.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.parameter2Label.Name = "parameter2Label"; + this.parameter2Label.Size = new System.Drawing.Size(170, 18); + this.parameter2Label.TabIndex = 4; + this.parameter2Label.Text = "Parameter 2 (if required)"; + this.parameter2Label.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.toolTip1.SetToolTip(this.parameter2Label, "Enter value of 2nd Parameter of the chosen distribution"); + // + // parameter1Label + // + this.parameter1Label.AutoSize = true; + this.parameter1Label.ForeColor = System.Drawing.Color.Black; + this.parameter1Label.Location = new System.Drawing.Point(28, 116); + this.parameter1Label.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.parameter1Label.Name = "parameter1Label"; + this.parameter1Label.Size = new System.Drawing.Size(89, 18); + this.parameter1Label.TabIndex = 3; + this.parameter1Label.Text = "Parameter 1"; + this.parameter1Label.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // parameter2 + // + this.parameter2.Location = new System.Drawing.Point(200, 171); + this.parameter2.Margin = new System.Windows.Forms.Padding(4); + this.parameter2.Name = "parameter2"; + this.parameter2.Size = new System.Drawing.Size(341, 24); + this.parameter2.TabIndex = 2; + // + // parameter1 + // + this.parameter1.Location = new System.Drawing.Point(200, 110); + this.parameter1.Margin = new System.Windows.Forms.Padding(4); + this.parameter1.Name = "parameter1"; + this.parameter1.Size = new System.Drawing.Size(341, 24); + this.parameter1.TabIndex = 1; + // + // distribution + // + this.distribution.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.distribution.FormattingEnabled = true; + this.distribution.Location = new System.Drawing.Point(200, 51); + this.distribution.Margin = new System.Windows.Forms.Padding(4); + this.distribution.MaxDropDownItems = 20; + this.distribution.Name = "distribution"; + this.distribution.Size = new System.Drawing.Size(341, 25); + this.distribution.TabIndex = 0; + this.distribution.SelectedIndexChanged += new System.EventHandler(this.distribution_SelectedIndexChanged); + // + // PropertiesTabPage + // + this.PropertiesTabPage.AccessibleDescription = "Show properties of distribution "; + this.PropertiesTabPage.AccessibleName = "PropertiesTabPage"; + this.PropertiesTabPage.AccessibleRole = System.Windows.Forms.AccessibleRole.None; + this.PropertiesTabPage.BackColor = System.Drawing.SystemColors.Control; + this.PropertiesTabPage.Controls.Add(this.toLabel2); + this.PropertiesTabPage.Controls.Add(this.toLabel1); + this.PropertiesTabPage.Controls.Add(this.supportUpperLabel); + this.PropertiesTabPage.Controls.Add(this.supportLowerLabel); + this.PropertiesTabPage.Controls.Add(this.supportLabel); + this.PropertiesTabPage.Controls.Add(this.rangeGreatestLabel); + this.PropertiesTabPage.Controls.Add(this.rangeLowestLabel); + this.PropertiesTabPage.Controls.Add(this.rangeLabel); + this.PropertiesTabPage.Controls.Add(this.parameter3ValueLabel); + this.PropertiesTabPage.Controls.Add(this.parameter2ValueLabel); + this.PropertiesTabPage.Controls.Add(this.parameter1ValueLabel); + this.PropertiesTabPage.Controls.Add(this.distributionValueLabel); + this.PropertiesTabPage.Controls.Add(this.parameterLabel3); + this.PropertiesTabPage.Controls.Add(this.parameterLabel2); + this.PropertiesTabPage.Controls.Add(this.parameterLabel1); + this.PropertiesTabPage.Controls.Add(this.DistributionLabel); + this.PropertiesTabPage.Controls.Add(this.coefficient_of_variation); + this.PropertiesTabPage.Controls.Add(this.CVlabel); + this.PropertiesTabPage.Controls.Add(this.kurtosis_excess); + this.PropertiesTabPage.Controls.Add(this.kurtosisExcessLabel); + this.PropertiesTabPage.Controls.Add(this.kurtosis); + this.PropertiesTabPage.Controls.Add(this.kurtosisLabel); + this.PropertiesTabPage.Controls.Add(this.skewness); + this.PropertiesTabPage.Controls.Add(this.skewnessLabel); + this.PropertiesTabPage.Controls.Add(this.median); + this.PropertiesTabPage.Controls.Add(this.standard_deviation); + this.PropertiesTabPage.Controls.Add(this.stddevLabel); + this.PropertiesTabPage.Controls.Add(this.variance); + this.PropertiesTabPage.Controls.Add(this.varianceLabel); + this.PropertiesTabPage.Controls.Add(this.medianLabel); + this.PropertiesTabPage.Controls.Add(this.mode); + this.PropertiesTabPage.Controls.Add(this.modeLabel); + this.PropertiesTabPage.Controls.Add(this.mean); + this.PropertiesTabPage.Controls.Add(this.meanLabel); + this.PropertiesTabPage.ForeColor = System.Drawing.SystemColors.WindowText; + this.PropertiesTabPage.Location = new System.Drawing.Point(4, 26); + this.PropertiesTabPage.Margin = new System.Windows.Forms.Padding(4); + this.PropertiesTabPage.Name = "PropertiesTabPage"; + this.PropertiesTabPage.Padding = new System.Windows.Forms.Padding(4); + this.PropertiesTabPage.Size = new System.Drawing.Size(634, 555); + this.PropertiesTabPage.TabIndex = 1; + this.PropertiesTabPage.Text = "Properties"; + this.PropertiesTabPage.ToolTipText = "Shows properties of chosen distribution."; + this.PropertiesTabPage.UseVisualStyleBackColor = true; + this.PropertiesTabPage.Enter += new System.EventHandler(this.tabPage2_Enter); + // + // toLabel2 + // + this.toLabel2.AutoSize = true; + this.toLabel2.Location = new System.Drawing.Point(384, 483); + this.toLabel2.Name = "toLabel2"; + this.toLabel2.Size = new System.Drawing.Size(21, 18); + this.toLabel2.TabIndex = 25; + this.toLabel2.Text = "to"; + // + // toLabel1 + // + this.toLabel1.AutoSize = true; + this.toLabel1.Location = new System.Drawing.Point(384, 449); + this.toLabel1.Name = "toLabel1"; + this.toLabel1.Size = new System.Drawing.Size(21, 18); + this.toLabel1.TabIndex = 24; + this.toLabel1.Text = "to"; + // + // supportUpperLabel + // + this.supportUpperLabel.AutoSize = true; + this.supportUpperLabel.Location = new System.Drawing.Point(411, 483); + this.supportUpperLabel.Name = "supportUpperLabel"; + this.supportUpperLabel.Size = new System.Drawing.Size(131, 18); + this.supportUpperLabel.TabIndex = 23; + this.supportUpperLabel.Text = "supportUpperValue"; + this.toolTip1.SetToolTip(this.supportUpperLabel, "PDF and CDF are unity for x argument values greater than this value."); + // + // supportLowerLabel + // + this.supportLowerLabel.AutoSize = true; + this.supportLowerLabel.Location = new System.Drawing.Point(207, 483); + this.supportLowerLabel.Name = "supportLowerLabel"; + this.supportLowerLabel.Size = new System.Drawing.Size(130, 18); + this.supportLowerLabel.TabIndex = 22; + this.supportLowerLabel.Text = "supportLowerValue"; + this.toolTip1.SetToolTip(this.supportLowerLabel, "PDF and CDF are zero for values of argument X less than this value."); + // + // supportLabel + // + this.supportLabel.AutoSize = true; + this.supportLabel.Location = new System.Drawing.Point(45, 483); + this.supportLabel.Name = "supportLabel"; + this.supportLabel.Size = new System.Drawing.Size(74, 18); + this.supportLabel.TabIndex = 21; + this.supportLabel.Text = "Supported"; + this.toolTip1.SetToolTip(this.supportLabel, "Range over which pdf is >0 but not yet =1"); + // + // rangeGreatestLabel + // + this.rangeGreatestLabel.AutoSize = true; + this.rangeGreatestLabel.Location = new System.Drawing.Point(411, 449); + this.rangeGreatestLabel.Name = "rangeGreatestLabel"; + this.rangeGreatestLabel.Size = new System.Drawing.Size(136, 18); + this.rangeGreatestLabel.TabIndex = 20; + this.rangeGreatestLabel.Text = "rangeGreatestValue"; + this.toolTip1.SetToolTip(this.rangeGreatestLabel, "Greatest argument X for calculating PDF and CDF."); + // + // rangeLowestLabel + // + this.rangeLowestLabel.AllowDrop = true; + this.rangeLowestLabel.AutoSize = true; + this.rangeLowestLabel.Location = new System.Drawing.Point(207, 449); + this.rangeLowestLabel.Name = "rangeLowestLabel"; + this.rangeLowestLabel.Size = new System.Drawing.Size(125, 18); + this.rangeLowestLabel.TabIndex = 19; + this.rangeLowestLabel.Text = "rangeLowestValue"; + this.toolTip1.SetToolTip(this.rangeLowestLabel, "Lowest argument X for calculating PDF and CDF."); + // + // rangeLabel + // + this.rangeLabel.AutoSize = true; + this.rangeLabel.Location = new System.Drawing.Point(45, 449); + this.rangeLabel.Name = "rangeLabel"; + this.rangeLabel.Size = new System.Drawing.Size(49, 18); + this.rangeLabel.TabIndex = 18; + this.rangeLabel.Text = "Range"; + this.toolTip1.SetToolTip(this.rangeLabel, "Lowest and greatest possible value of x argument for PDF & CDF."); + // + // parameter3ValueLabel + // + this.parameter3ValueLabel.AutoSize = true; + this.parameter3ValueLabel.Location = new System.Drawing.Point(204, 118); + this.parameter3ValueLabel.Name = "parameter3ValueLabel"; + this.parameter3ValueLabel.Size = new System.Drawing.Size(128, 18); + this.parameter3ValueLabel.TabIndex = 17; + this.parameter3ValueLabel.Text = "parameter 3 value"; + this.toolTip1.SetToolTip(this.parameter3ValueLabel, "Show 3rd parameter provided (if any)."); + // + // parameter2ValueLabel + // + this.parameter2ValueLabel.AutoSize = true; + this.parameter2ValueLabel.Location = new System.Drawing.Point(204, 87); + this.parameter2ValueLabel.Name = "parameter2ValueLabel"; + this.parameter2ValueLabel.Size = new System.Drawing.Size(128, 18); + this.parameter2ValueLabel.TabIndex = 16; + this.parameter2ValueLabel.Text = "parameter 2 value"; + this.toolTip1.SetToolTip(this.parameter2ValueLabel, "Show 2nd parameter provided (if any)."); + // + // parameter1ValueLabel + // + this.parameter1ValueLabel.AutoSize = true; + this.parameter1ValueLabel.Location = new System.Drawing.Point(204, 54); + this.parameter1ValueLabel.Name = "parameter1ValueLabel"; + this.parameter1ValueLabel.Size = new System.Drawing.Size(128, 18); + this.parameter1ValueLabel.TabIndex = 15; + this.parameter1ValueLabel.Text = "parameter 1 value"; + this.toolTip1.SetToolTip(this.parameter1ValueLabel, "Show 1st parameter provided."); + // + // distributionValueLabel + // + this.distributionValueLabel.AutoSize = true; + this.distributionValueLabel.Location = new System.Drawing.Point(204, 24); + this.distributionValueLabel.Name = "distributionValueLabel"; + this.distributionValueLabel.Size = new System.Drawing.Size(118, 18); + this.distributionValueLabel.TabIndex = 14; + this.distributionValueLabel.Text = "distribution name"; + this.toolTip1.SetToolTip(this.distributionValueLabel, "Show name of chosen distribution"); + // + // parameterLabel3 + // + this.parameterLabel3.AutoSize = true; + this.parameterLabel3.Location = new System.Drawing.Point(45, 118); + this.parameterLabel3.Name = "parameterLabel3"; + this.parameterLabel3.Size = new System.Drawing.Size(142, 18); + this.parameterLabel3.TabIndex = 13; + this.parameterLabel3.Text = "Parameter 3 (if any)"; + // + // parameterLabel2 + // + this.parameterLabel2.AutoSize = true; + this.parameterLabel2.Location = new System.Drawing.Point(45, 87); + this.parameterLabel2.Name = "parameterLabel2"; + this.parameterLabel2.Size = new System.Drawing.Size(142, 18); + this.parameterLabel2.TabIndex = 12; + this.parameterLabel2.Text = "Parameter 2 (if any)"; + // + // parameterLabel1 + // + this.parameterLabel1.AutoSize = true; + this.parameterLabel1.Location = new System.Drawing.Point(45, 54); + this.parameterLabel1.Name = "parameterLabel1"; + this.parameterLabel1.Size = new System.Drawing.Size(89, 18); + this.parameterLabel1.TabIndex = 11; + this.parameterLabel1.Text = "Parameter 1"; + // + // DistributionLabel + // + this.DistributionLabel.AutoSize = true; + this.DistributionLabel.Location = new System.Drawing.Point(45, 24); + this.DistributionLabel.Name = "DistributionLabel"; + this.DistributionLabel.Size = new System.Drawing.Size(78, 18); + this.DistributionLabel.TabIndex = 10; + this.DistributionLabel.Text = "Distribution"; + // + // coefficient_of_variation + // + this.coefficient_of_variation.AutoSize = true; + this.coefficient_of_variation.Location = new System.Drawing.Point(204, 318); + this.coefficient_of_variation.Name = "coefficient_of_variation"; + this.coefficient_of_variation.Size = new System.Drawing.Size(65, 18); + this.coefficient_of_variation.TabIndex = 9; + this.coefficient_of_variation.Text = "CV value"; + // + // CVlabel + // + this.CVlabel.AutoSize = true; + this.CVlabel.Location = new System.Drawing.Point(45, 318); + this.CVlabel.Name = "CVlabel"; + this.CVlabel.Size = new System.Drawing.Size(152, 18); + this.CVlabel.TabIndex = 8; + this.CVlabel.Text = "Coefficient of variation"; + this.toolTip1.SetToolTip(this.CVlabel, "or relative standard deviation that is standard deviation/mean"); + // + // kurtosis_excess + // + this.kurtosis_excess.AutoSize = true; + this.kurtosis_excess.Location = new System.Drawing.Point(204, 414); + this.kurtosis_excess.Name = "kurtosis_excess"; + this.kurtosis_excess.Size = new System.Drawing.Size(146, 18); + this.kurtosis_excess.TabIndex = 7; + this.kurtosis_excess.Text = "kurtosis excess value"; + // + // kurtosisExcessLabel + // + this.kurtosisExcessLabel.AutoSize = true; + this.kurtosisExcessLabel.Location = new System.Drawing.Point(45, 414); + this.kurtosisExcessLabel.Name = "kurtosisExcessLabel"; + this.kurtosisExcessLabel.Size = new System.Drawing.Size(109, 18); + this.kurtosisExcessLabel.TabIndex = 6; + this.kurtosisExcessLabel.Text = "Kurtosis excess"; + // + // kurtosis + // + this.kurtosis.AutoSize = true; + this.kurtosis.Location = new System.Drawing.Point(204, 383); + this.kurtosis.Name = "kurtosis"; + this.kurtosis.Size = new System.Drawing.Size(96, 18); + this.kurtosis.TabIndex = 5; + this.kurtosis.Text = "kurtosis value"; + // + // kurtosisLabel + // + this.kurtosisLabel.AutoSize = true; + this.kurtosisLabel.Location = new System.Drawing.Point(45, 383); + this.kurtosisLabel.Name = "kurtosisLabel"; + this.kurtosisLabel.Size = new System.Drawing.Size(59, 18); + this.kurtosisLabel.TabIndex = 4; + this.kurtosisLabel.Text = "Kurtosis"; + // + // skewness + // + this.skewness.AutoSize = true; + this.skewness.Location = new System.Drawing.Point(204, 351); + this.skewness.Name = "skewness"; + this.skewness.Size = new System.Drawing.Size(109, 18); + this.skewness.TabIndex = 3; + this.skewness.Text = "skewness value"; + // + // skewnessLabel + // + this.skewnessLabel.AutoSize = true; + this.skewnessLabel.Location = new System.Drawing.Point(45, 351); + this.skewnessLabel.Name = "skewnessLabel"; + this.skewnessLabel.Size = new System.Drawing.Size(71, 18); + this.skewnessLabel.TabIndex = 0; + this.skewnessLabel.Text = "Skewness"; + // + // median + // + this.median.AutoSize = true; + this.median.Location = new System.Drawing.Point(204, 228); + this.median.Name = "median"; + this.median.Size = new System.Drawing.Size(94, 18); + this.median.TabIndex = 1; + this.median.Text = "median value"; + // + // standard_deviation + // + this.standard_deviation.AutoSize = true; + this.standard_deviation.Location = new System.Drawing.Point(204, 286); + this.standard_deviation.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.standard_deviation.Name = "standard_deviation"; + this.standard_deviation.Size = new System.Drawing.Size(94, 18); + this.standard_deviation.TabIndex = 0; + this.standard_deviation.Text = "StdDev value"; + // + // stddevLabel + // + this.stddevLabel.AutoSize = true; + this.stddevLabel.Location = new System.Drawing.Point(45, 286); + this.stddevLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.stddevLabel.Name = "stddevLabel"; + this.stddevLabel.Size = new System.Drawing.Size(130, 18); + this.stddevLabel.TabIndex = 0; + this.stddevLabel.Text = "Standard Deviation"; + this.toolTip1.SetToolTip(this.stddevLabel, "sqrt("); + // + // variance + // + this.variance.AutoSize = true; + this.variance.Location = new System.Drawing.Point(204, 257); + this.variance.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.variance.Name = "variance"; + this.variance.Size = new System.Drawing.Size(101, 18); + this.variance.TabIndex = 0; + this.variance.Text = "variance value"; + // + // varianceLabel + // + this.varianceLabel.AutoSize = true; + this.varianceLabel.Location = new System.Drawing.Point(45, 257); + this.varianceLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.varianceLabel.Name = "varianceLabel"; + this.varianceLabel.Size = new System.Drawing.Size(63, 18); + this.varianceLabel.TabIndex = 0; + this.varianceLabel.Text = "Variance"; + this.toolTip1.SetToolTip(this.varianceLabel, "standard deviation squared"); + // + // medianLabel + // + this.medianLabel.AutoSize = true; + this.medianLabel.Location = new System.Drawing.Point(45, 228); + this.medianLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.medianLabel.Name = "medianLabel"; + this.medianLabel.Size = new System.Drawing.Size(54, 18); + this.medianLabel.TabIndex = 0; + this.medianLabel.Text = "Median"; + this.toolTip1.SetToolTip(this.medianLabel, "media is quantile(0.5)"); + // + // mode + // + this.mode.AutoSize = true; + this.mode.Location = new System.Drawing.Point(204, 197); + this.mode.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.mode.Name = "mode"; + this.mode.Size = new System.Drawing.Size(84, 18); + this.mode.TabIndex = 0; + this.mode.Text = "mode value"; + // + // mean + // + this.mean.AutoSize = true; + this.mean.Location = new System.Drawing.Point(204, 169); + this.mean.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.mean.Name = "mean"; + this.mean.Size = new System.Drawing.Size(84, 18); + this.mean.TabIndex = 0; + this.mean.Text = "mean value"; + // + // meanLabel + // + this.meanLabel.AutoSize = true; + this.meanLabel.Location = new System.Drawing.Point(45, 169); + this.meanLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.meanLabel.Name = "meanLabel"; + this.meanLabel.Size = new System.Drawing.Size(44, 18); + this.meanLabel.TabIndex = 0; + this.meanLabel.Text = "Mean"; + // + // cdfTabPage + // + this.cdfTabPage.Controls.Add(this.CDF_data); + this.cdfTabPage.Location = new System.Drawing.Point(4, 26); + this.cdfTabPage.Margin = new System.Windows.Forms.Padding(4); + this.cdfTabPage.Name = "cdfTabPage"; + this.cdfTabPage.Padding = new System.Windows.Forms.Padding(4); + this.cdfTabPage.Size = new System.Drawing.Size(634, 555); + this.cdfTabPage.TabIndex = 2; + this.cdfTabPage.Text = "PDF and CDF"; + this.cdfTabPage.ToolTipText = "Probability Density and Cumulative Distribution Function (and complement) for ran" + + "dom variate x"; + this.cdfTabPage.UseVisualStyleBackColor = true; + // + // CDF_data + // + this.CDF_data.AccessibleDescription = "PDF, CDF & complement Data Page"; + this.CDF_data.AccessibleName = "CDF Tab"; + this.CDF_data.AccessibleRole = System.Windows.Forms.AccessibleRole.PageTab; + this.CDF_data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.CDF_data.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.RandomVariable, + this.PDF, + this.CDF, + this.CCDF}); + this.CDF_data.Dock = System.Windows.Forms.DockStyle.Fill; + this.CDF_data.Location = new System.Drawing.Point(4, 4); + this.CDF_data.Margin = new System.Windows.Forms.Padding(4); + this.CDF_data.Name = "CDF_data"; + this.CDF_data.RowTemplate.Height = 24; + this.CDF_data.Size = new System.Drawing.Size(626, 547); + this.CDF_data.TabIndex = 0; + this.CDF_data.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellEndEdit); + this.CDF_data.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.CDF_data_CellContentClick); + // + // RandomVariable + // + this.RandomVariable.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.RandomVariable.HeaderText = "Random Variable"; + this.RandomVariable.Name = "RandomVariable"; + // + // PDF + // + this.PDF.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.PDF.HeaderText = "PDF"; + this.PDF.Name = "PDF"; + this.PDF.ReadOnly = true; + // + // CDF + // + this.CDF.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.CDF.HeaderText = "CDF"; + this.CDF.Name = "CDF"; + this.CDF.ReadOnly = true; + // + // CCDF + // + this.CCDF.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.CCDF.HeaderText = "1-CDF"; + this.CCDF.Name = "CCDF"; + this.CCDF.ReadOnly = true; + // + // QuantileTabPage + // + this.QuantileTabPage.Controls.Add(this.QuantileData); + this.QuantileTabPage.Location = new System.Drawing.Point(4, 26); + this.QuantileTabPage.Margin = new System.Windows.Forms.Padding(4); + this.QuantileTabPage.Name = "QuantileTabPage"; + this.QuantileTabPage.Padding = new System.Windows.Forms.Padding(4); + this.QuantileTabPage.Size = new System.Drawing.Size(634, 555); + this.QuantileTabPage.TabIndex = 3; + this.QuantileTabPage.Text = "Critical Values"; + this.QuantileTabPage.ToolTipText = "Critical values (quantiles or percentiles of probability 1 - alpha)"; + this.QuantileTabPage.UseVisualStyleBackColor = true; + this.QuantileTabPage.Enter += new System.EventHandler(this.QuantileTab_Enter); + // + // QuantileData + // + this.QuantileData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.QuantileData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.RiskLevel, + this.LowerCriticalValue, + this.UpperCriticalValue}); + this.QuantileData.Dock = System.Windows.Forms.DockStyle.Fill; + this.QuantileData.Location = new System.Drawing.Point(4, 4); + this.QuantileData.Margin = new System.Windows.Forms.Padding(4); + this.QuantileData.Name = "QuantileData"; + this.QuantileData.RowTemplate.Height = 24; + this.QuantileData.Size = new System.Drawing.Size(626, 547); + this.QuantileData.TabIndex = 0; + this.QuantileData.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.QuantileData_CellEndEdit); + // + // RiskLevel + // + this.RiskLevel.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.RiskLevel.HeaderText = "Risk Level (alpha)"; + this.RiskLevel.Name = "RiskLevel"; + // + // LowerCriticalValue + // + this.LowerCriticalValue.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.LowerCriticalValue.HeaderText = "Lower Critical Value"; + this.LowerCriticalValue.Name = "LowerCriticalValue"; + this.LowerCriticalValue.ReadOnly = true; + // + // UpperCriticalValue + // + this.UpperCriticalValue.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.UpperCriticalValue.HeaderText = "Upper Critical Value"; + this.UpperCriticalValue.Name = "UpperCriticalValue"; + this.UpperCriticalValue.ReadOnly = true; + // + // menuStrip1 + // + this.menuStrip1.BackColor = System.Drawing.SystemColors.Control; + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.editToolStripMenuItem, + this.helpToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(642, 26); + this.menuStrip1.TabIndex = 1; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.newToolStripMenuItem, + this.openToolStripMenuItem, + this.toolStripSeparator, + this.saveToolStripMenuItem, + this.toolStripSeparator1, + this.printToolStripMenuItem, + this.printPreviewToolStripMenuItem, + this.toolStripSeparator2, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(40, 22); + this.fileToolStripMenuItem.Text = "&File"; + // + // newToolStripMenuItem + // + this.newToolStripMenuItem.Enabled = false; + this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image"))); + this.newToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.newToolStripMenuItem.Name = "newToolStripMenuItem"; + this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.newToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.newToolStripMenuItem.Text = "&New"; + this.newToolStripMenuItem.ToolTipText = "New is not yet implemented. Enter data into dialog boxes."; + this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); + // + // openToolStripMenuItem + // + this.openToolStripMenuItem.Enabled = false; + this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image"))); + this.openToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.openToolStripMenuItem.Name = "openToolStripMenuItem"; + this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.openToolStripMenuItem.Text = "&Open"; + this.openToolStripMenuItem.ToolTipText = "Open is not yet implemented. Enter data into dialog boxes."; + this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // toolStripSeparator + // + this.toolStripSeparator.Name = "toolStripSeparator"; + this.toolStripSeparator.Size = new System.Drawing.Size(174, 6); + // + // saveToolStripMenuItem + // + this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image"))); + this.saveToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; + this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.saveToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.saveToolStripMenuItem.Text = "&Save"; + this.saveToolStripMenuItem.ToolTipText = "Save all values, input and output, to a file."; + this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(174, 6); + // + // printToolStripMenuItem + // + this.printToolStripMenuItem.Enabled = false; + this.printToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("printToolStripMenuItem.Image"))); + this.printToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.printToolStripMenuItem.Name = "printToolStripMenuItem"; + this.printToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.printToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.printToolStripMenuItem.Text = "&Print"; + this.printToolStripMenuItem.ToolTipText = "Printing not yet available. Output to a file and print that instead."; + this.printToolStripMenuItem.Click += new System.EventHandler(this.printToolStripMenuItem_Click); + // + // printPreviewToolStripMenuItem + // + this.printPreviewToolStripMenuItem.Enabled = false; + this.printPreviewToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("printPreviewToolStripMenuItem.Image"))); + this.printPreviewToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.printPreviewToolStripMenuItem.Name = "printPreviewToolStripMenuItem"; + this.printPreviewToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.printPreviewToolStripMenuItem.Text = "Print Pre&view"; + this.printPreviewToolStripMenuItem.ToolTipText = "Printing not yet available. Output to a file and print that instead."; + this.printPreviewToolStripMenuItem.Visible = false; + this.printPreviewToolStripMenuItem.Click += new System.EventHandler(this.printPreviewToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(174, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.AutoToolTip = true; + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(177, 22); + this.exitToolStripMenuItem.Text = "E&xit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // editToolStripMenuItem + // + this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.undoToolStripMenuItem, + this.redoToolStripMenuItem, + this.toolStripSeparator3, + this.cutToolStripMenuItem, + this.copyToolStripMenuItem, + this.pasteToolStripMenuItem, + this.toolStripSeparator4, + this.selectAllToolStripMenuItem}); + this.editToolStripMenuItem.Enabled = false; + this.editToolStripMenuItem.Name = "editToolStripMenuItem"; + this.editToolStripMenuItem.Size = new System.Drawing.Size(43, 22); + this.editToolStripMenuItem.Text = "&Edit"; + this.editToolStripMenuItem.Visible = false; + // + // undoToolStripMenuItem + // + this.undoToolStripMenuItem.Name = "undoToolStripMenuItem"; + this.undoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z))); + this.undoToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.undoToolStripMenuItem.Text = "&Undo"; + // + // redoToolStripMenuItem + // + this.redoToolStripMenuItem.Name = "redoToolStripMenuItem"; + this.redoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y))); + this.redoToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.redoToolStripMenuItem.Text = "&Redo"; + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(173, 6); + // + // cutToolStripMenuItem + // + this.cutToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cutToolStripMenuItem.Image"))); + this.cutToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.cutToolStripMenuItem.Name = "cutToolStripMenuItem"; + this.cutToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X))); + this.cutToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.cutToolStripMenuItem.Text = "Cu&t"; + // + // copyToolStripMenuItem + // + this.copyToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("copyToolStripMenuItem.Image"))); + this.copyToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; + this.copyToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this.copyToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.copyToolStripMenuItem.Text = "&Copy"; + // + // pasteToolStripMenuItem + // + this.pasteToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pasteToolStripMenuItem.Image"))); + this.pasteToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem"; + this.pasteToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V))); + this.pasteToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.pasteToolStripMenuItem.Text = "&Paste"; + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(173, 6); + // + // selectAllToolStripMenuItem + // + this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem"; + this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(176, 22); + this.selectAllToolStripMenuItem.Text = "Select &All"; + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contentsToolStripMenuItem, + this.toolStripSeparator5, + this.aboutToolStripMenuItem}); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(48, 22); + this.helpToolStripMenuItem.Text = "&Help"; + // + // contentsToolStripMenuItem + // + this.contentsToolStripMenuItem.AutoToolTip = true; + this.contentsToolStripMenuItem.Name = "contentsToolStripMenuItem"; + this.contentsToolStripMenuItem.Size = new System.Drawing.Size(149, 22); + this.contentsToolStripMenuItem.Text = "&Contents"; + this.contentsToolStripMenuItem.Click += new System.EventHandler(this.contentsToolStripMenuItem_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(146, 6); + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(149, 22); + this.aboutToolStripMenuItem.Text = "&About..."; + this.aboutToolStripMenuItem.ToolTipText = "About this program"; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); + // + // customizeToolStripMenuItem + // + this.customizeToolStripMenuItem.Name = "customizeToolStripMenuItem"; + this.customizeToolStripMenuItem.Size = new System.Drawing.Size(32, 19); + this.customizeToolStripMenuItem.Text = "&Customize"; + // + // saveFileDialog + // + this.saveFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.saveFileDialog1_FileOk); + // + // DistexForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 17F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.ControlLight; + this.ClientSize = new System.Drawing.Size(642, 611); + this.Controls.Add(this.propertiesTab); + this.Controls.Add(this.menuStrip1); + this.Font = new System.Drawing.Font("Tahoma", 8.400001F); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.Margin = new System.Windows.Forms.Padding(4); + this.MaximizeBox = false; + this.MinimumSize = new System.Drawing.Size(650, 645); + this.Name = "DistexForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Statistical Distribution Explorer"; + this.toolTip1.SetToolTip(this, "Statistical Distribution Explorer main form"); + this.Activated += new System.EventHandler(this.DistexForm_Activated); + this.Load += new System.EventHandler(this.Form_Load); + this.propertiesTab.ResumeLayout(false); + this.DistributionTab.ResumeLayout(false); + this.DistributionTab.PerformLayout(); + this.PropertiesTabPage.ResumeLayout(false); + this.PropertiesTabPage.PerformLayout(); + this.cdfTabPage.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.CDF_data)).EndInit(); + this.QuantileTabPage.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.QuantileData)).EndInit(); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl propertiesTab; + private System.Windows.Forms.TabPage DistributionTab; + private System.Windows.Forms.TabPage PropertiesTabPage; + private System.Windows.Forms.Label distributionNameLabel; + private System.Windows.Forms.Label parameter2Label; + private System.Windows.Forms.Label parameter1Label; + private System.Windows.Forms.TextBox parameter2; + private System.Windows.Forms.TextBox parameter1; + private System.Windows.Forms.ComboBox distribution; + private System.Windows.Forms.Label standard_deviation; + private System.Windows.Forms.Label stddevLabel; + private System.Windows.Forms.Label variance; + private System.Windows.Forms.Label varianceLabel; + private System.Windows.Forms.Label medianLabel; + private System.Windows.Forms.Label mode; + private System.Windows.Forms.Label mean; + private System.Windows.Forms.Label meanLabel; + private System.Windows.Forms.TabPage cdfTabPage; + private System.Windows.Forms.DataGridView CDF_data; + private System.Windows.Forms.DataGridViewTextBoxColumn RandomVariable; + private System.Windows.Forms.DataGridViewTextBoxColumn PDF; + private System.Windows.Forms.DataGridViewTextBoxColumn CDF; + private System.Windows.Forms.DataGridViewTextBoxColumn CCDF; + private System.Windows.Forms.TabPage QuantileTabPage; + private System.Windows.Forms.DataGridView QuantileData; + private System.Windows.Forms.DataGridViewTextBoxColumn RiskLevel; + private System.Windows.Forms.DataGridViewTextBoxColumn LowerCriticalValue; + private System.Windows.Forms.DataGridViewTextBoxColumn UpperCriticalValue; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator; + private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem printToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem printPreviewToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripMenuItem cutToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem pasteToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem selectAllToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem customizeToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem contentsToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + private System.Windows.Forms.Label median; + private System.Windows.Forms.Label skewness; + private System.Windows.Forms.Label skewnessLabel; + private System.Windows.Forms.Label kurtosis; + private System.Windows.Forms.Label kurtosisLabel; + private System.Windows.Forms.Label kurtosis_excess; + private System.Windows.Forms.Label kurtosisExcessLabel; + private System.Windows.Forms.Label modeLabel; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.Label CVlabel; + private System.Windows.Forms.Label coefficient_of_variation; + private System.Windows.Forms.Label parameter3Label; + private System.Windows.Forms.TextBox parameter3; + private System.Windows.Forms.Label parameterLabel3; + private System.Windows.Forms.Label parameterLabel2; + private System.Windows.Forms.Label parameterLabel1; + private System.Windows.Forms.Label DistributionLabel; + private System.Windows.Forms.Label parameter3ValueLabel; + private System.Windows.Forms.Label parameter2ValueLabel; + private System.Windows.Forms.Label parameter1ValueLabel; + private System.Windows.Forms.Label distributionValueLabel; + private System.Windows.Forms.SaveFileDialog saveFileDialog; + private System.Windows.Forms.Label supportLabel; + private System.Windows.Forms.Label rangeGreatestLabel; + private System.Windows.Forms.Label rangeLowestLabel; + private System.Windows.Forms.Label rangeLabel; + private System.Windows.Forms.Label supportUpperLabel; + private System.Windows.Forms.Label supportLowerLabel; + private System.Windows.Forms.Label toLabel2; + private System.Windows.Forms.Label toLabel1; + } +} + diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.cs new file mode 100644 index 000000000..8123b8ac3 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.cs @@ -0,0 +1,610 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Threading; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace distribution_explorer +{ + /// <summary> + /// Main distribution explorer. + /// </summary> + public partial class DistexForm : Form + { + + EventLog log = new EventLog(); + /// <summary> + /// Main form + /// </summary> + public DistexForm() + { + if (!EventLog.SourceExists("EventLogDistex")) + { + EventLog.CreateEventSource("EventLogDistex", "Application"); + } + log.Source = "EventLogDistex"; + log.WriteEntry("DistexForm"); + + InitializeComponent(); + + Application.DoEvents(); + } + + private void Form_Load(object sender, EventArgs e) + { // Load distribution & parameters names, and default values. + try + { + // Create and show splash screen: + this.Hide(); + distexSplash frmSplash = new distexSplash(); + frmSplash.Show(); + frmSplash.Update(); + // Now load our data while the splash is showing: + if (boost_math.any_distribution.size() <= 0) + { + MessageBox.Show("Problem loading any distributions, size = " + boost_math.any_distribution.size().ToString()); + } + for (int i = 0; i < boost_math.any_distribution.size(); ++i) + { + distribution.Items.Add(boost_math.any_distribution.distribution_name(i)); + } + distribution.SelectedIndex = 0; // 1st in array, but could be any other. + // All parameters are made zero by default, but updated from chosen distribution. + parameter1.Text = boost_math.any_distribution.first_param_default(0).ToString(); + parameter2.Text = boost_math.any_distribution.second_param_default(0).ToString(); + parameter3.Text = boost_math.any_distribution.third_param_default(0).ToString(); + // + // Sleep and then close splash; + Thread.Sleep(3000); + frmSplash.Close(); + this.Visible = true; + } + catch + { // + log.WriteEntry("DistexForm_load exception!"); + MessageBox.Show("Problem loading distributions, size = " + boost_math.any_distribution.size().ToString()); + } + } + + private void distribution_SelectedIndexChanged(object sender, EventArgs e) + { + int i = distribution.SelectedIndex; // distribution tab. + parameter1Label.Text = boost_math.any_distribution.first_param_name(i); + parameterLabel1.Text = boost_math.any_distribution.first_param_name(i); // properties tab. + parameter2Label.Text = boost_math.any_distribution.second_param_name(i); + parameter3Label.Text = boost_math.any_distribution.third_param_name(i); + if (boost_math.any_distribution.first_param_name(i).Length.CompareTo(0) != 0) + { // Actually all the distributions have at least one parameters, + parameter1.Visible = true; // so should always be true. + parameterLabel1.Visible = true; + } + else + { // If distribution chosen has no parameter name(s) then hide. + parameter1.Visible = false; + parameterLabel1.Visible = false; + } + parameter1.Text = boost_math.any_distribution.first_param_default(i).ToString(); + // Update parameter default to match distribution. + if (boost_math.any_distribution.second_param_name(i).Length.CompareTo(0) != 0) + { + parameter2.Visible = true; + parameterLabel2.Visible = true; + parameter2ValueLabel.Visible = true; + } + else + { // hide + parameter2.Visible = false; + parameterLabel2.Visible = false; + parameter2ValueLabel.Visible = false; + + } + parameter2.Text = boost_math.any_distribution.second_param_default(i).ToString(); + if (boost_math.any_distribution.third_param_name(i).Length.CompareTo(0) != 0) + { + parameter3.Visible = true; + parameterLabel3.Visible = true; + parameter3ValueLabel.Visible = true; + } + else + { // hide + parameter3.Visible = false; + parameterLabel3.Visible = false; + parameter3ValueLabel.Visible = false; + } + parameter3.Text = boost_math.any_distribution.third_param_default(i).ToString(); + // Update tool tips to show total and supported ranges. + PropertiesTabPage.ToolTipText = "Shows properties and ranges of chosen distribution."; + } + + private boost_math.any_distribution dist; + + private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) + { // Display a grid of pdf, cdf... values from user's random variate x value. + try + { + if (e.ColumnIndex == 0) + { // Clicked on left-most random variate x column to enter a value. + int i = e.RowIndex; + string s = CDF_data.Rows[i].Cells[0].Value.ToString(); + double x = double.Parse(s); // Get value of users random variate x. + double pdf = dist.pdf(x); // Compute pdf values from x + double cdf = dist.cdf(x); // & cdf + double ccdf = dist.ccdf(x); // & complements. + CDF_data.Rows[i].Cells[1].Value = pdf; // and display values. + CDF_data.Rows[i].Cells[2].Value = cdf; + CDF_data.Rows[i].Cells[3].Value = ccdf; + } + } + catch (SystemException se) + { + MessageBox.Show("Error in random variable value: " + se.Message, "Calculation Error"); + } + } + + private void tabPage2_Enter(object sender, EventArgs e) + { // Properties tab shows distribution's mean, mode, median... + try + { // Show chosen distribution name, and parameter names & values. + int i = distribution.SelectedIndex; + distributionValueLabel.Text = boost_math.any_distribution.distribution_name(i).ToString(); + parameterLabel1.Text = boost_math.any_distribution.first_param_name(i).ToString(); + parameter1ValueLabel.Text = double.Parse(parameter1.Text).ToString(); + parameterLabel2.Text = boost_math.any_distribution.second_param_name(i).ToString(); + parameter2ValueLabel.Text = double.Parse(parameter2.Text).ToString(); + parameterLabel3.Text = boost_math.any_distribution.third_param_name(i).ToString(); + parameter3ValueLabel.Text = double.Parse(parameter3.Text).ToString(); + + // Show computed properties of distribution. + try + { + mean.Text = dist.mean().ToString(); + } + catch + { + mean.Text = "Undefined."; + } + try + { + mode.Text = dist.mode().ToString(); + } + catch + { + mode.Text = "Undefined."; + } + try + { + median.Text = dist.median().ToString(); + } + catch + { + median.Text = "Undefined."; + } + try + { + variance.Text = dist.variance().ToString(); + } + catch + { + variance.Text = "Undefined."; + } + try + { + standard_deviation.Text = dist.standard_deviation().ToString(); + } + catch + { + standard_deviation.Text = "Undefined."; + } + try + { + skewness.Text = dist.skewness().ToString(); + } + catch + { + skewness.Text = "Undefined."; + } + try + { + kurtosis.Text = dist.kurtosis().ToString(); + } + catch + { + kurtosis.Text = "Undefined."; + } + try + { + kurtosis_excess.Text = dist.kurtosis_excess().ToString(); + } + catch + { + kurtosis_excess.Text = "Undefined."; + } + try + { + coefficient_of_variation.Text = dist.coefficient_of_variation().ToString(); + } + catch + { + coefficient_of_variation.Text = "Undefined."; + } + + rangeLowestLabel.Text = dist.lowest().ToString(); + rangeGreatestLabel.Text = dist.uppermost().ToString(); + supportLowerLabel.Text = dist.lower().ToString(); + supportUpperLabel.Text = dist.upper().ToString(); + cdfTabPage.ToolTipText = "Random variate can range from " + rangeLowestLabel.Text + + " to " + rangeGreatestLabel.Text + + ",\nbut is said to be supported from " + supportLowerLabel.Text + + " to " + supportUpperLabel.Text + + "\nWithin this supported range the PDF and CDF have values between 0 and 1,\nbut below " + supportLowerLabel.Text + " both are zero, and above " + + supportUpperLabel.Text + " both are unity"; + } + catch (SystemException se) + { + MessageBox.Show(se.Message, "Calculation Error!"); + } + } + + private void properties_tab_Deselecting(object sender, TabControlCancelEventArgs e) + { + try + { + if (e.TabPageIndex == 0) + { // Update selected distribution object: + double x = double.Parse(parameter1.Text); + double y = double.Parse(parameter2.Text); + double z = double.Parse(parameter3.Text); + int i = distribution.SelectedIndex; + dist = new boost_math.any_distribution(i, x, y, z); + // Clear existing CDF data (has to be a better way?): + while (CDF_data.Rows.Count > 1) + { + CDF_data.Rows.Remove(CDF_data.Rows[0]); + } + // Clear existing quantile data (has to be a better way?): + while (QuantileData.Rows.Count > 1) + { + QuantileData.Rows.Remove(QuantileData.Rows[0]); + } + } + } + catch (SystemException se) + { + MessageBox.Show(se.Message + + " Please check the distribution's parameters and try again.", "Distribution Error"); + this.propertiesTab.SelectedIndex = 0; + e.Cancel = true; + } + } + + private void QuantileData_CellEndEdit(object sender, DataGridViewCellEventArgs e) + { // aka Risk & critical values tab. + try + { + if (e.ColumnIndex == 0) + { + int i = e.RowIndex; + string s = QuantileData.Rows[i].Cells[0].Value.ToString(); + double x = double.Parse(s); + // Remember x is alpha: 1 - the probability: + double lcv = dist.quantile(x); + double ucv = dist.quantile_c(x); + QuantileData.Rows[i].Cells[1].Value = lcv; + QuantileData.Rows[i].Cells[2].Value = ucv; + } + } + catch (SystemException se) + { + // TODO add some proper handling here! + MessageBox.Show("Error in probability value: " + se.Message, "Calculation Error"); + } + } + + private void QuantileTab_Enter(object sender, EventArgs e) + { // Evaluate critical values (quantiles) for pre-chosen risk level. + // and then, optionally, for other user-provided risk levels. + try + { + if (QuantileData.Rows.Count == 1) + { + // Add some defaults: + QuantileData.Rows.Add(5); // 5 Risk levels. + QuantileData.Rows[0].Cells[0].Value = "0.001"; // Risk values as text, + QuantileData.Rows[0].Cells[1].Value = dist.quantile(0.001); // & as double. + QuantileData.Rows[0].Cells[2].Value = dist.quantile_c(0.001); + QuantileData.Rows[1].Cells[0].Value = "0.01"; + QuantileData.Rows[1].Cells[1].Value = dist.quantile(0.01); // 99% confidence. + QuantileData.Rows[1].Cells[2].Value = dist.quantile_c(0.01); + QuantileData.Rows[2].Cells[0].Value = "0.05"; + QuantileData.Rows[2].Cells[1].Value = dist.quantile(0.05); + QuantileData.Rows[2].Cells[2].Value = dist.quantile_c(0.05); + QuantileData.Rows[3].Cells[0].Value = "0.1"; + QuantileData.Rows[3].Cells[1].Value = dist.quantile(0.1); + QuantileData.Rows[3].Cells[2].Value = dist.quantile_c(0.1); + QuantileData.Rows[4].Cells[0].Value = "0.33333333333333333"; + QuantileData.Rows[4].Cells[1].Value = dist.quantile(0.33333333333333333); + QuantileData.Rows[4].Cells[2].Value = dist.quantile_c(0.33333333333333333); + } + } + catch (SystemException se) + { + // TODO add some proper handling here! + MessageBox.Show(se.Message, "Calculation Error"); + } + } + + + private void properties_tab_SelectedIndexChanged(object sender, EventArgs e) + { + } + + private void tabPage1_Click(object sender, EventArgs e) + { + } + + private void CDF_data_CellContentClick(object sender, DataGridViewCellEventArgs e) + { + } + + distexAboutBox DistexAboutBox = new distexAboutBox(); + + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + DistexAboutBox.ShowDialog(); + } + + private void DistexForm_Activated(object sender, EventArgs e) + { + } + + /// get AssemblyDescription + public string AssemblyDescription + { + get + { + // Get all Description attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + // If there aren't any Description attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Description attribute, return its value + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + private void saveFileDialog1_FileOk(object sender, CancelEventArgs e) + { + using (StreamWriter sw = new StreamWriter(this.saveFileDialog.FileName)) + { // Write distribution info and properties to file. + sw.WriteLine( AssemblyDescription); + sw.WriteLine("Version " + Assembly.GetExecutingAssembly().GetName().Version.ToString()); + // Get parameter names (null "" if no parameter). + int i = distribution.SelectedIndex; + distributionValueLabel.Text = boost_math.any_distribution.distribution_name(i).ToString(); + sw.WriteLine(distributionValueLabel.Text + " distribution"); + parameterLabel1.Text = boost_math.any_distribution.first_param_name(i).ToString(); + parameterLabel2.Text = boost_math.any_distribution.second_param_name(i).ToString(); + parameterLabel3.Text = boost_math.any_distribution.third_param_name(i).ToString(); + string separator = "\t "; // , or tab or space? + // Write parameter name & value. + sw.WriteLine(parameterLabel1.Text + separator + this.parameter1.Text); + if (boost_math.any_distribution.second_param_name(i).Length.CompareTo(0) != 0) + { // Is a 2nd parameter. + sw.WriteLine(parameterLabel2.Text + separator + this.parameter2.Text); + } + if (boost_math.any_distribution.third_param_name(i).Length.CompareTo(0) != 0) + { // Is a 3rd parameter. + sw.WriteLine(parameterLabel3.Text + separator + this.parameter3.Text); + } + sw.WriteLine(); + sw.WriteLine("Properties"); + // Show computed properties of distribution. + double x = double.Parse(parameter1.Text); + double y = double.Parse(parameter2.Text); + double z = double.Parse(parameter3.Text); + dist = new boost_math.any_distribution(i, x, y, z); + // Note global dist might not have been calculated yet if no of the tabs clicked. + try + { + mean.Text = dist.mean().ToString(); + } + catch + { + mean.Text = "Undefined"; + } + sw.WriteLine("Mean" + separator + mean.Text); + try + { + mode.Text = dist.mode().ToString(); + } + catch + { + mode.Text = "Undefined"; + } + sw.WriteLine("mode" + separator + mode.Text); + try + { + median.Text = dist.median().ToString(); + } + catch + { + median.Text = "Undefined"; + } + sw.WriteLine("Median" + separator + median.Text); + try + { + variance.Text = dist.variance().ToString(); + } + catch + { + variance.Text = "Undefined"; + } + sw.WriteLine("Variance" + separator + variance.Text); + try + { + standard_deviation.Text = dist.standard_deviation().ToString(); + } + catch + { + standard_deviation.Text = "Undefined"; + } + sw.WriteLine("Standard Deviation" + separator + standard_deviation.Text); + try + { + skewness.Text = dist.skewness().ToString(); + } + catch + { + skewness.Text = "Undefined"; + } + sw.WriteLine("Skewness" + separator + skewness.Text); + try + { + coefficient_of_variation.Text = dist.coefficient_of_variation().ToString(); + } + catch + { + coefficient_of_variation.Text = "Undefined"; + } + sw.WriteLine("Coefficient of variation" + separator + coefficient_of_variation.Text); + try + { + kurtosis.Text = dist.kurtosis().ToString(); + } + catch + { + kurtosis.Text = "Undefined"; + } + sw.WriteLine("Kurtosis" + separator + kurtosis.Text); + try + { + kurtosis_excess.Text = dist.kurtosis_excess().ToString(); + } + catch + { + kurtosis_excess.Text = "Undefined"; + } + sw.WriteLine("Kurtosis excess" + separator + kurtosis_excess.Text); + sw.WriteLine(); + + sw.WriteLine("Range from" + separator + dist.lowest().ToString() + separator + + "to" + separator + dist.uppermost().ToString()); + sw.WriteLine("Support from " + separator + dist.lower().ToString() +separator+ + "to " + separator + dist.upper().ToString()); + sw.WriteLine(); + + // + sw.WriteLine("Quantiles"); + if (QuantileData.Rows.Count == 1) + { // Add some defaults: + QuantileData.Rows.Add(5); // 5 Risk levels. + QuantileData.Rows[0].Cells[0].Value = "0.001"; // Risk values as text, + QuantileData.Rows[0].Cells[1].Value = dist.quantile(0.001); // & as double. + QuantileData.Rows[0].Cells[2].Value = dist.quantile_c(0.001); + QuantileData.Rows[1].Cells[0].Value = "0.01"; + QuantileData.Rows[1].Cells[1].Value = dist.quantile(0.01); // 99% confidence. + QuantileData.Rows[1].Cells[2].Value = dist.quantile_c(0.01); + QuantileData.Rows[2].Cells[0].Value = "0.05"; + QuantileData.Rows[2].Cells[1].Value = dist.quantile(0.05); + QuantileData.Rows[2].Cells[2].Value = dist.quantile_c(0.05); + QuantileData.Rows[3].Cells[0].Value = "0.1"; + QuantileData.Rows[3].Cells[1].Value = dist.quantile(0.1); + QuantileData.Rows[3].Cells[2].Value = dist.quantile_c(0.1); + QuantileData.Rows[4].Cells[0].Value = "0.33333333333333333"; + QuantileData.Rows[4].Cells[1].Value = dist.quantile(0.33333333333333333); + QuantileData.Rows[4].Cells[2].Value = dist.quantile_c(0.33333333333333333); + } + // else have already been calculated by entering the quantile tab. + for (int r = 0; r < QuantileData.Rows.Count-1; r++) + { // Show all the rows of quantiles, including any optional user values. + sw.WriteLine(QuantileData.Rows[r].Cells[0].Value.ToString() + separator + + QuantileData.Rows[r].Cells[1].Value.ToString() + separator + + QuantileData.Rows[r].Cells[2].Value.ToString()); + } + sw.WriteLine(); + sw.WriteLine("PDF, CDF & complement(s)"); + for (int r = 0; r < CDF_data.Rows.Count-1; r++) + { // Show all the rows of pdf, cdf, including any optional user values. + sw.WriteLine(CDF_data.Rows[r].Cells[0].Value.ToString() + separator + // x value. + CDF_data.Rows[r].Cells[1].Value.ToString() + separator + // pdf + CDF_data.Rows[r].Cells[2].Value.ToString() + separator + // cdf + CDF_data.Rows[r].Cells[3].Value.ToString());// cdf complement. + } + sw.WriteLine(); + } + + } // saveFileDialog1_FileOk + + private void saveToolStripMenuItem_Click(object sender, EventArgs e) + { + this.saveFileDialog.ShowDialog(); + } + + private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) + { // Same as Save. + this.saveFileDialog.ShowDialog(); + } + + private void contentsToolStripMenuItem_Click(object sender, EventArgs e) + { // In lieu of proper help. + string helpText = "\n" + AssemblyDescription + + "\nVersion " + Assembly.GetExecutingAssembly().GetName().Version.ToString() + + "\nA Windows utility to show the properties of distributions " + + "\nand permit calculation of probability density (or mass) function (PDF) " + + "\nand cumulative distribution function (CDF) and complements from values provided." + + "\nQuantiles are also calculated for typical risk (alpha) probabilities" + + "\nand for probabilities provided by the user." + + "\n" + + "\nResults can be saved to text files using Save or SaveAs." + + "\nAll the values on the four tabs are output to the file chosen," + + "\nand are tab separated to assist input to other programs," + + "\nfor example, spreadsheets or text editors." + + "\nNote: when importing to Excel, by default only 10 decimal digits are shown by Excel:" + + "\nit is necessary to format all cells to display the full 15 decimal digits," + + "\nalthough not all computed values will be as accurate as this." + + "\n\nValues shown as NaN cannot be calculated for the value given," + + "\nmost commonly because the value is outside the range for the distribution." + + "\n" + + "\nFor more information, including downloads, see " + + "\nhttp://sourceforge.net/projects/distexplorer/" + + "\n(Note that .NET framework 4.0 and VC Redistribution X86 are requirements for this program.)" + + "\n\nCopyright John Maddock & Paul A. Bristow 2007, 2009, 2010, 2012"; + + MessageBox.Show("Statistical Distribution Explorer\n" + helpText); + } + + private void newToolStripMenuItem_Click(object sender, EventArgs e) + { + MessageBox.Show("New is not yet implemented."); + } + + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + MessageBox.Show("Open is not yet implemented."); + } + + private void printToolStripMenuItem_Click(object sender, EventArgs e) + { + MessageBox.Show("Print is not yet implemented." + + "\nSave all values to a text file and print that file."); + } + + private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e) + { + MessageBox.Show("Print Preview is not yet implemented." + + "\nSave all values to a text file and print that file."); + } + + + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { // exit DistexForm + this.Close(); + } + } // class DistexForm +} // namespace distribution_explorer
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.resx new file mode 100644 index 000000000..5019fd5ce --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexForm.resx @@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>284, 17</value> + </metadata> + <metadata name="RandomVariable.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="PDF.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="CDF.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="CCDF.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="RiskLevel.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="LowerCriticalValue.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="UpperCriticalValue.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>True</value> + </metadata> + <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>159, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="newToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAQ9JREFUOE+t09lqwkAUBmBfyr5DfY32jaReSOmFCyKCgkKLFrVUBZeKiEbshqRuaNw1 + xiXmLxMJBJ0Zc+GBw9zMfDPnHMZmu1ZE35s4zXCqjmC8Al+sgHLjD9y7yGFWPIbecOO45yORtMAEHnxx + JHL1IyKI9JeEXqtMwOl50Q8bSS0l8PzBBPbqAQQxICrgjeapgKZpkJUdBmNZB+y3d/QSnsIZKrDdqZjM + FYj9OR9wB1NngHrQsJC36EkrfIkTPuDyJ84AZbOHNF2j1Z2h9i3xAVKfOUjjZssN2oMFmq0xSkLfOmBu + 3E97iurnENlKxzpgbpzwO0Kh1kOyKFoDjHmzVuYYjRmTDZfyWh9Yd/4B2Mz2w1z7EGUAAAAASUVORK5C + YII= +</value> + </data> + <data name="openToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAlpJREFUOE+tk21Ik1EYhif0oyA0sqIQCix/+GcQFFH9CCmiUBTLLEjShJofVBgL2fxo + U9Pp5ubUlS5rU9f8rCyjsA+pUCRCTR1ppmVFUSlmhq78unrnQF1KGHTg/nEOz30993PO+7qJFrmUeiv2 + n+Mij+XLRLLYULdF2pxlEVIDcw0pAsyxD5fmI/rQ94pqi26eOlsfuZj+7BgSm01QdA4ih7m73Yx9qGpa + vwatjPebqCzOprPt8YKQgzFagqL0BEjyEFWVaBkdLHMxT34uYNwWR9nVTEoL0zHlp2DMSeaSRk6eKt4V + Wm5WM/rVPNN5SjDTLQebZEHNA1wrUvHjk3E6tsNcV62e1r3KLGqtKm6WplNpSsVqVFJsOM8VfSKFWjkG + tcyZptSYzvC7XByx3zQoqCnTMvlGCX1prnornPUmQJcUXsbSVhGK5bIOkcmQyveeTHiv4VZ5Nk33Nc6i + uSO8CIfmECYa/bE/8ON1iRipJNh5F0V6Bd86lfQ1JlFj1TDVq4COKCegLVIwHmGiKRB7/V6G7+5koHoz + ymgfYRy5E1CgTWKgXcZ1i5qWp0KSrjgBcAJawph6FszYk/2M1O1isGYLX8p9ab6wgqP+3rMvYciS01Gf + zA1LFvQkQ6sQ9/khxhoCGHnox1DtNvorxXw0b8Km8UQh2cip6GOzgNyMeKqKM7HdjqFZJ5pRk2YJ9aql + 3EnxoCJxNaZ4Ly6e3UDY3O6OEXRp59ApTpIhiyDh9GHORAZyPHQPB/ZtZ/cOMVvFPvh6e7F+3SrWrHRn + raf7Xz/xf/rJ/kvxb84I3U1y+9/WAAAAAElFTkSuQmCC +</value> + </data> + <data name="saveToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAixJREFUOE+tk91Lk3EUx/cvdN9N0EW3NTWGa7EaPOUcyqphWBG9PZEv5dJlmqhYmUYt + XyBb4dJJy+kknFT4BqZIjaFMJUszV7TEoabYRDD49ju/6Pm1Mi+iH5zLz+c855zvo1L9j/fsaRRUvvZl + tHmX8Ni9gMaGCO47ZlBb8wn22yHcKJ9CackECgteIy93FBfOB6H0JrC3B6ipXsVGb2V1Dca0XhxOe8JL + EXhbF7mgsuLLX3mCIwsr2G1+DrVahuWQRwjcj+a5oLTk87qCn/D78CLiTD4UXJ7GAXOTEDjrZ7ngku3d + H4Jf4ZHJCLZJXlhzxpGa4hSCurthLsjOGo0R/A4PBsPYrHdDlgMwmRxCUF31kQvkMwFFsB7c4/+ATYkN + OHL0BZKSaoXgZuU0urvATgkcP/kKlmMDfNu0MJqZPps6/4D7cNDSCUmyC8HVskl0+MAyADS5vrG7f0X5 + 9Tm+VFoYzZyZEVTg5NR2GAwVQnClcByeZuChc40FJwpjek5MmU/YkH6uiHdOTmHwfg/0+jIhsOWNMRio + uhPlnUnAQoI4rYSht7MYm5qDnHsNe41tHNbucUGnKxICiqXjHpTPJgHBZ/Nv4U1oHqGZJVwstiNe72Jw + I+J3PYA2MV8IMjOG2dzLfOatBg+27JDQ0tEPX9cguvv8GHg5hH0mC9S6eiQweLumDhqNVQgo06dP9fN4 + UsIoJHRnOhVtmxZGM1NXKoJ3JmTHCv71r/4OTrQ4xWMwWlcAAAAASUVORK5CYII= +</value> + </data> + <data name="printToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAi1JREFUOE+1k/9PUlEYxv2nWK2tVlttGmpltrCcEQ1XUjSMaUHJNLIpNcnCragplBvU + oC/okJhZLG92ySUpU8RNICdIhAioEF+e7r1UZMDW1jrb+8t7z/N83vucc8rK/sdyeYIwvpopWYbRaZTk + 0uIx0o0/V/JbGt7lVTwxT6CKKyltoLd8xGYihS/hKGz2WaaeWUnoTATsMz7UCztx9Ex7cYN3jkUQU4tb + 4DR5LZaAcyEAg4VE5YlLMFmJQoNQJA61gUA6k4XPH9pCN9s+gZz2oq5Jjlq+DDfUz3Fba86bOGY9jHiU + dDF0mvqT7A/F4fKEcE9nZf5d1jOIB4ZxVJ2U5gyc8z70akegMX3AXb0ND1+8R6/GgvZbeog61OA2K3CA + 2lxR34JjZ69B2T8EsVyN/Q0XcwY3B14iGk8UpE43UukMNqhA6QyC4Q0srcQg7dagsbWHmuDHScj7jDC9 + nsJTqx0a4xjuaIfRqXoMSXc/hG0q8C4owGnqwEGeFOXHxThH9eoEV7G7VpiboE2pK0qnm9H1JLz+NUzO + BfHWEcAQsQSuqAuVDa1gVZzKGUgUjwoMqAzxNZbC3Od1jDvDYPdth+7NCpP8Yf4V7KoR5A1arg8gmQIo + GMLxLJYjWSwEMphwb2J4MoZB2yqULBZUIxHGYB9HlBfTE4jl9+GmBPTHv6lfo//+GGoaZajmXQabumXl + 1HHt5TRjz5Hz2HlIgB3Vp7GNzWeoRcX/+pq/AwHYL0leVl8fAAAAAElFTkSuQmCC +</value> + </data> + <data name="printPreviewToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAY5JREFUOE+d081LAkEUAPD1T+hYhzoERV77OHUo8JBBt+4RRkSQ4U0SunaJOkSRKQWZ + WCiF5kdroa0WRAoRFXXoEEkWCUFYWbvrvnqz7NK6OxANPIZh5v1m3uyOKZK5AaamiaLICILACDzPtDXX + M+3mRlPtGnWMAK15g4fQabVBYDej20QFdtJXVGBxg4Xk8aWMRDhjJLh/TgUW1hPQ1T+ihmEZgXieCghi + FRBRIEPAFzkxBO4fSsByOfBsRkkE4xkoFEv6Mla3szoAF2Jy+E2A0KMc/nyRINe3BS2yspXSAf4YR5Kf + q/LUE1QJopxEU8qSP6kD5nwxFUAEA0E8hdM1rz0BXtDvhheHwMEnwKkkJ2OPAJMuw+TUDB2QJAneKzxg + CRNnHwTBUJJd3ijYx8fowBcvwstrBXIXdxBOZAmCu2JgssMxBGvOOmNA+d5KP+sJw17qiJRjn3bDwOAo + cF4LQMWtRTABf9W/hLWjFcpsA0Fctm76+6C+vJ+J4b4WgmAp/0bMTXVg6ekFNrQM3y3xMcC3lb+tAAAA + AElFTkSuQmCC +</value> + </data> + <data name="cutToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAYdJREFUOE+t001LQlEQBuB+TdCmRVEJRRIWtRAUlKsQhFmkpZQtIiWyAlMwP5KkXS0s + hLqGFkgoFqWQmaRR2qIvU7FMwWhd8JZXkFx0uVGzOcNh5jkDw6mr+++4SN7B6fbju/uQecYm6a25+/Hd + l2IJptWNmmJyL4DwWZwZUJbtayT8RxGqIV8oQaaaRfrxkTmw4z2G+WuKbC6PYDgOkUSJp6ccc+AgdI4l + uwPbHh/UCxb0S0aZN5fHTmefMTVvwfDEHIiBMegMpt8BZUShNoGQTIKQGxA8TTIHMoUPGF1vEOvTWHTc + gqeJQahNwLqVQiRRpIdS+XcM2l4h1t2DI3WAP7oGoSYE3kwSPQofljcqm/kxjK4SCH0OXSMetItsUC26 + wZuOVptYhI0eEOuz1YI2gZnKBdpr6iR9V2jkKOkBQpeiCryhFFr4eioft16iU7qNho4h1Dc00QOqlRuw + pSSa+UawuZXdByIZsPoUaOmWwrUfowcOozlwZeto7ZXDuXvCfHV/+dGfqqrf44qgu28AAAAASUVORK5C + YII= +</value> + </data> + <data name="copyToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAeJJREFUOE+lk9FPklEYxv1TSsecde0f0FpZrTbbal7URVvZuuJCr7pq2WzLNWy0iSHN + wtIB9qG0ltLSYRJpBomUgZPMGSyU8SmJIOiv7zssCdrAzXd77s77e5/nnPdUVR20HBPfUCWNB4QsI176 + HB8IL/9iX2y1ubTMwx6utz0nuLhcGWIfCxT153Z26ep/g9Md4FJLZ2WIZdQnAM4QSJ/BH5Z5aH6NNClj + m0hgdSV4MppAPxQXCq5kil31OTx7DjLbOeSNNJFYUgBKq31glfpmN76F9QLEZHOJc73ubXQjMreln7Q+ + DdP/du0/QIsxhmNK5mjTMJ/m43mIQcmr5t5MZVlNpFiKrPM1vIbpVVQAOqSckF+ZekUX5UjTS+ouDFLb + +CwPUPNupbN7k7WmEDcMX3hgXSpyIP/OsrCyhXtuA6M0g+bc4wJATqaZ/x7DF4zg8f9g/OMibb355701 + kERriHL5fojzd2aFjNI0mjPdBUD96auUqlU/KwBZJV4skWUuvMmYV8b+Ls6jQQ81DfryO3KtfUoA/p38 + 10G37T3VJ3TlARdvukhldjANeemxz2B8MS0mq80GyySHj98rD2jQOpXbtgrVNprRnO2h5lQX1Sc7leYO + Dh27W3nN9/WZDnroDx0A5wwhdtmtAAAAAElFTkSuQmCC +</value> + </data> + <data name="pasteToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAA + EnQB3mYfeAAAAlBJREFUOE+1k1lIlGEUhn/owm6KFuqqq4LoJooIqouMwixMM4zEjKyJGJUSlcnSITU1 + RSe3SdPGyGVQc6tEUSkSIXFo13CMFonUyGmy5p9xz+Lp/z8ZbGjzpgMv5+a8z1n4Pkn6H9HZnEH7zVQa + yxKYF7+hMg+3ynKO4LBVMWa7xmBfNme1vuSl67hi0GNMj/sVqBon5XqmnXVMOqoxF+sYH6kgJyWKF13x + nD/tT7xmM7bOY4y0riY6bL8nRAWo5mlnDUUZR+m2ZCO/L2C4T89bywmaSgIJD/WmKnEVT/MkIg/v8wTU + VeTMAuQbGBLDSNaFoI8K5lxkEDptIDEafyJCfciPXiMAIX7enoDqUgNTci1TdhPjQ5nYn0dhrVgu1Fu+ + jO7iRTwyegmzKp9tGz0BZlMGE/YyJgbSGH95irFnB5GbF5Nb3kqmqZELl2uJN5iJSS0hPMFIWGyWJ6C0 + MJXRQSNjfVpGH/vjur+Jj7dXCLM7pme+4XBOMjDsIDgihYDj+jlISW4S8qs0XA99cXWsx9m2ksFySXRW + o/RWp5Cppp3efpsw3+2ysidIMwspzErgc88ZnO3rkFuWYq/3ov+6JMb+OvOdLy6l8wcHvW9sWHre4Rca + g69i3rX3AN7bdyDlX4zD/iBCMS/hU8NChioXYC2SiFZ2Vsd2T3BVmaDA3EZTh1VkVVs3rEW6lBwrHoj7 + yu6sVQ72c+d7ltfCXH+nm5rWJ3MAdY3cpJPKCwtEE7SbgJ1bBFm9trqzu9vvspjgT3FIubZa8C/N67P9 + regHTvjvLQ3rR38AAAAASUVORK5CYII= +</value> + </data> + <metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAIAEBAQAAAABAAoAQAAJgAAACAgEAAAAAQA6AIAAE4BAAAoAAAAEAAAACAAAAABAAQAAAAAAMAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAH//j/j/jwAAf/+P+P+PAAB4iIiIiIgAAH93h3h3 + jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4 + iIiIgAAAAH//j/j39wAAf/+P+PdwAAB3d3d3dwAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMAB + AADAAQAAwAEAAMABAADAAQAAwAEAAMADAADABwAAwA8AACgAAAAgAAAAQAAAAAEABAAAAAAAAAIAAAAA + AAAAAAAAEAAAABAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/ + /wD/AAAA/wD/AP//AAD///8Au7u7u7u7u7u7u7u7RLREu7u7u7u7u7u7u7u7u7S7S7u7u7u7u7u7u7u7 + u7u7u7u7u7u7u7u7u7u7u7u0RERES7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u0RLu7u7u7u7u7 + u7u0u7S7u0u7u7u7u7u7u7u7RLtES7RLu7u7u7u7u7u7u7S7tLu7S7u7u7u7u7u7u7u7u7u7u7u7u7u7 + u7u7u7u0REREREREREu7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u7u7u0RLu7u7u7u7u0u7S7u7u7u0u7 + u7u7u7u7RLtES7u7u7RLu7u7u7u7u7S7tLu7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7RERERERE + RERERERLu0u7u7u7u7u7u7u7u7u7u7tLu0u7u7u7u0RLu7u7u7u7S7REu7u7u7u0u7u7u7u7tEu7S7u7 + u7u7RLu7u7u7u7tLu7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u7u7tERERERERERERERERERES7u7 + u7u7u7u7u7u7u7u7u7u7u7u7u7u7REu7u7u7u7u7u7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7 + u7u7u7u7u7u7tLu7u7u7u7u7u7u7u7u7u0S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7u7sAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +</value> + </data> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.Designer.cs new file mode 100644 index 000000000..a37157ebc --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.Designer.cs @@ -0,0 +1,141 @@ +namespace distribution_explorer +{ + partial class distexSplash + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(distexSplash)); + this.labelApplicationTitle = new System.Windows.Forms.Label(); + this.labelApplicationVersion = new System.Windows.Forms.Label(); + this.labelApplicationCopyright = new System.Windows.Forms.Label(); + this.labelApplicationDescription = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // labelApplicationTitle + // + this.labelApplicationTitle.BackColor = System.Drawing.SystemColors.Control; + this.labelApplicationTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 24F); + this.labelApplicationTitle.ForeColor = System.Drawing.Color.Black; + this.labelApplicationTitle.Location = new System.Drawing.Point(331, 27); + this.labelApplicationTitle.Name = "labelApplicationTitle"; + this.labelApplicationTitle.Size = new System.Drawing.Size(313, 133); + this.labelApplicationTitle.TabIndex = 0; + this.labelApplicationTitle.Text = "labelApplicationTitle"; + this.labelApplicationTitle.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // labelApplicationVersion + // + this.labelApplicationVersion.BackColor = System.Drawing.SystemColors.Control; + this.labelApplicationVersion.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelApplicationVersion.ForeColor = System.Drawing.SystemColors.ControlText; + this.labelApplicationVersion.Location = new System.Drawing.Point(302, 158); + this.labelApplicationVersion.Name = "labelApplicationVersion"; + this.labelApplicationVersion.Size = new System.Drawing.Size(320, 20); + this.labelApplicationVersion.TabIndex = 1; + this.labelApplicationVersion.Text = "labelApplicationVersion"; + this.labelApplicationVersion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.labelApplicationVersion.Click += new System.EventHandler(this.labelApplicationVersion_Click); + // + // labelApplicationCopyright + // + this.labelApplicationCopyright.BackColor = System.Drawing.SystemColors.Control; + this.labelApplicationCopyright.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F); + this.labelApplicationCopyright.ForeColor = System.Drawing.SystemColors.ControlText; + this.labelApplicationCopyright.Location = new System.Drawing.Point(59, 191); + this.labelApplicationCopyright.Name = "labelApplicationCopyright"; + this.labelApplicationCopyright.Size = new System.Drawing.Size(563, 20); + this.labelApplicationCopyright.TabIndex = 2; + this.labelApplicationCopyright.Text = "labelApplicationCopyright"; + this.labelApplicationCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // labelApplicationDescription + // + this.labelApplicationDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F); + this.labelApplicationDescription.ForeColor = System.Drawing.SystemColors.ControlText; + this.labelApplicationDescription.Location = new System.Drawing.Point(27, 234); + this.labelApplicationDescription.Name = "labelApplicationDescription"; + this.labelApplicationDescription.Size = new System.Drawing.Size(608, 29); + this.labelApplicationDescription.TabIndex = 3; + this.labelApplicationDescription.Text = "labelApplicationDescription"; + this.labelApplicationDescription.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // pictureBox1 + // + this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); + this.pictureBox1.Location = new System.Drawing.Point(27, 27); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(282, 92); + this.pictureBox1.TabIndex = 4; + this.pictureBox1.TabStop = false; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelApplicationVersion); + this.groupBox1.Controls.Add(this.labelApplicationCopyright); + this.groupBox1.Location = new System.Drawing.Point(13, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(644, 254); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + // + // distexSplash + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.ClientSize = new System.Drawing.Size(669, 276); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.labelApplicationDescription); + this.Controls.Add(this.labelApplicationTitle); + this.Controls.Add(this.groupBox1); + this.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "distexSplash"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Statistical Distribution Explorer"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label labelApplicationTitle; + private System.Windows.Forms.Label labelApplicationVersion; + private System.Windows.Forms.Label labelApplicationCopyright; + private System.Windows.Forms.Label labelApplicationDescription; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.GroupBox groupBox1; + } +}
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.cs new file mode 100644 index 000000000..9aa070845 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Reflection; + +namespace distribution_explorer +{ /// namespace distribution_explorer + public partial class distexSplash : Form + { /// Splash + public distexSplash() + { + InitializeComponent(); + this.labelApplicationTitle.Text = AssemblyTitle; + this.labelApplicationDescription.Text = AssemblyDescription; + this.labelApplicationCopyright.Text = AssemblyCopyright; + this.labelApplicationVersion.Text = "Version " + AssemblyVersion; + } + + #region Assembly Attribute Accessors + /// get AssemblyTitle + public string AssemblyTitle + { + get + { + // Get all Title attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + // If there is at least one Title attribute + if (attributes.Length > 0) + { + // Select the first one + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + // If it is not an empty string, return it + if (titleAttribute.Title != "") + return titleAttribute.Title; + } + // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name + return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); + } + } + /// get AssemblyVersion + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + //public string AssemblyGuid + //{ // error CS0117: 'System.Reflection.AssemblyName' does not contain a definition for 'Guid' + // get + // { + // return Assembly.GetExecutingAssembly().GetName().Guid.ToString(); + // } + //} + /// get AssemblyDescription + public string AssemblyDescription + { + get + { + // Get all Description attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + // If there aren't any Description attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Description attribute, return its value + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + /// get AssemblyProduct + public string AssemblyProduct + { + get + { + // Get all Product attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + // If there aren't any Product attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Product attribute, return its value + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + /// get AssemblyCopyright + public string AssemblyCopyright + { + get + { + // Get all Copyright attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + // If there aren't any Copyright attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Copyright attribute, return its value + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + /// get AssemblyCompany + public string AssemblyCompany + { + get + { + // Get all Company attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + // If there aren't any Company attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Company attribute, return its value + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + + private void labelApplicationVersion_Click(object sender, EventArgs e) + { + + } + } +} + + + diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.resx new file mode 100644 index 000000000..d12898c4c --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/DistexSplash.resx @@ -0,0 +1,384 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAARUAAABWCAYAAADhVQKUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAScwAA + EnMBjCK5BwAANsVJREFUeF7tfWuMZVd1ZhMMIWDC2JgeOwZsYgPjtN2m676qqhvTgA0Yu9vGT2wMxq92 + 26aN3UnwA2y32/mRRBoN0iQ/UDL5MUyYEYpGmow0migkSBMpihQGjYIsETkGEgti7HR3Vd1bVd0Wmpv1 + rbXX3uvsOvucfe691VXdXEtX5b73PPZe6+zvrPWtx94yHA63TD9TGdQ9A1s20X/0yL5OP4cObfkF+n/9 + vJ7+nz67z5BP6w3D4bY3DocX/+IPf3jhm+g7+sz90ssvb3/LK69sO/PVV3e+9ciR3i8fPdp627FjH/g3 + C8NdZy0O585eWmqd0+/veEe/v33rYND7t68MOue+utw679XlHb+yTJ+Vlbnzj6z03rlCnyMrnXetmA9d + 69323/I7jsPxc+fjfFwH1xvQdXF93Af3w31xf4wD48G4MD6ME+PFuDF+zEPmc/EvyvwwT50z5s8flomT + j5fXSVFj3cM0/X0KOHgGNsN/Fkzc/9eCyXCIxYeF2HrzcLj9LQok9O+3LSxcdtbi4tzZP/EgMr8VALJM + Cx6LH0AAUDi62nr3sdUdF6yuzl64utp9z8Lxzq8uLLQuOn68ddHi8ZmLjx+fu3hxsffe+MPf8++ti3A8 + zsP5ch1cr/VuXB/3wf1wX9y/359nkMG4MD6ME+NVgME8ZD6YVx64xLJbV31OQWMKGjnPwLo+hPUX929a + Cybf/Ka+lddaJtYqobf5mcPhzrfiza9AwtbIcMc7YCnAaviXf7n8fFgUAJDV1Xla8N33HCcQWGRg6L13 + aan9fjrn3/X7s5f0+71f6/c72/on6NNvXzoYtC6Tz5z5yHf4XY7DB+fNXoLr4HrH6bq4Pu4jYDN/Ae6P + cWA8Ys2QJUPjZCvGAQzmgflgXtZ6SVkuTk4KwNZqeV296Ec4IueBmh4zBZ4RHq2JnFLl6nz72+Vg8pOf + iFVCwHIm3u5wJYbkUiwtdd8OCwALFVbBysrl5MZ03gUrZAEWCFkTsDaw4LH4T5wACAA0etsHg+7lg9c6 + H1hYbs0sL/daC8vd9uJyp7NMn5WVdlc+c93Fxdke/up3+B3H4Xg5rzWD6/D16Lq4vtwHYNN+P+7PVg2N + B+MSV+pycpscwLCb1H075oN5YX6YJ+Yr84aLV3SLRE4n0SWaAsYUMHKegYkgRLOLlFonsjhudrxJ4EzU + MlEXZzgUMMHbXTiSeeJHOufCAgCQwP1YWCBLZHHm4qXj3ff1+zNkgXS2icXRvXx5ub0DIMCgsDLbo4U8 + t7TSmadr7aL//yAdewV9PkSgsLu/Sp9+78NrPvw9PjiucwXO4/P5Ot05XBfXl/u0dwjQwLqBVTNzCcaF + 8WGcGC/GjfFjHpiPWi8CmsK9CJgK77LWcoHcArhYwCbVTM5qyXmgpsdMgacZHox3dDURu/uM73yn9Ybn + n9/2xhdewBtZOBNxA/DGJjAZCpgQ73COWiX0Rn8nOIyFhe57ikAilggWNawJWBgCIO2dS6sEHqsECKu9 + D9NC/uhg0L5qcLz3scVB5xOLy+2r6ZxPLi53r1mmz9Jy91r66z/u39fI7ziufTXOw/l8Hboerovr4z58 + P7ov7i9WDUBGLJkiwMBNIi6G5qPWC+aJ+WLemD/kENyiC98EOUFekJsQuutstdQBxifv/a0tFZ+z6Lcr + zecx+n/7+dWa86uuPf2tWvanjHyaQExEKBoitmidIPrx0ktKwG7zbk4MJuAn2CoBP8KuDXgRWCQCJAQE + BCRwWch6YBBp72YAOd67CiBAVsQnBSxm9xJQXN9f6dzQX+nd2O93b6br3EKfW+m7W2nxf5q+Dx/+N77n + Dx1Hx+M8Oh/XwfXkur1POrBxQNPejXFgPBgXxhcAprMN42cXiXkYuEcl4OLdInBJrTdDThItspGiSqul + icrWHjsCqABEhpkfHHvKPPzTsa6PrnKf0DSgGOuE+YLdbwq8CUz+1tvUzRHiFWFfgMk8uTiti8gCeF// + xOwl4toQL7IgQEIcxk6yFK6AxbBA1oNYILA62nuXVrqfEvAgQCCwGKx2bx+s9u4gF+VzS4PO5+k+dxEg + 3E2L/h4CiXvp771Ly5379CP/5u/vwXE4Xs7rfo6vQ9cTEOLr34j74b64P8aB8ThLhtym9k6MFxYMxs8u + Es0H88L8ME/MF/PG/NUtglyE0C3yLSmrJXKHctU2EVCBJZILKlNAmYJq7cOZDhWXWCfO1QF/oNGc4RAE + 7PxWIV+dZcIhX3AlvV87OphxVglIVXJtmBOBSwN3pvMJuCpihbRvXCDLYnHQvX1x0PssQACAAKDoL3fv + 7y93Hugv9x5a7HcPEBg8PFjpfZE+jxBQPDpY6T66NOgepP8/yH/p3/I9/U7H4XiyVg7gfLlO935cl69P + 98H9cF/cH+PAeDAuuE0YJ8YrFkx3TniY9g7MC/PDPAVcguUCeUAuiHZBTpCXukQJq2VNdAh6qVVe2QEj + WCr7CFT+3H2+UwEwL07f/Ovz5j/V5Fr1YJbxJwiB2siOcCfBOtGITojmdM5FYtmxYzsuQHiWLRNabAMG + k9aMRGI68yBMhRvpfpx5kCUCkn77pkVyVQarnc/Q93fSQr6HFv0+Xvgr3S8MVjpfBEjQwn+O/v4+/f3v + dMz/IVD4OzrmxwQS7tNdoO+G5kP/lt8GfFz373Aeny/XwfUIfDoEON0vCNB09uH+GAfGg3FhfBgnfa7F + uJmLoXmIe9TuYn6YJ+aLeWP+kAPkIYSuRItCpChYLSJX4Vkgbw09j50wNwKoxNZHynL55qn28E/Huz4g + mAKVHHcHEYzAnQgRi7cvTHwhYeHqIJpDBCzlfYDUHJxoXYbQLZOuRICCDKUFdiW93a8mV2IveA065xb6 + 7jPkhgBI7qVFvx9WhIBI5zdpwX+N/v45LfR/oN9eo78EGD0GDfp+SJYIf+T/O/S3R3/DR/6N78OxdD8H + OrgO/z+u+w+4j7vflxhk2Jrp7se4xGXqfMZxNzdg/JgH5sMkL83PgwvNG/OHHCAPyAXyUZdIkug0BC1c + C+Q7cXdoAqByc8JaAdhM3Z/TVwbQr1qsv12l63ILOaTaF9Psi+n1GtmRcKlwJ5JrAuuk985jx2Yv5GgO + E7DtS4+RW7C46CwTgMlxARP67KW3+U3kYtxGnMZn4XawS9OHNQIXBZZD53/RIn+RFvjPACBkYRAoCHDg + L0BCLJEAMMEywXcAEAUMPVatFw8kDmzMdfV6fN/Oi3Sf/43xYFwYH8bJvAyNG+PHPDAfBheaH8AFlgvm + jflDDkLozlwM+UBOarU4IrvgDq0NPSfDznne0ARAJWWpAGymoHL6ygCAotza15qASpWFovU64vfjTbr9 + LUV3Z34rCEnU2OBtLCQsXB3klnTbRHjOgXxdCJbJdUSE3kRWxW0EDM4qgWsDTqTzDAHG/6SF/CNnOTjw + IADwVkVwaQYEKAMGG7FSADL4S+4LHS8f/rf7f3xvj7PnR64S3w+ABPAKwNX5EcaHcTInQy6SWC/kHtF8 + MC+yXK4zlssVmD/kAHlALpAP5AR5QW6S31J0hyDntTzLGMAyAVCBm1NG3LamoHLagipSCazOK61S+3rL + AhTKPUF0B0V0sbsDrgCEJOpp8DZGJASujktQo5Bw9yOIniCSgjc6Fp9wJUS29tvk3sAq6f4eLdzndWGr + K2MWMwOHWCcOJBRAvKXiwAS/w6JhwAkf/JuBSkHHnCdARL+56/N9/PFi4RTHxEDzPMYt1kv7IcyHuReA + C82TI0c0b8wfRDTkwdm7JB/ICfISIhdci0SI1B2CnCWaFoedRwSWCYBKiqydWimnr5UCst6CSmXqgIJK + DqAwIUu5Fa9QXQuiFouL2wruDorxhDux1glI2PbuhUHvY4iYuFwShIE/J5EbAhOKxNDi/S/k0vyTuCkE + BHBViPugN74DBnFzxMIAUMgCx18FDAUPsWQENNRaUSCYnZ0tfM/HwRLha1ngMdcHyDBHI/eTa8v4ME5x + vXCNzj/xPGg+mBeDC83ThaeRA0OEbu9jkAcyd73VQvISriV2h7adLbVEktMimbg2n2UEYJkAqJRZKTCN + p6By+srAuj7Qf2WSowMVm3Zvktosh4IHGg+2AorwJxIqFjKWU+qpQA8h1cXFFtLnP4iICEKvHM0hAnZx + 0CbOhKM4D+LNTovwv9L/HxEXQxYuWxBugfO/1e1wYGIBwFsb7ny2aBwI6HXwF2CiH/u9nB8sEAYkZ8HY + +zCYKG/DXI5aMDLeYDkxwBzBvNhyoXlivpg35g85OJfoo2y1kJwgL8gN4edA4rbOg3zBszQFlsq0/jFB + JZUIV+ljTwHnlAbcWOdH6/QJUPH9Twq9TxKAAkKW+oqgzwjzJ5SWzqHi4+33i7vTayGlXULEvavYOum3 + b6S39+3EQdxF5OZ+cgUoh6T7H2jBvcTuCQOHLlq88WGhKJiopeIWsT82uDDetXHujuVExHUJFghbKu7f + 9q9YSOE4AR4HMBibAxHvOmGMajlx5MmN3xHHwgN1XsI8MV/MG/OHHCAPZOxCPpAT5AW5QX7HSY6QJ+Qq + PMv2rZD3UU6Wq7ZYDon++AWRZG3HBJXYDFarZRr5+fmxUmqt0pKGSlFBoLFQDKAgHMr1OuBPToA/6W1H + VinMeiSDMXey1LsOWa/0G6yTeykx7Qu0sA7RwvxbBRMhP9V9KPIVCgjWmsCiVpdHCVtEgMT9UCJWQMAD + k7pB9J26P4XfDWjIuFx0yLtFwssUrCALTEr6em5GI1Oe0/lbzBvzhxwgD8gF8mGuheSFCJFk5fa2Q57C + s7TeDTk3AhZpjJUGljFBJRX5mabnn56gUpY+UBlOjnkUSbCyFgrIQefyeEBBduyOX0ESF8Ki/ROUe0LR + DLQQoEWyi8lYqplxqfSflszX7v0uUe2PKRy8KmRnyCvhBesjK4EY9dEbjew4t0ijQbLIg8sEsGFeRPNU + 3HneUnFukPyb+JDoWHFxii5YIIjddV0+jOdrFMwUdJh3kZC0nSfmTQD6x5AD5AG5gGuBnCAvIXF7u5CR + K9EhymnhsPOOCwRY5kssliJ5a3qzpLvJjQkqsW+tlsq0kPD0AxVE8+DqxBxa0iqF321AhXkUZG5Ktey2 + NyKMKVEH4lAiC0UB5QgI2dcIUKR6GPwJ5Z10r0G9DL2BP7O8inyTHnEn3Sdoof0/dTFgYQgn4SwKtyCF + BJUkNW956GJ1xKxGZnxUx7kpGgnykRp/nnF/DKgUXaBg5fB1nCvkXR22ejS3JeS46L1kvAApk//i5qeu + nV4XcoA8IBfIB3KCvCA3yE+iQ+0u5ArCuwgsRVcI+tFwM/TmerMUUvrX8CtjgkrZQ1brY9f54NPfNx3n + kgIUAEzSKo0BRfugPO/6xiI/AuFMifIIh2ItFADKMSqgQ8YokYsfRJEdeALOO6GiPI7srHQP0Fv392mR + HpVsV+cOuKQ1tU7EUlGOArkmIRlNrBH5TVwfzRUxRGkEIGvyTIwlpJxK6TElQORD23pvBhixstSKEQ7I + jR8RIWu1GI7F5LkcZbmQfCRC1LsDchOepX0V5Am5okCxFFgceSthfZd5y3qDlckVzjGwBIplDFCJcxX0 + DRb72Hjo4pYI+Df4mPXMZcH4cA+Y55r5af9iDOuVoHey7437YS6YE/KGUvOFvHGslUmdDHDNspeH6rs0 + ylfNo6DmRBLbkIeCsPHLjpS1FgoABZ3U0OAIrQjIbN9Di+Rmyir9HL2F99GCABn7P2jh/X99W0vI1pGf + JhSsJO2Sy5T1XIoL4cpbXklU5TuUi5Hvw4INoOOBzLhWDCouelMGLIWojrGkMG5P+sJFslYWcy9wvQAu + IUQd8ltk3gKejpgmuUA+kBPkxXIj+UGOkCfkCvnGwALyFvqAXiStXxs/hVoh7cli64Q8qowBKqnIDx5Y + uD/4W/Uw6kOJwkMs/kmFoDGuVEJeWfgbY5wUsXyy7w05I9KWWzWO42KdxLLXHjmQCXRTd+0yAPPfferB + ZzryAAqPgiI21Jy87DJlkYClYWOJ8rQuQlm/WChzXTz4kn/CNTu3IJuUFirxJwgV9/7KR1QYFJDTEcLF + yqME66PoOviMV09+OrBQgPAEr/AxGorm6yL71fAlFjx89MfwLnq851M8CBn3zACTumaFjF1jufg5OevK + cz9ODiF5juuS/kpCz+BZSH6QI8kTcoV8IWfIG3KH/KEHhPGhF+gHGc3QF/RmixBNsyclbSUiNAaopEha + JMPFDy7+jQcNQJNKlsP341guWGApjgcgo5ZJCuzGuf9G3LtM/gABzA+/AeAAGACdKnCP3ZcmrS3qAGd4 + w4NPvNfyKJJc1Xrzq9TnA53KpDAQdTyddyHMeYKjPN3L1eXBG1UBBRmktDD204L5Ei2q7zGIcPKahowd + V+He1jYXhRed5qOwFaCWiQGa2Brx7pBLx3cgIuRokUfR6BL+CqiE8HHheD3PWSIxgRxbQ2x1qVukIXAH + PoXIlYsiSaKd5rRIoaNwMd3vQW4sPwMskG9whbqXQ/7QA/QBvUA/0BP0ZZPjlF+JidtxQSXnDZmyQvAg + p/iYUYAFi6fsegCTMtIYb+MyawbXaHr/jbg3gMMuaIy7ytrDfHMzn21rC7U4UhYLvk9YKs9965r7nvuW + WimohA3ELKqNW29DDQpSxqUHCrrXIw8FHdkQ5QEpCw4FLg9CxgIotOiepL+Ue2IXdqjV4YiIW7iW1NRM + VQUDy2PIInSLV/NCNERc4EBMApuCko8WCcgUEuDMGO14C5Ela+1oVIjBLeStWCuIk/c078aNwc+Tz7eh + auFlzJxfcvLzwMKuEMkZ8paoUG879CAJcihEREo/Gm0jh2U3p/NDj9CnbU1ZcIPGsFRSVoEtMsPDnHJr + UuQfFkjVefH14gWm989xqcqABQsl9/4bce84rJsLhJhTDA4Amhy3M6XrNXxMRM6a8LHwKEVidn6r1PLM + XohMTyRmcVEghT0lStHZQ02L1OUBoDxGi+QfAyHrXBJ+GztS1QOK4UFMZqq++W14ueDWRNZIDELRIg08 + TAQumuQWA0LMsdgaH72XuFcRh+OtEwdszvJSfibkuBhyGYSuO89YQP9I/0+RIQboO1m+JGeRN8LNyGNB + ghwyb5HSP3c+h5pLiNuwiZlP5Rc3aAxQqTJ9cxY0HuZU8lxuL5aUtZR7fyy0MgsnJyN4o+4dA0PuXCHv + 2LXJlXPKfSpYdWXRHg0fw+1B5zH454FHQXLb/AVSy9O+VDJl2zuRdo+mRAvU1xXkouSgsOn+A13UftHy + onGREk1Gc2FjjaB4N8FETDyZqRmuxi0pA5IyMEl9lwMkZQRuDDA8bgUXZ7kUrq3zceHmkJ2rRLJEi0JV + tSeYfwB5Qq6QL+QsTaAg9/ZO6AH6kFqheZfDYvgVaTLONUKi32I0aFRQgUuRApXKZKiSN2PKtK5LoEsB + UtP7p8ChKtdmo+5dlnyWY2noMTG5nkNQp6J80H/h3mVWinV70BMFHciUR0E5PhOzFDpGbYqk3lOmLBK1 + OA+FskIR5Vnp/ToRsH+vFoqv31Guwbk8mkqv/IkNu3pORXmTCExil6Rs0ae+awJC+dcNrlYBXJQbMn8t + L+NlwPxLyNLVuiG1WGjMfw+5Up8WigqRnCFvyB1tK0kPXCvErSqJuCU9eX6F9Ac9ptygcSyVVGOmUVpI + plyIKmsBb8hUJCfXddEFkZpLCpw28t5lJGoTUIlfBnXhZFw7FeUruE4WUEI7SIr2oHObcXssj4L9bKR9 + ASW3Sej4Q5x6jwxQStji/Arq70pk43clYS2Qo97dcfUxEiqW3yWsvDbHRAsHNWojC9wkmpW4MPkgUAwz + NzlvDc9TGEcAFx/NKkSJ4nYLzu3TuiEjFxuuZnmSXFm+JGeWt8idUvpJDxxq7l4O/UBPll9BXhHcWOgV + +oUbZNtRjmqppCIEOW5DvAhSi7oqiS5FOua8eeP7Zy0a81beyHuXcRtN5hzPNSfzOUvXABWzWbrjUkDm + aRr+zrdatwcdydBACP774qIQsxI6Rq0KNVRClTES21a6fyqhYpdyr1wCA4Ka90X3hxPFLPEaRXU089ST + tRGY1Lkva3iRApnbLHEuZeWsda1CBGoNp8QyiYskpUxAuCMHuCb8LPJkoP5TSZBDlTPk3ruO9cDVzSBu + 0Y+l+z7oS1L5xQ2SLv22B0vYT2hUUEnlgTR5wFMmubVAyqyOlOuB85paKVVv4jXmfQUHdDLujbGmCFNY + VTlzt6CSm/mcsiS9ruvIWVf5StEDRHs658KcRmr4Edp/B42bUSAIf16yZSnSs0o1K9wvFpmy3Z/59HPf + +8SBBvMFIfM0ZMLabFTtUaJ1NSZqVAEmSVcnASC5lskafifjet5CMy6b1P7E1pEBXo1OKbAwyEpWroSZ + PUhBviRnkjfkTvKXrFviV7gfS2sGeoK+1A2CHiUaFLJtLWk7Kqik3tZ1PEiZqV61j1DZ9VIcTG21bCLS + 0eT+G3lvyK4ujK/5OJhTDsjkuE4pIPO6KQcVDjl6clbS8DXagzaQzu2hDmVoKIT+H9iaAn1YEZmgB/1Z + WgADXVA2VDv9/9C3ZRxZeGtI5Pwsyx3yJz2wPkgv6CCnbpCEmUM0iJPiDGmrIeZRQSVF0uaY0/GDXGV5 + xKBSBQCjWEl1loq9/0beO8eqK9MJQBBAlMOdpACmUtf1VsruM5WcRZYmp+G7aI+Ej5GPwub29dwPRXmU + FYn0eLJRIzuaR6Kcic0otSSmkrjGErBvfFlQRYumNLKSYUnkWilVx1VZMDrOePx6PVurVAiVO3kUyVuX + caxy85XOXYoICb/CemB9iBsEPWk0SCqaW+dxUhzv4YycI6kNUmtlFFBJLa5cczp3i4+yYrWUKV5Z2FaT + i1GVQWpBZSPvbWVWlx+UAgEATFNLMhXl87qutFKQis+1PXNna5IbsjWxjQS6vkuTairHd26Pa7BE/VC6 + fyLZso6Y5dR7197RRTQK2aQ2VOzJWkPsrnFzNg+Y5PIzclxx3BZkuCaoRA6FDncepKXZk8+LcbwLy136 + 0dwlqfzkjkI/pCfp0j9DafyBtIVeoV+k8Ic2lLvPGAVUUpbFqO5HlUkfL4KqWpQcU77smNz7b+S97bir + smNr0+ZrMm9zSWzWdRzxCX1StGCQrBSk4tMG4svD1nlovMzkLO1Pg+xNdL3naAPtw8OtEDkhq3OYFs+K + 8ijKmfjmSCZiI1EeIRyLC04AJZ8EbViNfBKsl9hyqZuL/G5BxxGxkqLvq501tB661Vl+pbci8kfnPG5N + SXpBM+3OFZxtS3qT7vxkrZA+oVfZFL5orYwCKqk3e9P8EH2Aq968MS+QWjS5maFloFK1y6I9fiPvXTbu + uurhKoDJLUWo1HXaSrnwTVwwGFkp2JoTuQ/o8g4SENtoSF1P79PSY5U28uKaHrg9oWDPhn59ToYjLeOt + NDi0zICStkYm4a5M4hq+n+0EQEo2MkM4PZq31gS5uqEYYOQckbcLx38PeuAev2jwxIWHpCfuGteaYf2R + HjXEXLRWpKHTKKCSAoFROY0qc90upipOIzcztGxx5tx/I+9dZYFpiwVYWzkVxan2FKl7JKN8pgGT66uB + rEpkV6qVsq3ApbCVQqnf2P8XDYKwARaaVSPpirvBc5Pq7h9JVEIARepY3JvW1bxoOLXAI7hISFw1HKyV + zQswTXqvrAWyokWm8y2LDNnvfPc551LxZmmeY2K3CHp40HXpp6Q40hP0RXqD/qBHtlYK3EqIBI0CKqmU + 7ab+eh1JGue8nGyi1N5/I+/dxK1r0rYgJzqUjPKVWSnX3vfcX/Bn33N/ecvDTz+Mt9hPXcGgcCnOSpFU + fOwcuJce4NuWV6mnqnSF/4knJX0OiiMWlSvxqfjOpNewapy4xotkLQ8xCQtjktcYD1RcDopabdbiUXnY + sHNcT6QuIp+vxYfsDkEPj4heSD/QE9cGIYVfrBXlVqBftlZcJAjFhk1BJTtlO7NQrYr8jCMW67Gwq0ha + W1OzkfeOwbcJIQ4ZjvMSSFlxBT4FtR/7v3Jwq81y/uxvPPl5RAg44qNcChLdYKVQxqaELGkTLK4+Zivl + 69qoWsv3OULjojiWmI35Bpuv4clLQ2xaPqKKm5gkWOReqymolM8lZBPb39e2UQgAvUaurneMds5z+niQ + 9SPbrJK+xFrxCXGRtcJZttRzpSmopBbXKOn5WCypN2HZ9Zrkk+S+3VP3jxfuRt4bc4nBL3d+OC5VVlBn + WabOe3Ft4eDuM246cOgTFlSe+o8PULRgO1chI80bkQOp7wlcirwF2Uo5SEDyUyVnpU2B+vpR/Yp7G/vF + 6I5NgcUoyWa5gDCJ45qCSm60KHAlxQQ528FOqqFFvsE90qgQ9NE7KPpBpq3jVkh/Uhc0c4mk7yNvZfvW + heFlZ6HnCjaCawoqqTf7KJGf1EOLt2NZ5W2VlVS3QMoWYVVRZMwPbeS9MfaY22gCKqmkuTqZJaN8Za7P + 3v2Hn7SgIjU+lD3L3dzmLuY8B0r75taQHPFBoptwKQQi1AFfWyCGfiihj6xrPOQaIHmC0/Q+GacgcBLg + MOo1xgWV9H3X7vMc8lq02xw4K5fezwAjtVBqrdDfbwRuBfsqcV0QtaCEHtuXQq/QrxQbdt+OmiAQ9E1B + JRV+HYWkTZGAVZGcFBnZpPxfF2RqLql+Kpvp3nWAEINOWX1VHaeSeoE8VgSVm1+P8vc9+w7/oYLKnvsP + f/ufqUYEvU6PUU8O2QQM3dx6s5QHQdtEUOOlfpsjPthOgt6EP/Zmt/PtmTxkK8RFJXxPFCmw0z6wksRW + XcyH39dv8Y5eSOjnMWL0J2feGkIO4OO2X9U+Ky4fyG/3wfJ2OxGQXtx2H/dAX6K37kegR86yJb1Cv9Az + 9C3h5W1nNgWVVOSn6aKucieqwp2jVDSXvdWrrKTUgt3Ie8fcRlMQjwEiJwRfCipX3/Pc/Q5U/JYbiPpc + c99v/UBBhVyhr/aH81uPUOewEEZGrxQ0X6IsTaqGpTqTO5APQSb2V/khdm9J7Wgfck9cFbHfvgLhTwGJ + smhPnCCmi2kzgkrcJW5Ua6d4XjHpT90grdD2xxa2A5GcltBCIehD9IP0/c4drDfOsu3tkp4rEl6GnqHv + 4XAXFxo2BZUUcdekOjnVGCnl9lhQqM3wzCCIq5LHqhbrRt27DICbupuxlZUDSqWgQhbJVQZUuBr5hgPP + FPiUzz/25N0wibH7HVLyuRKZCL5jqCXhXinUFIizNlGF3PtrbYfI3eRNUyLb8Z7DpdptnqwYLEjlYHIW + 42YElZxxj3+MdYN0o3n3ne11q/skOTlLzgqH9/+aq5hFXzdDf6xHR9hKI6eiC9QEVKo4CABCTkJV1YLO + tXZqq2ZrgCXlduUA40bcO8Vt5NZZxefntussBZVr9x2+JYAKclN2n0Eh5L9QK4X60v6QM2h5y1K0N0Dh + YOcDSPWmt91HQfgJQYteKejmptmzyEuJ0tBd9MdU1EqClrNUdMHVuQHjuhnjL+zxXKRR71+IBDm5FWWm + IFMcn+rBheQpy7b7mNMXE7asR+gTeiX9Qs/QN2fYUj1QE1BJ9T1R6wUmdV1P2knwEqMCExZhKtqTmw28 + EfdOcRs5LkxZH+Dc4sIUmH3NgkpM0N726NOPoBoZJnHITSHXZ7W3i/p1fJyIvhtQCUsP6QPkl3+DMznV + FHeRCK1XUT5AEt1CQ2f8rh3rUwsup3o3PjfnnNPlGHY5OZPWAIpm1xp9QD/QE+sLFcykP+gR+lQXCHpm + F4j0vrCw66wmoFL2cMccS9k2F7oHUKqKtinpqGHSFEDB4rBv8ao9iPDWzl1k6oZhoZ7Me1eVMeC31G4B + ZfrKtQYx16SbStYIeJVf2LPvuSdsxAcEbSgexJYbFPU50b7U1flQBq24PvSGE9dnuft9IgK9y+O7xJtG + 1Z43MWQmvrN76+S8yX9e3Z/YWvGWSkRwa22V7jqg7SdZP6Qn2QkyuEDIsGW9kn6hZ9nSQxLhmoBK7Dao + X14WRQG44PeqBZHbWCgVPsVDX3V9LPyq1HWMuy4CshnuXbaHUgzQkAPkrTsPxr+PAp51Gc+FcRHQfPf3 + /vOdFyxRA59XKeFN0/KPoVUkoj5cjdzZI93FvOvzmt1SQh54hJQlAsH/jlpIaiPnpiDR9PgcoDq1jgl7 + OXPETEHaR84iufvOeVwq8RpcVWk7yfrbA31Cr9Cvpu1D79B/E1CxW2XG/ENucRsWOY7N5QNy8jFg6eS2 + A9DNtiZ1/5NxbwsQKrsm88U5o4KnAktlXRFS83/na3e9E/40Qovwrxeooc8SbUyFknl6i1FnN2wK1r2e + itU46kNvwj8scCW6VSfCyDDJ3V9b46NbaYwSIj7VQGWSxYYFHiVK1fdJb5HctVDTJCSSvlC9TFEg0iP0 + Cb1yQiPpGfrWdpNNQCV3geMhjj9YfJNayFXWA+5Tdn+4ODlEcs4cy46xNTfx/ce9t71eHAmDO3Oy5N2C + 20Ofx/GB67OHEt5ue/TJOTTpQYd16UG7PfApJ9AlH6Fk6nfKCW+9GyUtn1oXDjrfDqa47uZnd/WLtih1 + QKOA0nTRnWqgMmlyudD02smywKfovtMaZTNRILZsWF+9h1h/vNMBNSjnBk4UWiY9B15l+9ZJg8qoi3J6 + Xt6mXhsqpzjpTauSsV0D8hOUTzlC/vWiZtFK3xTyv7H9Axr/9O4mYvZhelB/pAV/7Mfrg25J2TgpzPdI + KW5Vemq5IfmRoMkDoQkvlybchY3pvU7CLgY/gt5Yf6RH1qfyKrxHUOBVpqByCizmjNybkwI2tmM+tmQA + qKAqVTcJ09R85C0cp/yFo7SFJnqc9ld7H5am1tw3BbUkvy5+enEbUd09UOpTtOZHOsJb16fACYyYjXoq + ANEkQaVgqfhcIKly1jYToXFTpBfWE/MqtE9Q916nR+oKR3s0kX6hZ+hb81WmoDIFlSxAKuvy5vbT5YZM + qPsASYeqZOnwJqn5Lp+BOuXPUn5D93ZazPcTYPz7UGMinfE1vOk5lKhzG0cjTmMAKQO5SYKKvb4tKmSA + BlnrCNuCHrSfja9ght5ot0jSI+uTO+4jXwX7A2H/ZemxMgWVKag0BhXddB1dvtCbFCXvsuF66xzUgWjS + myVp6Q13PeU5EEnbeUAK1QRM/O57nDOh4JJ2bzREys2c16G7W1OuZj0tnkmBCneFc4BcmSho5C8VzA7I + A7igwBD5KnewPh1Zy/2GXRIc9D8FlSmojAAqkkkLUEH/jFeoiAyRH2w0JZm03ff0T8xesrA8O8P1Psd7 + H0O/U6lKBtnX+TNdjL5g0D7EriS/YJlElkuTbNqmC39Si7npfcuS8ca9RhmIWMvEu5Lqijo9qMVo21OK + 3rA/EOkR+iS9Sh3Q7Az0Db1D/1NQmYLKWKAi2zPAUiFQGe54B/dPcV3eOPKzaiM/tFlVn3fD+y6Zzq7s + XnJTAoBomwNDaJptOKQGKJ/sHGVR1oFK3e+j3LMMUCZtNYl1J7KLs2ltMWHgrFQv9FesmO+y/gbYdMxF + gEi/HAFCcSF32p87fwoqU1AZG1QknLyLwsmuMpk3Xe9sW8B+MeiYz13DkEnbw9YPiPy86CM/vu2hbBvB + iwtukVYt+yStUH07iUVbdY060Kj7fb3HN+71xVKxdVZaYGgqwjX5zbXkdGD0IvTHeiR9ut61V7CeoW/S + OxpiT0FlCiojgQp6qLzwgjS5tqCCh4q3yESYEeFktCBcbnM4md5od2PDKoryvBz29NGmTKE5E2fNRj1S + 4kbX4y6sn2dQ8ZaKsfhY3oV+v6IPjdAJUd55GfqDHqFPp1fSrzRtgt6noDIFlCxAQUh7TWMmCie/QJ3z + kaPCoEK9NNAEWXJUZkLND7c76F5DD+Gt0pQJDa57fR8y9pZKSWFb/NAb8z2nMnlU4CmzRKoKCfU+p1Kx + YSloWyA3AKMhZ+iNG2Jj+w7Sp+gVW9ZKDRD0Dv1PLZUpsGQBS1XiG3qTAlRQUKaJb0e1yfUqHjp6+FY6 + t9LDeS+FHx+lh3NV34B4Gxa3jJA3puVNQnGb3WS9agfC8TiXOvem7vdRwWzS5/lIGVscEgFiTsp9Cg3D + TcWyRn5ULxJ25lyVVegPeoQ+Wa+kX9m6g3rmUALcKKBSlgafW1eCNPk4pXw9U+e10hZjHqUSOrXY9HpN + /673XO14rZxtFXac1p8FKGWWis+mpUbHNpsW1ap4uAKozO6mh/DaRbQjlMQ3gMrP0LMjPLSS4OYXVez6 + +N+KSVnrEQHK6cZ2qoHKWjmJHONu+3HLCQ77O9CXHiu9n0F/0KPTJyXAzXpQ0WrlppYKFgYWk61Mzl2w + WuWM4jQ86DgvF5CyH36TfYqFpf1TmnZKq6ovQoGfFibaxatVu1qhrb/pvHN7towy1/gcW+ho9QP9aaOp + nO5vel3Wt2vQRG0kw8Zh6J6+BlQWkU2r3d56HxZQwW53CirakMlEekwCln24y7Y7XU/XJ8da2AygMkpk + KMgtpOPHYXuev9NFob2ka6AVQIX1ee2xPrJqnaVCesdLpSmo6EOmZfZYYDkPJ96QCkQ5x+curJz+ILlj + zLknwBAAVQaGWk1c1p9FASbnHpM6RvuplAFO0w3teW7aRyUGlVsfeYY3DpNN2E9tSyUHVDbLMXXgFoNv + DCqbxVKxoKKd4Oq2HLVbc+b0oW2yqOre/toCMwd8cu4bN4DSc2yrzbJqbHUbc+4xqWN0K9T4etrRrUnV + +D4HKK9DcyYLKnd+6YmdtxConE6cymYBjbpx5IKKcCh1nEpwQU82p2JBRRdS3UZi2s9De4Dkukt1iwv3 + r3NrtGn0pO6ZAlDbnLps3JPmdepkg98hmzL5pCyYymumoj977z/8n+78zS/vPZ2iP3WLebP8XgcqdpyW + tBXiNepLaxpiSa6Q+505Fb+v9bpGf9SFUR4h9daDlaLugLoHOQsi5xjtdlZ17EgLKFEVjDmmXDe9Twrk + NgJUUm5fCmyagQrlqdz0haevhlvUOE9lZXPnqWwW0KgbRxNQia8V5/1k5amQ3tYrTwVknwKFWh+pPq+6 + CNWqqWvWjOOwAKsiJfhN74vr64ItOweWhb2nEs1NTH9dbADIFLFcR8ZWnavjzyWtc47XfY3K9IIXgXUb + tcGUjWbFY7nyuv2HLtKG1/d9+alzXH/ao9jvB5bKPU88cf2Dz3zppj/51s2cWXkqZ9TWLea6xLlxFnuT + e496n/qMWin2DBaND9+vW0at7WSmb+iyN7guYCzKOv5FI0rw95V/gFsVA4X+pqCCxaEkaJmLA0DBgteo + B8ahm5ZPkjDWKFPuNbFowXngg3FjTBhniiNqerzKO5afbt9qxwmA1XaRav0p6CovA5L2cQUV7vrmml6j + N+2NDx166tYvPn3otkefOpxd+8N5D6a2xCe6bXztT5OFXXbsqIu96X2b3meU2p+wYfv61v7YB1If3pTv + bjmYlDmOBxhvz5hMxQOd2qNGw6J1bhLuicUav7Fzz6+7vv6url0Od6PbZpRZEZBj3P+36fEYU5PIjzYQ + T42d+aLiJmI3v/7A4cfege+vf+DZr5xuVcpNF3d8fN1ir/s95/45+TRl3In/znAq2n6Cf4uqlGU/a1eE + uI5VyvFbDgsKi98uwNiFUfcgFW7VxW+voQuj7GHH4qtzpdQFKCNX1dLJBY2q4+wWqnUujAJoauMynbNa + GE2P13HGbl8M7jpOtRCrxs1juunAU2fbnQlveOjZj8v3h26feD8V7aRfUo283v1UchZ03TF1oFH3e931 + m/6e3U/FVy+7vjYnsZ9KbOKr6Wx5ivgYdQ+q9qiJH2y1JsrOAYjV7SioodMyINPtOyYBKmqtxcBadm3N + 1UlxRrE72fR4vae6ffEYbJgZ96qLnuF8Pifu/KbuzwPPPH7JtPNbMZJSBxp1vzcFjabHr+38JpmzuM5G + dX6LASO2QrDIYiCoi/xoZEU5ErxBFYjihaGkbx1/oQs0laiWs6ByQKcu8mOvUSeHGFSaHm/dsTL5qIUH + nam1Vkda+2iR7VFLXMofwFJp3KN29fTvUTtKQeLJKkbUBk3aaBzujWYtZ/WoJf1NukdtWWjULgQs4Phh + 1hyO1CIGkJRtdgVrouycstwTLIx4ceDcMutBz68DpRxA0XyQnKzdOjnYa6mccd0q8CvL/anKzdHrQU8K + znUWn5+btVYo6vMtfIauUhmp+vd9+fFP2axalMPr7oS13fRtbkTK/TlFuunXWSJ1vze1PPKPT3fTV0JW + c1T8fkCumz4Bzrp104dLES9eu1jwe2wZqBtS9vCm6lA0SqHnWBdGQcyOo2xcKVDS8Uwqy1bdv7rr6SKu + AgmtKwLAND1eQTCVMVuWXazuVYqkLZxjQQVWCm3M/ge2p8otDz99aHL7/hQ7v3Eylumzst7d3/IX6lrX + p64uZyNApX7fHyFppbNe2IdJ5YB9f+jFQPs1mX1/tOvbmPv+lIU8FQCwIKqI2DLLIGXeK0+h59hzyyIb + 8bV1TGXjVSCbVNVwk8gPAChFMJcR002Pr4r8qEwtgNQBVyE0HYMKeBXtU/vw4Ucuve3Rr9Dm7MUdCrGD + XdYOhdic3exMWLdD4aiLfjOclwKVOjAad+wF10cjOlqtHO9QWNg+hXXzR3T//QQufodC6qC/c9wdCjWf + oYyjqHr4lRuJ34a68GMXRXMyFKRilyrmSsoyXatcnElGfnTRYaw57hLGhfnGssC/tXo7jqI1OR7nQt5l + 1lAqjK7yKLO0CgAegcpRApXf1Y76yFU5mXsp+72W17lf7bgLuen562fFbK69lLUyV9/IeMjjhxbEn10o + eo4CioadcZ59eHEcFpOer8lpujh072W70BR0NFHLWimabavlA9YFijcvx9jqChLLgEKJS12MKhe9F76v + ywjGfOF6YOwYQ9Vm9bhWzvG4hpW3yhrytmO181ag0TngOC0AVU4Kv+GcfVu2bEFBIRcVog0CcSr/F8By + 3f5nv3z344/tOnKk98u2Whn9NdARTHmVRexqt4JetZ27Vla6B8jc/j6a/+ANyjvikdkdCMTgVsTNrm2K + +Ua3QWgKGnXH14FK3e/x9a18CnKL6n+UrLV6kEJEBqPvs75Ib9Af61F3JyT9ah8V8GnQf23rgyE9QdPP + VAYEKPxfZQe4qAE29tflLuvcVb+3a3HQ/Til79NWHb3PEtA8QP75N/ro06ENr+EClRS2yWIITbGld6r5 + 7jSyVupAo+73ctAyBK1Lv+fN3ArkuPRREfmbBtggaklPrC/SG/QHPUKf0Cv0G/ZRnt+KBuhTwJiCZtYz + kAYVs/8PbSqG/X+Whq1zZP+f2QuxyRS94T7AO9mt0o52y+29BAi30UN6H70VH6NuYiv6NpXuYsZC0QxP + RxyGzE738LtjTydrpQ406n4vyM9kzYZojshXQZnJ2QiUVQ/oI4wWktAT9AW9sf6gR96ZkPTqNhGDvqF3 + 6D/rgZpaKlNLpRxUtvhNxYZD2lNZtz9d6r6dHrhzsbfuIu2xO/Bd4NAEW1wgemBhSh+gbM+/4baS/HAH + V8jvXujepvJWlbog/nuaWiuj5LhUu1SRleLkZ60Ulr/fu1r0EPTR+xvoyemLXZ9jaGZO3d5Yr2YPZeyl + je1vp6AytVSyngEFFcurgFvRjdqRr0J9a7m15JCaYPeH81uxXcPCAiqWnQuE3QoHtKvdSvdT9LajLVAp + mrDS+yqb4urO+I3DuCdqcHvUJFeQccdpE+fw9i1aO3Ucxmb7vc4SqfsdMis2vNZ+KKZHinVxGEBE1rZ9 + pLdkWD+kJ9IX6w36410J3QZipF/oGfqG3qH/rAdqaqlMLRUDKmu36zB7AGG3wmO0W+E/U2gZ++oegwt0 + XDZrp4dvljah+sjSUmcPJcZ9Wrbs6HyRHuAf+2pYV8DGW3gwcAhIhA3azT7LrpFQnftT9/tmAZacIkEL + KnZeMdjg3/53klP4XaJA2koS8mU5a6sDB+RuB4MfQz+yJQc1Lme9dT8CPfKm7KRX6Bd6hr6hd+h/CipT + SyXrGUiDSrULdJRcII4C8WZTvLnYFeQafaK/0r5R9lbuPEgP/38rWCuOC5AKWWmRwHkrNtPW5bScrm5Q + CujqLRXlpKzbU7RSxN1Rohsg46w7Zy2q1ej08qDsnUz6gt5If6JHifpAv3B11fWBC5z1QE0tlamlUgEq + 1LMWZG3rDZyyTy6Q7AN0GW2Dup1cINpbeQFRoJlLOFFqqTO/MOhcqYQtPeBEAPYOkh//UzW5xUIJkQgN + hQZrpZhti99T1shmzbydlHWUmh+H6ePojiNlg5UikR6VdeidwrwK6aN3UPQjBC3rjfQHPUKf0Cv0Cz1D + 39A79D8FlamlkvUMWFApCy3rNqgvvTT3S2iFwFGgJUSBWucdW91xAb3J3jc4Idt2SI4D9lfu3YS0b4os + wFr5OlsreIOCP1HXxoGLXzxajm8iFoVNsbyVA+CRN7AFnFPFFUqBTvlcXFFgNNe4W36hb4oDHS9XJ3cD + LF9nvSAtn/TE+iK9MUFLeoQ+oVfoF3qGvqF36D/rgZpaKlNLpRpUxAV6/vltb7RVy0iEwlaoIPJCzkpr + BundZDJfSQ+qhJe5crl3kEAFPVBd5EE3snL70GhaOT/8UV1QnNvi3siSNKfXG2/XwklZFpO6TqgoFmJ2 + jcWiMoo2aSsAjc9LMXJi+bMeDopeEP4nPbGV0t65sNya0dwU6BX6hZ6R+Pjyy9vfAv3/K8WJNkqxisLA + AAAAAElFTkSuQmCC +</value> + </data> + <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAIAEBAQAAAABAAoAQAAJgAAACAgEAAAAAQA6AIAAE4BAAAoAAAAEAAAACAAAAABAAQAAAAAAMAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAH//j/j/jwAAf/+P+P+PAAB4iIiIiIgAAH93h3h3 + jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4iIiIiIgAAH93h3h3jwAAf3eHeHePAAB4 + iIiIgAAAAH//j/j39wAAf/+P+PdwAAB3d3d3dwAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMAB + AADAAQAAwAEAAMABAADAAQAAwAEAAMADAADABwAAwA8AACgAAAAgAAAAQAAAAAEABAAAAAAAAAIAAAAA + AAAAAAAAEAAAABAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/ + /wD/AAAA/wD/AP//AAD///8Au7u7u7u7u7u7u7u7RLREu7u7u7u7u7u7u7u7u7S7S7u7u7u7u7u7u7u7 + u7u7u7u7u7u7u7u7u7u7u7u0RERES7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u0RLu7u7u7u7u7 + u7u0u7S7u0u7u7u7u7u7u7u7RLtES7RLu7u7u7u7u7u7u7S7tLu7S7u7u7u7u7u7u7u7u7u7u7u7u7u7 + u7u7u7u0REREREREREu7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7u7u7u0RLu7u7u7u7u0u7S7u7u7u0u7 + u7u7u7u7RLtES7u7u7RLu7u7u7u7u7S7tLu7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u0RLu7RERERERE + RERERERLu0u7u7u7u7u7u7u7u7u7u7tLu0u7u7u7u0RLu7u7u7u7S7REu7u7u7u0u7u7u7u7tEu7S7u7 + u7u7RLu7u7u7u7tLu7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u7u7u7u7u7tERERERERERERERERERES7u7 + u7u7u7u7u7u7u7u7u7u7u7u7u7u7REu7u7u7u7u7u7u7u7u7u7S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7 + u7u7u7u7u7u7tLu7u7u7u7u7u7u7u7u7u0S7u7u7u7u7u7u7u7u7u7u0u7u7u7u7u7sAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +</value> + </data> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/IconToolkit.ico b/src/boost/libs/math/example/dot_net_example/distribution_explorer/IconToolkit.ico Binary files differnew file mode 100644 index 000000000..bfd8035cc --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/IconToolkit.ico diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Program.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Program.cs new file mode 100644 index 000000000..3a44ac763 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace distribution_explorer +{ + static class Program + { + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new DistexForm()); + } + } +}
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/AssemblyInfo.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1f6d55db5 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Statistical Distribution Explorer")] +[assembly: AssemblyDescription("Shows most properties for 31 Statistical Distributions (mean, mode, median, variance, skewness, kurtosis, range).\n Calculates probability distribution function (PDF), cumulative distribution function (CDF), quantiles, and complements, and upper and lower critical values for given risk levels (alpha).")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Boost 1.52")] +[assembly: AssemblyProduct("Statistical Distribution Explorer")] +[assembly: AssemblyCopyright("Copyright © John Maddock & Paul A. Bristow 2007 - 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a8cd54bd-81b1-4bd3-be18-2cd56fffa1f1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.1.52")] +[assembly: AssemblyFileVersion("1.0.1.52")] +[assembly: AssemblyInformationalVersion("From Boost 1.52")]
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.Designer.cs new file mode 100644 index 000000000..cb5a05a2a --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace distribution_explorer.Properties { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("distribution_explorer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap ToolkitLogo { + get { + object obj = ResourceManager.GetObject("ToolkitLogo", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.resx new file mode 100644 index 000000000..0eba41ff7 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="ToolkitLogo" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\ToolkitLogo.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.Designer.cs new file mode 100644 index 000000000..14afa0d78 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace distribution_explorer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.settings b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile> diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/app.manifest b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/app.manifest new file mode 100644 index 000000000..a78d4c9ae --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Properties/app.manifest @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <applicationRequestMinimum> + <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" /> + <defaultAssemblyRequest permissionSetReference="Custom" /> + </applicationRequestMinimum> + </security> + </trustInfo> +</asmv1:assembly>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/Settings.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Settings.cs new file mode 100644 index 000000000..d5d2b0732 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/Settings.cs @@ -0,0 +1,28 @@ +namespace distribution_explorer.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/ToolkitLogo.bmp b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ToolkitLogo.bmp Binary files differnew file mode 100644 index 000000000..c712ff58b --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/ToolkitLogo.bmp diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/boost.png b/src/boost/libs/math/example/dot_net_example/distribution_explorer/boost.png Binary files differnew file mode 100644 index 000000000..461cf27b2 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/boost.png diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.Designer.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.Designer.cs new file mode 100644 index 000000000..5d05ce647 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.Designer.cs @@ -0,0 +1,190 @@ +namespace distribution_explorer +{ + partial class distexAboutBox + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + this.logoPictureBox = new System.Windows.Forms.PictureBox(); + this.labelProductName = new System.Windows.Forms.Label(); + this.labelVersion = new System.Windows.Forms.Label(); + this.labelCopyright = new System.Windows.Forms.Label(); + this.labelCompanyName = new System.Windows.Forms.Label(); + this.textBoxDescription = new System.Windows.Forms.TextBox(); + this.okButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel + // + this.tableLayoutPanel.ColumnCount = 2; + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F)); + this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0); + this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0); + this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1); + this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2); + this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3); + this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4); + this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); + this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel.Location = new System.Drawing.Point(12, 11); + this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4); + this.tableLayoutPanel.Name = "tableLayoutPanel"; + this.tableLayoutPanel.RowCount = 6; + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel.Size = new System.Drawing.Size(556, 326); + this.tableLayoutPanel.TabIndex = 0; + // + // logoPictureBox + // + this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.logoPictureBox.Image = global::distribution_explorer.Properties.Resources.ToolkitLogo; + this.logoPictureBox.InitialImage = global::distribution_explorer.Properties.Resources.ToolkitLogo; + this.logoPictureBox.Location = new System.Drawing.Point(4, 4); + this.logoPictureBox.Margin = new System.Windows.Forms.Padding(4); + this.logoPictureBox.Name = "logoPictureBox"; + this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6); + this.logoPictureBox.Size = new System.Drawing.Size(175, 318); + this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.logoPictureBox.TabIndex = 12; + this.logoPictureBox.TabStop = false; + // + // labelProductName + // + this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelProductName.Location = new System.Drawing.Point(191, 0); + this.labelProductName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelProductName.MaximumSize = new System.Drawing.Size(0, 21); + this.labelProductName.Name = "labelProductName"; + this.labelProductName.Size = new System.Drawing.Size(361, 21); + this.labelProductName.TabIndex = 19; + this.labelProductName.Text = "Product Name"; + this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelVersion + // + this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelVersion.Location = new System.Drawing.Point(191, 32); + this.labelVersion.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelVersion.MaximumSize = new System.Drawing.Size(0, 21); + this.labelVersion.Name = "labelVersion"; + this.labelVersion.Size = new System.Drawing.Size(361, 21); + this.labelVersion.TabIndex = 0; + this.labelVersion.Text = "Version"; + this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCopyright + // + this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelCopyright.Location = new System.Drawing.Point(191, 64); + this.labelCopyright.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 21); + this.labelCopyright.Name = "labelCopyright"; + this.labelCopyright.Size = new System.Drawing.Size(361, 21); + this.labelCopyright.TabIndex = 21; + this.labelCopyright.Text = "Copyright"; + this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCompanyName + // + this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelCompanyName.Location = new System.Drawing.Point(191, 96); + this.labelCompanyName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0); + this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 21); + this.labelCompanyName.Name = "labelCompanyName"; + this.labelCompanyName.Size = new System.Drawing.Size(361, 21); + this.labelCompanyName.TabIndex = 22; + this.labelCompanyName.Text = "Company Name"; + this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // textBoxDescription + // + this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxDescription.Location = new System.Drawing.Point(191, 132); + this.textBoxDescription.Margin = new System.Windows.Forms.Padding(8, 4, 4, 4); + this.textBoxDescription.Multiline = true; + this.textBoxDescription.Name = "textBoxDescription"; + this.textBoxDescription.ReadOnly = true; + this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBoxDescription.Size = new System.Drawing.Size(361, 155); + this.textBoxDescription.TabIndex = 23; + this.textBoxDescription.TabStop = false; + this.textBoxDescription.Text = "Description"; + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.okButton.Location = new System.Drawing.Point(452, 295); + this.okButton.Margin = new System.Windows.Forms.Padding(4); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(100, 27); + this.okButton.TabIndex = 24; + this.okButton.Text = "&OK"; + // + // distexAboutBox + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(580, 348); + this.Controls.Add(this.tableLayoutPanel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Margin = new System.Windows.Forms.Padding(4); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "distexAboutBox"; + this.Padding = new System.Windows.Forms.Padding(12, 11, 12, 11); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "About Statistical Distribution Explorer"; + this.tableLayoutPanel.ResumeLayout(false); + this.tableLayoutPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.PictureBox logoPictureBox; + private System.Windows.Forms.Label labelProductName; + private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label labelCopyright; + private System.Windows.Forms.Label labelCompanyName; + private System.Windows.Forms.TextBox textBoxDescription; + private System.Windows.Forms.Button okButton; + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.cs b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.cs new file mode 100644 index 000000000..b8aa9249e --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; + +namespace distribution_explorer +{ + partial class distexAboutBox : Form + { + public distexAboutBox() + { + InitializeComponent(); + + // Initialize the AboutBox to display the product information from the assembly information. + // Change assembly information settings for your application through either: + // - Project->Properties->Application->Assembly Information + // - AssemblyInfo.cs + this.Text = String.Format("About {0}", AssemblyTitle); + this.labelProductName.Text = AssemblyProduct; + this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion); + this.labelCopyright.Text = AssemblyCopyright; + this.labelCompanyName.Text = AssemblyCompany; + this.textBoxDescription.Text = AssemblyDescription; + // URL http://sourceforge.net/projects/distexplorer + } + + #region Assembly Attribute Accessors + + public string AssemblyTitle + { + get + { + // Get all Title attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + // If there is at least one Title attribute + if (attributes.Length > 0) + { + // Select the first one + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + // If it is not an empty string, return it + if (titleAttribute.Title != "") + return titleAttribute.Title; + } + // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name + return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); + } + } + + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + public string AssemblyDescription + { + get + { + // Get all Description attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + // If there aren't any Description attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Description attribute, return its value + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + public string AssemblyProduct + { + get + { + // Get all Product attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + // If there aren't any Product attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Product attribute, return its value + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + + public string AssemblyCopyright + { + get + { + // Get all Copyright attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + // If there aren't any Copyright attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Copyright attribute, return its value + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + + public string AssemblyCompany + { + get + { + // Get all Company attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + // If there aren't any Company attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Company attribute, return its value + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + } +} diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.resx b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.resx new file mode 100644 index 000000000..d58980a38 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distexAboutBox.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution.txt b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution.txt new file mode 100644 index 000000000..f99b6b2e8 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution.txt @@ -0,0 +1,10 @@ +Statistical Distribution Explorer +Version 1.0.1.52 +Company Boost 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) +Copyright Copyright © John Maddock and Paul A. Bristow 2009, 2010, 2012 +Product Distribution_Explorer +Title Distribution_Explorer +Mean +MeanParameter 1 0 +Parameter 2 1 + diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj new file mode 100644 index 000000000..591341b0b --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{77742493-4236-4975-9BD9-AA3611F0DC0E}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>distribution_explorer</RootNamespace> + <AssemblyName>distribution_explorer</AssemblyName> + <ApplicationIcon> + </ApplicationIcon> + <IsWebBootstrapper>false</IsWebBootstrapper> + <ManifestCertificateThumbprint>393B9B4A721C946375D6D44F80492CFFA03E57B5</ManifestCertificateThumbprint> + <ManifestKeyFile>distribution_explorer_TemporaryKey.pfx</ManifestKeyFile> + <GenerateManifests>true</GenerateManifests> + <TargetZone>LocalIntranet</TargetZone> + <SignManifests>false</SignManifests> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + <OldToolsVersion>3.5</OldToolsVersion> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <TargetFrameworkProfile>Client</TargetFrameworkProfile> + <PublishUrl>\\hetpA\H%24\Distex\</PublishUrl> + <Install>true</Install> + <InstallFrom>Unc</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <SupportUrl>http://sourceforge.net/projects/distexplorer/</SupportUrl> + <ProductName>Statistical Distribution Explorer</ProductName> + <PublisherName>hetp</PublisherName> + <ApplicationRevision>8</ApplicationRevision> + <ApplicationVersion>1.0.1.8</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + <CreateDesktopShortcut>true</CreateDesktopShortcut> + <PublishWizardCompleted>true</PublishWizardCompleted> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <UseVSHostingProcess>false</UseVSHostingProcess> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants> + </DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + <DocumentationFile>bin\Release\distribution_explorer.XML</DocumentationFile> + <UseVSHostingProcess>false</UseVSHostingProcess> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x64\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x64</PlatformTarget> + <UseVSHostingProcess>false</UseVSHostingProcess> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <OutputPath>bin\x64\Release\</OutputPath> + <DocumentationFile>bin\Release\distribution_explorer.XML</DocumentationFile> + <Optimize>true</Optimize> + <PlatformTarget>x64</PlatformTarget> + <UseVSHostingProcess>false</UseVSHostingProcess> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Deployment" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="distexAboutBox.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="distexAboutBox.Designer.cs"> + <DependentUpon>distexAboutBox.cs</DependentUpon> + </Compile> + <Compile Include="DistexForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="DistexForm.Designer.cs"> + <DependentUpon>DistexForm.cs</DependentUpon> + </Compile> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <EmbeddedResource Include="distexAboutBox.resx"> + <SubType>Designer</SubType> + <DependentUpon>distexAboutBox.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="DistexForm.resx"> + <SubType>Designer</SubType> + <DependentUpon>DistexForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="DistexSplash.resx"> + <SubType>Designer</SubType> + <DependentUpon>DistexSplash.cs</DependentUpon> + </EmbeddedResource> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Resources.resx</DependentUpon> + <DesignTime>True</DesignTime> + </Compile> + <None Include="app.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <Compile Include="DistexSplash.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="DistexSplash.Designer.cs"> + <DependentUpon>DistexSplash.cs</DependentUpon> + </Compile> + <Compile Include="Settings.cs" /> + </ItemGroup> + <ItemGroup> + <Content Include="IconToolkit.ico"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <None Include="ClassDiagram1.cd" /> + <None Include="ClassDiagram2.cd" /> + <None Include="ToolkitLogo.bmp" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client"> + <Visible>False</Visible> + <ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.2.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 2.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.0"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.0 %28x86%29</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Visual.C++.10.0.x86"> + <Visible>False</Visible> + <ProductName>Visual C++ 2010 Runtime Libraries %28x86%29</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.4.5"> + <Visible>False</Visible> + <ProductName>Windows Installer 4.5</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\boost_math\boost_math.vcxproj"> + <Project>{cee4bad0-967a-4193-9edb-c0dd6c3b05c9}</Project> + <Name>boost_math</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj.user b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj.user new file mode 100644 index 000000000..395652714 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.csproj.user @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectView>ProjectFiles</ProjectView> + <PublishUrlHistory>\\hetpA\H%24\Distex\|\\hetp7\H%24\Distex\|\\hetp7\H%24\|I:\boost-sandbox\libs\math_functions\dot_net_example\Distex\|publish\</PublishUrlHistory> + <InstallUrlHistory>\\hetp7\H%24\</InstallUrlHistory> + <SupportUrlHistory> + </SupportUrlHistory> + <UpdateUrlHistory> + </UpdateUrlHistory> + <BootstrapperUrlHistory> + </BootstrapperUrlHistory> + <FallbackCulture>en-US</FallbackCulture> + <VerifyUploadedFiles>false</VerifyUploadedFiles> + <EnableSecurityDebugging>false</EnableSecurityDebugging> + <ErrorReportUrlHistory /> + </PropertyGroup> + <PropertyGroup> + <ReferencePath>I:\boost-trunk\libs\math\dot_net_example\boost_math\</ReferencePath> + </PropertyGroup> +</Project>
\ No newline at end of file diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.sln b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.sln new file mode 100644 index 000000000..6e3c90178 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.sln @@ -0,0 +1,50 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2024 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "distribution_explorer", "distribution_explorer.csproj", "{77742493-4236-4975-9BD9-AA3611F0DC0E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boost_math", "..\boost_math\boost_math.vcxproj", "{80E5F29C-93FB-4C84-A818-D2B8263C7CA1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Description = Statistical Distribution Explorer + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|x64.ActiveCfg = Debug|x64 + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|x64.Build.0 = Debug|x64 + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Debug|x86.Build.0 = Debug|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|Any CPU.Build.0 = Release|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|x64.ActiveCfg = Release|x64 + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|x64.Build.0 = Release|x64 + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|x86.ActiveCfg = Release|Any CPU + {77742493-4236-4975-9BD9-AA3611F0DC0E}.Release|x86.Build.0 = Release|Any CPU + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x64.ActiveCfg = Debug|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x64.Build.0 = Debug|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x86.ActiveCfg = Debug|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Debug|x86.Build.0 = Debug|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|Any CPU.ActiveCfg = Release|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x64.ActiveCfg = Release|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x64.Build.0 = Release|x64 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x86.ActiveCfg = Release|Win32 + {80E5F29C-93FB-4C84-A818-D2B8263C7CA1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E7B27F35-B063-4E0E-AA07-9A53BEA22670} + EndGlobalSection +EndGlobal diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.suo b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.suo Binary files differnew file mode 100644 index 000000000..d2c71687f --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/distribution_explorer.suo diff --git a/src/boost/libs/math/example/dot_net_example/distribution_explorer/readme.txt b/src/boost/libs/math/example/dot_net_example/distribution_explorer/readme.txt new file mode 100644 index 000000000..d483173d7 --- /dev/null +++ b/src/boost/libs/math/example/dot_net_example/distribution_explorer/readme.txt @@ -0,0 +1,86 @@ +Statistical Distribution Explorer + +Paul A. Bristow +John Maddock + +Copyright © 2008 , 2009, 2010, 2012 Paul A. Bristow, 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) + +A Windows utility to show the properties of statistical distributions using parameters provided interactively by the user. + +The 31 distributions provided (by version 1.0.1.52) are: + + * bernoulli + * beta + * binomial + * cauchy + * chi_squared + * exponential + * extreme_value + * fisher_f + * gamma + * geometric + * hypergeometric + * inverse_chi_squared + * inverse_gamma + * inverse_gaussian + * laplace + * logistic + * lognormal + * negative_binomial + * non-central beta + * non-central_chi_squared + * non-central_F + * non-central_t + * normal (Gaussian) + * pareto + * poisson + * rayleigh + * students_t + * skew_normal + * triangular + * uniform + * weibull + +Properties of distributions computed (where possible) are: + + * mean + * mode + * median + * variance + * standard deviation + * coefficient of variation, + * skewness + * kurtosis + * excess + * range supported + +Calculated, from values provided, are: + + * probability density (or mass) function (PDF) + * cumulative distribution function (CDF), and complement + * Quantiles (percentiles) are calculated for typical risk (alpha) probabilities (0.001, 0.01, 0.5, 0.1, 0.333) and for additional probabilities that can be requested by the user. + +Results can be saved to text files using Save or SaveAs. All the values on the four tabs are output to the file chosen, and are tab separated to assist input to other programs, for example, spreadsheets or text editors. + +Note: Excel (for example), by default, only shows 10 decimal digits: to display the maximum possible precision (about 15 decimal digits), it is necessary to format all cells to display this precision. Although unusually accurate, not all values computed by Statistical Distribution Explorer will be as accurate as 15 decimal digits. Values shown as NaN cannot be calculated from the value(s) given, most commonly because the value input is outside the range for the distribution. + +For more information, including downloads, and this index.html file, see Distexplorer at Sourceforge. + +This Microsoft Windows 32 package was generated from a C# program and uses a boost_math.dll generated using the Boost.Math C++ source code containing the underlying statistical distribution classes and functions (C++ was compiled in CLI mode). + +All source code is freely available for view and for use under the Boost Open Source License. + +Math Toolkit C++ source code to produce boost_math.dll is in the most recent Boost release, currently 1.52.0 (and the Boost version used to build the explorer is embedded in its version number). You can download the current Boost library and find the source to build the Distribution Explorer at /libs/math/dot_net_example/. + +Installation +============ +Statistical Distribution Explorer is distributed as a single Windows Installer package setupdistex.msi. Unzip the distexplorer.zip file to a temporary location of your choice and run setupdistex.msi. + +(If the program installs OK, but does not run, it will be necessary to run setup.exe to install Microsoft redistributables. This is because .NET Framework 4.0 Client Profile and VC Redistributable X86 are requirements for this program. Most recent and updated Windows environments will already have these installed, but they are quickly, easily and safely installed from the Microsoft site if required. This program has been tested on Windows 200 up to Windows 8). + +(The package cannot be run on other platforms at present but it should be possible to build an equivalent utility on any C/C++ platform if anyone would like to undertake this task.) + +Last revised: 15 Oct 2012 + diff --git a/src/boost/libs/math/example/double_exponential.cpp b/src/boost/libs/math/example/double_exponential.cpp new file mode 100644 index 000000000..c225f8646 --- /dev/null +++ b/src/boost/libs/math/example/double_exponential.cpp @@ -0,0 +1,59 @@ +// Copyright Nick Thompson, 2017 +// 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) + +#include <iostream> +#include <cmath> +#include <boost/math/quadrature/tanh_sinh.hpp> +#include <boost/math/quadrature/sinh_sinh.hpp> +#include <boost/math/quadrature/exp_sinh.hpp> + +using boost::math::quadrature::tanh_sinh; +using boost::math::quadrature::sinh_sinh; +using boost::math::quadrature::exp_sinh; +using boost::math::constants::pi; +using boost::math::constants::half_pi; +using boost::math::constants::half; +using boost::math::constants::third; +using boost::math::constants::root_pi; +using std::log; +using std::cos; +using std::cosh; +using std::exp; +using std::sqrt; + +int main() +{ + std::cout << std::setprecision(std::numeric_limits<double>::digits10); + double tol = sqrt(std::numeric_limits<double>::epsilon()); + // For an integral over a finite domain, use tanh_sinh: + tanh_sinh<double> tanh_integrator(tol, 10); + auto f1 = [](double x) { return log(x)*log(1-x); }; + double Q = tanh_integrator.integrate(f1, (double) 0, (double) 1); + double Q_expected = 2 - pi<double>()*pi<double>()*half<double>()*third<double>(); + + std::cout << "tanh_sinh quadrature of log(x)log(1-x) gives " << Q << std::endl; + std::cout << "The exact integral is " << Q_expected << std::endl; + + // For an integral over the entire real line, use sinh-sinh quadrature: + sinh_sinh<double> sinh_integrator(10); + auto f2 = [](double t) { return cos(t)/cosh(t);}; + Q = sinh_integrator.integrate(f2); + Q_expected = pi<double>()/cosh(half_pi<double>()); + std::cout << "sinh_sinh quadrature of cos(x)/cosh(x) gives " << Q << std::endl; + std::cout << "The exact integral is " << Q_expected << std::endl; + + // For half-infinite intervals, use exp-sinh. + // Endpoint singularities are handled well: + exp_sinh<double> exp_integrator(10); + auto f3 = [](double t) { return exp(-t)/sqrt(t); }; + Q = exp_integrator.integrate(f3, 0, std::numeric_limits<double>::infinity()); + Q_expected = root_pi<double>(); + std::cout << "exp_sinh quadrature of exp(-t)/sqrt(t) gives " << Q << std::endl; + std::cout << "The exact integral is " << Q_expected << std::endl; + + + +} diff --git a/src/boost/libs/math/example/error_handling_example.cpp b/src/boost/libs/math/example/error_handling_example.cpp new file mode 100644 index 000000000..24543cdfa --- /dev/null +++ b/src/boost/libs/math/example/error_handling_example.cpp @@ -0,0 +1,153 @@ +// example_error_handling.cpp + +// Copyright Paul A. Bristow 2007, 2010. +// Copyright John Maddock 2007. + +// 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) + +// Note that this file contains quickbook markup as well as code +// and comments, don't change any of the special comment markups! + +// Optional macro definitions described in text below: +// #define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error +// #define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error +// #define BOOST_MATH_DOMAIN_ERROR_POLICY is set to: throw_on_error + +//[error_handling_example +/*` +The following example demonstrates the effect of +setting the macro BOOST_MATH_DOMAIN_ERROR_POLICY +when an invalid argument is encountered. For the +purposes of this example, we'll pass a negative +degrees of freedom parameter to the student's t +distribution. + +Since we know that this is a single file program we could +just add: + + #define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error + +to the top of the source file to change the default policy +to one that simply returns a NaN when a domain error occurs. +Alternatively we could use: + + #define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error + +To ensure the `::errno` is set when a domain error occurs +as well as returning a NaN. + +This is safe provided the program consists of a single +translation unit /and/ we place the define /before/ any +#includes. Note that should we add the define after the includes +then it will have no effect! A warning such as: + +[pre warning C4005: 'BOOST_MATH_OVERFLOW_ERROR_POLICY' : macro redefinition] + +is a certain sign that it will /not/ have the desired effect. + +We'll begin our sample program with the needed includes: +*/ + + + #define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error + +// Boost +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; // Probability of students_t(df, t). + +// std +#include <iostream> + using std::cout; + using std::endl; + +#include <stdexcept> + + +#include <cstddef> + // using ::errno + +/*` +Next we'll define the program's main() to call the student's t +distribution with an invalid degrees of freedom parameter, +the program is set up to handle either an exception or a NaN: +*/ + +int main() +{ + cout << "Example error handling using Student's t function. " << endl; + cout << "BOOST_MATH_DOMAIN_ERROR_POLICY is set to: " + << BOOST_STRINGIZE(BOOST_MATH_DOMAIN_ERROR_POLICY) << endl; + + double degrees_of_freedom = -1; // A bad argument! + double t = 10; + + try + { + errno = 0; // Clear/reset. + students_t dist(degrees_of_freedom); // exception is thrown here if enabled. + double p = cdf(dist, t); + // Test for error reported by other means: + if((boost::math::isnan)(p)) + { + cout << "cdf returned a NaN!" << endl; + if (errno != 0) + { // So errno has been set. + cout << "errno is set to: " << errno << endl; + } + } + else + cout << "Probability of Student's t is " << p << endl; + } + catch(const std::exception& e) + { + std::cout << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +/*` + +Here's what the program output looks like with a default build +(one that *does throw exceptions*): + +[pre +Example error handling using Student's t function. +BOOST_MATH_DOMAIN_ERROR_POLICY is set to: throw_on_error + +Message from thrown exception was: + Error in function boost::math::students_t_distribution<double>::students_t_distribution: + Degrees of freedom argument is -1, but must be > 0 ! +] + +Alternatively let's build with: + + #define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error + +Now the program output is: + +[pre +Example error handling using Student's t function. +BOOST_MATH_DOMAIN_ERROR_POLICY is set to: ignore_error +cdf returned a NaN! +] + +And finally let's build with: + + #define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error + +Which gives the output show errno: + +[pre +Example error handling using Student's t function. +BOOST_MATH_DOMAIN_ERROR_POLICY is set to: errno_on_error +cdf returned a NaN! +errno is set to: 33 +] + +*/ + +//] [error_handling_eg end quickbook markup] diff --git a/src/boost/libs/math/example/error_policies_example.cpp b/src/boost/libs/math/example/error_policies_example.cpp new file mode 100644 index 000000000..289d1016b --- /dev/null +++ b/src/boost/libs/math/example/error_policies_example.cpp @@ -0,0 +1,105 @@ +// error_policies_example.cpp + +// Copyright Paul A. Bristow 2007, 2010. +// Copyright John Maddock 2007. + +// 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) + +#include <boost/math/distributions/normal.hpp> + using boost::math::normal_distribution; + +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; // Probability of students_t(df, t). + using boost::math::students_t_distribution; + +// using namespace boost::math; causes: +//.\error_policy_normal.cpp(30) : error C2872: 'policy' : ambiguous symbol +// could be '\boost/math/policies/policy.hpp(392) : boost::math::policies::policy' +// or 'boost::math::policies' + +// So should not use this 'using namespace boost::math;' command. + +// Suppose we want a statistical distribution to return infinities, +// rather than throw exceptions (the default policy), then we can use: + +// std +#include <iostream> + using std::cout; + using std::endl; + +// using namespace boost::math::policies; or + +using boost::math::policies::policy; +// Possible errors +using boost::math::policies::overflow_error; +using boost::math::policies::underflow_error; +using boost::math::policies::domain_error; +using boost::math::policies::pole_error; +using boost::math::policies::denorm_error; +using boost::math::policies::evaluation_error; +using boost::math::policies::ignore_error; + +// Define a custom policy to ignore just overflow: +typedef policy< +overflow_error<ignore_error> + > my_policy; + +// Define another custom policy (perhaps ill-advised?) +// to ignore all errors: domain, pole, overflow, underflow, denorm & evaluation: +typedef policy< +domain_error<ignore_error>, +pole_error<ignore_error>, +overflow_error<ignore_error>, +underflow_error<ignore_error>, +denorm_error<ignore_error>, +evaluation_error<ignore_error> + > my_ignoreall_policy; + +// Define a new distribution with a custom policy to ignore_error +// (& thus perhaps return infinity for some arguments): +typedef boost::math::normal_distribution<double, my_policy> my_normal; +// Note: uses default parameters zero mean and unit standard deviation. + +// We could also do the same for another distribution, for example: +using boost::math::students_t_distribution; +typedef students_t_distribution<double, my_ignoreall_policy> my_students_t; + +int main() +{ + cout << "quantile(my_normal(), 0.05); = " << quantile(my_normal(), 0.05) << endl; // 0.05 is argument within normal range. + cout << "quantile(my_normal(), 0.); = " << quantile(my_normal(), 0.) << endl; // argument zero, so expect infinity. + cout << "quantile(my_normal(), 0.); = " << quantile(my_normal(), 0.F) << endl; // argument zero, so expect infinity. + + cout << "quantile(my_students_t(), 0.); = " << quantile(my_students_t(-1), 0.F) << endl; // 'bad' argument negative, so expect NaN. + +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + // Construct a (0, 1) normal distribution that ignores all errors, + // returning NaN, infinity, zero, or best guess, + // and NOT setting errno. + normal_distribution<long double, my_ignoreall_policy> my_normal2(0.L, 1.L); // explicit parameters for distribution. + cout << "quantile(my_normal2(), 0.); = " << quantile(my_normal2, 0.01) << endl; // argument 0.01, so result finite. + cout << "quantile(my_normal2(), 0.); = " << quantile(my_normal2, 0.) << endl; // argument zero, so expect infinity. +#endif + + return 0; +} + +/* + +Output: + +error_policies_example.cpp + Generating code + Finished generating code + error_policy_normal_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\error_policies_example.exe + quantile(my_normal(), 0.05); = -1.64485 + quantile(my_normal(), 0.); = -1.#INF + quantile(my_normal(), 0.); = -1.#INF + quantile(my_students_t(), 0.); = 1.#QNAN + quantile(my_normal2(), 0.); = -2.32635 + quantile(my_normal2(), 0.); = -1.#INF + +*/ diff --git a/src/boost/libs/math/example/error_policy_example.cpp b/src/boost/libs/math/example/error_policy_example.cpp new file mode 100644 index 000000000..37cb51633 --- /dev/null +++ b/src/boost/libs/math/example/error_policy_example.cpp @@ -0,0 +1,93 @@ +// example_policy_handling.cpp + +// Copyright Paul A. Bristow 2007, 2010. +// Copyright John Maddock 2007. + +// 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) + +// See error_handling_example.cpp for use of +// macro definition to change policy for +// domain_error - negative degrees of freedom argument +// for student's t distribution CDF, +// and catching the exception. + +// See error_handling_policies.cpp for more examples. + +// Boost +#include <boost/math/distributions/students_t.hpp> +using boost::math::students_t_distribution; // Probability of students_t(df, t). +using boost::math::students_t; // Probability of students_t(df, t) convenience typedef for double. + +using boost::math::policies::policy; +using boost::math::policies::domain_error; +using boost::math::policies::ignore_error; + +// std +#include <iostream> + using std::cout; + using std::endl; + +#include <stdexcept> + + +// Define a (bad?) policy to ignore domain errors ('bad' arguments): +typedef policy< + domain_error<ignore_error> + > my_policy; + +// Define my_students_t distribution with this different domain error policy: +typedef students_t_distribution<double, my_policy> my_students_t; + +int main() +{ // Example of error handling of bad argument(s) to a distribution. + cout << "Example error handling using Student's t function. " << endl; + + double degrees_of_freedom = -1; double t = -1.; // Two 'bad' arguments! + + try + { + cout << "Probability of ignore_error Student's t is " + << cdf(my_students_t(degrees_of_freedom), t) << endl; + cout << "Probability of default error policy Student's t is " << endl; + // By contrast the students_t distribution default domain error policy is to throw, + cout << cdf(students_t(-1), -1) << endl; // so this will throw. +/*` + Message from thrown exception was: + Error in function boost::math::students_t_distribution<double>::students_t_distribution: + Degrees of freedom argument is -1, but must be > 0 ! +*/ + + // We could also define a 'custom' distribution + // with an "ignore overflow error policy" in a single statement: + using boost::math::policies::overflow_error; + students_t_distribution<double, policy<overflow_error<ignore_error> > > students_t_no_throw(-1); + + } + catch(const std::exception& e) + { + std::cout << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + + return 0; +} // int main() + +/* + +Output: + + error_policy_example.cpp + Generating code + Finished generating code + error_policy_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\error_policy_example.exe + Example error handling using Student's t function. + Probability of ignore_error Student's t is 1.#QNAN + Probability of default error policy Student's t is + + Message from thrown exception was: + Error in function boost::math::students_t_distribution<double>::students_t_distribution: Degrees of freedom argument is -1, but must be > 0 ! + +*/ diff --git a/src/boost/libs/math/example/f_test.cpp b/src/boost/libs/math/example/f_test.cpp new file mode 100644 index 000000000..f7fabdee3 --- /dev/null +++ b/src/boost/libs/math/example/f_test.cpp @@ -0,0 +1,250 @@ +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2007, 2008, 2010 + +// 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) + +#ifdef _MSC_VER +# pragma warning(disable: 4512) // assignment operator could not be generated. +# pragma warning(disable: 4510) // default constructor could not be generated. +# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required. +# pragma warning(disable: 4180) // qualifier has no effect (in Fusion). +#endif + +#include <iostream> +using std::cout; using std::endl; +using std::left; using std::fixed; using std::right; using std::scientific; +#include <iomanip> +using std::setw; +using std::setprecision; + +#include <boost/math/distributions/fisher_f.hpp> + +void f_test( + double sd1, // Sample 1 std deviation + double sd2, // Sample 2 std deviation + double N1, // Sample 1 size + double N2, // Sample 2 size + double alpha) // Significance level +{ + // + // An F test applied to two sets of data. + // We are testing the null hypothesis that the + // standard deviation of the samples is equal, and + // that any variation is down to chance. We can + // also test the alternative hypothesis that any + // difference is not down to chance. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda359.htm + // + // Avoid "using namespace boost::math;" because of potential name ambiguity. + using boost::math::fisher_f; + + // Print header: + cout << + "____________________________________\n" + "F test for equal standard deviations\n" + "____________________________________\n\n"; + cout << setprecision(5); + cout << "Sample 1:\n"; + cout << setw(55) << left << "Number of Observations" << "= " << N1 << "\n"; + cout << setw(55) << left << "Sample Standard Deviation" << "= " << sd1 << "\n\n"; + cout << "Sample 2:\n"; + cout << setw(55) << left << "Number of Observations" << "= " << N2 << "\n"; + cout << setw(55) << left << "Sample Standard Deviation" << "= " << sd2 << "\n\n"; + // + // Now we can calculate and output some stats: + // + // F-statistic: + double F = (sd1 / sd2); + F *= F; + cout << setw(55) << left << "Test Statistic" << "= " << F << "\n\n"; + // + // Finally define our distribution, and get the probability: + // + fisher_f dist(N1 - 1, N2 - 1); + double p = cdf(dist, F); + cout << setw(55) << left << "CDF of test statistic: " << "= " + << setprecision(3) << scientific << p << "\n"; + double ucv = quantile(complement(dist, alpha)); + double ucv2 = quantile(complement(dist, alpha / 2)); + double lcv = quantile(dist, alpha); + double lcv2 = quantile(dist, alpha / 2); + cout << setw(55) << left << "Upper Critical Value at alpha: " << "= " + << setprecision(3) << scientific << ucv << "\n"; + cout << setw(55) << left << "Upper Critical Value at alpha/2: " << "= " + << setprecision(3) << scientific << ucv2 << "\n"; + cout << setw(55) << left << "Lower Critical Value at alpha: " << "= " + << setprecision(3) << scientific << lcv << "\n"; + cout << setw(55) << left << "Lower Critical Value at alpha/2: " << "= " + << setprecision(3) << scientific << lcv2 << "\n\n"; + // + // Finally print out results of null and alternative hypothesis: + // + cout << setw(55) << left << + "Results for Alternative Hypothesis and alpha" << "= " + << setprecision(4) << fixed << alpha << "\n\n"; + cout << "Alternative Hypothesis Conclusion\n"; + cout << "Standard deviations are unequal (two sided test) "; + if((ucv2 < F) || (lcv2 > F)) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Standard deviation 1 is less than standard deviation 2 "; + if(lcv > F) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Standard deviation 1 is greater than standard deviation 2 "; + if(ucv < F) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << endl << endl; +} + +int main() +{ + // + // Run tests for ceramic strength data: + // see http://www.itl.nist.gov/div898/handbook/eda/section4/eda42a1.htm + // The data for this case study were collected by Said Jahanmir of the + // NIST Ceramics Division in 1996 in connection with a NIST/industry + // ceramics consortium for strength optimization of ceramic strength. + // + f_test(65.54909, 61.85425, 240, 240, 0.05); + // + // And again for the process change comparison: + // see http://www.itl.nist.gov/div898/handbook/prc/section3/prc32.htm + // A new procedure to assemble a device is introduced and tested for + // possible improvement in time of assembly. The question being addressed + // is whether the standard deviation of the new assembly process (sample 2) is + // better (i.e., smaller) than the standard deviation for the old assembly + // process (sample 1). + // + f_test(4.9082, 2.5874, 11, 9, 0.05); + return 0; +} + +/* + +Output: + + f_test.cpp + F-test_example1.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\F_test_example1.exe + ____________________________________ + F test for equal standard deviations + ____________________________________ + + Sample 1: + Number of Observations = 240 + Sample Standard Deviation = 65.549 + + Sample 2: + Number of Observations = 240 + Sample Standard Deviation = 61.854 + + Test Statistic = 1.123 + + CDF of test statistic: = 8.148e-001 + Upper Critical Value at alpha: = 1.238e+000 + Upper Critical Value at alpha/2: = 1.289e+000 + Lower Critical Value at alpha: = 8.080e-001 + Lower Critical Value at alpha/2: = 7.756e-001 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Standard deviations are unequal (two sided test) REJECTED + Standard deviation 1 is less than standard deviation 2 REJECTED + Standard deviation 1 is greater than standard deviation 2 REJECTED + + + ____________________________________ + F test for equal standard deviations + ____________________________________ + + Sample 1: + Number of Observations = 11.00000 + Sample Standard Deviation = 4.90820 + + Sample 2: + Number of Observations = 9.00000 + Sample Standard Deviation = 2.58740 + + Test Statistic = 3.59847 + + CDF of test statistic: = 9.589e-001 + Upper Critical Value at alpha: = 3.347e+000 + Upper Critical Value at alpha/2: = 4.295e+000 + Lower Critical Value at alpha: = 3.256e-001 + Lower Critical Value at alpha/2: = 2.594e-001 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Standard deviations are unequal (two sided test) REJECTED + Standard deviation 1 is less than standard deviation 2 REJECTED + Standard deviation 1 is greater than standard deviation 2 NOT REJECTED + + + ____________________________________ + F test for equal standard deviations + ____________________________________ + + Sample 1: + Number of Observations = 240 + Sample Standard Deviation = 65.549 + + Sample 2: + Number of Observations = 240 + Sample Standard Deviation = 61.854 + + Test Statistic = 1.123 + + CDF of test statistic: = 8.148e-001 + Upper Critical Value at alpha: = 1.238e+000 + Upper Critical Value at alpha/2: = 1.289e+000 + Lower Critical Value at alpha: = 8.080e-001 + Lower Critical Value at alpha/2: = 7.756e-001 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Standard deviations are unequal (two sided test) REJECTED + Standard deviation 1 is less than standard deviation 2 REJECTED + Standard deviation 1 is greater than standard deviation 2 REJECTED + + + ____________________________________ + F test for equal standard deviations + ____________________________________ + + Sample 1: + Number of Observations = 11.00000 + Sample Standard Deviation = 4.90820 + + Sample 2: + Number of Observations = 9.00000 + Sample Standard Deviation = 2.58740 + + Test Statistic = 3.59847 + + CDF of test statistic: = 9.589e-001 + Upper Critical Value at alpha: = 3.347e+000 + Upper Critical Value at alpha/2: = 4.295e+000 + Lower Critical Value at alpha: = 3.256e-001 + Lower Critical Value at alpha/2: = 2.594e-001 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Standard deviations are unequal (two sided test) REJECTED + Standard deviation 1 is less than standard deviation 2 REJECTED + Standard deviation 1 is greater than standard deviation 2 NOT REJECTED + + + +*/ + diff --git a/src/boost/libs/math/example/factorial_example.cpp b/src/boost/libs/math/example/factorial_example.cpp new file mode 100644 index 000000000..7a51e0746 --- /dev/null +++ b/src/boost/libs/math/example/factorial_example.cpp @@ -0,0 +1,97 @@ +// TestFactorial.cpp +// +// Factorials and Binomial Coefficients. +// +// Copyright Datasim Education BV 2009-2010 +// Copyright John Maddock and Paul A. Bristow 2010 + +// 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) + +#include <boost/math/special_functions/factorials.hpp> +#include <boost/math/special_functions.hpp> + +#include <iostream> +using namespace std; + +int main() +{ + using namespace boost::math; + + // Factorials + unsigned int n = 3; + + try + { + cout << "Factorial: " << factorial<double>(n) << endl; + + // Caution: You must provide a return type template value, so this will not compile + // unsigned int nfac = factorial(n); // could not deduce template argument for 'T' + // You must provide an explicit floating-point (not integer) return type. + // If you do provide an integer type, like this: + // unsigned int uintfac = factorial<unsigned int>(n); + // you will also get a compile error, for MSVC C2338. + // If you really want an integer type, you can convert from double: + unsigned int intfac = static_cast<unsigned int>(factorial<double>(n)); + // this will be exact, until the result of the factorial overflows the integer type. + + cout << "Unchecked factorial: " << boost::math::unchecked_factorial<float>(n) << endl; + // Note: + // unsigned int unfac = boost::math::unchecked_factorial<unsigned int>(n); + // also fails to compile for the same reasons. + } + catch(exception& e) + { + cout << e.what() << endl; + } + + // Double factorial n!! + try + { + //cout << "Double factorial: " << boost::math::double_factorial<unsigned>(n); + } + catch(exception& e) + { + cout << e.what() << endl; + } + + // Rising and falling factorials + try + { + int i = 2; double x = 8; + cout << "Rising factorial: " << rising_factorial(x,i) << endl; + cout << "Falling factorial: " << falling_factorial(x,i) << endl; + } + catch(exception& e) + { + cout << e.what() << endl; + } + + // Binomial coefficients + try + { + unsigned n = 10; unsigned k = 2; + // cout << "Binomial coefficient: " << boost::math::binomial_coefficient<unsigned>(n,k) << endl; + } + catch(exception& e) + { + cout << e.what() << endl; + } + return 0; +} + +/* + +Output: + + factorial_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\factorial_example.exe + Factorial: 6 + Unchecked factorial: 6 + Rising factorial: 72 + Falling factorial: 56 + +*/ + + diff --git a/src/boost/libs/math/example/fft_sines_table.cpp b/src/boost/libs/math/example/fft_sines_table.cpp new file mode 100644 index 000000000..edcb8af74 --- /dev/null +++ b/src/boost/libs/math/example/fft_sines_table.cpp @@ -0,0 +1,270 @@ +// 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) + +// Copyright Paul A. Bristow 2013. +// Copyright Christopher Kormanyos 2012, 2013. +// Copyright John Maddock 2013. + +// This file is written to be included from a Quickbook .qbk document. +// It can be compiled by the C++ compiler, and run. Any output can +// also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +#ifdef _MSC_VER +# pragma warning (disable : 4996) // -D_SCL_SECURE_NO_WARNINGS. +#endif + +//[fft_sines_table_example_1 + +/*`[h5 Using Boost.Multiprecision to generate a high-precision array of sine coefficients for use with FFT.] + +The Boost.Multiprecision library can be used for computations requiring precision +exceeding that of standard built-in types such as `float`, `double` +and `long double`. For extended-precision calculations, Boost.Multiprecision +supplies a template data type called `cpp_bin_float`. The number of decimal +digits of precision is fixed at compile-time via a template parameter. + +One often needs to compute tables of numbers in mathematical software. +To avoid the +[@https://en.wikipedia.org/wiki/Rounding#Table-maker's_dilemma Table-maker's dilemma] +it is necessary to use a higher precision type to compute the table values so that they have +the nearest representable bit-pattern for the type, say `double`, of the table value. + +This example is a program `fft_since_table.cpp` that writes a header file `sines.hpp` +containing an array of sine coefficients for use with a Fast Fourier Transform (FFT), +that can be included by the FFT program. + +To use Boost.Multiprecision's high-precision floating-point types and constants, we need some includes: +*/ +#include <boost/math/constants/constants.hpp> +// using boost::math::constants::pi; + +#include <boost/multiprecision/cpp_bin_float.hpp> // for +// using boost::multiprecision::cpp_bin_float and +// using boost::multiprecision::cpp_bin_float_50; +// using boost::multiprecision::cpp_bin_float_quad; + +#include <boost/array.hpp> // or <array> for std::array + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> +#include <fstream> + +/*`First, this example defines a prolog text string which is a C++ comment with the program licence, copyright etc. +(You would of course, tailor this to your needs, including *your* copyright claim). +This will appear at the top of the written header file `sines.hpp`. +*/ + +//] [fft_sines_table_example_1] + +static const char* prolog = +{ + "// Use, modification and distribution are subject to the\n" + "// Boost Software License, Version 1.0.\n" + "// (See accompanying file LICENSE_1_0.txt\n" + "// or copy at ""http://www.boost.org/LICENSE_1_0.txt)\n\n" + + "// Copyright A N Other, 2019.\n\n" +}; + +//[fft_sines_table_example_2 + +using boost::multiprecision::cpp_bin_float_50; +using boost::math::constants::pi; + +//] [fft_sines_table_example_2] + +// VS 2010 (wrongly) requires these at file scope, not local scope in `main`. +// This program also requires `-std=c++11` option to compile using Clang and GCC. + +int main() +{ +//[fft_sines_table_example_3 +/*`A fast Fourier transform (FFT), for example, may use a table of the values of +sin(([pi]/2[super n]) in its implementation details. In order to maximize the precision in +the FFT implementation, the precision of the tabulated trigonometric values +should exceed that of the built-in floating-point type used in the FFT. + +The sample below computes a table of the values of sin([pi]/2[super n]) +in the range 1 <= n <= 31. + +This program makes use of, among other program elements, the data type +`boost::multiprecision::cpp_bin_float_50` +for a precision of 50 decimal digits from Boost.Multiprecision, +the value of constant [pi] retrieved from Boost.Math, +guaranteed to be initialized with the very last bit of precision for the type, +here `cpp_bin_float_50`, +and a C++11 lambda function combined with `std::for_each()`. +*/ + +/*`define the number of values (32) in the array of sines. +*/ + + std::size_t size = 32U; + //cpp_bin_float_50 p = pi<cpp_bin_float_50>(); + cpp_bin_float_50 p = boost::math::constants::pi<cpp_bin_float_50>(); + + std::vector <cpp_bin_float_50> sin_values (size); + unsigned n = 1U; + // Generate the sine values. + std::for_each + ( + sin_values.begin (), + sin_values.end (), + [&n](cpp_bin_float_50& y) + { + y = sin( pi<cpp_bin_float_50>() / pow(cpp_bin_float_50 (2), n)); + ++n; + } + ); + +/*`Define the floating-point type for the generated file, either built-in +`double, `float, or `long double`, or a user defined type like `cpp_bin_float_50`. +*/ + +std::string fp_type = "double"; + +std::cout << "Generating an `std::array` or `std::array` for floating-point type: " + << fp_type << ". " << std::endl; + +/*`By default, output would only show the standard 6 decimal digits, +so set precision to show enough significant digits for the chosen floating-point type. +For `cpp_bin_float_50` is 50. (50 decimal digits should be ample for most applications). + +*/ + std::streamsize precision = std::numeric_limits<cpp_bin_float_50>::digits10; + + std::cout << "Sines table precision is " << precision << " decimal digits. " << std::endl; + +/*`Of course, one could also choose a lower precision for the table values, for example, + +`std::streamsize precision = std::numeric_limits<cpp_bin_float_quad>::max_digits10;` + +128-bit 'quad' precision of 36 decimal digits would be sufficient +for the most precise current `long double` implementations using 128-bit. +In general, it should be a couple of decimal digits more (guard digits) than +`std::numeric_limits<RealType>::max_digits10` for the target system floating-point type. +(If the implementation does not provide `max_digits10`, the the Kahan formula +`std::numeric_limits<RealType>::digits * 3010/10000 + 2` can be used instead). + +The compiler will read these values as decimal digits strings and +use the nearest representation for the floating-point type. + +Now output all the sine table, to a file of your chosen name. +*/ + const char sines_name[] = "sines.hpp"; // Assuming in same directory as .exe + + std::ofstream fout(sines_name, std::ios_base::out); // Creates if no file exists, + // & uses default overwrite/ ios::replace. + if (fout.is_open() == false) + { // failed to open OK! + std::cout << "Open file " << sines_name << " failed!" << std::endl; + return EXIT_FAILURE; + } + else + { // Write prolog etc as a C++ comment. + std::cout << "Open file " << sines_name << " for output OK." << std::endl; + fout << prolog + << "// Table of " << sin_values.size() << " values with " + << precision << " decimal digits precision,\n" + "// generated by program fft_sines_table.cpp.\n" << std::endl; + + fout << "#include <array> // std::array" << std::endl; + + // Write the table of sines as a C++ array. + fout << "\nstatic const std::array<double, " << size << "> sines =\n" + "{{\n"; // 2nd { needed for some old GCC compiler versions. + fout.precision(precision); + + for (unsigned int i = 0U; ;) + { + fout << " " << sin_values[i]; + if (i == sin_values.size()-1) + { // next is last value. + fout << "\n}}; // array sines\n"; // 2nd } needed for some old GCC compiler versions. + break; + } + else + { + fout << ",\n"; + i++; + } + } // for + + fout.close(); + std::cout << "Closed file " << sines_name << " for output." << std::endl; + } +//`The output file generated can be seen at [@../../example/sines.hpp] + +//] [/fft_sines_table_example_3] + + return EXIT_SUCCESS; + +} // int main() + +/* +//[fft_sines_table_example_output + +The printed table is: + + 1 + 0.70710678118654752440084436210484903928483593768847 + 0.38268343236508977172845998403039886676134456248563 + 0.19509032201612826784828486847702224092769161775195 + 0.098017140329560601994195563888641845861136673167501 + 0.049067674327418014254954976942682658314745363025753 + 0.024541228522912288031734529459282925065466119239451 + 0.012271538285719926079408261951003212140372319591769 + 0.0061358846491544753596402345903725809170578863173913 + 0.003067956762965976270145365490919842518944610213452 + 0.0015339801862847656123036971502640790799548645752374 + 0.00076699031874270452693856835794857664314091945206328 + 0.00038349518757139558907246168118138126339502603496474 + 0.00019174759731070330743990956198900093346887403385916 + 9.5873799095977345870517210976476351187065612851145e-05 + 4.7936899603066884549003990494658872746866687685767e-05 + 2.3968449808418218729186577165021820094761474895673e-05 + 1.1984224905069706421521561596988984804731977538387e-05 + 5.9921124526424278428797118088908617299871778780951e-06 + 2.9960562263346607504548128083570598118251878683408e-06 + 1.4980281131690112288542788461553611206917585861527e-06 + 7.4901405658471572113049856673065563715595930217207e-07 + 3.7450702829238412390316917908463317739740476297248e-07 + 1.8725351414619534486882457659356361712045272098287e-07 + 9.3626757073098082799067286680885620193236507169473e-08 + 4.681337853654909269511551813854009695950362701667e-08 + 2.3406689268274552759505493419034844037886207223779e-08 + 1.1703344634137277181246213503238103798093456639976e-08 + 5.8516723170686386908097901008341396943900085051757e-09 + 2.9258361585343193579282304690689559020175857150074e-09 + 1.4629180792671596805295321618659637103742615227834e-09 +*/ + +//] [/fft_sines_table_example_output] + +//[fft_sines_table_example_check + +/*` +The output can be copied as text and readily integrated into a given source +code. Alternatively, the output can be written to a text or even be used +within a self-written automatic code generator as this example. + +A computer algebra system can be used to verify the results obtained from +Boost.Math and Boost.Multiprecision. For example, the __Mathematica +computer algebra system can obtain a similar table with the command: + + Table[N[Sin[Pi / (2^n)], 50], {n, 1, 31, 1}] + +The __WolframAlpha computational knowledge engine can also be used to generate +this table. The same command can be pasted into the compute box. + +*/ + +//] [/fft_sines_table_example_check] diff --git a/src/boost/libs/math/example/find_location_example.cpp b/src/boost/libs/math/example/find_location_example.cpp new file mode 100644 index 000000000..c9ce58d62 --- /dev/null +++ b/src/boost/libs/math/example/find_location_example.cpp @@ -0,0 +1,174 @@ +// find_location.cpp + +// Copyright Paul A. Bristow 2008, 2010. + +// 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) + +// Example of finding location (mean) +// for normal (Gaussian) & Cauchy distribution. + +// 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 + +//[find_location1 +/*` +First we need some includes to access the normal distribution, +the algorithms to find location (and some std output of course). +*/ + +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. +#include <boost/math/distributions/cauchy.hpp> // for cauchy_distribution + using boost::math::cauchy; // typedef provides default type is double. +#include <boost/math/distributions/find_location.hpp> + using boost::math::find_location; // for mean +#include <boost/math/distributions/find_scale.hpp> + using boost::math::find_scale; // for standard deviation + using boost::math::complement; // Needed if you want to use the complement version. + using boost::math::policies::policy; + +#include <iostream> + using std::cout; using std::endl; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; + +//] [/find_location1] + +int main() +{ + cout << "Example: Find location (or mean)." << endl; + try + { +//[find_location2 +/*` +For this example, we will use the standard normal distribution, +with mean (location) zero and standard deviation (scale) unity. +This is also the default for this implementation. +*/ + normal N01; // Default 'standard' normal distribution with zero mean and + double sd = 1.; // normal default standard deviation is 1. +/*`Suppose we want to find a different normal distribution whose mean is shifted +so that only fraction p (here 0.001 or 0.1%) are below a certain chosen limit +(here -2, two standard deviations). +*/ + double z = -2.; // z to give prob p + double p = 0.001; // only 0.1% below z + + cout << "Normal distribution with mean = " << N01.location() + << ", standard deviation " << N01.scale() + << ", has " << "fraction <= " << z + << ", p = " << cdf(N01, z) << endl; + cout << "Normal distribution with mean = " << N01.location() + << ", standard deviation " << N01.scale() + << ", has " << "fraction > " << z + << ", p = " << cdf(complement(N01, z)) << endl; // Note: uses complement. +/*` +[pre +Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501 +Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725 +] +We can now use ''find_location'' to give a new offset mean. +*/ + double l = find_location<normal>(z, p, sd); + cout << "offset location (mean) = " << l << endl; +/*` +that outputs: +[pre +offset location (mean) = 1.09023 +] +showing that we need to shift the mean just over one standard deviation from its previous value of zero. + +Then we can check that we have achieved our objective +by constructing a new distribution +with the offset mean (but same standard deviation): +*/ + normal np001pc(l, sd); // Same standard_deviation (scale) but with mean (location) shifted. +/*` +And re-calculating the fraction below our chosen limit. +*/ +cout << "Normal distribution with mean = " << l + << " has " << "fraction <= " << z + << ", p = " << cdf(np001pc, z) << endl; + cout << "Normal distribution with mean = " << l + << " has " << "fraction > " << z + << ", p = " << cdf(complement(np001pc, z)) << endl; +/*` +[pre +Normal distribution with mean = 1.09023 has fraction <= -2, p = 0.001 +Normal distribution with mean = 1.09023 has fraction > -2, p = 0.999 +] + +[h4 Controlling Error Handling from find_location] +We can also control the policy for handling various errors. +For example, we can define a new (possibly unwise) +policy to ignore domain errors ('bad' arguments). + +Unless we are using the boost::math namespace, we will need: +*/ + using boost::math::policies::policy; + using boost::math::policies::domain_error; + using boost::math::policies::ignore_error; + +/*` +Using a typedef is often convenient, especially if it is re-used, +although it is not required, as the various examples below show. +*/ + typedef policy<domain_error<ignore_error> > ignore_domain_policy; + // find_location with new policy, using typedef. + l = find_location<normal>(z, p, sd, ignore_domain_policy()); + // Default policy policy<>, needs "using boost::math::policies::policy;" + l = find_location<normal>(z, p, sd, policy<>()); + // Default policy, fully specified. + l = find_location<normal>(z, p, sd, boost::math::policies::policy<>()); + // A new policy, ignoring domain errors, without using a typedef. + l = find_location<normal>(z, p, sd, policy<domain_error<ignore_error> >()); +/*` +If we want to use a probability that is the __complements of our probability, +we should not even think of writing `find_location<normal>(z, 1 - p, sd)`, +but use the complement version, see __why_complements. +*/ + z = 2.; + double q = 0.95; // = 1 - p; // complement. + l = find_location<normal>(complement(z, q, sd)); + + normal np95pc(l, sd); // Same standard_deviation (scale) but with mean(location) shifted + cout << "Normal distribution with mean = " << l << " has " + << "fraction <= " << z << " = " << cdf(np95pc, z) << endl; + cout << "Normal distribution with mean = " << l << " has " + << "fraction > " << z << " = " << cdf(complement(np95pc, z)) << endl; + //] [/find_location2] + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +//[find_location_example_output +/*` +[pre +Example: Find location (mean). +Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501 +Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725 +offset location (mean) = 1.09023 +Normal distribution with mean = 1.09023 has fraction <= -2, p = 0.001 +Normal distribution with mean = 1.09023 has fraction > -2, p = 0.999 +Normal distribution with mean = 0.355146 has fraction <= 2 = 0.95 +Normal distribution with mean = 0.355146 has fraction > 2 = 0.05 +] +*/ +//] [/find_location_example_output] diff --git a/src/boost/libs/math/example/find_mean_and_sd_normal.cpp b/src/boost/libs/math/example/find_mean_and_sd_normal.cpp new file mode 100644 index 000000000..752c06a7f --- /dev/null +++ b/src/boost/libs/math/example/find_mean_and_sd_normal.cpp @@ -0,0 +1,413 @@ +// find_mean_and_sd_normal.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Example of finding mean or sd for normal distribution. + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[normal_std +/*` +First we need some includes to access the normal distribution, +the algorithms to find location and scale +(and some std output of course). +*/ + +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. +#include <boost/math/distributions/cauchy.hpp> // for cauchy_distribution + using boost::math::cauchy; // typedef provides default type is double. +#include <boost/math/distributions/find_location.hpp> + using boost::math::find_location; +#include <boost/math/distributions/find_scale.hpp> + using boost::math::find_scale; + using boost::math::complement; + using boost::math::policies::policy; + +#include <iostream> + using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; +#include <stdexcept> + +//] [/normal_std Quickbook] + +int main() +{ + cout << "Find_location (mean) and find_scale (standard deviation) examples." << endl; + try + { + +//[normal_find_location_and_scale_eg + +/*` +[h4 Using find_location and find_scale to meet dispensing and measurement specifications] + +Consider an example from K Krishnamoorthy, +Handbook of Statistical Distributions with Applications, +ISBN 1-58488-635-8, (2006) p 126, example 10.3.7. + +"A machine is set to pack 3 kg of ground beef per pack. +Over a long period of time it is found that the average packed was 3 kg +with a standard deviation of 0.1 kg. +Assume the packing is normally distributed." + +We start by constructing a normal distribution with the given parameters: +*/ + +double mean = 3.; // kg +double standard_deviation = 0.1; // kg +normal packs(mean, standard_deviation); +/*`We can then find the fraction (or %) of packages that weigh more than 3.1 kg. +*/ + +double max_weight = 3.1; // kg +cout << "Percentage of packs > " << max_weight << " is " +<< cdf(complement(packs, max_weight)) * 100. << endl; // P(X > 3.1) + +/*`We might want to ensure that 95% of packs are over a minimum weight specification, +then we want the value of the mean such that P(X < 2.9) = 0.05. + +Using the mean of 3 kg, we can estimate +the fraction of packs that fail to meet the specification of 2.9 kg. +*/ + +double minimum_weight = 2.9; +cout <<"Fraction of packs <= " << minimum_weight << " with a mean of " << mean + << " is " << cdf(complement(packs, minimum_weight)) << endl; +// fraction of packs <= 2.9 with a mean of 3 is 0.841345 + +/*`This is 0.84 - more than the target fraction of 0.95. +If we want 95% to be over the minimum weight, +what should we set the mean weight to be? + +Using the KK StatCalc program supplied with the book and the method given on page 126 gives 3.06449. + +We can confirm this by constructing a new distribution which we call 'xpacks' +with a safety margin mean of 3.06449 thus: +*/ +double over_mean = 3.06449; +normal xpacks(over_mean, standard_deviation); +cout << "Fraction of packs >= " << minimum_weight +<< " with a mean of " << xpacks.mean() + << " is " << cdf(complement(xpacks, minimum_weight)) << endl; +// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005 + +/*`Using this Math Toolkit, we can calculate the required mean directly thus: +*/ +double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9 +double low_limit = standard_deviation; +double offset = mean - low_limit - quantile(packs, under_fraction); +double nominal_mean = mean + offset; +// mean + (mean - low_limit - quantile(packs, under_fraction)); + +normal nominal_packs(nominal_mean, standard_deviation); +cout << "Setting the packer to " << nominal_mean << " will mean that " + << "fraction of packs >= " << minimum_weight + << " is " << cdf(complement(nominal_packs, minimum_weight)) << endl; +// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95 + +/*` +This calculation is generalized as the free function called `find_location`, +see __algorithms. + +To use this we will need to +*/ + +#include <boost/math/distributions/find_location.hpp> + using boost::math::find_location; +/*`and then use find_location function to find safe_mean, +& construct a new normal distribution called 'goodpacks'. +*/ +double safe_mean = find_location<normal>(minimum_weight, under_fraction, standard_deviation); +normal good_packs(safe_mean, standard_deviation); +/*`with the same confirmation as before: +*/ +cout << "Setting the packer to " << nominal_mean << " will mean that " + << "fraction of packs >= " << minimum_weight + << " is " << cdf(complement(good_packs, minimum_weight)) << endl; +// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95 + +/*` +[h4 Using Cauchy-Lorentz instead of normal distribution] + +After examining the weight distribution of a large number of packs, we might decide that, +after all, the assumption of a normal distribution is not really justified. +We might find that the fit is better to a __cauchy_distrib. +This distribution has wider 'wings', so that whereas most of the values +are closer to the mean than the normal, there are also more values than 'normal' +that lie further from the mean than the normal. + +This might happen because a larger than normal lump of meat is either included or excluded. + +We first create a __cauchy_distrib with the original mean and standard deviation, +and estimate the fraction that lie below our minimum weight specification. +*/ + +cauchy cpacks(mean, standard_deviation); +cout << "Cauchy Setting the packer to " << mean << " will mean that " + << "fraction of packs >= " << minimum_weight + << " is " << cdf(complement(cpacks, minimum_weight)) << endl; +// Cauchy Setting the packer to 3 will mean that fraction of packs >= 2.9 is 0.75 + +/*`Note that far fewer of the packs meet the specification, only 75% instead of 95%. +Now we can repeat the find_location, using the cauchy distribution as template parameter, +in place of the normal used above. +*/ + +double lc = find_location<cauchy>(minimum_weight, under_fraction, standard_deviation); +cout << "find_location<cauchy>(minimum_weight, over fraction, standard_deviation); " << lc << endl; +// find_location<cauchy>(minimum_weight, over fraction, packs.standard_deviation()); 3.53138 +/*`Note that the safe_mean setting needs to be much higher, 3.53138 instead of 3.06449, +so we will make rather less profit. + +And again confirm that the fraction meeting specification is as expected. +*/ +cauchy goodcpacks(lc, standard_deviation); +cout << "Cauchy Setting the packer to " << lc << " will mean that " + << "fraction of packs >= " << minimum_weight + << " is " << cdf(complement(goodcpacks, minimum_weight)) << endl; +// Cauchy Setting the packer to 3.53138 will mean that fraction of packs >= 2.9 is 0.95 + +/*`Finally we could estimate the effect of a much tighter specification, +that 99% of packs met the specification. +*/ + +cout << "Cauchy Setting the packer to " + << find_location<cauchy>(minimum_weight, 0.99, standard_deviation) + << " will mean that " + << "fraction of packs >= " << minimum_weight + << " is " << cdf(complement(goodcpacks, minimum_weight)) << endl; + +/*`Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99, +but will more than double the mean loss from 0.0644 to 0.133 kg per pack. + +Of course, this calculation is not limited to packs of meat, it applies to dispensing anything, +and it also applies to a 'virtual' material like any measurement. + +The only caveat is that the calculation assumes that the standard deviation (scale) is known with +a reasonably low uncertainty, something that is not so easy to ensure in practice. +And that the distribution is well defined, __normal_distrib or __cauchy_distrib, or some other. + +If one is simply dispensing a very large number of packs, +then it may be feasible to measure the weight of hundreds or thousands of packs. +With a healthy 'degrees of freedom', the confidence intervals for the standard deviation +are not too wide, typically about + and - 10% for hundreds of observations. + +For other applications, where it is more difficult or expensive to make many observations, +the confidence intervals are depressingly wide. + +See [link math_toolkit.stat_tut.weg.cs_eg.chi_sq_intervals Confidence Intervals on the standard deviation] +for a worked example +[@../../example/chi_square_std_dev_test.cpp chi_square_std_dev_test.cpp] +of estimating these intervals. + + +[h4 Changing the scale or standard deviation] + +Alternatively, we could invest in a better (more precise) packer +(or measuring device) with a lower standard deviation, or scale. + +This might cost more, but would reduce the amount we have to 'give away' +in order to meet the specification. + +To estimate how much better (how much smaller standard deviation) it would have to be, +we need to get the 5% quantile to be located at the under_weight limit, 2.9 +*/ +double p = 0.05; // wanted p th quantile. +cout << "Quantile of " << p << " = " << quantile(packs, p) + << ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; +/*` +Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1 + +With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg, +a little below our target of 2.9 kg. +So we know that the standard deviation is going to have to be smaller. + +Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05 kg. +*/ +normal pack05(mean, 0.05); +cout << "Quantile of " << p << " = " << quantile(pack05, p) + << ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl; +// Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05 + +cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean + << " and standard deviation of " << pack05.standard_deviation() + << " is " << cdf(complement(pack05, minimum_weight)) << endl; +// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725 +/*` +So 0.05 was quite a good guess, but we are a little over the 2.9 target, +so the standard deviation could be a tiny bit more. So we could do some +more guessing to get closer, say by increasing standard deviation to 0.06 kg, +constructing another new distribution called pack06. +*/ +normal pack06(mean, 0.06); +cout << "Quantile of " << p << " = " << quantile(pack06, p) + << ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl; +// Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06 + +cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean + << " and standard deviation of " << pack06.standard_deviation() + << " is " << cdf(complement(pack06, minimum_weight)) << endl; +// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221 +/*` +Now we are getting really close, but to do the job properly, +we might need to use root finding method, for example the tools provided, +and used elsewhere, in the Math Toolkit, see __root_finding_without_derivatives + +But in this (normal) distribution case, we can and should be even smarter +and make a direct calculation. +*/ + +/*`Our required limit is minimum_weight = 2.9 kg, often called the random variate z. +For a standard normal distribution, then probability p = N((minimum_weight - mean) / sd). + +We want to find the standard deviation that would be required to meet this limit, +so that the p th quantile is located at z (minimum_weight). +In this case, the 0.05 (5%) quantile is at 2.9 kg pack weight, when the mean is 3 kg, +ensuring that 0.95 (95%) of packs are above the minimum weight. + +Rearranging, we can directly calculate the required standard deviation: +*/ +normal N01; // standard normal distribution with mean zero and unit standard deviation. +p = 0.05; +double qp = quantile(N01, p); +double sd95 = (minimum_weight - mean) / qp; + +cout << "For the "<< p << "th quantile to be located at " + << minimum_weight << ", would need a standard deviation of " << sd95 << endl; +// For the 0.05th quantile to be located at 2.9, would need a standard deviation of 0.0607957 + +/*`We can now construct a new (normal) distribution pack95 for the 'better' packer, +and check that our distribution will meet the specification. +*/ + +normal pack95(mean, sd95); +cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean + << " and standard deviation of " << pack95.standard_deviation() + << " is " << cdf(complement(pack95, minimum_weight)) << endl; +// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95 + +/*`This calculation is generalized in the free function find_scale, +as shown below, giving the same standard deviation. +*/ +double ss = find_scale<normal>(minimum_weight, under_fraction, packs.mean()); +cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss << endl; +// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957 + +/*`If we had defined an over_fraction, or percentage that must pass specification +*/ +double over_fraction = 0.95; +/*`And (wrongly) written + + double sso = find_scale<normal>(minimum_weight, over_fraction, packs.mean()); + +With the default policy, we would get a message like + +[pre +Message from thrown exception was: + Error in function boost::math::find_scale<Dist, Policy>(double, double, double, Policy): + Computed scale (-0.060795683191176959) is <= 0! Was the complement intended? +] + +But this would return a *negative* standard deviation - obviously impossible. +The probability should be 1 - over_fraction, not over_fraction, thus: +*/ + +double ss1o = find_scale<normal>(minimum_weight, 1 - over_fraction, packs.mean()); +cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss1o << endl; +// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957 + +/*`But notice that using '1 - over_fraction' - will lead to a +loss of accuracy, especially if over_fraction was close to unity. (See __why_complements). +In this (very common) case, we should instead use the __complements, +giving the most accurate result. +*/ + +double ssc = find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); +cout << "find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); " << ssc << endl; +// find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); 0.0607957 + +/*`Note that our guess of 0.06 was close to the accurate value of 0.060795683191176959. + +We can again confirm our prediction thus: +*/ + +normal pack95c(mean, ssc); +cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean + << " and standard deviation of " << pack95c.standard_deviation() + << " is " << cdf(complement(pack95c, minimum_weight)) << endl; +// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95 + +/*`Notice that these two deceptively simple questions: + +* Do we over-fill to make sure we meet a minimum specification (or under-fill to avoid an overdose)? + +and/or + +* Do we measure better? + +are actually extremely common. + +The weight of beef might be replaced by a measurement of more or less anything, +from drug tablet content, Apollo landing rocket firing, X-ray treatment doses... + +The scale can be variation in dispensing or uncertainty in measurement. +*/ +//] [/normal_find_location_and_scale_eg Quickbook end] + + } + 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. + // 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. + cout << + "\n""Message from thrown exception was:\n " << e.what() << endl; + } + return 0; +} // int main() + + +/* + +Output is: + +//[normal_find_location_and_scale_output + +Find_location (mean) and find_scale (standard deviation) examples. +Percentage of packs > 3.1 is 15.8655 +Fraction of packs <= 2.9 with a mean of 3 is 0.841345 +Fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005 +Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95 +Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95 +Cauchy Setting the packer to 3 will mean that fraction of packs >= 2.9 is 0.75 +find_location<cauchy>(minimum_weight, over fraction, standard_deviation); 3.53138 +Cauchy Setting the packer to 3.53138 will mean that fraction of packs >= 2.9 is 0.95 +Cauchy Setting the packer to -0.282052 will mean that fraction of packs >= 2.9 is 0.95 +Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1 +Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725 +Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221 +For the 0.05th quantile to be located at 2.9, would need a standard deviation of 0.0607957 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95 +find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957 +find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957 +find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); 0.0607957 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95 + +//] [/normal_find_location_and_scale_eg_output] + +*/ + + + diff --git a/src/boost/libs/math/example/find_root_example.cpp b/src/boost/libs/math/example/find_root_example.cpp new file mode 100644 index 000000000..e944e09e8 --- /dev/null +++ b/src/boost/libs/math/example/find_root_example.cpp @@ -0,0 +1,169 @@ +// find_root_example.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Example of using root finding. + +// 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_find1 +/*` +First we need some includes to access the normal distribution +(and some std output of course). +*/ + +#include <boost/math/tools/roots.hpp> // root finding. + +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. + +#include <iostream> + using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; +#include <stdexcept> + + +//] //[/root_find1] + +int main() +{ + cout << "Example: Normal distribution, root finding."; + try + { + +//[root_find2 + +/*`A machine is set to pack 3 kg of ground beef per pack. +Over a long period of time it is found that the average packed was 3 kg +with a standard deviation of 0.1 kg. +Assuming the packing is normally distributed, +we can find the fraction (or %) of packages that weigh more than 3.1 kg. +*/ + +double mean = 3.; // kg +double standard_deviation = 0.1; // kg +normal packs(mean, standard_deviation); + +double max_weight = 3.1; // kg +cout << "Percentage of packs > " << max_weight << " is " +<< cdf(complement(packs, max_weight)) << endl; // P(X > 3.1) + +double under_weight = 2.9; +cout <<"fraction of packs <= " << under_weight << " with a mean of " << mean + << " is " << cdf(complement(packs, under_weight)) << endl; +// fraction of packs <= 2.9 with a mean of 3 is 0.841345 +// This is 0.84 - more than the target 0.95 +// Want 95% to be over this weight, so what should we set the mean weight to be? +// KK StatCalc says: +double over_mean = 3.0664; +normal xpacks(over_mean, standard_deviation); +cout << "fraction of packs >= " << under_weight +<< " with a mean of " << xpacks.mean() + << " is " << cdf(complement(xpacks, under_weight)) << endl; +// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005 +double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9 +double low_limit = standard_deviation; +double offset = mean - low_limit - quantile(packs, under_fraction); +double nominal_mean = mean + offset; + +normal nominal_packs(nominal_mean, standard_deviation); +cout << "Setting the packer to " << nominal_mean << " will mean that " + << "fraction of packs >= " << under_weight + << " is " << cdf(complement(nominal_packs, under_weight)) << endl; + +/*` +Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95. + +Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99, +but will more than double the mean loss from 0.0644 to 0.133. + +Alternatively, we could invest in a better (more precise) packer with a lower standard deviation. + +To estimate how much better (how much smaller standard deviation) it would have to be, +we need to get the 5% quantile to be located at the under_weight limit, 2.9 +*/ +double p = 0.05; // wanted p th quantile. +cout << "Quantile of " << p << " = " << quantile(packs, p) + << ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; // +/*` +Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1 + +With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg, +a little below our target of 2.9 kg. +So we know that the standard deviation is going to have to be smaller. + +Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05 +*/ +normal pack05(mean, 0.05); +cout << "Quantile of " << p << " = " << quantile(pack05, p) + << ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl; + +cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean + << " and standard deviation of " << pack05.standard_deviation() + << " is " << cdf(complement(pack05, under_weight)) << endl; +// +/*` +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.9772 + +So 0.05 was quite a good guess, but we are a little over the 2.9 target, +so the standard deviation could be a tiny bit more. So we could do some +more guessing to get closer, say by increasing to 0.06 +*/ + +normal pack06(mean, 0.06); +cout << "Quantile of " << p << " = " << quantile(pack06, p) + << ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl; + +cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean + << " and standard deviation of " << pack06.standard_deviation() + << " is " << cdf(complement(pack06, under_weight)) << endl; +/*` +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.9522 + +Now we are getting really close, but to do the job properly, +we could use root finding method, for example the tools provided, and used elsewhere, +in the Math Toolkit, see __root_finding_without_derivatives. + +But in this normal distribution case, we could be even smarter and make a direct calculation. +*/ +//] [/root_find2] + + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +/* +Output is: + +//[root_find_output + +Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\find_root_example.exe" +Example: Normal distribution, root finding.Percentage of packs > 3.1 is 0.158655 +fraction of packs <= 2.9 with a mean of 3 is 0.841345 +fraction of packs >= 2.9 with a mean of 3.0664 is 0.951944 +Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95 +Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1 +Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725 +Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06 +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221 + +//] [/root_find_output] +*/ diff --git a/src/boost/libs/math/example/find_scale_example.cpp b/src/boost/libs/math/example/find_scale_example.cpp new file mode 100644 index 000000000..29e474f0f --- /dev/null +++ b/src/boost/libs/math/example/find_scale_example.cpp @@ -0,0 +1,180 @@ +// find_scale.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Example of finding scale (standard deviation) for normal (Gaussian). + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[find_scale1 +/*` +First we need some includes to access the __normal_distrib, +the algorithms to find scale (and some std output of course). +*/ + +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. +#include <boost/math/distributions/find_scale.hpp> + using boost::math::find_scale; + using boost::math::complement; // Needed if you want to use the complement version. + using boost::math::policies::policy; // Needed to specify the error handling policy. + +#include <iostream> + using std::cout; using std::endl; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; +//] [/find_scale1] + +int main() +{ + cout << "Example: Find scale (standard deviation)." << endl; + try + { +//[find_scale2 +/*` +For this example, we will use the standard __normal_distrib, +with location (mean) zero and standard deviation (scale) unity. +Conveniently, this is also the default for this implementation's constructor. +*/ + normal N01; // Default 'standard' normal distribution with zero mean + double sd = 1.; // and standard deviation is 1. +/*`Suppose we want to find a different normal distribution with standard deviation +so that only fraction p (here 0.001 or 0.1%) are below a certain chosen limit +(here -2. standard deviations). +*/ + double z = -2.; // z to give prob p + double p = 0.001; // only 0.1% below z = -2 + + cout << "Normal distribution with mean = " << N01.location() // aka N01.mean() + << ", standard deviation " << N01.scale() // aka N01.standard_deviation() + << ", has " << "fraction <= " << z + << ", p = " << cdf(N01, z) << endl; + cout << "Normal distribution with mean = " << N01.location() + << ", standard deviation " << N01.scale() + << ", has " << "fraction > " << z + << ", p = " << cdf(complement(N01, z)) << endl; // Note: uses complement. +/*` +[pre +Normal distribution with mean = 0 has fraction <= -2, p = 0.0227501 +Normal distribution with mean = 0 has fraction > -2, p = 0.97725 +] +Noting that p = 0.02 instead of our target of 0.001, +we can now use `find_scale` to give a new standard deviation. +*/ + double l = N01.location(); + double s = find_scale<normal>(z, p, l); + cout << "scale (standard deviation) = " << s << endl; +/*` +that outputs: +[pre +scale (standard deviation) = 0.647201 +] +showing that we need to reduce the standard deviation from 1. to 0.65. + +Then we can check that we have achieved our objective +by constructing a new distribution +with the new standard deviation (but same zero mean): +*/ + normal np001pc(N01.location(), s); +/*` +And re-calculating the fraction below (and above) our chosen limit. +*/ + cout << "Normal distribution with mean = " << l + << " has " << "fraction <= " << z + << ", p = " << cdf(np001pc, z) << endl; + cout << "Normal distribution with mean = " << l + << " has " << "fraction > " << z + << ", p = " << cdf(complement(np001pc, z)) << endl; +/*` +[pre +Normal distribution with mean = 0 has fraction <= -2, p = 0.001 +Normal distribution with mean = 0 has fraction > -2, p = 0.999 +] + +[h4 Controlling how Errors from find_scale are handled] +We can also control the policy for handling various errors. +For example, we can define a new (possibly unwise) +policy to ignore domain errors ('bad' arguments). + +Unless we are using the boost::math namespace, we will need: +*/ + using boost::math::policies::policy; + using boost::math::policies::domain_error; + using boost::math::policies::ignore_error; + +/*` +Using a typedef is convenient, especially if it is re-used, +although it is not required, as the various examples below show. +*/ + typedef policy<domain_error<ignore_error> > ignore_domain_policy; + // find_scale with new policy, using typedef. + l = find_scale<normal>(z, p, l, ignore_domain_policy()); + // Default policy policy<>, needs using boost::math::policies::policy; + + l = find_scale<normal>(z, p, l, policy<>()); + // Default policy, fully specified. + l = find_scale<normal>(z, p, l, boost::math::policies::policy<>()); + // New policy, without typedef. + l = find_scale<normal>(z, p, l, policy<domain_error<ignore_error> >()); +/*` +If we want to express a probability, say 0.999, that is a complement, `1 - p` +we should not even think of writing `find_scale<normal>(z, 1 - p, l)`, +but use the __complements version (see __why_complements). +*/ + z = -2.; + double q = 0.999; // = 1 - p; // complement of 0.001. + sd = find_scale<normal>(complement(z, q, l)); + + normal np95pc(l, sd); // Same standard_deviation (scale) but with mean(scale) shifted + cout << "Normal distribution with mean = " << l << " has " + << "fraction <= " << z << " = " << cdf(np95pc, z) << endl; + cout << "Normal distribution with mean = " << l << " has " + << "fraction > " << z << " = " << cdf(complement(np95pc, z)) << endl; + +/*` +Sadly, it is all too easy to get probabilities the wrong way round, +when you may get a warning like this: +[pre +Message from thrown exception was: + Error in function boost::math::find_scale<Dist, Policy>(complement(double, double, double, Policy)): + Computed scale (-0.48043523852179076) is <= 0! Was the complement intended? +] +The default error handling policy is to throw an exception with this message, +but if you chose a policy to ignore the error, +the (impossible) negative scale is quietly returned. +*/ +//] [/find_scale2] + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +//[find_scale_example_output +/*` +[pre +Example: Find scale (standard deviation). +Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501 +Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725 +scale (standard deviation) = 0.647201 +Normal distribution with mean = 0 has fraction <= -2, p = 0.001 +Normal distribution with mean = 0 has fraction > -2, p = 0.999 +Normal distribution with mean = 0.946339 has fraction <= -2 = 0.001 +Normal distribution with mean = 0.946339 has fraction > -2 = 0.999 +] +*/ +//] [/find_scale_example_output] diff --git a/src/boost/libs/math/example/float128_example.cpp b/src/boost/libs/math/example/float128_example.cpp new file mode 100644 index 000000000..23e01666a --- /dev/null +++ b/src/boost/libs/math/example/float128_example.cpp @@ -0,0 +1,289 @@ +// Copyright John Maddock 2016 +// Copyright Christopher Kormanyos 2016. +// Copyright Paul A. Bristow 2016. + +// 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) + +// Contains Quickbook snippets as C++ comments - do not remove. + +// http://gcc.gnu.org/onlinedocs/libquadmath/ GCC Quad-Precision Math Library +// https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format + +// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options GNU 3.5 Options Controlling C++ Dialect +// https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options 3.4 Options Controlling C Dialect + +//[float128_includes_1 + +#include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include! +//#include <boost/config.hpp> +#include <boost/multiprecision/float128.hpp> +#include <boost/math/special_functions.hpp> // For gamma function. +#include <boost/math/constants/constants.hpp> // For constants pi, e ... +#include <typeinfo> // + +#include <cmath> // for pow function. + +// #include <quadmath.h> +// C:\program files\gcc-6-win64\lib\gcc\x86_64-w64-mingw32\6.1.1\include\quadmath.h + +// i:\modular-boost\boost\multiprecision\float128.hpp|210| undefined reference to `quadmath_snprintf'. + +//] [/float128_includes_1] + +//[float128_dialect_1 +/*`To make float128 available it is vital to get the dialect and options on the command line correct. + +Quad type is forbidden by all the strict C++ standards, so using or adding -std=c++11 and later standards will prevent its use. +so explicitly use -std=gnu++11, 1y, 14, 17, or 1z or ... + +For GCC 6.1.1, for example, the default is if no C++ language dialect options are given, is -std=gnu++14. + +See https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options +https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Standards 2 Language Standards Supported by GCC + + g++.exe -Wall -fexceptions -std=gnu++17 -g -fext-numeric-literals -fpermissive -lquadmath + -II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o + +Requires GCC linker option -lquadmath + +If this is missing, then get errors like: + + \modular-boost\boost\multiprecision\float128.hpp|210|undefined reference to `quadmath_snprintf'| + \modular-boost\boost\multiprecision\float128.hpp|351|undefined reference to `sqrtq'| + +Requires compile option + + -fext-numeric-literals + +If missing, then get errors like: + +\modular-boost\libs\math\include/boost/math/cstdfloat/cstdfloat_types.hpp:229:43: error: unable to find numeric literal operator 'operator""Q' + +A successful build log was: + + g++.exe -Wall -std=c++11 -fexceptions -std=gnu++17 -g -fext-numeric-literals -II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o + g++.exe -o bin\Debug\float128.exe obj\Debug\float128_example.o -lquadmath +*/ + +//] [/float128_dialect_1] + +void show_versions(std::string title) +{ + std::cout << title << std::endl; + + std::cout << "Platform: " << BOOST_PLATFORM << '\n' + << "Compiler: " << BOOST_COMPILER << '\n' + << "STL : " << BOOST_STDLIB << '\n' + << "Boost : " << BOOST_VERSION / 100000 << "." + << BOOST_VERSION / 100 % 1000 << "." + << BOOST_VERSION % 100 + << std::endl; +#ifdef _MSC_VER + std::cout << "_MSC_FULL_VER = " << _MSC_FULL_VER << std::endl; // VS 2015 190023026 +#if defined _M_IX86 + std::cout << "(x86)" << std::endl; +#endif +#if defined _M_X64 + std::cout << " (x64)" << std::endl; +#endif +#if defined _M_IA64 + std::cout << " (Itanium)" << std::endl; +#endif + // Something very wrong if more than one is defined (so show them in all just in case)! +#endif // _MSC_VER +#ifdef __GNUC__ +//PRINT_MACRO(__GNUC__); +//PRINT_MACRO(__GNUC_MINOR__); +//PRINT_MACRO(__GNUC_PATCH__); +std::cout << "GCC " << __VERSION__ << std::endl; +//PRINT_MACRO(LONG_MAX); +#endif // __GNUC__ + return; +} // void show_version(std::string title) + +int main() +{ + try + { + +//[float128_example_3 +// Always use try'n'catch blocks to ensure any error messages are displayed. +//`Ensure that all possibly significant digits (17) including trailing zeros are shown. + + std::cout.precision(std::numeric_limits<boost::float64_t>::max_digits10); + std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros. + //] [/ float128_example_3] + +#ifdef BOOST_FLOAT128_C + std::cout << "Floating-point type boost::float128_t is available." << std::endl; + std::cout << " std::numeric_limits<boost::float128_t>::digits10 == " + << std::numeric_limits<boost::float128_t>::digits10 << std::endl; + std::cout << " std::numeric_limits<boost::float128_t>::max_digits10 == " + << std::numeric_limits<boost::float128_t>::max_digits10 << std::endl; +#else + std::cout << "Floating-point type boost::float128_t is NOT available." << std::endl; +#endif + + show_versions(""); + + using boost::multiprecision::float128; // Wraps, for example, __float128 or _Quad. + // or + //using namespace boost::multiprecision; + + std::cout.precision(std::numeric_limits<float128>::max_digits10); // Show all potentially meaningful digits. + std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros. + + // float128 pi0 = boost::math::constants::pi(); // Compile fails - need to specify a type for the constant! + + float128 pi1 = boost::math::constants::pi<float128>(); // Returns a constant of type float128. + std::cout << sqrt(pi1) << std::endl; // 1.77245385090551602729816748334114514 + + float128 pi2 = boost::math::constants::pi<__float128>(); // Constant of type __float128 gets converted to float128 on the assignment. + std::cout << sqrt(pi2) << std::endl; // 1.77245385090551602729816748334114514 + + // DIY decimal digit literal constant, with suffix Q. + float128 pi3 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348Q; + std::cout << sqrt(pi3) << std::endl; // 1.77245385090551602729816748334114514 + + // Compare to ready-rolled sqrt(pi) constant from Boost.Math: + std::cout << boost::math::constants::root_pi<float128>() << std::endl; // 1.77245385090551602729816748334114514 + + // DIY decimal digit literal constant, without suffix Q, suffering seventeen silent digits loss of precision! + float128 pi4 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348; + std::cout << sqrt(pi4) << std::endl; // 1.77245385090551599275151910313924857 + + // float128 variables constructed from a quad-type literal can be declared constexpr if required: + +#ifndef BOOST_NO_CXX11_CONSTEXPR + constexpr float128 pi_constexpr = 3.1415926535897932384626433832795028841971693993751058Q; +#endif + std::cout << pi_constexpr << std::endl; // 3.14159265358979323846264338327950280 + + // But sadly functions like sqrt are not yet available constexpr for float128. + + // constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Fails - not constexpr (yet). + // constexpr float128 root_pi_constexpr = std::sqrt(pi_constexpr); // Fails - no known conversion for argument 1 from 'const float128'. + // constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Call to non-constexpr + // constexpr float128 root_pi_constexpr = boost::math::constants::root_pi(); // Missing type for constant. + + // Best current way to get a constexpr is to use a Boost.Math constant if one is available. + constexpr float128 root_pi_constexpr = boost::math::constants::root_pi<float128>(); + std::cout << root_pi_constexpr << std::endl; // 1.77245385090551602729816748334114514 + + // Note that casts within the sqrt call are NOT NEEDED (nor allowed), + // since all the variables are the correct type to begin with. + // std::cout << sqrt<float128>(pi3) << std::endl; + // But note examples of catastrophic (but hard to see) loss of precision below. + + // Note also that the library functions, here sqrt, is NOT defined using std::sqrt, + // so that the correct overload is found using Argument Dependent LookUp (ADL). + + float128 ee = boost::math::constants::e<float128>(); + std::cout << ee << std::endl; // 2.71828182845904523536028747135266231 + + float128 e1 = exp(1.Q); // Note argument to exp is type float128. + std::cout << e1 << std::endl; // 2.71828182845904523536028747135266231 + + // Beware - it is all too easy to silently get a much lower precision by mistake. + + float128 e1d = exp(1.); // Caution - only double 17 decimal digits precision! + std::cout << e1d << std::endl; // 2.71828182845904509079559829842764884 + + float128 e1i = exp(1); // Caution int promoted to double so only 17 decimal digits precision! + std::cout << e1i << std::endl; // 2.71828182845904509079559829842764884 + + float f1 = 1.F; + float128 e1f = exp(f1); // Caution float so only 6 decimal digits precision out of 36! + std::cout << e1f << std::endl; // 2.71828174591064453125000000000000000 + + // In all these cases you get what you asked for and not what you expected or wanted. + + // Casting is essential if you start with a lower precision type. + + float128 e1q = exp(static_cast<float128>(f1)); // Full 36 decimal digits precision! + std::cout << e1q << std::endl; // 2.71828182845904523536028747135266231 + + float128 e1qc = exp((float128)f1); // Full 36 decimal digits precision! + std::cout << e1qc << std::endl; // 2.71828182845904523536028747135266231 + + float128 e1qcc = exp(float128(f1)); // Full 36 decimal digits precision! + std::cout << e1qcc << std::endl; // 2.71828182845904523536028747135266231 + + //float128 e1q = exp<float128>(1.); // Compile fails. + // std::cout << e1q << std::endl; // + +// http://en.cppreference.com/w/cpp/language/typeid +// The name()is implementation-dependent mangled, and may not be able to be output. +// The example showing output using one of the implementations where type_info::name prints full type names; +// filter through c++filt -t if using gcc or similar. + +//[float128_type_info +const std::type_info& tifu128 = typeid(__float128); // OK. +//std::cout << tifu128.name() << std::endl; // On GCC, aborts (because not printable string). +//std::cout << typeid(__float128).name() << std::endl; // Aborts - +// string name cannot be output. + +const std::type_info& tif128 = typeid(float128); // OK. +std::cout << tif128.name() << std::endl; // OK. +std::cout << typeid(float128).name() << std::endl; // OK. + +const std::type_info& tpi = typeid(pi1); // OK using GCC 6.1.1. +// (from GCC 5 according to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622) +std::cout << tpi.name() << std::endl; // OK, Output implementation-dependent mangled name: + +// N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE + +//] [/float128_type_info] + + } + catch (std::exception ex) + { // Display details about why any exceptions are thrown. + std::cout << "Thrown exception " << ex.what() << std::endl; + } +} // int main() + +/* +[float128_output + +-std=c++11 or -std=c++17 don't work + +Floating-point type boost::float128_t is NOT available. + +Platform: Win32 +Compiler: GNU C++ version 6.1.1 20160609 +STL : GNU libstdc++ version 20160609 +Boost : 1.62.0 +GCC 6.1.1 20160609 + + +Added -fext-numeric-literals to + +-std=gnu++11 -fext-numeric-literals -lquadmath + +Floating-point type boost::float128_t is available. + std::numeric_limits<boost::float128_t>::digits10 == 33 + std::numeric_limits<boost::float128_t>::max_digits10 == 36 + +Platform: Win32 +Compiler: GNU C++ version 6.1.1 20160609 +STL : GNU libstdc++ version 20160609 +Boost : 1.62.0 +GCC 6.1.1 20160609 +1.77245385090551602729816748334114514 +1.77245385090551602729816748334114514 +1.77245385090551602729816748334114514 +1.77245385090551602729816748334114514 +N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE +N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE +N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE + +Process returned 0 (0x0) execution time : 0.033 s +Press any key to continue. + + + +//] [/float128_output] + +*/ diff --git a/src/boost/libs/math/example/float_comparison_example.cpp b/src/boost/libs/math/example/float_comparison_example.cpp new file mode 100644 index 000000000..6c892fa21 --- /dev/null +++ b/src/boost/libs/math/example/float_comparison_example.cpp @@ -0,0 +1,444 @@ +//!file +//! \brief floating-point comparison from Boost.Test +// Copyright Paul A. Bristow 2015. +// Copyright John Maddock 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) + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <boost/math/special_functions/relative_difference.hpp> +#include <boost/math/special_functions/next.hpp> + +#include <iostream> +#include <limits> // for std::numeric_limits<T>::epsilon(). + +int main() +{ + std::cout << "Compare floats using Boost.Math functions/classes" << std::endl; + + +//[compare_floats_using +/*`Some using statements will ensure that the functions we need are accessible. +*/ + + using namespace boost::math; + +//`or + + using boost::math::relative_difference; + using boost::math::epsilon_difference; + using boost::math::float_next; + using boost::math::float_prior; + +//] [/compare_floats_using] + + +//[compare_floats_example_1 +/*`The following examples display values with all possibly significant digits. +Newer compilers should provide `std::numeric_limits<FPT>::max_digits10` +for this purpose, and here we use `float` precision where `max_digits10` = 9 +to avoid displaying a distracting number of decimal digits. + +[note Older compilers can use this formula to calculate `max_digits10` +from `std::numeric_limits<FPT>::digits10`: +__spaces `int max_digits10 = 2 + std::numeric_limits<FPT>::digits10 * 3010/10000;` +] [/note] + +One can set the display including all trailing zeros +(helpful for this example to show all potentially significant digits), +and also to display `bool` values as words rather than integers: +*/ + std::cout.precision(std::numeric_limits<float>::max_digits10); + std::cout << std::boolalpha << std::showpoint << std::endl; + +//] [/compare_floats_example_1] + +//[compare_floats_example_2] +/*` +When comparing values that are ['quite close] or ['approximately equal], +we could use either `float_distance` or `relative_difference`/`epsilon_difference`, for example +with type `float`, these two values are adjacent to each other: +*/ + + float a = 1; + float b = 1 + std::numeric_limits<float>::epsilon(); + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "float_distance = " << float_distance(a, b) << std::endl; + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(a, b) << std::endl; + +/*` +Which produces the output: + +[pre +a = 1.00000000 +b = 1.00000012 +float_distance = 1.00000000 +relative_difference = 1.19209290e-007 +epsilon_difference = 1.00000000 +] +*/ + //] [/compare_floats_example_2] + +//[compare_floats_example_3] +/*` +In the example above, it just so happens that the edit distance as measured by `float_distance`, and the +difference measured in units of epsilon were equal. However, due to the way floating point +values are represented, that is not always the case:*/ + + a = 2.0f / 3.0f; // 2/3 inexactly represented as a float + b = float_next(float_next(float_next(a))); // 3 floating point values above a + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "float_distance = " << float_distance(a, b) << std::endl; + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(a, b) << std::endl; + +/*` +Which produces the output: + +[pre +a = 0.666666687 +b = 0.666666865 +float_distance = 3.00000000 +relative_difference = 2.68220901e-007 +epsilon_difference = 2.25000000 +] + +There is another important difference between `float_distance` and the +`relative_difference/epsilon_difference` functions in that `float_distance` +returns a signed result that reflects which argument is larger in magnitude, +where as `relative_difference/epsilon_difference` simply return an unsigned +value that represents how far apart the values are. For example if we swap +the order of the arguments: +*/ + + std::cout << "float_distance = " << float_distance(b, a) << std::endl; + std::cout << "relative_difference = " << relative_difference(b, a) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(b, a) << std::endl; + + /*` + The output is now: + + [pre + float_distance = -3.00000000 + relative_difference = 2.68220901e-007 + epsilon_difference = 2.25000000 + ] +*/ + //] [/compare_floats_example_3] + +//[compare_floats_example_4] +/*` +Zeros are always treated as equal, as are infinities as long as they have the same sign:*/ + + a = 0; + b = -0; // signed zero + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + a = b = std::numeric_limits<float>::infinity(); + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "relative_difference = " << relative_difference(a, -b) << std::endl; + +/*` +Which produces the output: + +[pre +relative_difference = 0.000000000 +relative_difference = 0.000000000 +relative_difference = 3.40282347e+038 +] +*/ +//] [/compare_floats_example_4] + +//[compare_floats_example_5] +/*` +Note that finite values are always infinitely far away from infinities even if those finite values are very large:*/ + + a = (std::numeric_limits<float>::max)(); + b = std::numeric_limits<float>::infinity(); + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(a, b) << std::endl; + +/*` +Which produces the output: + +[pre +a = 3.40282347e+038 +b = 1.#INF0000 +relative_difference = 3.40282347e+038 +epsilon_difference = 3.40282347e+038 +] +*/ +//] [/compare_floats_example_5] + +//[compare_floats_example_6] +/*` +Finally, all denormalized values and zeros are treated as being effectively equal:*/ + + a = std::numeric_limits<float>::denorm_min(); + b = a * 2; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "float_distance = " << float_distance(a, b) << std::endl; + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(a, b) << std::endl; + a = 0; + std::cout << "a = " << a << std::endl; + std::cout << "b = " << b << std::endl; + std::cout << "float_distance = " << float_distance(a, b) << std::endl; + std::cout << "relative_difference = " << relative_difference(a, b) << std::endl; + std::cout << "epsilon_difference = " << epsilon_difference(a, b) << std::endl; + +/*` +Which produces the output: + +[pre +a = 1.40129846e-045 +b = 2.80259693e-045 +float_distance = 1.00000000 +relative_difference = 0.000000000 +epsilon_difference = 0.000000000 +a = 0.000000000 +b = 2.80259693e-045 +float_distance = 2.00000000 +relative_difference = 0.000000000 +epsilon_difference = 0.000000000] + +Notice how, in the above example, two denormalized values that are a factor of 2 apart are +none the less only one representation apart! + +*/ +//] [/compare_floats_example_6] + + +#if 0 +//[old_compare_floats_example_3 +//`The simplest use is to compare two values with a tolerance thus: + + bool is_close = is_close_to(1.F, 1.F + epsilon, epsilon); // One epsilon apart is close enough. + std::cout << "is_close_to(1.F, 1.F + epsilon, epsilon); is " << is_close << std::endl; // true + + is_close = is_close_to(1.F, 1.F + 2 * epsilon, epsilon); // Two epsilon apart isn't close enough. + std::cout << "is_close_to(1.F, 1.F + epsilon, epsilon); is " << is_close << std::endl; // false + +/*` +[note The type FPT of the tolerance and the type of the values [*must match]. + +So `is_close(0.1F, 1., 1.)` will fail to compile because "template parameter 'FPT' is ambiguous". +Always provide the same type, using `static_cast<FPT>` if necessary.] +*/ + + +/*`An instance of class `close_at_tolerance` is more convenient +when multiple tests with the same conditions are planned. +A class that stores a tolerance of three epsilon (and the default ['strong] test) is: +*/ + + close_at_tolerance<float> three_rounds(3 * epsilon); // 'strong' by default. + +//`and we can confirm these settings: + + std::cout << "fraction_tolerance = " + << three_rounds.fraction_tolerance() + << std::endl; // +3.57627869e-007 + std::cout << "strength = " + << (three_rounds.strength() == FPC_STRONG ? "strong" : "weak") + << std::endl; // strong + +//`To start, let us use two values that are truly equal (having identical bit patterns) + + float a = 1.23456789F; + float b = 1.23456789F; + +//`and make a comparison using our 3*epsilon `three_rounds` functor: + + bool close = three_rounds(a, b); + std::cout << "three_rounds(a, b) = " << close << std::endl; // true + +//`Unsurprisingly, the result is true, and the failed fraction is zero. + + std::cout << "failed_fraction = " << three_rounds.failed_fraction() << std::endl; + +/*`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> + +and some using declarations: +*/ + + using boost::math::float_next; + using boost::math::float_prior; + using boost::math::nextafter; + using boost::math::float_distance; + +//`To add a few __ulp to one value: + b = float_next(a); // Add just one ULP to a. + b = float_next(b); // Add another one ULP. + b = float_next(b); // Add another one ULP. + // 3 epsilon would pass. + b = float_next(b); // Add another one ULP. + +//`and repeat our comparison: + + close = three_rounds(a, b); + std::cout << "three_rounds(a, b) = " << close << std::endl; // false + std::cout << "failed_fraction = " << three_rounds.failed_fraction() + << std::endl; // abs(u-v) / abs(v) = 3.86237957e-007 + +//`We can also 'measure' the number of bits different using the `float_distance` function: + + std::cout << "float_distance = " << float_distance(a, b) << std::endl; // 4 + +/*`Now consider two values that are much further apart +than one might expect from ['computational noise], +perhaps the result of two measurements of some physical property like length +where an uncertainty of a percent or so might be expected. +*/ + float fp1 = 0.01000F; + float fp2 = 0.01001F; // Slightly different. + + float tolerance = 0.0001F; + + close_at_tolerance<float> strong(epsilon); // Default is strong. + bool rs = strong(fp1, fp2); + std::cout << "strong(fp1, fp2) is " << rs << std::endl; + +//`Or we could contrast using the ['weak] criterion: + close_at_tolerance<float> weak(epsilon, FPC_WEAK); // Explicitly weak. + bool rw = weak(fp1, fp2); // + std::cout << "weak(fp1, fp2) is " << rw << std::endl; + +//`We can also construct, setting tolerance and strength, and compare in one statement: + + std::cout << a << " #= " << b << " is " + << close_at_tolerance<float>(epsilon, FPC_STRONG)(a, b) << std::endl; + std::cout << a << " ~= " << b << " is " + << close_at_tolerance<float>(epsilon, FPC_WEAK)(a, b) << std::endl; + +//`but this has little advantage over using function `is_close_to` directly. + +//] [/old_compare_floats_example_3] + + +/*When the floating-point values become very small and near zero, using +//a relative test becomes unhelpful because one is dividing by zero or tiny, + +//Instead, an absolute test is needed, comparing one (or usually both) values with zero, +//using a tolerance. +//This is provided by the `small_with_tolerance` class and `is_small` function. + + namespace boost { + namespace math { + namespace fpc { + + + template<typename FPT> + class small_with_tolerance + { + public: + // Public typedefs. + typedef bool result_type; + + // Constructor. + explicit small_with_tolerance(FPT tolerance); // tolerance >= 0 + + // Functor + bool operator()(FPT value) const; // return true if <= absolute tolerance (near zero). + }; + + template<typename FPT> + bool + is_small(FPT value, FPT tolerance); // return true if value <= absolute tolerance (near zero). + + }}} // namespaces. + +/*` +[note The type FPT of the tolerance and the type of the value [*must match]. + +So `is_small(0.1F, 0.000001)` will fail to compile because "template parameter 'FPT' is ambiguous". +Always provide the same type, using `static_cast<FPT>` if necessary.] + +A few values near zero are tested with varying tolerance below. +*/ +//[compare_floats_small_1 + + float c = 0; + std::cout << "0 is_small " << is_small(c, epsilon) << std::endl; // true + + c = std::numeric_limits<float>::denorm_min(); // 1.40129846e-045 + std::cout << "denorm_ min =" << c << ", is_small is " << is_small(c, epsilon) << std::endl; // true + + c = (std::numeric_limits<float>::min)(); // 1.17549435e-038 + std::cout << "min = " << c << ", is_small is " << is_small(c, epsilon) << std::endl; // true + + c = 1 * epsilon; // 1.19209290e-007 + std::cout << "epsilon = " << c << ", is_small is " << is_small(c, epsilon) << std::endl; // false + + c = 1 * epsilon; // 1.19209290e-007 + std::cout << "2 epsilon = " << c << ", is_small is " << is_small(c, 2 * epsilon) << std::endl; // true + + c = 2 * epsilon; //2.38418579e-007 + std::cout << "4 epsilon = " << c << ", is_small is " << is_small(c, 2 * epsilon) << std::endl; // false + + c = 0.00001F; + std::cout << "0.00001 = " << c << ", is_small is " << is_small(c, 0.0001F) << std::endl; // true + + c = -0.00001F; + std::cout << "0.00001 = " << c << ", is_small is " << is_small(c, 0.0001F) << std::endl; // true + +/*`Using the class `small_with_tolerance` allows storage of the tolerance, +convenient if you make repeated tests with the same tolerance. +*/ + + small_with_tolerance<float>my_test(0.01F); + + std::cout << "my_test(0.001F) is " << my_test(0.001F) << std::endl; // true + std::cout << "my_test(0.001F) is " << my_test(0.01F) << std::endl; // false + + //] [/compare_floats_small_1] +#endif + return 0; +} // int main() + +/* + +Example output is: + +//[compare_floats_output +Compare floats using Boost.Test functions/classes + +float epsilon = 1.19209290e-007 +is_close_to(1.F, 1.F + epsilon, epsilon); is true +is_close_to(1.F, 1.F + epsilon, epsilon); is false +fraction_tolerance = 3.57627869e-007 +strength = strong +three_rounds(a, b) = true +failed_fraction = 0.000000000 +three_rounds(a, b) = false +failed_fraction = 3.86237957e-007 +float_distance = 4.00000000 +strong(fp1, fp2) is false +weak(fp1, fp2) is false +1.23456788 #= 1.23456836 is false +1.23456788 ~= 1.23456836 is false +0 is_small true +denorm_ min =1.40129846e-045, is_small is true +min = 1.17549435e-038, is_small is true +epsilon = 1.19209290e-007, is_small is false +2 epsilon = 1.19209290e-007, is_small is true +4 epsilon = 2.38418579e-007, is_small is false +0.00001 = 9.99999975e-006, is_small is true +0.00001 = -9.99999975e-006, is_small is true +my_test(0.001F) is true + +my_test(0.001F) is false//] [/compare_floats_output] +*/ diff --git a/src/boost/libs/math/example/gauss_example.cpp b/src/boost/libs/math/example/gauss_example.cpp new file mode 100644 index 000000000..466d58b4c --- /dev/null +++ b/src/boost/libs/math/example/gauss_example.cpp @@ -0,0 +1,142 @@ +/* + * Copyright John Maddock, 2017 + * 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) + * + * This example Illustrates numerical integration via Gauss and Gauss-Kronrod quadrature. + */ + +#include <iostream> +#include <cmath> +#include <limits> +#include <boost/math/quadrature/gauss.hpp> +#include <boost/math/quadrature/gauss_kronrod.hpp> +#include <boost/math/constants/constants.hpp> +#include <boost/math/special_functions/relative_difference.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> + +void gauss_examples() +{ + //[gauss_example + + /*` + We'll begin by integrating t[super 2] atan(t) over (0,1) using a 7 term Gauss-Legendre rule, + and begin by defining the function to integrate as a C++ lambda expression: + */ + using namespace boost::math::quadrature; + + auto f = [](const double& t) { return t * t * std::atan(t); }; + + /*` + Integration is simply a matter of calling the `gauss<double, 7>::integrate` method: + */ + + double Q = gauss<double, 7>::integrate(f, 0, 1); + + /*` + Which yields a value 0.2106572512 accurate to 1e-10. + + For more accurate evaluations, we'll move to a multiprecision type and use a 20-point integration scheme: + */ + + using boost::multiprecision::cpp_bin_float_quad; + + auto f2 = [](const cpp_bin_float_quad& t) { return t * t * atan(t); }; + + cpp_bin_float_quad Q2 = gauss<cpp_bin_float_quad, 20>::integrate(f2, 0, 1); + + /*` + Which yields 0.2106572512258069881080923020669, which is accurate to 5e-28. + */ + + //] + + std::cout << std::setprecision(18) << Q << std::endl; + std::cout << boost::math::relative_difference(Q, (boost::math::constants::pi<double>() - 2 + 2 * boost::math::constants::ln_two<double>()) / 12) << std::endl; + + std::cout << std::setprecision(34) << Q2 << std::endl; + std::cout << boost::math::relative_difference(Q2, (boost::math::constants::pi<cpp_bin_float_quad>() - 2 + 2 * boost::math::constants::ln_two<cpp_bin_float_quad>()) / 12) << std::endl; +} + +void gauss_kronrod_examples() +{ + //[gauss_kronrod_example + + /*` + We'll begin by integrating exp(-t[super 2]/2) over (0,+[infin]) using a 7 term Gauss rule + and 15 term Kronrod rule, + and begin by defining the function to integrate as a C++ lambda expression: + */ + using namespace boost::math::quadrature; + + auto f1 = [](double t) { return std::exp(-t*t / 2); }; + + //<- + double Q_expected = sqrt(boost::math::constants::half_pi<double>()); + //-> + + /*` + We'll start off with a one shot (ie non-adaptive) + integration, and keep track of the estimated error: + */ + double error; + double Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 0, 0, &error); + + /*` + This yields Q = 1.25348207361, which has an absolute error of 1e-4 compared to the estimated error + of 5e-3: this is fairly typical, with the difference between Gauss and Gauss-Kronrod schemes being + much higher than the actual error. Before moving on to adaptive quadrature, lets try again + with more points, in fact with the largest Gauss-Kronrod scheme we have cached (30/61): + */ + //<- + std::cout << std::setprecision(16) << Q << std::endl; + std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl; + std::cout << fabs(Q - Q_expected) << std::endl; + std::cout << error << std::endl; + //-> + Q = gauss_kronrod<double, 61>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 0, 0, &error); + //<- + std::cout << std::setprecision(16) << Q << std::endl; + std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl; + std::cout << fabs(Q - Q_expected) << std::endl; + std::cout << error << std::endl; + //-> + /*` + This yields an absolute error of 3e-15 against an estimate of 1e-8, which is about as good as we're going to get + at double precision + + However, instead of continuing with ever more points, lets switch to adaptive integration, and set the desired relative + error to 1e-14 against a maximum depth of 5: + */ + Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 5, 1e-14, &error); + //<- + std::cout << std::setprecision(16) << Q << std::endl; + std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl; + std::cout << fabs(Q - Q_expected) << std::endl; + std::cout << error << std::endl; + //-> + /*` + This yields an actual error of zero, against an estimate of 4e-15. In fact in this case the requested tolerance was almost + certainly set too low: as we've seen above, for smooth functions, the precision achieved is often double + that of the estimate, so if we integrate with a tolerance of 1e-9: + */ + Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 5, 1e-9, &error); + //<- + std::cout << std::setprecision(16) << Q << std::endl; + std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl; + std::cout << fabs(Q - Q_expected) << std::endl; + std::cout << error << std::endl; + //-> + /*` + We still achieve 1e-15 precision, with an error estimate of 1e-10. + */ + //] +} + +int main() +{ + gauss_examples(); + gauss_kronrod_examples(); + return 0; +} diff --git a/src/boost/libs/math/example/geometric_examples.cpp b/src/boost/libs/math/example/geometric_examples.cpp new file mode 100644 index 000000000..92ea28e56 --- /dev/null +++ b/src/boost/libs/math/example/geometric_examples.cpp @@ -0,0 +1,364 @@ +// geometric_examples.cpp + +// Copyright Paul A. Bristow 2010. + +// 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) + +// This file is written to be included from a Quickbook .qbk document. +// It can still be compiled by the C++ compiler, and run. +// Any output can also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +// Examples of using the geometric distribution. + +//[geometric_eg1_1 +/*` +For this example, we will opt to #define two macros to control +the error and discrete handling policies. +For this simple example, we want to avoid throwing +an exception (the default policy) and just return infinity. +We want to treat the distribution as if it was continuous, +so we choose a discrete_quantile policy of real, +rather than the default policy integer_round_outwards. +*/ +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real +/*` +[caution It is vital to #include distributions etc *after* the above #defines] +After that we need some includes to provide easy access to the negative binomial distribution, +and we need some std library iostream, of course. +*/ +#include <boost/math/distributions/geometric.hpp> + // for geometric_distribution + using ::boost::math::geometric_distribution; // + using ::boost::math::geometric; // typedef provides default type is double. + using ::boost::math::pdf; // Probability mass function. + using ::boost::math::cdf; // Cumulative density function. + using ::boost::math::quantile; + +#include <boost/math/distributions/negative_binomial.hpp> + // for negative_binomial_distribution + using boost::math::negative_binomial; // typedef provides default type is double. + +#include <boost/math/distributions/normal.hpp> + // for negative_binomial_distribution + using boost::math::normal; // typedef provides default type is double. + +#include <iostream> + using std::cout; using std::endl; + using std::noshowpoint; using std::fixed; using std::right; using std::left; +#include <iomanip> + using std::setprecision; using std::setw; + +#include <limits> + using std::numeric_limits; +//] [geometric_eg1_1] + +int main() +{ + cout <<"Geometric distribution example" << endl; + cout << endl; + + cout.precision(4); // But only show a few for this example. + try + { +//[geometric_eg1_2 +/*` +It is always sensible to use try and catch blocks because defaults policies are to +throw an exception if anything goes wrong. + +Simple try'n'catch blocks (see below) will ensure that you get a +helpful error message instead of an abrupt (and silent) program abort. + +[h6 Throwing a dice] +The Geometric distribution describes the probability (/p/) of a number of failures +to get the first success in /k/ Bernoulli trials. +(A [@http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli trial] +is one with only two possible outcomes, success of failure, +and /p/ is the probability of success). + +Suppose an 'fair' 6-face dice is thrown repeatedly: +*/ + double success_fraction = 1./6; // success_fraction (p) = 0.1666 + // (so failure_fraction is 1 - success_fraction = 5./6 = 1- 0.1666 = 0.8333) + +/*`If the dice is thrown repeatedly until the *first* time a /three/ appears. +The probability distribution of the number of times it is thrown *not* getting a /three/ + (/not-a-threes/ number of failures to get a /three/) +is a geometric distribution with the success_fraction = 1/6 = 0.1666[recur]. + +We therefore start by constructing a geometric distribution +with the one parameter success_fraction, the probability of success. +*/ + geometric g6(success_fraction); // type double by default. +/*` +To confirm, we can echo the success_fraction parameter of the distribution. +*/ + cout << "success fraction of a six-sided dice is " << g6.success_fraction() << endl; +/*`So the probability of getting a three at the first throw (zero failures) is +*/ + cout << pdf(g6, 0) << endl; // 0.1667 + cout << cdf(g6, 0) << endl; // 0.1667 +/*`Note that the cdf and pdf are identical because the is only one throw. +If we want the probability of getting the first /three/ on the 2nd throw: +*/ + cout << pdf(g6, 1) << endl; // 0.1389 + +/*`If we want the probability of getting the first /three/ on the 1st or 2nd throw +(allowing one failure): +*/ + cout << "pdf(g6, 0) + pdf(g6, 1) = " << pdf(g6, 0) + pdf(g6, 1) << endl; +/*`Or more conveniently, and more generally, +we can use the Cumulative Distribution Function CDF.*/ + + cout << "cdf(g6, 1) = " << cdf(g6, 1) << endl; // 0.3056 + +/*`If we allow many more (12) throws, the probability of getting our /three/ gets very high:*/ + cout << "cdf(g6, 12) = " << cdf(g6, 12) << endl; // 0.9065 or 90% probability. +/*`If we want to be much more confident, say 99%, +we can estimate the number of throws to be this sure +using the inverse or quantile. +*/ + cout << "quantile(g6, 0.99) = " << quantile(g6, 0.99) << endl; // 24.26 +/*`Note that the value returned is not an integer: +if you want an integer result you should use either floor, round or ceil functions, +or use the policies mechanism. + +See __understand_dis_quant. + +The geometric distribution is related to the negative binomial +__spaces `negative_binomial_distribution(RealType r, RealType p);` with parameter /r/ = 1. +So we could get the same result using the negative binomial, +but using the geometric the results will be faster, and may be more accurate. +*/ + negative_binomial nb(1, success_fraction); + cout << pdf(nb, 1) << endl; // 0.1389 + cout << cdf(nb, 1) << endl; // 0.3056 +/*`We could also the complement to express the required probability +as 1 - 0.99 = 0.01 (and get the same result): +*/ + cout << "quantile(complement(g6, 1 - p)) " << quantile(complement(g6, 0.01)) << endl; // 24.26 +/*` +Note too that Boost.Math geometric distribution is implemented as a continuous function. +Unlike other implementations (for example R) it *uses* the number of failures as a *real* parameter, +not as an integer. If you want this integer behaviour, you may need to enforce this by +rounding the parameter you pass, probably rounding down, to the nearest integer. +For example, R returns the success fraction probability for all values of failures +from 0 to 0.999999 thus: +[pre +__spaces R> formatC(pgeom(0.0001,0.5, FALSE), digits=17) " 0.5" +] [/pre] +So in Boost.Math the equivalent is +*/ + geometric g05(0.5); // Probability of success = 0.5 or 50% + // Output all potentially significant digits for the type, here double. + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + int max_digits10 = 2 + (boost::math::policies::digits<double, boost::math::policies::policy<> >() * 30103UL) / 100000UL; + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined" << endl; +#else + int max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = " + << max_digits10 << endl; + cout.precision(max_digits10); // + + cout << cdf(g05, 0.0001) << endl; // returns 0.5000346561579232, not exact 0.5. +/*`To get the R discrete behaviour, you simply need to round with, +for example, the `floor` function. +*/ + cout << cdf(g05, floor(0.0001)) << endl; // returns exactly 0.5 +/*` +[pre +`> formatC(pgeom(0.9999999,0.5, FALSE), digits=17) [1] " 0.25"` +`> formatC(pgeom(1.999999,0.5, FALSE), digits=17)[1] " 0.25" k = 1` +`> formatC(pgeom(1.9999999,0.5, FALSE), digits=17)[1] "0.12500000000000003" k = 2` +] [/pre] +shows that R makes an arbitrary round-up decision at about 1e7 from the next integer above. +This may be convenient in practice, and could be replicated in C++ if desired. + +[h6 Surveying customers to find one with a faulty product] +A company knows from warranty claims that 2% of their products will be faulty, +so the 'success_fraction' of finding a fault is 0.02. +It wants to interview a purchaser of faulty products to assess their 'user experience'. + +To estimate how many customers they will probably need to contact +in order to find one who has suffered from the fault, +we first construct a geometric distribution with probability 0.02, +and then chose a confidence, say 80%, 95%, or 99% to finding a customer with a fault. +Finally, we probably want to round up the result to the integer above using the `ceil` function. +(We could also use a policy, but that is hardly worthwhile for this simple application.) + +(This also assumes that each customer only buys one product: +if customers bought more than one item, +the probability of finding a customer with a fault obviously improves.) +*/ + cout.precision(5); + geometric g(0.02); // On average, 2 in 100 products are faulty. + double c = 0.95; // 95% confidence. + cout << " quantile(g, " << c << ") = " << quantile(g, c) << endl; + + cout << "To be " << c * 100 + << "% confident of finding we customer with a fault, need to survey " + << ceil(quantile(g, c)) << " customers." << endl; // 148 + c = 0.99; // Very confident. + cout << "To be " << c * 100 + << "% confident of finding we customer with a fault, need to survey " + << ceil(quantile(g, c)) << " customers." << endl; // 227 + c = 0.80; // Only reasonably confident. + cout << "To be " << c * 100 + << "% confident of finding we customer with a fault, need to survey " + << ceil(quantile(g, c)) << " customers." << endl; // 79 + +/*`[h6 Basket Ball Shooters] +According to Wikipedia, average pro basket ball players get +[@http://en.wikipedia.org/wiki/Free_throw free throws] +in the baskets 70 to 80 % of the time, +but some get as high as 95%, and others as low as 50%. +Suppose we want to compare the probabilities +of failing to get a score only on the first or on the fifth shot? +To start we will consider the average shooter, say 75%. +So we construct a geometric distribution +with success_fraction parameter 75/100 = 0.75. +*/ + cout.precision(2); + geometric gav(0.75); // Shooter averages 7.5 out of 10 in the basket. +/*`What is probability of getting 1st try in the basket, that is with no failures? */ + cout << "Probability of score on 1st try = " << pdf(gav, 0) << endl; // 0.75 +/*`This is, of course, the success_fraction probability 75%. +What is the probability that the shooter only scores on the fifth shot? +So there are 5-1 = 4 failures before the first success.*/ + cout << "Probability of score on 5th try = " << pdf(gav, 4) << endl; // 0.0029 +/*`Now compare this with the poor and the best players success fraction. +We need to constructing new distributions with the different success fractions, +and then get the corresponding probability density functions values: +*/ + geometric gbest(0.95); + cout << "Probability of score on 5th try = " << pdf(gbest, 4) << endl; // 5.9e-6 + geometric gmediocre(0.50); + cout << "Probability of score on 5th try = " << pdf(gmediocre, 4) << endl; // 0.031 +/*`So we can see the very much smaller chance (0.000006) of 4 failures by the best shooters, +compared to the 0.03 of the mediocre.*/ + +/*`[h6 Estimating failures] +Of course one man's failure is an other man's success. +So a fault can be defined as a 'success'. + +If a fault occurs once after 100 flights, then one might naively say +that the risk of fault is obviously 1 in 100 = 1/100, a probability of 0.01. + +This is the best estimate we can make, but while it is the truth, +it is not the whole truth, +for it hides the big uncertainty when estimating from a single event. +"One swallow doesn't make a summer." +To show the magnitude of the uncertainty, the geometric +(or the negative binomial) distribution can be used. + +If we chose the popular 95% confidence in the limits, corresponding to an alpha of 0.05, +because we are calculating a two-sided interval, we must divide alpha by two. +*/ + double alpha = 0.05; + double k = 100; // So frequency of occurrence is 1/100. + cout << "Probability is failure is " << 1/k << endl; + double t = geometric::find_lower_bound_on_p(k, alpha/2); + cout << "geometric::find_lower_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 0.00025 + t = geometric::find_upper_bound_on_p(k, alpha/2); + cout << "geometric::find_upper_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 0.037 +/*`So while we estimate the probability is 0.01, it might lie between 0.0003 and 0.04. +Even if we relax our confidence to alpha = 90%, the bounds only contract to 0.0005 and 0.03. +And if we require a high confidence, they widen to 0.00005 to 0.05. +*/ + alpha = 0.1; // 90% confidence. + t = geometric::find_lower_bound_on_p(k, alpha/2); + cout << "geometric::find_lower_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 0.0005 + t = geometric::find_upper_bound_on_p(k, alpha/2); + cout << "geometric::find_upper_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 0.03 + + alpha = 0.01; // 99% confidence. + t = geometric::find_lower_bound_on_p(k, alpha/2); + cout << "geometric::find_lower_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 5e-005 + t = geometric::find_upper_bound_on_p(k, alpha/2); + cout << "geometric::find_upper_bound_on_p(" << int(k) << ", " << alpha/2 << ") = " + << t << endl; // 0.052 +/*`In real life, there will usually be more than one event (fault or success), +when the negative binomial, which has the necessary extra parameter, will be needed. +*/ + +/*`As noted above, using a catch block is always a good idea, +even if you hope not to use it! +*/ + } + catch(const std::exception& e) + { // Since we have set an overflow policy of ignore_error, + // an overflow exception should never be thrown. + std::cout << "\nMessage from thrown exception was:\n " << e.what() << std::endl; +/*` +For example, without a ignore domain error policy, +if we asked for ``pdf(g, -1)`` for example, +we would get an unhelpful abort, but with a catch: +[pre +Message from thrown exception was: + Error in function boost::math::pdf(const exponential_distribution<double>&, double): + Number of failures argument is -1, but must be >= 0 ! +] [/pre] +*/ +//] [/ geometric_eg1_2] + } + return 0; +} // int main() + + +/* +Output is: + + Geometric distribution example + + success fraction of a six-sided dice is 0.1667 + 0.1667 + 0.1667 + 0.1389 + pdf(g6, 0) + pdf(g6, 1) = 0.3056 + cdf(g6, 1) = 0.3056 + cdf(g6, 12) = 0.9065 + quantile(g6, 0.99) = 24.26 + 0.1389 + 0.3056 + quantile(complement(g6, 1 - p)) 24.26 + 0.5000346561579232 + 0.5 + quantile(g, 0.95) = 147.28 + To be 95% confident of finding we customer with a fault, need to survey 148 customers. + To be 99% confident of finding we customer with a fault, need to survey 227 customers. + To be 80% confident of finding we customer with a fault, need to survey 79 customers. + Probability of score on 1st try = 0.75 + Probability of score on 5th try = 0.0029 + Probability of score on 5th try = 5.9e-006 + Probability of score on 5th try = 0.031 + Probability is failure is 0.01 + geometric::find_lower_bound_on_p(100, 0.025) = 0.00025 + geometric::find_upper_bound_on_p(100, 0.025) = 0.037 + geometric::find_lower_bound_on_p(100, 0.05) = 0.00051 + geometric::find_upper_bound_on_p(100, 0.05) = 0.03 + geometric::find_lower_bound_on_p(100, 0.005) = 5e-005 + geometric::find_upper_bound_on_p(100, 0.005) = 0.052 + +*/ + + + + + + + + + + diff --git a/src/boost/libs/math/example/handle_test_result.hpp b/src/boost/libs/math/example/handle_test_result.hpp new file mode 100644 index 000000000..88a908c48 --- /dev/null +++ b/src/boost/libs/math/example/handle_test_result.hpp @@ -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(__INTEL_COMPILER) +# 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<std::uintmax_t, std::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, + std::uintmax_t max_peek_error, + std::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<std::uintmax_t, std::uintmax_t>& + get_max_errors(const char* type_name, const char* test_name, const char* group_name) +{ + static const std::pair<std::uintmax_t, std::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 _MSC_VER +#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<std::uintmax_t, std::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 _MSC_VER +#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 + diff --git a/src/boost/libs/math/example/hyperexponential_more_snips.cpp b/src/boost/libs/math/example/hyperexponential_more_snips.cpp new file mode 100644 index 000000000..ba9d5010e --- /dev/null +++ b/src/boost/libs/math/example/hyperexponential_more_snips.cpp @@ -0,0 +1,155 @@ +// Copyright 2014 Marco Guazzone (marco.guazzone@gmail.com). + +// 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) + +// Caution: this file contains Quickbook markup as well as code +// and comments, don't change any of the special comment markups! + + +//[hyperexponential_more_snip1 +#include <boost/math/distributions.hpp> +#include <iostream> +#include <string> + +struct ds_info +{ + std::string name; + double iat_sample_mean; + double iat_sample_sd; + boost::math::hyperexponential iat_he; + double multi_lt_sample_mean; + double multi_lt_sample_sd; + boost::math::hyperexponential multi_lt_he; + double single_lt_sample_mean; + double single_lt_sample_sd; + boost::math::hyperexponential single_lt_he; +}; + +// DS1 dataset +ds_info make_ds1() +{ + ds_info ds; + + ds.name = "DS1"; + + // VM interarrival time distribution + const double iat_fit_probs[] = { 0.34561,0.08648,0.56791 }; + const double iat_fit_rates[] = { 0.0008,0.00005,0.02894 }; + ds.iat_sample_mean = 2202.1; + ds.iat_sample_sd = 2.2e+4; + ds.iat_he = boost::math::hyperexponential(iat_fit_probs, iat_fit_rates); + + // Multi-core VM lifetime distribution + const double multi_lt_fit_probs[] = { 0.24667,0.37948,0.37385 }; + const double multi_lt_fit_rates[] = { 0.00004,0.000002,0.00059 }; + ds.multi_lt_sample_mean = 257173; + ds.multi_lt_sample_sd = 4.6e+5; + ds.multi_lt_he = boost::math::hyperexponential(multi_lt_fit_probs, multi_lt_fit_rates); + + // Single-core VM lifetime distribution + const double single_lt_fit_probs[] = { 0.09325,0.22251,0.68424 }; + const double single_lt_fit_rates[] = { 0.000003,0.00109,0.00109 }; + ds.single_lt_sample_mean = 28754.4; + ds.single_lt_sample_sd = 1.6e+5; + ds.single_lt_he = boost::math::hyperexponential(single_lt_fit_probs, single_lt_fit_rates); + + return ds; +} + +// DS2 dataset +ds_info make_ds2() +{ + ds_info ds; + + ds.name = "DS2"; + + // VM interarrival time distribution + const double iat_fit_probs[] = { 0.38881,0.18227,0.42892 }; + const double iat_fit_rates[] = { 0.000006,0.05228,0.00081 }; + ds.iat_sample_mean = 41285.7; + ds.iat_sample_sd = 1.1e+05; + ds.iat_he = boost::math::hyperexponential(iat_fit_probs, iat_fit_rates); + + // Multi-core VM lifetime distribution + const double multi_lt_fit_probs[] = { 0.42093,0.43960,0.13947 }; + const double multi_lt_fit_rates[] = { 0.00186,0.00008,0.0000008 }; + ds.multi_lt_sample_mean = 144669.0; + ds.multi_lt_sample_sd = 7.9e+05; + ds.multi_lt_he = boost::math::hyperexponential(multi_lt_fit_probs, multi_lt_fit_rates); + + // Single-core VM lifetime distribution + const double single_lt_fit_probs[] = { 0.44885,0.30675,0.2444 }; + const double single_lt_fit_rates[] = { 0.00143,0.00005,0.0000004 }; + ds.single_lt_sample_mean = 599815.0; + ds.single_lt_sample_sd = 1.7e+06; + ds.single_lt_he = boost::math::hyperexponential(single_lt_fit_probs, single_lt_fit_rates); + + return ds; +} + +// DS3 dataset +ds_info make_ds3() +{ + ds_info ds; + + ds.name = "DS3"; + + // VM interarrival time distribution + const double iat_fit_probs[] = { 0.39442,0.24644,0.35914 }; + const double iat_fit_rates[] = { 0.00030,0.00003,0.00257 }; + ds.iat_sample_mean = 11238.8; + ds.iat_sample_sd = 3.0e+04; + ds.iat_he = boost::math::hyperexponential(iat_fit_probs, iat_fit_rates); + + // Multi-core VM lifetime distribution + const double multi_lt_fit_probs[] = { 0.37621,0.14838,0.47541 }; + const double multi_lt_fit_rates[] = { 0.00498,0.000005,0.00022 }; + ds.multi_lt_sample_mean = 30739.2; + ds.multi_lt_sample_sd = 1.6e+05; + ds.multi_lt_he = boost::math::hyperexponential(multi_lt_fit_probs, multi_lt_fit_rates); + + // Single-core VM lifetime distribution + const double single_lt_fit_probs[] = { 0.34131,0.12544,0.53325 }; + const double single_lt_fit_rates[] = { 0.000297,0.000003,0.00410 }; + ds.single_lt_sample_mean = 44447.8; + ds.single_lt_sample_sd = 2.2e+05; + ds.single_lt_he = boost::math::hyperexponential(single_lt_fit_probs, single_lt_fit_rates); + + return ds; +} + +void print_fitted(ds_info const& ds) +{ + const double secs_in_a_hour = 3600; + const double secs_in_a_month = 30 * 24 * secs_in_a_hour; + + std::cout << "### " << ds.name << std::endl; + std::cout << "* Fitted Request Interarrival Time" << std::endl; + std::cout << " - Mean (SD): " << boost::math::mean(ds.iat_he) << " (" << boost::math::standard_deviation(ds.iat_he) << ") seconds." << std::endl; + std::cout << " - 99th Percentile: " << boost::math::quantile(ds.iat_he, 0.99) << " seconds." << std::endl; + std::cout << " - Probability that a VM will arrive within 30 minutes: " << boost::math::cdf(ds.iat_he, secs_in_a_hour / 2.0) << std::endl; + std::cout << " - Probability that a VM will arrive after 1 hour: " << boost::math::cdf(boost::math::complement(ds.iat_he, secs_in_a_hour)) << std::endl; + std::cout << "* Fitted Multi-core VM Lifetime" << std::endl; + std::cout << " - Mean (SD): " << boost::math::mean(ds.multi_lt_he) << " (" << boost::math::standard_deviation(ds.multi_lt_he) << ") seconds." << std::endl; + std::cout << " - 99th Percentile: " << boost::math::quantile(ds.multi_lt_he, 0.99) << " seconds." << std::endl; + std::cout << " - Probability that a VM will last for less than 1 month: " << boost::math::cdf(ds.multi_lt_he, secs_in_a_month) << std::endl; + std::cout << " - Probability that a VM will last for more than 3 months: " << boost::math::cdf(boost::math::complement(ds.multi_lt_he, 3.0*secs_in_a_month)) << std::endl; + std::cout << "* Fitted Single-core VM Lifetime" << std::endl; + std::cout << " - Mean (SD): " << boost::math::mean(ds.single_lt_he) << " (" << boost::math::standard_deviation(ds.single_lt_he) << ") seconds." << std::endl; + std::cout << " - 99th Percentile: " << boost::math::quantile(ds.single_lt_he, 0.99) << " seconds." << std::endl; + std::cout << " - Probability that a VM will last for less than 1 month: " << boost::math::cdf(ds.single_lt_he, secs_in_a_month) << std::endl; + std::cout << " - Probability that a VM will last for more than 3 months: " << boost::math::cdf(boost::math::complement(ds.single_lt_he, 3.0*secs_in_a_month)) << std::endl; +} + +int main() +{ + print_fitted(make_ds1()); + + print_fitted(make_ds2()); + + print_fitted(make_ds3()); +} +//] diff --git a/src/boost/libs/math/example/hyperexponential_snips.cpp b/src/boost/libs/math/example/hyperexponential_snips.cpp new file mode 100644 index 000000000..694263246 --- /dev/null +++ b/src/boost/libs/math/example/hyperexponential_snips.cpp @@ -0,0 +1,103 @@ +// Copyright John Maddock 2014. + +// 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) + +// Caution: this file contains Quickbook markup as well as code +// and comments, don't change any of the special comment markups! + +#ifdef _MSC_VER +# pragma warning (disable : 4996) // disable -D_SCL_SECURE_NO_WARNINGS C++ 'Checked Iterators' +#endif + +#include <boost/math/distributions/hyperexponential.hpp> +#include <iostream> + +#ifndef BOOST_NO_CXX11_HDR_ARRAY +#include <array> +#endif + +int main() +{ + { +//[hyperexponential_snip1 +//=#include <boost/math/distributions/hyperexponential.hpp> +//=#include <iostream> +//=int main() +//={ + const double rates[] = { 1.0 / 10.0, 1.0 / 12.0 }; + + boost::math::hyperexponential he(rates); + + std::cout << "Average lifetime: " + << boost::math::mean(he) + << " years" << std::endl; + std::cout << "Probability that the appliance will work for more than 15 years: " + << boost::math::cdf(boost::math::complement(he, 15.0)) + << std::endl; +//=} +//] + } + using namespace boost::math; +#ifndef BOOST_NO_CXX11_HDR_ARRAY + { + //[hyperexponential_snip2 + std::array<double, 2> phase_prob = { 0.5, 0.5 }; + std::array<double, 2> rates = { 1.0 / 10, 1.0 / 12 }; + + hyperexponential he(phase_prob.begin(), phase_prob.end(), rates.begin(), rates.end()); + //] + } + + { + //[hyperexponential_snip3 + // We could be using any standard library container here... vector, deque, array, list etc: + std::array<double, 2> phase_prob = { 0.5, 0.5 }; + std::array<double, 2> rates = { 1.0 / 10, 1.0 / 12 }; + + hyperexponential he1(phase_prob, rates); // Construct from standard library container. + + double phase_probs2[] = { 0.5, 0.5 }; + double rates2[] = { 1.0 / 10, 1.0 / 12 }; + + hyperexponential he2(phase_probs2, rates2); // Construct from native C++ array. + //] + } + { + //[hyperexponential_snip4 + // We could be using any standard library container here... vector, deque, array, list etc: + std::array<double, 2> rates = { 1.0 / 10, 1.0 / 12 }; + + hyperexponential he(rates.begin(), rates.end()); + + BOOST_MATH_ASSERT(he.probabilities()[0] == 0.5); // Phase probabilities will be equal and normalised to unity. + //] + } + { + //[hyperexponential_snip5 + std::array<double, 2> rates = { 1.0 / 10, 1.0 / 12 }; + + hyperexponential he(rates); + + BOOST_MATH_ASSERT(he.probabilities()[0] == 0.5); // Phase probabilities will be equal and normalised to unity. + //] + } +#endif +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !(defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION < 40500)) + { + //[hyperexponential_snip6 + hyperexponential he = { { 0.5, 0.5 }, { 1.0 / 10, 1.0 / 12 } }; + //] + } + { + //[hyperexponential_snip7 + hyperexponential he = { 1.0 / 10, 1.0 / 12 }; + + BOOST_MATH_ASSERT(he.probabilities()[0] == 0.5); + //] + } +#endif + return 0; +} diff --git a/src/boost/libs/math/example/inspect_fp.cpp b/src/boost/libs/math/example/inspect_fp.cpp new file mode 100644 index 000000000..71ea686f4 --- /dev/null +++ b/src/boost/libs/math/example/inspect_fp.cpp @@ -0,0 +1,229 @@ +// inspect.cpp + +// Copyright (c) 2006 Johan Rade + +// 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) + +//------------------------------------- + +#include <cstring> + +#include <iomanip> +#include <iostream> +#include <limits> + +#ifndef BOOST_MATH_STANDALONE +#include <boost/endian.hpp> +#else +#include <boost/math/tools/config.hpp> +#endif + +//------------------------------------------------------------------------------ + +bool is_big_endian() +{ + float x = 1.0f; + unsigned char first_byte; + memcpy(&first_byte, &x, 1); + return first_byte != 0; +} + +//------------------------------------------------------------------------------ + +void print_processor(); +void print_endianness(); +template<class T> void print_table(); +template<class T> void print_row(const char* name, T val, bool ok = true); + +//------------------------------------------------------------------------------ + +int main() +{ + std::cout << '\n'; + + print_processor(); + + print_endianness(); + + std::cout << "---------- float --------------------\n\n"; + print_table<float>(); + + std::cout << "---------- double -------------------\n\n"; + print_table<double>(); + + std::cout << "---------- long double --------------\n\n"; + print_table<long double>(); + + return 0; +} + +//------------------------------------------------------------------------------ + +void print_processor() +{ +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \ + || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \ + || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) + + std::cout << "Processor: x86 or x64\n\n"; + +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + + std::cout << "Processor: ia64\n\n"; + +#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \ + || defined(__ppc) || defined(__ppc__) || defined(__PPC__) + + std::cout << "Processor: PowerPC\n\n"; + +#elif defined(__m68k) || defined(__m68k__) \ + || defined(__mc68000) || defined(__mc68000__) \ + + std::cout << "Processor: Motorola 68K\n\n"; + +#else + + std::cout << "Processor: Unknown\n\n"; + +#endif +} + +void print_endianness() +{ + if(is_big_endian()) + std::cout << "This platform is big-endian.\n"; + else + std::cout << "This platform is little-endian.\n"; + +#ifdef BOOST_BIG_ENDIAN + std::cout << "BOOST_BIG_ENDIAN is defined.\n\n"; +#endif +#if defined BOOST_LITTLE_ENDIAN + std::cout << "BOOST_LITTTLE_ENDIAN is defined.\n\n"; +#endif +} + +//.............................................................................. + +template<class T> void print_table() +{ + print_row("0", (T)0); + print_row("sn.min", std::numeric_limits<T>::denorm_min(), + std::numeric_limits<T>::has_denorm); + print_row("-sn.min", -std::numeric_limits<T>::denorm_min(), + std::numeric_limits<T>::has_denorm); + print_row("n.min/256", (std::numeric_limits<T>::min)()/256); + print_row("n.min/2", (std::numeric_limits<T>::min)()/2); + print_row("-n.min/2", -(std::numeric_limits<T>::min)()/2); + print_row("n.min", (std::numeric_limits<T>::min)()); + print_row("1", (T)1); + print_row("3/4", (T)3/(T)4); + print_row("4/3", (T)4/(T)3); + print_row("max", (std::numeric_limits<T>::max)()); + print_row("inf", std::numeric_limits<T>::infinity(), + std::numeric_limits<T>::has_infinity); + print_row("q.nan", std::numeric_limits<T>::quiet_NaN(), + std::numeric_limits<T>::has_quiet_NaN); + print_row("s.nan", std::numeric_limits<T>::signaling_NaN(), + std::numeric_limits<T>::has_signaling_NaN); + + std::cout << "\n\n"; +} + +template<class T> +void print_row(const char* name, T val, bool ok) +{ + std::cout << std::left << std::setw(10) << name << std::right; + + std::cout << std::hex << std::setfill('0'); + + if(ok) { + if(is_big_endian()) { + for(size_t i = 0; i < sizeof(T); ++i) { + unsigned char c = *(reinterpret_cast<unsigned char*>(&val) + i); + std::cout << std::setw(2) + << static_cast<unsigned int>(c) << ' '; + } + } + else { + for(size_t i = sizeof(T) - 1; i < sizeof(T); --i) { + unsigned char c = *(reinterpret_cast<unsigned char*>(&val) + i); + std::cout << std::setw(2) + << static_cast<unsigned int>(c) << ' '; + } + } + } + else { + for(size_t i = 0; i < sizeof(T); ++i) + std::cout << "-- "; + } + + std::cout << '\n'; + std::cout << std::dec << std::setfill(' '); +} + +/* + +Sample output on an AMD Quadcore running MSVC 10 + + Processor: x86 or x64 + + This platform is little-endian. + BOOST_LITTTLE_ENDIAN is defined. + + ---------- float -------------------- + + 0 00 00 00 00 + sn.min 00 00 00 01 + -sn.min 80 00 00 01 + n.min/256 00 00 80 00 + n.min/2 00 40 00 00 + -n.min/2 80 40 00 00 + n.min 00 80 00 00 + 1 3f 80 00 00 + 3/4 3f 40 00 00 + 4/3 3f aa aa ab + max 7f 7f ff ff + inf 7f 80 00 00 + q.nan 7f c0 00 00 + s.nan 7f c0 00 01 + + + ---------- double ------------------- + + 0 00 00 00 00 00 00 00 00 + sn.min 00 00 00 00 00 00 00 01 + -sn.min 80 00 00 00 00 00 00 01 + n.min/256 00 00 10 00 00 00 00 00 + n.min/2 00 08 00 00 00 00 00 00 + -n.min/2 80 08 00 00 00 00 00 00 + n.min 00 10 00 00 00 00 00 00 + 1 3f f0 00 00 00 00 00 00 + 3/4 3f e8 00 00 00 00 00 00 + 4/3 3f f5 55 55 55 55 55 55 + max 7f ef ff ff ff ff ff ff + inf 7f f0 00 00 00 00 00 00 + q.nan 7f f8 00 00 00 00 00 00 + s.nan 7f f8 00 00 00 00 00 01 + + + ---------- long double -------------- + + 0 00 00 00 00 00 00 00 00 + sn.min 00 00 00 00 00 00 00 01 + -sn.min 80 00 00 00 00 00 00 01 + n.min/256 00 00 10 00 00 00 00 00 + n.min/2 00 08 00 00 00 00 00 00 + -n.min/2 80 08 00 00 00 00 00 00 + n.min 00 10 00 00 00 00 00 00 + 1 3f f0 00 00 00 00 00 00 + 3/4 3f e8 00 00 00 00 00 00 + 4/3 3f f5 55 55 55 55 55 55 + max 7f ef ff ff ff ff ff ff + inf 7f f0 00 00 00 00 00 00 + q.nan 7f f8 00 00 00 00 00 00 + s.nan 7f f8 00 00 00 00 00 01 + + */ diff --git a/src/boost/libs/math/example/inverse_chi_squared_bayes_eg.cpp b/src/boost/libs/math/example/inverse_chi_squared_bayes_eg.cpp new file mode 100644 index 000000000..364094325 --- /dev/null +++ b/src/boost/libs/math/example/inverse_chi_squared_bayes_eg.cpp @@ -0,0 +1,338 @@ +// inverse_chi_squared_bayes_eg.cpp + +// Copyright Thomas Mang 2011. +// Copyright Paul A. Bristow 2011. + +// 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) + +// This file is written to be included from a Quickbook .qbk document. +// It can still be compiled by the C++ compiler, and run. +// Any output can also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +#include <iostream> +// using std::cout; using std::endl; + +//#define define possible error-handling macros here? + +#include "boost/math/distributions.hpp" +// using ::boost::math::inverse_chi_squared; + +int main() +{ + using std::cout; using std::endl; + + using ::boost::math::inverse_chi_squared; + using ::boost::math::inverse_gamma; + using ::boost::math::quantile; + using ::boost::math::cdf; + + cout << "Inverse_chi_squared_distribution Bayes example: " << endl <<endl; + + cout.precision(3); +// Examples of using the inverse_chi_squared distribution. + +//[inverse_chi_squared_bayes_eg_1 +/*` +The scaled-inversed-chi-squared distribution is the conjugate prior distribution +for the variance ([sigma][super 2]) parameter of a normal distribution +with known expectation ([mu]). +As such it has widespread application in Bayesian statistics: + +In [@http://en.wikipedia.org/wiki/Bayesian_inference Bayesian inference], +the strength of belief into certain parameter values is +itself described through a distribution. Parameters +hence become themselves modelled and interpreted as random variables. + +In this worked example, we perform such a Bayesian analysis by using +the scaled-inverse-chi-squared distribution as prior and posterior distribution +for the variance parameter of a normal distribution. + +For more general information on Bayesian type of analyses, +see: + +* Andrew Gelman, John B. Carlin, Hal E. Stern, Donald B. Rubin, Bayesian Data Analysis, +2003, ISBN 978-1439840955. + +* Jim Albert, Bayesian Computation with R, Springer, 2009, ISBN 978-0387922973. + +(As the scaled-inversed-chi-squared is another parameterization of the inverse-gamma distribution, +this example could also have used the inverse-gamma distribution). + +Consider precision machines which produce balls for a high-quality ball bearing. +Ideally each ball should have a diameter of precisely 3000 [mu]m (3 mm). +Assume that machines generally produce balls of that size on average (mean), +but individual balls can vary slightly in either direction +following (approximately) a normal distribution. Depending on various production conditions +(e.g. raw material used for balls, workplace temperature and humidity, maintenance frequency and quality) +some machines produce balls tighter distributed around the target of 3000 [mu]m, +while others produce balls with a wider distribution. +Therefore the variance parameter of the normal distribution of the ball sizes varies +from machine to machine. An extensive survey by the precision machinery manufacturer, however, +has shown that most machines operate with a variance between 15 and 50, +and near 25 [mu]m[super 2] on average. + +Using this information, we want to model the variance of the machines. +The variance is strictly positive, and therefore we look for a statistical distribution +with support in the positive domain of the real numbers. +Given the expectation of the normal distribution of the balls is known (3000 [mu]m), +for reasons of conjugacy, it is customary practice in Bayesian statistics +to model the variance to be scaled-inverse-chi-squared distributed. + +In a first step, we will try to use the survey information to model +the general knowledge about the variance parameter of machines measured by the manufacturer. +This will provide us with a generic prior distribution that is applicable +if nothing more specific is known about a particular machine. + +In a second step, we will then combine the prior-distribution information in a Bayesian analysis +with data on a specific single machine to derive a posterior distribution for that machine. + +[h5 Step one: Using the survey information.] + +Using the survey results, we try to find the parameter set +of a scaled-inverse-chi-squared distribution +so that the properties of this distribution match the results. +Using the mathematical properties of the scaled-inverse-chi-squared distribution +as guideline, we see that that both the mean and mode of the scaled-inverse-chi-squared distribution +are approximately given by the scale parameter (s) of the distribution. As the survey machines operated at a +variance of 25 [mu]m[super 2] on average, we hence set the scale parameter (s[sub prior]) of our prior distribution +equal to this value. Using some trial-and-error and calls to the global quantile function, we also find that a +value of 20 for the degrees-of-freedom ([nu][sub prior]) parameter is adequate so that +most of the prior distribution mass is located between 15 and 50 (see figure below). + +We first construct our prior distribution using these values, and then list out a few quantiles: + +*/ + double priorDF = 20.0; + double priorScale = 25.0; + + inverse_chi_squared prior(priorDF, priorScale); + // Using an inverse_gamma distribution instead, we could equivalently write + // inverse_gamma prior(priorDF / 2.0, priorScale * priorDF / 2.0); + + cout << "Prior distribution:" << endl << endl; + cout << " 2.5% quantile: " << quantile(prior, 0.025) << endl; + cout << " 50% quantile: " << quantile(prior, 0.5) << endl; + cout << " 97.5% quantile: " << quantile(prior, 0.975) << endl << endl; + + //] [/inverse_chi_squared_bayes_eg_1] + +//[inverse_chi_squared_bayes_eg_output_1 +/*`This produces this output: + + Prior distribution: + + 2.5% quantile: 14.6 + 50% quantile: 25.9 + 97.5% quantile: 52.1 + +*/ +//] [/inverse_chi_squared_bayes_eg_output_1] + +//[inverse_chi_squared_bayes_eg_2 +/*` +Based on this distribution, we can now calculate the probability of having a machine +working with an unusual work precision (variance) at <= 15 or > 50. +For this task, we use calls to the `boost::math::` functions `cdf` and `complement`, +respectively, and find a probability of about 0.031 (3.1%) for each case. +*/ + + cout << " probability variance <= 15: " << boost::math::cdf(prior, 15.0) << endl; + cout << " probability variance <= 25: " << boost::math::cdf(prior, 25.0) << endl; + cout << " probability variance > 50: " + << boost::math::cdf(boost::math::complement(prior, 50.0)) + << endl << endl; + //] [/inverse_chi_squared_bayes_eg_2] + +//[inverse_chi_squared_bayes_eg_output_2 +/*`This produces this output: + + probability variance <= 15: 0.031 + probability variance <= 25: 0.458 + probability variance > 50: 0.0318 + +*/ +//] [/inverse_chi_squared_bayes_eg_output_2] + +//[inverse_chi_squared_bayes_eg_3 +/*`Therefore, only 3.1% of all precision machines produce balls with a variance of 15 or less +(particularly precise machines), +but also only 3.2% of all machines produce balls +with a variance of as high as 50 or more (particularly imprecise machines). Moreover, slightly more than +one-half (1 - 0.458 = 54.2%) of the machines work at a variance greater than 25. + +Notice here the distinction between a +[@http://en.wikipedia.org/wiki/Bayesian_inference Bayesian] analysis and a +[@http://en.wikipedia.org/wiki/Frequentist_inference frequentist] analysis: +because we model the variance as random variable itself, +we can calculate and straightforwardly interpret probabilities for given parameter values directly, +while such an approach is not possible (and interpretationally a strict ['must-not]) in the frequentist +world. + +[h5 Step 2: Investigate a single machine] + +In the second step, we investigate a single machine, +which is suspected to suffer from a major fault +as the produced balls show fairly high size variability. +Based on the prior distribution of generic machinery performance (derived above) +and data on balls produced by the suspect machine, we calculate the posterior distribution for that +machine and use its properties for guidance regarding continued machine operation or suspension. + +It can be shown that if the prior distribution +was chosen to be scaled-inverse-chi-square distributed, +then the posterior distribution is also scaled-inverse-chi-squared-distributed +(prior and posterior distributions are hence conjugate). +For more details regarding conjugacy and formula to derive the parameters set +for the posterior distribution see +[@http://en.wikipedia.org/wiki/Conjugate_prior Conjugate prior]. + + +Given the prior distribution parameters and sample data (of size n), the posterior distribution parameters +are given by the two expressions: + +__spaces [nu][sub posterior] = [nu][sub prior] + n + +which gives the posteriorDF below, and + +__spaces s[sub posterior] = ([nu][sub prior]s[sub prior] + [Sigma][super n][sub i=1](x[sub i] - [mu])[super 2]) / ([nu][sub prior] + n) + +which after some rearrangement gives the formula for the posteriorScale below. + +Machine-specific data consist of 100 balls which were accurately measured +and show the expected mean of 3000 [mu]m and a sample variance of 55 (calculated for a sample mean defined to be 3000 exactly). +From these data, the prior parameterization, and noting that the term +[Sigma][super n][sub i=1](x[sub i] - [mu])[super 2] equals the sample variance multiplied by n - 1, +it follows that the posterior distribution of the variance parameter +is scaled-inverse-chi-squared distribution with degrees-of-freedom ([nu][sub posterior]) = 120 and +scale (s[sub posterior]) = 49.54. +*/ + + int ballsSampleSize = 100; + cout <<"balls sample size: " << ballsSampleSize << endl; + double ballsSampleVariance = 55.0; + cout <<"balls sample variance: " << ballsSampleVariance << endl; + + double posteriorDF = priorDF + ballsSampleSize; + cout << "prior degrees-of-freedom: " << priorDF << endl; + cout << "posterior degrees-of-freedom: " << posteriorDF << endl; + + double posteriorScale = + (priorDF * priorScale + (ballsSampleVariance * (ballsSampleSize - 1))) / posteriorDF; + cout << "prior scale: " << priorScale << endl; + cout << "posterior scale: " << posteriorScale << endl; + +/*`An interesting feature here is that one needs only to know a summary statistics of the sample +to parameterize the posterior distribution: the 100 individual ball measurements are irrelevant, +just knowledge of the sample variance and number of measurements is sufficient. +*/ + +//] [/inverse_chi_squared_bayes_eg_3] + +//[inverse_chi_squared_bayes_eg_output_3 +/*`That produces this output: + + + balls sample size: 100 + balls sample variance: 55 + prior degrees-of-freedom: 20 + posterior degrees-of-freedom: 120 + prior scale: 25 + posterior scale: 49.5 + + */ +//] [/inverse_chi_squared_bayes_eg_output_3] + +//[inverse_chi_squared_bayes_eg_4 +/*`To compare the generic machinery performance with our suspect machine, +we calculate again the same quantiles and probabilities as above, +and find a distribution clearly shifted to greater values (see figure). + +[graph prior_posterior_plot] + +*/ + + inverse_chi_squared posterior(posteriorDF, posteriorScale); + + cout << "Posterior distribution:" << endl << endl; + cout << " 2.5% quantile: " << boost::math::quantile(posterior, 0.025) << endl; + cout << " 50% quantile: " << boost::math::quantile(posterior, 0.5) << endl; + cout << " 97.5% quantile: " << boost::math::quantile(posterior, 0.975) << endl << endl; + + cout << " probability variance <= 15: " << boost::math::cdf(posterior, 15.0) << endl; + cout << " probability variance <= 25: " << boost::math::cdf(posterior, 25.0) << endl; + cout << " probability variance > 50: " + << boost::math::cdf(boost::math::complement(posterior, 50.0)) << endl; + +//] [/inverse_chi_squared_bayes_eg_4] + +//[inverse_chi_squared_bayes_eg_output_4 +/*`This produces this output: + + Posterior distribution: + + 2.5% quantile: 39.1 + 50% quantile: 49.8 + 97.5% quantile: 64.9 + + probability variance <= 15: 2.97e-031 + probability variance <= 25: 8.85e-010 + probability variance > 50: 0.489 + +*/ +//] [/inverse_chi_squared_bayes_eg_output_4] + +//[inverse_chi_squared_bayes_eg_5 +/*`Indeed, the probability that the machine works at a low variance (<= 15) is almost zero, +and even the probability of working at average or better performance is negligibly small +(less than one-millionth of a permille). +On the other hand, with an almost near-half probability (49%), the machine operates in the +extreme high variance range of > 50 characteristic for poorly performing machines. + +Based on this information the operation of the machine is taken out of use and serviced. + +In summary, the Bayesian analysis allowed us to make exact probabilistic statements about a +parameter of interest, and hence provided us results with straightforward interpretation. + +*/ +//] [/inverse_chi_squared_bayes_eg_5] + +} // int main() + +//[inverse_chi_squared_bayes_eg_output +/*` +[pre + Inverse_chi_squared_distribution Bayes example: + + Prior distribution: + + 2.5% quantile: 14.6 + 50% quantile: 25.9 + 97.5% quantile: 52.1 + + probability variance <= 15: 0.031 + probability variance <= 25: 0.458 + probability variance > 50: 0.0318 + + balls sample size: 100 + balls sample variance: 55 + prior degrees-of-freedom: 20 + posterior degrees-of-freedom: 120 + prior scale: 25 + posterior scale: 49.5 + Posterior distribution: + + 2.5% quantile: 39.1 + 50% quantile: 49.8 + 97.5% quantile: 64.9 + + probability variance <= 15: 2.97e-031 + probability variance <= 25: 8.85e-010 + probability variance > 50: 0.489 + +] [/pre] +*/ +//] [/inverse_chi_squared_bayes_eg_output] diff --git a/src/boost/libs/math/example/inverse_chi_squared_example.cpp b/src/boost/libs/math/example/inverse_chi_squared_example.cpp new file mode 100644 index 000000000..d21b0dc0c --- /dev/null +++ b/src/boost/libs/math/example/inverse_chi_squared_example.cpp @@ -0,0 +1,171 @@ +// inverse_chi_squared_distribution_example.cpp + +// Copyright Paul A. Bristow 2010. +// Copyright Thomas Mang 2010. + +// 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) + +// Example 1 of using inverse chi squared distribution +#include <boost/math/distributions/inverse_chi_squared.hpp> +using boost::math::inverse_chi_squared_distribution; // inverse_chi_squared_distribution. +using boost::math::inverse_chi_squared; //typedef for nverse_chi_squared_distribution double. + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::setprecision; +using std::setw; +#include <cmath> +using std::sqrt; + +template <class RealType> +RealType naive_pdf1(RealType df, RealType x) +{ // Formula from Wikipedia http://en.wikipedia.org/wiki/Inverse-chi-square_distribution + // definition 1 using tgamma for simplicity as a check. + using namespace std; // For ADL of std functions. + using boost::math::tgamma; + RealType df2 = df / 2; + RealType result = (pow(2., -df2) * pow(x, (-df2 -1)) * exp(-1/(2 * x) ) ) + / tgamma(df2); // + return result; +} + +template <class RealType> +RealType naive_pdf2(RealType df, RealType x) +{ // Formula from Wikipedia http://en.wikipedia.org/wiki/Inverse-chi-square_distribution + // Definition 2, using tgamma for simplicity as a check. + // Not scaled, so assumes scale = 1 and only uses nu aka df. + using namespace std; // For ADL of std functions. + using boost::math::tgamma; + RealType df2 = df / 2; + RealType result = (pow(df2, df2) * pow(x, (-df2 -1)) * exp(-df/(2*x) ) ) + / tgamma(df2); + return result; +} + +template <class RealType> +RealType naive_pdf3(RealType df, RealType scale, RealType x) +{ // Formula from Wikipedia http://en.wikipedia.org/wiki/Scaled-inverse-chi-square_distribution + // *Scaled* version, definition 3, df aka nu, scale aka sigma^2 + // using tgamma for simplicity as a check. + using namespace std; // For ADL of std functions. + using boost::math::tgamma; + RealType df2 = df / 2; + RealType result = (pow(scale * df2, df2) * exp(-df2 * scale/x) ) + / (tgamma(df2) * pow(x, 1+df2)); + return result; +} + +template <class RealType> +RealType naive_pdf4(RealType df, RealType scale, RealType x) +{ // Formula from http://mathworld.wolfram.com/InverseChi-SquaredDistribution.html + // Weisstein, Eric W. "Inverse Chi-Squared Distribution." From MathWorld--A Wolfram Web Resource. + // *Scaled* version, definition 3, df aka nu, scale aka sigma^2 + // using tgamma for simplicity as a check. + using namespace std; // For ADL of std functions. + using boost::math::tgamma; + RealType nu = df; // Wolfram uses greek symbols nu, + RealType xi = scale; // and xi. + RealType result = + pow(2, -nu/2) * exp(- (nu * xi)/(2 * x)) * pow(x, -1-nu/2) * pow((nu * xi), nu/2) + / tgamma(nu/2); + return result; +} + +int main() +{ + + cout << "Example (basic) using Inverse chi squared distribution. " << endl; + + // TODO find a more practical/useful example. Suggestions welcome? + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + int max_digits10 = 2 + (boost::math::policies::digits<double, boost::math::policies::policy<> >() * 30103UL) / 100000UL; + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined" << endl; +#else + int max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = " + << max_digits10 << endl; + cout.precision(max_digits10); // + + inverse_chi_squared ichsqdef; // All defaults - not very useful! + cout << "default df = " << ichsqdef.degrees_of_freedom() + << ", default scale = " << ichsqdef.scale() << endl; // default df = 1, default scale = 0.5 + + inverse_chi_squared ichsqdef4(4); // Unscaled version, default scale = 1 / degrees_of_freedom + cout << "default df = " << ichsqdef4.degrees_of_freedom() + << ", default scale = " << ichsqdef4.scale() << endl; // default df = 4, default scale = 2 + + inverse_chi_squared ichsqdef32(3, 2); // Scaled version, both degrees_of_freedom and scale specified. + cout << "default df = " << ichsqdef32.degrees_of_freedom() + << ", default scale = " << ichsqdef32.scale() << endl; // default df = 3, default scale = 2 + + { + cout.precision(3); + double nu = 5.; + //double scale1 = 1./ nu; // 1st definition sigma^2 = 1/df; + //double scale2 = 1.; // 2nd definition sigma^2 = 1 + inverse_chi_squared ichsq(nu, 1/nu); // Not scaled + inverse_chi_squared sichsq(nu, 1/nu); // scaled + + cout << "nu = " << ichsq.degrees_of_freedom() << ", scale = " << ichsq.scale() << endl; + + int width = 8; + + cout << " x pdf pdf1 pdf2 pdf(scaled) pdf pdf cdf cdf" << endl; + for (double x = 0.0; x < 1.; x += 0.1) + { + cout + << setw(width) << x + << ' ' << setw(width) << pdf(ichsq, x) // unscaled + << ' ' << setw(width) << naive_pdf1(nu, x) // Wiki def 1 unscaled matches graph + << ' ' << setw(width) << naive_pdf2(nu, x) // scale = 1 - 2nd definition. + << ' ' << setw(width) << naive_pdf3(nu, 1/nu, x) // scaled + << ' ' << setw(width) << naive_pdf4(nu, 1/nu, x) // scaled + << ' ' << setw(width) << pdf(sichsq, x) // scaled + << ' ' << setw(width) << cdf(sichsq, x) // scaled + << ' ' << setw(width) << cdf(ichsq, x) // unscaled + << endl; + } + } + + cout.precision(max_digits10); + + inverse_chi_squared ichisq(2., 0.5); + cout << "pdf(ichisq, 1.) = " << pdf(ichisq, 1.) << endl; + cout << "cdf(ichisq, 1.) = " << cdf(ichisq, 1.) << endl; + + return 0; +} // int main() + +/* + +Output is: + Example (basic) using Inverse chi squared distribution. + Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = 17 + default df = 1, default scale = 1 + default df = 4, default scale = 0.25 + default df = 3, default scale = 2 + nu = 5, scale = 0.2 + x pdf pdf1 pdf2 pdf(scaled) pdf pdf cdf cdf + 0 0 -1.#J -1.#J -1.#J -1.#J 0 0 0 + 0.1 2.83 2.83 3.26e-007 2.83 2.83 2.83 0.0752 0.0752 + 0.2 3.05 3.05 0.00774 3.05 3.05 3.05 0.416 0.416 + 0.3 1.7 1.7 0.121 1.7 1.7 1.7 0.649 0.649 + 0.4 0.941 0.941 0.355 0.941 0.941 0.941 0.776 0.776 + 0.5 0.553 0.553 0.567 0.553 0.553 0.553 0.849 0.849 + 0.6 0.345 0.345 0.689 0.345 0.345 0.345 0.893 0.893 + 0.7 0.227 0.227 0.728 0.227 0.227 0.227 0.921 0.921 + 0.8 0.155 0.155 0.713 0.155 0.155 0.155 0.94 0.94 + 0.9 0.11 0.11 0.668 0.11 0.11 0.11 0.953 0.953 + 1 0.0807 0.0807 0.61 0.0807 0.0807 0.0807 0.963 0.963 + pdf(ichisq, 1.) = 0.30326532985631671 + cdf(ichisq, 1.) = 0.60653065971263365 + + +*/ + diff --git a/src/boost/libs/math/example/inverse_chi_squared_find_df_example.cpp b/src/boost/libs/math/example/inverse_chi_squared_find_df_example.cpp new file mode 100644 index 000000000..7d1ea2f20 --- /dev/null +++ b/src/boost/libs/math/example/inverse_chi_squared_find_df_example.cpp @@ -0,0 +1,188 @@ +// inverse_chi_squared_distribution_find_df_example.cpp + +// Copyright Paul A. Bristow 2010. +// Copyright Thomas Mang 2010. + +// 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) + +//#define BOOST_MATH_INSTRUMENT + +// Example 1 of using inverse chi squared distribution +#include <boost/math/distributions/inverse_chi_squared.hpp> +using boost::math::inverse_chi_squared_distribution; // inverse_chi_squared_distribution. +using boost::math::inverse_chi_squared; //typedef for nverse_chi_squared_distribution double. + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::setprecision; +using std::setw; +#include <cmath> +using std::sqrt; + +int main() +{ + cout << "Example using Inverse chi squared distribution to find df. " << endl; + try + { + cout.precision(std::numeric_limits<double>::max_digits10); // + int i = std::numeric_limits<double>::max_digits10; + cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = " << i << endl; + + cout.precision(3); + double nu = 10.; + double scale1 = 1./ nu; // 1st definition sigma^2 = 1/df; + double scale2 = 1.; // 2nd definition sigma^2 = 1 + inverse_chi_squared sichsq(nu, 1/nu); // Explicitly scaled to default scale = 1/df. + inverse_chi_squared ichsq(nu); // Implicitly scaled to default scale = 1/df. + // Try degrees of freedom estimator + + //double df = chi_squared::find_degrees_of_freedom(-diff, alpha[i], alpha[i], variance); + + cout << "ichsq.degrees_of_freedom() = " << ichsq.degrees_of_freedom() << endl; + + double diff = 0.5; // difference from variance to detect (delta). + double variance = 1.; // true variance + double alpha = 0.9; + double beta = 0.9; + + cout << "diff = " << diff + << ", variance = " << variance << ", ratio = " << diff/variance + << ", alpha = " << alpha << ", beta = " << beta << endl; + + /* inverse_chi_square_df_estimator is not in the code base anymore? + + using boost::math::detail::inverse_chi_square_df_estimator; + using boost::math::policies::default_policy; + inverse_chi_square_df_estimator<> a_df(alpha, beta, variance, diff); + + cout << "df est" << endl; + for (double df = 1; df < 3; df += 0.1) + { + double est_df = a_df(1); + cout << df << " " << a_df(df) << endl; + } + */ + + //template <class F, class T, class Tol, class Policy>std::pair<T, T> + // bracket_and_solve_root(F f, const T& guess, T factor, bool rising, Tol tol, std::uintmax_t& max_iter, const Policy& pol) + + + // TODO: Not implemented + //double df = inverse_chi_squared_distribution<>::find_degrees_of_freedom(diff, alpha, beta, variance, 0); + //cout << df << endl; + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +/* + +Output is: + + Example using Inverse chi squared distribution to find df. + Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = 17 + 10 + + Message from thrown exception was: + Error in function boost::math::inverse_chi_squared_distribution<double>::inverse_chi_squared_distribution: Degrees of freedom argument is 1.#INF, but must be > 0 ! +diff = 0.5, variance = 1, ratio = 0.5, alpha = 0.1, beta = 0.1 + df est + 1 1 + ratio+1 = 1.5, quantile(0.1) = 0.00618, cdf = 6.5e-037, result = -0.1 + 1.1 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.00903, cdf = 1.2e-025, result = -0.1 + 1.2 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0125, cdf = 8.25e-019, result = -0.1 + 1.3 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0166, cdf = 2.17e-014, result = -0.1 + 1.4 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0212, cdf = 2.2e-011, result = -0.1 + 1.5 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0265, cdf = 3e-009, result = -0.1 + 1.6 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0323, cdf = 1.11e-007, result = -0.1 + 1.7 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0386, cdf = 1.7e-006, result = -0.1 + 1.8 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0454, cdf = 1.41e-005, result = -0.1 + 1.9 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0527, cdf = 7.55e-005, result = -0.1 + 2 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0604, cdf = 0.000291, result = -0.1 + 2.1 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0685, cdf = 0.00088, result = -0.1 + 2.2 -0.1 + ratio+1 = 1.5, quantile(0.1) = 0.0771, cdf = 0.0022, result = -0.0999 + 2.3 -0.0999 + ratio+1 = 1.5, quantile(0.1) = 0.0859, cdf = 0.00475, result = -0.0997 + 2.4 -0.0997 + ratio+1 = 1.5, quantile(0.1) = 0.0952, cdf = 0.00911, result = -0.0993 + 2.5 -0.0993 + ratio+1 = 1.5, quantile(0.1) = 0.105, cdf = 0.0159, result = -0.0984 + 2.6 -0.0984 + ratio+1 = 1.5, quantile(0.1) = 0.115, cdf = 0.0257, result = -0.0967 + 2.7 -0.0967 + ratio+1 = 1.5, quantile(0.1) = 0.125, cdf = 0.039, result = -0.094 + 2.8 -0.094 + ratio+1 = 1.5, quantile(0.1) = 0.135, cdf = 0.056, result = -0.0897 + 2.9 -0.0897 + ratio+1 = 1.5, quantile(0.1) = 20.6, cdf = 1, result = 0.9 + + ichsq.degrees_of_freedom() = 10 + diff = 0.5, variance = 1, ratio = 0.5, alpha = 0.9, beta = 0.9 + df est + 1 1 + ratio+1 = 1.5, quantile(0.9) = 0.729, cdf = 0.269, result = -0.729 + 1.1 -0.729 + ratio+1 = 1.5, quantile(0.9) = 0.78, cdf = 0.314, result = -0.693 + 1.2 -0.693 + ratio+1 = 1.5, quantile(0.9) = 0.83, cdf = 0.36, result = -0.655 + 1.3 -0.655 + ratio+1 = 1.5, quantile(0.9) = 0.879, cdf = 0.405, result = -0.615 + 1.4 -0.615 + ratio+1 = 1.5, quantile(0.9) = 0.926, cdf = 0.449, result = -0.575 + 1.5 -0.575 + ratio+1 = 1.5, quantile(0.9) = 0.973, cdf = 0.492, result = -0.535 + 1.6 -0.535 + ratio+1 = 1.5, quantile(0.9) = 1.02, cdf = 0.534, result = -0.495 + 1.7 -0.495 + ratio+1 = 1.5, quantile(0.9) = 1.06, cdf = 0.574, result = -0.455 + 1.8 -0.455 + ratio+1 = 1.5, quantile(0.9) = 1.11, cdf = 0.612, result = -0.417 + 1.9 -0.417 + ratio+1 = 1.5, quantile(0.9) = 1.15, cdf = 0.648, result = -0.379 + 2 -0.379 + ratio+1 = 1.5, quantile(0.9) = 1.19, cdf = 0.681, result = -0.342 + 2.1 -0.342 + ratio+1 = 1.5, quantile(0.9) = 1.24, cdf = 0.713, result = -0.307 + 2.2 -0.307 + ratio+1 = 1.5, quantile(0.9) = 1.28, cdf = 0.742, result = -0.274 + 2.3 -0.274 + ratio+1 = 1.5, quantile(0.9) = 1.32, cdf = 0.769, result = -0.242 + 2.4 -0.242 + ratio+1 = 1.5, quantile(0.9) = 1.36, cdf = 0.793, result = -0.212 + 2.5 -0.212 + ratio+1 = 1.5, quantile(0.9) = 1.4, cdf = 0.816, result = -0.184 + 2.6 -0.184 + ratio+1 = 1.5, quantile(0.9) = 1.44, cdf = 0.836, result = -0.157 + 2.7 -0.157 + ratio+1 = 1.5, quantile(0.9) = 1.48, cdf = 0.855, result = -0.133 + 2.8 -0.133 + ratio+1 = 1.5, quantile(0.9) = 1.52, cdf = 0.872, result = -0.11 + 2.9 -0.11 + ratio+1 = 1.5, quantile(0.9) = 29.6, cdf = 1, result = 0.1 + + + */ + diff --git a/src/boost/libs/math/example/inverse_gamma_distribution_example.cpp b/src/boost/libs/math/example/inverse_gamma_distribution_example.cpp new file mode 100644 index 000000000..53e5ccf0f --- /dev/null +++ b/src/boost/libs/math/example/inverse_gamma_distribution_example.cpp @@ -0,0 +1,103 @@ +// inverse_gamma_distribution_example.cpp + +// Copyright Paul A. Bristow 2010. +// Copyright Thomas Mang 2010. + +// 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) + +// Example 1 of using inverse gamma +#include <boost/math/distributions/inverse_gamma.hpp> +using boost::math::inverse_gamma_distribution; // inverse_gamma_distribution. +using boost::math::inverse_gamma; + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; // Used for naive pdf as a comparison. + +#include <boost/math/distributions/gamma.hpp> +using boost::math::inverse_gamma_distribution; + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::setprecision; +#include <cmath> +using std::sqrt; + +int main() +{ + + cout << "Example using Inverse Gamma distribution. " << endl; + // TODO - awaiting a real example using Bayesian statistics. + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + int max_digits10 = 2 + (boost::math::policies::digits<double, boost::math::policies::policy<> >() * 30103UL) / 100000UL; + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined" << endl; +#else + int max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = " + << max_digits10 << endl; + cout.precision(max_digits10); // + + double shape = 1.; + double scale = 1.; + double x = 0.5; + // Construction using default RealType double, and default shape and scale.. + inverse_gamma_distribution<> my_inverse_gamma(shape, scale); // (alpha, beta) + + cout << "my_inverse_gamma.shape() = " << my_inverse_gamma.shape() + << ", scale = "<< my_inverse_gamma.scale() << endl; + cout << "x = " << x << ", pdf = " << pdf(my_inverse_gamma, x) + << ", cdf = " << cdf(my_inverse_gamma, x) << endl; + + // Construct using typedef and default shape and scale parameters. + inverse_gamma my_ig; + + inverse_gamma my_ig23(2, 3); + cout << "my_inverse_gamma.shape() = " << my_ig23.shape() + << ", scale = "<< my_ig23.scale() << endl; + cout << "x = " << x << ", pdf = " << pdf(my_ig23, x) + << ", cdf = " << cdf(my_ig23, x) << endl; + + // Example of providing an 'out of domain' or 'bad' parameter, + // here a shape < 1, for which mean is not defined. + // Try block is essential to catch the exception message. + // (Uses the default policy which is to throw on all errors). + try + { + inverse_gamma if051(0.5, 1); + //inverse_gamma if051(0.5, 1); + cout << "mean(if051) = " << mean(if051) << endl; + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + + return 0; +} // int main() + +/* + +Output is: + Example using Inverse Gamma distribution. + std::numeric_limits<double>::max_digits10 = 17 + my_inverse_gamma.shape() = 1, scale = 1 + x = 0.5, pdf = 0.54134113294645081, cdf = 0.1353352832366127 + my_inverse_gamma.shape() = 2, scale = 3 + x = 0.5, pdf = 0.17847015671997774, cdf = 0.017351265236664509 + + Message from thrown exception was: + Error in function boost::math::mean(const inverse_gamma_distribution<double>&): Shape parameter is 0.5, but for a defined mean it must be > 1 + + +*/ + + diff --git a/src/boost/libs/math/example/inverse_gamma_example.cpp b/src/boost/libs/math/example/inverse_gamma_example.cpp new file mode 100644 index 000000000..5ec496659 --- /dev/null +++ b/src/boost/libs/math/example/inverse_gamma_example.cpp @@ -0,0 +1,57 @@ +// inverse_gamma_example.cpp + +// Copyright Paul A. Bristow 2010. + +// 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) + +// Example 1 of using inverse gamma functions. + +#include <boost/math/special_functions/gamma.hpp> + +using boost::math::gamma_p_inv; // Compute x given a +//using boost::math::gamma_q_inv; +//using boost::math::gamma_p_inva; // Compute a given x +//using boost::math::gamma_q_inva; + +#include <iostream> + using std::cout; using std::endl; +#include <iomanip> + using std::setprecision; +#include <cmath> + using std::sqrt; +#include <limits> + +int main() +{ + cout << "Example 1 using Inverse Gamma function. " << endl; + + #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + int max_digits10 = 2 + (boost::math::policies::digits<double, boost::math::policies::policy<> >() * 30103UL) / 100000UL; + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined" << endl; +#else + int max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = " + << max_digits10 << endl; + cout.precision(max_digits10); // + + double x = 1.; + double a = 10; + + double r = boost::math::gamma_q_inv(a ,x); + + cout << " x = " << x << ", = gamma_q_inv(a,x)" << r << endl; // + + return 0; +} // int main() + +/* + +Output is: + +*/ + + diff --git a/src/boost/libs/math/example/inverse_gaussian_example.cpp b/src/boost/libs/math/example/inverse_gaussian_example.cpp new file mode 100644 index 000000000..b1598a9f7 --- /dev/null +++ b/src/boost/libs/math/example/inverse_gaussian_example.cpp @@ -0,0 +1,513 @@ +// wald_example.cpp or inverse_gaussian_example.cpp + +// Copyright Paul A. Bristow 2010. + +// 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) + +// Example of using the Inverse Gaussian (or Inverse Normal) distribution. +// The Wald Distribution is + + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[inverse_gaussian_basic1 +/*` +First we need some includes to access the normal distribution +(and some std output of course). +*/ + +#ifdef _MSC_VER +# pragma warning (disable : 4224) +# pragma warning (disable : 4189) +# pragma warning (disable : 4100) +# pragma warning (disable : 4224) +# pragma warning (disable : 4512) +# pragma warning (disable : 4702) +# pragma warning (disable : 4127) +#endif + +//#define BOOST_MATH_INSTRUMENT + +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error + +#include <boost/math/distributions/inverse_gaussian.hpp> // for inverse_gaussian_distribution + using boost::math::inverse_gaussian; // typedef provides default type is double. + using boost::math::inverse_gaussian_distribution; // for inverse gaussian distribution. + +#include <boost/math/distributions/normal.hpp> // for normal_distribution +using boost::math::normal; // typedef provides default type is double. + +#include <boost/array.hpp> +using std::array; + +#include <iostream> + using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; +#include <sstream> + using std::string; +#include <string> + using std::stringstream; + +// const double tol = 3 * numeric_limits<double>::epsilon(); + +int main() +{ + cout << "Example: Inverse Gaussian Distribution."<< endl; + + try + { + + double tolfeweps = numeric_limits<double>::epsilon(); + //cout << "Tolerance = " << tol << endl; + + int precision = 17; // traditional tables are only computed to much lower precision. + cout.precision(17); // std::numeric_limits<double>::max_digits10; for 64-bit doubles. + + // Traditional tables and values. + double step = 0.2; // in z + double range = 4; // min and max z = -range to +range. + // Construct a (standard) inverse gaussian distribution s + inverse_gaussian w11(1, 1); + // (default mean = units, and standard deviation = unity) + cout << "(Standard) Inverse Gaussian distribution, mean = "<< w11.mean() + << ", scale = " << w11.scale() << endl; + +/*` First the probability distribution function (pdf). + */ + cout << "Probability distribution function (pdf) values" << endl; + cout << " z " " pdf " << endl; + cout.precision(5); + for (double z = (numeric_limits<double>::min)(); z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(12) << pdf(w11, z) << endl; + } + cout.precision(6); // default + /*`And the area under the normal curve from -[infin] up to z, + the cumulative distribution function (cdf). +*/ + + // For a (default) inverse gaussian distribution. + cout << "Integral (area under the curve) from 0 up to z (cdf) " << endl; + cout << " z " " cdf " << endl; + for (double z = (numeric_limits<double>::min)(); z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(12) << cdf(w11, z) << endl; + } + /*`giving the following table: +[pre + z pdf + 2.23e-308 -1.#IND + 0.2 0.90052111680384117 + 0.4 1.0055127039453111 + 0.6 0.75123750098955733 + 0.8 0.54377310461643302 + 1 0.3989422804014327 + 1.2 0.29846949816803292 + 1.4 0.2274579835638664 + 1.6 0.17614566625628389 + 1.8 0.13829083543591469 + 2 0.10984782236693062 + 2.2 0.088133964251182237 + 2.4 0.071327382959107177 + 2.6 0.058162562161661699 + 2.8 0.047742223328567722 + 3 0.039418357969819712 + 3.2 0.032715223861241892 + 3.4 0.027278388940958308 + 3.6 0.022840312999395804 + 3.8 0.019196657941016954 + 4 0.016189699458236451 + Integral (area under the curve) from 0 up to z (cdf) + z cdf + 2.23e-308 0 + 0.2 0.063753567519976254 + 0.4 0.2706136704424541 + 0.6 0.44638391340412931 + 0.8 0.57472390962590925 + 1 0.66810200122317065 + 1.2 0.73724578422952536 + 1.4 0.78944214237790356 + 1.6 0.82953458108474554 + 1.8 0.86079282968276671 + 2 0.88547542598600626 + 2.2 0.90517870624273966 + 2.4 0.92105495653509362 + 2.6 0.93395164268166786 + 2.8 0.94450240360053817 + 3 0.95318792074278835 + 3.2 0.96037753019309191 + 3.4 0.96635823989417369 + 3.6 0.97135533107998406 + 3.8 0.97554722413538364 + 4 0.97907636417888622 +] + +/*`We can get the inverse, the quantile, percentile, percentage point, or critical value +for a probability for a few probability from the above table, for z = 0.4, 1.0, 2.0: +*/ + cout << quantile(w11, 0.27061367044245421 ) << endl; // 0.4 + cout << quantile(w11, 0.66810200122317065) << endl; // 1.0 + cout << quantile(w11, 0.88547542598600615) << endl; // 2.0 +/*`turning the expect values apart from some 'computational noise' in the least significant bit or two. + +[pre + 0.40000000000000008 + 0.99999999999999967 + 1.9999999999999973 +] + +*/ + + // cout << "pnorm01(-0.406053) " << pnorm01(-0.406053) << ", cdfn01(-0.406053) = " << cdf(n01, -0.406053) << endl; + //cout << "pnorm01(0.5) = " << pnorm01(0.5) << endl; // R pnorm(0.5,0,1) = 0.6914625 == 0.69146246127401312 + // R qnorm(0.6914625,0,1) = 0.5 + + // formatC(SuppDists::qinvGauss(0.3649755481729598, 1, 1), digits=17) [1] "0.50000000969034875" + + + + // formatC(SuppDists::dinvGauss(0.01, 1, 1), digits=17) [1] "2.0811768202028392e-19" + // formatC(SuppDists::pinvGauss(0.01, 1, 1), digits=17) [1] "4.122313403318778e-23" + + + + //cout << " qinvgauss(0.3649755481729598, 1, 1) = " << qinvgauss(0.3649755481729598, 1, 1) << endl; // 0.5 + // cout << quantile(s, 0.66810200122317065) << endl; // expect 1, get 0.50517388467190727 + //cout << " qinvgauss(0.62502320258649202, 1, 1) = " << qinvgauss(0.62502320258649202, 1, 1) << endl; // 0.9 + //cout << " qinvgauss(0.063753567519976254, 1, 1) = " << qinvgauss(0.063753567519976254, 1, 1) << endl; // 0.2 + //cout << " qinvgauss(0.0040761113207110162, 1, 1) = " << qinvgauss(0.0040761113207110162, 1, 1) << endl; // 0.1 + + //double x = 1.; // SuppDists::pinvGauss(0.4, 1,1) [1] 0.2706137 + //double c = pinvgauss(x, 1, 1); // 0.3649755481729598 == cdf(x, 1,1) 0.36497554817295974 + //cout << " pinvgauss(x, 1, 1) = " << c << endl; // pinvgauss(x, 1, 1) = 0.27061367044245421 + //double p = pdf(w11, x); + //double c = cdf(w11, x); // cdf(1, 1, 1) = 0.66810200122317065 + //cout << "cdf(" << x << ", " << w11.mean() << ", "<< w11.scale() << ") = " << c << endl; // cdf(x, 1, 1) 0.27061367044245421 + //cout << "pdf(" << x << ", " << w11.mean() << ", "<< w11.scale() << ") = " << p << endl; + //double q = quantile(w11, c); + //cout << "quantile(w11, " << c << ") = " << q << endl; + + //cout << "quantile(w11, 4.122313403318778e-23) = "<< quantile(w11, 4.122313403318778e-23) << endl; // quantile + //cout << "quantile(w11, 4.8791443010851493e-219) = " << quantile(w11, 4.8791443010851493e-219) << endl; // quantile + + //double c1 = 1 - cdf(w11, x); // 1 - cdf(1, 1, 1) = 0.33189799877682935 + //cout << "1 - cdf(" << x << ", " << w11.mean() << ", " << w11.scale() << ") = " << c1 << endl; // cdf(x, 1, 1) 0.27061367044245421 + //double cc = cdf(complement(w11, x)); + //cout << "cdf(complement(" << x << ", " << w11.mean() << ", "<< w11.scale() << ")) = " << cc << endl; // cdf(x, 1, 1) 0.27061367044245421 + //// 1 - cdf(1000, 1, 1) = 0 + //// cdf(complement(1000, 1, 1)) = 4.8694344366900402e-222 + + //cout << "quantile(w11, " << c << ") = "<< quantile(w11, c) << endl; // quantile = 0.99999999999999978 == x = 1 + //cout << "quantile(w11, " << c << ") = "<< quantile(w11, 1 - c) << endl; // quantile complement. quantile(w11, 0.66810200122317065) = 0.46336593652340152 +// cout << "quantile(complement(w11, " << c << ")) = " << quantile(complement(w11, c)) << endl; // quantile complement = 0.46336593652340163 + + // cdf(1, 1, 1) = 0.66810200122317065 + // 1 - cdf(1, 1, 1) = 0.33189799877682935 + // cdf(complement(1, 1, 1)) = 0.33189799877682929 + + // quantile(w11, 0.66810200122317065) = 0.99999999999999978 + // 1 - quantile(w11, 0.66810200122317065) = 2.2204460492503131e-016 + // quantile(complement(w11, 0.33189799877682929)) = 0.99999999999999989 + + + // qinvgauss(c, 1, 1) = 0.3999999999999998 + // SuppDists::qinvGauss(0.270613670442454, 1, 1) [1] 0.4 + + + /* + double qs = pinvgaussU(c, 1, 1); // + cout << "qinvgaussU(c, 1, 1) = " << qs << endl; // qinvgaussU(c, 1, 1) = 0.86567442459240929 + // > z=q - exp(c) * p [1] 0.8656744 qs 0.86567442459240929 double + // Is this the complement? + cout << "qgamma(0.2, 0.5, 1) expect 0.0320923 = " << qgamma(0.2, 0.5, 1) << endl; + // qgamma(0.2, 0.5, 1) expect 0.0320923 = 0.032092377333650807 + + + cout << "qinvgauss(pinvgauss(x, 1, 1) = " << q + << ", diff = " << x - q << ", fraction = " << (x - q) /x << endl; // 0.5 + + */ // > SuppDists::pinvGauss(0.02, 1,1) [1] 4.139176e-12 + // > SuppDists::qinvGauss(4.139176e-12, 1,1) [1] 0.02000000 + + + // pinvGauss(1,1,1) = 0.668102 C++ == 0.66810200122317065 + // qinvGauss(0.668102,1,1) = 1 + + // SuppDists::pinvGauss(0.3,1,1) = 0.1657266 + // cout << "qinvGauss(0.0040761113207110162, 1, 1) = " << qinvgauss(0.0040761113207110162, 1, 1) << endl; + //cout << "quantile(s, 0.1657266) = " << quantile(s, 0.1657266) << endl; // expect 1. + + //wald s12(2, 1); + //cout << "qinvGauss(0.3, 2, 1) = " << qinvgauss(0.3, 2, 1) << endl; // SuppDists::qinvGauss(0.3,2,1) == 0.58288065635052944 + //// but actually get qinvGauss(0.3, 2, 1) = 0.58288064777632187 + //cout << "cdf(s12, 0.3) = " << cdf(s12, 0.3) << endl; // cdf(s12, 0.3) = 0.10895339868447573 + + // using boost::math::wald; + //cout.precision(6); + + /* + double m = 1; + double l = 1; + double x = 0.1; + //c = cdf(w, x); + double p = pinvgauss(x, m, l); + cout << "x = " << x << ", pinvgauss(x, m, l) = " << p << endl; // R 0.4 0.2706137 + double qg = qgamma(1.- p, 0.5, 1.0, true, false); + cout << " qgamma(1.- p, 0.5, 1.0, true, false) = " << qg << endl; // 0.606817 + double g = guess_whitmore(p, m, l); + cout << "m = " << m << ", l = " << l << ", x = " << x << ", guess = " << g + << ", diff = " << (x - g) << endl; + + g = guess_wheeler(p, m, l); + cout << "m = " << m << ", l = " << l << ", x = " << x << ", guess = " << g + << ", diff = " << (x - g) << endl; + + g = guess_bagshaw(p, m, l); + cout << "m = " << m << ", l = " << l << ", x = " << x << ", guess = " << g + << ", diff = " << (x - g) << endl; + + // m = 1, l = 10, x = 0.9, guess = 0.89792, diff = 0.00231075 so a better fit. + // x = 0.9, guess = 0.887907 + // x = 0.5, guess = 0.474977 + // x = 0.4, guess = 0.369597 + // x = 0.2, guess = 0.155196 + + // m = 1, l = 2, x = 0.9, guess = 1.0312, diff = -0.145778 + // m = 1, l = 2, x = 0.1, guess = 0.122201, diff = -0.222013 + // m = 1, l = 2, x = 0.2, guess = 0.299326, diff = -0.49663 + // m = 1, l = 2, x = 0.5, guess = 1.00437, diff = -1.00875 + // m = 1, l = 2, x = 0.7, guess = 1.01517, diff = -0.450247 + + double ls[7] = {0.1, 0.2, 0.5, 1., 2., 10, 100}; // scale values. + double ms[10] = {0.001, 0.02, 0.1, 0.2, 0.5, 0.9, 1., 2., 10, 100}; // mean values. + */ + + cout.precision(6); // Restore to default. + } // try + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + + +/* + +Output is: + +inverse_gaussian_example.cpp + inverse_gaussian_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\inverse_gaussian_example.exe + Example: Inverse Gaussian Distribution. + (Standard) Inverse Gaussian distribution, mean = 1, scale = 1 + Probability distribution function (pdf) values + z pdf + 2.23e-308 -1.#IND + 0.2 0.90052111680384117 + 0.4 1.0055127039453111 + 0.6 0.75123750098955733 + 0.8 0.54377310461643302 + 1 0.3989422804014327 + 1.2 0.29846949816803292 + 1.4 0.2274579835638664 + 1.6 0.17614566625628389 + 1.8 0.13829083543591469 + 2 0.10984782236693062 + 2.2 0.088133964251182237 + 2.4 0.071327382959107177 + 2.6 0.058162562161661699 + 2.8 0.047742223328567722 + 3 0.039418357969819712 + 3.2 0.032715223861241892 + 3.4 0.027278388940958308 + 3.6 0.022840312999395804 + 3.8 0.019196657941016954 + 4 0.016189699458236451 + Integral (area under the curve) from 0 up to z (cdf) + z cdf + 2.23e-308 0 + 0.2 0.063753567519976254 + 0.4 0.2706136704424541 + 0.6 0.44638391340412931 + 0.8 0.57472390962590925 + 1 0.66810200122317065 + 1.2 0.73724578422952536 + 1.4 0.78944214237790356 + 1.6 0.82953458108474554 + 1.8 0.86079282968276671 + 2 0.88547542598600626 + 2.2 0.90517870624273966 + 2.4 0.92105495653509362 + 2.6 0.93395164268166786 + 2.8 0.94450240360053817 + 3 0.95318792074278835 + 3.2 0.96037753019309191 + 3.4 0.96635823989417369 + 3.6 0.97135533107998406 + 3.8 0.97554722413538364 + 4 0.97907636417888622 + 0.40000000000000008 + 0.99999999999999967 + 1.9999999999999973 + + + +> SuppDists::dinvGauss(2, 1, 1) [1] 0.1098478 +> SuppDists::dinvGauss(0.4, 1, 1) [1] 1.005513 +> SuppDists::dinvGauss(0.5, 1, 1) [1] 0.8787826 +> SuppDists::dinvGauss(0.39, 1, 1) [1] 1.016559 +> SuppDists::dinvGauss(0.38, 1, 1) [1] 1.027006 +> SuppDists::dinvGauss(0.37, 1, 1) [1] 1.036748 +> SuppDists::dinvGauss(0.36, 1, 1) [1] 1.045661 +> SuppDists::dinvGauss(0.35, 1, 1) [1] 1.053611 +> SuppDists::dinvGauss(0.3, 1, 1) [1] 1.072888 +> SuppDists::dinvGauss(0.1, 1, 1) [1] 0.2197948 +> SuppDists::dinvGauss(0.2, 1, 1) [1] 0.9005211 +> +x = 0.3 [1, 1] 1.0728879234594337 // R SuppDists::dinvGauss(0.3, 1, 1) [1] 1.072888 + +x = 1 [1, 1] 0.3989422804014327 + + + 0 " NA" + 1 "0.3989422804014327" + 2 "0.10984782236693059" + 3 "0.039418357969819733" + 4 "0.016189699458236468" + 5 "0.007204168934430732" + 6 "0.003379893528659049" + 7 "0.0016462878258114036" + 8 "0.00082460931140859956" + 9 "0.00042207355643694234" +10 "0.00021979480031862676" + + +[1] " NA" " 0.690988298942671" "0.11539974210409144" + [4] "0.01799698883772935" "0.0029555399206496469" "0.00050863023587406587" + [7] "9.0761842931362914e-05" "1.6655279133132795e-05" "3.1243174913715429e-06" +[10] "5.96530227727434e-07" "1.1555606328299836e-07" + + +matC(dinvGauss(0:10, 1, 3), digits=17) df = 3 +[1] " NA" " 0.690988298942671" "0.11539974210409144" + [4] "0.01799698883772935" "0.0029555399206496469" "0.00050863023587406587" + [7] "9.0761842931362914e-05" "1.6655279133132795e-05" "3.1243174913715429e-06" +[10] "5.96530227727434e-07" "1.1555606328299836e-07" +$title +[1] "Inverse Gaussian" + +$nu +[1] 1 + +$lambda +[1] 3 + +$Mean +[1] 1 + +$Median +[1] 0.8596309 + +$Mode +[1] 0.618034 + +$Variance +[1] 0.3333333 + +$SD +[1] 0.5773503 + +$ThirdCentralMoment +[1] 0.3333333 + +$FourthCentralMoment +[1] 0.8888889 + +$PearsonsSkewness...mean.minus.mode.div.SD +[1] 0.6615845 + +$Skewness...sqrtB1 +[1] 1.732051 + +$Kurtosis...B2.minus.3 +[1] 5 + + Example: Wald distribution. + (Standard) Wald distribution, mean = 1, scale = 1 + 1 dx = 0.24890250442652451, x = 0.70924622051646713 + 2 dx = -0.038547954953794553, x = 0.46034371608994262 + 3 dx = -0.0011074090830291131, x = 0.49889167104373716 + 4 dx = -9.1987259926368029e-007, x = 0.49999908012676625 + 5 dx = -6.346513344581067e-013, x = 0.49999999999936551 + dx = 6.3168242705156857e-017 at i = 6 + qinvgauss(0.3649755481729598, 1, 1) = 0.50000000000000011 + 1 dx = 0.6719944578376621, x = 1.3735318786222666 + 2 dx = -0.16997432635769361, x = 0.70153742078460446 + 3 dx = -0.027865119206495724, x = 0.87151174714229807 + 4 dx = -0.00062283290009492603, x = 0.89937686634879377 + 5 dx = -3.0075104108208687e-007, x = 0.89999969924888867 + 6 dx = -7.0485322513588089e-014, x = 0.89999999999992975 + 7 dx = 9.557331866250277e-016, x = 0.90000000000000024 + dx = 0 at i = 8 + qinvgauss(0.62502320258649202, 1, 1) = 0.89999999999999925 + 1 dx = -0.0052296256747447678, x = 0.19483508278446249 + 2 dx = 6.4699046853900505e-005, x = 0.20006470845920726 + 3 dx = 9.4123530465288137e-009, x = 0.20000000941235335 + 4 dx = 2.7739513919147025e-016, x = 0.20000000000000032 + dx = 1.5410841066192808e-016 at i = 5 + qinvgauss(0.063753567519976254, 1, 1) = 0.20000000000000004 + 1 dx = -1, x = -0.46073286697416105 + 2 dx = 0.47665501251497061, x = 0.53926713302583895 + 3 dx = -0.171105768635964, x = 0.062612120510868341 + 4 dx = 0.091490360797512563, x = 0.23371788914683234 + 5 dx = 0.029410311722649803, x = 0.14222752834931979 + 6 dx = 0.010761845493592421, x = 0.11281721662666999 + 7 dx = 0.0019864890597643035, x = 0.10205537113307757 + 8 dx = 6.8800383732599561e-005, x = 0.10006888207331327 + 9 dx = 8.1689466405590418e-008, x = 0.10000008168958067 + 10 dx = 1.133634672475146e-013, x = 0.10000000000011428 + 11 dx = 5.9588135045224526e-016, x = 0.10000000000000091 + 12 dx = 3.433223674791152e-016, x = 0.10000000000000031 + dx = 9.0763384505974048e-017 at i = 13 + qinvgauss(0.0040761113207110162, 1, 1) = 0.099999999999999964 + + + wald_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\wald_example.exe + Example: Wald distribution. + Tolerance = 6.66134e-016 + (Standard) Wald distribution, mean = 1, scale = 1 + cdf(x, 1,1) 4.1390252102096375e-012 + qinvgauss(pinvgauss(x, 1, 1) = 0.020116801973767886, diff = -0.00011680197376788548, fraction = -0.005840098688394274 + ____________________________________________________________ + wald 1, 1 + x = 0.02, diff x - qinvgauss(cdf) = -0.00011680197376788548 + x = 0.10000000000000001, diff x - qinvgauss(cdf) = 8.7430063189231078e-016 + x = 0.20000000000000001, diff x - qinvgauss(cdf) = -1.1102230246251565e-016 + x = 0.29999999999999999, diff x - qinvgauss(cdf) = 0 + x = 0.40000000000000002, diff x - qinvgauss(cdf) = 2.2204460492503131e-016 + x = 0.5, diff x - qinvgauss(cdf) = -1.1102230246251565e-016 + x = 0.59999999999999998, diff x - qinvgauss(cdf) = 1.1102230246251565e-016 + x = 0.80000000000000004, diff x - qinvgauss(cdf) = 1.1102230246251565e-016 + x = 0.90000000000000002, diff x - qinvgauss(cdf) = 0 + x = 0.98999999999999999, diff x - qinvgauss(cdf) = -1.1102230246251565e-016 + x = 0.999, diff x - qinvgauss(cdf) = -1.1102230246251565e-016 + + +*/ + + + diff --git a/src/boost/libs/math/example/jacobi_zeta_example.cpp b/src/boost/libs/math/example/jacobi_zeta_example.cpp new file mode 100644 index 000000000..062f27baa --- /dev/null +++ b/src/boost/libs/math/example/jacobi_zeta_example.cpp @@ -0,0 +1,104 @@ +// Copyright Paul A. Bristow, 2019 + +// 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) + +/*! \title Simple example of computation of the Jacobi Zeta function using Boost.Math, +and also using corresponding WolframAlpha commands. +*/ + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS +# error "This example requires a C++ compiler that supports C++11 numeric_limits. Try C++11 or later." +#endif + +#include <boost/math/special_functions/jacobi_zeta.hpp> // For jacobi_zeta function. +#include <boost/multiprecision/cpp_bin_float.hpp> // For cpp_bin_float_50. + +#include <iostream> +#include <limits> +#include <iostream> +#include <exception> + +int main() +{ + try + { + std::cout.precision(std::numeric_limits<double>::max_digits10); // Show all potentially significant digits. + std::cout.setf(std::ios_base::showpoint); // Include any significant trailing zeros. + + using boost::math::jacobi_zeta; // jacobi_zeta(T1 k, T2 phi) |k| <=1, k = sqrt(m) + using boost::multiprecision::cpp_bin_float_50; + + // Wolfram Mathworld function JacobiZeta[phi, m] where m = k^2 + // JacobiZeta[phi,m] gives the Jacobi zeta function Z(phi | m) + + // If phi = 2, and elliptic modulus k = 0.9 so m = 0.9 * 0.9 = 0.81 + + // https://reference.wolfram.com/language/ref/JacobiZeta.html // Function information. + // A simple computation using phi = 2. and m = 0.9 * 0.9 + // JacobiZeta[2, 0.9 * 0.9] + // https://www.wolframalpha.com/input/?i=JacobiZeta%5B2,+0.9+*+0.9%5D + // -0.248584... + // To get the expected 17 decimal digits precision for a 64-bit double type, + // we need to ask thus: + // N[JacobiZeta[2, 0.9 * 0.9],17] + // https://www.wolframalpha.com/input/?i=N%5BJacobiZeta%5B2,+0.9+*+0.9%5D,17%5D + + double k = 0.9; + double m = k * k; + double phi = 2.; + + std::cout << "m = k^2 = " << m << std::endl; // m = k^2 = 0.81000000000000005 + std::cout << "jacobi_zeta(" << k << ", " << phi << " ) = " << jacobi_zeta(k, phi) << std::endl; + // jacobi_zeta(0.90000000000000002, 2.0000000000000000 ) = + // -0.24858442708494899 Boost.Math + // -0.24858442708494893 Wolfram + // that agree within the expected precision of 17 decimal digits for 64-bit type double. + + // We can also easily get a higher precision too: + // For example, to get 50 decimal digit precision using WolframAlpha: + // N[JacobiZeta[2, 0.9 * 0.9],50] + // https://www.wolframalpha.com/input/?i=N%5BJacobiZeta%5B2,+0.9+*+0.9%5D,50%5D + // -0.24858442708494893408462856109734087389683955309853 + + // Using Boost.Multiprecision we can do them same almost as easily. + + // To check that we are not losing precision, we show all the significant digits of the arguments ad result: + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); // Show all significant digits. + + // We can force the computation to use 50 decimal digit precision thus: + cpp_bin_float_50 k50("0.9"); + cpp_bin_float_50 phi50("2."); + + std::cout << "jacobi_zeta(" << k50 << ", " << phi50 << " ) = " << jacobi_zeta(k50, phi50) << std::endl; + // jacobi_zeta(0.90000000000000000000000000000000000000000000000000, + // 2.0000000000000000000000000000000000000000000000000 ) + // = -0.24858442708494893408462856109734087389683955309853 + + // and a comparison with Wolfram shows agreement to the expected precision. + // -0.24858442708494893408462856109734087389683955309853 Boost.Math + // -0.24858442708494893408462856109734087389683955309853 Wolfram + + // Taking care not to fall into the awaiting pit, we ensure that ALL arguments passed are of the + // appropriate 50-digit precision and do NOT suffer from precision reduction to that of type double, + // We do NOT write: + std::cout << "jacobi_zeta<cpp_bin_float_50>(0.9, 2.) = " << jacobi_zeta<cpp_bin_float_50>(0.9, 2) << std::endl; + // jacobi_zeta(0.90000000000000000000000000000000000000000000000000, + // 2.0000000000000000000000000000000000000000000000000 ) + // = -0.24858442708494895921459900494815797085727097762164 << Wrong at about 17th digit! + // -0.24858442708494893408462856109734087389683955309853 Wolfram + } + catch (std::exception const& ex) + { + // Lacking try&catch blocks, the program will abort after any throw, whereas the + // message below from the thrown exception will give some helpful clues as to the cause of the problem. + std::cout << "\n""Message from thrown exception was:\n " << ex.what() << std::endl; + // An example of message: + // std::cout << " = " << jacobi_zeta(2, 0.5) << std::endl; + // Message from thrown exception was: + // Error in function boost::math::ellint_k<long double>(long double) : Got k = 2, function requires |k| <= 1 + // Shows that first parameter is k and is out of range, as the definition in docs jacobi_zeta(T1 k, T2 phi); + } +} // int main() diff --git a/src/boost/libs/math/example/lambert_w_basic_example.cpp b/src/boost/libs/math/example/lambert_w_basic_example.cpp new file mode 100644 index 000000000..869416194 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_basic_example.cpp @@ -0,0 +1,30 @@ +// Copyright Paul A. Bristow 2018 + +// 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) + +// Example of most basic call of both lambert W functions. +// Only requires C++03 +// (and optionally a call of max_digits10 to show precision). + +#include <boost/math/special_functions/lambert_w.hpp> // For lambert_w0 and wm1 functions. + +#include <iostream> +#include <iomanip> + +int main() +{ + double z = 2.0; + double w0 = boost::math::lambert_w0(z); + std::cout.setf(std::ios_base::showpoint); // Include any trailing zeros. + std::cout.precision(std::numeric_limits<double>::max_digits10); // Show all possibly significant digits. + // Avoid using max_digfigs10 so as many old compilers can run the most basic lambert_w0 test? + // Require to get max_digits10 + // [ run lambert_w_basic_example.cpp : : : [ requires cxx11_numeric_limits ] ] + std::cout << " lambert_w0(" << z << ") = " << w0 << std::endl; // lambert_w0(2.00000) = 0.852606 + z = -0.2; + double wm1 = boost::math::lambert_wm1(z); + std::cout << " lambert_wm1(" << z << ") = " << wm1 << std::endl; // lambert_wm1(-0.200000) = -2.54264 + return 0; +} // int main() diff --git a/src/boost/libs/math/example/lambert_w_diode.cpp b/src/boost/libs/math/example/lambert_w_diode.cpp new file mode 100644 index 000000000..79c64bd26 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_diode.cpp @@ -0,0 +1,165 @@ +// Copyright Paul A. Bristow 2016 +// Copyright John Z. Maddock 2016 + +// 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). + +/*! brief Example of using Lambert W function to compute current through a diode connected transistor with preset series resistance. + \details T. C. Banwell and A. Jayakumar, + Exact analytical solution of current flow through diode with series resistance, + Electron Letters, 36(4):291-2 (2000) + DOI: doi.org/10.1049/el:20000301 + + The current through a diode connected NPN bipolar junction transistor (BJT) + type 2N2222 (See https://en.wikipedia.org/wiki/2N2222 and + https://www.fairchildsemi.com/datasheets/PN/PN2222.pdf Datasheet) + was measured, for a voltage between 0.3 to 1 volt, see Fig 2 for a log plot, + showing a knee visible at about 0.6 V. + + The transistor parameter isat was estimated to be 25 fA and the ideality factor = 1.0. + The intrinsic emitter resistance re was estimated from the rsat = 0 data to be 0.3 ohm. + + The solid curves in Figure 2 are calculated using equation 5 with rsat included with re. + + http://www3.imperial.ac.uk/pls/portallive/docs/1/7292572.PDF +*/ + +#include <boost/math/special_functions/lambert_w.hpp> +using boost::math::lambert_w0; + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <array> +#include <vector> + +/*! +Compute thermal voltage as a function of temperature, +about 25 mV at room temperature. +https://en.wikipedia.org/wiki/Boltzmann_constant#Role_in_semiconductor_physics:_the_thermal_voltage + +\param temperature Temperature (degrees centigrade). +*/ +const double v_thermal(double temperature) +{ + constexpr const double boltzmann_k = 1.38e-23; // joules/kelvin. + const double charge_q = 1.6021766208e-19; // Charge of an electron (columb). + double temp =+ 273; // Degrees C to K. + return boltzmann_k * temp / charge_q; +} // v_thermal + +/*! +Banwell & Jayakumar, equation 2 +*/ +double i(double isat, double vd, double vt, double nu) +{ + double i = isat * (exp(vd / (nu * vt)) - 1); + return i; +} // + +/*! + +Banwell & Jayakumar, Equation 4. +i current flow = isat +v voltage source. +isat reverse saturation current in equation 4. +(might implement equation 4 instead of simpler equation 5?). +vd voltage drop = v - i* rs (equation 1). +vt thermal voltage, 0.0257025 = 25 mV. +nu junction ideality factor (default = unity), also known as the emission coefficient. +re intrinsic emitter resistance, estimated to be 0.3 ohm from low current. +rsat reverse saturation current + +\param v Voltage V to compute current I(V). +\param vt Thermal voltage, for example 0.0257025 = 25 mV, computed from boltzmann_k * temp / charge_q; +\param rsat Resistance in series with the diode. +\param re Intrinsic emitter resistance (estimated to be 0.3 ohm from the Rs = 0 data) +\param isat Reverse saturation current (See equation 2). +\param nu Ideality factor (default = unity). + +\returns I amp as function of V volt. + +*/ +double iv(double v, double vt, double rsat, double re, double isat, double nu = 1.) +{ + // V thermal 0.0257025 = 25 mV + // was double i = (nu * vt/r) * lambert_w((i0 * r) / (nu * vt)); equ 5. + + rsat = rsat + re; + double i = nu * vt / rsat; + std::cout << "nu * vt / rsat = " << i << std::endl; // 0.000103223 + + double x = isat * rsat / (nu * vt); + std::cout << "isat * rsat / (nu * vt) = " << x << std::endl; + + double eterm = (v + isat * rsat) / (nu * vt); + std::cout << "(v + isat * rsat) / (nu * vt) = " << eterm << std::endl; + + double e = exp(eterm); + std::cout << "exp(eterm) = " << e << std::endl; + + double w0 = lambert_w0(x * e); + std::cout << "w0 = " << w0 << std::endl; + return i * w0 - isat; + +} // double iv + +std::array<double, 5> rss = {0., 2.18, 10., 51., 249}; // series resistance (ohm). +std::array<double, 8> vds = { 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 }; // Diode voltage. + +int main() +{ + try + { + std::cout << "Lambert W diode current example." << std::endl; + + //[lambert_w_diode_example_1 + double x = 0.01; + //std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.00990147 + + double nu = 1.0; // Assumed ideal. + double vt = v_thermal(25); // v thermal, Shockley equation, expect about 25 mV at room temperature. + double boltzmann_k = 1.38e-23; // joules/kelvin + double temp = 273 + 25; + double charge_q = 1.6e-19; // column + vt = boltzmann_k * temp / charge_q; + std::cout << "V thermal " + << vt << std::endl; // V thermal 0.0257025 = 25 mV + double rsat = 0.; + double isat = 25.e-15; // 25 fA; + std::cout << "Isat = " << isat << std::endl; + + double re = 0.3; // Estimated from slope of straight section of graph (equation 6). + + double v = 0.9; + double icalc = iv(v, vt, 249., re, isat); + + std::cout << "voltage = " << v << ", current = " << icalc << ", " << log(icalc) << std::endl; // voltage = 0.9, current = 0.00108485, -6.82631 + //] [/lambert_w_diode_example_1] + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } +} // int main() + +/* + Output: +//[lambert_w_output_1 + Lambert W diode current example. + V thermal 0.0257025 + Isat = 2.5e-14 + nu * vt / rsat = 0.000103099 + isat * rsat / (nu * vt) = 2.42486e-10 + (v + isat * rsat) / (nu * vt) = 35.016 + exp(eterm) = 1.61167e+15 + w0 = 10.5225 + voltage = 0.9, current = 0.00108485, -6.82631 + +//] [/lambert_w_output_1] +*/ + diff --git a/src/boost/libs/math/example/lambert_w_diode_graph.cpp b/src/boost/libs/math/example/lambert_w_diode_graph.cpp new file mode 100644 index 000000000..bb073bd36 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_diode_graph.cpp @@ -0,0 +1,283 @@ +// Copyright Paul A. Bristow 2016 +// Copyright John Z. Maddock 2016 + +// 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). + +/*! \brief Graph showing use of Lambert W function to compute current +through a diode-connected transistor with preset series resistance. + +\details T. C. Banwell and A. Jayakumar, +Exact analytical solution of current flow through diode with series resistance, +Electron Letters, 36(4):291-2 (2000). +DOI: doi.org/10.1049/el:20000301 + +The current through a diode connected NPN bipolar junction transistor (BJT) +type 2N2222 (See https://en.wikipedia.org/wiki/2N2222 and +https://www.fairchildsemi.com/datasheets/PN/PN2222.pdf Datasheet) +was measured, for a voltage between 0.3 to 1 volt, see Fig 2 for a log plot, showing a knee visible at about 0.6 V. + +The transistor parameter I sat was estimated to be 25 fA and the ideality factor = 1.0. +The intrinsic emitter resistance re was estimated from the rsat = 0 data to be 0.3 ohm. + +The solid curves in Figure 2 are calculated using equation 5 with rsat included with re. + +http://www3.imperial.ac.uk/pls/portallive/docs/1/7292572.PDF + +*/ + +#ifndef BOOST_MATH_STANDALONE + +#include <boost/math/special_functions/lambert_w.hpp> +using boost::math::lambert_w0; +#include <boost/math/special_functions.hpp> +using boost::math::isfinite; +#include <boost/svg_plot/svg_2d_plot.hpp> +using namespace boost::svg; + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <array> +#include <vector> +#include <utility> +using std::pair; +#include <map> +using std::map; +#include <set> +using std::multiset; +#include <limits> +using std::numeric_limits; +#include <cmath> // + +/*! +Compute thermal voltage as a function of temperature, +about 25 mV at room temperature. +https://en.wikipedia.org/wiki/Boltzmann_constant#Role_in_semiconductor_physics:_the_thermal_voltage + +\param temperature Temperature (degrees Celsius). +*/ +const double v_thermal(double temperature) +{ + constexpr const double boltzmann_k = 1.38e-23; // joules/kelvin. + constexpr double charge_q = 1.6021766208e-19; // Charge of an electron (columb). + double temp = +273; // Degrees C to K. + return boltzmann_k * temp / charge_q; +} // v_thermal + + /*! + Banwell & Jayakumar, equation 2, page 291. + */ +double i(double isat, double vd, double vt, double nu) +{ + double i = isat * (exp(vd / (nu * vt)) - 1); + return i; +} // + + /*! + Banwell & Jayakumar, Equation 4, page 291. + i current flow = isat + v voltage source. + isat reverse saturation current in equation 4. + (might implement equation 4 instead of simpler equation 5?). + vd voltage drop = v - i* rs (equation 1). + vt thermal voltage, 0.0257025 = 25 mV. + nu junction ideality factor (default = unity), also known as the emission coefficient. + re intrinsic emitter resistance, estimated to be 0.3 ohm from low current. + rsat reverse saturation current + + \param v Voltage V to compute current I(V). + \param vt Thermal voltage, for example 0.0257025 = 25 mV, computed from boltzmann_k * temp / charge_q; + \param rsat Resistance in series with the diode. + \param re Intrinsic emitter resistance (estimated to be 0.3 ohm from the Rs = 0 data) + \param isat Reverse saturation current (See equation 2). + \param nu Ideality factor (default = unity). + + \returns I amp as function of V volt. + */ + +//[lambert_w_diode_graph_2 +double iv(double v, double vt, double rsat, double re, double isat, double nu = 1.) +{ + // V thermal 0.0257025 = 25 mV + // was double i = (nu * vt/r) * lambert_w((i0 * r) / (nu * vt)); equ 5. + + rsat = rsat + re; + double i = nu * vt / rsat; + // std::cout << "nu * vt / rsat = " << i << std::endl; // 0.000103223 + + double x = isat * rsat / (nu * vt); +// std::cout << "isat * rsat / (nu * vt) = " << x << std::endl; + + double eterm = (v + isat * rsat) / (nu * vt); + // std::cout << "(v + isat * rsat) / (nu * vt) = " << eterm << std::endl; + + double e = exp(eterm); +// std::cout << "exp(eterm) = " << e << std::endl; + + double w0 = lambert_w0(x * e); +// std::cout << "w0 = " << w0 << std::endl; + return i * w0 - isat; +} // double iv + +//] [\lambert_w_diode_graph_2] + + +std::array<double, 5> rss = { 0., 2.18, 10., 51., 249 }; // series resistance (ohm). +std::array<double, 7> vds = { 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 }; // Diode voltage. +std::array<double, 7> lni = { -19.65, -15.75, -11.86, -7.97, -4.08, -0.0195, 3.6 }; // ln(current). + +int main() +{ + try + { + std::cout << "Lambert W diode current example." << std::endl; + +//[lambert_w_diode_graph_1 + double nu = 1.0; // Assumed ideal. + double vt = v_thermal(25); // v thermal, Shockley equation, expect about 25 mV at room temperature. + double boltzmann_k = 1.38e-23; // joules/kelvin + double temp = 273 + 25; + double charge_q = 1.6e-19; // column + vt = boltzmann_k * temp / charge_q; + std::cout << "V thermal " << vt << std::endl; // V thermal 0.0257025 = 25 mV + double rsat = 0.; + double isat = 25.e-15; // 25 fA; + std::cout << "Isat = " << isat << std::endl; + double re = 0.3; // Estimated from slope of straight section of graph (equation 6). + double v = 0.9; + double icalc = iv(v, vt, 249., re, isat); + std::cout << "voltage = " << v << ", current = " << icalc << ", " << log(icalc) << std::endl; // voltage = 0.9, current = 0.00108485, -6.82631 +//] [/lambert_w_diode_graph_1] + + // Plot a few measured data points. + std::map<const double, double> zero_data; // Extrapolated from slope of measurements with no external resistor. + zero_data[0.3] = -19.65; + zero_data[0.4] = -15.75; + zero_data[0.5] = -11.86; + zero_data[0.6] = -7.97; + zero_data[0.7] = -4.08; + zero_data[0.8] = -0.0195; + zero_data[0.9] = 3.9; + + std::map<const double, double> measured_zero_data; // No external series resistor. + measured_zero_data[0.3] = -19.65; + measured_zero_data[0.4] = -15.75; + measured_zero_data[0.5] = -11.86; + measured_zero_data[0.6] = -7.97; + measured_zero_data[0.7] = -4.2; + measured_zero_data[0.72] = -3.5; + measured_zero_data[0.74] = -2.8; + measured_zero_data[0.76] = -2.3; + measured_zero_data[0.78] = -2.0; + // Measured from Fig 2 as raw data not available. + + double step = 0.1; + for (int i = 0; i < vds.size(); i++) + { + zero_data[vds[i]] = lni[i]; + std::cout << lni[i] << " " << vds[i] << std::endl; + } + step = 0.01; + + std::map<const double, double> data_2; + for (double v = 0.3; v < 1.; v += step) + { + double current = iv(v, vt, 2., re, isat); + data_2[v] = log(current); + // std::cout << "v " << v << ", current = " << current << " log current = " << log(current) << std::endl; + } + std::map<const double, double> data_10; + for (double v = 0.3; v < 1.; v += step) + { + double current = iv(v, vt, 10., re, isat); + data_10[v] = log(current); + // std::cout << "v " << v << ", current = " << current << " log current = " << log(current) << std::endl; + } + std::map<const double, double> data_51; + for (double v = 0.3; v < 1.; v += step) + { + double current = iv(v, vt, 51., re, isat); + data_51[v] = log(current); + // std::cout << "v " << v << ", current = " << current << " log current = " << log(current) << std::endl; + } + std::map<const double, double> data_249; + for (double v = 0.3; v < 1.; v += step) + { + double current = iv(v, vt, 249., re, isat); + data_249[v] = log(current); + // std::cout << "v " << v << ", current = " << current << " log current = " << log(current) << std::endl; + } + + svg_2d_plot data_plot; + + data_plot.title("Diode current versus voltage") + .x_size(400) + .y_size(300) + .legend_on(true) + .legend_lines(true) + .x_label("voltage (V)") + .y_label("log(current) (A)") + //.x_label_on(true) + //.y_label_on(true) + //.xy_values_on(false) + .x_range(0.25, 1.) + .y_range(-20., +4.) + .x_major_interval(0.1) + .y_major_interval(4) + .x_major_grid_on(true) + .y_major_grid_on(true) + //.x_values_on(true) + //.y_values_on(true) + .y_values_rotation(horizontal) + //.plot_window_on(true) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2016") + //.background_border_color(black); + ; + + // ₀ = subscript zero. + data_plot.plot(zero_data, "I₀(V)").fill_color(lightgray).shape(none).size(3).line_on(true).line_width(0.5); + data_plot.plot(measured_zero_data, "Rs=0 Ω").fill_color(lightgray).shape(square).size(3).line_on(true).line_width(0.5); + data_plot.plot(data_2, "Rs=2 Ω").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plot.plot(data_10, "Rs=10 Ω").line_color(purple).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plot.plot(data_51, "Rs=51 Ω").line_color(green).shape(none).line_on(true).line_width(1); + data_plot.plot(data_249, "Rs=249 Ω").line_color(red).shape(none).line_on(true).line_width(1); + data_plot.write("./diode_iv_plot"); + + // bezier_on(true); + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } + + +} // int main() + + /* + + //[lambert_w_output_1 + Output: + Lambert W diode current example. + V thermal 0.0257025 + Isat = 2.5e-14 + voltage = 0.9, current = 0.00108485, -6.82631 + -19.65 0.3 + -15.75 0.4 + -11.86 0.5 + -7.97 0.6 + -4.08 0.7 + -0.0195 0.8 + 3.6 0.9 + + //] [/lambert_w_output_1] + */ +#endif // BOOST_MATH_STANDALONE diff --git a/src/boost/libs/math/example/lambert_w_example.cpp b/src/boost/libs/math/example/lambert_w_example.cpp new file mode 100644 index 000000000..5c862a3b7 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_example.cpp @@ -0,0 +1,243 @@ +// Copyright Paul A. Bristow 2016. + +// 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). + +// Test that can build and run a simple example of Lambert W function, +// using algorithm of Thomas Luu. +// https://svn.boost.org/trac/boost/ticket/11027 + +#ifndef BOOST_MATH_STANDALONE + +#include <boost/config.hpp> // for BOOST_PLATFORM, BOOST_COMPILER, BOOST_STDLIB ... +#include <boost/version.hpp> // for BOOST_MSVC versions. +#include <boost/cstdint.hpp> +#include <boost/exception/exception.hpp> // boost::exception +#include <boost/math/constants/constants.hpp> // For exp_minus_one == 3.67879441171442321595523770161460867e-01. + +#define BOOST_MATH_INSTRUMENT_LAMBERT_W // #define only for diagnostic output. + +// For lambert_w function. +#include <boost/math/special_functions/lambert_w.hpp> + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <limits> // For std::numeric_limits. + +//! Show information about build, architecture, address model, platform, ... +std::string show_versions() +{ + std::ostringstream message; + + message << "Program: " << __FILE__ << "\n"; +#ifdef __TIMESTAMP__ + message << __TIMESTAMP__; +#endif + message << "\nBuildInfo:\n" " Platform " << BOOST_PLATFORM; + // http://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#define IS64BIT 1 + message << ", 64-bit."; +#else +#define IS32BIT 1 + message << ", 32-bit."; +#endif + + message << "\n Compiler " BOOST_COMPILER; +#ifdef BOOST_MSC_VER +#ifdef _MSC_FULL_VER + message << "\n MSVC version " << BOOST_STRINGIZE(_MSC_FULL_VER) << "."; +#endif +#ifdef __WIN64 + mess age << "\n WIN64" << std::endl; +#endif // __WIN64 +#ifdef _WIN32 + message << "\n WIN32" << std::endl; +#endif // __WIN32 +#endif +#ifdef __GNUC__ + //PRINT_MACRO(__GNUC__); + //PRINT_MACRO(__GNUC_MINOR__); + //PRINT_MACRO(__GNUC_PATCH__); + std::cout << "GCC " << __VERSION__ << std::endl; + //PRINT_MACRO(LONG_MAX); +#endif // __GNUC__ + + message << "\n STL " << BOOST_STDLIB; + + message << "\n Boost version " << BOOST_VERSION / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100; + +#ifdef BOOST_HAS_FLOAT128 + message << ", BOOST_HAS_FLOAT128" << std::endl; +#endif + message << std::endl; + return message.str(); +} // std::string versions() + +int main() +{ + try + { + //std::cout << "Lambert W example basic!" << std::endl; + //std::cout << show_versions() << std::endl; + + //std::cout << exp(1) << std::endl; // 2.71828 + //std::cout << exp(-1) << std::endl; // 0.367879 + //std::cout << std::numeric_limits<double>::epsilon() / 2 << std::endl; // 1.11022e-16 + + using namespace boost::math; + using boost::math::constants::exp_minus_one; + double x = 1.; + + double W1 = lambert_w(1.); + // Note, NOT integer X, for example: lambert_w(1); or will get message like + // error C2338: Must be floating-point, not integer type, for example W(1.), not W(1)! + // + + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.567143 + // This 'golden ratio' for exponentials is http://mathworld.wolfram.com/OmegaConstant.html + // since exp[-W(1)] = W(1) + // A030178 Decimal expansion of LambertW(1): the solution to x*exp(x) + // = 0.5671432904097838729999686622103555497538157871865125081351310792230457930866 + // http://oeis.org/A030178 + + double expplogone = exp(-lambert_w(1.)); + if (expplogone != W1) + { + std::cout << expplogone << " " << W1 << std::endl; // + } + + +//[lambert_w_example_1 + + x = 0.01; + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.00990147 +//] [/lambert_w_example_1] + x = -0.01; + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // -0.0101015 + x = -0.1; + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // + /**/ + + for (double xd = 1.; xd < 1e20; xd *= 10) + { + + // 1. 0.56714329040978387 + // 0.56714329040978384 + + // 10 1.7455280027406994 + // 1.7455280027406994 + + // 100 3.3856301402900502 + // 3.3856301402900502 + // 1000 5.2496028524015959 + // 5.249602852401596227126056319697306282521472386059592844451465483991362228320942832739693150854347718 + + // 1e19 40.058769161984308 + // 40.05876916198431163898797971203180915622644925765346546858291325452428038208071849105889199253335063 + std::cout << "Lambert W (" << xd << ") = " << lambert_w(xd) << std::endl; // + } + // + // Test near singularity. + + // http://www.wolframalpha.com/input/?i=N%5Blambert_w%5B-0.367879%5D,17%5D test value N[lambert_w[-0.367879],17] + // -0.367879441171442321595523770161460867445811131031767834 + x = -0.367879; // < -exp(1) = -0.367879 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // Lambert W (-0.36787900000000001) = -0.99845210378080340 + // -0.99845210378080340 + // -0.99845210378072726 N[lambert_w[-0.367879],17] wolfram so very close. + + x = -0.3678794; // expect -0.99952696660756813 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + x = -0.36787944; // expect -0.99992019848408340 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + x = -0.367879441; // -0.99996947070054883 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + x = -0.36787944117; // -0.99999719977527159 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + x = -0.367879441171; // -0.99999844928821992 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + + x = -exp_minus_one<double>() + std::numeric_limits<double>::epsilon(); + // Lambert W (-0.36787944117144211) = -0.99999996349975895 + // N[lambert_w[-0.36787944117144211],17] == -0.99999996608315303 + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + std::cout << " 1 - sqrt(eps) = " << static_cast<double>(1) - sqrt(std::numeric_limits<double>::epsilon()) << std::endl; + x = -exp_minus_one<double>(); + // N[lambert_w[-0.36787944117144233],17] == -1.000000000000000 + 6.7595465843924897*10^-9i + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // 0.0 + // At Singularity - 0.36787944117144233 == -0.36787944117144233 returned - 1.0000000000000000 + // Lambert W(-0.36787944117144233) = -1.0000000000000000 + + + x = (std::numeric_limits<double>::max)()/4; + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // OK 702.023799146706 + x = (std::numeric_limits<double>::max)()/2; + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // + x = (std::numeric_limits<double>::max)(); + std::cout << "Lambert W (" << x << ") = " << lambert_w(x) << std::endl; // + // Error in function boost::math::log1p<double>(double): numeric overflow + /* */ + + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } + + +} // int main() + + /* + +//[lambert_w_output_1 + Output: + + 1> example_basic.cpp +1> Generating code +1> All 237 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. +1> Finished generating code +1> LambertW.vcxproj -> J:\Cpp\Misc\x64\Release\LambertW.exe +1> LambertW.vcxproj -> J:\Cpp\Misc\x64\Release\LambertW.pdb (Full PDB) +1> Lambert W example basic! +1> Platform: Win32 +1> Compiler: Microsoft Visual C++ version 14.0 +1> STL : Dinkumware standard library version 650 +1> Boost : 1.63.0 +1> _MSC_FULL_VER = 190024123 +1> Win32 +1> x64 +1> (x64) +1> Iteration #0, w0 0.577547206058041, w1 = 0.567143616915443, difference = 0.0289944962755619, relative 0.018343835374856 +1> Iteration #1, w0 0.567143616915443, w1 = 0.567143290409784, difference = 9.02208135089566e-07, relative 5.75702234328901e-07 +1> Final 0.567143290409784 after 2 iterations, difference = 0 +1> Iteration #0, w0 0.577547206058041, w1 = 0.567143616915443, difference = 0.0289944962755619, relative 0.018343835374856 +1> Iteration #1, w0 0.567143616915443, w1 = 0.567143290409784, difference = 9.02208135089566e-07, relative 5.75702234328901e-07 +1> Final 0.567143290409784 after 2 iterations, difference = 0 +1> Lambert W (1) = 0.567143290409784 +1> Iteration #0, w0 0.577547206058041, w1 = 0.567143616915443, difference = 0.0289944962755619, relative 0.018343835374856 +1> Iteration #1, w0 0.567143616915443, w1 = 0.567143290409784, difference = 9.02208135089566e-07, relative 5.75702234328901e-07 +1> Final 0.567143290409784 after 2 iterations, difference = 0 +1> Iteration #0, w0 0.0099072820916067, w1 = 0.00990147384359511, difference = 5.92416060777624e-06, relative 0.000586604388734591 +1> Final 0.00990147384359511 after 1 iterations, difference = 0 +1> Lambert W (0.01) = 0.00990147384359511 +1> Iteration #0, w0 -0.0101016472705154, w1 = -0.0101015271985388, difference = -1.17664437923951e-07, relative 1.18865171889748e-05 +1> Final -0.0101015271985388 after 1 iterations, difference = 0 +1> Lambert W (-0.01) = -0.0101015271985388 +1> Iteration #0, w0 -0.111843322610692, w1 = -0.111832559158964, difference = -8.54817065376601e-06, relative 9.62461362694622e-05 +1> Iteration #1, w0 -0.111832559158964, w1 = -0.111832559158963, difference = -5.68989300120393e-16, relative 6.43929354282591e-15 +1> Final -0.111832559158963 after 2 iterations, difference = 0 +1> Lambert W (-0.1) = -0.111832559158963 +1> Iteration #0, w0 -0.998452103785573, w1 = -0.998452103780803, difference = -2.72004641033163e-15, relative 4.77662354114727e-12 +1> Final -0.998452103780803 after 1 iterations, difference = 0 +1> Lambert W (-0.367879) = -0.998452103780803 + +//] [/lambert_w_output_1] + */ + +#endif // BOOST_MATH_STANDALONE diff --git a/src/boost/libs/math/example/lambert_w_graph.cpp b/src/boost/libs/math/example/lambert_w_graph.cpp new file mode 100644 index 000000000..d084fc51b --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_graph.cpp @@ -0,0 +1,289 @@ +// Copyright Paul A. Bristow 2017 +// Copyright John Z. Maddock 2017 + +// 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). + +/*! \brief Graph showing use of Lambert W function. + +\details + +Both Lambert W0 and W-1 branches can be shown on one graph. +But useful to have another graph for larger values of argument z. +Need two separate graphs for Lambert W0 and -1 prime because +the sensible ranges and axes are too different. + +One would get too small LambertW0 in top right and W-1 in bottom left. + +*/ +#ifndef BOOST_MATH_STANDALONE + +#include <boost/math/special_functions/lambert_w.hpp> +using boost::math::lambert_w0; +using boost::math::lambert_wm1; +using boost::math::lambert_w0_prime; +using boost::math::lambert_wm1_prime; + +#include <boost/math/special_functions.hpp> +using boost::math::isfinite; +#include <boost/svg_plot/svg_2d_plot.hpp> +using namespace boost::svg; +#include <boost/svg_plot/show_2d_settings.hpp> +using boost::svg::show_2d_plot_settings; + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <array> +#include <vector> +#include <utility> +using std::pair; +#include <map> +using std::map; +#include <set> +using std::multiset; +#include <limits> +using std::numeric_limits; +#include <cmath> // + + /*! + */ +int main() +{ + try + { + std::cout << "Lambert W graph example." << std::endl; + +//[lambert_w_graph_1 +//] [/lambert_w_graph_1] + { + std::map<const double, double> wm1s; // Lambert W-1 branch values. + std::map<const double, double> w0s; // Lambert W0 branch values. + + std::cout.precision(std::numeric_limits<double>::max_digits10); + + int count = 0; + for (double z = -0.36787944117144232159552377016146086744581113103176804; z < 2.8; z += 0.001) + { + double w0 = lambert_w0(z); + w0s[z] = w0; + // std::cout << "z " << z << ", w = " << w0 << std::endl; + count++; + } + std::cout << "points " << count << std::endl; + + count = 0; + for (double z = -0.3678794411714423215955237701614608727; z < -0.001; z += 0.001) + { + double wm1 = lambert_wm1(z); + wm1s[z] = wm1; + count++; + } + std::cout << "points " << count << std::endl; + + svg_2d_plot data_plot; + data_plot.title("Lambert W function.") + .x_size(400) + .y_size(300) + .legend_on(true) + .legend_lines(true) + .x_label("z") + .y_label("W") + .x_range(-1, 3.) + .y_range(-4., +1.) + .x_major_interval(1.) + .y_major_interval(1.) + .x_major_grid_on(true) + .y_major_grid_on(true) + //.x_values_on(true) + //.y_values_on(true) + .y_values_rotation(horizontal) + //.plot_window_on(true) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + //.background_border_color(black); + ; + data_plot.plot(w0s, "W0 branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plot.plot(wm1s, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plot.write("./lambert_w_graph"); + + show_2d_plot_settings(data_plot); // For plot diagnosis only. + + } // small z Lambert W + + { // bigger argument z Lambert W + + std::map<const double, double> w0s_big; // Lambert W0 branch values for large z and W. + std::map<const double, double> wm1s_big; // Lambert W-1 branch values for small z and large -W. + int count = 0; + for (double z = -0.3678794411714423215955237701614608727; z < 10000.; z += 50.) + { + double w0 = lambert_w0(z); + w0s_big[z] = w0; + count++; + } + std::cout << "points " << count << std::endl; + + count = 0; + for (double z = -0.3678794411714423215955237701614608727; z < -0.001; z += 0.001) + { + double wm1 = lambert_wm1(z); + wm1s_big[z] = wm1; + count++; + } + std::cout << "Lambert W0 large z argument points = " << count << std::endl; + + svg_2d_plot data_plot2; + data_plot2.title("Lambert W0 function for larger z.") + .x_size(400) + .y_size(300) + .legend_on(false) + .x_label("z") + .y_label("W") + //.x_label_on(true) + //.y_label_on(true) + //.xy_values_on(false) + .x_range(-1, 10000.) + .y_range(-1., +8.) + .x_major_interval(2000.) + .y_major_interval(1.) + .x_major_grid_on(true) + .y_major_grid_on(true) + //.x_values_on(true) + //.y_values_on(true) + .y_values_rotation(horizontal) + //.plot_window_on(true) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + //.background_border_color(black); + ; + + data_plot2.plot(w0s_big, "W0 branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1); + // data_plot2.plot(wm1s_big, "W-1 branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1); + // This wouldn't show anything useful. + data_plot2.write("./lambert_w_graph_big_w"); + } // Big argument z Lambert W + + { // Lambert W0 Derivative plots + + // std::map<const double, double> wm1ps; // Lambert W-1 prime branch values. + std::map<const double, double> w0ps; // Lambert W0 prime branch values. + + std::cout.precision(std::numeric_limits<double>::max_digits10); + + int count = 0; + for (double z = -0.36; z < 3.; z += 0.001) + { + double w0p = lambert_w0_prime(z); + w0ps[z] = w0p; + // std::cout << "z " << z << ", w0 = " << w0 << std::endl; + count++; + } + std::cout << "points " << count << std::endl; + + //count = 0; + //for (double z = -0.36; z < -0.1; z += 0.001) + //{ + // double wm1p = lambert_wm1_prime(z); + // std::cout << "z " << z << ", w-1 = " << wm1p << std::endl; + // wm1ps[z] = wm1p; + // count++; + //} + //std::cout << "points " << count << std::endl; + + svg_2d_plot data_plotp; + data_plotp.title("Lambert W0 prime function.") + .x_size(400) + .y_size(300) + .legend_on(false) + .x_label("z") + .y_label("W0'") + .x_range(-0.3, +1.) + .y_range(0., +5.) + .x_major_interval(0.2) + .y_major_interval(2.) + .x_major_grid_on(true) + .y_major_grid_on(true) + .y_values_rotation(horizontal) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + ; + + // derivative of N[productlog(0, x), 55] at x=0 to 10 + // Plot[D[N[ProductLog[0, x], 55], x], {x, 0, 10}] + // Plot[ProductLog[x]/(x + x ProductLog[x]), {x, 0, 10}] + data_plotp.plot(w0ps, "W0 prime branch").line_color(red).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plotp.write("./lambert_w0_prime_graph"); + } // Lambert W0 Derivative plots + + { // Lambert Wm1 Derivative plots + + std::map<const double, double> wm1ps; // Lambert W-1 prime branch values. + + std::cout.precision(std::numeric_limits<double>::max_digits10); + + int count = 0; + for (double z = -0.3678; z < -0.00001; z += 0.001) + { + double wm1p = lambert_wm1_prime(z); + // std::cout << "z " << z << ", w-1 = " << wm1p << std::endl; + wm1ps[z] = wm1p; + count++; + } + std::cout << "Lambert W-1 prime points = " << count << std::endl; + + svg_2d_plot data_plotp; + data_plotp.title("Lambert W-1 prime function.") + .x_size(400) + .y_size(300) + .legend_on(false) + .x_label("z") + .y_label("W-1'") + .x_range(-0.4, +0.01) + .x_major_interval(0.1) + .y_range(-20., -5.) + .y_major_interval(5.) + .x_major_grid_on(true) + .y_major_grid_on(true) + .y_values_rotation(horizontal) + .x_values_precision(3) + .y_values_precision(3) + .coord_precision(4) // Needed to avoid stepping on curves. + .copyright_holder("Paul A. Bristow") + .copyright_date("2018") + ; + + // derivative of N[productlog(0, x), 55] at x=0 to 10 + // Plot[D[N[ProductLog[0, x], 55], x], {x, 0, 10}] + // Plot[ProductLog[x]/(x + x ProductLog[x]), {x, 0, 10}] + data_plotp.plot(wm1ps, "W-1 prime branch").line_color(blue).shape(none).line_on(true).bezier_on(false).line_width(1); + data_plotp.write("./lambert_wm1_prime_graph"); + } // Lambert W-1 prime graph + } // try + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } +} // int main() + + /* + + //[lambert_w_graph_1_output + + //] [/lambert_w_graph_1_output] + */ + +#endif // BOOST_MATH_STANDALONE diff --git a/src/boost/libs/math/example/lambert_w_precision_example.cpp b/src/boost/libs/math/example/lambert_w_precision_example.cpp new file mode 100644 index 000000000..e95f3b193 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_precision_example.cpp @@ -0,0 +1,263 @@ +// Copyright Paul A. Bristow 2016, 2018. + +// 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). + +//! Lambert W examples of controlling precision + +// #define BOOST_MATH_INSTRUMENT_LAMBERT_W // #define only for (much) diagnostic output. + +#include <boost/config.hpp> // for BOOST_PLATFORM, BOOST_COMPILER, BOOST_STDLIB ... +#include <boost/version.hpp> // for BOOST_MSVC versions. +#include <boost/cstdint.hpp> +#include <boost/exception/exception.hpp> // boost::exception +#include <boost/math/constants/constants.hpp> // For exp_minus_one == 3.67879441171442321595523770161460867e-01. +#include <boost/math/policies/policy.hpp> +#include <boost/math/special_functions/next.hpp> // for float_distance. +#include <boost/math/special_functions/relative_difference.hpp> // for relative and epsilon difference. + +// Built-in/fundamental GCC float128 or Intel Quad 128-bit type, if available. +#ifdef BOOST_HAS_FLOAT128 +#include <boost/multiprecision/float128.hpp> // Not available for MSVC. +// sets BOOST_MP_USE_FLOAT128 for GCC +using boost::multiprecision::float128; +#endif //# NOT _MSC_VER + +#include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_50 +using boost::multiprecision::cpp_dec_float_50; // 50 decimal digits type. +using boost::multiprecision::cpp_dec_float_100; // 100 decimal digits type. + +#include <boost/multiprecision/cpp_bin_float.hpp> +using boost::multiprecision::cpp_bin_float_double_extended; +using boost::multiprecision::cpp_bin_float_double; +using boost::multiprecision::cpp_bin_float_quad; +// For lambert_w function. +#include <boost/math/special_functions/lambert_w.hpp> +// using boost::math::lambert_w0; +// using boost::math::lambert_wm1; + +#include <iostream> +#include <exception> +#include <stdexcept> +#include <string> +#include <limits> // For std::numeric_limits. + +int main() +{ + try + { + std::cout << "Lambert W examples of precision control." << std::endl; + std::cout.precision(std::numeric_limits<double>::max_digits10); + std::cout << std::showpoint << std::endl; // Show any trailing zeros. + + using boost::math::constants::exp_minus_one; + + using boost::math::lambert_w0; + using boost::math::lambert_wm1; + + // Error handling policy examples. + using namespace boost::math::policies; + using boost::math::policies::make_policy; + using boost::math::policies::policy; + using boost::math::policies::evaluation_error; + using boost::math::policies::domain_error; + using boost::math::policies::overflow_error; + using boost::math::policies::throw_on_error; + +//[lambert_w_precision_reference_w + + using boost::multiprecision::cpp_bin_float_50; + using boost::math::float_distance; + + cpp_bin_float_50 z("10."); // Note use a decimal digit string, not a double 10. + cpp_bin_float_50 r; + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); + + r = lambert_w0(z); // Default policy. + std::cout << "lambert_w0(z) cpp_bin_float_50 = " << r << std::endl; + //lambert_w0(z) cpp_bin_float_50 = 1.7455280027406993830743012648753899115352881290809 + // [N[productlog[10], 50]] == 1.7455280027406993830743012648753899115352881290809 + std::cout.precision(std::numeric_limits<double>::max_digits10); + std::cout << "lambert_w0(z) static_cast from cpp_bin_float_50 = " + << static_cast<double>(r) << std::endl; + // double lambert_w0(z) static_cast from cpp_bin_float_50 = 1.7455280027406994 + // [N[productlog[10], 17]] == 1.7455280027406994 + std::cout << "bits different from Wolfram = " + << static_cast<int>(float_distance(static_cast<double>(r), 1.7455280027406994)) + << std::endl; // 0 + + +//] [/lambert_w_precision_reference_w] + +//[lambert_w_precision_0 + std::cout.precision(std::numeric_limits<float>::max_digits10); // Show all potentially significant decimal digits, + std::cout << std::showpoint << std::endl; // and show any significant trailing zeros too. + + float x = 10.; + std::cout << "Lambert W (" << x << ") = " << lambert_w0(x) << std::endl; +//] [/lambert_w_precision_0] + +/* +//[lambert_w_precision_output_0 +Lambert W (10.0000000) = 1.74552800 +//] [/lambert_w_precision_output_0] +*/ + { // Lambert W0 Halley step example +//[lambert_w_precision_1 + using boost::math::lambert_w_detail::lambert_w_halley_step; + using boost::math::epsilon_difference; + using boost::math::relative_difference; + + std::cout << std::showpoint << std::endl; // and show any significant trailing zeros too. + std::cout.precision(std::numeric_limits<double>::max_digits10); // 17 decimal digits for double. + + cpp_bin_float_50 z50("1.23"); // Note: use a decimal digit string, not a double 1.23! + double z = static_cast<double>(z50); + cpp_bin_float_50 w50; + w50 = lambert_w0(z50); + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::max_digits10); // 50 decimal digits. + std::cout << "Reference Lambert W (" << z << ") =\n " + << w50 << std::endl; + std::cout.precision(std::numeric_limits<double>::max_digits10); // 17 decimal digits for double. + double wr = static_cast<double>(w50); + std::cout << "Reference Lambert W (" << z << ") = " << wr << std::endl; + + double w = lambert_w0(z); + std::cout << "Rat/poly Lambert W (" << z << ") = " << lambert_w0(z) << std::endl; + // Add a Halley step to the value obtained from rational polynomial approximation. + double ww = lambert_w_halley_step(lambert_w0(z), z); + std::cout << "Halley Step Lambert W (" << z << ") = " << lambert_w_halley_step(lambert_w0(z), z) << std::endl; + + std::cout << "absolute difference from Halley step = " << w - ww << std::endl; + std::cout << "relative difference from Halley step = " << relative_difference(w, ww) << std::endl; + std::cout << "epsilon difference from Halley step = " << epsilon_difference(w, ww) << std::endl; + std::cout << "epsilon for float = " << std::numeric_limits<double>::epsilon() << std::endl; + std::cout << "bits different from Halley step = " << static_cast<int>(float_distance(w, ww)) << std::endl; +//] [/lambert_w_precision_1] + + +/* +//[lambert_w_precision_output_1 + Reference Lambert W (1.2299999999999999822364316059974953532218933105468750) = + 0.64520356959320237759035605255334853830173300262666480 + Reference Lambert W (1.2300000000000000) = 0.64520356959320235 + Rat/poly Lambert W (1.2300000000000000) = 0.64520356959320224 + Halley Step Lambert W (1.2300000000000000) = 0.64520356959320235 + absolute difference from Halley step = -1.1102230246251565e-16 + relative difference from Halley step = 1.7207329236029286e-16 + epsilon difference from Halley step = 0.77494921535422934 + epsilon for float = 2.2204460492503131e-16 + bits different from Halley step = 1 +//] [/lambert_w_precision_output_1] +*/ + + } // Lambert W0 Halley step example + + { // Lambert W-1 Halley step example + //[lambert_w_precision_2 + using boost::math::lambert_w_detail::lambert_w_halley_step; + using boost::math::epsilon_difference; + using boost::math::relative_difference; + + std::cout << std::showpoint << std::endl; // and show any significant trailing zeros too. + std::cout.precision(std::numeric_limits<double>::max_digits10); // 17 decimal digits for double. + + cpp_bin_float_50 z50("-0.123"); // Note: use a decimal digit string, not a double -1.234! + double z = static_cast<double>(z50); + cpp_bin_float_50 wm1_50; + wm1_50 = lambert_wm1(z50); + std::cout.precision(std::numeric_limits<cpp_bin_float_50>::max_digits10); // 50 decimal digits. + std::cout << "Reference Lambert W-1 (" << z << ") =\n " + << wm1_50 << std::endl; + std::cout.precision(std::numeric_limits<double>::max_digits10); // 17 decimal digits for double. + double wr = static_cast<double>(wm1_50); + std::cout << "Reference Lambert W-1 (" << z << ") = " << wr << std::endl; + + double w = lambert_wm1(z); + std::cout << "Rat/poly Lambert W-1 (" << z << ") = " << lambert_wm1(z) << std::endl; + // Add a Halley step to the value obtained from rational polynomial approximation. + double ww = lambert_w_halley_step(lambert_wm1(z), z); + std::cout << "Halley Step Lambert W (" << z << ") = " << lambert_w_halley_step(lambert_wm1(z), z) << std::endl; + + std::cout << "absolute difference from Halley step = " << w - ww << std::endl; + std::cout << "relative difference from Halley step = " << relative_difference(w, ww) << std::endl; + std::cout << "epsilon difference from Halley step = " << epsilon_difference(w, ww) << std::endl; + std::cout << "epsilon for float = " << std::numeric_limits<double>::epsilon() << std::endl; + std::cout << "bits different from Halley step = " << static_cast<int>(float_distance(w, ww)) << std::endl; + //] [/lambert_w_precision_2] + } + /* + //[lambert_w_precision_output_2 + Reference Lambert W-1 (-0.12299999999999999822364316059974953532218933105468750) = + -3.2849102557740360179084675531714935199110302996513384 + Reference Lambert W-1 (-0.12300000000000000) = -3.2849102557740362 + Rat/poly Lambert W-1 (-0.12300000000000000) = -3.2849102557740357 + Halley Step Lambert W (-0.12300000000000000) = -3.2849102557740362 + absolute difference from Halley step = 4.4408920985006262e-16 + relative difference from Halley step = 1.3519066740696092e-16 + epsilon difference from Halley step = 0.60884463935795785 + epsilon for float = 2.2204460492503131e-16 + bits different from Halley step = -1 + //] [/lambert_w_precision_output_2] + */ + + + + // Similar example using cpp_bin_float_quad (128-bit floating-point types). + + cpp_bin_float_quad zq = 10.; + std::cout << "\nTest evaluation of cpp_bin_float_quad Lambert W(" << zq << ")" + << std::endl; + std::cout << std::setprecision(3) << "std::numeric_limits<cpp_bin_float_quad>::digits = " << std::numeric_limits<cpp_bin_float_quad>::digits << std::endl; + std::cout << std::setprecision(3) << "std::numeric_limits<cpp_bin_float_quad>::epsilon() = " << std::numeric_limits<cpp_bin_float_quad>::epsilon() << std::endl; + std::cout << std::setprecision(3) << "std::numeric_limits<cpp_bin_float_quad>::max_digits10 = " << std::numeric_limits<cpp_bin_float_quad>::max_digits10 << std::endl; + std::cout << std::setprecision(3) << "std::numeric_limits<cpp_bin_float_quad>::digits10 = " << std::numeric_limits<cpp_bin_float_quad>::digits10 << std::endl; + std::cout.precision(std::numeric_limits<cpp_bin_float_quad>::max_digits10); + // All are same precision because double precision first approximation used before Halley. + + /* + + */ + + { // Reference value for lambert_w0(10) + cpp_dec_float_50 z("10"); + cpp_dec_float_50 r; + std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); + + r = lambert_w0(z); // Default policy. + std::cout << "lambert_w0(z) cpp_dec_float_50 = " << r << std::endl; // 0.56714329040978387299996866221035554975381578718651 + std::cout.precision(std::numeric_limits<cpp_bin_float_quad>::max_digits10); + + std::cout << "lambert_w0(z) cpp_dec_float_50 cast to quad (max_digits10(" << std::numeric_limits<cpp_bin_float_quad>::max_digits10 << + " ) = " << static_cast<cpp_bin_float_quad>(r) << std::endl; // 1.7455280027406993830743012648753899115352881290809 + std::cout.precision(std::numeric_limits<cpp_bin_float_quad>::digits10); // 1.745528002740699383074301264875389837 + std::cout << "lambert_w0(z) cpp_dec_float_50 cast to quad (digits10(" << std::numeric_limits<cpp_bin_float_quad>::digits10 << + " ) = " << static_cast<cpp_bin_float_quad>(r) << std::endl; // 1.74552800274069938307430126487539 + std::cout.precision(std::numeric_limits<cpp_bin_float_quad>::digits10 + 1); // + + std::cout << "lambert_w0(z) cpp_dec_float_50 cast to quad (digits10(" << std::numeric_limits<cpp_bin_float_quad>::digits10 << + " ) = " << static_cast<cpp_bin_float_quad>(r) << std::endl; // 1.74552800274069938307430126487539 + + // [N[productlog[10], 50]] == 1.7455280027406993830743012648753899115352881290809 + + // [N[productlog[10], 37]] == 1.745528002740699383074301264875389912 + // [N[productlog[10], 34]] == 1.745528002740699383074301264875390 + // [N[productlog[10], 33]] == 1.74552800274069938307430126487539 + + // lambert_w0(z) cpp_dec_float_50 cast to quad = 1.745528002740699383074301264875389837 + + // lambert_w0(z) cpp_dec_float_50 = 1.7455280027406993830743012648753899115352881290809 + // lambert_w0(z) cpp_dec_float_50 cast to quad = 1.745528002740699383074301264875389837 + // lambert_w0(z) cpp_dec_float_50 cast to quad = 1.74552800274069938307430126487539 + } + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } +} // int main() + + + + diff --git a/src/boost/libs/math/example/lambert_w_simple_examples.cpp b/src/boost/libs/math/example/lambert_w_simple_examples.cpp new file mode 100644 index 000000000..3c422e062 --- /dev/null +++ b/src/boost/libs/math/example/lambert_w_simple_examples.cpp @@ -0,0 +1,251 @@ +// Copyright Paul A. Bristow 2016, 2017. + +// 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). + +// Build and run a simple examples of Lambert W function. + +// Some macros that will show some(or much) diagnostic values if #defined. +//#define-able macros +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W0 // W0 branch diagnostics. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_Wm1 // W1 branch diagnostics. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W_HALLEY // Halley refinement diagnostics. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W_SCHROEDER // Schroeder refinement diagnostics. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W_TERMS // Number of terms used for near-singularity series. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W0_NOT_BUILTIN // higher than built-in precision types approximation and refinement. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W_SINGULARITY_SERIES // Show evaluation of series near branch singularity. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W_SMALL_Z_SERIES_ITERATIONS // Show evaluation of series for small z. +//#define BOOST_MATH_INSTRUMENT_LAMBERT_W0_LOOKUP // Show results from lookup table. + +#include <boost/config.hpp> // for BOOST_PLATFORM, BOOST_COMPILER, BOOST_STDLIB ... +#include <boost/version.hpp> // for BOOST_MSVC versions. +#include <boost/cstdint.hpp> +#include <boost/exception/exception.hpp> // boost::exception +#include <boost/math/constants/constants.hpp> // For exp_minus_one == 3.67879441171442321595523770161460867e-01. +#include <boost/math/policies/policy.hpp> + +#include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_50 +using boost::multiprecision::cpp_dec_float_50; // 50 decimal digits type. +using boost::multiprecision::cpp_dec_float_100; // 100 decimal digits type. +using boost::multiprecision::backends::cpp_dec_float; +using boost::multiprecision::number; +typedef number<cpp_dec_float<1000> > cpp_dec_float_1000; // 1000 decimal digit types + +#include <boost/multiprecision/cpp_bin_float.hpp> +using boost::multiprecision::cpp_bin_float_double; // == double +using boost::multiprecision::cpp_bin_float_double_extended; // 80-bit long double emulation. +using boost::multiprecision::cpp_bin_float_quad; // 128-bit quad precision. + +//[lambert_w_simple_examples_includes +#include <boost/math/special_functions/lambert_w.hpp> // For lambert_w function. + +using boost::math::lambert_w0; +using boost::math::lambert_wm1; +//] //[/lambert_w_simple_examples_includes] + +#include <iostream> +// using std::cout; +// using std::endl; +#include <exception> +#include <stdexcept> +#include <string> +#include <limits> // For std::numeric_limits. + +//! Show value of z to the full possibly-significant max_digits10 precision of type T. +template<typename T> +void show_value(T z) +{ + std::streamsize precision = std::cout.precision(std::numeric_limits<T>::max_digits10); // Save. + std::cout.precision(std::numeric_limits<T>::max_digits10); // Show all possibly significant digits. + std::ios::fmtflags flags(std::cout.flags()); + std::cout.setf(std::ios_base::showpoint); // Include any trailing zeros. + std::cout << z; + // Restore: + std::cout.precision(precision); + std::cout.flags(flags); +} // template<typename T> void show_value(T z) + +int main() +{ + try + { + std::cout << "Lambert W simple examples." << std::endl; + + using boost::math::constants::exp_minus_one; //-1/e, the branch point, a singularity ~= -0.367879. + + // using statements needed for changing error handling policy. + using boost::math::policies::policy; + using boost::math::policies::make_policy; + using boost::math::policies::evaluation_error; + using boost::math::policies::domain_error; + using boost::math::policies::overflow_error; + using boost::math::policies::ignore_error; + using boost::math::policies::throw_on_error; + + { +//[lambert_w_simple_examples_0 + std::cout.precision(std::numeric_limits<double>::max_digits10); + // Show all potentially significant decimal digits, + std::cout << std::showpoint << std::endl; + // and show significant trailing zeros too. + + double z = 10.; + double r = lambert_w0(z); // Default policy for double. + std::cout << "lambert_w0(z) = " << r << std::endl; + // lambert_w0(z) = 1.7455280027406994 +//] [/lambert_w_simple_examples_0] + } + { + // Other floating-point types can be used too, here float. + // It is convenient to use a function like `show_value` + // to display all potentially significant decimal digits + // for the type, including any significant trailing zeros. + //[lambert_w_simple_examples_1 + float z = 10.F; + float r; + r = lambert_w0(z); // Default policy digits10 = 7, digits2 = 24 + std::cout << "lambert_w0("; + show_value(z); + std::cout << ") = "; + show_value(r); + std::cout << std::endl; // lambert_w0(10.0000000) = 1.74552798 + //] //[/lambert_w_simple_examples_1] + } + { + // Example of an integer argument to lambert_w, + // showing that an integer is correctly promoted to a double. +//[lambert_w_simple_examples_2 + std::cout.precision(std::numeric_limits<double>::max_digits10); + double r = lambert_w0(10); // Pass an int argument "10" that should be promoted to double argument. + std::cout << "lambert_w0(10) = " << r << std::endl; // lambert_w0(10) = 1.7455280027406994 + double rp = lambert_w0(10); + std::cout << "lambert_w0(10) = " << rp << std::endl; + // lambert_w0(10) = 1.7455280027406994 + auto rr = lambert_w0(10); // C++11 needed. + std::cout << "lambert_w0(10) = " << rr << std::endl; + // lambert_w0(10) = 1.7455280027406994 too, showing that rr has been promoted to double. +//] //[/lambert_w_simple_examples_2] + } + { + // Using multiprecision types to get much higher precision is painless. + //[lambert_w_simple_examples_3 + cpp_dec_float_50 z("10"); + // Note construction using a decimal digit string "10", + // NOT a floating-point double literal 10. + cpp_dec_float_50 r; + r = lambert_w0(z); + std::cout << "lambert_w0("; show_value(z); std::cout << ") = "; + show_value(r); + std::cout << std::endl; + // lambert_w0(10.000000000000000000000000000000000000000000000000000000000000000000000000000000) = + // 1.7455280027406993830743012648753899115352881290809413313533156980404446940000000 + //] //[/lambert_w_simple_examples_3] + } + // Using multiprecision types to get multiprecision precision wrong! + { + //[lambert_w_simple_examples_4 + cpp_dec_float_50 z(0.7777777777777777777777777777777777777777777777777777777777777777777777777); + // Compiler evaluates the nearest double-precision binary representation, + // from the max_digits10 of the floating_point literal double 0.7777777777777777777777777777..., + // so any extra digits in the multiprecision type + // beyond max_digits10 (usually 17) are random and meaningless. + cpp_dec_float_50 r; + r = lambert_w0(z); + std::cout << "lambert_w0("; + show_value(z); + std::cout << ") = "; show_value(r); + std::cout << std::endl; + // lambert_w0(0.77777777777777779011358916250173933804035186767578125000000000000000000000000000) + // = 0.48086152073210493501934682309060873341910109230469724725005039758139532631901386 + //] //[/lambert_w_simple_examples_4] + } + { + //[lambert_w_simple_examples_4a + cpp_dec_float_50 z(0.9); // Construct from floating_point literal double 0.9. + cpp_dec_float_50 r; + r = lambert_w0(0.9); + std::cout << "lambert_w0("; + show_value(z); + std::cout << ") = "; show_value(r); + std::cout << std::endl; + // lambert_w0(0.90000000000000002220446049250313080847263336181640625000000000000000000000000000) + // = 0.52983296563343440510607251781038939952850341796875000000000000000000000000000000 + std::cout << "lambert_w0(0.9) = " << lambert_w0(static_cast<double>(0.9)) + // lambert_w0(0.9) + // = 0.52983296563343441 + << std::endl; + //] //[/lambert_w_simple_examples_4a] + } + { + // Using multiprecision types to get multiprecision precision right! + //[lambert_w_simple_examples_4b + cpp_dec_float_50 z("0.9"); // Construct from decimal digit string. + cpp_dec_float_50 r; + r = lambert_w0(z); + std::cout << "lambert_w0("; + show_value(z); + std::cout << ") = "; show_value(r); + std::cout << std::endl; + // 0.90000000000000000000000000000000000000000000000000000000000000000000000000000000) + // = 0.52983296563343441213336643954546304857788132269804249284012528304239956413801252 + //] //[/lambert_w_simple_examples_4b] + } + // Getting extreme precision (1000 decimal digits) Lambert W values. + { + std::cout.precision(std::numeric_limits<cpp_dec_float_1000>::digits10); + cpp_dec_float_1000 z("2.0"); + cpp_dec_float_1000 r; + r = lambert_w0(z); + std::cout << "lambert_w0(z) = " << r << std::endl; + // 0.8526055020137254913464724146953174668984533001514035087721073946525150656742630448965773783502494847334503972691804119834761668851953598826198984364998343940330324849743119327028383008883133161249045727544669202220292076639777316648311871183719040610274221013237163543451621208284315007250267190731048119566857455987975973474411544571619699938899354169616378479326962044241495398851839432070255805880208619490399218130868317114428351234208216131218024303904457925834743326836272959669122797896855064630871955955318383064292191644322931561534814178034773896739684452724587331245831001449498844495771266728242975586931792421997636537572767708722190588748148949667744956650966402600446780664924889043543203483210769017254907808218556111831854276511280553252641907484685164978750601216344998778097446525021666473925144772131644151718261199915247932015387685261438125313159125475113124470774926288823525823567568542843625471594347837868505309329628014463491611881381186810879712667681285740515197493390563 + // Wolfram alpha command N[productlog[0, 2.0],1000] gives the identical result: + // 0.8526055020137254913464724146953174668984533001514035087721073946525150656742630448965773783502494847334503972691804119834761668851953598826198984364998343940330324849743119327028383008883133161249045727544669202220292076639777316648311871183719040610274221013237163543451621208284315007250267190731048119566857455987975973474411544571619699938899354169616378479326962044241495398851839432070255805880208619490399218130868317114428351234208216131218024303904457925834743326836272959669122797896855064630871955955318383064292191644322931561534814178034773896739684452724587331245831001449498844495771266728242975586931792421997636537572767708722190588748148949667744956650966402600446780664924889043543203483210769017254907808218556111831854276511280553252641907484685164978750601216344998778097446525021666473925144772131644151718261199915247932015387685261438125313159125475113124470774926288823525823567568542843625471594347837868505309329628014463491611881381186810879712667681285740515197493390563 + } + { +//[lambert_w_simple_examples_error_policies + // Define an error handling policy: + typedef policy< + domain_error<throw_on_error>, + overflow_error<ignore_error> // possibly unwise? + > my_throw_policy; + + std::cout.precision(std::numeric_limits<double>::max_digits10); + // Show all potentially significant decimal digits, + std::cout << std::showpoint << std::endl; + // and show significant trailing zeros too. + double z = +1; + std::cout << "Lambert W (" << z << ") = " << lambert_w0(z) << std::endl; + // Lambert W (1.0000000000000000) = 0.56714329040978384 + std::cout << "\nLambert W (" << z << ", my_throw_policy()) = " + << lambert_w0(z, my_throw_policy()) << std::endl; + // Lambert W (1.0000000000000000, my_throw_policy()) = 0.56714329040978384 + //] //[/lambert_w_simple_example_error_policies] + } + { + // Show error reporting from passing a value to lambert_wm1 that is out of range, + // (and probably was meant to be passed to lambert_0 instead). +//[lambert_w_simple_examples_out_of_range + double z = +1.; + double r = lambert_wm1(z); + std::cout << "lambert_wm1(+1.) = " << r << std::endl; + //] [/lambert_w_simple_examples_out_of_range] + // Error in function boost::math::lambert_wm1<RealType>(<RealType>): + // Argument z = 1 is out of range (z <= 0) for Lambert W-1 branch! (Try Lambert W0 branch?) + } + } + catch (std::exception& ex) + { + std::cout << ex.what() << std::endl; + } +} // int main() + + /* + + Output: +//[lambert_w_simple_examples_error_message_1 +Error in function boost::math::lambert_wm1<RealType>(<RealType>): +Argument z = 1 is out of range (z <= 0) for Lambert W-1 branch! (Try Lambert W0 branch?) +//] [/lambert_w_simple_examples_error_message_1] + + */ diff --git a/src/boost/libs/math/example/laplace_example.cpp b/src/boost/libs/math/example/laplace_example.cpp new file mode 100644 index 000000000..ed99dba21 --- /dev/null +++ b/src/boost/libs/math/example/laplace_example.cpp @@ -0,0 +1,169 @@ +// laplace_example.cpp + +// Copyright Paul A. Bristow 2008, 2010. + +// 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) + +// Example of using laplace (& comparing with normal) distribution. + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[laplace_example1 +/*` +First we need some includes to access the laplace & normal distributions +(and some std output of course). +*/ + +#include <boost/math/distributions/laplace.hpp> // for laplace_distribution + using boost::math::laplace; // typedef provides default type is double. +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. + +#include <iostream> + using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; + +int main() +{ + cout << "Example: Laplace distribution." << endl; + + try + { + { // Traditional tables and values. +/*`Let's start by printing some traditional tables. +*/ + double step = 1.; // in z + double range = 4; // min and max z = -range to +range. + //int precision = 17; // traditional tables are only computed to much lower precision. + int precision = 4; // traditional table at much lower precision. + int width = 10; // for use with setw. + + // Construct standard laplace & normal distributions l & s + normal s; // (default location or mean = zero, and scale or standard deviation = unity) + cout << "Standard normal distribution, mean or location = "<< s.location() + << ", standard deviation or scale = " << s.scale() << endl; + laplace l; // (default mean = zero, and standard deviation = unity) + cout << "Laplace normal distribution, location = "<< l.location() + << ", scale = " << l.scale() << endl; + +/*` First the probability distribution function (pdf). +*/ + cout << "Probability distribution function values" << endl; + cout << " z PDF normal laplace (difference)" << endl; + cout.precision(5); + for (double z = -range; z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(width) << pdf(s, z) << " " + << setprecision(precision) << setw(width) << pdf(l, z)<< " (" + << setprecision(precision) << setw(width) << pdf(l, z) - pdf(s, z) // difference. + << ")" << endl; + } + cout.precision(6); // default +/*`Notice how the laplace is less at z = 1 , but has 'fatter' tails at 2 and 3. + + And the area under the normal curve from -[infin] up to z, + the cumulative distribution function (cdf). +*/ + // For a standard distribution + cout << "Standard location = "<< s.location() + << ", scale = " << s.scale() << endl; + cout << "Integral (area under the curve) from - infinity up to z " << endl; + cout << " z CDF normal laplace (difference)" << endl; + for (double z = -range; z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(width) << cdf(s, z) << " " + << setprecision(precision) << setw(width) << cdf(l, z) << " (" + << setprecision(precision) << setw(width) << cdf(l, z) - cdf(s, z) // difference. + << ")" << endl; + } + cout.precision(6); // default + +/*` +Pretty-printing a traditional 2-dimensional table is left as an exercise for the student, +but why bother now that the Boost Math Toolkit lets you write +*/ + double z = 2.; + cout << "Area for gaussian z = " << z << " is " << cdf(s, z) << endl; // to get the area for z. + cout << "Area for laplace z = " << z << " is " << cdf(l, z) << endl; // +/*` +Correspondingly, we can obtain the traditional 'critical' values for significance levels. +For the 95% confidence level, the significance level usually called alpha, +is 0.05 = 1 - 0.95 (for a one-sided test), so we can write +*/ + cout << "95% of gaussian area has a z below " << quantile(s, 0.95) << endl; + cout << "95% of laplace area has a z below " << quantile(l, 0.95) << endl; + // 95% of area has a z below 1.64485 + // 95% of laplace area has a z below 2.30259 +/*`and a two-sided test (a comparison between two levels, rather than a one-sided test) + +*/ + cout << "95% of gaussian area has a z between " << quantile(s, 0.975) + << " and " << -quantile(s, 0.975) << endl; + cout << "95% of laplace area has a z between " << quantile(l, 0.975) + << " and " << -quantile(l, 0.975) << endl; + // 95% of area has a z between 1.95996 and -1.95996 + // 95% of laplace area has a z between 2.99573 and -2.99573 +/*`Notice how much wider z has to be to enclose 95% of the area. +*/ + } +//] [/[laplace_example1] + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +/* + +Output is: + +Example: Laplace distribution. +Standard normal distribution, mean or location = 0, standard deviation or scale = 1 +Laplace normal distribution, location = 0, scale = 1 +Probability distribution function values + z PDF normal laplace (difference) +-4 0.0001338 0.009158 (0.009024 ) +-3 0.004432 0.02489 (0.02046 ) +-2 0.05399 0.06767 (0.01368 ) +-1 0.242 0.1839 (-0.05803 ) +0 0.3989 0.5 (0.1011 ) +1 0.242 0.1839 (-0.05803 ) +2 0.05399 0.06767 (0.01368 ) +3 0.004432 0.02489 (0.02046 ) +4 0.0001338 0.009158 (0.009024 ) +Standard location = 0, scale = 1 +Integral (area under the curve) from - infinity up to z + z CDF normal laplace (difference) +-4 3.167e-005 0.009158 (0.009126 ) +-3 0.00135 0.02489 (0.02354 ) +-2 0.02275 0.06767 (0.04492 ) +-1 0.1587 0.1839 (0.02528 ) +0 0.5 0.5 (0 ) +1 0.8413 0.8161 (-0.02528 ) +2 0.9772 0.9323 (-0.04492 ) +3 0.9987 0.9751 (-0.02354 ) +4 1 0.9908 (-0.009126 ) +Area for gaussian z = 2 is 0.97725 +Area for laplace z = 2 is 0.932332 +95% of gaussian area has a z below 1.64485 +95% of laplace area has a z below 2.30259 +95% of gaussian area has a z between 1.95996 and -1.95996 +95% of laplace area has a z between 2.99573 and -2.99573 + +*/ + diff --git a/src/boost/libs/math/example/legendre_stieltjes_example.cpp b/src/boost/libs/math/example/legendre_stieltjes_example.cpp new file mode 100644 index 000000000..00ceba277 --- /dev/null +++ b/src/boost/libs/math/example/legendre_stieltjes_example.cpp @@ -0,0 +1,110 @@ +// Copyright Nick Thompson 2017. +// 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) + +#include <iostream> +#include <string> +#include <boost/math/constants/constants.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/special_functions/legendre_stieltjes.hpp> + +using boost::math::legendre_p; +using boost::math::legendre_p_zeros; +using boost::math::legendre_p_prime; +using boost::math::legendre_stieltjes; +using boost::multiprecision::cpp_bin_float_quad; +using boost::multiprecision::cpp_bin_float_100; +using boost::multiprecision::cpp_dec_float_100; + +template<class Real> +void gauss_kronrod_rule(size_t order) +{ + std::cout << std::setprecision(std::numeric_limits<Real>::digits10); + std::cout << std::fixed; + auto gauss_nodes = boost::math::legendre_p_zeros<Real>(order); + auto E = legendre_stieltjes<Real>(order + 1); + std::vector<Real> gauss_weights(gauss_nodes.size(), std::numeric_limits<Real>::quiet_NaN()); + std::vector<Real> gauss_kronrod_weights(gauss_nodes.size(), std::numeric_limits<Real>::quiet_NaN()); + for (size_t i = 0; i < gauss_nodes.size(); ++i) + { + Real node = gauss_nodes[i]; + Real lp = legendre_p_prime<Real>(order, node); + gauss_weights[i] = 2/( (1-node*node)*lp*lp); + // P_n(x) = (2n)!/(2^n (n!)^2) pi_n(x), where pi_n is the monic Legendre polynomial. + gauss_kronrod_weights[i] = gauss_weights[i] + static_cast<Real>(2)/(static_cast<Real>(order+1)*legendre_p_prime(order, node)*E(node)); + } + + std::cout << "static const std::vector<Real> gauss_nodes {\n"; + for (auto const & node : gauss_nodes) + { + std::cout << " boost::lexical_cast<Real>(\"" << node << "\"),\n"; + } + std::cout << "};\n\n"; + + std::cout << "static const std::vector<Real> gauss_weights {\n"; + for (auto const & weight : gauss_weights) + { + std::cout << " boost::lexical_cast<Real>(\"" << weight << "\"),\n"; + } + std::cout << "};\n\n"; + + std::cout << "static const std::vector<Real> gauss_kronrod_weights {\n"; + for (auto const & weight : gauss_kronrod_weights) + { + std::cout << " boost::lexical_cast<Real>(\"" << weight << "\"),\n"; + } + std::cout << "};\n\n"; + + auto kronrod_nodes = E.zeros(); + std::vector<Real> kronrod_weights(kronrod_nodes.size()); + for (size_t i = 0; i < kronrod_weights.size(); ++i) + { + Real node = kronrod_nodes[i]; + kronrod_weights[i] = static_cast<Real>(2)/(static_cast<Real>(order+1)*legendre_p(order, node)*E.prime(node)); + } + + std::cout << "static const std::vector<Real> kronrod_nodes {\n"; + for (auto node : kronrod_nodes) + { + std::cout << " boost::lexical_cast<Real>(\"" << node << "\"),\n"; + } + std::cout << "};\n\n"; + + std::cout << "static const std::vector<Real> kronrod_weights {\n"; + for (auto const & weight : kronrod_weights) + { + std::cout << " boost::lexical_cast<Real>(\"" << weight << "\"),\n"; + } + std::cout << "};\n\n"; + +} + +int main() +{ + //std::cout << "Gauss-Kronrod 7-15 Rule:\n"; + //gauss_kronrod_rule<cpp_dec_float_100>(7); + + //std::cout << "\n\nGauss-Kronrod 10-21 Rule:\n"; + //gauss_kronrod_rule<cpp_dec_float_100>(10); + + std::cout << "\n\nGauss-Kronrod 15-31 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(15); + /* + std::cout << "\n\nGauss-Kronrod 20-41 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(20); + + std::cout << "\n\nGauss-Kronrod 25-51 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(25); + + std::cout << "\n\nGauss-Kronrod 30-61 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(30); + + std::cout << "\n\nGauss-Kronrod 35-71 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(35); + + std::cout << "\n\nGauss-Kronrod 40-81 Rule:\n"; + gauss_kronrod_rule<cpp_dec_float_100>(40);*/ +} diff --git a/src/boost/libs/math/example/lexical_cast_native.cpp b/src/boost/libs/math/example/lexical_cast_native.cpp new file mode 100644 index 000000000..6539074e7 --- /dev/null +++ b/src/boost/libs/math/example/lexical_cast_native.cpp @@ -0,0 +1,133 @@ +/** lexical_cast_nonfinite_facets.cpp +* +* Copyright (c) 2011 Paul A. Bristow +* +* 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) +* +* This very simple program illustrates how to use the +* `boost/math/nonfinite_num_facets.hpp' with lexical cast +* to obtain C99 representation of infinity and NaN. +* This example is from the original Floating Point Utilities contribution by Johan Rade. +* Floating Point Utility library has been accepted into Boost, +* but the utilities are incorporated into Boost.Math library. +* +\file + +\brief A very simple example of using lexical cast with +non_finite_num facet for C99 standard output of infinity and NaN. + +\detail This example shows how to create a C99 non-finite locale, +and imbue input and output streams with the non_finite_num put and get facets. +This allows lexical_cast output and input of infinity and NaN in a Standard portable way, +This permits 'loop-back' of output back into input (and portably across different system too). + +*/ + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_get; +using boost::math::nonfinite_num_put; + +#include <boost/lexical_cast.hpp> +using boost::lexical_cast; + +#include <iostream> +using std::cout; +using std::endl; +using std::cerr; + +#include <iomanip> +using std::setw; +using std::left; +using std::right; +using std::internal; + +#include <string> +using std::string; + +#include <sstream> +using std::istringstream; + +#include <limits> +using std::numeric_limits; + +#include <locale> +using std::locale; + +#include <boost/math/tools/assert.hpp> + +int main () +{ + std::cout << "lexical_cast example (NOT using finite_num_facet)." << std::endl; + + if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + + // Some tests that are expected to fail on some platforms. + // (But these tests are expected to pass using non_finite num_put and num_get facets). + + // Use the current 'native' default locale. + std::locale default_locale (std::locale::classic ()); // Note the current (default C) locale. + + // Create plus and minus infinity. + double plus_infinity = +std::numeric_limits<double>::infinity(); + double minus_infinity = -std::numeric_limits<double>::infinity(); + + // and create a NaN (NotANumber). + double NaN = +std::numeric_limits<double>::quiet_NaN (); + + // Output the nonfinite values using the current (default C) locale. + // The default representations differ from system to system, + // for example, using Microsoft compilers, 1.#INF, -1.#INF, and 1.#QNAN. + cout << "Using default locale" << endl; + cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl; + cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl; + cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl; + + // Checks below are expected to fail on some platforms! + + // Now try some 'round-tripping', 'reading' "inf" + double x = boost::lexical_cast<double>("inf"); + // and check we get a floating-point infinity. + BOOST_MATH_ASSERT(x == std::numeric_limits<double>::infinity()); + + // Check we can convert the other way from floating-point infinity, + string s = boost::lexical_cast<string>(numeric_limits<double>::infinity()); + // to a C99 string representation as "inf". + BOOST_MATH_ASSERT(s == "inf"); + + // Finally try full 'round-tripping' (in both directions): + BOOST_MATH_ASSERT(lexical_cast<double>(lexical_cast<string>(numeric_limits<double>::infinity())) + == numeric_limits<double>::infinity()); + BOOST_MATH_ASSERT(lexical_cast<string>(lexical_cast<double>("inf")) == "inf"); + + return 0; +} // int main() + +/* + +Output: + +from MSVC 10, fails (as expected) + + lexical_cast_native.vcxproj -> J:\Cpp\fp_facet\fp_facet\Debug\lexical_cast_native.exe + lexical_cast example (NOT using finite_num_facet). + Using default locale + +std::numeric_limits<double>::infinity() = 1.#INF + -std::numeric_limits<double>::infinity() = -1.#INF + +std::numeric_limits<double>::quiet_NaN () = 1.#QNAN +C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: The command ""J:\Cpp\fp_facet\fp_facet\Debug\lexical_cast_native.exe" +C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: :VCEnd" exited with code 3. + + +*/ diff --git a/src/boost/libs/math/example/lexical_cast_nonfinite_facets.cpp b/src/boost/libs/math/example/lexical_cast_nonfinite_facets.cpp new file mode 100644 index 000000000..97fbf6b08 --- /dev/null +++ b/src/boost/libs/math/example/lexical_cast_nonfinite_facets.cpp @@ -0,0 +1,133 @@ +/** lexical_cast_nonfinite_facets.cpp +* +* Copyright (c) 2011 Paul A. Bristow +* +* 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) +* +* This very simple program illustrates how to use the +* `boost/math/nonfinite_num_facets.hpp' with lexical cast +* to obtain C99 representation of infinity and NaN. +* This example is from the original Floating Point Utilities contribution by Johan Rade. +* Floating Point Utility library has been accepted into Boost, +* but the utilities are incorporated into Boost.Math library. +* +\file + +\brief A very simple example of using lexical cast with +non_finite_num facet for C99 standard output of infinity and NaN. + +\detail This example shows how to create a C99 non-finite locale, +and imbue input and output streams with the non_finite_num put and get facets. +This allows lexical_cast output and input of infinity and NaN in a Standard portable way, +This permits 'loop-back' of output back into input (and portably across different system too). + +See also lexical_cast_native.cpp which is expected to fail on many systems, +but might succeed if the default locale num_put and num_get facets +comply with C99 nonfinite input and output specification. + +*/ + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_get; +using boost::math::nonfinite_num_put; + +#include <boost/lexical_cast.hpp> +using boost::lexical_cast; + +#include <iostream> +using std::cout; +using std::endl; +using std::cerr; + +#include <iomanip> +using std::setw; +using std::left; +using std::right; +using std::internal; + +#include <string> +using std::string; + +#include <sstream> +using std::istringstream; + +#include <limits> +using std::numeric_limits; + +#include <locale> +using std::locale; + +#include <boost/math/tools/assert.hpp> + +int main () +{ + std::cout << "finite_num_facet with lexical_cast example." << std::endl; + + // Example of using non_finite num_put and num_get facets with lexical_cast. + //locale old_locale; + //locale tmp_locale(old_locale, new nonfinite_num_put<char>); + //// Create a new temporary output locale, and add the output nonfinite_num_put facet. + + //locale new_locale(tmp_locale, new nonfinite_num_get<char>); + // Create a new output locale (from the tmp locale), and add the input nonfinite_num_get facet. + + // Note that you can only add facets one at a time, + // unless you chain thus: + + std::locale new_locale(std::locale(std::locale(), + new boost::math::nonfinite_num_put<char>), + new boost::math::nonfinite_num_get<char>); + + locale::global(new_locale); // Newly constructed streams + // (including those streams inside lexical_cast) + // now use new_locale with nonfinite facets. + + // Output using the new locale. + cout << "Using C99_out_locale " << endl; + cout.imbue(new_locale); + // Necessary because cout already constructed using default C locale, + // and default facets for nonfinites. + + // Create plus and minus infinity. + double plus_infinity = +std::numeric_limits<double>::infinity(); + double minus_infinity = -std::numeric_limits<double>::infinity(); + + // and create a NaN (NotANumber) + double NaN = +std::numeric_limits<double>::quiet_NaN (); + cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl; + cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl; + cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl; + + // Now try some 'round-tripping', 'reading' "inf". + double x = boost::lexical_cast<double>("inf"); + // and check we get a floating-point infinity. + BOOST_MATH_ASSERT(x == std::numeric_limits<double>::infinity()); + cout << "boost::lexical_cast<double>(\"inf\") = " << x << endl; + + // Check we can convert the other way from floating-point infinity, + string s = boost::lexical_cast<string>(numeric_limits<double>::infinity()); + // to a C99 string representation as "inf". + BOOST_MATH_ASSERT(s == "inf"); + + // Finally try full 'round-tripping' (in both directions): + BOOST_MATH_ASSERT(lexical_cast<double>(lexical_cast<string>(numeric_limits<double>::infinity())) + == numeric_limits<double>::infinity()); + BOOST_MATH_ASSERT(lexical_cast<string>(lexical_cast<double>("inf")) == "inf"); + + return 0; +} // int main() + +/* + +Output: + finite_num_facet with lexical_cast example. + Using C99_out_locale + +std::numeric_limits<double>::infinity() = inf + -std::numeric_limits<double>::infinity() = -inf + +std::numeric_limits<double>::quiet_NaN () = nan + boost::lexical_cast<double>("inf") = inf + + +*/ diff --git a/src/boost/libs/math/example/luroth.cpp b/src/boost/libs/math/example/luroth.cpp new file mode 100644 index 000000000..7bb33e554 --- /dev/null +++ b/src/boost/libs/math/example/luroth.cpp @@ -0,0 +1,28 @@ +// (C) Copyright Nick Thompson 2020. +// 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) + +#include <iostream> +#include <boost/math/tools/luroth_expansion.hpp> +#include <boost/math/constants/constants.hpp> + +#ifndef BOOST_MATH_STANDALONE +#include <boost/multiprecision/mpfr.hpp> +using boost::multiprecision::mpfr_float; +#endif // BOOST_MATH_STANDALONE + +using boost::math::constants::pi; +using boost::math::tools::luroth_expansion; + +int main() { + #ifndef BOOST_MATH_STANDALONE + using Real = mpfr_float; + mpfr_float::default_precision(1024); + #else + using Real = long double; + #endif + + auto luroth = luroth_expansion(pi<Real>()); + std::cout << luroth << "\n"; +} diff --git a/src/boost/libs/math/example/naive_monte_carlo_example.cpp b/src/boost/libs/math/example/naive_monte_carlo_example.cpp new file mode 100644 index 000000000..800eb6794 --- /dev/null +++ b/src/boost/libs/math/example/naive_monte_carlo_example.cpp @@ -0,0 +1,136 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + */ + +#include <boost/math/quadrature/naive_monte_carlo.hpp> +#include <iostream> +#include <iomanip> +#include <limits> +#include <cmath> +#include <thread> +#include <future> +#include <string> +#include <chrono> +#include <boost/math/special_functions/pow.hpp> +#include <boost/math/constants/constants.hpp> + +using std::vector; +using std::pair; +using boost::math::quadrature::naive_monte_carlo; + +void display_progress(double progress, + double error_estimate, + double current_estimate, + std::chrono::duration<double> estimated_time_to_completion) +{ + int barWidth = 70; + + std::cout << "["; + int pos = barWidth * progress; + for (int i = 0; i < barWidth; ++i) { + if (i < pos) std::cout << "="; + else if (i == pos) std::cout << ">"; + else std::cout << " "; + } + std::cout << "] " + << int(progress * 100.0) + << "%, E = " + << std::setprecision(3) + << error_estimate + << ", time to completion: " + << estimated_time_to_completion.count() + << " seconds, estimate: " + << std::setprecision(5) + << current_estimate + << " \r"; + + std::cout.flush(); +} + +int main() +{ + double exact = 1.3932039296856768591842462603255; + double A = 1.0 / boost::math::pow<3>(boost::math::constants::pi<double>()); + auto g = [&](std::vector<double> const & x) + { + return A / (1.0 - cos(x[0])*cos(x[1])*cos(x[2])); + }; + vector<pair<double, double>> bounds{{0, boost::math::constants::pi<double>() }, {0, boost::math::constants::pi<double>() }, {0, boost::math::constants::pi<double>() }}; + naive_monte_carlo<double, decltype(g)> mc(g, bounds, 0.001); + + auto task = mc.integrate(); + + int s = 0; + std::cout << "Hit ctrl-c to cancel.\n"; + while (task.wait_for(std::chrono::seconds(1)) != std::future_status::ready) + { + display_progress(mc.progress(), + mc.current_error_estimate(), + mc.current_estimate(), + mc.estimated_time_to_completion()); + // TODO: The following shows that cancellation works, + // but it would be nice to show how it works with a ctrl-c signal handler. + if (s++ > 25){ + mc.cancel(); + std::cout << "\nCancelling because this is too slow!\n"; + } + } + double y = task.get(); + display_progress(mc.progress(), + mc.current_error_estimate(), + mc.current_estimate(), + mc.estimated_time_to_completion()); + std::cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed; + std::cout << "\nFinal value: " << y << std::endl; + std::cout << "Exact : " << exact << std::endl; + std::cout << "Final error estimate: " << mc.current_error_estimate() << std::endl; + std::cout << "Actual error : " << abs(y - exact) << std::endl; + std::cout << "Function calls: " << mc.calls() << std::endl; + std::cout << "Is this good enough? [y/N] "; + bool goodenough = true; + std::string line; + std::getline(std::cin, line); + if (line[0] != 'y') + { + goodenough = false; + } + double new_error = -1; + if (!goodenough) + { + std::cout << "What is the new target error? "; + std::getline(std::cin, line); + new_error = atof(line.c_str()); + if (new_error >= mc.current_error_estimate()) + { + std::cout << "That error bound is already satisfied.\n"; + return 0; + } + } + if (new_error > 0) + { + mc.update_target_error(new_error); + auto task = mc.integrate(); + std::cout << "Hit ctrl-c to cancel.\n"; + while (task.wait_for(std::chrono::seconds(1)) != std::future_status::ready) + { + display_progress(mc.progress(), + mc.current_error_estimate(), + mc.current_estimate(), + mc.estimated_time_to_completion()); + } + double y = task.get(); + display_progress(mc.progress(), + mc.current_error_estimate(), + mc.current_estimate(), + mc.estimated_time_to_completion()); + std::cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed; + std::cout << "\nFinal value: " << y << std::endl; + std::cout << "Exact : " << exact << std::endl; + std::cout << "Final error estimate: " << mc.current_error_estimate() << std::endl; + std::cout << "Actual error : " << abs(y - exact) << std::endl; + std::cout << "Function calls: " << mc.calls() << std::endl; + } +} diff --git a/src/boost/libs/math/example/nc_chi_sq_example.cpp b/src/boost/libs/math/example/nc_chi_sq_example.cpp new file mode 100644 index 000000000..75bfa9443 --- /dev/null +++ b/src/boost/libs/math/example/nc_chi_sq_example.cpp @@ -0,0 +1,115 @@ +// Copyright John Maddock 2008 +// Copyright Paul A. Bristow 2010, 2013 +// 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) + +// Caution: this file contains Quickbook markup as well as code +// and comments, don't change any of the special comment markups! + +//[nccs_eg + +/*` + +This example computes a table of the power of the [chi][super 2] +test at the 5% significance level, for various degrees of freedom +and non-centrality parameters. The table is deliberately the same +as Table 6 from "The Non-Central [chi][super 2] and F-Distributions and +their applications.", P. B. Patnaik, Biometrika, Vol. 36, No. 1/2 (June 1949), +202-232. + +First we need some includes to access the non-central chi squared distribution +(and some basic std output of course). + +*/ + +#include <boost/math/distributions/non_central_chi_squared.hpp> +using boost::math::chi_squared; +using boost::math::non_central_chi_squared; + +#include <iostream> +using std::cout; using std::endl; +using std::setprecision; + +int main() +{ + /*` + Create a table of the power of the [chi][super 2] test at + 5% significance level, start with a table header: + */ + cout << "[table\n[[[nu]]"; + for(int lam = 2; lam <= 20; lam += 2) + { + cout << "[[lambda]=" << lam << "]"; + } + cout << "]\n"; + + /*` + (Note: the enclosing [] brackets are to format as a table in Boost.Quickbook). + + Enumerate the rows and columns and print the power of the test + for each table cell: + */ + + for(int n = 2; n <= 20; ++n) + { + cout << "[[" << n << "]"; + for(int lam = 2; lam <= 20; lam += 2) + { + /*` + Calculate the [chi][super 2] statistic for a 5% significance: + */ + double cs = quantile(complement(chi_squared(n), 0.05)); + /*` + The power of the test is given by the complement of the CDF + of the non-central [chi][super 2] distribution: + */ + double beta = cdf(complement(non_central_chi_squared(n, lam), cs)); + /*` + Then output the cell value: + */ + cout << "[" << setprecision(3) << beta << "]"; + } + cout << "]" << endl; + } + cout << "]" << endl; +} + +/*` +The output from this program is a table in Boost.Quickbook format as shown below. + +We can interpret this as follows - for example if [nu]=10 and [lambda]=10 +then the power of the test is 0.542 - so we have only a 54% chance of +correctly detecting that our null hypothesis is false, and a 46% chance +of incurring a type II error (failing to reject the null hypothesis when +it is in fact false): + +[table +[[[nu]][[lambda]=2][[lambda]=4][[lambda]=6][[lambda]=8][[lambda]=10][[lambda]=12][[lambda]=14][[lambda]=16][[lambda]=18][[lambda]=20]] +[[2][0.226][0.415][0.584][0.718][0.815][0.883][0.928][0.957][0.974][0.985]] +[[3][0.192][0.359][0.518][0.654][0.761][0.84][0.896][0.934][0.959][0.975]] +[[4][0.171][0.32][0.47][0.605][0.716][0.802][0.866][0.912][0.943][0.964]] +[[5][0.157][0.292][0.433][0.564][0.677][0.769][0.839][0.89][0.927][0.952]] +[[6][0.146][0.27][0.403][0.531][0.644][0.738][0.813][0.869][0.911][0.94]] +[[7][0.138][0.252][0.378][0.502][0.614][0.71][0.788][0.849][0.895][0.928]] +[[8][0.131][0.238][0.357][0.477][0.588][0.685][0.765][0.829][0.879][0.915]] +[[9][0.125][0.225][0.339][0.454][0.564][0.661][0.744][0.811][0.863][0.903]] +[[10][0.121][0.215][0.323][0.435][0.542][0.64][0.723][0.793][0.848][0.891]] +[[11][0.117][0.206][0.309][0.417][0.523][0.62][0.704][0.775][0.833][0.878]] +[[12][0.113][0.198][0.297][0.402][0.505][0.601][0.686][0.759][0.818][0.866]] +[[13][0.11][0.191][0.286][0.387][0.488][0.584][0.669][0.743][0.804][0.854]] +[[14][0.108][0.185][0.276][0.374][0.473][0.567][0.653][0.728][0.791][0.842]] +[[15][0.105][0.179][0.267][0.362][0.459][0.552][0.638][0.713][0.777][0.83]] +[[16][0.103][0.174][0.259][0.351][0.446][0.538][0.623][0.699][0.764][0.819]] +[[17][0.101][0.169][0.251][0.341][0.434][0.525][0.609][0.686][0.752][0.807]] +[[18][0.0992][0.165][0.244][0.332][0.423][0.512][0.596][0.673][0.74][0.796]] +[[19][0.0976][0.161][0.238][0.323][0.412][0.5][0.584][0.66][0.728][0.786]] +[[20][0.0961][0.158][0.232][0.315][0.402][0.489][0.572][0.648][0.716][0.775]] +] + +See [@../../example/nc_chi_sq_example.cpp nc_chi_sq_example.cpp] for the full C++ source code. + +*/ + +//] diff --git a/src/boost/libs/math/example/neg_binom_confidence_limits.cpp b/src/boost/libs/math/example/neg_binom_confidence_limits.cpp new file mode 100644 index 000000000..6cca70cb6 --- /dev/null +++ b/src/boost/libs/math/example/neg_binom_confidence_limits.cpp @@ -0,0 +1,178 @@ +// neg_binomial_confidence_limits.cpp + +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2007, 2010 +// 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) + +// Caution: this file contains quickbook markup as well as code +// and comments, don't change any of the special comment markups! + +//[neg_binomial_confidence_limits + +/*` + +First we need some includes to access the negative binomial distribution +(and some basic std output of course). + +*/ + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial; + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::setprecision; +using std::setw; using std::left; using std::fixed; using std::right; + +/*` +First define a table of significance levels: these are the +probabilities that the true occurrence frequency lies outside the calculated +interval: +*/ + + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + +/*` +Confidence value as % is (1 - alpha) * 100, so alpha 0.05 == 95% confidence +that the true occurrence frequency lies *inside* the calculated interval. + +We need a function to calculate and print confidence limits +for an observed frequency of occurrence +that follows a negative binomial distribution. + +*/ + +void confidence_limits_on_frequency(unsigned trials, unsigned successes) +{ + // trials = Total number of trials. + // successes = Total number of observed successes. + // failures = trials - successes. + // success_fraction = successes /trials. + // Print out general info: + cout << + "______________________________________________\n" + "2-Sided Confidence Limits For Success Fraction\n" + "______________________________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Number of trials" << " = " << trials << "\n"; + cout << setw(40) << left << "Number of successes" << " = " << successes << "\n"; + cout << setw(40) << left << "Number of failures" << " = " << trials - successes << "\n"; + cout << setw(40) << left << "Observed frequency of occurrence" << " = " << double(successes) / trials << "\n"; + + // Print table header: + cout << "\n\n" + "___________________________________________\n" + "Confidence Lower Upper\n" + " Value (%) Limit Limit\n" + "___________________________________________\n"; + + +/*` +And now for the important part - the bounds themselves. +For each value of /alpha/, we call `find_lower_bound_on_p` and +`find_upper_bound_on_p` to obtain lower and upper bounds respectively. +Note that since we are calculating a two-sided interval, +we must divide the value of alpha in two. Had we been calculating a +single-sided interval, for example: ['"Calculate a lower bound so that we are P% +sure that the true occurrence frequency is greater than some value"] +then we would *not* have divided by two. +*/ + + // Now print out the upper and lower limits for the alpha table values. + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // Calculate bounds: + double lower = negative_binomial::find_lower_bound_on_p(trials, successes, alpha[i]/2); + double upper = negative_binomial::find_upper_bound_on_p(trials, successes, alpha[i]/2); + // Print limits: + cout << fixed << setprecision(5) << setw(15) << right << lower; + cout << fixed << setprecision(5) << setw(15) << right << upper << endl; + } + cout << endl; +} // void confidence_limits_on_frequency(unsigned trials, unsigned successes) + +/*` + +And then call confidence_limits_on_frequency with increasing numbers of trials, +but always the same success fraction 0.1, or 1 in 10. + +*/ + +int main() +{ + confidence_limits_on_frequency(20, 2); // 20 trials, 2 successes, 2 in 20, = 1 in 10 = 0.1 success fraction. + confidence_limits_on_frequency(200, 20); // More trials, but same 0.1 success fraction. + confidence_limits_on_frequency(2000, 200); // Many more trials, but same 0.1 success fraction. + + return 0; +} // int main() + +//] [/negative_binomial_confidence_limits_eg end of Quickbook in C++ markup] + +/* + +______________________________________________ +2-Sided Confidence Limits For Success Fraction +______________________________________________ +Number of trials = 20 +Number of successes = 2 +Number of failures = 18 +Observed frequency of occurrence = 0.1 +___________________________________________ +Confidence Lower Upper + Value (%) Limit Limit +___________________________________________ + 50.000 0.04812 0.13554 + 75.000 0.03078 0.17727 + 90.000 0.01807 0.22637 + 95.000 0.01235 0.26028 + 99.000 0.00530 0.33111 + 99.900 0.00164 0.41802 + 99.990 0.00051 0.49202 + 99.999 0.00016 0.55574 +______________________________________________ +2-Sided Confidence Limits For Success Fraction +______________________________________________ +Number of trials = 200 +Number of successes = 20 +Number of failures = 180 +Observed frequency of occurrence = 0.1000000 +___________________________________________ +Confidence Lower Upper + Value (%) Limit Limit +___________________________________________ + 50.000 0.08462 0.11350 + 75.000 0.07580 0.12469 + 90.000 0.06726 0.13695 + 95.000 0.06216 0.14508 + 99.000 0.05293 0.16170 + 99.900 0.04343 0.18212 + 99.990 0.03641 0.20017 + 99.999 0.03095 0.21664 +______________________________________________ +2-Sided Confidence Limits For Success Fraction +______________________________________________ +Number of trials = 2000 +Number of successes = 200 +Number of failures = 1800 +Observed frequency of occurrence = 0.1000000 +___________________________________________ +Confidence Lower Upper + Value (%) Limit Limit +___________________________________________ + 50.000 0.09536 0.10445 + 75.000 0.09228 0.10776 + 90.000 0.08916 0.11125 + 95.000 0.08720 0.11352 + 99.000 0.08344 0.11802 + 99.900 0.07921 0.12336 + 99.990 0.07577 0.12795 + 99.999 0.07282 0.13206 +*/ + diff --git a/src/boost/libs/math/example/neg_binomial_sample_sizes.cpp b/src/boost/libs/math/example/neg_binomial_sample_sizes.cpp new file mode 100644 index 000000000..d01089e9d --- /dev/null +++ b/src/boost/libs/math/example/neg_binomial_sample_sizes.cpp @@ -0,0 +1,209 @@ +// neg_binomial_sample_sizes.cpp + +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2007, 2010 + +// 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) + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial; + +// Default RealType is double so this permits use of: +double find_minimum_number_of_trials( +double k, // number of failures (events), k >= 0. +double p, // fraction of trails for which event occurs, 0 <= p <= 1. +double probability); // probability threshold, 0 <= probability <= 1. + +#include <iostream> +using std::cout; +using std::endl; +using std::fixed; +using std::right; +#include <iomanip> +using std::setprecision; +using std::setw; + +//[neg_binomial_sample_sizes + +/*` +It centres around a routine that prints out a table of +minimum sample sizes (number of trials) for various probability thresholds: +*/ + void find_number_of_trials(double failures, double p); +/*` +First define a table of significance levels: these are the maximum +acceptable probability that /failure/ or fewer events will be observed. +*/ + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; +/*` +Confidence value as % is (1 - alpha) * 100, so alpha 0.05 == 95% confidence +that the desired number of failures will be observed. +The values range from a very low 0.5 or 50% confidence up to an extremely high +confidence of 99.999. + +Much of the rest of the program is pretty-printing, the important part +is in the calculation of minimum number of trials required for each +value of alpha using: + + (int)ceil(negative_binomial::find_minimum_number_of_trials(failures, p, alpha[i]); + +find_minimum_number_of_trials returns a double, +so `ceil` rounds this up to ensure we have an integral minimum number of trials. +*/ + +void find_number_of_trials(double failures, double p) +{ + // trials = number of trials + // failures = number of failures before achieving required success(es). + // p = success fraction (0 <= p <= 1.). + // + // Calculate how many trials we need to ensure the + // required number of failures DOES exceed "failures". + + cout << "\n""Target number of failures = " << (int)failures; + cout << ", Success fraction = " << fixed << setprecision(1) << 100 * p << "%" << endl; + // Print table header: + cout << "____________________________\n" + "Confidence Min Number\n" + " Value (%) Of Trials \n" + "____________________________\n"; + // Now print out the data for the alpha table values. + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { // Confidence values %: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]) << " " + // find_minimum_number_of_trials + << setw(6) << right + << (int)ceil(negative_binomial::find_minimum_number_of_trials(failures, p, alpha[i])) + << endl; + } + cout << endl; +} // void find_number_of_trials(double failures, double p) + +/*` finally we can produce some tables of minimum trials for the chosen confidence levels: +*/ + +int main() +{ + find_number_of_trials(5, 0.5); + find_number_of_trials(50, 0.5); + find_number_of_trials(500, 0.5); + find_number_of_trials(50, 0.1); + find_number_of_trials(500, 0.1); + find_number_of_trials(5, 0.9); + + return 0; +} // int main() + +//] [/neg_binomial_sample_sizes.cpp end of Quickbook in C++ markup] + +/* + +Output is: +Target number of failures = 5, Success fraction = 50.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 11 + 75.000 14 + 90.000 17 + 95.000 18 + 99.000 22 + 99.900 27 + 99.990 31 + 99.999 36 + + + Target number of failures = 50, Success fraction = 50.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 101 + 75.000 109 + 90.000 115 + 95.000 119 + 99.000 128 + 99.900 137 + 99.990 146 + 99.999 154 + + + Target number of failures = 500, Success fraction = 50.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 1001 + 75.000 1023 + 90.000 1043 + 95.000 1055 + 99.000 1078 + 99.900 1104 + 99.990 1126 + 99.999 1146 + + + Target number of failures = 50, Success fraction = 10.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 56 + 75.000 58 + 90.000 60 + 95.000 61 + 99.000 63 + 99.900 66 + 99.990 68 + 99.999 71 + + + Target number of failures = 500, Success fraction = 10.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 556 + 75.000 562 + 90.000 567 + 95.000 570 + 99.000 576 + 99.900 583 + 99.990 588 + 99.999 594 + + + Target number of failures = 5, Success fraction = 90.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 57 + 75.000 73 + 90.000 91 + 95.000 103 + 99.000 127 + 99.900 159 + 99.990 189 + 99.999 217 + + + Target number of failures = 5, Success fraction = 95.0% + ____________________________ + Confidence Min Number + Value (%) Of Trials + ____________________________ + 50.000 114 + 75.000 148 + 90.000 184 + 95.000 208 + 99.000 259 + 99.900 324 + 99.990 384 + 99.999 442 + +*/ diff --git a/src/boost/libs/math/example/negative_binomial_example1.cpp b/src/boost/libs/math/example/negative_binomial_example1.cpp new file mode 100644 index 000000000..92fe48ce2 --- /dev/null +++ b/src/boost/libs/math/example/negative_binomial_example1.cpp @@ -0,0 +1,513 @@ +// negative_binomial_example1.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Example 1 of using negative_binomial distribution. + +//[negative_binomial_eg1_1 + +/*` +Based on [@http://en.wikipedia.org/wiki/Negative_binomial_distribution +a problem by Dr. Diane Evans, +Professor of Mathematics at Rose-Hulman Institute of Technology]. + +Pat is required to sell candy bars to raise money for the 6th grade field trip. +There are thirty houses in the neighborhood, +and Pat is not supposed to return home until five candy bars have been sold. +So the child goes door to door, selling candy bars. +At each house, there is a 0.4 probability (40%) of selling one candy bar +and a 0.6 probability (60%) of selling nothing. + +What is the probability mass (density) function (pdf) for selling the last (fifth) +candy bar at the nth house? + +The Negative Binomial(r, p) distribution describes the probability of k failures +and r successes in k+r Bernoulli(p) trials with success on the last trial. +(A [@http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli trial] +is one with only two possible outcomes, success of failure, +and p is the probability of success). +See also [@ http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli distribution] +and [@http://www.math.uah.edu/stat/bernoulli/Introduction.xhtml Bernoulli applications]. + +In this example, we will deliberately produce a variety of calculations +and outputs to demonstrate the ways that the negative binomial distribution +can be implemented with this library: it is also deliberately over-commented. + +First we need to #define macros to control the error and discrete handling policies. +For this simple example, we want to avoid throwing +an exception (the default policy) and just return infinity. +We want to treat the distribution as if it was continuous, +so we choose a discrete_quantile policy of real, +rather than the default policy integer_round_outwards. +*/ +#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error +#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real +/*` +After that we need some includes to provide easy access to the negative binomial distribution, +[caution It is vital to #include distributions etc *after* the above #defines] +and we need some std library iostream, of course. +*/ +#include <boost/math/distributions/negative_binomial.hpp> + // for negative_binomial_distribution + using boost::math::negative_binomial; // typedef provides default type is double. + using ::boost::math::pdf; // Probability mass function. + using ::boost::math::cdf; // Cumulative density function. + using ::boost::math::quantile; + +#include <iostream> + using std::cout; using std::endl; + using std::noshowpoint; using std::fixed; using std::right; using std::left; +#include <iomanip> + using std::setprecision; using std::setw; + +#include <limits> + using std::numeric_limits; +//] [negative_binomial_eg1_1] + +int main() +{ + cout <<"Selling candy bars - using the negative binomial distribution." + << "\nby Dr. Diane Evans," + "\nProfessor of Mathematics at Rose-Hulman Institute of Technology," + << "\nsee http://en.wikipedia.org/wiki/Negative_binomial_distribution\n" + << endl; + cout << endl; + cout.precision(5); + // None of the values calculated have a useful accuracy as great this, but + // INF shows wrongly with < 5 ! + // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=240227 +//[negative_binomial_eg1_2 +/*` +It is always sensible to use try and catch blocks because defaults policies are to +throw an exception if anything goes wrong. + +A simple catch block (see below) will ensure that you get a +helpful error message instead of an abrupt program abort. +*/ + try + { +/*` +Selling five candy bars means getting five successes, so successes r = 5. +The total number of trials (n, in this case, houses visited) this takes is therefore + = successes + failures or k + r = k + 5. +*/ + double sales_quota = 5; // Pat's sales quota - successes (r). +/*` +At each house, there is a 0.4 probability (40%) of selling one candy bar +and a 0.6 probability (60%) of selling nothing. +*/ + double success_fraction = 0.4; // success_fraction (p) - so failure_fraction is 0.6. +/*` +The Negative Binomial(r, p) distribution describes the probability of k failures +and r successes in k+r Bernoulli(p) trials with success on the last trial. +(A [@http://en.wikipedia.org/wiki/Bernoulli_distribution Bernoulli trial] +is one with only two possible outcomes, success of failure, +and p is the probability of success). + +We therefore start by constructing a negative binomial distribution +with parameters sales_quota (required successes) and probability of success. +*/ + negative_binomial nb(sales_quota, success_fraction); // type double by default. +/*` +To confirm, display the success_fraction & successes parameters of the distribution. +*/ + cout << "Pat has a sales per house success rate of " << success_fraction + << ".\nTherefore he would, on average, sell " << nb.success_fraction() * 100 + << " bars after trying 100 houses." << endl; + + int all_houses = 30; // The number of houses on the estate. + + cout << "With a success rate of " << nb.success_fraction() + << ", he might expect, on average,\n" + "to need to visit about " << success_fraction * all_houses + << " houses in order to sell all " << nb.successes() << " bars. " << endl; +/*` +[pre +Pat has a sales per house success rate of 0.4. +Therefore he would, on average, sell 40 bars after trying 100 houses. +With a success rate of 0.4, he might expect, on average, +to need to visit about 12 houses in order to sell all 5 bars. +] + +The random variable of interest is the number of houses +that must be visited to sell five candy bars, +so we substitute k = n - 5 into a negative_binomial(5, 0.4) +and obtain the __pdf of the distribution of houses visited. +Obviously, the best possible case is that Pat makes sales on all the first five houses. + +We calculate this using the pdf function: +*/ + cout << "Probability that Pat finishes on the " << sales_quota << "th house is " + << pdf(nb, 5 - sales_quota) << endl; // == pdf(nb, 0) +/*` +Of course, he could not finish on fewer than 5 houses because he must sell 5 candy bars. +So the 5th house is the first that he could possibly finish on. + +To finish on or before the 8th house, Pat must finish at the 5th, 6th, 7th or 8th house. +The probability that he will finish on *exactly* ( == ) on any house +is the Probability Density Function (pdf). +*/ + cout << "Probability that Pat finishes on the 6th house is " + << pdf(nb, 6 - sales_quota) << endl; + cout << "Probability that Pat finishes on the 7th house is " + << pdf(nb, 7 - sales_quota) << endl; + cout << "Probability that Pat finishes on the 8th house is " + << pdf(nb, 8 - sales_quota) << endl; +/*` +[pre +Probability that Pat finishes on the 6th house is 0.03072 +Probability that Pat finishes on the 7th house is 0.055296 +Probability that Pat finishes on the 8th house is 0.077414 +] + +The sum of the probabilities for these houses is the Cumulative Distribution Function (cdf). +We can calculate it by adding the individual probabilities. +*/ + cout << "Probability that Pat finishes on or before the 8th house is sum " + "\n" << "pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = " + // Sum each of the mass/density probabilities for houses sales_quota = 5, 6, 7, & 8. + << pdf(nb, 5 - sales_quota) // 0 failures. + + pdf(nb, 6 - sales_quota) // 1 failure. + + pdf(nb, 7 - sales_quota) // 2 failures. + + pdf(nb, 8 - sales_quota) // 3 failures. + << endl; +/*`[pre +pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = 0.17367 +] + +Or, usually better, by using the negative binomial *cumulative* distribution function. +*/ + cout << "\nProbability of selling his quota of " << sales_quota + << " bars\non or before the " << 8 << "th house is " + << cdf(nb, 8 - sales_quota) << endl; +/*`[pre +Probability of selling his quota of 5 bars on or before the 8th house is 0.17367 +]*/ + cout << "\nProbability that Pat finishes exactly on the 10th house is " + << pdf(nb, 10 - sales_quota) << endl; + cout << "\nProbability of selling his quota of " << sales_quota + << " bars\non or before the " << 10 << "th house is " + << cdf(nb, 10 - sales_quota) << endl; +/*` +[pre +Probability that Pat finishes exactly on the 10th house is 0.10033 +Probability of selling his quota of 5 bars on or before the 10th house is 0.3669 +]*/ + cout << "Probability that Pat finishes exactly on the 11th house is " + << pdf(nb, 11 - sales_quota) << endl; + cout << "\nProbability of selling his quota of " << sales_quota + << " bars\non or before the " << 11 << "th house is " + << cdf(nb, 11 - sales_quota) << endl; +/*`[pre +Probability that Pat finishes on the 11th house is 0.10033 +Probability of selling his quota of 5 candy bars +on or before the 11th house is 0.46723 +]*/ + cout << "Probability that Pat finishes exactly on the 12th house is " + << pdf(nb, 12 - sales_quota) << endl; + + cout << "\nProbability of selling his quota of " << sales_quota + << " bars\non or before the " << 12 << "th house is " + << cdf(nb, 12 - sales_quota) << endl; +/*`[pre +Probability that Pat finishes on the 12th house is 0.094596 +Probability of selling his quota of 5 candy bars +on or before the 12th house is 0.56182 +] +Finally consider the risk of Pat not selling his quota of 5 bars +even after visiting all the houses. +Calculate the probability that he /will/ sell on +or before the last house: +Calculate the probability that he would sell all his quota on the very last house. +*/ + cout << "Probability that Pat finishes on the " << all_houses + << " house is " << pdf(nb, all_houses - sales_quota) << endl; +/*` +Probability of selling his quota of 5 bars on the 30th house is +[pre +Probability that Pat finishes on the 30 house is 0.00069145 +] +when he'd be very unlucky indeed! + +What is the probability that Pat exhausts all 30 houses in the neighborhood, +and *still* doesn't sell the required 5 candy bars? +*/ + cout << "\nProbability of selling his quota of " << sales_quota + << " bars\non or before the " << all_houses << "th house is " + << cdf(nb, all_houses - sales_quota) << endl; +/*` +[pre +Probability of selling his quota of 5 bars +on or before the 30th house is 0.99849 +] + +So the risk of failing even after visiting all the houses is 1 - this probability, + ``1 - cdf(nb, all_houses - sales_quota`` +But using this expression may cause serious inaccuracy, +so it would be much better to use the complement of the cdf: +So the risk of failing even at, or after, the 31th (non-existent) houses is 1 - this probability, + ``1 - cdf(nb, all_houses - sales_quota)`` +But using this expression may cause serious inaccuracy. +So it would be much better to use the __complement of the cdf (see __why_complements). +*/ + cout << "\nProbability of failing to sell his quota of " << sales_quota + << " bars\neven after visiting all " << all_houses << " houses is " + << cdf(complement(nb, all_houses - sales_quota)) << endl; +/*` +[pre +Probability of failing to sell his quota of 5 bars +even after visiting all 30 houses is 0.0015101 +] +We can also use the quantile (percentile), the inverse of the cdf, to +predict which house Pat will finish on. So for the 8th house: +*/ + double p = cdf(nb, (8 - sales_quota)); + cout << "Probability of meeting sales quota on or before 8th house is "<< p << endl; +/*` +[pre +Probability of meeting sales quota on or before 8th house is 0.174 +] +*/ + cout << "If the confidence of meeting sales quota is " << p + << ", then the finishing house is " << quantile(nb, p) + sales_quota << endl; + + cout<< " quantile(nb, p) = " << quantile(nb, p) << endl; +/*` +[pre +If the confidence of meeting sales quota is 0.17367, then the finishing house is 8 +] +Demanding absolute certainty that all 5 will be sold, +implies an infinite number of trials. +(Of course, there are only 30 houses on the estate, +so he can't ever be *certain* of selling his quota). +*/ + cout << "If the confidence of meeting sales quota is " << 1. + << ", then the finishing house is " << quantile(nb, 1) + sales_quota << endl; + // 1.#INF == infinity. +/*`[pre +If the confidence of meeting sales quota is 1, then the finishing house is 1.#INF +] +And similarly for a few other probabilities: +*/ + cout << "If the confidence of meeting sales quota is " << 0. + << ", then the finishing house is " << quantile(nb, 0.) + sales_quota << endl; + + cout << "If the confidence of meeting sales quota is " << 0.5 + << ", then the finishing house is " << quantile(nb, 0.5) + sales_quota << endl; + + cout << "If the confidence of meeting sales quota is " << 1 - 0.00151 // 30 th + << ", then the finishing house is " << quantile(nb, 1 - 0.00151) + sales_quota << endl; +/*` +[pre +If the confidence of meeting sales quota is 0, then the finishing house is 5 +If the confidence of meeting sales quota is 0.5, then the finishing house is 11.337 +If the confidence of meeting sales quota is 0.99849, then the finishing house is 30 +] + +Notice that because we chose a discrete quantile policy of real, +the result can be an 'unreal' fractional house. + +If the opposite is true, we don't want to assume any confidence, then this is tantamount +to assuming that all the first sales_quota trials will be successful sales. +*/ + cout << "If confidence of meeting quota is zero\n(we assume all houses are successful sales)" + ", then finishing house is " << sales_quota << endl; +/*` +[pre +If confidence of meeting quota is zero (we assume all houses are successful sales), then finishing house is 5 +If confidence of meeting quota is 0, then finishing house is 5 +] +We can list quantiles for a few probabilities: +*/ + + double ps[] = {0., 0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.95, 0.99, 0.999, 1.}; + // Confidence as fraction = 1-alpha, as percent = 100 * (1-alpha[i]) % + cout.precision(3); + for (unsigned i = 0; i < sizeof(ps)/sizeof(ps[0]); i++) + { + cout << "If confidence of meeting quota is " << ps[i] + << ", then finishing house is " << quantile(nb, ps[i]) + sales_quota + << endl; + } + +/*` +[pre +If confidence of meeting quota is 0, then finishing house is 5 +If confidence of meeting quota is 0.001, then finishing house is 5 +If confidence of meeting quota is 0.01, then finishing house is 5 +If confidence of meeting quota is 0.05, then finishing house is 6.2 +If confidence of meeting quota is 0.1, then finishing house is 7.06 +If confidence of meeting quota is 0.5, then finishing house is 11.3 +If confidence of meeting quota is 0.9, then finishing house is 17.8 +If confidence of meeting quota is 0.95, then finishing house is 20.1 +If confidence of meeting quota is 0.99, then finishing house is 24.8 +If confidence of meeting quota is 0.999, then finishing house is 31.1 +If confidence of meeting quota is 1, then finishing house is 1.#INF +] + +We could have applied a ceil function to obtain a 'worst case' integer value for house. +``ceil(quantile(nb, ps[i]))`` + +Or, if we had used the default discrete quantile policy, integer_outside, by omitting +``#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real`` +we would have achieved the same effect. + +The real result gives some suggestion which house is most likely. +For example, compare the real and integer_outside for 95% confidence. + +[pre +If confidence of meeting quota is 0.95, then finishing house is 20.1 +If confidence of meeting quota is 0.95, then finishing house is 21 +] +The real value 20.1 is much closer to 20 than 21, so integer_outside is pessimistic. +We could also use integer_round_nearest policy to suggest that 20 is more likely. + +Finally, we can tabulate the probability for the last sale being exactly on each house. +*/ + cout << "\nHouse for " << sales_quota << "th (last) sale. Probability (%)" << endl; + cout.precision(5); + for (int i = (int)sales_quota; i < all_houses+1; i++) + { + cout << left << setw(3) << i << " " << setw(8) << cdf(nb, i - sales_quota) << endl; + } + cout << endl; +/*` +[pre +House for 5 th (last) sale. Probability (%) +5 0.01024 +6 0.04096 +7 0.096256 +8 0.17367 +9 0.26657 +10 0.3669 +11 0.46723 +12 0.56182 +13 0.64696 +14 0.72074 +15 0.78272 +16 0.83343 +17 0.874 +18 0.90583 +19 0.93039 +20 0.94905 +21 0.96304 +22 0.97342 +23 0.98103 +24 0.98655 +25 0.99053 +26 0.99337 +27 0.99539 +28 0.99681 +29 0.9978 +30 0.99849 +] + +As noted above, using a catch block is always a good idea, even if you do not expect to use it. +*/ + } + catch(const std::exception& e) + { // Since we have set an overflow policy of ignore_error, + // an overflow exception should never be thrown. + std::cout << "\nMessage from thrown exception was:\n " << e.what() << std::endl; +/*` +For example, without a ignore domain error policy, if we asked for ``pdf(nb, -1)`` for example, we would get: +[pre +Message from thrown exception was: + Error in function boost::math::pdf(const negative_binomial_distribution<double>&, double): + Number of failures argument is -1, but must be >= 0 ! +] +*/ +//] [/ negative_binomial_eg1_2] + } + return 0; +} // int main() + + +/* + +Output is: + +Selling candy bars - using the negative binomial distribution. +by Dr. Diane Evans, +Professor of Mathematics at Rose-Hulman Institute of Technology, +see http://en.wikipedia.org/wiki/Negative_binomial_distribution +Pat has a sales per house success rate of 0.4. +Therefore he would, on average, sell 40 bars after trying 100 houses. +With a success rate of 0.4, he might expect, on average, +to need to visit about 12 houses in order to sell all 5 bars. +Probability that Pat finishes on the 5th house is 0.01024 +Probability that Pat finishes on the 6th house is 0.03072 +Probability that Pat finishes on the 7th house is 0.055296 +Probability that Pat finishes on the 8th house is 0.077414 +Probability that Pat finishes on or before the 8th house is sum +pdf(sales_quota) + pdf(6) + pdf(7) + pdf(8) = 0.17367 +Probability of selling his quota of 5 bars +on or before the 8th house is 0.17367 +Probability that Pat finishes exactly on the 10th house is 0.10033 +Probability of selling his quota of 5 bars +on or before the 10th house is 0.3669 +Probability that Pat finishes exactly on the 11th house is 0.10033 +Probability of selling his quota of 5 bars +on or before the 11th house is 0.46723 +Probability that Pat finishes exactly on the 12th house is 0.094596 +Probability of selling his quota of 5 bars +on or before the 12th house is 0.56182 +Probability that Pat finishes on the 30 house is 0.00069145 +Probability of selling his quota of 5 bars +on or before the 30th house is 0.99849 +Probability of failing to sell his quota of 5 bars +even after visiting all 30 houses is 0.0015101 +Probability of meeting sales quota on or before 8th house is 0.17367 +If the confidence of meeting sales quota is 0.17367, then the finishing house is 8 + quantile(nb, p) = 3 +If the confidence of meeting sales quota is 1, then the finishing house is 1.#INF +If the confidence of meeting sales quota is 0, then the finishing house is 5 +If the confidence of meeting sales quota is 0.5, then the finishing house is 11.337 +If the confidence of meeting sales quota is 0.99849, then the finishing house is 30 +If confidence of meeting quota is zero +(we assume all houses are successful sales), then finishing house is 5 +If confidence of meeting quota is 0, then finishing house is 5 +If confidence of meeting quota is 0.001, then finishing house is 5 +If confidence of meeting quota is 0.01, then finishing house is 5 +If confidence of meeting quota is 0.05, then finishing house is 6.2 +If confidence of meeting quota is 0.1, then finishing house is 7.06 +If confidence of meeting quota is 0.5, then finishing house is 11.3 +If confidence of meeting quota is 0.9, then finishing house is 17.8 +If confidence of meeting quota is 0.95, then finishing house is 20.1 +If confidence of meeting quota is 0.99, then finishing house is 24.8 +If confidence of meeting quota is 0.999, then finishing house is 31.1 +If confidence of meeting quota is 1, then finishing house is 1.#J +House for 5th (last) sale. Probability (%) +5 0.01024 +6 0.04096 +7 0.096256 +8 0.17367 +9 0.26657 +10 0.3669 +11 0.46723 +12 0.56182 +13 0.64696 +14 0.72074 +15 0.78272 +16 0.83343 +17 0.874 +18 0.90583 +19 0.93039 +20 0.94905 +21 0.96304 +22 0.97342 +23 0.98103 +24 0.98655 +25 0.99053 +26 0.99337 +27 0.99539 +28 0.99681 +29 0.9978 +30 0.99849 + +*/ diff --git a/src/boost/libs/math/example/negative_binomial_example2.cpp b/src/boost/libs/math/example/negative_binomial_example2.cpp new file mode 100644 index 000000000..c1c90916a --- /dev/null +++ b/src/boost/libs/math/example/negative_binomial_example2.cpp @@ -0,0 +1,182 @@ +// negative_binomial_example2.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Simple example demonstrating use of the Negative Binomial Distribution. + +#include <boost/math/distributions/negative_binomial.hpp> + using boost::math::negative_binomial_distribution; + using boost::math::negative_binomial; // typedef + +// In a sequence of trials or events +// (Bernoulli, independent, yes or no, succeed or fail) +// with success_fraction probability p, +// negative_binomial is the probability that k or fewer failures +// precede the r th trial's success. + +#include <iostream> +using std::cout; +using std::endl; +using std::setprecision; +using std::showpoint; +using std::setw; +using std::left; +using std::right; +#include <limits> +using std::numeric_limits; + +int main() +{ + cout << "Negative_binomial distribution - simple example 2" << endl; + // Construct a negative binomial distribution with: + // 8 successes (r), success fraction (p) 0.25 = 25% or 1 in 4 successes. + negative_binomial mynbdist(8, 0.25); // Shorter method using typedef. + + // Display (to check) properties of the distribution just constructed. + cout << "mean(mynbdist) = " << mean(mynbdist) << endl; // 24 + cout << "mynbdist.successes() = " << mynbdist.successes() << endl; // 8 + // r th successful trial, after k failures, is r + k th trial. + cout << "mynbdist.success_fraction() = " << mynbdist.success_fraction() << endl; + // success_fraction = failures/successes or k/r = 0.25 or 25%. + cout << "mynbdist.percent success = " << mynbdist.success_fraction() * 100 << "%" << endl; + // Show as % too. + // Show some cumulative distribution function values for failures k = 2 and 8 + cout << "cdf(mynbdist, 2.) = " << cdf(mynbdist, 2.) << endl; // 0.000415802001953125 + cout << "cdf(mynbdist, 8.) = " << cdf(mynbdist, 8.) << endl; // 0.027129956288263202 + cout << "cdf(complement(mynbdist, 8.)) = " << cdf(complement(mynbdist, 8.)) << endl; // 0.9728700437117368 + // Check that cdf plus its complement is unity. + cout << "cdf + complement = " << cdf(mynbdist, 8.) + cdf(complement(mynbdist, 8.)) << endl; // 1 + // Note: No complement for pdf! + + // Compare cdf with sum of pdfs. + double sum = 0.; // Calculate the sum of all the pdfs, + int k = 20; // for 20 failures + for(signed i = 0; i <= k; ++i) + { + sum += pdf(mynbdist, double(i)); + } + // Compare with the cdf + double cdf8 = cdf(mynbdist, static_cast<double>(k)); + double diff = sum - cdf8; // Expect the difference to be very small. + cout << setprecision(17) << "Sum pdfs = " << sum << ' ' // sum = 0.40025683281803698 + << ", cdf = " << cdf(mynbdist, static_cast<double>(k)) // cdf = 0.40025683281803687 + << ", difference = " // difference = 0.50000000000000000 + << setprecision(1) << diff/ (std::numeric_limits<double>::epsilon() * sum) + << " in epsilon units." << endl; + + // Note: Use boost::math::tools::epsilon rather than std::numeric_limits + // to cover RealTypes that do not specialize numeric_limits. + +//[neg_binomial_example2 + + // Print a table of values that can be used to plot + // using Excel, or some other superior graphical display tool. + + cout.precision(17); // Use max_digits10 precision, the maximum available for a reference table. + cout << showpoint << endl; // include trailing zeros. + // This is a maximum possible precision for the type (here double) to suit a reference table. + int maxk = static_cast<int>(2. * mynbdist.successes() / mynbdist.success_fraction()); + // This maxk shows most of the range of interest, probability about 0.0001 to 0.999. + cout << "\n"" k pdf cdf""\n" << endl; + for (int k = 0; k < maxk; k++) + { + cout << right << setprecision(17) << showpoint + << right << setw(3) << k << ", " + << left << setw(25) << pdf(mynbdist, static_cast<double>(k)) + << left << setw(25) << cdf(mynbdist, static_cast<double>(k)) + << endl; + } + cout << endl; +//] [/ neg_binomial_example2] + return 0; +} // int main() + +/* + +Output is: + +negative_binomial distribution - simple example 2 +mean(mynbdist) = 24 +mynbdist.successes() = 8 +mynbdist.success_fraction() = 0.25 +mynbdist.percent success = 25% +cdf(mynbdist, 2.) = 0.000415802001953125 +cdf(mynbdist, 8.) = 0.027129956288263202 +cdf(complement(mynbdist, 8.)) = 0.9728700437117368 +cdf + complement = 1 +Sum pdfs = 0.40025683281803692 , cdf = 0.40025683281803687, difference = 0.25 in epsilon units. + +//[neg_binomial_example2_1 + k pdf cdf + 0, 1.5258789062500000e-005 1.5258789062500003e-005 + 1, 9.1552734375000000e-005 0.00010681152343750000 + 2, 0.00030899047851562522 0.00041580200195312500 + 3, 0.00077247619628906272 0.0011882781982421875 + 4, 0.0015932321548461918 0.0027815103530883789 + 5, 0.0028678178787231476 0.0056493282318115234 + 6, 0.0046602040529251142 0.010309532284736633 + 7, 0.0069903060793876605 0.017299838364124298 + 8, 0.0098301179241389001 0.027129956288263202 + 9, 0.013106823898851871 0.040236780187115073 + 10, 0.016711200471036140 0.056947980658151209 + 11, 0.020509200578089786 0.077457181236241013 + 12, 0.024354675686481652 0.10181185692272265 + 13, 0.028101548869017230 0.12991340579173993 + 14, 0.031614242477644432 0.16152764826938440 + 15, 0.034775666725408917 0.19630331499479325 + 16, 0.037492515688331451 0.23379583068312471 + 17, 0.039697957787645101 0.27349378847076977 + 18, 0.041352039362130305 0.31484582783290005 + 19, 0.042440250924291580 0.35728607875719176 + 20, 0.042970754060845245 0.40025683281803687 + 21, 0.042970754060845225 0.44322758687888220 + 22, 0.042482450037426581 0.48571003691630876 + 23, 0.041558918514873783 0.52726895543118257 + 24, 0.040260202311284021 0.56752915774246648 + 25, 0.038649794218832620 0.60617895196129912 + 26, 0.036791631035234917 0.64297058299653398 + 27, 0.034747651533277427 0.67771823452981139 + 28, 0.032575923312447595 0.71029415784225891 + 29, 0.030329307911589130 0.74062346575384819 + 30, 0.028054609818219924 0.76867807557206813 + 31, 0.025792141284492545 0.79447021685656061 + 32, 0.023575629142856460 0.81804584599941710 + 33, 0.021432390129869489 0.83947823612928651 + 34, 0.019383705779220189 0.85886194190850684 + 35, 0.017445335201298231 0.87630727710980494 + 36, 0.015628112784496322 0.89193538989430121 + 37, 0.013938587078064250 0.90587397697236549 + 38, 0.012379666154859701 0.91825364312722524 + 39, 0.010951243136991251 0.92920488626421649 + 40, 0.0096507830144735539 0.93885566927869002 + 41, 0.0084738582566109364 0.94732952753530097 + 42, 0.0074146259745345548 0.95474415350983555 + 43, 0.0064662435824429246 0.96121039709227851 + 44, 0.0056212231142827853 0.96683162020656122 + 45, 0.0048717266990450708 0.97170334690560634 + 46, 0.0042098073105878630 0.97591315421619418 + 47, 0.0036275999165703964 0.97954075413276465 + 48, 0.0031174686783026818 0.98265822281106729 + 49, 0.0026721160099737302 0.98533033882104104 + 50, 0.0022846591885275322 0.98761499800956853 + 51, 0.0019486798960970148 0.98956367790566557 + 52, 0.0016582516423517923 0.99122192954801736 + 53, 0.0014079495076571762 0.99262987905567457 + 54, 0.0011928461106539983 0.99382272516632852 + 55, 0.0010084971662802015 0.99483122233260868 + 56, 0.00085091948404891532 0.99568214181665760 + 57, 0.00071656377604119542 0.99639870559269883 + 58, 0.00060228420831048650 0.99700098980100937 + 59, 0.00050530624256557675 0.99750629604357488 + 60, 0.00042319397814867202 0.99792949002172360 + 61, 0.00035381791615708398 0.99828330793788067 + 62, 0.00029532382517950324 0.99857863176306016 + 63, 0.00024610318764958566 0.99882473495070978 +//] [neg_binomial_example2_1 end of Quickbook] + +*/ diff --git a/src/boost/libs/math/example/neumann_zeros_example_1.cpp b/src/boost/libs/math/example/neumann_zeros_example_1.cpp new file mode 100644 index 000000000..b8042d96a --- /dev/null +++ b/src/boost/libs/math/example/neumann_zeros_example_1.cpp @@ -0,0 +1,85 @@ + +// Copyright Christopher Kormanyos 2013. +// Copyright Paul A. Bristow 2013. +// Copyright John Maddock 2013. + +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated. +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +#include <iostream> +#include <limits> +#include <vector> +#include <algorithm> +#include <iomanip> +#include <iterator> + +//[neumann_zeros_example_1 + +/*`[h5 Calculating zeros of the Neumann function.] +This example also shows how Boost.Math and Boost.Multiprecision can be combined to provide +a many decimal digit precision. For 50 decimal digit precision we need to include +*/ + + #include <boost/multiprecision/cpp_dec_float.hpp> + +/*`and a `typedef` for `float_type` may be convenient +(allowing a quick switch to re-compute at built-in `double` or other precision) +*/ + typedef boost::multiprecision::cpp_dec_float_50 float_type; + +//`To use the functions for finding zeros of the `cyl_neumann` function we need: + + #include <boost/math/special_functions/bessel.hpp> +//] [/neumann_zerso_example_1] + +int main() +{ + try + { + { +//[neumann_zeros_example_2 +/*`The Neumann (Bessel Y) function zeros are evaluated very similarly: +*/ + using boost::math::cyl_neumann_zero; + double zn = cyl_neumann_zero(2., 1); + std::cout << "cyl_neumann_zero(2., 1) = " << zn << std::endl; + + std::vector<float> nzeros(3); // Space for 3 zeros. + cyl_neumann_zero<float>(2.F, 1, nzeros.size(), nzeros.begin()); + + std::cout << "cyl_neumann_zero<float>(2.F, 1, "; + // Print the zeros to the output stream. + std::copy(nzeros.begin(), nzeros.end(), + std::ostream_iterator<float>(std::cout, ", ")); + + std::cout << "\n""cyl_neumann_zero(static_cast<float_type>(220)/100, 1) = " + << cyl_neumann_zero(static_cast<float_type>(220)/100, 1) << std::endl; + // 3.6154383428745996706772556069431792744372398748422 + +//] //[/neumann_zeros_example_2] + } + } + catch (std::exception const& ex) + { + std::cout << "Thrown exception " << ex.what() << std::endl; + } +} // int main() + +/* + Output: + +cyl_neumann_zero(2., 1) = 3.38424 +cyl_neumann_zero<float>(2.F, 1, +3.38424 +6.79381 +10.0235 +3.61544 +*/ + + diff --git a/src/boost/libs/math/example/nonfinite_facet_simple.cpp b/src/boost/libs/math/example/nonfinite_facet_simple.cpp new file mode 100644 index 000000000..730228161 --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_facet_simple.cpp @@ -0,0 +1,269 @@ +/** nonfinite_num_facet.cpp +* +* Copyright (c) 2011 Paul A. Bristow +* +* 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) +* +* This very simple program illustrates how to use the +* `boost/math/nonfinite_num_facets.hpp' to obtain C99 +* representation of infinity and NaN. +* (from the original +* Floating Point Utilities contribution by Johan Rade. +* Floating Point Utility library has been accepted into Boost, +* but the utilities are incorporated into Boost.Math library. +* +\file + +\brief A very simple example of using non_finite_num facet for +C99 standard output of infinity and NaN. + +\detail Provided infinity and nan are supported, +this example shows how to create a C99 non-finite locale, +and imbue input and output streams with the non_finite_num put and get facets. +This allow output and input of infinity and NaN in a Standard portable way, +This permits 'loop-back' of output back into input (and portably across different system too). +This is particularly useful when used with Boost.Serialization so that non-finite NaNs and infinity +values in text and xml archives can be handled correctly and portably. + +*/ + +#ifdef _MSC_VER +# pragma warning (disable : 4127) // conditional expression is constant. +#endif + +#include <iostream> +using std::cout; +using std::endl; +using std::cerr; + +#include <iomanip> +using std::setw; +using std::left; +using std::right; +using std::internal; + +#include <string> +using std::string; + +#include <sstream> +using std::istringstream; + +#include <limits> +using std::numeric_limits; + +#include <locale> +using std::locale; + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +// from Johan Rade Floating Point Utilities. + +int main () +{ + std::cout << "Nonfinite_num_facet very simple example." << std::endl; + + if((std::numeric_limits<double>::has_infinity == 0) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == 0) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + + std::locale default_locale (std::locale::classic ()); // Note the current (default C) locale. + + // Create plus and minus infinity. + double plus_infinity = +std::numeric_limits<double>::infinity(); + double minus_infinity = -std::numeric_limits<double>::infinity(); + + // and create a NaN (NotANumber) + double NaN = +std::numeric_limits<double>::quiet_NaN (); + + double negated_NaN = (boost::math::changesign)(std::numeric_limits<double>::quiet_NaN ()); + + + // Output the nonfinite values using the current (default C) locale. + // The default representations differ from system to system, + // for example, using Microsoft compilers, 1.#INF, -1.#INF, and 1.#QNAN, + // Linux "inf", "-inf", "nan" + cout << "Using C locale" << endl; + cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl; + cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl; + cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl; + + // Display negated NaN. + cout << "negated NaN " << negated_NaN << endl; // "-1.IND" or "-nan". + + // Create a new output locale, and add the nonfinite_num_put facet + std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>); + // and imbue the cout stream with the new locale. + cout.imbue (C99_out_locale); + + // Or for the same effect more concisely: + cout.imbue (locale(locale(), new boost::math::nonfinite_num_put<char>)); + + // Output using the new locale: + cout << "Using C99_out_locale " << endl; + cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl; + cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl; + cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl; + // Expect "inf", "-inf", "nan". + + // Display negated NaN. + cout << "negated NaN " << negated_NaN << endl; // Expect "-nan". + + // Create a string with the expected C99 representation of plus infinity. + std::string inf = "inf"; + { // Try to read an infinity value using the default C locale. + // Create an input stream which will provide "inf" + std::istringstream iss (inf); + + // Create a double ready to take the input, + double infinity; + // and read "inf" from the stringstream: + iss >> infinity; + + // This will not work on all platforms! (Intel-Linux-13.0.1 fails EXIT STATUS: 139) + if (! iss) + { // Reading infinity went wrong! + std::cerr << "C locale input format error!" << std::endl; + } + } // Using default C locale. + + { // Now retry using C99 facets. + // Create a new input locale and add the nonfinite_num_get facet. + std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>); + + // Create an input stream which will provide "inf". + std::istringstream iss (inf); + // Imbue the stream with the C99 input locale. + iss.imbue (C99_in_locale); + + // Create a double ready to take the input, + double infinity; + // and read from the stringstream: + iss >> infinity; + + if (! iss) + { // Reading infinity went wrong! + std::cout << "C99 input format error!" << std::endl; + } + // Expect to get an infinity, which will display still using the C99 locale as "inf" + cout << "infinity in C99 representation is " << infinity << endl; + + // To check, we can switch back to the default C locale. + cout.imbue (default_locale); + cout << "infinity in default C representation is " << infinity << endl; + } // using C99 locale. + + { + // A 'loop-back example, output to a stringstream, and reading it back in. + // Create C99 input and output locales. + std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>); + std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>); + + std::ostringstream oss; + oss.imbue(C99_out_locale); + oss << plus_infinity; + + std::istringstream iss(oss.str()); // So stream contains "inf". + iss.imbue (C99_in_locale); + + std::string s; + + iss >> s; + + cout.imbue(C99_out_locale); + if (oss.str() != s) + { + cout << plus_infinity << " != " << s << " loopback failed!" << endl; + } + else + { + cout << plus_infinity << " == " << s << " as expected." << endl; + } + } + + + // Example varying the width and position of the nonfinite representations. + // With the nonfinite_num_put and _get facets, the width of the output is constant. + + #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available." << endl; + std::streamsize max_digits10 = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL; +#else + // Can use new C++0X max_digits10 (the maximum potentially significant digits). + std::streamsize max_digits10 = std::numeric_limits<double>::max_digits10; +#endif + cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10 << endl; + cout.precision(max_digits10); + + double pi = 3.141592653589793238462643383279502884197169399375105820974944; + // Expect 17 (probably) decimal digits (regardless of locale). + // cout has the default locale. + cout << "pi = " << pi << endl; // pi = 3.1415926535897931 + cout.imbue (C99_out_locale); // Use cout with the C99 locale + // (expect the same output for a double). + cout << "pi = " << pi << endl; // pi = 3.1415926535897931 + + cout << "infinity in C99 representation is " << plus_infinity << endl; + + //int width = 2; // Check effect if width too small is OK. + // (There was a disturbed layout on older MSVC?). + int width = 20; + + // Similarly if we can switch back to the default C locale. + cout.imbue (default_locale); + cout << "infinity in default C representation is " << plus_infinity << endl; + cout << "infinity in default C representation (setw(" << width << ") is |" << setw(width) << plus_infinity <<'|' << endl; + cout << "infinity in default C representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|' << endl; + cout << "infinity in default C representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|' << endl; + + cout.imbue (C99_out_locale); + cout << "infinity in C99 representation (setw(" << width << ") is |" << right << setw(width) << plus_infinity <<'|'<< endl; + cout << "infinity in C99 representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|'<< endl; + cout << "infinity in C99 representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|'<< endl; + + return 0; +} // int main() + +// end of test_nonfinite_num_facets.cpp + +/* + +Output: + +simple_nonfinite_facet.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\nonfinite_facet_simple.exe + Nonfinite_num_facet very simple example. + Using C locale + +std::numeric_limits<double>::infinity() = 1.#INF + -std::numeric_limits<double>::infinity() = -1.#INF + +std::numeric_limits<double>::quiet_NaN () = 1.#QNAN + Using C99_out_locale + +std::numeric_limits<double>::infinity() = inf + -std::numeric_limits<double>::infinity() = -inf + +std::numeric_limits<double>::quiet_NaN () = nan + infinity in C99 representation is inf + infinity in default C representation is 1.#INF + 3 + 3 + inf == inf as expected. + std::numeric_limits<double>::max_digits10 is 17 + pi = 3.1415926535897931 + C locale input format error! + pi = 3.1415926535897931 + infinity in C99 representation is inf + infinity in default C representation is 1.#INF + infinity in default C representation (setw(20) is 1.#INF| + infinity in default C representation (setw(20) is 1.#INF | + infinity in default C representation (setw(20) is 1.#INF| + infinity in C99 representation (setw(20) is inf| + infinity in C99 representation (setw(20) is inf | + infinity in C99 representation (setw(20) is inf| + +*/ diff --git a/src/boost/libs/math/example/nonfinite_facet_sstream.cpp b/src/boost/libs/math/example/nonfinite_facet_sstream.cpp new file mode 100644 index 000000000..826d7f657 --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_facet_sstream.cpp @@ -0,0 +1,132 @@ +// nonfinite_facet_sstream.cpp + +// 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) + +// Copyright (c) 2006 Johan Rade +// Copyright (c) 2011 Paul A. Bristow + +/*! +\file +\brief Examples of nonfinite with output and input facets and stringstreams. + +\detail Construct a new locale with the nonfinite_num_put and nonfinite_num_get +facets and imbue istringstream, ostringstream and stringstreams, +showing output and input (and loopback for the stringstream). + +*/ + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_put; +using boost::math::nonfinite_num_get; + +using boost::math::legacy; + +#include <iostream> +using std::cout; +using std::endl; +#include <locale> +using std::locale; + +#include <sstream> +using std::stringstream; +using std::istringstream; +using std::ostringstream; + +#include <limits> +using std::numeric_limits; + +#include <assert.h> + +int main() +{ + //[nonfinite_facets_sstream_1 + locale old_locale; + locale tmp_locale(old_locale, new nonfinite_num_put<char>); + locale new_locale(tmp_locale, new nonfinite_num_get<char>); + //] [/nonfinite_facets_sstream_1] + + // Note that to add two facets, nonfinite_num_put and nonfinite_num_get, + // you have to add one at a time, using a temporary locale. + + { + ostringstream oss; + oss.imbue(new_locale); + double inf = numeric_limits<double>::infinity(); + oss << inf; // Write out. + cout << "infinity output was " << oss.str() << endl; + BOOST_MATH_ASSERT(oss.str() == "inf"); + } + { + istringstream iss; + iss.str("inf"); + iss.imbue(new_locale); + double inf; + iss >> inf; // Read from "inf" + cout << "Infinity input was " << iss.str() << endl; + BOOST_MATH_ASSERT(inf == numeric_limits<double>::infinity()); + } + + { + //[nonfinite_facets_sstream_2 + stringstream ss; + ss.imbue(new_locale); + double inf = numeric_limits<double>::infinity(); + ss << inf; // Write out. + BOOST_MATH_ASSERT(ss.str() == "inf"); + double r; + ss >> r; // Read back in. + BOOST_MATH_ASSERT(inf == r); // Confirms that the double values really are identical. + + cout << "infinity output was " << ss.str() << endl; + cout << "infinity input was " << r << endl; + // But the string representation of r displayed will be the native type + // because, when it was constructed, cout had NOT been imbued + // with the new locale containing the nonfinite_numput facet. + // So the cout output will be "1.#INF on MS platforms + // and may be "inf" or other string representation on other platforms. + + //] [/nonfinite_facets_sstream_2] + } + + { + stringstream ss; + ss.imbue(new_locale); + + double nan = numeric_limits<double>::quiet_NaN(); + ss << nan; // Write out. + BOOST_MATH_ASSERT(ss.str() == "nan"); + + double v; + ss >> v; // Read back in. + + cout << "NaN output was " << ss.str() << endl; + cout << "NaN input was " << v << endl; + + // assert(nan == v); // Always fails because NaN == NaN fails! + // assert(nan == numeric_limits<double>::quiet_NaN()); asserts! + + // And the string representation will be the native type + // because cout has NOT been imbued with a locale containing + // the nonfinite_numput facet. + // So the output will be "1.#QNAN on MS platforms + // and may be "nan" or other string representation on other platforms. + } + +} // int main() + + +/* +//[nonfinite_facet_sstream_output + +infinity output was inf +Infinity input was inf +infinity output was inf +infinity input was 1.#INF +NaN output was nan +NaN input was 1.#QNAN + +//] [nonfinite_facet_sstream_output] +*/ + diff --git a/src/boost/libs/math/example/nonfinite_legacy.cpp b/src/boost/libs/math/example/nonfinite_legacy.cpp new file mode 100644 index 000000000..94890cbef --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_legacy.cpp @@ -0,0 +1,94 @@ +// nonfinite_legacy.cpp + +// 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) + +// Copyright (c) 2006 Johan Rade +// Copyright (c) 2011 Paul A. Bristow + +/*! +\file +\brief Basic tests of nonfinite loopback with output and input facet. + +\detail Basic loopback test outputs using the so-called 'legacy' facets, +"1.#INF" and "1.#QNAN". + +and reads back in using nonfinite input 'legacy' facet, and +(if possible) checks if loopback OK. + +*/ + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_put; +using boost::math::nonfinite_num_get; + +using boost::math::legacy; + +#include <iostream> +using std::cout; +using std::endl; + +#include <iomanip> +using std::setfill; +using std::setw; + +#include <locale> +using std::locale; + +#include <sstream> +using std::stringstream; +#include <limits> +using std::numeric_limits; + +#include <assert.h> + +int main() +{ + // Create a new locale with both the nonfinite facets. + std::locale new_locale(std::locale(std::locale(), + new boost::math::nonfinite_num_put<char>), + new boost::math::nonfinite_num_get<char>); + + { + stringstream ss; + ss.imbue(new_locale); + double inf = numeric_limits<double>::infinity(); + ss << inf; // Write out. + double r; + ss >> r; // Read back in. + + cout << "infinity output was " << inf << endl; + cout << "infinity input was " << r << endl; + + BOOST_MATH_ASSERT(inf == r); + } + { + stringstream ss; + ss.imbue(new_locale); + + double nan = numeric_limits<double>::quiet_NaN(); + ss << nan; // Write out. + double v; + ss >> v; // Read back in. + + cout << "NaN output was " << nan << endl; + cout << "NaN input was " << v << endl; + + // BOOST_MATH_ASSERT(nan == v); // Always fails because NaN == NaN fails! + // BOOST_MATH_ASSERT(nan == numeric_limits<double>::quiet_NaN()); asserts! + } + +} // int main() + +/* + +Output: + +infinity output was 1.#INF +infinity input was 1.#INF +NaN output was 1.#QNAN +NaN input was 1.#QNAN + +*/ + diff --git a/src/boost/libs/math/example/nonfinite_loopback_ok.cpp b/src/boost/libs/math/example/nonfinite_loopback_ok.cpp new file mode 100644 index 000000000..4906c88e1 --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_loopback_ok.cpp @@ -0,0 +1,89 @@ +// 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) + +// Copyright (c) 2006 Johan Rade +// Copyright (c) 2011 Paul A. Bristow + +/*! +\file +\brief Basic tests of nonfinite loopback. + +\detail Basic loopback test outputs using nonfinite facets +(output and input) and reads back in, and checks if loopback OK. + +Expected to work portably on all platforms. + +*/ + +#ifdef _MSC_VER +# pragma warning(disable : 4702) +# pragma warning(disable : 4127) // conditional expression is constant. +#endif + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_get; +using boost::math::nonfinite_num_put; + +#include <iostream> +using std::cout; +using std::endl; + +#include <locale> +using std::locale; + +#include <sstream> +using std::stringstream; +#include <limits> +using std::numeric_limits; + +#include <assert.h> + +int main() +{ + + if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + //locale old_locale; // Current global locale. + // Create tmp_locale and store the output nonfinite_num_put facet in it. + //locale tmp_locale(old_locale, new nonfinite_num_put<char>); + // Create new_locale and store the input nonfinite_num_get facet in it. + //locale new_locale(tmp_locale, new nonfinite_num_get<char>); + // Can only add one facet at a time, hence need a tmp_locale, + // unless we write: + + std::locale new_locale(std::locale(std::locale(std::locale(), + new boost::math::nonfinite_num_put<char>), + new boost::math::nonfinite_num_get<char>)); + + stringstream ss; // Both input and output, so need both get and put facets. + + ss.imbue(new_locale); + + double inf = numeric_limits<double>::infinity(); + ss << inf; // Write out. + double r; + ss >> r; // Read back in. + + BOOST_MATH_ASSERT(inf == r); // OK MSVC <= 10.0! + +} // int main() + +/* + +Output: + +nonfinite_loopback_ok.vcxproj -> J:\Cpp\fp_facet\fp_facet\Debug\nonfinite_loopback_ok.exe + +*/ + + diff --git a/src/boost/libs/math/example/nonfinite_num_facet.cpp b/src/boost/libs/math/example/nonfinite_num_facet.cpp new file mode 100644 index 000000000..80e4e8140 --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_num_facet.cpp @@ -0,0 +1,291 @@ +/** nonfinite_num_facet.cpp + * + * Copyright (c) 2011 Francois Mauger + * Copyright (c) 2011 Paul A. Bristow + * + * 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) + * + * This simple program illustrates how to use the + * `boost/math/nonfinite_num_facets.hpp' material from the original + * Floating Point Utilities contribution by Johan Rade. + * Floating Point Utility library has been accepted into Boost, + * but the utilities have been/will be incorporated into Boost.Math library. + * +\file + +\brief A fairly simple example of using non_finite_num facet for +C99 standard output of infinity and NaN. + +\detail This program illustrates how to use the + `boost/math/nonfinite_num_facets.hpp' material from the original + Floating Point Utilities contribution by Johan Rade. + Floating Point Utility library has been accepted into Boost, + but the utilities have been/will be incorporated into Boost.Math library. + + Based on an example from Francois Mauger. + + Double and float variables are assigned ordinary finite values (pi), + and nonfinite like infinity and NaN. + + These values are then output and read back in, and then redisplayed. + +*/ + +#ifdef _MSC_VER +# pragma warning(disable : 4127) // conditional expression is constant. +#endif + +#include <iostream> +#include <iomanip> +using std::cout; +using std::endl; + +#include <limits> // numeric_limits +using std::numeric_limits; + +#include <boost/cstdint.hpp> + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> + +static const char sep = ','; // Separator of bracketed float and double values. + +// Use max_digits10 (or equivalent) to obtain +// all potentially significant decimal digits for the floating-point types. + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + std::streamsize max_digits10_float = 2 + std::numeric_limits<float>::digits * 30103UL / 100000UL; + std::streamsize max_digits10_double = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL; +#else + // Can use new C++0X max_digits10 (the maximum potentially significant digits). + std::streamsize max_digits10_float = std::numeric_limits<float>::max_digits10; + std::streamsize max_digits10_double = std::numeric_limits<double>::max_digits10; +#endif + + +/* A class with a float and a double */ +struct foo +{ + foo () : fvalue (3.1415927F), dvalue (3.1415926535897931) + { + } + // Set both the values to -infinity : + void minus_infinity () + { + fvalue = -std::numeric_limits<float>::infinity (); + dvalue = -std::numeric_limits<double>::infinity (); + return; + } + // Set the values to +infinity : + void plus_infinity () + { + fvalue = +std::numeric_limits<float>::infinity (); + dvalue = +std::numeric_limits<double>::infinity (); + return; + } + // Set the values to NaN : + void nan () + { + fvalue = +std::numeric_limits<float>::quiet_NaN (); + dvalue = +std::numeric_limits<double>::quiet_NaN (); + return; + } + // Print a foo: + void print (std::ostream & a_out, const std::string & a_title) + { + if (a_title.empty ()) a_out << "foo"; + else a_out << a_title; + a_out << " : " << std::endl; + a_out << "|-- " << "fvalue = "; + + a_out.precision (max_digits10_float); + a_out << fvalue << std::endl; + a_out << "`-- " << "dvalue = "; + a_out.precision (max_digits10_double); + a_out << dvalue << std::endl; + return; + } + + // I/O operators for a foo structure of a float and a double : + friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo); + friend std::istream & operator>> (std::istream & a_in, foo & a_foo); + + // Attributes : + float fvalue; // Single precision floating number. + double dvalue; // Double precision floating number. +}; + +std::ostream & operator<< (std::ostream & a_out, const foo & a_foo) +{ // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)" + a_out.precision (max_digits10_float); + a_out << "(" << a_foo.fvalue << sep ; + a_out.precision (max_digits10_double); + a_out << a_foo.dvalue << ")"; + return a_out; +} + +std::istream & operator>> (std::istream & a_in, foo & a_foo) +{ // Input bracketed floating-point values into a foo structure, + // for example from "(3.1415927,3.1415926535897931)" + char c = 0; + a_in.get (c); + if (c != '(') + { + std::cerr << "ERROR: operator>> No ( " << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + float f; + a_in >> std::ws >> f; + if (! a_in) + { + return a_in; + } + a_in >> std::ws; + a_in.get (c); + if (c != sep) + { + std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl; + std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + double d; + a_in >> std::ws >> d; + if (! a_in) + { + return a_in; + } + a_in >> std::ws; + a_in.get (c); + if (c != ')') + { + std::cerr << "ERROR: operator>> No ) " << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + a_foo.fvalue = f; + a_foo.dvalue = d; + return a_in; +} // std::istream & operator>> (std::istream & a_in, foo & a_foo) + +int main () +{ + std::cout << "nonfinite_num_facet simple example." << std::endl; + + if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either:" + "\n we'll have to calculate our own version." << endl; +#endif + std::cout << "std::numeric_limits<float>::max_digits10 is " << max_digits10_float << endl; + std::cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10_double << endl; + + std::locale the_default_locale (std::locale::classic ()); + + { + std::cout << "Write to a string buffer (using default locale) :" << std::endl; + foo f0; // pi + foo f1; f1.minus_infinity (); + foo f2; f2.plus_infinity (); + foo f3; f3.nan (); + + f0.print (std::cout, "f0"); // pi + f1.print (std::cout, "f1"); // +inf + f2.print (std::cout, "f2"); // -inf + f3.print (std::cout, "f3"); // NaN + + std::ostringstream oss; + std::locale C99_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>); + oss.imbue (C99_out_locale); + oss.precision (15); + oss << f0 << f1 << f2 << f3; + std::cout << "Output in C99 format is: \"" << oss.str () << "\"" << std::endl; + std::cout << "Output done." << std::endl; + } + + { + std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"; // C99 format + // Must have correct separator! + std::cout << "Read C99 format from a string buffer containing \"" << the_string << "\""<< std::endl; + + std::locale C99_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>); + std::istringstream iss (the_string); + iss.imbue (C99_in_locale); + + foo f0, f1, f2, f3; + iss >> f0 >> f1 >> f2 >> f3; + if (! iss) + { + std::cerr << "Input Format error !" << std::endl; + } + else + { + std::cerr << "Input OK." << std::endl; + cout << "Display in default locale format " << endl; + f0.print (std::cout, "f0"); + f1.print (std::cout, "f1"); + f2.print (std::cout, "f2"); + f3.print (std::cout, "f3"); + } + std::cout << "Input done." << std::endl; + } + + std::cout << "End nonfinite_num_facet.cpp" << std::endl; + return 0; +} // int main() + + // end of test_nonfinite_num_facets.cpp + +/* + +Output: + +nonfinite_num_facet simple example. + std::numeric_limits<float>::max_digits10 is 8 + std::numeric_limits<double>::max_digits10 is 17 + Write to a string buffer (using default locale) : + f0 : + |-- fvalue = 3.1415927 + `-- dvalue = 3.1415926535897931 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Output in C99 format is: "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)" + Output done. + Read C99 format from a string buffer containing "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)" + Display in default locale format + f0 : + |-- fvalue = 3.1415927 + `-- dvalue = 3.1415926535897931 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Input done. + End nonfinite_num_facet.cpp + +*/ diff --git a/src/boost/libs/math/example/nonfinite_num_facet_serialization.cpp b/src/boost/libs/math/example/nonfinite_num_facet_serialization.cpp new file mode 100644 index 000000000..e2972a10f --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_num_facet_serialization.cpp @@ -0,0 +1,433 @@ +/** nonfinite_num_facet_serialization.cpp + * + * Copyright (c) 2011 Francois Mauger + * Copyright (c) 2011 Paul A. Bristow + * + * 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) + * + * This sample program by Francois Mauger illustrates how to use the + * `boost/math/nonfinite_num_facets.hpp' material from the original + * Floating Point Utilities contribution by Johan Rade. Here it is + * shown how non finite floating number can be serialized and + * deserialized from I/O streams and/or Boost text/XML archives. It + * produces two archives stored in `test.txt' and `test.xml' files. + * + * Tested with Boost 1.44, gcc 4.4.1, Linux/i686 (32bits). + * Tested with Boost.1.46.1 MSVC 10.0 32 bit. + */ + +#ifdef _MSC_VER +# pragma warning(push) +//# pragma warning(disable : 4100) // unreferenced formal parameter. +#endif + +#include <iostream> +#include <sstream> +#include <fstream> +#include <limits> + +#include <boost/cstdint.hpp> +#include <boost/serialization/nvp.hpp> +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/archive/xml_oarchive.hpp> +#include <boost/archive/xml_iarchive.hpp> +#include <boost/archive/codecvt_null.hpp> + +// from the Floating Point Utilities : +#include <boost/math/special_functions/nonfinite_num_facets.hpp> + +static const char sep = ','; // Separator of bracketed float and double values. + +// Use max_digits10 (or equivalent) to obtain +// all potentially significant decimal digits for the floating-point types. + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + std::streamsize max_digits10_float = 2 + std::numeric_limits<float>::digits * 30103UL / 100000UL; + std::streamsize max_digits10_double = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL; +#else + // Can use new C++0X max_digits10 (the maximum potentially significant digits). + std::streamsize max_digits10_float = std::numeric_limits<float>::max_digits10; + std::streamsize max_digits10_double = std::numeric_limits<double>::max_digits10; +#endif + + +/* A class with a float and a double */ +struct foo +{ + foo () : fvalue (3.1415927F), dvalue (3.1415926535897931) + { // Construct using 32 and 64-bit max_digits10 decimal digits value of pi. + } + // Set the values at -infinity : + void minus_infinity () + { + fvalue = -std::numeric_limits<float>::infinity (); + dvalue = -std::numeric_limits<double>::infinity (); + return; + } + // Set the values at +infinity : + void plus_infinity () + { + fvalue = +std::numeric_limits<float>::infinity (); + dvalue = +std::numeric_limits<double>::infinity (); + return; + } + // Set the values at NaN : + void nan () + { + fvalue = +std::numeric_limits<float>::quiet_NaN (); + dvalue = +std::numeric_limits<double>::quiet_NaN (); + return; + } + // Print : + void print (std::ostream & a_out, const std::string & a_title) + { + if (a_title.empty ()) a_out << "foo"; + else a_out << a_title; + a_out << " : " << std::endl; + a_out << "|-- " << "fvalue = "; + a_out.precision (7); + a_out << fvalue << std::endl; + a_out << "`-- " << "dvalue = "; + a_out.precision (15); + a_out << dvalue << std::endl; + return; + } + + // I/O operators : + friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo); + friend std::istream & operator>> (std::istream & a_in, foo & a_foo); + + // Boost serialization : + template <class Archive> + void serialize (Archive & ar, int /*version*/) + { + ar & BOOST_SERIALIZATION_NVP (fvalue); + ar & BOOST_SERIALIZATION_NVP (dvalue); + return; + } + + // Attributes : + float fvalue; // Single precision floating-point number. + double dvalue; // Double precision floating-point number. +}; + +std::ostream & operator<< (std::ostream & a_out, const foo & a_foo) +{ // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)" + a_out.precision (max_digits10_float); + a_out << "(" << a_foo.fvalue << sep ; + a_out.precision (max_digits10_double); + a_out << a_foo.dvalue << ")"; + return a_out; +} + +std::istream & operator>> (std::istream & a_in, foo & a_foo) +{ // Input bracketed floating-point values into a foo structure, + // for example from "(3.1415927,3.1415926535897931)" + char c = 0; + a_in.get (c); + if (c != '(') + { + std::cerr << "ERROR: operator>> No ( " << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + float f; + a_in >> std::ws >> f; + if (! a_in) + { + return a_in; + } + a_in >> std::ws; + a_in.get (c); + if (c != sep) + { + std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl; + std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + double d; + a_in >> std::ws >> d; + if (! a_in) + { + return a_in; + } + a_in >> std::ws; + a_in.get (c); + if (c != ')') + { + std::cerr << "ERROR: operator>> No ) " << std::endl; + a_in.setstate(std::ios::failbit); + return a_in; + } + a_foo.fvalue = f; + a_foo.dvalue = d; + return a_in; +} + +int main (void) +{ + std::clog << std::endl + << "Nonfinite_serialization.cpp' example program." << std::endl; + +#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS + std::cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either," + "using our own version instead." << std::endl; +#endif + std::cout << "std::numeric_limits<float>::max_digits10 is " << max_digits10_float << std::endl; + std::cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10_double << std::endl; + + std::locale the_default_locale (std::locale::classic (), + new boost::archive::codecvt_null<char>); + + // Demonstrate use of nonfinite facets with stringstreams. + { + std::clog << "Construct some foo structures with a finite and nonfinites." << std::endl; + foo f0; + foo f1; f1.minus_infinity (); + foo f2; f2.plus_infinity (); + foo f3; f3.nan (); + // Display them. + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + std::clog << " Write to a string buffer." << std::endl; + + std::ostringstream oss; + std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>); + oss.imbue (the_out_locale); + oss.precision (max_digits10_double); + oss << f0 << f1 << f2 << f3; + std::clog << "Output is: `" << oss.str () << "'" << std::endl; + std::clog << "Done output to ostringstream." << std::endl; + } + + { + std::clog << "Read foo structures from a string buffer." << std::endl; + + std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"; + std::clog << "Input is: `" << the_string << "'" << std::endl; + + std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>); + std::istringstream iss (the_string); + iss.imbue (the_in_locale); + + foo f0, f1, f2, f3; + iss >> f0 >> f1 >> f2 >> f3; + if (! iss) + { + std::cerr << "Format error !" << std::endl; + } + else + { + std::cerr << "Read OK." << std::endl; + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + } + std::clog << "Done input from istringstream." << std::endl; + } + + { // Demonstrate use of nonfinite facets for Serialization with Boost text archives. + std::clog << "Serialize (using Boost text archive)." << std::endl; + // Construct some foo structures with a finite and nonfinites. + foo f0; + foo f1; f1.minus_infinity (); + foo f2; f2.plus_infinity (); + foo f3; f3.nan (); + // Display them. + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + + std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>); + // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). + std::ofstream fout ("./.temps/nonfinite_archive_test.txt"); + fout.imbue (the_out_locale); + boost::archive::text_oarchive toar (fout, boost::archive::no_codecvt); + // Write to archive. + toar & f0; + toar & f1; + toar & f2; + toar & f3; + std::clog << "Done." << std::endl; + } + + { + std::clog << "Deserialize (Boost text archive)..." << std::endl; + std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>); + // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). + std::ifstream fin ("./.temps/nonfinite_archive_test.txt"); + fin.imbue (the_in_locale); + boost::archive::text_iarchive tiar (fin, boost::archive::no_codecvt); + foo f0, f1, f2, f3; + // Read from archive. + tiar & f0; + tiar & f1; + tiar & f2; + tiar & f3; + // Display foos. + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + + std::clog << "Done." << std::endl; + } + + { // Demonstrate use of nonfinite facets for Serialization with Boost XML Archive. + std::clog << "Serialize (Boost XML archive)..." << std::endl; + // Construct some foo structures with a finite and nonfinites. + foo f0; + foo f1; f1.minus_infinity (); + foo f2; f2.plus_infinity (); + foo f3; f3.nan (); + // Display foos. + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + + std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>); + // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). + std::ofstream fout ("./.temps/nonfinite_XML_archive_test.txt"); + fout.imbue (the_out_locale); + boost::archive::xml_oarchive xoar (fout, boost::archive::no_codecvt); + + xoar & BOOST_SERIALIZATION_NVP (f0); + xoar & BOOST_SERIALIZATION_NVP (f1); + xoar & BOOST_SERIALIZATION_NVP (f2); + xoar & BOOST_SERIALIZATION_NVP (f3); + std::clog << "Done." << std::endl; + } + + { + std::clog << "Deserialize (Boost XML archive)..." << std::endl; + std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>); + // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). + std::ifstream fin ("./.temps/nonfinite_XML_archive_test.txt"); // Previously written above. + fin.imbue (the_in_locale); + boost::archive::xml_iarchive xiar (fin, boost::archive::no_codecvt); + foo f0, f1, f2, f3; + + xiar & BOOST_SERIALIZATION_NVP (f0); + xiar & BOOST_SERIALIZATION_NVP (f1); + xiar & BOOST_SERIALIZATION_NVP (f2); + xiar & BOOST_SERIALIZATION_NVP (f3); + + f0.print (std::clog, "f0"); + f1.print (std::clog, "f1"); + f2.print (std::clog, "f2"); + f3.print (std::clog, "f3"); + + std::clog << "Done." << std::endl; + } + + std::clog << "End nonfinite_serialization.cpp' example program." << std::endl; + return 0; +} + +/* + +Output: + + Nonfinite_serialization.cpp' example program. + std::numeric_limits<float>::max_digits10 is 8 + std::numeric_limits<double>::max_digits10 is 17 + Construct some foo structures with a finite and nonfinites. + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Write to a string buffer. + Output is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)' + Done output to ostringstream. + Read foo structures from a string buffer. + Input is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)' + Read OK. + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Done input from istringstream. + Serialize (using Boost text archive). + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Done. + Deserialize (Boost text archive)... + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Done. + Serialize (Boost XML archive)... + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Done. + Deserialize (Boost XML archive)... + f0 : + |-- fvalue = 3.141593 + `-- dvalue = 3.14159265358979 + f1 : + |-- fvalue = -1.#INF + `-- dvalue = -1.#INF + f2 : + |-- fvalue = 1.#INF + `-- dvalue = 1.#INF + f3 : + |-- fvalue = 1.#QNAN + `-- dvalue = 1.#QNAN + Done. + End nonfinite_serialization.cpp' example program. + + */ diff --git a/src/boost/libs/math/example/nonfinite_num_facet_trap.cpp b/src/boost/libs/math/example/nonfinite_num_facet_trap.cpp new file mode 100644 index 000000000..9a4b2d58e --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_num_facet_trap.cpp @@ -0,0 +1,115 @@ + +/** nonfinite_num_facet_trap.cpp +* +* Copyright (c) 2012 Paul A. Bristow +* +* 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) +* +* This very simple program illustrates how to use the +* `boost/math/nonfinite_num_facets.hpp` trapping output of infinity and/or NaNs. +* +\file + +\brief A very simple example of using non_finite_num facet for +trapping output of infinity and/or NaNs. + +\note To actually get an exception throw by the iostream library +one must enable exceptions. + `oss.exceptions(std::ios_base::failbit | std::ios_base::badbit);` +\note Which bit is set is implementation dependent, so enable exceptions for both. + +This is a fairly brutal method of catching nonfinites on output, +but may suit some applications. + +*/ + +#ifdef _MSC_VER +# pragma warning(disable : 4127) // conditional expression is constant. +// assumes C++ exceptions enabled /EHsc +#endif + +#include <boost/cstdint.hpp> +#include <boost/math/special_functions/nonfinite_num_facets.hpp> + +#include <iostream> +#include <iomanip> +using std::cout; +using std::endl; +using std::hex; +#include <exception> +#include <limits> // numeric_limits +using std::numeric_limits; + +int main() +{ + using namespace boost::math; + + std::cout << "nonfinite_num_facet_trap.cpp" << std::endl; + + const double inf = +std::numeric_limits<double>::infinity (); + const double nan = +std::numeric_limits<double>::quiet_NaN (); + + { // Output infinity and NaN with default flags (no trapping). + std::ostringstream oss; + std::locale default_locale (std::locale::classic ()); + std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>); + oss.imbue (C99_out_locale); + oss.exceptions(std::ios_base::failbit | std::ios_base::badbit); + oss << inf << ' ' << nan; + cout << "oss.rdstate() = " << hex << oss.rdstate() << endl; // 0 + cout << "os.str() = " << oss.str() << endl; // os.str() = inf nan + } + + try + { // // Output infinity with flags set to trap and catch any infinity. + std::ostringstream oss; + std::locale default_locale (std::locale::classic ()); + std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>(trap_infinity)); + oss.imbue (C99_out_locale); + oss.exceptions(std::ios_base::failbit | std::ios_base::badbit); + // Note that which bit is set is implementation dependent, so enable exceptions for both. + oss << inf; + cout << "oss.rdstate() = " << hex << oss.rdstate() << endl; + cout << "oss.str() = " << oss.str() << endl; + } + catch(const std::ios_base::failure& e) + { // Expect "Infinity". + std::cout << "\n""Message from thrown exception was: " << e.what() << std::endl; + } + + try + { // // Output NaN with flags set to catch any NaNs. + std::ostringstream oss; + std::locale default_locale (std::locale::classic ()); + std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>(trap_nan)); + oss.imbue (C99_out_locale); + oss.exceptions(std::ios_base::failbit | std::ios_base::badbit); + // Note that which bit is set is implementation dependent, so enable exceptions for both. + oss << nan; + cout << "oss.str() = " << oss.str() << endl; + } + catch(const std::ios_base::failure& e) + { // Expect "Infinity". + std::cout << "\n""Message from thrown exception was: " << e.what() << std::endl; + } + + + return 0; // end of nonfinite_num_facet_trap.cpp +} // int main() + + +/* + +Output: + + nonfinite_num_facet_trap.cpp + oss.rdstate() = 0 + os.str() = inf nan + + Message from thrown exception was: Infinity + + Message from thrown exception was: NaN + +*/ diff --git a/src/boost/libs/math/example/nonfinite_serialization_archives.cpp b/src/boost/libs/math/example/nonfinite_serialization_archives.cpp new file mode 100644 index 000000000..0cb53ff0c --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_serialization_archives.cpp @@ -0,0 +1,136 @@ +/** nonfinite_serialization_archives.cpp +* +* Copyright (c) 2011 Paul A. Bristow +* +* 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) +* +* This very simple program illustrates how to use the +* `boost/math/nonfinite_num_facets.hpp' to obtain C99 +* representation of infinity and NaN. +* From the original Floating Point Utilities contribution by Johan Rade. +* Floating Point Utility library has been accepted into Boost, +* but the utilities are incorporated into Boost.Math library. +* +\file + +\brief A simple example of using non_finite_num facet for +C99 standard output of infinity and NaN in serialization archives. + +\detail This example shows how to create a C99 non-finite locale, +and imbue input and output streams with the non_finite_num put and get facets. +This allow output and input of infinity and NaN in a Standard portable way, +This permits 'loop-back' of output back into input (and portably across different system too). +This is particularly useful when used with Boost.Serialization so that non-finite NaNs and infinity +values in text and xml archives can be handled correctly and portably. + +*/ + + +#ifdef _MSC_VER +# pragma warning(disable : 4127) // conditional expression is constant. +#endif + + +#include <boost/archive/text_oarchive.hpp> +using boost::archive::text_oarchive; +#include <boost/archive/codecvt_null.hpp> +using boost::archive::codecvt_null; +using boost::archive::no_codecvt; + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_get; +using boost::math::nonfinite_num_put; + +#include <iostream> +using std::cout; +using std::endl; +using std::cerr; + +#include <iomanip> +using std::setw; +using std::left; +using std::right; +using std::internal; + +#include <string> +using std::string; + +#include <sstream> +using std::istringstream; + +#include <fstream> +using std::ofstream; + +#include <limits> +using std::numeric_limits; + +#include <locale> +using std::locale; + + +/* +Use with serialization archives. + +It is important that the same locale is used +when an archive is saved and when it is loaded. +Otherwise, loading the archive may fail. + +By default, archives are saved and loaded with a classic C locale with a +`boost::archive::codecvt_null` facet added. +Normally you do not have to worry about that. +The constructors for the archive classes, as a side-effect, +imbue the stream with such a locale. + +However, if you want to use the facets `nonfinite_num_put` and `nonfinite_num_get` +with archives,`then you have to manage the locale manually. + +That is done by calling the archive constructor with the flag `boost::archive::no_codecvt`. +Then the archive constructor will not imbue the stream with a new locale. + +The following code shows how to use `nonfinite_num_put` with a `text_oarchive`: + +*/ + +int main() +{ + + if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + + locale default_locale(locale::classic(), new boost::archive::codecvt_null<char>); + // codecvt_null so the archive constructor will not imbue the stream with a new locale. + + locale my_locale(default_locale, new nonfinite_num_put<char>); + // Add nonfinite_num_put facet to locale. + + // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too). + ofstream ofs("./.temps/test.txt"); + ofs.imbue(my_locale); + + boost::archive::text_oarchive oa(ofs, no_codecvt); + + double x = numeric_limits<double>::infinity(); + oa & x; + +} // int main() + + +/* The same method works with nonfinite_num_get and text_iarchive. + +If you use the trap_infinity and trap_nan flags with a serialization archive, +then you must set the exception mask of the stream. +Serialization archives do not check the stream state. + + +*/ diff --git a/src/boost/libs/math/example/nonfinite_signaling_NaN.cpp b/src/boost/libs/math/example/nonfinite_signaling_NaN.cpp new file mode 100644 index 000000000..2e6e1fde3 --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_signaling_NaN.cpp @@ -0,0 +1,189 @@ +// 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) + +// Copyright (c) 2006 Johan Rade +// Copyright (c) 2011 Paul A. Bristow + +/*! +\file +\brief Tests of nonfinite signaling NaN loopback. + +\detail nonfinite signaling NaN +test outputs using nonfinite facets +(output and input) and reads back in, and checks if loopback OK. + +Not expected to work on all platforms (if any). But shows that on MSVC, +this legacy locale can ensure a consistent quiet NaN input from representations +"1.#QNAN", "1.#SNAN" and "1.#IND" + +*/ + +#ifdef _MSC_VER +# pragma warning(disable : 4702) +#endif + +#include <boost/math/special_functions/nonfinite_num_facets.hpp> +using boost::math::nonfinite_num_get; +using boost::math::nonfinite_num_put; + +#include <iostream> +using std::cout; +using std::endl; + +#include <locale> +using std::locale; + +#include <string> +using std::string; + +#include <sstream> + using std::stringstream; + using std::istringstream; + +#include <limits> +using std::numeric_limits; + +int main() +{ + if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) + { + std::cout << "Infinity not supported on this platform." << std::endl; + return 0; + } + + if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) + { + std::cout << "NaN not supported on this platform." << std::endl; + return 0; + } + + locale default_locale; // Current global locale. + // Try to use the default locale first. + // On MSVC this doesn't work. + + { // Try Quiet NaN + stringstream ss; // Both input and output. + ss.imbue(default_locale); // Redundant, of course. + string infs; + if(numeric_limits<double>::has_quiet_NaN) + { // Make sure quiet NaN is specialised for type double. + double qnan = numeric_limits<double>::quiet_NaN(); + ss << qnan; // Output quiet_NaN. + infs = ss.str(); // + } + else + { // Need to provide a suitable string for quiet NaN. + infs = "1.#QNAN"; + ss << infs; + } + double r; + ss >> r; // Read back in. + + cout << "quiet_NaN output was " << infs << endl; // "1.#QNAN" + cout << "quiet_NaN input was " << r << endl; // "1" + } + +#if (!defined BOOST_BORLANDC && !defined BOOST_CODEGEARC) + // These compilers trap when trying to create a signaling_NaN! + { // Try Signaling NaN + stringstream ss; // Both input and output. + ss.imbue(default_locale); // Redundant, of course. + string infs; + if(numeric_limits<double>::has_signaling_NaN) + { // Make sure signaling NaN is specialised for type double. + double qnan = numeric_limits<double>::signaling_NaN(); + ss << qnan; // Output signaling_NaN. + infs = ss.str(); // + } + else + { // Need to provide a suitable string for signaling NaN. + infs = "1.#SNAN"; + ss << infs; + } + double r; + ss >> r; // Read back in. + + cout << "signaling_NaN output was " << infs << endl; // "1.#QNAN" (or "1.#SNAN"?) + cout << "signaling_NaN input was " << r << endl; // "1" + } +#endif // Not Borland or CodeGear. + + // Create legacy_locale and store the nonfinite_num_get facet (with legacy flag) in it. + locale legacy_locale(default_locale, new nonfinite_num_get<char>(boost::math::legacy)); + // Note that the legacy flag has no effect on the nonfinite_num_put output facet. + + cout << "Use legacy locale." << endl; + + { // Try infinity. + stringstream ss; // Both input and output. + ss.imbue(legacy_locale); + string infs; + if(numeric_limits<double>::has_infinity) + { // Make sure infinity is specialised for type double. + double inf = numeric_limits<double>::infinity(); + ss << inf; // Output infinity. + infs = ss.str(); // + } + else + { // Need to provide a suitable string for infinity. + infs = "1.#INF"; + ss << infs; + } + double r; + ss >> r; // Read back in. + + cout << "infinity output was " << infs << endl; // "1.#INF" + cout << "infinity input was " << r << endl; // "1.#INF" + } + + { // Try input of "1.#SNAN". + //double inf = numeric_limits<double>::signaling_NaN(); // Assigns "1.#QNAN" on MSVC. + // So must use explicit string "1.#SNAN" instead. + stringstream ss; // Both input and output. + ss.imbue(legacy_locale); + string s = "1.#SNAN"; + + ss << s; // Write out. + double r; + + ss >> r; // Read back in. + + cout << "SNAN output was " << s << endl; // "1.#SNAN" + cout << "SNAN input was " << r << endl; // "1.#QNAN" + } + + { // Try input of "1.#IND" . + stringstream ss; // Both input and output. + ss.imbue(legacy_locale); + string s = "1.#IND"; + ss << s; // Write out. + double r; + ss >> r; // Read back in. + + cout << "IND output was " << s << endl; // "1.#IND" + cout << "IND input was " << r << endl; // "1.#QNAN" + } + +} // int main() + +/* + +Output: + nonfinite_signaling_NaN.vcxproj -> J:\Cpp\fp_facet\fp_facet\Debug\nonfinite_signaling_NaN.exe + + quiet_NaN output was 1.#QNAN + quiet_NaN input was 1 + signaling_NaN output was 1.#QNAN + signaling_NaN input was 1 + Use legacy locale. + infinity output was 1.#INF + infinity input was 1.#INF + SNAN output was 1.#SNAN + SNAN input was 1.#QNAN + IND output was 1.#IND + IND input was 1.#QNAN + + +*/ + diff --git a/src/boost/libs/math/example/normal_misc_examples.cpp b/src/boost/libs/math/example/normal_misc_examples.cpp new file mode 100644 index 000000000..3d0f3acff --- /dev/null +++ b/src/boost/libs/math/example/normal_misc_examples.cpp @@ -0,0 +1,509 @@ +// normal_misc_examples.cpp + +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +// Example of using normal distribution. + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[normal_basic1 +/*` +First we need some includes to access the normal distribution +(and some std output of course). +*/ + +#include <boost/math/distributions/normal.hpp> // for normal_distribution + using boost::math::normal; // typedef provides default type is double. + +#include <iostream> + using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + using std::setw; using std::setprecision; +#include <limits> + using std::numeric_limits; + +int main() +{ + cout << "Example: Normal distribution, Miscellaneous Applications."; + + try + { + { // Traditional tables and values. +/*`Let's start by printing some traditional tables. +*/ + double step = 1.; // in z + double range = 4; // min and max z = -range to +range. + int precision = 17; // traditional tables are only computed to much lower precision. + // but std::numeric_limits<double>::max_digits10; on new Standard Libraries gives + // 17, the maximum number of digits that can possibly be significant. + // std::numeric_limits<double>::digits10; == 15 is number of guaranteed digits, + // the other two digits being 'noisy'. + + // Construct a standard normal distribution s + normal s; // (default mean = zero, and standard deviation = unity) + cout << "Standard normal distribution, mean = "<< s.mean() + << ", standard deviation = " << s.standard_deviation() << endl; + +/*` First the probability distribution function (pdf). +*/ + cout << "Probability distribution function values" << endl; + cout << " z " " pdf " << endl; + cout.precision(5); + for (double z = -range; z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(12) << pdf(s, z) << endl; + } + cout.precision(6); // default + /*`And the area under the normal curve from -[infin] up to z, + the cumulative distribution function (cdf). +*/ + // For a standard normal distribution + cout << "Standard normal mean = "<< s.mean() + << ", standard deviation = " << s.standard_deviation() << endl; + cout << "Integral (area under the curve) from - infinity up to z " << endl; + cout << " z " " cdf " << endl; + for (double z = -range; z < range + step; z += step) + { + cout << left << setprecision(3) << setw(6) << z << " " + << setprecision(precision) << setw(12) << cdf(s, z) << endl; + } + cout.precision(6); // default + +/*`And all this you can do with a nanoscopic amount of work compared to +the team of *human computers* toiling with Milton Abramovitz and Irene Stegen +at the US National Bureau of Standards (now [@http://www.nist.gov NIST]). +Starting in 1938, their "Handbook of Mathematical Functions with Formulas, Graphs and Mathematical Tables", +was eventually published in 1964, and has been reprinted numerous times since. +(A major replacement is planned at [@http://dlmf.nist.gov Digital Library of Mathematical Functions]). + +Pretty-printing a traditional 2-dimensional table is left as an exercise for the student, +but why bother now that the Math Toolkit lets you write +*/ + double z = 2.; + cout << "Area for z = " << z << " is " << cdf(s, z) << endl; // to get the area for z. +/*` +Correspondingly, we can obtain the traditional 'critical' values for significance levels. +For the 95% confidence level, the significance level usually called alpha, +is 0.05 = 1 - 0.95 (for a one-sided test), so we can write +*/ + cout << "95% of area has a z below " << quantile(s, 0.95) << endl; + // 95% of area has a z below 1.64485 +/*`and a two-sided test (a comparison between two levels, rather than a one-sided test) + +*/ + cout << "95% of area has a z between " << quantile(s, 0.975) + << " and " << -quantile(s, 0.975) << endl; + // 95% of area has a z between 1.95996 and -1.95996 +/*` + +First, define a table of significance levels: these are the probabilities +that the true occurrence frequency lies outside the calculated interval. + +It is convenient to have an alpha level for the probability that z lies outside just one standard deviation. +This will not be some nice neat number like 0.05, but we can easily calculate it, +*/ + double alpha1 = cdf(s, -1) * 2; // 0.3173105078629142 + cout << setprecision(17) << "Significance level for z == 1 is " << alpha1 << endl; +/*` + and place in our array of favorite alpha values. +*/ + double alpha[] = {0.3173105078629142, // z for 1 standard deviation. + 0.20, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; +/*` + +Confidence value as % is (1 - alpha) * 100 (so alpha 0.05 == 95% confidence) +that the true occurrence frequency lies *inside* the calculated interval. + +*/ + cout << "level of significance (alpha)" << setprecision(4) << endl; + cout << "2-sided 1 -sided z(alpha) " << endl; + for (unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + cout << setw(15) << alpha[i] << setw(15) << alpha[i] /2 << setw(10) << quantile(complement(s, alpha[i]/2)) << endl; + // Use quantile(complement(s, alpha[i]/2)) to avoid potential loss of accuracy from quantile(s, 1 - alpha[i]/2) + } + cout << endl; + +/*`Notice the distinction between one-sided (also called one-tailed) +where we are using a > *or* < test (and not both) +and considering the area of the tail (integral) from z up to +[infin], +and a two-sided test where we are using two > *and* < tests, and thus considering two tails, +from -[infin] up to z low and z high up to +[infin]. + +So the 2-sided values alpha[i] are calculated using alpha[i]/2. + +If we consider a simple example of alpha = 0.05, then for a two-sided test, +the lower tail area from -[infin] up to -1.96 is 0.025 (alpha/2) +and the upper tail area from +z up to +1.96 is also 0.025 (alpha/2), +and the area between -1.96 up to 12.96 is alpha = 0.95. +and the sum of the two tails is 0.025 + 0.025 = 0.05, + +*/ +//] [/[normal_basic1] + +//[normal_basic2 + +/*`Armed with the cumulative distribution function, we can easily calculate the +easy to remember proportion of values that lie within 1, 2 and 3 standard deviations from the mean. + +*/ + cout.precision(3); + cout << showpoint << "cdf(s, s.standard_deviation()) = " + << cdf(s, s.standard_deviation()) << endl; // from -infinity to 1 sd + cout << "cdf(complement(s, s.standard_deviation())) = " + << cdf(complement(s, s.standard_deviation())) << endl; + cout << "Fraction 1 standard deviation within either side of mean is " + << 1 - cdf(complement(s, s.standard_deviation())) * 2 << endl; + cout << "Fraction 2 standard deviations within either side of mean is " + << 1 - cdf(complement(s, 2 * s.standard_deviation())) * 2 << endl; + cout << "Fraction 3 standard deviations within either side of mean is " + << 1 - cdf(complement(s, 3 * s.standard_deviation())) * 2 << endl; + +/*` +To a useful precision, the 1, 2 & 3 percentages are 68, 95 and 99.7, +and these are worth memorising as useful 'rules of thumb', as, for example, in +[@http://en.wikipedia.org/wiki/Standard_deviation standard deviation]: + +[pre +Fraction 1 standard deviation within either side of mean is 0.683 +Fraction 2 standard deviations within either side of mean is 0.954 +Fraction 3 standard deviations within either side of mean is 0.997 +] + +We could of course get some really accurate values for these +[@http://en.wikipedia.org/wiki/Confidence_interval confidence intervals] +by using cout.precision(15); + +[pre +Fraction 1 standard deviation within either side of mean is 0.682689492137086 +Fraction 2 standard deviations within either side of mean is 0.954499736103642 +Fraction 3 standard deviations within either side of mean is 0.997300203936740 +] + +But before you get too excited about this impressive precision, +don't forget that the *confidence intervals of the standard deviation* are surprisingly wide, +especially if you have estimated the standard deviation from only a few measurements. +*/ +//] [/[normal_basic2] + + +//[normal_bulbs_example1 +/*` +Examples from K. Krishnamoorthy, Handbook of Statistical Distributions with Applications, +ISBN 1 58488 635 8, page 125... implemented using the Math Toolkit library. + +A few very simple examples are shown here: +*/ +// K. Krishnamoorthy, Handbook of Statistical Distributions with Applications, + // ISBN 1 58488 635 8, page 125, example 10.3.5 +/*`Mean lifespan of 100 W bulbs is 1100 h with standard deviation of 100 h. +Assuming, perhaps with little evidence and much faith, that the distribution is normal, +we construct a normal distribution called /bulbs/ with these values: +*/ + double mean_life = 1100.; + double life_standard_deviation = 100.; + normal bulbs(mean_life, life_standard_deviation); + double expected_life = 1000.; + +/*`The we can use the Cumulative distribution function to predict fractions +(or percentages, if * 100) that will last various lifetimes. +*/ + cout << "Fraction of bulbs that will last at best (<=) " // P(X <= 1000) + << expected_life << " is "<< cdf(bulbs, expected_life) << endl; + cout << "Fraction of bulbs that will last at least (>) " // P(X > 1000) + << expected_life << " is "<< cdf(complement(bulbs, expected_life)) << endl; + double min_life = 900; + double max_life = 1200; + cout << "Fraction of bulbs that will last between " + << min_life << " and " << max_life << " is " + << cdf(bulbs, max_life) // P(X <= 1200) + - cdf(bulbs, min_life) << endl; // P(X <= 900) +/*` +[note Real-life failures are often very ab-normal, +with a significant number that 'dead-on-arrival' or suffer failure very early in their life: +the lifetime of the survivors of 'early mortality' may be well described by the normal distribution.] +*/ +//] [/normal_bulbs_example1 Quickbook end] + } + { + // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications, + // ISBN 1 58488 635 8, page 125, Example 10.3.6 + +//[normal_bulbs_example3 +/*`Weekly demand for 5 lb sacks of onions at a store is normally distributed with mean 140 sacks and standard deviation 10. +*/ + double mean = 140.; // sacks per week. + double standard_deviation = 10; + normal sacks(mean, standard_deviation); + + double stock = 160.; // per week. + cout << "Percentage of weeks overstocked " + << cdf(sacks, stock) * 100. << endl; // P(X <=160) + // Percentage of weeks overstocked 97.7 + +/*`So there will be lots of mouldy onions! +So we should be able to say what stock level will meet demand 95% of the weeks. +*/ + double stock_95 = quantile(sacks, 0.95); + cout << "Store should stock " << int(stock_95) << " sacks to meet 95% of demands." << endl; +/*`And it is easy to estimate how to meet 80% of demand, and waste even less. +*/ + double stock_80 = quantile(sacks, 0.80); + cout << "Store should stock " << int(stock_80) << " sacks to meet 8 out of 10 demands." << endl; +//] [/normal_bulbs_example3 Quickbook end] + } + { // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications, + // ISBN 1 58488 635 8, page 125, Example 10.3.7 + +//[normal_bulbs_example4 + +/*`A machine is set to pack 3 kg of ground beef per pack. +Over a long period of time it is found that the average packed was 3 kg +with a standard deviation of 0.1 kg. +Assuming the packing is normally distributed, +we can find the fraction (or %) of packages that weigh more than 3.1 kg. +*/ + +double mean = 3.; // kg +double standard_deviation = 0.1; // kg +normal packs(mean, standard_deviation); + +double max_weight = 3.1; // kg +cout << "Percentage of packs > " << max_weight << " is " +<< cdf(complement(packs, max_weight)) << endl; // P(X > 3.1) + +double under_weight = 2.9; +cout <<"fraction of packs <= " << under_weight << " with a mean of " << mean + << " is " << cdf(complement(packs, under_weight)) << endl; +// fraction of packs <= 2.9 with a mean of 3 is 0.841345 +// This is 0.84 - more than the target 0.95 +// Want 95% to be over this weight, so what should we set the mean weight to be? +// KK StatCalc says: +double over_mean = 3.0664; +normal xpacks(over_mean, standard_deviation); +cout << "fraction of packs >= " << under_weight +<< " with a mean of " << xpacks.mean() + << " is " << cdf(complement(xpacks, under_weight)) << endl; +// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005 +double under_fraction = 0.05; // so 95% are above the minimum weight mean - sd = 2.9 +double low_limit = standard_deviation; +double offset = mean - low_limit - quantile(packs, under_fraction); +double nominal_mean = mean + offset; + +normal nominal_packs(nominal_mean, standard_deviation); +cout << "Setting the packer to " << nominal_mean << " will mean that " + << "fraction of packs >= " << under_weight + << " is " << cdf(complement(nominal_packs, under_weight)) << endl; + +/*` +Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95. + +Setting the packer to 3.13263 will mean that fraction of packs >= 2.9 is 0.99, +but will more than double the mean loss from 0.0644 to 0.133. + +Alternatively, we could invest in a better (more precise) packer with a lower standard deviation. + +To estimate how much better (how much smaller standard deviation) it would have to be, +we need to get the 5% quantile to be located at the under_weight limit, 2.9 +*/ +double p = 0.05; // wanted p th quantile. +cout << "Quantile of " << p << " = " << quantile(packs, p) + << ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl; // +/*` +Quantile of 0.05 = 2.83551, mean = 3, sd = 0.1 + +With the current packer (mean = 3, sd = 0.1), the 5% quantile is at 2.8551 kg, +a little below our target of 2.9 kg. +So we know that the standard deviation is going to have to be smaller. + +Let's start by guessing that it (now 0.1) needs to be halved, to a standard deviation of 0.05 +*/ +normal pack05(mean, 0.05); +cout << "Quantile of " << p << " = " << quantile(pack05, p) + << ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl; + +cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean + << " and standard deviation of " << pack05.standard_deviation() + << " is " << cdf(complement(pack05, under_weight)) << endl; +// +/*` +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.9772 + +So 0.05 was quite a good guess, but we are a little over the 2.9 target, +so the standard deviation could be a tiny bit more. So we could do some +more guessing to get closer, say by increasing to 0.06 +*/ + +normal pack06(mean, 0.06); +cout << "Quantile of " << p << " = " << quantile(pack06, p) + << ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl; + +cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean + << " and standard deviation of " << pack06.standard_deviation() + << " is " << cdf(complement(pack06, under_weight)) << endl; +/*` +Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.9522 + +Now we are getting really close, but to do the job properly, +we could use root finding method, for example the tools provided, and used elsewhere, +in the Math Toolkit, see __root_finding_without_derivatives. + +But in this normal distribution case, we could be even smarter and make a direct calculation. +*/ + +normal s; // For standard normal distribution, +double sd = 0.1; +double x = 2.9; // Our required limit. +// then probability p = N((x - mean) / sd) +// So if we want to find the standard deviation that would be required to meet this limit, +// so that the p th quantile is located at x, +// in this case the 0.95 (95%) quantile at 2.9 kg pack weight, when the mean is 3 kg. + +double prob = pdf(s, (x - mean) / sd); +double qp = quantile(s, 0.95); +cout << "prob = " << prob << ", quantile(p) " << qp << endl; // p = 0.241971, quantile(p) 1.64485 +// Rearranging, we can directly calculate the required standard deviation: +double sd95 = std::abs((x - mean)) / qp; + +cout << "If we want the "<< p << " th quantile to be located at " + << x << ", would need a standard deviation of " << sd95 << endl; + +normal pack95(mean, sd95); // Distribution of the 'ideal better' packer. +cout <<"Fraction of packs >= " << under_weight << " with a mean of " << mean + << " and standard deviation of " << pack95.standard_deviation() + << " is " << cdf(complement(pack95, under_weight)) << endl; + +// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0608 is 0.95 + +/*`Notice that these two deceptively simple questions +(do we over-fill or measure better) are actually very common. +The weight of beef might be replaced by a measurement of more or less anything. +But the calculations rely on the accuracy of the standard deviation - something +that is almost always less good than we might wish, +especially if based on a few measurements. +*/ + +//] [/normal_bulbs_example4 Quickbook end] + } + + { // K. Krishnamoorthy, Handbook of Statistical Distributions with Applications, + // ISBN 1 58488 635 8, page 125, example 10.3.8 +//[normal_bulbs_example5 +/*`A bolt is usable if between 3.9 and 4.1 long. +From a large batch of bolts, a sample of 50 show a +mean length of 3.95 with standard deviation 0.1. +Assuming a normal distribution, what proportion is usable? +The true sample mean is unknown, +but we can use the sample mean and standard deviation to find approximate solutions. +*/ + + normal bolts(3.95, 0.1); + double top = 4.1; + double bottom = 3.9; + +cout << "Fraction long enough [ P(X <= " << top << ") ] is " << cdf(bolts, top) << endl; +cout << "Fraction too short [ P(X <= " << bottom << ") ] is " << cdf(bolts, bottom) << endl; +cout << "Fraction OK -between " << bottom << " and " << top + << "[ P(X <= " << top << ") - P(X<= " << bottom << " ) ] is " + << cdf(bolts, top) - cdf(bolts, bottom) << endl; + +cout << "Fraction too long [ P(X > " << top << ") ] is " + << cdf(complement(bolts, top)) << endl; + +cout << "95% of bolts are shorter than " << quantile(bolts, 0.95) << endl; + +//] [/normal_bulbs_example5 Quickbook end] + } + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + + +/* + +Output is: + +Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\normal_misc_examples.exe" +Example: Normal distribution, Miscellaneous Applications.Standard normal distribution, mean = 0, standard deviation = 1 +Probability distribution function values + z pdf +-4 0.00013383022576488537 +-3 0.0044318484119380075 +-2 0.053990966513188063 +-1 0.24197072451914337 +0 0.3989422804014327 +1 0.24197072451914337 +2 0.053990966513188063 +3 0.0044318484119380075 +4 0.00013383022576488537 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z + z cdf +-4 3.1671241833119979e-005 +-3 0.0013498980316300959 +-2 0.022750131948179219 +-1 0.1586552539314571 +0 0.5 +1 0.84134474606854293 +2 0.97724986805182079 +3 0.9986501019683699 +4 0.99996832875816688 +Area for z = 2 is 0.97725 +95% of area has a z below 1.64485 +95% of area has a z between 1.95996 and -1.95996 +Significance level for z == 1 is 0.3173105078629142 +level of significance (alpha) +2-sided 1 -sided z(alpha) +0.3173 0.1587 1 +0.2 0.1 1.282 +0.1 0.05 1.645 +0.05 0.025 1.96 +0.01 0.005 2.576 +0.001 0.0005 3.291 +0.0001 5e-005 3.891 +1e-005 5e-006 4.417 +cdf(s, s.standard_deviation()) = 0.841 +cdf(complement(s, s.standard_deviation())) = 0.159 +Fraction 1 standard deviation within either side of mean is 0.683 +Fraction 2 standard deviations within either side of mean is 0.954 +Fraction 3 standard deviations within either side of mean is 0.997 +Fraction of bulbs that will last at best (<=) 1.00e+003 is 0.159 +Fraction of bulbs that will last at least (>) 1.00e+003 is 0.841 +Fraction of bulbs that will last between 900. and 1.20e+003 is 0.819 +Percentage of weeks overstocked 97.7 +Store should stock 156 sacks to meet 95% of demands. +Store should stock 148 sacks to meet 8 out of 10 demands. +Percentage of packs > 3.10 is 0.159 +fraction of packs <= 2.90 with a mean of 3.00 is 0.841 +fraction of packs >= 2.90 with a mean of 3.07 is 0.952 +Setting the packer to 3.06 will mean that fraction of packs >= 2.90 is 0.950 +Quantile of 0.0500 = 2.84, mean = 3.00, sd = 0.100 +Quantile of 0.0500 = 2.92, mean = 3.00, sd = 0.0500 +Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0500 is 0.977 +Quantile of 0.0500 = 2.90, mean = 3.00, sd = 0.0600 +Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0600 is 0.952 +prob = 0.242, quantile(p) 1.64 +If we want the 0.0500 th quantile to be located at 2.90, would need a standard deviation of 0.0608 +Fraction of packs >= 2.90 with a mean of 3.00 and standard deviation of 0.0608 is 0.950 +Fraction long enough [ P(X <= 4.10) ] is 0.933 +Fraction too short [ P(X <= 3.90) ] is 0.309 +Fraction OK -between 3.90 and 4.10[ P(X <= 4.10) - P(X<= 3.90 ) ] is 0.625 +Fraction too long [ P(X > 4.10) ] is 0.0668 +95% of bolts are shorter than 4.11 + +*/ diff --git a/src/boost/libs/math/example/normal_tables.cpp b/src/boost/libs/math/example/normal_tables.cpp new file mode 100644 index 000000000..e130f5fd4 --- /dev/null +++ b/src/boost/libs/math/example/normal_tables.cpp @@ -0,0 +1,566 @@ + +// normal_misc_examples.cpp + +// Copyright Paul A. Bristow 2007, 2010, 2014, 2016. + +// 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) + +// Example of using normal distribution. + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +/*` +First we need some includes to access the normal distribution +(and some std output of course). +*/ + +#include <boost/cstdfloat.hpp> // MUST be first include!!! +// See Implementation of Float128 type, Overloading template functions with float128_t. + +#include <boost/math/distributions/normal.hpp> // for normal_distribution. + using boost::math::normal; // typedef provides default type of double. + +#include <iostream> + //using std::cout; using std::endl; + //using std::left; using std::showpoint; using std::noshowpoint; +#include <iomanip> + //using std::setw; using std::setprecision; +#include <limits> + //using std::numeric_limits; + + /*! +Function max_digits10 +Returns maximum number of possibly significant decimal digits for a floating-point type FPT, +even for older compilers/standard libraries that +lack support for std::std::numeric_limits<FPT>::max_digits10, +when the Kahan formula 2 + binary_digits * 0.3010 is used instead. +Also provides the correct result for Visual Studio 2010 where the max_digits10 provided for float is wrong. +*/ +namespace boost +{ +namespace math +{ +template <typename FPT> +int max_digits10() +{ +// Since max_digits10 is not defined (or wrong) on older systems, define a local max_digits10. + + // Usage: int m = max_digits10<boost::float64_t>(); + const int m = +#if (defined BOOST_NO_CXX11_NUMERIC_LIMITS) || (_MSC_VER == 1600) // is wrongly 8 not 9 for VS2010. + 2 + std::numeric_limits<FPT>::digits * 3010/10000; +#else + std::numeric_limits<FPT>::max_digits10; +#endif + return m; +} +} // namespace math +} // namespace boost + +template <typename FPT> +void normal_table() +{ + using namespace boost::math; + + FPT step = static_cast<FPT>(1.); // step in z. + FPT range = static_cast<FPT>(10.); // min and max z = -range to +range. + + // Traditional tables are only computed to much lower precision. + // but @c std::std::numeric_limits<double>::max_digits10; + // on new Standard Libraries gives 17, + // the maximum number of digits from 64-bit double that can possibly be significant. + // @c std::std::numeric_limits<double>::digits10; == 15 + // is number of @b guaranteed digits, the other two digits being 'noisy'. + // Here we use a custom version of max_digits10 which deals with those platforms + // where @c std::numeric_limits is not specialized, + // or @c std::numeric_limits<>::max_digits10 not implemented, or wrong. + int precision = boost::math::max_digits10<FPT>(); + +// std::cout << typeid(FPT).name() << std::endl; +// demo_normal.cpp:85: undefined reference to `typeinfo for __float128' +// [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622 GCC 43622] +// typeinfo for __float128 was missing GCC 4.9 Mar 2014, but OK for GCC 6.1.1. + + // Construct a standard normal distribution s, with + // (default mean = zero, and standard deviation = unity) + normal s; + std::cout << "\nStandard normal distribution, mean = "<< s.mean() + << ", standard deviation = " << s.standard_deviation() << std::endl; + + std::cout << "maxdigits_10 is " << precision + << ", digits10 is " << std::numeric_limits<FPT>::digits10 << std::endl; + + std::cout << "Probability distribution function values" << std::endl; + + std::cout << " z " " PDF " << std::endl; + for (FPT z = -range; z < range + step; z += step) + { + std::cout << std::left << std::setprecision(3) << std::setw(6) << z << " " + << std::setprecision(precision) << std::setw(12) << pdf(s, z) << std::endl; + } + std::cout.precision(6); // Restore to default precision. + +/*`And the area under the normal curve from -[infin] up to z, + the cumulative distribution function (CDF). +*/ + // For a standard normal distribution: + std::cout << "Standard normal mean = "<< s.mean() + << ", standard deviation = " << s.standard_deviation() << std::endl; + std::cout << "Integral (area under the curve) from - infinity up to z." << std::endl; + std::cout << " z " " CDF " << std::endl; + for (FPT z = -range; z < range + step; z += step) + { + std::cout << std::left << std::setprecision(3) << std::setw(6) << z << " " + << std::setprecision(precision) << std::setw(12) << cdf(s, z) << std::endl; + } + std::cout.precision(6); // Reset to default precision. +} // template <typename FPT> void normal_table() + +int main() +{ + std::cout << "\nExample: Normal distribution tables." << std::endl; + + using namespace boost::math; + + try + {// Tip - always use try'n'catch blocks to ensure that messages from thrown exceptions are shown. + +//[normal_table_1 +#ifdef BOOST_FLOAT32_C + normal_table<boost::float32_t>(); // Usually type float +#endif + normal_table<boost::float64_t>(); // Usually type double. Assume that float64_t is always available. +#ifdef BOOST_FLOAT80_C + normal_table<boost::float80_t>(); // Type long double on some X86 platforms. +#endif +#ifdef BOOST_FLOAT128_C + normal_table<boost::float128_t>(); // Type _Quad on some Intel and __float128 on some GCC platforms. +#endif + normal_table<boost::floatmax_t>(); +//] [/normal_table_1 ] + } + catch(std::exception ex) + { + std::cout << "exception thrown " << ex.what() << std::endl; + } + + return 0; +} // int main() + + +/* + +GCC 4.8.1 with quadmath + +Example: Normal distribution tables. + +Standard normal distribution, mean = 0, standard deviation = 1 +maxdigits_10 is 9, digits10 is 6 +Probability distribution function values + z PDF +-10 7.69459863e-023 +-9 1.02797736e-018 +-8 5.05227108e-015 +-7 9.13472041e-012 +-6 6.07588285e-009 +-5 1.48671951e-006 +-4 0.000133830226 +-3 0.00443184841 +-2 0.0539909665 +-1 0.241970725 +0 0.39894228 +1 0.241970725 +2 0.0539909665 +3 0.00443184841 +4 0.000133830226 +5 1.48671951e-006 +6 6.07588285e-009 +7 9.13472041e-012 +8 5.05227108e-015 +9 1.02797736e-018 +10 7.69459863e-023 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z. + z CDF +-10 7.61985302e-024 +-9 1.12858841e-019 +-8 6.22096057e-016 +-7 1.27981254e-012 +-6 9.86587645e-010 +-5 2.86651572e-007 +-4 3.16712418e-005 +-3 0.00134989803 +-2 0.0227501319 +-1 0.158655254 +0 0.5 +1 0.841344746 +2 0.977249868 +3 0.998650102 +4 0.999968329 +5 0.999999713 +6 0.999999999 +7 1 +8 1 +9 1 +10 1 + +Standard normal distribution, mean = 0, standard deviation = 1 +maxdigits_10 is 17, digits10 is 15 +Probability distribution function values + z PDF +-10 7.6945986267064199e-023 +-9 1.0279773571668917e-018 +-8 5.0522710835368927e-015 +-7 9.1347204083645953e-012 +-6 6.0758828498232861e-009 +-5 1.4867195147342979e-006 +-4 0.00013383022576488537 +-3 0.0044318484119380075 +-2 0.053990966513188063 +-1 0.24197072451914337 +0 0.3989422804014327 +1 0.24197072451914337 +2 0.053990966513188063 +3 0.0044318484119380075 +4 0.00013383022576488537 +5 1.4867195147342979e-006 +6 6.0758828498232861e-009 +7 9.1347204083645953e-012 +8 5.0522710835368927e-015 +9 1.0279773571668917e-018 +10 7.6945986267064199e-023 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z. + z CDF +-10 7.6198530241605945e-024 +-9 1.1285884059538422e-019 +-8 6.2209605742718204e-016 +-7 1.279812543885835e-012 +-6 9.865876450377014e-010 +-5 2.8665157187919455e-007 +-4 3.1671241833119972e-005 +-3 0.0013498980316300957 +-2 0.022750131948179216 +-1 0.15865525393145705 +0 0.5 +1 0.84134474606854293 +2 0.97724986805182079 +3 0.9986501019683699 +4 0.99996832875816688 +5 0.99999971334842808 +6 0.9999999990134123 +7 0.99999999999872013 +8 0.99999999999999933 +9 1 +10 1 + +Standard normal distribution, mean = 0, standard deviation = 1 +maxdigits_10 is 21, digits10 is 18 +Probability distribution function values + z PDF +-10 7.69459862670641993759e-023 +-9 1.0279773571668916523e-018 +-8 5.05227108353689273243e-015 +-7 9.13472040836459525705e-012 +-6 6.07588284982328608733e-009 +-5 1.48671951473429788965e-006 +-4 0.00013383022576488536764 +-3 0.00443184841193800752729 +-2 0.0539909665131880628364 +-1 0.241970724519143365328 +0 0.398942280401432702863 +1 0.241970724519143365328 +2 0.0539909665131880628364 +3 0.00443184841193800752729 +4 0.00013383022576488536764 +5 1.48671951473429788965e-006 +6 6.07588284982328608733e-009 +7 9.13472040836459525705e-012 +8 5.05227108353689273243e-015 +9 1.0279773571668916523e-018 +10 7.69459862670641993759e-023 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z. + z CDF +-10 7.61985302416059451083e-024 +-9 1.12858840595384222719e-019 +-8 6.22096057427182035917e-016 +-7 1.279812543885834962e-012 +-6 9.86587645037701399241e-010 +-5 2.86651571879194547129e-007 +-4 3.16712418331199717608e-005 +-3 0.00134989803163009566139 +-2 0.0227501319481792155242 +-1 0.158655253931457046468 +0 0.5 +1 0.841344746068542925777 +2 0.977249868051820791415 +3 0.998650101968369896532 +4 0.999968328758166880021 +5 0.999999713348428076465 +6 0.999999999013412299576 +7 0.999999999998720134897 +8 0.999999999999999333866 +9 1 +10 1 + +Standard normal distribution, mean = 0, standard deviation = 1 +maxdigits_10 is 36, digits10 is 34 +Probability distribution function values + z PDF +-10 7.69459862670641993759264402330435296e-023 +-9 1.02797735716689165230378750485667109e-018 +-8 5.0522710835368927324337437844893081e-015 +-7 9.13472040836459525705208369548147081e-012 +-6 6.07588284982328608733411870229841611e-009 +-5 1.48671951473429788965346931561839483e-006 +-4 0.00013383022576488536764006964663309418 +-3 0.00443184841193800752728870762098267733 +-2 0.0539909665131880628363703067407186609 +-1 0.241970724519143365327522587904240936 +0 0.398942280401432702863218082711682655 +1 0.241970724519143365327522587904240936 +2 0.0539909665131880628363703067407186609 +3 0.00443184841193800752728870762098267733 +4 0.00013383022576488536764006964663309418 +5 1.48671951473429788965346931561839483e-006 +6 6.07588284982328608733411870229841611e-009 +7 9.13472040836459525705208369548147081e-012 +8 5.0522710835368927324337437844893081e-015 +9 1.02797735716689165230378750485667109e-018 +10 7.69459862670641993759264402330435296e-023 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z. + z CDF +-10 7.61985302416059451083278826816793623e-024 +-9 1.1285884059538422271881384555435713e-019 +-8 6.22096057427182035917417257601387863e-016 +-7 1.27981254388583496200054074948511201e-012 +-6 9.86587645037701399241244820583623953e-010 +-5 2.86651571879194547128505464808623238e-007 +-4 3.16712418331199717608064048146587766e-005 +-3 0.001349898031630095661392854111682027 +-2 0.0227501319481792155241528519127314212 +-1 0.158655253931457046467912164189328905 +0 0.5 +1 0.841344746068542925776512220181757584 +2 0.977249868051820791414741051994496956 +3 0.998650101968369896532351503992686048 +4 0.999968328758166880021462930017150939 +5 0.999999713348428076464813329948810861 +6 0.999999999013412299575520592043176293 +7 0.999999999998720134897212119540199637 +8 0.999999999999999333866185224906075746 +9 1 +10 1 + +Standard normal distribution, mean = 0, standard deviation = 1 +maxdigits_10 is 36, digits10 is 34 +Probability distribution function values + z PDF +-10 7.69459862670641993759264402330435296e-023 +-9 1.02797735716689165230378750485667109e-018 +-8 5.0522710835368927324337437844893081e-015 +-7 9.13472040836459525705208369548147081e-012 +-6 6.07588284982328608733411870229841611e-009 +-5 1.48671951473429788965346931561839483e-006 +-4 0.00013383022576488536764006964663309418 +-3 0.00443184841193800752728870762098267733 +-2 0.0539909665131880628363703067407186609 +-1 0.241970724519143365327522587904240936 +0 0.398942280401432702863218082711682655 +1 0.241970724519143365327522587904240936 +2 0.0539909665131880628363703067407186609 +3 0.00443184841193800752728870762098267733 +4 0.00013383022576488536764006964663309418 +5 1.48671951473429788965346931561839483e-006 +6 6.07588284982328608733411870229841611e-009 +7 9.13472040836459525705208369548147081e-012 +8 5.0522710835368927324337437844893081e-015 +9 1.02797735716689165230378750485667109e-018 +10 7.69459862670641993759264402330435296e-023 +Standard normal mean = 0, standard deviation = 1 +Integral (area under the curve) from - infinity up to z. + z CDF +-10 7.61985302416059451083278826816793623e-024 +-9 1.1285884059538422271881384555435713e-019 +-8 6.22096057427182035917417257601387863e-016 +-7 1.27981254388583496200054074948511201e-012 +-6 9.86587645037701399241244820583623953e-010 +-5 2.86651571879194547128505464808623238e-007 +-4 3.16712418331199717608064048146587766e-005 +-3 0.001349898031630095661392854111682027 +-2 0.0227501319481792155241528519127314212 +-1 0.158655253931457046467912164189328905 +0 0.5 +1 0.841344746068542925776512220181757584 +2 0.977249868051820791414741051994496956 +3 0.998650101968369896532351503992686048 +4 0.999968328758166880021462930017150939 +5 0.999999713348428076464813329948810861 +6 0.999999999013412299575520592043176293 +7 0.999999999998720134897212119540199637 +8 0.999999999999999333866185224906075746 +9 1 +10 1 + +MSVC 2013 64-bit +1> +1> Example: Normal distribution tables. +1> +1> Standard normal distribution, mean = 0, standard deviation = 1 +1> maxdigits_10 is 9, digits10 is 6 +1> Probability distribution function values +1> z PDF +1> -10 7.69459863e-023 +1> -9 1.02797736e-018 +1> -8 5.05227108e-015 +1> -7 9.13472041e-012 +1> -6 6.07588285e-009 +1> -5 1.48671951e-006 +1> -4 0.000133830226 +1> -3 0.00443184841 +1> -2 0.0539909665 +1> -1 0.241970725 +1> 0 0.39894228 +1> 1 0.241970725 +1> 2 0.0539909665 +1> 3 0.00443184841 +1> 4 0.000133830226 +1> 5 1.48671951e-006 +1> 6 6.07588285e-009 +1> 7 9.13472041e-012 +1> 8 5.05227108e-015 +1> 9 1.02797736e-018 +1> 10 7.69459863e-023 +1> Standard normal mean = 0, standard deviation = 1 +1> Integral (area under the curve) from - infinity up to z. +1> z CDF +1> -10 7.61985302e-024 +1> -9 1.12858841e-019 +1> -8 6.22096057e-016 +1> -7 1.27981254e-012 +1> -6 9.86587645e-010 +1> -5 2.86651572e-007 +1> -4 3.16712418e-005 +1> -3 0.00134989803 +1> -2 0.0227501319 +1> -1 0.158655254 +1> 0 0.5 +1> 1 0.841344746 +1> 2 0.977249868 +1> 3 0.998650102 +1> 4 0.999968329 +1> 5 0.999999713 +1> 6 0.999999999 +1> 7 1 +1> 8 1 +1> 9 1 +1> 10 1 +1> +1> Standard normal distribution, mean = 0, standard deviation = 1 +1> maxdigits_10 is 17, digits10 is 15 +1> Probability distribution function values +1> z PDF +1> -10 7.6945986267064199e-023 +1> -9 1.0279773571668917e-018 +1> -8 5.0522710835368927e-015 +1> -7 9.1347204083645953e-012 +1> -6 6.0758828498232861e-009 +1> -5 1.4867195147342979e-006 +1> -4 0.00013383022576488537 +1> -3 0.0044318484119380075 +1> -2 0.053990966513188063 +1> -1 0.24197072451914337 +1> 0 0.3989422804014327 +1> 1 0.24197072451914337 +1> 2 0.053990966513188063 +1> 3 0.0044318484119380075 +1> 4 0.00013383022576488537 +1> 5 1.4867195147342979e-006 +1> 6 6.0758828498232861e-009 +1> 7 9.1347204083645953e-012 +1> 8 5.0522710835368927e-015 +1> 9 1.0279773571668917e-018 +1> 10 7.6945986267064199e-023 +1> Standard normal mean = 0, standard deviation = 1 +1> Integral (area under the curve) from - infinity up to z. +1> z CDF +1> -10 7.6198530241605813e-024 +1> -9 1.1285884059538408e-019 +1> -8 6.2209605742718292e-016 +1> -7 1.2798125438858352e-012 +1> -6 9.8658764503770161e-010 +1> -5 2.8665157187919439e-007 +1> -4 3.1671241833119979e-005 +1> -3 0.0013498980316300957 +1> -2 0.022750131948179219 +1> -1 0.15865525393145707 +1> 0 0.5 +1> 1 0.84134474606854293 +1> 2 0.97724986805182079 +1> 3 0.9986501019683699 +1> 4 0.99996832875816688 +1> 5 0.99999971334842808 +1> 6 0.9999999990134123 +1> 7 0.99999999999872013 +1> 8 0.99999999999999933 +1> 9 1 +1> 10 1 +1> +1> Standard normal distribution, mean = 0, standard deviation = 1 +1> maxdigits_10 is 17, digits10 is 15 +1> Probability distribution function values +1> z PDF +1> -10 7.6945986267064199e-023 +1> -9 1.0279773571668917e-018 +1> -8 5.0522710835368927e-015 +1> -7 9.1347204083645953e-012 +1> -6 6.0758828498232861e-009 +1> -5 1.4867195147342979e-006 +1> -4 0.00013383022576488537 +1> -3 0.0044318484119380075 +1> -2 0.053990966513188063 +1> -1 0.24197072451914337 +1> 0 0.3989422804014327 +1> 1 0.24197072451914337 +1> 2 0.053990966513188063 +1> 3 0.0044318484119380075 +1> 4 0.00013383022576488537 +1> 5 1.4867195147342979e-006 +1> 6 6.0758828498232861e-009 +1> 7 9.1347204083645953e-012 +1> 8 5.0522710835368927e-015 +1> 9 1.0279773571668917e-018 +1> 10 7.6945986267064199e-023 +1> Standard normal mean = 0, standard deviation = 1 +1> Integral (area under the curve) from - infinity up to z. +1> z CDF +1> -10 7.6198530241605813e-024 +1> -9 1.1285884059538408e-019 +1> -8 6.2209605742718292e-016 +1> -7 1.2798125438858352e-012 +1> -6 9.8658764503770161e-010 +1> -5 2.8665157187919439e-007 +1> -4 3.1671241833119979e-005 +1> -3 0.0013498980316300957 +1> -2 0.022750131948179219 +1> -1 0.15865525393145707 +1> 0 0.5 +1> 1 0.84134474606854293 +1> 2 0.97724986805182079 +1> 3 0.9986501019683699 +1> 4 0.99996832875816688 +1> 5 0.99999971334842808 +1> 6 0.9999999990134123 +1> 7 0.99999999999872013 +1> 8 0.99999999999999933 +1> 9 1 +1> 10 1 + + +*/ diff --git a/src/boost/libs/math/example/numerical_derivative_example.cpp b/src/boost/libs/math/example/numerical_derivative_example.cpp new file mode 100644 index 000000000..6f05c6ba0 --- /dev/null +++ b/src/boost/libs/math/example/numerical_derivative_example.cpp @@ -0,0 +1,209 @@ +// Copyright Christopher Kormanyos 2013. +// 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). + +#ifdef _MSC_VER +# pragma warning (disable : 4996) // assignment operator could not be generated. +#endif + +# include <iostream> +# include <iomanip> +# include <limits> +# include <type_traits> +# include <cmath> + +#include <boost/math/tools/assert.hpp> +#include <boost/math/special_functions/next.hpp> // for float_distance + +//[numeric_derivative_example +/*`The following example shows how multiprecision calculations can be used to +obtain full precision in a numerical derivative calculation that suffers from precision loss. + +Consider some well-known central difference rules for numerically +computing the 1st derivative of a function [f'(x)] with [/x] real. + +Need a reference here? Introduction to Partial Differential Equations, Peter J. Olver + December 16, 2012 + +Here, the implementation uses a C++ template that can be instantiated with various +floating-point types such as `float`, `double`, `long double`, or even +a user-defined floating-point type like __multiprecision. + +We will now use the derivative template with the built-in type `double` in +order to numerically compute the derivative of a function, and then repeat +with a 5 decimal digit higher precision user-defined floating-point type. + +Consider the function shown below. +!! +(3) +We will now take the derivative of this function with respect to x evaluated +at x = 3= 2. In other words, + +(4) + +The expected result is + + 0:74535 59924 99929 89880 . (5) +The program below uses the derivative template in order to perform +the numerical calculation of this derivative. The program also compares the +numerically-obtained result with the expected result and reports the absolute +relative error scaled to a deviation that can easily be related to the number of +bits of lost precision. + +*/ + +/*` [note Requires the C++11 feature of +[@http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B anonymous functions] +for the derivative function calls like `[]( const double & x_) -> double`. +*/ + + + +template <typename value_type, typename function_type> +value_type derivative (const value_type x, const value_type dx, function_type function) +{ + /*! \brief Compute the derivative of function using a 3-point central difference rule of O(dx^6). + \tparam value_type, floating-point type, for example: `double` or `cpp_dec_float_50` + \tparam function_type + + \param x Value at which to evaluate derivative. + \param dx Incremental step-size. + \param function Function whose derivative is to computed. + + \return derivative at x. + */ + + static_assert(false == std::numeric_limits<value_type>::is_integer, "value_type must be a floating-point type!"); + + const value_type dx2(dx * 2U); + const value_type dx3(dx * 3U); + // Difference terms. + const value_type m1 ((function (x + dx) - function(x - dx)) / 2U); + const value_type m2 ((function (x + dx2) - function(x - dx2)) / 4U); + const value_type m3 ((function (x + dx3) - function(x - dx3)) / 6U); + const value_type fifteen_m1 (m1 * 15U); + const value_type six_m2 (m2 * 6U); + const value_type ten_dx (dx * 10U); + return ((fifteen_m1 - six_m2) + m3) / ten_dx; // Derivative. +} // + +#include <boost/multiprecision/cpp_dec_float.hpp> + using boost::multiprecision::number; + using boost::multiprecision::cpp_dec_float; + +// Re-compute using 5 extra decimal digits precision (22) than double (17). +#define MP_DIGITS10 unsigned (std::numeric_limits<double>::max_digits10 + 5) + +typedef cpp_dec_float<MP_DIGITS10> mp_backend; +typedef number<mp_backend> mp_type; + + +int main() +{ + { + const double d = + derivative + ( 1.5, // x = 3.2 + std::ldexp (1., -9), // step size 2^-9 = see below for choice. + [](const double & x)->double // Function f(x). + { + return std::sqrt((x * x) - 1.) - std::acos(1. / x); + } + ); + + // The 'exactly right' result is [sqrt]5 / 3 = 0.74535599249992989880. + const double rel_error = (d - 0.74535599249992989880) / 0.74535599249992989880; + const double bit_error = std::abs(rel_error) / std::numeric_limits<double>::epsilon(); + std::cout.precision (std::numeric_limits<double>::digits10); // Show all guaranteed decimal digits. + std::cout << std::showpoint ; // Ensure that any trailing zeros are shown too. + + std::cout << " derivative : " << d << std::endl; + std::cout << " expected : " << 0.74535599249992989880 << std::endl; + // Can compute an 'exact' value using multiprecision type. + std::cout << " expected : " << sqrt(static_cast<mp_type>(5))/3U << std::endl; + std::cout << " bit_error : " << static_cast<unsigned long>(bit_error) << std::endl; + + std::cout.precision(6); + std::cout << "float_distance = " << boost::math::float_distance(0.74535599249992989880, d) << std::endl; + + } + + { // Compute using multiprecision type with an extra 5 decimal digits of precision. + const mp_type mp = + derivative(mp_type(mp_type(3) / 2U), // x = 3/2 + mp_type(mp_type(1) / 10000000U), // Step size 10^7. + [](const mp_type & x)->mp_type + { + return sqrt((x * x) - 1.) - acos (1. / x); // Function + } + ); + + const double d = mp.convert_to<double>(); // Convert to closest double. + const double rel_error = (d - 0.74535599249992989880) / 0.74535599249992989880; + const double bit_error = std::abs (rel_error) / std::numeric_limits<double>::epsilon(); + std::cout.precision (std::numeric_limits <double>::digits10); // All guaranteed decimal digits. + std::cout << std::showpoint ; // Ensure that any trailing zeros are shown too. + std::cout << " derivative : " << d << std::endl; + // Can compute an 'exact' value using multiprecision type. + std::cout << " expected : " << sqrt(static_cast<mp_type>(5))/3U << std::endl; + std::cout << " expected : " << 0.74535599249992989880 + << std::endl; + std::cout << " bit_error : " << static_cast<unsigned long>(bit_error) << std::endl; + + std::cout.precision(6); + std::cout << "float_distance = " << boost::math::float_distance(0.74535599249992989880, d) << std::endl; + + + } + + +} // int main() + +/*` +The result of this program on a system with an eight-byte, 64-bit IEEE-754 +conforming floating-point representation for `double` is: + + derivative : 0.745355992499951 + + derivative : 0.745355992499943 + expected : 0.74535599249993 + bit_error : 78 + + derivative : 0.745355992499930 + expected : 0.745355992499930 + bit_error : 0 + +The resulting bit error is 0. This means that the result of the derivative +calculation is bit-identical with the double representation of the expected result, +and this is the best result possible for the built-in type. + +The derivative in this example has a known closed form. There are, however, +countless situations in numerical analysis (and not only for numerical deriva- +tives) for which the calculation at hand does not have a known closed-form +solution or for which the closed-form solution is highly inconvenient to use. In +such cases, this technique may be useful. + +This example has shown how multiprecision can be used to add extra digits +to an ill-conditioned calculation that suffers from precision loss. When the result +of the multiprecision calculation is converted to a built-in type such as double, +the entire precision of the result in double is preserved. + + */ + +/* + + Description: Autorun "J:\Cpp\big_number\Debug\numerical_derivative_example.exe" + derivative : 0.745355992499943 + expected : 0.745355992499930 + expected : 0.745355992499930 + bit_error : 78 + float_distance = 117.000 + derivative : 0.745355992499930 + expected : 0.745355992499930 + expected : 0.745355992499930 + bit_error : 0 + float_distance = 0.000000 + + */ + diff --git a/src/boost/libs/math/example/ooura_fourier_integrals_cosine_example.cpp b/src/boost/libs/math/example/ooura_fourier_integrals_cosine_example.cpp new file mode 100644 index 000000000..2269202d3 --- /dev/null +++ b/src/boost/libs/math/example/ooura_fourier_integrals_cosine_example.cpp @@ -0,0 +1,83 @@ +// Copyright Paul A. Bristow, 2019 +// Copyright Nick Thompson, 2019 + +// 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) + +//#define BOOST_MATH_INSTRUMENT_OOURA // or -DBOOST_MATH_INSTRUMENT_OOURA etc for diagnostic output. + +#include <boost/math/quadrature/ooura_fourier_integrals.hpp> // For ooura_fourier_cos +#include <boost/math/constants/constants.hpp> // For pi (including for multiprecision types, if used.) + +#include <cmath> +#include <iostream> +#include <limits> +#include <iostream> + +int main() +{ + try + { + std::cout.precision(std::numeric_limits<double>::max_digits10); // Show all potentially significant digits. + + using boost::math::quadrature::ooura_fourier_cos; + using boost::math::constants::half_pi; + using boost::math::constants::e; + + //[ooura_fourier_integrals_cosine_example_1 + auto integrator = ooura_fourier_cos<double>(); + // Use the default tolerance root_epsilon and eight levels for type double. + + auto f = [](double x) + { // More complex example function. + return 1 / (x * x + 1); + }; + + double omega = 1; + + auto [result, relative_error] = integrator.integrate(f, omega); + std::cout << "Integral = " << result << ", relative error estimate " << relative_error << std::endl; + + //] [/ooura_fourier_integrals_cosine_example_1] + + //[ooura_fourier_integrals_cosine_example_2 + + constexpr double expected = half_pi<double>() / e<double>(); + std::cout << "pi/(2e) = " << expected << ", difference " << result - expected << std::endl; + //] [/ooura_fourier_integrals_cosine_example_2] + } + catch (std::exception const & ex) + { + // Lacking try&catch blocks, the program will abort after any throw, whereas the + // message below from the thrown exception will give some helpful clues as to the cause of the problem. + std::cout << "\n""Message from thrown exception was:\n " << ex.what() << std::endl; + } + +} // int main() + +/* + +//[ooura_fourier_integrals_example_cosine_output_1 +`` +Integral = 0.57786367489546109, relative error estimate 6.4177395404415149e-09 +pi/(2e) = 0.57786367489546087, difference 2.2204460492503131e-16 +`` +//] [/ooura_fourier_integrals_example_cosine_output_1] + + +//[ooura_fourier_integrals_example_cosine_diagnostic_output_1 +`` +ooura_fourier_cos with relative error goal 1.4901161193847656e-08 & 8 levels. +epsilon for type = 2.2204460492503131e-16 +h = 1.000000000000000, I_h = 0.588268622591776 = 0x1.2d318b7e96dbe00p-1, absolute error estimate = nan +h = 0.500000000000000, I_h = 0.577871642184837 = 0x1.27decab8f07b200p-1, absolute error estimate = 1.039698040693926e-02 +h = 0.250000000000000, I_h = 0.577863671186883 = 0x1.27ddbf42969be00p-1, absolute error estimate = 7.970997954576120e-06 +h = 0.125000000000000, I_h = 0.577863674895461 = 0x1.27ddbf6271dc000p-1, absolute error estimate = 3.708578555361441e-09 +Integral = 5.778636748954611e-01, relative error estimate 6.417739540441515e-09 +pi/(2e) = 5.778636748954609e-01, difference 2.220446049250313e-16 +`` +//] [/ooura_fourier_integrals_example_cosine_diagnostic_output_1] + +*/ diff --git a/src/boost/libs/math/example/ooura_fourier_integrals_example.cpp b/src/boost/libs/math/example/ooura_fourier_integrals_example.cpp new file mode 100644 index 000000000..22a9d015a --- /dev/null +++ b/src/boost/libs/math/example/ooura_fourier_integrals_example.cpp @@ -0,0 +1,83 @@ +// Copyright Paul A. Bristow, 2019 +// Copyright Nick Thompson, 2019 + +// 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) + +#ifdef BOOST_NO_CXX11_LAMBDAS +# error "This example requires a C++11 compiler that supports lambdas. Try C++11 or later." +#endif + +//#define BOOST_MATH_INSTRUMENT_OOURA // or -DBOOST_MATH_INSTRUMENT_OOURA etc for diagnostics. + +#include <boost/math/quadrature/ooura_fourier_integrals.hpp> +#include <boost/math/constants/constants.hpp> // For pi (including for multiprecision types, if used.) + +#include <cmath> +#include <iostream> +#include <limits> +#include <iostream> + +int main() +{ + try + { + std::cout.precision(std::numeric_limits<double>::max_digits10); // Show all potentially significant digits. + + using boost::math::quadrature::ooura_fourier_sin; + using boost::math::constants::half_pi; + +//[ooura_fourier_integrals_example_1 + ooura_fourier_sin<double>integrator = ooura_fourier_sin<double>(); + // Use the default tolerance root_epsilon and eight levels for type double. + + auto f = [](double x) + { // Simple reciprocal function for sinc. + return 1 / x; + }; + + double omega = 1; + std::pair<double, double> result = integrator.integrate(f, omega); + std::cout << "Integral = " << result.first << ", relative error estimate " << result.second << std::endl; + +//] [/ooura_fourier_integrals_example_1] + +//[ooura_fourier_integrals_example_2 + + constexpr double expected = half_pi<double>(); + std::cout << "pi/2 = " << expected << ", difference " << result.first - expected << std::endl; +//] [/ooura_fourier_integrals_example_2] + } + catch (std::exception const & ex) + { + // Lacking try&catch blocks, the program will abort after any throw, whereas the + // message below from the thrown exception will give some helpful clues as to the cause of the problem. + std::cout << "\n""Message from thrown exception was:\n " << ex.what() << std::endl; + } +} // int main() + +/* + +//[ooura_fourier_integrals_example_output_1 + +integral = 1.5707963267948966, relative error estimate 1.2655356398390254e-11 +pi/2 = 1.5707963267948966, difference 0 + +//] [/ooura_fourier_integrals_example_output_1] + + +//[ooura_fourier_integrals_example_diagnostic_output_1 + +ooura_fourier_sin with relative error goal 1.4901161193847656e-08 & 8 levels. +h = 1.000000000000000, I_h = 1.571890732004545 = 0x1.92676e56d853500p+0, absolute error estimate = nan +h = 0.500000000000000, I_h = 1.570793292491940 = 0x1.921f825c076f600p+0, absolute error estimate = 1.097439512605325e-03 +h = 0.250000000000000, I_h = 1.570796326814776 = 0x1.921fb54458acf00p+0, absolute error estimate = 3.034322835882008e-06 +h = 0.125000000000000, I_h = 1.570796326794897 = 0x1.921fb54442d1800p+0, absolute error estimate = 1.987898734512328e-11 +Integral = 1.570796326794897e+00, relative error estimate 1.265535639839025e-11 +pi/2 = 1.570796326794897e+00, difference 0.000000000000000e+00 + +//] [/ooura_fourier_integrals_example_diagnostic_output_1] + +*/ diff --git a/src/boost/libs/math/example/ooura_fourier_integrals_multiprecision_example.cpp b/src/boost/libs/math/example/ooura_fourier_integrals_multiprecision_example.cpp new file mode 100644 index 000000000..f2ac13194 --- /dev/null +++ b/src/boost/libs/math/example/ooura_fourier_integrals_multiprecision_example.cpp @@ -0,0 +1,98 @@ +// Copyright Paul A. Bristow, 2019 +// Copyright Nick Thompson, 2019 + +// 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) + +#if !defined(__cpp_structured_bindings) || (__cpp_structured_bindings < 201606L) +# error "This example requires a C++17 compiler that supports 'structured bindings'. Try /std:c++17 or -std=c++17 or later." +#endif + +//#define BOOST_MATH_INSTRUMENT_OOURA // or -DBOOST_MATH_INSTRUMENT_OOURA etc for diagnostic output. + +#include <boost/math/quadrature/ooura_fourier_integrals.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> // for cpp_bin_float_quad, cpp_bin_float_50... +#include <boost/math/constants/constants.hpp> // For pi (including for multiprecision types, if used.) + +#include <cmath> +#include <iostream> +#include <limits> +#include <iostream> +#include <exception> + +int main() +{ + try + { + typedef boost::multiprecision::cpp_bin_float_quad Real; + + std::cout.precision(std::numeric_limits<Real>::max_digits10); // Show all potentially significant digits. + + using boost::math::quadrature::ooura_fourier_cos; + using boost::math::constants::half_pi; + using boost::math::constants::e; + + //[ooura_fourier_integrals_multiprecision_example_1 + + // Use the default parameters for tolerance root_epsilon and eight levels for a type of 8 bytes. + //auto integrator = ooura_fourier_cos<Real>(); + // Decide on a (tight) tolerance. + const Real tol = 2 * std::numeric_limits<Real>::epsilon(); + auto integrator = ooura_fourier_cos<Real>(tol, 8); // Loops or gets worse for more than 8. + + auto f = [](Real x) + { // More complex example function. + return 1 / (x * x + 1); + }; + + double omega = 1; + auto [result, relative_error] = integrator.integrate(f, omega); + + //] [/ooura_fourier_integrals_multiprecision_example_1] + + //[ooura_fourier_integrals_multiprecision_example_2 + std::cout << "Integral = " << result << ", relative error estimate " << relative_error << std::endl; + + const Real expected = half_pi<Real>() / e<Real>(); // Expect integral = 1/(2e) + std::cout << "pi/(2e) = " << expected << ", difference " << result - expected << std::endl; + //] [/ooura_fourier_integrals_multiprecision_example_2] + } + catch (std::exception const & ex) + { + // Lacking try&catch blocks, the program will abort after any throw, whereas the + // message below from the thrown exception will give some helpful clues as to the cause of the problem. + std::cout << "\n""Message from thrown exception was:\n " << ex.what() << std::endl; + } +} // int main() + +/* + +//[ooura_fourier_integrals_example_multiprecision_output_1 +`` +Integral = 0.5778636748954608589550465916563501587, relative error estimate 4.609814684522163895264277312610830278e-17 +pi/(2e) = 0.5778636748954608659545328919193707407, difference -6.999486300263020581921171645255733758e-18 +`` +//] [/ooura_fourier_integrals_example_multiprecision_output_1] + + +//[ooura_fourier_integrals_example_multiprecision_diagnostic_output_1 +`` +ooura_fourier_cos with relative error goal 3.851859888774471706111955885169854637e-34 & 15 levels. +epsilon for type = 1.925929944387235853055977942584927319e-34 +h = 1.000000000000000000000000000000000, I_h = 0.588268622591776615359568690603776 = 0.5882686225917766153595686906037760, absolute error estimate = nan +h = 0.500000000000000000000000000000000, I_h = 0.577871642184837461311756940493259 = 0.5778716421848374613117569404932595, absolute error estimate = 1.039698040693915404781175011051656e-02 +h = 0.250000000000000000000000000000000, I_h = 0.577863671186882539559996800783122 = 0.5778636711868825395599968007831220, absolute error estimate = 7.970997954921751760139710137450075e-06 +h = 0.125000000000000000000000000000000, I_h = 0.577863674895460885593491133506723 = 0.5778636748954608855934911335067232, absolute error estimate = 3.708578346033494332723601147051768e-09 +h = 0.062500000000000000000000000000000, I_h = 0.577863674895460858955046591656350 = 0.5778636748954608589550465916563502, absolute error estimate = 2.663844454185037302771663314961535e-17 +h = 0.031250000000000000000000000000000, I_h = 0.577863674895460858955046591656348 = 0.5778636748954608589550465916563484, absolute error estimate = 1.733336949948512267750380148326435e-33 +h = 0.015625000000000000000000000000000, I_h = 0.577863674895460858955046591656348 = 0.5778636748954608589550465916563479, absolute error estimate = 4.814824860968089632639944856462318e-34 +h = 0.007812500000000000000000000000000, I_h = 0.577863674895460858955046591656347 = 0.5778636748954608589550465916563473, absolute error estimate = 6.740754805355325485695922799047246e-34 +h = 0.003906250000000000000000000000000, I_h = 0.577863674895460858955046591656347 = 0.5778636748954608589550465916563475, absolute error estimate = 1.925929944387235853055977942584927e-34 +Integral = 5.778636748954608589550465916563475e-01, relative error estimate 3.332844800697411177051445985473052e-34 +pi/(2e) = 5.778636748954608589550465916563481e-01, difference -6.740754805355325485695922799047246e-34 +`` +//] [/ooura_fourier_integrals_example_multiprecision_diagnostic_output_1] + +*/ diff --git a/src/boost/libs/math/example/owens_t_example.cpp b/src/boost/libs/math/example/owens_t_example.cpp new file mode 100644 index 000000000..6c6d20417 --- /dev/null +++ b/src/boost/libs/math/example/owens_t_example.cpp @@ -0,0 +1,113 @@ +// Copyright Benjamin Sobotta 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) + +#ifdef _MSC_VER +# pragma warning(disable : 4127) // conditional expression is constant. +#endif + +#include <boost/math/special_functions/owens_t.hpp> +#include <iostream> + +int main() +{ + double h = 0.0,a; + std::cout << std::setprecision(20); + + static const double a_vec[] = { + 0.5000000000000000E+00, + 0.1000000000000000E+01, + 0.2000000000000000E+01, + 0.3000000000000000E+01, + 0.5000000000000000E+00, + 0.1000000000000000E+01, + 0.2000000000000000E+01, + 0.3000000000000000E+01, + 0.5000000000000000E+00, + 0.1000000000000000E+01, + 0.2000000000000000E+01, + 0.3000000000000000E+01, + 0.5000000000000000E+00, + 0.1000000000000000E+01, + 0.2000000000000000E+01, + 0.3000000000000000E+01, + 0.5000000000000000E+00, + 0.1000000000000000E+01, + 0.2000000000000000E+01, + 0.3000000000000000E+01, + 0.1000000000000000E+02, + 0.1000000000000000E+03 }; + + static const double h_vec[] = { + 0.1000000000000000E+01, + 0.1000000000000000E+01, + 0.1000000000000000E+01, + 0.1000000000000000E+01, + 0.5000000000000000E+00, + 0.5000000000000000E+00, + 0.5000000000000000E+00, + 0.5000000000000000E+00, + 0.2500000000000000E+00, + 0.2500000000000000E+00, + 0.2500000000000000E+00, + 0.2500000000000000E+00, + 0.1250000000000000E+00, + 0.1250000000000000E+00, + 0.1250000000000000E+00, + 0.1250000000000000E+00, + 0.7812500000000000E-02, + 0.7812500000000000E-02, + 0.7812500000000000E-02, + 0.7812500000000000E-02, + 0.7812500000000000E-02, + 0.7812500000000000E-02 }; + + static const double t_vec[] = { + 0.4306469112078537E-01, + 0.6674188216570097E-01, + 0.7846818699308410E-01, + 0.7929950474887259E-01, + 0.6448860284750376E-01, + 0.1066710629614485E+00, + 0.1415806036539784E+00, + 0.1510840430760184E+00, + 0.7134663382271778E-01, + 0.1201285306350883E+00, + 0.1666128410939293E+00, + 0.1847501847929859E+00, + 0.7317273327500385E-01, + 0.1237630544953746E+00, + 0.1737438887583106E+00, + 0.1951190307092811E+00, + 0.7378938035365546E-01, + 0.1249951430754052E+00, + 0.1761984774738108E+00, + 0.1987772386442824E+00, + 0.2340886964802671E+00, + 0.2479460829231492E+00 }; + + for(unsigned i = 0; i != 22; ++i) + { + h = h_vec[i]; + a = a_vec[i]; + const double t = boost::math::owens_t(h, a); + std::cout << "h=" << h << "\ta=" << a << "\tcomp=" + << t << "\ttab=" << t_vec[i] + << "\tdiff=" << std::fabs(t_vec[i]-t) << std::endl;; + } + + return 0; +} + + +// EOF + + + + + + + + diff --git a/src/boost/libs/math/example/policy_eg_1.cpp b/src/boost/libs/math/example/policy_eg_1.cpp new file mode 100644 index 000000000..7f8d9fbb4 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_1.cpp @@ -0,0 +1,70 @@ +// Copyright John Maddock 2007. +// Copyright Paul A> Bristow 2010 +// 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) + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_1 + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; + +// Define the policy to use: +using namespace boost::math::policies; // may be convenient, or + +using boost::math::policies::policy; +// Types of error whose action can be altered by policies:. +using boost::math::policies::evaluation_error; +using boost::math::policies::domain_error; +using boost::math::policies::overflow_error; +using boost::math::policies::domain_error; +using boost::math::policies::pole_error; +// Actions on error (in enum error_policy_type): +using boost::math::policies::errno_on_error; +using boost::math::policies::ignore_error; +using boost::math::policies::throw_on_error; +using boost::math::policies::user_error; + +typedef policy< + domain_error<errno_on_error>, + pole_error<errno_on_error>, + overflow_error<errno_on_error>, + evaluation_error<errno_on_error> +> c_policy; +// +// Now use the policy when calling tgamma: + +// http://msdn.microsoft.com/en-us/library/t3ayayh1.aspx +// Microsoft errno declared in STDLIB.H as "extern int errno;" + +int main() +{ + errno = 0; // Reset. + cout << "Result of tgamma(30000) is: " + << tgamma(30000, c_policy()) << endl; // Too big parameter + cout << "errno = " << errno << endl; // errno 34 Numerical result out of range. + cout << "Result of tgamma(-10) is: " + << boost::math::tgamma(-10, c_policy()) << endl; // Negative parameter. + cout << "errno = " << errno << endl; // error 33 Numerical argument out of domain. +} // int main() + +//] + +/* Output + +policy_eg_1.cpp + Generating code + Finished generating code + policy_eg_1.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\policy_eg_1.exe + Result of tgamma(30000) is: 1.#INF + errno = 34 + Result of tgamma(-10) is: 1.#QNAN + errno = 33 + +*/ + + diff --git a/src/boost/libs/math/example/policy_eg_10.cpp b/src/boost/libs/math/example/policy_eg_10.cpp new file mode 100644 index 000000000..87f84c090 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_10.cpp @@ -0,0 +1,183 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_eg_10 + +/*` + +To understand how the rounding policies for +the discrete distributions can be used, we'll +use the 50-sample binomial distribution with a +success fraction of 0.5 once again, and calculate +all the possible quantiles at 0.05 and 0.95. + +Begin by including the needed headers (and some using statements for conciseness): + +*/ +#include <iostream> +using std::cout; using std::endl; +using std::left; using std::fixed; using std::right; using std::scientific; +#include <iomanip> +using std::setw; +using std::setprecision; + +#include <boost/math/distributions/binomial.hpp> +/*` + +Next we'll bring the needed declarations into scope, and +define distribution types for all the available rounding policies: + +*/ +// Avoid +// using namespace std; // and +// using namespace boost::math; +// to avoid potential ambiguity of names, like binomial. +// using namespace boost::math::policies; is small risk, but +// the necessary items are brought into scope thus: + +using boost::math::binomial_distribution; +using boost::math::policies::policy; +using boost::math::policies::discrete_quantile; + +using boost::math::policies::integer_round_outwards; +using boost::math::policies::integer_round_down; +using boost::math::policies::integer_round_up; +using boost::math::policies::integer_round_nearest; +using boost::math::policies::integer_round_inwards; +using boost::math::policies::real; + +using boost::math::binomial_distribution; // Not std::binomial_distribution. + +typedef binomial_distribution< + double, + policy<discrete_quantile<integer_round_outwards> > > + binom_round_outwards; + +typedef binomial_distribution< + double, + policy<discrete_quantile<integer_round_inwards> > > + binom_round_inwards; + +typedef binomial_distribution< + double, + policy<discrete_quantile<integer_round_down> > > + binom_round_down; + +typedef binomial_distribution< + double, + policy<discrete_quantile<integer_round_up> > > + binom_round_up; + +typedef binomial_distribution< + double, + policy<discrete_quantile<integer_round_nearest> > > + binom_round_nearest; + +typedef binomial_distribution< + double, + policy<discrete_quantile<real> > > + binom_real_quantile; + +/*` +Now let's set to work calling those quantiles: +*/ + +int main() +{ + cout << + "Testing rounding policies for a 50 sample binomial distribution,\n" + "with a success fraction of 0.5.\n\n" + "Lower quantiles are calculated at p = 0.05\n\n" + "Upper quantiles at p = 0.95.\n\n"; + + cout << setw(25) << right + << "Policy"<< setw(18) << right + << "Lower Quantile" << setw(18) << right + << "Upper Quantile" << endl; + + // Test integer_round_outwards: + cout << setw(25) << right + << "integer_round_outwards" + << setw(18) << right + << quantile(binom_round_outwards(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_round_outwards(50, 0.5), 0.95) + << endl; + + // Test integer_round_inwards: + cout << setw(25) << right + << "integer_round_inwards" + << setw(18) << right + << quantile(binom_round_inwards(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_round_inwards(50, 0.5), 0.95) + << endl; + + // Test integer_round_down: + cout << setw(25) << right + << "integer_round_down" + << setw(18) << right + << quantile(binom_round_down(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_round_down(50, 0.5), 0.95) + << endl; + + // Test integer_round_up: + cout << setw(25) << right + << "integer_round_up" + << setw(18) << right + << quantile(binom_round_up(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_round_up(50, 0.5), 0.95) + << endl; + + // Test integer_round_nearest: + cout << setw(25) << right + << "integer_round_nearest" + << setw(18) << right + << quantile(binom_round_nearest(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_round_nearest(50, 0.5), 0.95) + << endl; + + // Test real: + cout << setw(25) << right + << "real" + << setw(18) << right + << quantile(binom_real_quantile(50, 0.5), 0.05) + << setw(18) << right + << quantile(binom_real_quantile(50, 0.5), 0.95) + << endl; +} // int main() + +/*` + +Which produces the program output: + +[pre + policy_eg_10.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\policy_eg_10.exe + Testing rounding policies for a 50 sample binomial distribution, + with a success fraction of 0.5. + + Lower quantiles are calculated at p = 0.05 + + Upper quantiles at p = 0.95. + + Policy Lower Quantile Upper Quantile + integer_round_outwards 18 31 + integer_round_inwards 19 30 + integer_round_down 18 30 + integer_round_up 19 31 + integer_round_nearest 19 30 + real 18.701 30.299 +] + +*/ + +//] //[policy_eg_10] ends quickbook import. diff --git a/src/boost/libs/math/example/policy_eg_2.cpp b/src/boost/libs/math/example/policy_eg_2.cpp new file mode 100644 index 000000000..3ab8312e8 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_2.cpp @@ -0,0 +1,65 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_2 + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; + +int main() +{ + // using namespace boost::math::policies; // or + using boost::math::policies::errno_on_error; + using boost::math::policies::make_policy; + using boost::math::policies::pole_error; + using boost::math::policies::domain_error; + using boost::math::policies::overflow_error; + using boost::math::policies::evaluation_error; + + errno = 0; + std::cout << "Result of tgamma(30000) is: " + << boost::math::tgamma( + 30000, + make_policy( + domain_error<errno_on_error>(), + pole_error<errno_on_error>(), + overflow_error<errno_on_error>(), + evaluation_error<errno_on_error>() + ) + ) << std::endl; + // Check errno was set: + std::cout << "errno = " << errno << std::endl; + // and again with evaluation at a pole: + std::cout << "Result of tgamma(-10) is: " + << boost::math::tgamma( + -10, + make_policy( + domain_error<errno_on_error>(), + pole_error<errno_on_error>(), + overflow_error<errno_on_error>(), + evaluation_error<errno_on_error>() + ) + ) << std::endl; + // Check errno was set: + std::cout << "errno = " << errno << std::endl; +} + +//] //[/policy_eg_2] + +/* + +Output: + + Result of tgamma(30000) is: 1.#INF + errno = 34 + Result of tgamma(-10) is: 1.#QNAN + errno = 33 +*/ + diff --git a/src/boost/libs/math/example/policy_eg_3.cpp b/src/boost/libs/math/example/policy_eg_3.cpp new file mode 100644 index 000000000..adf8c9e44 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_3.cpp @@ -0,0 +1,55 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2007, 2010. + +// 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) + +#ifdef _MSC_VER +# pragma warning (disable : 4305) // 'initializing' : truncation from 'long double' to 'const eval_type' +# pragma warning (disable : 4244) // conversion from 'long double' to 'const eval_type' +#endif + +#include <iostream> +using std::cout; using std::endl; + +//[policy_eg_3 + +#include <boost/math/distributions/binomial.hpp> +using boost::math::binomial_distribution; + +// Begin by defining a policy type, that gives the behaviour we want: + +//using namespace boost::math::policies; or explicitly +using boost::math::policies::policy; + +using boost::math::policies::promote_float; +using boost::math::policies::discrete_quantile; +using boost::math::policies::integer_round_nearest; + +typedef policy< + promote_float<false>, // Do not promote to double. + discrete_quantile<integer_round_nearest> // Round result to nearest integer. +> mypolicy; +// +// Then define a new distribution that uses it: +typedef boost::math::binomial_distribution<float, mypolicy> mybinom; + +// And now use it to get the quantile: + +int main() +{ + cout << "quantile(mybinom(200, 0.25), 0.05) is: " << + quantile(mybinom(200, 0.25), 0.05) << endl; +} + +//] + +/* + +Output: + + quantile(mybinom(200, 0.25), 0.05) is: 40 + +*/ + diff --git a/src/boost/libs/math/example/policy_eg_4.cpp b/src/boost/libs/math/example/policy_eg_4.cpp new file mode 100644 index 000000000..5cd281618 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_4.cpp @@ -0,0 +1,107 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 + +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_4 + +/*` +Suppose we want `C::foo()` to behave in a C-compatible way and set +`::errno` on error rather than throwing any exceptions. + +We'll begin by including the needed header for our function: +*/ + +#include <boost/math/special_functions.hpp> +//using boost::math::tgamma; // Not needed because using C::tgamma. + +/*` +Open up the "C" namespace that we'll use for our functions, and +define the policy type we want: in this case a C-style one that sets +::errno and returns a standard value, rather than throwing exceptions. + +Any policies we don't specify here will inherit the defaults. +*/ + +namespace C +{ // To hold our C-style policy. + //using namespace boost::math::policies; or explicitly: + using boost::math::policies::policy; + + using boost::math::policies::domain_error; + using boost::math::policies::pole_error; + using boost::math::policies::overflow_error; + using boost::math::policies::evaluation_error; + using boost::math::policies::errno_on_error; + + typedef policy< + domain_error<errno_on_error>, + pole_error<errno_on_error>, + overflow_error<errno_on_error>, + evaluation_error<errno_on_error> + > c_policy; + +/*` +All we need do now is invoke the BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS +macro passing our policy type c_policy as the single argument: +*/ + +BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy) + +} // close namespace C + +/*` +We now have a set of forwarding functions defined in namespace C +that all look something like this: + +`` +template <class RealType> +inline typename boost::math::tools::promote_args<RT>::type + tgamma(RT z) +{ + return boost::math::tgamma(z, c_policy()); +} +`` + +So that when we call `C::tgamma(z)`, we really end up calling +`boost::math::tgamma(z, C::c_policy())`: +*/ + +int main() +{ + errno = 0; + cout << "Result of tgamma(30000) is: " + << C::tgamma(30000) << endl; // Note using C::tgamma + cout << "errno = " << errno << endl; // errno = 34 + cout << "Result of tgamma(-10) is: " + << C::tgamma(-10) << endl; + cout << "errno = " << errno << endl; // errno = 33, overwriting previous value of 34. +} + +/*` + +Which outputs: + +[pre +Result of C::tgamma(30000) is: 1.#INF +errno = 34 +Result of C::tgamma(-10) is: 1.#QNAN +errno = 33 +] + +This mechanism is particularly useful when we want to define a project-wide policy, +and don't want to modify the Boost source, +or to set project wide build macros (possibly fragile and easy to forget). + +*/ +//] //[/policy_eg_4] + diff --git a/src/boost/libs/math/example/policy_eg_5.cpp b/src/boost/libs/math/example/policy_eg_5.cpp new file mode 100644 index 000000000..d022c9c85 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_5.cpp @@ -0,0 +1,66 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_5 + +#include <boost/math/special_functions.hpp> +// using boost::math::tgamma; // Would create an ambiguity between +// 'double boost::math::tgamma<int>(T)' and +// 'double 'anonymous-namespace'::tgamma<int>(RT)'. + +namespace mymath +{ // unnamed + +using namespace boost::math::policies; + +typedef policy< + domain_error<errno_on_error>, + pole_error<errno_on_error>, + overflow_error<errno_on_error>, + evaluation_error<errno_on_error> +> c_policy; + +BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(c_policy) + +/*` +So that when we call `mymath::tgamma(z)`, we really end up calling + `boost::math::tgamma(z, anonymous-namespace::c_policy())`. +*/ + +} // close unnamed namespace + +int main() +{ + errno = 0; + cout << "Result of tgamma(30000) is: " + << mymath::tgamma(30000) << endl; + // tgamma in unnamed namespace in this translation unit (file) only. + cout << "errno = " << errno << endl; + cout << "Result of tgamma(-10) is: " + << mymath::tgamma(-10) << endl; + cout << "errno = " << errno << endl; + // Default tgamma policy would throw an exception, and abort. +} + +//] //[/policy_eg_5] + +/* +Output: + + Result of tgamma(30000) is: 1.#INF + errno = 34 + Result of tgamma(-10) is: 1.#QNAN + errno = 33 + + +*/ diff --git a/src/boost/libs/math/example/policy_eg_6.cpp b/src/boost/libs/math/example/policy_eg_6.cpp new file mode 100644 index 000000000..57f92fccc --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_6.cpp @@ -0,0 +1,121 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_6 + +/*` +Suppose we want a set of distributions to behave as follows: + +* Return infinity on overflow, rather than throwing an exception. +* Don't perform any promotion from double to long double internally. +* Return the closest integer result from the quantiles of discrete +distributions. + +We'll begin by including the needed header for all the distributions: +*/ + +#include <boost/math/distributions.hpp> + +/*` + +Open up an appropriate namespace, calling it `my_distributions`, +for our distributions, and define the policy type we want. +Any policies we don't specify here will inherit the defaults: + +*/ + +namespace my_distributions +{ + using namespace boost::math::policies; + // using boost::math::policies::errno_on_error; // etc. + + typedef policy< + // return infinity and set errno rather than throw: + overflow_error<errno_on_error>, + // Don't promote double -> long double internally: + promote_double<false>, + // Return the closest integer result for discrete quantiles: + discrete_quantile<integer_round_nearest> + > my_policy; + +/*` + +All we need do now is invoke the BOOST_MATH_DECLARE_DISTRIBUTIONS +macro passing the floating point type `double` and policy types `my_policy` as arguments: + +*/ + +BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy) + +} // close namespace my_namespace + +/*` + +We now have a set of typedefs defined in namespace my_distributions +that all look something like this: + +`` +typedef boost::math::normal_distribution<double, my_policy> normal; +typedef boost::math::cauchy_distribution<double, my_policy> cauchy; +typedef boost::math::gamma_distribution<double, my_policy> gamma; +// etc +`` + +So that when we use my_distributions::normal we really end up using +`boost::math::normal_distribution<double, my_policy>`: + +*/ + +int main() +{ + // Construct distribution with something we know will overflow + // (using double rather than if promoted to long double): + my_distributions::normal norm(10, 2); + + errno = 0; + cout << "Result of quantile(norm, 0) is: " + << quantile(norm, 0) << endl; // -infinity. + cout << "errno = " << errno << endl; + errno = 0; + cout << "Result of quantile(norm, 1) is: " + << quantile(norm, 1) << endl; // +infinity. + cout << "errno = " << errno << endl; + + // Now try a discrete distribution. + my_distributions::binomial binom(20, 0.25); + cout << "Result of quantile(binom, 0.05) is: " + << quantile(binom, 0.05) << endl; // To check we get integer results. + cout << "Result of quantile(complement(binom, 0.05)) is: " + << quantile(complement(binom, 0.05)) << endl; +} + +/*` + +Which outputs: + +[pre +Result of quantile(norm, 0) is: -1.#INF +errno = 34 +Result of quantile(norm, 1) is: 1.#INF +errno = 34 +Result of quantile(binom, 0.05) is: 1 +Result of quantile(complement(binom, 0.05)) is: 8 +] + +This mechanism is particularly useful when we want to define a +project-wide policy, and don't want to modify the Boost source +or set project wide build macros (possibly fragile and easy to forget). + +*/ +//] //[/policy_eg_6] + diff --git a/src/boost/libs/math/example/policy_eg_7.cpp b/src/boost/libs/math/example/policy_eg_7.cpp new file mode 100644 index 000000000..2865bea36 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_7.cpp @@ -0,0 +1,73 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; +#include <cerrno> // for ::errno + +//[policy_eg_7 + +#include <boost/math/distributions.hpp> // All distributions. +// using boost::math::normal; // Would create an ambiguity between +// boost::math::normal_distribution<RealType> boost::math::normal and +// 'anonymous-namespace'::normal'. + +namespace +{ // anonymous or unnamed (rather than named as in policy_eg_6.cpp). + + using namespace boost::math::policies; + // using boost::math::policies::errno_on_error; // etc. + typedef policy< + // return infinity and set errno rather than throw: + overflow_error<errno_on_error>, + // Don't promote double -> long double internally: + promote_double<false>, + // Return the closest integer result for discrete quantiles: + discrete_quantile<integer_round_nearest> + > my_policy; + + BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy) + +} // close namespace my_namespace + +int main() +{ + // Construct distribution with something we know will overflow. + normal norm(10, 2); // using 'anonymous-namespace'::normal + errno = 0; + cout << "Result of quantile(norm, 0) is: " + << quantile(norm, 0) << endl; + cout << "errno = " << errno << endl; + errno = 0; + cout << "Result of quantile(norm, 1) is: " + << quantile(norm, 1) << endl; + cout << "errno = " << errno << endl; + // + // Now try a discrete distribution: + binomial binom(20, 0.25); + cout << "Result of quantile(binom, 0.05) is: " + << quantile(binom, 0.05) << endl; + cout << "Result of quantile(complement(binom, 0.05)) is: " + << quantile(complement(binom, 0.05)) << endl; +} + +//] //[/policy_eg_7] + +/* + +Output: + + Result of quantile(norm, 0) is: -1.#INF + errno = 34 + Result of quantile(norm, 1) is: 1.#INF + errno = 34 + Result of quantile(binom, 0.05) is: 1 + Result of quantile(complement(binom, 0.05)) is: 8 + +*/ diff --git a/src/boost/libs/math/example/policy_eg_8.cpp b/src/boost/libs/math/example/policy_eg_8.cpp new file mode 100644 index 000000000..775f042e2 --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_8.cpp @@ -0,0 +1,133 @@ +// Copyright John Maddock 2007. +// Copyright Paul a. Bristow 2010 +// 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) + +// 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 : 4100) // unreferenced formal parameters +#endif + +#include <iostream> +using std::cout; using std::endl; using std::cerr; + +//[policy_eg_8 + +/*` +Suppose we want our own user-defined error handlers rather than the +any of the default ones supplied by the library to be used. +If we set the policy for a specific type of error to `user_error` +then the library will call a user-supplied error handler. +These are forward declared, but not defined in +boost/math/policies/error_handling.hpp like this: + + namespace boost{ namespace math{ namespace policies{ + + template <class T> + T user_domain_error(const char* function, const char* message, const T& val); + template <class T> + T user_pole_error(const char* function, const char* message, const T& val); + template <class T> + T user_overflow_error(const char* function, const char* message, const T& val); + template <class T> + T user_underflow_error(const char* function, const char* message, const T& val); + template <class T> + T user_denorm_error(const char* function, const char* message, const T& val); + template <class T> + T user_evaluation_error(const char* function, const char* message, const T& val); + template <class T, class TargetType> + T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t); + template <class T> + T user_indeterminate_result_error(const char* function, const char* message, const T& val); + + }}} // namespaces + +So out first job is to include the header we want to use, and then +provide definitions for our user-defined error handlers that we want to use. +We only provide our special domain and pole error handlers; +other errors like overflow and underflow use the default. +*/ + +#include <boost/math/special_functions.hpp> + +namespace boost{ namespace math +{ + namespace policies + { + template <class T> + T user_domain_error(const char* function, const char* message, const T& val) + { // Ignoring function, message and val for this example, perhaps unhelpfully. + cerr << "Domain Error!" << endl; + return std::numeric_limits<T>::quiet_NaN(); + } + + template <class T> + T user_pole_error(const char* function, const char* message, const T& val) + { // Ignoring function, message and val for this example, perhaps unhelpfully. + cerr << "Pole Error!" << endl; + return std::numeric_limits<T>::quiet_NaN(); + } + } // namespace policies +}} // namespace boost{ namespace math + + +/*` +Now we'll need to define a suitable policy that will call these handlers, +and define some forwarding functions that make use of the policy: +*/ + +namespace mymath{ + +using namespace boost::math::policies; + +typedef policy< + domain_error<user_error>, + pole_error<user_error> +> user_error_policy; + +BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy) + +} // close unnamed namespace + +/*` +We now have a set of forwarding functions defined in namespace mymath +that all look something like this: + +`` +template <class RealType> +inline typename boost::math::tools::promote_args<RT>::type + tgamma(RT z) +{ + return boost::math::tgamma(z, user_error_policy()); +} +`` + +So that when we call `mymath::tgamma(z)` we really end up calling +`boost::math::tgamma(z, user_error_policy())`, and any +errors will get directed to our own error handlers. +*/ + +int main() +{ + cout << "Result of erf_inv(-10) is: " + << mymath::erf_inv(-10) << endl; + cout << "Result of tgamma(-10) is: " + << mymath::tgamma(-10) << endl; +} + +/*` + +Which outputs: + +[pre + Domain Error! + Pole Error! + Result of erf_inv(-10) is: 1.#QNAN + Result of tgamma(-10) is: 1.#QNAN +] +*/ + +//] // //[/policy_eg_8] diff --git a/src/boost/libs/math/example/policy_eg_9.cpp b/src/boost/libs/math/example/policy_eg_9.cpp new file mode 100644 index 000000000..dceda875c --- /dev/null +++ b/src/boost/libs/math/example/policy_eg_9.cpp @@ -0,0 +1,313 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +#include <boost/format.hpp> +using std::cout; using std::endl; using std::cerr; + +//[policy_eg_9 + +/*` +The previous example was all well and good, but the custom error handlers +didn't really do much of any use. In this example we'll implement all +the custom handlers and show how the information provided to them can be +used to generate nice formatted error messages. + +Each error handler has the general form: + + template <class T> + T user_``['error_type]``( + const char* function, + const char* message, + const T& val); + +and accepts three arguments: + +[variablelist +[[const char* function] + [The name of the function that raised the error, this string + contains one or more %1% format specifiers that should be + replaced by the name of real type T, like float or double.]] +[[const char* message] + [A message associated with the error, normally this + contains a %1% format specifier that should be replaced with + the value of ['value]: however note that overflow and underflow messages + do not contain this %1% specifier (since the value of ['value] is + immaterial in these cases).]] +[[const T& value] + [The value that caused the error: either an argument to the function + if this is a domain or pole error, the tentative result + if this is a denorm or evaluation error, or zero or infinity for + underflow or overflow errors.]] +] + +As before we'll include the headers we need first: + +*/ + +#include <boost/math/special_functions.hpp> + +/*` +Next we'll implement our own error handlers for each type of error, +starting with domain errors: +*/ + +namespace boost{ namespace math{ +namespace policies +{ + +template <class T> +T user_domain_error(const char* function, const char* message, const T& val) +{ + /*` + We'll begin with a bit of defensive programming in case function or message are empty: + */ + if(function == 0) + function = "Unknown function with arguments of type %1%"; + if(message == 0) + message = "Cause unknown with bad argument %1%"; + /*` + Next we'll format the name of the function with the name of type T, perhaps double: + */ + std::string msg("Error in function "); + msg += (boost::format(function) % typeid(T).name()).str(); + /*` + Then likewise format the error message with the value of parameter /val/, + making sure we output all the potentially significant digits of /val/: + */ + msg += ": \n"; + int prec = 2 + (std::numeric_limits<T>::digits * 30103UL) / 100000UL; + // int prec = std::numeric_limits<T>::max_digits10; // For C++0X Standard Library + msg += (boost::format(message) % boost::io::group(std::setprecision(prec), val)).str(); + /*` + Now we just have to do something with the message, we could throw an + exception, but for the purposes of this example we'll just dump the message + to std::cerr: + */ + std::cerr << msg << std::endl; + /*` + Finally the only sensible value we can return from a domain error is a NaN: + */ + return std::numeric_limits<T>::quiet_NaN(); +} + +/*` +Pole errors are essentially a special case of domain errors, +so in this example we'll just return the result of a domain error: +*/ + +template <class T> +T user_pole_error(const char* function, const char* message, const T& val) +{ + return user_domain_error(function, message, val); +} + +/*` +Overflow errors are very similar to domain errors, except that there's +no %1% format specifier in the /message/ parameter: +*/ +template <class T> +T user_overflow_error(const char* function, const char* message, const T& val) +{ + if(function == 0) + function = "Unknown function with arguments of type %1%"; + if(message == 0) + message = "Result of function is too large to represent"; + + std::string msg("Error in function "); + msg += (boost::format(function) % typeid(T).name()).str(); + + msg += ": \n"; + msg += message; + + std::cerr << msg << std::endl; + + // Value passed to the function is an infinity, just return it: + return val; +} + +/*` +Underflow errors are much the same as overflow: +*/ + +template <class T> +T user_underflow_error(const char* function, const char* message, const T& val) +{ + if(function == 0) + function = "Unknown function with arguments of type %1%"; + if(message == 0) + message = "Result of function is too small to represent"; + + std::string msg("Error in function "); + msg += (boost::format(function) % typeid(T).name()).str(); + + msg += ": \n"; + msg += message; + + std::cerr << msg << std::endl; + + // Value passed to the function is zero, just return it: + return val; +} + +/*` +Denormalised results are much the same as underflow: +*/ + +template <class T> +T user_denorm_error(const char* function, const char* message, const T& val) +{ + if(function == 0) + function = "Unknown function with arguments of type %1%"; + if(message == 0) + message = "Result of function is denormalised"; + + std::string msg("Error in function "); + msg += (boost::format(function) % typeid(T).name()).str(); + + msg += ": \n"; + msg += message; + + std::cerr << msg << std::endl; + + // Value passed to the function is denormalised, just return it: + return val; +} + +/*` +Which leaves us with evaluation errors: these occur when an internal +error occurs that prevents the function being fully evaluated. +The parameter /val/ contains the closest approximation to the result +found so far: +*/ + +template <class T> +T user_evaluation_error(const char* function, const char* message, const T& val) +{ + if(function == 0) + function = "Unknown function with arguments of type %1%"; + if(message == 0) + message = "An internal evaluation error occurred with " + "the best value calculated so far of %1%"; + + std::string msg("Error in function "); + msg += (boost::format(function) % typeid(T).name()).str(); + + msg += ": \n"; + int prec = 2 + (std::numeric_limits<T>::digits * 30103UL) / 100000UL; + // int prec = std::numeric_limits<T>::max_digits10; // For C++0X Standard Library + msg += (boost::format(message) % boost::io::group(std::setprecision(prec), val)).str(); + + std::cerr << msg << std::endl; + + // What do we return here? This is generally a fatal error, that should never occur, + // so we just return a NaN for the purposes of the example: + return std::numeric_limits<T>::quiet_NaN(); +} + +} // policies +}} // boost::math + + +/*` +Now we'll need to define a suitable policy that will call these handlers, +and define some forwarding functions that make use of the policy: +*/ + +namespace mymath +{ // unnamed. + +using namespace boost::math::policies; + +typedef policy< + domain_error<user_error>, + pole_error<user_error>, + overflow_error<user_error>, + underflow_error<user_error>, + denorm_error<user_error>, + evaluation_error<user_error> +> user_error_policy; + +BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(user_error_policy) + +} // unnamed namespace + +/*` +We now have a set of forwarding functions, defined in namespace mymath, +that all look something like this: + +`` +template <class RealType> +inline typename boost::math::tools::promote_args<RT>::type + tgamma(RT z) +{ + return boost::math::tgamma(z, user_error_policy()); +} +`` + +So that when we call `mymath::tgamma(z)` we really end up calling +`boost::math::tgamma(z, user_error_policy())`, and any +errors will get directed to our own error handlers: +*/ + +int main() +{ + // Raise a domain error: + cout << "Result of erf_inv(-10) is: " + << mymath::erf_inv(-10) << std::endl << endl; + // Raise a pole error: + cout << "Result of tgamma(-10) is: " + << mymath::tgamma(-10) << std::endl << endl; + // Raise an overflow error: + cout << "Result of tgamma(3000) is: " + << mymath::tgamma(3000) << std::endl << endl; + // Raise an underflow error: + cout << "Result of tgamma(-190.5) is: " + << mymath::tgamma(-190.5) << std::endl << endl; + // Unfortunately we can't predictably raise a denormalised + // result, nor can we raise an evaluation error in this example + // since these should never really occur! +} // int main() + +/*` + +Which outputs: + +[pre +Error in function boost::math::erf_inv<double>(double, double): +Argument outside range \[-1, 1\] in inverse erf function (got p=-10). +Result of erf_inv(-10) is: 1.#QNAN + +Error in function boost::math::tgamma<long double>(long double): +Evaluation of tgamma at a negative integer -10. +Result of tgamma(-10) is: 1.#QNAN + +Error in function boost::math::tgamma<long double>(long double): +Result of tgamma is too large to represent. +Error in function boost::math::tgamma<double>(double): +Result of function is too large to represent +Result of tgamma(3000) is: 1.#INF + +Error in function boost::math::tgamma<long double>(long double): +Result of tgamma is too large to represent. +Error in function boost::math::tgamma<long double>(long double): +Result of tgamma is too small to represent. +Result of tgamma(-190.5) is: 0 +] + +Notice how some of the calls result in an error handler being called more +than once, or for more than one handler to be called: this is an artefact +of the fact that many functions are implemented in terms of one or more +sub-routines each of which may have it's own error handling. For example +`tgamma(-190.5)` is implemented in terms of `tgamma(190.5)` - which overflows - +the reflection formula for `tgamma` then notices that it is dividing by +infinity and so underflows. +*/ + +//] //[/policy_eg_9] diff --git a/src/boost/libs/math/example/policy_ref_snip1.cpp b/src/boost/libs/math/example/policy_ref_snip1.cpp new file mode 100644 index 000000000..217719395 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip1.cpp @@ -0,0 +1,75 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_ref_snip1 + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; + +//using namespace boost::math::policies; may also be convenient. +using boost::math::policies::policy; +using boost::math::policies::evaluation_error; +using boost::math::policies::domain_error; +using boost::math::policies::overflow_error; +using boost::math::policies::domain_error; +using boost::math::policies::pole_error; +using boost::math::policies::errno_on_error; + +// Define a policy: +typedef policy< + domain_error<errno_on_error>, + pole_error<errno_on_error>, + overflow_error<errno_on_error>, + evaluation_error<errno_on_error> +> my_policy; + +double my_value = 0.; // + +// Call the function applying my_policy: +double t1 = tgamma(my_value, my_policy()); + +// Alternatively (and equivalently) we could use helpful function +// make_policy and define everything at the call site: +double t2 = tgamma(my_value, + make_policy( + domain_error<errno_on_error>(), + pole_error<errno_on_error>(), + overflow_error<errno_on_error>(), + evaluation_error<errno_on_error>() ) + ); +//] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "my_value = " << my_value << endl; + try + { // First with default policy - throw an exception. + cout << "tgamma(my_value) = " << tgamma(my_value) << endl; + } + catch(const std::exception& e) + { + cout <<"\n""Message from thrown exception was:\n " << e.what() << endl; + } + + cout << "tgamma(my_value, my_policy() = " << t1 << endl; + cout << "tgamma(my_value, make_policy(domain_error<errno_on_error>(), pole_error<errno_on_error>(), overflow_error<errno_on_error>(), evaluation_error<errno_on_error>() ) = " << t2 << endl; +} + +/* +Output: + my_value = 0 + + Message from thrown exception was: + Error in function boost::math::tgamma<long double>(long double): Evaluation of tgamma at a negative integer 0. + tgamma(my_value, my_policy() = 1.#QNAN + tgamma(my_value, make_policy(domain_error<errno_on_error>(), pole_error<errno_on_error>(), overflow_error<errno_on_error>(), evaluation_error<errno_on_error>() ) = 1.#QNAN +*/ diff --git a/src/boost/libs/math/example/policy_ref_snip10.cpp b/src/boost/libs/math/example/policy_ref_snip10.cpp new file mode 100644 index 000000000..a4806dc6e --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip10.cpp @@ -0,0 +1,40 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// Setting precision in a single function call using make_policy. + +#include <iostream> +using std::cout; using std::endl; + +//[policy_ref_snip10 + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; + +using namespace boost::math::policies; + +double t = tgamma(12, policy<digits10<5> >()); // Concise make_policy. + +//] //[/policy_ref_snip10] + + + +int main() +{ + cout << "tgamma(12, policy<digits10<5> >()) = "<< t << endl; +} + +/* + +Output: + + tgamma(12, policy<digits10<5> >()) = 3.99168e+007 + +*/ + diff --git a/src/boost/libs/math/example/policy_ref_snip11.cpp b/src/boost/libs/math/example/policy_ref_snip11.cpp new file mode 100644 index 000000000..ea7c737c6 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip11.cpp @@ -0,0 +1,45 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; + +// Setting (approximate) precision 25 bits in a single function call using make_policy. + +//[policy_ref_snip11 + +#include <boost/math/distributions/normal.hpp> +using boost::math::normal_distribution; + +using namespace boost::math::policies; + +const int bits = 25; // approximate precision. + +double q = quantile( + normal_distribution<double, policy<digits2<bits> > >(), + 0.05); // 5% quantile. + +//] //[/policy_ref_snip11] + +int main() +{ + std::streamsize p = 2 + (bits * 30103UL) / 100000UL; + // Approximate number of significant decimal digits for 25 bits. + cout.precision(p); + cout << bits << " binary bits is approximately equivalent to " << p << " decimal digits " << endl; + cout << "quantile(normal_distribution<double, policy<digits2<25> > >(), 0.05 = " + << q << endl; // -1.64485 +} + +/* +Output: + 25 binary bits is approximately equivalent to 9 decimal digits + quantile(normal_distribution<double, policy<digits2<25> > >(), 0.05 = -1.64485363 + */ + diff --git a/src/boost/libs/math/example/policy_ref_snip12.cpp b/src/boost/libs/math/example/policy_ref_snip12.cpp new file mode 100644 index 000000000..e406ce561 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip12.cpp @@ -0,0 +1,55 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// Define tgamma function with a no overflow policy +// into a specific namespace-scope. + +#include <iostream> +using std::cout; using std::endl; + +//[policy_ref_snip12 + +#include <boost/math/special_functions/gamma.hpp> +//using boost::math::tgamma; +// Need not declare using boost::math::tgamma here, +// because will define tgamma in myspace using macro below. + +namespace myspace +{ + using namespace boost::math::policies; + + // Define a policy that does not throw on overflow: + typedef policy<overflow_error<errno_on_error> > my_policy; + + // Define the special functions in this scope to use the policy: + BOOST_MATH_DECLARE_SPECIAL_FUNCTIONS(my_policy) +} + +// Now we can use myspace::tgamma etc. +// They will automatically use "my_policy": +// +double t = myspace::tgamma(30.0); // Will *not* throw on overflow, +// despite the large value of factorial 30 = 265252859812191058636308480000000 +// unlike default policy boost::math::tgamma; + +//] + +int main() +{ + cout << "myspace::tgamma(30.0) = " << t << endl; +} + +/* + +Output: + +myspace::tgamma(30.0) = 8.84176e+030 + +*/ + diff --git a/src/boost/libs/math/example/policy_ref_snip13.cpp b/src/boost/libs/math/example/policy_ref_snip13.cpp new file mode 100644 index 000000000..ce4b0948c --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip13.cpp @@ -0,0 +1,81 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <boost/config.hpp> +#ifdef _MSC_VER +# pragma warning (disable : 4189) // 'd' : local variable is initialized but not referenced +#endif +#ifdef BOOST_GCC +# pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#include <iostream> +using std::cout; using std::endl; + +#include <stdexcept> +using std::domain_error; + +//[policy_ref_snip13 + +#include <boost/math/distributions/cauchy.hpp> + +namespace myspace +{ // using namespace boost::math::policies; // May be convenient in myspace. + + // Define a policy called my_policy to use. + using boost::math::policies::policy; + +// In this case we want all the distribution accessor functions to compile, +// even if they are mathematically undefined, so +// make the policy assert_undefined. + using boost::math::policies::assert_undefined; + +typedef policy<assert_undefined<false> > my_policy; + +// Finally apply this policy to type double. +BOOST_MATH_DECLARE_DISTRIBUTIONS(double, my_policy) +} // namespace myspace + +// Now we can use myspace::cauchy etc, which will use policy +// myspace::mypolicy: +// +// This compiles but throws a domain error exception at runtime. +// Caution! If you omit the try'n'catch blocks, +// it will just silently terminate, giving no clues as to why! +// So try'n'catch blocks are very strongly recommended. + +void test_cauchy() +{ + try + { + double d = mean(myspace::cauchy()); // Cauchy does not have a mean! + (void) d; + } + catch(const std::domain_error& e) + { + cout << e.what() << endl; + } +} + +//] //[/policy_ref_snip13] + +int main() +{ + test_cauchy(); +} + +/* + +Output: + +policy_snip_13.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\policy_snip_13.exe + Error in function boost::math::mean(cauchy<double>&): The Cauchy distribution does not have a mean: the only possible return value is 1.#QNAN. + + */ + diff --git a/src/boost/libs/math/example/policy_ref_snip2.cpp b/src/boost/libs/math/example/policy_ref_snip2.cpp new file mode 100644 index 000000000..304250d4f --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip2.cpp @@ -0,0 +1,47 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; + +//[policy_ref_snip2 + +#include <boost/math/distributions/normal.hpp> +using boost::math::normal_distribution; + +using namespace boost::math::policies; + +// Define a specific policy: +typedef policy< + overflow_error<ignore_error> + > my_policy; + +// Define the distribution, using my_policy: +typedef normal_distribution<double, my_policy> my_norm; + +// Construct a my_norm distribution, using default mean and standard deviation, +// and get a 0.05 or 5% quantile: +double q = quantile(my_norm(), 0.05); // = -1.64485 + +//] //[/policy_ref_snip2] + +int main() +{ + my_norm n; // Construct a my_norm distribution, + // using default mean zero and standard deviation unity. + double q = quantile(n, 0.05); // and get a quantile. + cout << "quantile(my_norm(), 0.05) = " << q << endl; +} + +/* + +Output: + + quantile(my_norm(), 0.05) = -1.64485 +*/ diff --git a/src/boost/libs/math/example/policy_ref_snip3.cpp b/src/boost/libs/math/example/policy_ref_snip3.cpp new file mode 100644 index 000000000..b3820ad30 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip3.cpp @@ -0,0 +1,40 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +double some_value = 2.; + +//[policy_ref_snip3 + +#include <boost/math/special_functions/gamma.hpp> + +using namespace boost::math::policies; +using boost::math::tgamma; + +// Define a new policy *not* internally promoting RealType to double: +typedef policy< + promote_double<false> + > my_policy; + +// Call the function, applying the new policy: +double t1 = tgamma(some_value, my_policy()); + +// Alternatively we could use helper function make_policy, +// and concisely define everything at the call site: +double t2 = tgamma(some_value, make_policy(promote_double<false>())); + +//] //[\policy_ref_snip3] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "tgamma(some_value, my_policy()) = " << t1 + << ", tgamma(some_value, make_policy(promote_double<false>()) = " << t2 << endl; +} diff --git a/src/boost/libs/math/example/policy_ref_snip4.cpp b/src/boost/libs/math/example/policy_ref_snip4.cpp new file mode 100644 index 000000000..7df35be1c --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip4.cpp @@ -0,0 +1,41 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// 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 : 4305) // 'initializing' : truncation from 'long double' to 'const eval_type' +# pragma warning (disable : 4244) // 'conversion' : truncation from 'long double' to 'const eval_type' +#endif + +//[policy_ref_snip4 + +#include <boost/math/distributions/normal.hpp> +using boost::math::normal_distribution; + +using namespace boost::math::policies; + +// Define a policy: +typedef policy< + promote_float<false> + > my_policy; + +// Define the new normal distribution using my_policy: +typedef normal_distribution<float, my_policy> my_norm; + +// Get a quantile: +float q = quantile(my_norm(), 0.05f); + +//] [policy_ref_snip4] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << " quantile(my_norm(), 0.05f) = " << q << endl; // -1.64485 +} diff --git a/src/boost/libs/math/example/policy_ref_snip5.cpp b/src/boost/libs/math/example/policy_ref_snip5.cpp new file mode 100644 index 000000000..06f270af4 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip5.cpp @@ -0,0 +1,45 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_ref_snip5 + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial_distribution; + +using namespace boost::math::policies; + +typedef negative_binomial_distribution< + double, + policy<discrete_quantile<real> > + > dist_type; + +// Lower 5% quantile: +double x = quantile(dist_type(20, 0.3), 0.05); +// Upper 95% quantile: +double y = quantile(complement(dist_type(20, 0.3), 0.05)); + +//] //[/policy_ref_snip5] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "quantile(dist_type(20, 0.3), 0.05) = " << x + << "\nquantile(complement(dist_type(20, 0.3), 0.05) = " << y << endl; +} + +/* + +Output: + quantile(dist_type(20, 0.3), 0.05) = 27.3898 + quantile(complement(dist_type(20, 0.3), 0.05) = 68.1584 + + */ + diff --git a/src/boost/libs/math/example/policy_ref_snip6.cpp b/src/boost/libs/math/example/policy_ref_snip6.cpp new file mode 100644 index 000000000..9dc207297 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip6.cpp @@ -0,0 +1,38 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_ref_snip6 + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial; + +// Use the default rounding policy integer_round_outwards. +// Lower quantile rounded down: +double x = quantile(negative_binomial(20, 0.3), 0.05); // rounded up 27 from 27.3898 +// Upper quantile rounded up: +double y = quantile(complement(negative_binomial(20, 0.3), 0.05)); // rounded down to 69 from 68.1584 + +//] //[/policy_ref_snip6] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "quantile(negative_binomial(20, 0.3), 0.05) = "<< x <<endl + << "quantile(complement(negative_binomial(20, 0.3), 0.05)) = " << y << endl; +} + +/* +Output: + + quantile(negative_binomial(20, 0.3), 0.05) = 27 + quantile(complement(negative_binomial(20, 0.3), 0.05)) = 69 +*/ + diff --git a/src/boost/libs/math/example/policy_ref_snip7.cpp b/src/boost/libs/math/example/policy_ref_snip7.cpp new file mode 100644 index 000000000..004205b01 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip7.cpp @@ -0,0 +1,48 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_ref_snip7 + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial_distribution; + +using namespace boost::math::policies; + +typedef negative_binomial_distribution< + double, + policy<discrete_quantile<integer_round_inwards> > + > dist_type; + +// Lower quantile rounded up: +double x = quantile(dist_type(20, 0.3), 0.05); // 28 rounded up from 27.3898 +// Upper quantile rounded down: +double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 68 rounded down from 68.1584 + +//] //[/policy_ref_snip7] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "using policy<discrete_quantile<integer_round_inwards> > " << endl + << "quantile(dist_type(20, 0.3), 0.05) = " << x << endl + << "quantile(complement(dist_type(20, 0.3), 0.05)) = " << y << endl; +} + +/* + +Output: + using policy<discrete_quantile<integer_round_inwards> > + quantile(dist_type(20, 0.3), 0.05) = 28 + quantile(complement(dist_type(20, 0.3), 0.05)) = 68 + + +*/ + diff --git a/src/boost/libs/math/example/policy_ref_snip8.cpp b/src/boost/libs/math/example/policy_ref_snip8.cpp new file mode 100644 index 000000000..abc48b9ae --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip8.cpp @@ -0,0 +1,47 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010. +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//[policy_ref_snip8 + +#include <boost/math/distributions/negative_binomial.hpp> +using boost::math::negative_binomial_distribution; + +using namespace boost::math::policies; + +typedef negative_binomial_distribution< + double, + policy<discrete_quantile<integer_round_nearest> > + > dist_type; + +// Lower quantile rounded (down) to nearest: +double x = quantile(dist_type(20, 0.3), 0.05); // 27 +// Upper quantile rounded (down) to nearest: +double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 68 + +//] //[/policy_ref_snip8] + +#include <iostream> +using std::cout; using std::endl; + +int main() +{ + cout << "using policy<discrete_quantile<integer_round_nearest> " << endl + << "quantile(dist_type(20, 0.3), 0.05) = " << x << endl + << "quantile(complement(dist_type(20, 0.3), 0.05)) " << y << endl; +} + +/* + +Output: + + using policy<discrete_quantile<integer_round_nearest> + quantile(dist_type(20, 0.3), 0.05) = 27 + quantile(complement(dist_type(20, 0.3), 0.05)) 68 + +*/ diff --git a/src/boost/libs/math/example/policy_ref_snip9.cpp b/src/boost/libs/math/example/policy_ref_snip9.cpp new file mode 100644 index 000000000..ed38d4601 --- /dev/null +++ b/src/boost/libs/math/example/policy_ref_snip9.cpp @@ -0,0 +1,36 @@ +// Copyright John Maddock 2007. +// Copyright Paul A. Bristow 2010 + +// 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) + +// Note that this file contains quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +#include <iostream> +using std::cout; using std::endl; + +//[policy_ref_snip9 + +#include <boost/math/special_functions/gamma.hpp> +using boost::math::tgamma; +using boost::math::policies::policy; +using boost::math::policies::digits10; + +typedef policy<digits10<5> > my_pol_5; // Define a new, non-default, policy +// to calculate tgamma to accuracy of approximately 5 decimal digits. +//] + +int main() +{ + cout.precision(5); // To only show 5 (hopefully) accurate decimal digits. + double t = tgamma(12, my_pol_5()); // Apply the 5 decimal digits accuracy policy to use of tgamma. + cout << "tgamma(12, my_pol_5() = " << t << endl; +} + +/* + +Output: + tgamma(12, my_pol_5() = 3.9917e+007 +*/ diff --git a/src/boost/libs/math/example/polynomial_arithmetic.cpp b/src/boost/libs/math/example/polynomial_arithmetic.cpp new file mode 100644 index 000000000..048879ed5 --- /dev/null +++ b/src/boost/libs/math/example/polynomial_arithmetic.cpp @@ -0,0 +1,238 @@ +// 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) + +// Copyright Jeremy W. Murphy 2015. + +// This file is written to be included from a Quickbook .qbk document. +// It can be compiled by the C++ compiler, and run. Any output can +// also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +//[polynomial_arithmetic_0 +/*`First include the essential polynomial header (and others) to make the example: +*/ +#include <boost/math/tools/polynomial.hpp> +//] [polynomial_arithmetic_0 + +#include <boost/array.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/math/tools/assert.hpp> + +#include <iostream> +#include <stdexcept> +#include <cmath> +#include <string> +#include <utility> + +//[polynomial_arithmetic_1 +/*`and some using statements are convenient: +*/ + +using std::string; +using std::exception; +using std::cout; +using std::abs; +using std::pair; + +using namespace boost::math; +using namespace boost::math::tools; // for polynomial +using boost::lexical_cast; + +//] [/polynomial_arithmetic_1] + +template <typename T> +string sign_str(T const &x) +{ + return x < 0 ? "-" : "+"; +} + +template <typename T> +string inner_coefficient(T const &x) +{ + string result(" " + sign_str(x) + " "); + if (abs(x) != T(1)) + result += lexical_cast<string>(abs(x)); + return result; +} + +/*! Output in formula format. +For example: from a polynomial in Boost container storage [ 10, -6, -4, 3 ] +show as human-friendly formula notation: 3x^3 - 4x^2 - 6x + 10. +*/ +template <typename T> +string formula_format(polynomial<T> const &a) +{ + string result; + if (a.size() == 0) + result += lexical_cast<string>(T(0)); + else + { + // First one is a special case as it may need unary negate. + unsigned i = a.size() - 1; + if (a[i] < 0) + result += "-"; + if (abs(a[i]) != T(1)) + result += lexical_cast<string>(abs(a[i])); + + if (i > 0) + { + result += "x"; + if (i > 1) + { + result += "^" + lexical_cast<string>(i); + i--; + for (; i != 1; i--) + if (a[i]) + result += inner_coefficient(a[i]) + "x^" + lexical_cast<string>(i); + + if (a[i]) + result += inner_coefficient(a[i]) + "x"; + } + i--; + + if (a[i]) + result += " " + sign_str(a[i]) + " " + lexical_cast<string>(abs(a[i])); + } + } + return result; +} // string formula_format(polynomial<T> const &a) + + +int main() +{ + cout << "Example: Polynomial arithmetic.\n\n"; + + try + { +//[polynomial_arithmetic_2 +/*`Store the coefficients in a convenient way to access them, +then create some polynomials using construction from an iterator range, +and finally output in a 'pretty' formula format. + +[tip Although we might conventionally write a polynomial from left to right +in descending order of degree, Boost.Math stores in [*ascending order of degree].] + + Read/write for humans: 3x^3 - 4x^2 - 6x + 10 + Boost polynomial storage: [ 10, -6, -4, 3 ] +*/ + std::array<double, 4> const d3a = {{10, -6, -4, 3}}; + polynomial<double> const a(d3a.begin(), d3a.end()); + + // With C++11 and later, you can also use initializer_list construction. + polynomial<double> const b{{-2.0, 1.0}}; + + // formula_format() converts from Boost storage to human notation. + cout << "a = " << formula_format(a) + << "\nb = " << formula_format(b) << "\n\n"; + +//] [/polynomial_arithmetic_2] + +//[polynomial_arithmetic_3 + // Now we can do arithmetic with the usual infix operators: + - * / and %. + polynomial<double> s = a + b; + cout << "a + b = " << formula_format(s) << "\n"; + polynomial<double> d = a - b; + cout << "a - b = " << formula_format(d) << "\n"; + polynomial<double> p = a * b; + cout << "a * b = " << formula_format(p) << "\n"; + polynomial<double> q = a / b; + cout << "a / b = " << formula_format(q) << "\n"; + polynomial<double> r = a % b; + cout << "a % b = " << formula_format(r) << "\n"; +//] [/polynomial_arithmetic_3] + +//[polynomial_arithmetic_4 +/*` +Division is a special case where you can calculate two for the price of one. + +Actually, quotient and remainder are always calculated together due to the nature +of the algorithm: the infix operators return one result and throw the other +away. + +If you are doing a lot of division and want both the quotient and remainder, then +you don't want to do twice the work necessary. + +In that case you can call the underlying function, [^quotient_remainder], +to get both results together as a pair. +*/ + pair< polynomial<double>, polynomial<double> > result; + result = quotient_remainder(a, b); +// Reassure ourselves that the result is the same. + BOOST_MATH_ASSERT(result.first == q); + BOOST_MATH_ASSERT(result.second == r); +//] [/polynomial_arithmetic_4] +//[polynomial_arithmetic_5 + /* +We can use the right and left shift operators to add and remove a factor of x. +This has the same semantics as left and right shift for integers where it is a +factor of 2. x is the smallest prime factor of a polynomial as is 2 for integers. +*/ + cout << "Right and left shift operators.\n"; + cout << "\n" << formula_format(p) << "\n"; + cout << "... right shift by 1 ...\n"; + p >>= 1; + cout << formula_format(p) << "\n"; + cout << "... left shift by 2 ...\n"; + p <<= 2; + cout << formula_format(p) << "\n"; + +/* +We can also give a meaning to odd and even for a polynomial that is consistent +with these operations: a polynomial is odd if it has a non-zero constant value, +even otherwise. That is: + x^2 + 1 odd + x^2 even + */ + cout << std::boolalpha; + cout << "\nPrint whether a polynomial is odd.\n"; + cout << formula_format(s) << " odd? " << odd(s) << "\n"; + // We cheekily use the internal details to subtract the constant, making it even. + s -= s.data().front(); + cout << formula_format(s) << " odd? " << odd(s) << "\n"; + // And of course you can check if it is even: + cout << formula_format(s) << " even? " << even(s) << "\n"; + + + //] [/polynomial_arithmetic_5] + //[polynomial_arithmetic_6] + /* For performance and convenience, we can test whether a polynomial is zero + * by implicitly converting to bool with the same semantics as int. */ + polynomial<double> zero; // Default construction is 0. + cout << "zero: " << (zero ? "not zero" : "zero") << "\n"; + cout << "r: " << (r ? "not zero" : "zero") << "\n"; + /* We can also set a polynomial to zero without needing a another zero + * polynomial to assign to it. */ + r.set_zero(); + cout << "r: " << (r ? "not zero" : "zero") << "\n"; + //] [/polynomial_arithmetic_6] +} +catch (exception const &e) +{ + cout << "\nMessage from thrown exception was:\n " << e.what() << "\n"; +} +return 0; +} // int main() + +/* +//[polynomial_output_1 + +a = 3x^3 - 4x^2 - 6x + 10 +b = x - 2 + +//] [/polynomial_output_1] + + +//[polynomial_output_2 + +a + b = 3x^3 - 4x^2 - 5x + 8 +a - b = 3x^3 - 4x^2 - 7x + 12 +a * b = 3x^4 - 10x^3 + 2x^2 + 22x - 20 +a / b = 3x^2 + 2x - 2 +a % b = 6 + +//] [/polynomial_output_2] + +*/ diff --git a/src/boost/libs/math/example/reciprocal_fibonacci_constant.cpp b/src/boost/libs/math/example/reciprocal_fibonacci_constant.cpp new file mode 100644 index 000000000..7c6405c52 --- /dev/null +++ b/src/boost/libs/math/example/reciprocal_fibonacci_constant.cpp @@ -0,0 +1,31 @@ +// Copyright 2020, Madhur Chauhan + +// 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) + +// This is an example to calculate Reciprocal Fibonacci Constant (A079586 in the OEIS) +// compile with flags: -std=c++11 -lmpfr + +//[fibonacci_eg + +#include <boost/math/special_functions/fibonacci.hpp> +#include <boost/multiprecision/mpfr.hpp> +#include <iomanip> +#include <iostream> + +int main() { + using Real = boost::multiprecision::mpfr_float_1000; + boost::math::fibonacci_generator<Real> gen; + gen.set(1); // start producing values from 1st fibonacci number + Real ans = 0; + const int ITR = 1000; + for (int i = 0; i < ITR; ++i) { + ans += 1.0 / gen(); + } + std::cout << std::setprecision(1000) << "Reciprocal fibonacci constant after " + << ITR << " iterations is: " << ans << std::endl; +} + +//] diff --git a/src/boost/libs/math/example/root_elliptic_finding.cpp b/src/boost/libs/math/example/root_elliptic_finding.cpp new file mode 100644 index 000000000..4a60bd4a6 --- /dev/null +++ b/src/boost/libs/math/example/root_elliptic_finding.cpp @@ -0,0 +1,877 @@ +// 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 & Schroder 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/math/tools/roots.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/ellint_2.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::schroder_iterate; + +#include <boost/math/special_functions/next.hpp> // For float_distance. + +#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/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(); +#include <type_traits> + +#ifdef __FILE__ + std::string sourcefilename = __FILE__; +#else + std::string sourcefilename(""); +#endif + + std::string chop_last(std::string s) + { + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(pos); + else if(s.empty()) + abort(); + else + s.erase(); + return s; + } + + std::string make_root() + { + std::string result; + if(sourcefilename.find_first_of(":") != std::string::npos) + { + result = chop_last(sourcefilename); // lose filename part + result = chop_last(result); // lose /example/ + result = chop_last(result); // lose /math/ + result = chop_last(result); // lose /libs/ + } + else + { + result = chop_last(sourcefilename); // lose filename part + if(result.empty()) + result = "."; + result += "/../../.."; + } + return result; + } + + std::string short_file_name(std::string s) + { + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(0, pos + 1); + return s; + } + + std::string boost_root = make_root(); + + +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; + +double digits_accuracy = 1.0; // 1 == maximum possible accuracy. + +std::stringstream ss; + +std::ofstream fout; + +std::vector<std::string> algo_names = +{ + "TOMS748", "Newton", "Halley", "Schr'''ö'''der" +}; + +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 & Schroder. + //std::vector< std::int_least64_t> times; converted to int. + std::vector<int> times; // arbitrary units (ticks). + //std::int_least64_t min_time = std::numeric_limits<std::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; +#if defined(_DEBUG) || !defined(NDEBUG) + result += "|"; + result += " debug"; +#else + result += "|"; + result += " release"; +#endif + result += "|"; + return result; +} // std::string build_test_name + +// Algorithms ////////////////////////////////////////////// + +// No derivatives - using TOMS748 internally. +//[elliptic_noderv_func +template <typename T = double> +struct elliptic_root_functor_noderiv +{ // Nth root of x using only function - no derivatives. + elliptic_root_functor_noderiv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) + { // Constructor just stores value a to find root of. + } + T operator()(T const& x) + { + using std::sqrt; + // return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x: + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T k = sqrt(1 - b * b / (a * a)); + return 4 * a * boost::math::ellint_2(k) - m_arc; + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; // template <class T> struct elliptic_root_functor_noderiv +//] +//[elliptic_root_noderiv +template <class T = double> +T elliptic_root_noderiv(T radius, T arc) +{ // return the other radius of an ellipse, given one radii and the arc-length + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For bracket_and_solve_root. + + T guess = sqrt(arc * arc / 16 - radius * radius); + T factor = 1.2; // How big steps to take when searching. + + const std::uintmax_t maxit = 50; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially our chosen max iterations, but updated with actual. + bool is_rising = true; // arc-length increases if one radii increases, so function is rising + // Define a termination condition, stop when nearly all digits are correct, but allow for + // the fact that we are returning a range, and must have some inaccuracy in the elliptic integral: + eps_tolerance<T> tol(std::numeric_limits<T>::digits - 2); + // Call bracket_and_solve_root to find the solution, note that this is a rising function: + std::pair<T, T> r = bracket_and_solve_root(elliptic_root_functor_noderiv<T>(arc, radius), guess, factor, is_rising, tol, it); + //<- + iters = it; + //-> + // Result is midway between the endpoints of the range: + return r.first + (r.second - r.first) / 2; +} // template <class T> T elliptic_root_noderiv(T x) +//] +// Using 1st derivative only Newton-Raphson +//[elliptic_1deriv_func +template <class T = double> +struct elliptic_root_functor_1deriv +{ // Functor also returning 1st derivative. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + elliptic_root_functor_1deriv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) + { // Constructor just stores value a to find root of. + } + std::pair<T, T> operator()(T const& x) + { + using std::sqrt; + // Return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x, plus it's derivative. + // See http://www.wolframalpha.com/input/?i=d%2Fda+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29] + // We require two elliptic integral calls, but from these we can calculate both + // the function and it's derivative: + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T a2 = a * a; + T b2 = b * b; + T k = sqrt(1 - b2 / a2); + T Ek = boost::math::ellint_2(k); + T Kk = boost::math::ellint_1(k); + T fx = 4 * a * Ek - m_arc; + T dfx = 4 * (a2 * Ek - b2 * Kk) / (a2 - b2); + return std::make_pair(fx, dfx); + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; // struct elliptic_root__functor_1deriv +//] +//[elliptic_1deriv +template <class T = double> +T elliptic_root_1deriv(T radius, T arc) +{ + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For newton_raphson_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T guess = sqrt(arc * arc / 16 - radius * radius); + T min = 0; // Minimum possible value is zero. + T max = arc; // Maximum possible value is the arc length. + + // Accuracy doubles at each step, so stop when just over half of the digits are + // correct, and rely on that step to polish off the remainder: + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.6); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = newton_raphson_iterate(elliptic_root_functor_1deriv<T>(arc, radius), guess, min, max, get_digits, it); + //<- + iters = it; + //-> + return result; +} // T elliptic_root_1_deriv Newton-Raphson +//] + +// Using 1st and 2nd derivatives with Halley algorithm. +//[elliptic_2deriv_func +template <class T = double> +struct elliptic_root_functor_2deriv +{ // Functor returning both 1st and 2nd derivatives. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + elliptic_root_functor_2deriv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) {} + std::tuple<T, T, T> operator()(T const& x) + { + using std::sqrt; + // Return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x, plus it's derivative. + // See http://www.wolframalpha.com/input/?i=d^2%2Fda^2+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29] + // for the second derivative. + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T a2 = a * a; + T b2 = b * b; + T k = sqrt(1 - b2 / a2); + T Ek = boost::math::ellint_2(k); + T Kk = boost::math::ellint_1(k); + T fx = 4 * a * Ek - m_arc; + T dfx = 4 * (a2 * Ek - b2 * Kk) / (a2 - b2); + T dfx2 = 4 * b2 * ((a2 + b2) * Kk - 2 * a2 * Ek) / (a * (a2 - b2) * (a2 - b2)); + return std::make_tuple(fx, dfx, dfx2); + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; +//] +//[elliptic_2deriv +template <class T = double> +T elliptic_root_2deriv(T radius, T arc) +{ + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For halley_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T guess = sqrt(arc * arc / 16 - radius * radius); + T min = 0; // Minimum possible value is zero. + T max = arc; // radius can't be larger than the arc length. + + // Accuracy triples at each step, so stop when just over one-third of the digits + // are correct, and the last iteration will polish off the remaining digits: + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = halley_iterate(elliptic_root_functor_2deriv<T>(arc, radius), guess, min, max, get_digits, it); + //<- + iters = it; + //-> + return result; +} // nth_2deriv Halley +//] +// Using 1st and 2nd derivatives using Schroder algorithm. + +template <class T = double> +T elliptic_root_2deriv_s(T arc, T radius) +{ // return nth root of x using 1st and 2nd derivatives and Schroder. + + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For schroder_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T guess = sqrt(arc * arc / 16 - radius * radius); + T min = 0; // Minimum possible value is zero. + T max = arc; // radius can't be larger than the arc length. + + 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 std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = schroder_iterate(elliptic_root_functor_2deriv<T>(arc, radius), guess, min, max, get_digits, it); + iters = it; + + return result; +} // T elliptic_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 <typename T> +int test_root(cpp_bin_float_100 big_radius, cpp_bin_float_100 big_arc, 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 radius = static_cast<T>(big_radius); + T arc = static_cast<T>(big_arc); + + T result; // root + T sum = 0; + T ans = static_cast<T>(answer); + + using boost::timer::nanosecond_type; + using boost::timer::cpu_times; + using boost::timer::cpu_timer; + + long eval_count = std::is_floating_point<T>::value ? 1000000 : 10000; // 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 = eval_count; i >= 0; --i) + { + result = elliptic_root_noderiv(radius, arc); // + sum += result; + } + 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 = eval_count; i >= 0; --i) + { + result = elliptic_root_1deriv(radius, arc); // + sum += result; + } + 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 = eval_count; i >= 0; --i) + { + result = elliptic_root_2deriv(radius, arc); // + sum += result; + } + 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("Schr'''ö'''der"); // algorithm + cpu_timer ti; // Can start, pause, resume and stop, and read elapsed. + ti.start(); + for(long i = eval_count; i >= 0; --i) + { + result = elliptic_root_2deriv_s(arc, radius); // + sum += result; + } + 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); + } + + std::cout << "Accumulated result was: " << sum << std::endl; + + return 4; // eval_count of how many algorithms used. +} // test_root + +/*! Fill array of times, iterations, etc for Nth root for all 4 types, + and write a table of results in Quickbook format. + */ +void table_root_info(cpp_bin_float_100 radius, cpp_bin_float_100 arc) +{ + using std::abs; + + std::cout << nooftypes << " floating-point types tested:" << std::endl; +#if defined(_DEBUG) || !defined(NDEBUG) + std::cout << "Compiled in debug mode." << std::endl; +#else + std::cout << "Compiled in optimise mode." << std::endl; +#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 = elliptic_root_noderiv(radius, arc); + + root_infos.clear(); // Erase any previous data. + // Fill the elements of the array for each floating-point type. + + test_root<float>(radius, arc, full_answer, "float", 0); + test_root<double>(radius, arc, full_answer, "double", 1); + test_root<long double>(radius, arc, full_answer, "long double", 2); + test_root<cpp_bin_float_50>(radius, arc, 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:elliptic root with radius " << radius << " and arc length " << arc << ") 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 radius, cpp_bin_float_100 arc, double digits_accuracy) +{ + ::digits_accuracy = digits_accuracy; + // Save globally so that it is available to root-finding algorithms. Ugly :-( + +#if defined(_DEBUG) || !defined(NDEBUG) + std::string debug_or_optimize("Compiled in debug mode."); +#else + std::string debug_or_optimize("Compiled in optimise mode."); +#endif + + // Create filename for roots_table + std::string qbk_name = full_roots_name; + qbk_name += "elliptic_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 [@../../example/" << short_file_name(sourcefilename) << " " << short_file_name(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(radius, arc); + + 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 radius("28."); + cpp_bin_float_100 arc("300."); + // 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 << "radius 1" << radius << std::endl; + std::cout << "arc length" << arc << 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(radius, arc, 1.); + + // Output tables for some roots at less accuracy. + //roots_tables(full_value, 0.75); + + return boost::exit_success; + } + catch (std::exception const& ex) + { + std::cout << "exception thrown: " << ex.what() << std::endl; + return boost::exit_failure; + } +} // int main() + +/* + +*/ diff --git a/src/boost/libs/math/example/root_finding_algorithms.cpp b/src/boost/libs/math/example/root_finding_algorithms.cpp new file mode 100644 index 000000000..389d33510 --- /dev/null +++ b/src/boost/libs/math/example/root_finding_algorithms.cpp @@ -0,0 +1,905 @@ +// 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, Schroder & 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 "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::schroder_iterate; + +#include <boost/math/special_functions/next.hpp> // For float_distance. +#include <tuple> // 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(); +#include <type_traits> + +#ifndef BOOST_ROOT +# define BOOST_ROOT i:/modular-boost/ +#endif +// Need to find this + +#ifdef __FILE__ +std::string sourcefilename = __FILE__; +#endif + +std::string chop_last(std::string s) +{ + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(pos); + else if(s.empty()) + abort(); + else + s.erase(); + return s; +} + +std::string make_root() +{ + std::string result; + if(sourcefilename.find_first_of(":") != std::string::npos) + { + result = chop_last(sourcefilename); // lose filename part + result = chop_last(result); // lose /example/ + result = chop_last(result); // lose /math/ + result = chop_last(result); // lose /libs/ + } + else + { + result = chop_last(sourcefilename); // lose filename part + if(result.empty()) + result = "."; + result += "/../../.."; + } + return result; +} + +std::string short_file_name(std::string s) +{ + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(0, pos + 1); + return s; +} + +std::string boost_root = make_root(); + +#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", "Schr'''ö'''der" +}; + +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 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< std::int_least64_t> times; converted to int. + std::vector<int> times; + //std::int_least64_t min_time = std::numeric_limits<std::int_least64_t>::max(); // Used to normalize times (as int). + std::vector<double> normed_times; + std::int_least64_t min_time = (std::numeric_limits<std::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; +#if defined(_DEBUG ) || !defined(NDEBUG) + result += "|"; + result += " debug"; +#else + result += "|"; + result += " release"; +#endif + result += "|"; + return result; +} + +// 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 (std::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 std::uintmax_t maxit = 50; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially 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. + // Some fraction of digits is used to control how accurate to try to make the result. + int get_digits = static_cast<int>(std::numeric_limits<T>::digits - 2); + + 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 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. + } + 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; + T guess; + if(std::is_fundamental<T>::value) + { + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three. + } + else + guess = boost::math::cbrt(static_cast<double>(x)); + T min = guess / 2; // Minimum possible value is half our guess. + T max = 2 * guess; // Maximum possible value is twice our guess. + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.6); + const std::uintmax_t maxit = 20; + std::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, + } + 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). + 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. + } +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; + T guess; + if(std::is_fundamental<T>::value) + { + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three. + } + else + guess = boost::math::cbrt(static_cast<double>(x)); + T min = guess / 2; // Minimum possible value is half our guess. + T max = 2 * guess; // Maximum possible value is twice our guess. + // digits used to control how accurate to try to make the result. + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + std::uintmax_t maxit = 20; + std::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 Schroder algorithm. + +template <class T> +T cbrt_2deriv_s(T x) +{ // return cube root of x using 1st and 2nd derivatives and Schroder algorithm. + //using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; + int exponent; + T guess; + if(std::is_fundamental<T>::value) + { + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + guess = ldexp(static_cast<T>(1), exponent / 3); // Rough guess is to divide the exponent by three. + } + else + guess = boost::math::cbrt(static_cast<double>(x)); + T min = guess / 2; // Minimum possible value is half our guess. + T max = 2 * guess; // Maximum possible value is twice our guess. + // digits used to control how accurate to try to make the result. + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = schroder_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 = std::numeric_limits<T>::digits; + + 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. + T sum = 0; + + // 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); // + sum += result; + } + now = ti.elapsed(); + + 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; + } + 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); // + sum += result; + } + 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); // + sum += result; + } + 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); // + sum += result; + } + 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); // + sum += result; + } + 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++; + std::cout << "Accumulated sum was " << sum << std::endl; + 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. + test_root<float>(full_value, full_answer, "float"); + test_root<double>(full_value, full_answer, "double"); + test_root<long double>(full_value, full_answer, "long double"); + test_root<cpp_bin_float_50>(full_value, full_answer, "cpp_bin_float_50"); + //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 - 2 << ", " << static_cast<int>(root_infos[tp].get_digits * 0.6) << ", " << static_cast<int>(root_infos[tp].get_digits * 0.4) << 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; + + // Row for all algorithms. + for (unsigned 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. +#if 0 + 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; +#endif + // 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 (size_t 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] << "]["; + if(fabs(root_infos[tp].normed_times[algo]) <= 1.05) + fout << "[role blue " << std::setw(3) << std::setprecision(2) << root_infos[tp].normed_times[algo] << "]"; + else if(fabs(root_infos[tp].normed_times[algo]) > 4) + fout << "[role red " << std::setw(3) << std::setprecision(2) << root_infos[tp].normed_times[algo] << "]"; + else + fout << std::setw(3) << std::setprecision(2) << root_infos[tp].normed_times[algo]; + fout + << "][" + << 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 " << short_file_name(sourcefilename) << ", " + << BOOST_COMPILER << ", " + << BOOST_STDLIB << ", " + << BOOST_PLATFORM << (sizeof(void*) == 8 ? ", x64" : ", x86") + << debug_or_optimize << "[br]" + << count << " evaluations of each of " << algo_names.size() << " root_finding algorithms." + << "]" + << 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 const& 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> ================================================================== + + + +*/ diff --git a/src/boost/libs/math/example/root_finding_example.cpp b/src/boost/libs/math/example/root_finding_example.cpp new file mode 100644 index 000000000..724bd5e36 --- /dev/null +++ b/src/boost/libs/math/example/root_finding_example.cpp @@ -0,0 +1,548 @@ +// root_finding_example.cpp + +// Copyright Paul A. Bristow 2010, 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) + +// Example of finding roots using Newton-Raphson, Halley. + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +//#define BOOST_MATH_INSTRUMENT + +/* +This example demonstrates how to use the various tools for root finding +taking the simple cube root function (`cbrt`) as an example. + +It shows how use of derivatives can improve the speed. +(But is only a demonstration and does not try to make the ultimate improvements of 'real-life' +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 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. + +First some `#includes` that will be needed. + +[tip For clarity, `using` statements are provided to list what functions are being used in this example: +you can of course partly or fully qualify the names in other ways. +(For your application, you may wish to extract some parts into header files, +but you should never use `using` statements globally in header files).] +*/ + +//[root_finding_include_1 + +#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; + +#include <boost/math/special_functions/next.hpp> // For float_distance. +#include <tuple> // for std::tuple and std::make_tuple. +#include <boost/math/special_functions/cbrt.hpp> // For boost::math::cbrt. +#include <boost/math/special_functions/pow.hpp> // boost::math::pow<5,double> + +//] [/root_finding_include_1] + +// using boost::math::tuple; +// using boost::math::make_tuple; +// using boost::math::tie; +// which provide convenient aliases for various implementations, +// including std::tr1, depending on what is available. + +#include <iostream> +//using std::cout; using std::endl; +#include <iomanip> +//using std::setw; using std::setprecision; +#include <limits> +//using std::numeric_limits; + +/* + +Let's suppose we want to find the root of a number ['a], and to start, compute the cube root. + +So the equation we want to solve is: + +__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. + +We then show how adding what we can know about this function, first just the slope, +the 1st derivation /f'(x)/, will speed homing in on the solution. + +Lastly we show how adding the curvature /f''(x)/ too will speed convergence even more. + +*/ + +//[root_finding_noderiv_1 + +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'. +}; +//] [/root_finding_noderiv_1 + +/* +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'.) + +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'). +*/ + +//[root_finding_noderiv_2 + +template <class T> +T cbrt_noderiv(T x) +{ + // return cube root of x using bracket_and_solve (no derivatives). + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For bracket_and_solve_root. + + int exponent; + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + T guess = ldexp(1., exponent/3); // Rough guess is to divide the exponent by three. + T factor = 2; // How big steps to take when searching. + + const std::uintmax_t maxit = 20; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially 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 = digits - 3; // We have to have a non-zero interval at each step, so + // maximum accuracy is digits - 1. But we also have to + // allow for inaccuracy in f(x), otherwise the last few + // iterations just thrash around. + 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 is our result, if necessary we could + // return the result as an interval here. +} + +/*` + +[note The final parameter specifying a maximum number of iterations is optional. +However, it defaults to `std::uintmax_t maxit = (std::numeric_limits<std::uintmax_t>::max)();` +which is `18446744073709551615` and is more than anyone would wish to wait for! + +So it may be wise to chose some reasonable estimate of how many iterations may be needed, +In this case the function is so well behaved that we can chose a low value of 20. + +Internally when Boost.Math uses these functions, it sets the maximum iterations to +`policies::get_max_root_iterations<Policy>();`.] + +Should we have wished we can show how many iterations were used in `bracket_and_solve_root` +(this information is lost outside `cbrt_noderiv`), for example with: + + if (it >= maxit) + { + 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; + } + +for output like + + Converged after 11 (from maximum of 20 iterations). +*/ +//] [/root_finding_noderiv_2] + + +// Cube root with 1st derivative (slope) + +/* +We now solve the same problem, but using more information about the function, +to show how this can speed up finding the best estimate of the root. + +For the root function, the 1st differential (the slope of the tangent to a curve at any point) is known. + +If you need some reminders then +[@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]], +allows us to get the 1st differential as ['3x[super 2]]. + +To see how this extra information is used to find a root, view +[@http://en.wikipedia.org/wiki/Newton%27s_method Newton-Raphson iterations] +and the [@http://en.wikipedia.org/wiki/Newton%27s_method#mediaviewer/File:NewtonIteration_Ani.gif animation]. + +We need to define a different functor `cbrt_functor_deriv` that returns +both the evaluation of the function to solve, along with its first derivative: + +To \'return\' two values, we use a `std::pair` of floating-point values +(though we could equally have used a std::tuple): +*/ + +//[root_finding_1_deriv_1 + +template <class T> +struct cbrt_functor_deriv +{ // 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>(a) to use to get cube root of a. + } + 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; // Store value to be 'cube_rooted'. +}; + +/*`Our cube root function is now:*/ + +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(1., exponent/3); // Rough guess is to divide the exponent by three. + T min = ldexp(0.5, exponent/3); // Minimum possible value is half our guess. + T max = ldexp(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 * 0.6); // Accuracy doubles with each step, so stop when we have + // just over half the digits correct. + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = newton_raphson_iterate(cbrt_functor_deriv<T>(x), guess, min, max, get_digits, it); + return result; +} + +//] [/root_finding_1_deriv_1] + + +/* +[h3:cbrt_2_derivatives Cube root with 1st & 2nd derivative (slope & curvature)] + +Finally we define yet another functor `cbrt_functor_2deriv` that returns +both the evaluation of the function to solve, +along with its first *and second* derivatives: + +__spaces[''f](x) = 6x + +To \'return\' three values, we use a `tuple` of three floating-point values: +*/ + +//[root_finding_2deriv_1 + +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, + } + 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). + 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. + } +private: + T a; // to be 'cube_rooted'. +}; + +/*`Our cube root function is now:*/ + +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(1., exponent/3); // Rough guess is to divide the exponent by three. + T min = ldexp(0.5, exponent/3); // Minimum possible value is half our guess. + T max = ldexp(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 * 0.4); // Accuracy triples with each step, so stop when just + // over one third of the digits are correct. + std::uintmax_t maxit = 20; + T result = halley_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, get_digits, maxit); + return result; +} + +//] [/root_finding_2deriv_1] + +//[root_finding_2deriv_lambda + +template <class T> +T cbrt_2deriv_lambda(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(1., exponent / 3); // Rough guess is to divide the exponent by three. + T min = ldexp(0.5, exponent / 3); // Minimum possible value is half our guess. + T max = ldexp(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 * 0.4); // Accuracy triples with each step, so stop when just + // over one third of the digits are correct. + std::uintmax_t maxit = 20; + T result = halley_iterate( + // lambda function: + [x](const T& g){ return std::make_tuple(g * g * g - x, 3 * g * g, 6 * g); }, + guess, min, max, get_digits, maxit); + return result; +} + +//] [/root_finding_2deriv_lambda] +/* + +[h3 Fifth-root function] +Let's now suppose we want to find the [*fifth root] of a number ['a]. + +The equation we want to solve is : + +__spaces['f](x) = x[super 5] - a + +If your differentiation is a little rusty +(or you are faced with an equation whose complexity is daunting), +then you can get help, for example from the invaluable +[@http://www.wolframalpha.com/ WolframAlpha site.] + +For example, entering the command: `differentiate x ^ 5` + +or the Wolfram Language command: ` D[x ^ 5, x]` + +gives the output: `d/dx(x ^ 5) = 5 x ^ 4` + +and to get the second differential, enter: `second differentiate x ^ 5` + +or the Wolfram Language command: `D[x ^ 5, { x, 2 }]` + +to get the output: `d ^ 2 / dx ^ 2(x ^ 5) = 20 x ^ 3` + +To get a reference value, we can enter: [^fifth root 3126] + +or: `N[3126 ^ (1 / 5), 50]` + +to get a result with a precision of 50 decimal digits: + +5.0003199590478625588206333405631053401128722314376 + +(We could also get a reference value using Boost.Multiprecision - see below). + +The 1st and 2nd derivatives of x[super 5] are: + +__spaces['f]\'(x) = 5x[super 4] + +__spaces['f]\'\'(x) = 20x[super 3] + +*/ + +//[root_finding_fifth_1 +//] [/root_finding_fifth_1] + + +//[root_finding_fifth_functor_2deriv + +/*`Using these expressions for the derivatives, the functor is: +*/ + +template <class T> +struct fifth_functor_2deriv +{ + // Functor returning both 1st and 2nd derivatives. + fifth_functor_2deriv(T const& to_find_root_of) : a(to_find_root_of) + { /* Constructor stores value a to find root of, for example: */ } + + std::tuple<T, T, T> operator()(T const& x) + { + // Return both f(x) and f'(x) and f''(x). + T fx = boost::math::pow<5>(x) - a; // Difference (estimate x^3 - value). + T dx = 5 * boost::math::pow<4>(x); // 1st derivative = 5x^4. + T d2x = 20 * boost::math::pow<3>(x); // 2nd derivative = 20 x^3 + return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x. + } +private: + T a; // to be 'fifth_rooted'. +}; // struct fifth_functor_2deriv + +//] [/root_finding_fifth_functor_2deriv] + +//[root_finding_fifth_2deriv + +/*`Our fifth-root function is now: +*/ + +template <class T> +T fifth_2deriv(T x) +{ + // return fifth 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. + + int exponent; + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + T guess = ldexp(1., exponent / 5); // Rough guess is to divide the exponent by five. + T min = ldexp(0.5, exponent / 5); // Minimum possible value is half our guess. + T max = ldexp(2., exponent / 5); // Maximum possible value is twice our guess. + // Stop when slightly more than one of the digits are correct: + const int digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + const std::uintmax_t maxit = 50; + std::uintmax_t it = maxit; + T result = halley_iterate(fifth_functor_2deriv<T>(x), guess, min, max, digits, it); + return result; +} + +//] [/root_finding_fifth_2deriv] + + +int main() +{ + std::cout << "Root finding Examples." << std::endl; + std::cout.precision(std::numeric_limits<double>::max_digits10); + // Show all possibly significant decimal digits for double. + // std::cout.precision(std::numeric_limits<double>::digits10); + // Show all guaranteed significant decimal digits for double. + + +//[root_finding_main_1 + try + { + 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. + std::cout <<" cast double " << static_cast<double>(3.0365889718756625194208095785056696355814539772481111) << std::endl; + + // Cube root using bracketing: + double r = cbrt_noderiv(threecubed); + std::cout << "cbrt_noderiv(" << threecubed << ") = " << r << std::endl; + r = cbrt_noderiv(threecubedp1); + std::cout << "cbrt_noderiv(" << threecubedp1 << ") = " << r << std::endl; +//] [/root_finding_main_1] + //[root_finding_main_2 + + // Cube root using 1st differential Newton-Raphson: + r = cbrt_deriv(threecubed); + std::cout << "cbrt_deriv(" << threecubed << ") = " << r << std::endl; + r = cbrt_deriv(threecubedp1); + std::cout << "cbrt_deriv(" << threecubedp1 << ") = " << r << std::endl; + + // Cube root using Halley with 1st and 2nd differentials. + r = cbrt_2deriv(threecubed); + std::cout << "cbrt_2deriv(" << threecubed << ") = " << r << std::endl; + r = cbrt_2deriv(threecubedp1); + std::cout << "cbrt_2deriv(" << threecubedp1 << ") = " << r << std::endl; + + // Cube root using lambda's: + r = cbrt_2deriv_lambda(threecubed); + std::cout << "cbrt_2deriv(" << threecubed << ") = " << r << std::endl; + r = cbrt_2deriv_lambda(threecubedp1); + std::cout << "cbrt_2deriv(" << threecubedp1 << ") = " << r << std::endl; + + // Fifth root. + + double fivepowfive = 3125; // Example of a value that has an exact integer fifth root. + // Exact value of fifth root is exactly 5. + std::cout << "Fifth root of " << fivepowfive << " is " << 5 << std::endl; + + double fivepowfivep1 = fivepowfive + 1; // Example of a value whose fifth root is *not* exactly representable. + // Value of fifth root is 5.0003199590478625588206333405631053401128722314376 (50 decimal digits precision) + // and to std::numeric_limits<double>::max_digits10 double precision (usually 17) is + + double root5v2 = static_cast<double>(5.0003199590478625588206333405631053401128722314376); + std::cout << "Fifth root of " << fivepowfivep1 << " is " << root5v2 << std::endl; + + // Using Halley with 1st and 2nd differentials. + r = fifth_2deriv(fivepowfive); + std::cout << "fifth_2deriv(" << fivepowfive << ") = " << r << std::endl; + r = fifth_2deriv(fivepowfivep1); + std::cout << "fifth_2deriv(" << fivepowfivep1 << ") = " << r << std::endl; +//] [/root_finding_main_?] + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + +//[root_finding_example_output +/*` +Normal output is: + +[pre + root_finding_example.cpp + Generating code + Finished generating code + root_finding_example.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\root_finding_example.exe + Cube Root finding (cbrt) Example. + Iterations 10 + cbrt_1(27) = 3 + Iterations 10 + Unable to locate solution in chosen iterations: Current best guess is between 3.0365889718756613 and 3.0365889718756627 + cbrt_1(28) = 3.0365889718756618 + cbrt_1(27) = 3 + cbrt_2(28) = 3.0365889718756627 + Iterations 4 + cbrt_3(27) = 3 + Iterations 5 + cbrt_3(28) = 3.0365889718756627 + +] [/pre] + +to get some (much!) diagnostic output we can add + +#define BOOST_MATH_INSTRUMENT + +[pre + +] +*/ +//] [/root_finding_example_output] + +/* + +cbrt(28) 3.0365889718756622 +std::cbrt(28) 3.0365889718756627 + +*/ diff --git a/src/boost/libs/math/example/root_finding_fifth.cpp b/src/boost/libs/math/example/root_finding_fifth.cpp new file mode 100644 index 000000000..d820e0ba3 --- /dev/null +++ b/src/boost/libs/math/example/root_finding_fifth.cpp @@ -0,0 +1,485 @@ +// root_finding_fith.cpp + +// Copyright Paul A. Bristow 2014. + +// 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) + +// Example of finding fifth root using Newton-Raphson, Halley, Schroder, TOMS748 . + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// To get (copious!) diagnostic output, add make this define here or elsewhere. +//#define BOOST_MATH_INSTRUMENT + + +//[root_fifth_headers +/* +This example demonstrates how to use the Boost.Math tools for root finding, +taking the fifth root function (fifth_root) as an example. +It shows how use of derivatives can improve the speed. + +First some includes that will be needed. +Using statements are provided to list what functions are being used in this example: +you can of course qualify the names in other ways. +*/ + +#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; + +#include <boost/math/special_functions/next.hpp> + +#include <tuple> +#include <utility> // pair, make_pair + +//] [/root_finding_headers] + +#include <iostream> +using std::cout; using std::endl; +#include <iomanip> +using std::setw; using std::setprecision; +#include <limits> +using std::numeric_limits; + +/* +//[root_finding_fifth_1 +Let's suppose we want to find the fifth root of a number. + +The equation we want to solve is: + +__spaces ['f](x) = x[fifth] + +We will first solve this without using any information +about the slope or curvature of the fifth function. + +If your differentiation is a little rusty +(or you are faced with an equation whose complexity is daunting, +then you can get help, for example from the invaluable + +http://www.wolframalpha.com/ site + +entering the command + + differentiate x^5 + +or the Wolfram Language command + + D[x^5, x] + +gives the output + + d/dx(x^5) = 5 x^4 + +and to get the second differential, enter + + second differentiate x^5 + +or the Wolfram Language + + D[x^5, {x, 2}] + +to get the output + + d^2/dx^2(x^5) = 20 x^3 + +or + + 20 x^3 + +To get a reference value we can enter + + fifth root 3126 + +or + + N[3126^(1/5), 50] + +to get a result with a precision of 50 decimal digits + + 5.0003199590478625588206333405631053401128722314376 + +(We could also get a reference value using Boost.Multiprecision). + +We then show how adding what we can know, for this function, about the slope, +the 1st derivation /f'(x)/, will speed homing in on the solution, +and then finally how adding the curvature /f''(x)/ as well will improve even more. + +The 1st and 2nd derivatives of x[fifth] are: + +__spaces ['f]\'(x) = 2x[sup2] + +__spaces ['f]\'\'(x) = 6x + +*/ + +//] [/root_finding_fifth_1] + +//[root_finding_fifth_functor_noderiv + +template <class T> +struct fifth_functor_noderiv +{ // fifth root of x using only function - no derivatives. + fifth_functor_noderiv(T const& to_find_root_of) : value(to_find_root_of) + { // Constructor stores value to find root of. + // For example: calling fifth_functor<T>(x) to get fifth root of x. + } + T operator()(T const& x) + { //! \returns f(x) - value. + T fx = x*x*x*x*x - value; // Difference (estimate x^5 - value). + return fx; + } +private: + T value; // to be 'fifth_rooted'. +}; + +//] [/root_finding_fifth_functor_noderiv] + +//cout << ", std::numeric_limits<" << typeid(T).name() << ">::digits = " << digits +// << ", accuracy " << get_digits << " bits."<< endl; + + +/*`Implementing the fifth 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 five. +(There are better but more complex guess algorithms used in 'real-life'.) + +fifth 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'). +*/ + +//[root_finding_fifth_noderiv + +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::tools; // For bracket_and_solve_root. + + int exponent; + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + T guess = ldexp(1., exponent / 5); // Rough guess is to divide the exponent by five. + T factor = 2; // To multiply and divide guess to bracket. + // digits used to control how accurate to try to make the result. + // int digits = 3 * std::numeric_limits<T>::digits / 4; // 3/4 maximum possible binary digits accuracy for type T. + int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T. + + //std::uintmax_t maxit = (std::numeric_limits<std::uintmax_t>::max)(); + // (std::numeric_limits<std::uintmax_t>::max)() = 18446744073709551615 + // which is more than anyone might wish to wait for!!! + // so better to choose some reasonable estimate of how many iterations may be needed. + + const std::uintmax_t maxit = 50; // Chosen max iterations, + // but updated on exit with actual iteration count. + + // We could also have used a maximum iterations provided by any policy: + // std::uintmax_t max_it = policies::get_max_root_iterations<Policy>(); + + std::uintmax_t it = maxit; // Initially our chosen max iterations, + + bool is_rising = true; // So if result if guess^5 is too low, try increasing guess. + eps_tolerance<double> tol(digits); + std::pair<T, T> r = + bracket_and_solve_root(fifth_functor_noderiv<T>(x), guess, factor, is_rising, tol, it); + // because the iteration count is updating, + // you can't call with a literal maximum iterations value thus: + //bracket_and_solve_root(fifth_functor_noderiv<T>(x), guess, factor, is_rising, tol, 20); + + // Can show how many iterations (this information is lost outside fifth_noderiv). + cout << "Iterations " << it << endl; + if (it >= maxit) + { // Failed to converge (or is jumping between bracket values). + cout << "Unable to locate solution in chosen iterations:" + " Current best guess is between " << r.first << " and " << r.second << endl; + } + T distance = boost::math::float_distance(r.first, r.second); + if (distance > 0) + { // + std::cout << distance << " bits separate the bracketing values." << std::endl; + for (int i = 0; i < distance; i++) + { // Show all the values within the bracketing values. + std::cout << boost::math::float_advance(r.first, i) << std::endl; + } + } + else + { // distance == 0 and r.second == r.first + std::cout << "Converged to a single value " << r.first << std::endl; + } + + return r.first + (r.second - r.first) / 2; // return midway between bracketed interval. +} // T fifth_noderiv(T x) + +//] [/root_finding_fifth_noderiv] + + + +// maxit = 10 +// Unable to locate solution in chosen iterations: Current best guess is between 3.0365889718756613 and 3.0365889718756627 + + +/*` +We now solve the same problem, but using more information about the function, +to show how this can speed up finding the best estimate of the root. + +For this function, the 1st differential (the slope of the tangent to a curve at any point) is known. + +[@http://en.wikipedia.org/wiki/Derivative#Derivatives_of_elementary_functions Derivatives] +gives some reminders. + +Using the rule that the derivative of x^n for positive n (actually all nonzero n) is nx^n-1, +allows use to get the 1st differential as 3x^2. + +To see how this extra information is used to find the root, view this demo: +[@http://en.wikipedia.org/wiki/Newton%27s_methodNewton Newton-Raphson iterations]. + +We need to define a different functor that returns +both the evaluation of the function to solve, along with its first derivative: + +To \'return\' two values, we use a pair of floating-point values: +*/ + +//[root_finding_fifth_functor_1stderiv + +template <class T> +struct fifth_functor_1stderiv +{ // Functor returning function and 1st derivative. + + fifth_functor_1stderiv(T const& target) : value(target) + { // Constructor stores the value to be 'fifth_rooted'. + } + + std::pair<T, T> operator()(T const& z) // z is best estimate so far. + { // Return both f(x) and first derivative f'(x). + T fx = z*z*z*z*z - value; // Difference estimate fx = x^5 - value. + T d1x = 5 * z*z*z*z; // 1st derivative d1x = 5x^4. + return std::make_pair(fx, d1x); // 'return' both fx and d1x. + } +private: + T value; // to be 'fifth_rooted'. +}; // fifth_functor_1stderiv + +//] [/root_finding_fifth_functor_1stderiv] + + +/*`Our fifth root function using fifth_functor_1stderiv is now:*/ + +//[root_finding_fifth_1deriv + +template <class T> +T fifth_1deriv(T x) +{ //! \return fifth root of x using 1st derivative and Newton_Raphson. + using namespace std; // For frexp, ldexp, numeric_limits. + using namespace boost::math::tools; // For newton_raphson_iterate. + + int exponent; + frexp(x, &exponent); // Get exponent of x (ignore mantissa). + T guess = ldexp(1., exponent / 5); // Rough guess is to divide the exponent by three. + // Set an initial bracket interval. + T min = ldexp(0.5, exponent / 5); // Minimum possible value is half our guess. + T max = ldexp(2., exponent / 5);// Maximum possible value is twice our guess. + + // digits used to control how accurate to try to make the result. + int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T. + + const std::uintmax_t maxit = 20; // Optionally limit the number of iterations. + std::uintmax_t it = maxit; // limit the number of iterations. + //cout << "Max Iterations " << maxit << endl; // + T result = newton_raphson_iterate(fifth_functor_1stderiv<T>(x), guess, min, max, digits, it); + // Can check and show how many iterations (updated by newton_raphson_iterate). + cout << it << " iterations (from max of " << maxit << ")" << endl; + return result; +} // fifth_1deriv + +//] [/root_finding_fifth_1deriv] + +// int get_digits = (digits * 2) /3; // Two thirds of maximum possible accuracy. + +//std::uintmax_t maxit = (std::numeric_limits<std::uintmax_t>::max)(); +// the default (std::numeric_limits<std::uintmax_t>::max)() = 18446744073709551615 +// which is more than we might wish to wait for!!! so we can reduce it + +/*` +Finally need to define yet another functor that returns +both the evaluation of the function to solve, +along with its first and second derivatives: + +f''(x) = 3 * 3x + +To \'return\' three values, we use a tuple of three floating-point values: +*/ + +//[root_finding_fifth_functor_2deriv + +template <class T> +struct fifth_functor_2deriv +{ // Functor returning both 1st and 2nd derivatives. + fifth_functor_2deriv(T const& to_find_root_of) : value(to_find_root_of) + { // Constructor stores value to find root of, for example: + } + + // using boost::math::tuple; // to return three values. + std::tuple<T, T, T> operator()(T const& x) + { // Return both f(x) and f'(x) and f''(x). + T fx = x*x*x*x*x - value; // Difference (estimate x^3 - value). + T dx = 5 * x*x*x*x; // 1st derivative = 5x^4. + T d2x = 20 * x*x*x; // 2nd derivative = 20 x^3 + return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x. + } +private: + T value; // to be 'fifth_rooted'. +}; // struct fifth_functor_2deriv + +//] [/root_finding_fifth_functor_2deriv] + + +/*`Our fifth function is now:*/ + +//[root_finding_fifth_2deriv + +template <class T> +T fifth_2deriv(T x) +{ // return fifth root of x using 1st and 2nd derivatives and Halley. + using namespace std; // Help ADL of std functions. + using namespace boost::math; // halley_iterate + + int exponent; + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + T guess = ldexp(1., exponent / 5); // Rough guess is to divide the exponent by three. + T min = ldexp(0.5, exponent / 5); // Minimum possible value is half our guess. + T max = ldexp(2., exponent / 5); // Maximum possible value is twice our guess. + + int digits = std::numeric_limits<T>::digits / 2; // Half maximum possible binary digits accuracy for type T. + const std::uintmax_t maxit = 50; + std::uintmax_t it = maxit; + T result = halley_iterate(fifth_functor_2deriv<T>(x), guess, min, max, digits, it); + // Can show how many iterations (updated by halley_iterate). + cout << it << " iterations (from max of " << maxit << ")" << endl; + + return result; +} // fifth_2deriv(x) + +//] [/root_finding_fifth_2deriv] + +int main() +{ + + //[root_finding_example_1 + cout << "fifth Root finding (fifth) Example." << endl; + // Show all possibly significant decimal digits. + cout.precision(std::numeric_limits<double>::max_digits10); + // or use cout.precision(max_digits10 = 2 + std::numeric_limits<double>::digits * 3010/10000); + try + { // Always use try'n'catch blocks with Boost.Math to get any error messages. + + double v27 = 3125; // Example of a value that has an exact integer fifth root. + // exact value of fifth root is exactly 5. + + std::cout << "Fifth root of " << v27 << " is " << 5 << std::endl; + + double v28 = v27+1; // Example of a value whose fifth root is *not* exactly representable. + // Value of fifth root is 5.0003199590478625588206333405631053401128722314376 (50 decimal digits precision) + // and to std::numeric_limits<double>::max_digits10 double precision (usually 17) is + + double root5v2 = static_cast<double>(5.0003199590478625588206333405631053401128722314376); + + std::cout << "Fifth root of " << v28 << " is " << root5v2 << std::endl; + + // Using bracketing: + double r = fifth_noderiv(v27); + cout << "fifth_noderiv(" << v27 << ") = " << r << endl; + + r = fifth_noderiv(v28); + cout << "fifth_noderiv(" << v28 << ") = " << r << endl; + + // Using 1st differential Newton-Raphson: + r = fifth_1deriv(v27); + cout << "fifth_1deriv(" << v27 << ") = " << r << endl; + r = fifth_1deriv(v28); + cout << "fifth_1deriv(" << v28 << ") = " << r << endl; + + // Using Halley with 1st and 2nd differentials. + r = fifth_2deriv(v27); + cout << "fifth_2deriv(" << v27 << ") = " << r << endl; + r = fifth_2deriv(v28); + cout << "fifth_2deriv(" << v28 << ") = " << r << endl; + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + //] [/root_finding_example_1 + return 0; +} // int main() + +//[root_finding_example_output +/*` +Normal output is: + +[pre +1> Description: Autorun "J:\Cpp\MathToolkit\test\Math_test\Release\root_finding_fifth.exe" +1> fifth Root finding (fifth) Example. +1> Fifth root of 3125 is 5 +1> Fifth root of 3126 is 5.0003199590478626 +1> Iterations 10 +1> Converged to a single value 5 +1> fifth_noderiv(3125) = 5 +1> Iterations 11 +1> 2 bits separate the bracketing values. +1> 5.0003199590478609 +1> 5.0003199590478618 +1> fifth_noderiv(3126) = 5.0003199590478618 +1> 6 iterations (from max of 20) +1> fifth_1deriv(3125) = 5 +1> 7 iterations (from max of 20) +1> fifth_1deriv(3126) = 5.0003199590478626 +1> 4 iterations (from max of 50) +1> fifth_2deriv(3125) = 5 +1> 4 iterations (from max of 50) +1> fifth_2deriv(3126) = 5.0003199590478626 +[/pre] + +to get some (much!) diagnostic output we can add + +#define BOOST_MATH_INSTRUMENT + +[pre +1> fifth Root finding (fifth) Example. +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:537 a = 4 b = 8 fa = -2101 fb = 29643 count = 18 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:340 a = 4.264742943548387 b = 8 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:352 a = 4.264742943548387 b = 5.1409225585147951 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:259 a = 4.264742943548387 b = 5.1409225585147951 d = 8 e = 4 fa = -1714.2037505671719 fb = 465.91652114644285 fd = 29643 fe = -2101 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:267 q11 = -3.735257056451613 q21 = -0.045655399937094755 q31 = 0.68893005658139972 d21 = -2.9047328414222999 d31 = -0.18724955838500826 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:275 q22 = -0.15074699539567221 q32 = 0.007740525571111408 d32 = -0.13385363287680208 q33 = 0.074868009790687237 c = 5.0362815354915851 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:388 a = 4.264742943548387 b = 5.0362815354915851 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:259 a = 4.264742943548387 b = 5.0362815354915851 d = 5.1409225585147951 e = 8 fa = -1714.2037505671719 fb = 115.03721886368339 fd = 465.91652114644285 fe = 29643 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:267 q11 = -0.045655399937094755 q21 = -0.034306988726112195 q31 = 0.7230181097615842 d21 = -0.1389480117493222 d31 = -0.048520482181613811 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:275 q22 = -0.00036345624935100459 q32 = 0.011175908093791367 d32 = -0.0030375853617102483 q33 = 0.00014618657296010219 c = 4.999083147976723 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:408 a = 4.999083147976723 b = 5.0362815354915851 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:433 a = 4.999083147976723 b = 5.0008904277935091 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:434 tol = -0.00036152225583956088 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:259 a = 4.999083147976723 b = 5.0008904277935091 d = 5.0362815354915851 e = 4.264742943548387 fa = -2.8641119933622576 fb = 2.7835781082976609 fd = 115.03721886368339 fe = -1714.2037505671719 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:267 q11 = -0.048520482181613811 q21 = -0.00087760104664616457 q31 = 0.00091652546535745522 d21 = -0.036268708744722128 d31 = -0.00089075435142862297 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:275 q22 = -1.9862562616034592e-005 q32 = 3.1952597740788757e-007 d32 = -1.2833778805050512e-005 q33 = 1.1763429980834706e-008 c = 5.0000000047314881 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:388 a = 4.999083147976723 b = 5.0000000047314881 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:259 a = 4.999083147976723 b = 5.0000000047314881 d = 5.0008904277935091 e = 5.0362815354915851 fa = -2.8641119933622576 fb = 1.4785900475544622e-005 fd = 2.7835781082976609 fe = 115.03721886368339 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:267 q11 = -0.00087760104664616457 q21 = -4.7298032238887272e-009 q31 = 0.00091685202154135855 d21 = -0.00089042779182425238 d31 = -4.7332236912279757e-009 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:275 q22 = -1.6486403607318402e-012 q32 = 1.7346209428817704e-012 d32 = -1.6858463963666777e-012 q33 = 9.0382569995250912e-016 c = 5 +1> I:\modular-boost\boost/math/tools/toms748_solve.hpp:592 max_iter = 10 count = 7 +1> Iterations 20 +1> 0 bits separate brackets. +1> fifth_noderiv(3125) = 5 +] +*/ +//] [/root_finding_example_output] diff --git a/src/boost/libs/math/example/root_finding_multiprecision_example.cpp b/src/boost/libs/math/example/root_finding_multiprecision_example.cpp new file mode 100644 index 000000000..14d31397f --- /dev/null +++ b/src/boost/libs/math/example/root_finding_multiprecision_example.cpp @@ -0,0 +1,236 @@ +// 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) + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// Example of root finding using Boost.Multiprecision. + +#ifndef BOOST_MATH_STANDALONE + +#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; + +#include <boost/math/special_functions/next.hpp> // For float_distance. +#include <boost/math/special_functions/pow.hpp> +#include <boost/math/constants/constants.hpp> + +//[root_finding_multiprecision_include_1 +#include <boost/multiprecision/cpp_bin_float.hpp> // For cpp_bin_float_50. +#include <boost/multiprecision/cpp_dec_float.hpp> // For cpp_dec_float_50. +#ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2013. +# include <boost/multiprecision/float128.hpp> // Requires libquadmath. +#endif +//] [/root_finding_multiprecision_include_1] + +#include <iostream> +// using std::cout; using std::endl; +#include <iomanip> +// using std::setw; using std::setprecision; +#include <limits> +// using std::numeric_limits; +#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. + using namespace std; // Help ADL of std functions. + 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 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. + // 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 std::uintmax_t maxit = 20; + std::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 " << it << " (from max of "<< maxit << ")." << std::endl; + return result; +} // cbrt_2deriv(x) + + +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 to find root of, for example: + } + + // using boost::math::tuple; // to return three values. + 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. + } +private: + T a; // to be 'cube_rooted'. +}; // struct cbrt_functor_2deriv + +template <int n, class T> +struct nth_functor_2deriv +{ // Functor returning both 1st and 2nd derivatives. + + nth_functor_2deriv(T const& to_find_root_of) : value(to_find_root_of) + { /* Constructor stores value to find root of, for example: */ } + + // using std::tuple; // to return three values. + std::tuple<T, T, T> operator()(T const& x) + { + // Return both f(x) and f'(x) and f''(x). + using boost::math::pow; + T fx = pow<n>(x) - value; // Difference (estimate x^3 - value). + T dx = n * pow<n - 1>(x); // 1st derivative = 5x^4. + T d2x = n * (n - 1) * pow<n - 2 >(x); // 2nd derivative = 20 x^3 + return std::make_tuple(fx, dx, d2x); // 'return' fx, dx and d2x. + } +private: + T value; // to be 'nth_rooted'. +}; // struct nth_functor_2deriv + + +template <int n, class T> +T nth_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; // For halley_iterate. + + int exponent; + frexp(x, &exponent); // Get exponent of z (ignore mantissa). + T guess = ldexp(static_cast<T>(1.), exponent / n); // Rough guess is to divide the exponent by three. + T min = ldexp(static_cast<T>(0.5), exponent / n); // Minimum possible value is half our guess. + T max = ldexp(static_cast<T>(2.), exponent / n); // Maximum possible value is twice our guess. + + int digits = std::numeric_limits<T>::digits / 2; // Half maximum possible binary digits accuracy for type T. + const std::uintmax_t maxit = 50; + std::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). + std::cout << it << " iterations (from max of " << maxit << ")" << std::endl; + + return result; +} // nth_2deriv(x) + +//[root_finding_multiprecision_show_1 + +template <typename T> +T show_cube_root(T value) +{ // Demonstrate by printing the root using all definitely significant digits. + std::cout.precision(std::numeric_limits<T>::digits10); + T r = cbrt_2deriv(value); + std::cout << "value = " << value << ", cube root =" << r << std::endl; + return r; +} + +//] [/root_finding_multiprecision_show_1] + +int main() +{ + std::cout << "Multiprecision Root finding Example." << std::endl; + // Show all possibly significant decimal digits. + std::cout.precision(std::numeric_limits<double>::digits10); + // or use cout.precision(max_digits10 = 2 + std::numeric_limits<double>::digits * 3010/10000); + //[root_finding_multiprecision_example_1 + using boost::multiprecision::cpp_dec_float_50; // decimal. + using boost::multiprecision::cpp_bin_float_50; // binary. +#ifndef _MSC_VER // Not supported by Microsoft compiler. + using boost::multiprecision::float128; +#endif + //] [/root_finding_multiprecision_example_1 + + try + { // Always use try'n'catch blocks with Boost.Math to get any error messages. + // Increase the precision to 50 decimal digits using Boost.Multiprecision +//[root_finding_multiprecision_example_2 + + std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); + + cpp_dec_float_50 two = 2; // + cpp_dec_float_50 r = cbrt_2deriv(two); + std::cout << "cbrt(" << two << ") = " << r << std::endl; + + r = cbrt_2deriv(2.); // Passing a double, so ADL will compute a double precision result. + std::cout << "cbrt(" << two << ") = " << r << std::endl; + // cbrt(2) = 1.2599210498948731906665443602832965552806854248047 'wrong' from digits 17 onwards! + r = cbrt_2deriv(static_cast<cpp_dec_float_50>(2.)); // Passing a cpp_dec_float_50, + // so will compute a cpp_dec_float_50 precision result. + std::cout << "cbrt(" << two << ") = " << r << std::endl; + r = cbrt_2deriv<cpp_dec_float_50>(2.); // Explicitly a cpp_dec_float_50, so will compute a cpp_dec_float_50 precision result. + std::cout << "cbrt(" << two << ") = " << r << std::endl; + // cpp_dec_float_50 1.2599210498948731647672106072782283505702514647015 +//] [/root_finding_multiprecision_example_2 + // N[2^(1/3), 50] 1.2599210498948731647672106072782283505702514647015 + + //show_cube_root(2); // Integer parameter - Errors! + //show_cube_root(2.F); // Float parameter - Warnings! +//[root_finding_multiprecision_example_3 + show_cube_root(2.); + show_cube_root(2.L); + show_cube_root(two); + +//] [/root_finding_multiprecision_example_3 + + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // 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 + + +*/ + +#endif // BOOST_MATH_STANDALONE diff --git a/src/boost/libs/math/example/root_finding_n_example.cpp b/src/boost/libs/math/example/root_finding_n_example.cpp new file mode 100644 index 000000000..5cf7aa864 --- /dev/null +++ b/src/boost/libs/math/example/root_finding_n_example.cpp @@ -0,0 +1,213 @@ +// Copyright Paul A. Bristow 2014, 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) + +// Note that this file contains Quickbook mark-up as well as code +// and comments, don't change any of the special comment mark-ups! + +// Example of finding nth root using 1st and 2nd derivatives of x^n. + +#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; + +#include <boost/math/special_functions/next.hpp> +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/special_functions/pow.hpp> +#include <boost/math/constants/constants.hpp> + +#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> +#endif + +#include <iostream> +// using std::cout; using std::endl; +#include <iomanip> +// using std::setw; using std::setprecision; +#include <limits> +using std::numeric_limits; +#include <tuple> +#include <utility> // pair, make_pair + + +//[root_finding_nth_functor_2deriv +template <int N, class T = double> +struct nth_functor_2deriv +{ // Functor returning both 1st and 2nd derivatives. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((N > 0) == true, "root N must be > 0!"); + + nth_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; + 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'. +}; + +//] [/root_finding_nth_functor_2deriv] + +/* +To show the progress, one might use this before the return statement above? +#ifdef BOOST_MATH_ROOT_DIAGNOSTIC +std::cout << " x = " << x << ", fx = " << fx << ", dx = " << dx << ", dx2 = " << d2x << std::endl; +#endif +*/ + +// 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 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 the full range of T. +// typedef double guess_type; is used to specify the this. + +//[root_finding_nth_function_2deriv + +template <int N, class T = double> +T nth_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. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((N > 0) == true, "root N must be > 0!"); + static_assert((N > 1000) == false, "root N is too big!"); + + 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). + T guess = ldexp(static_cast<guess_type>(1.), exponent / N); // Rough guess is to divide the exponent by n. + T min = ldexp(static_cast<guess_type>(1.) / 2, exponent / N); // Minimum possible value is half our guess. + T max = ldexp(static_cast<guess_type>(2.), exponent / N); // Maximum possible value is twice our guess. + + int digits = std::numeric_limits<T>::digits * 0.4; // Accuracy triples with each step, so stop when + // slightly more than one third of the digits are correct. + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = halley_iterate(nth_functor_2deriv<N, T>(x), guess, min, max, digits, it); + return result; +} + +//] [/root_finding_nth_function_2deriv] + + +template <int N, typename T = double> +T show_nth_root(T value) +{ // Demonstrate by printing the nth root using all possibly significant digits. + //std::cout.precision(std::numeric_limits<T>::max_digits10); + // or use cout.precision(max_digits10 = 2 + std::numeric_limits<double>::digits * 3010/10000); + // Or guaranteed significant digits: + std::cout.precision(std::numeric_limits<T>::digits10); + + T r = nth_2deriv<N>(value); + std::cout << "Type " << typeid(T).name() << " value = " << value << ", " << N << "th root = " << r << std::endl; + return r; +} // print_nth_root + + +int main() +{ + std::cout << "nth Root finding Example." << std::endl; + using boost::multiprecision::cpp_dec_float_50; // decimal. + using boost::multiprecision::cpp_bin_float_50; // binary. +#ifndef _MSC_VER // Not supported by Microsoft compiler. + using boost::multiprecision::float128; // Requires libquadmath +#endif + try + { // Always use try'n'catch blocks with Boost.Math to get any error messages. + +//[root_finding_n_example_1 + double r1 = nth_2deriv<5, double>(2); // Integral value converted to double. + + // double r2 = nth_2deriv<5>(2); // Only floating-point type types can be used! + +//] [/root_finding_n_example_1 + + //show_nth_root<5, float>(2); // Integral value converted to float. + //show_nth_root<5, float>(2.F); // 'initializing' : conversion from 'double' to 'float', possible loss of data + +//[root_finding_n_example_2 + + + 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<5, float128>(2); +#endif + show_nth_root<5, cpp_dec_float_50>(2); // dec + show_nth_root<5, cpp_bin_float_50>(2); // bin +//] [/root_finding_n_example_2 + + // show_nth_root<1000000>(2.); // Type double value = 2, 555th root = 1.00124969405651 + // Type double value = 2, 1000th root = 1.00069338746258 + // Type double value = 2, 1000000th root = 1.00000069314783 + } + 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. + // 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 << + "\n""Message from thrown exception was:\n " << e.what() << std::endl; + } + return 0; +} // int main() + + +/* +//[root_finding_example_output_1 + Using MSVC 2013 + +nth Root finding Example. +Type double value = 2, 5th root = 1.14869835499704 +Type long double value = 2, 5th root = 1.14869835499704 +Type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_dec_float<50,int,void>,1> value = 2, + 5th root = 1.1486983549970350067986269467779275894438508890978 +Type class boost::multiprecision::number<class boost::multiprecision::backends::cpp_bin_float<50,10,void,int,0,0>,0> value = 2, + 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 :-( + + */ diff --git a/src/boost/libs/math/example/root_finding_start_locations.cpp b/src/boost/libs/math/example/root_finding_start_locations.cpp new file mode 100644 index 000000000..cc848312a --- /dev/null +++ b/src/boost/libs/math/example/root_finding_start_locations.cpp @@ -0,0 +1,449 @@ +// Copyright John Maddock 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 & Schroder 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! +// 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/math/tools/roots.hpp> +#include <boost/math/special_functions/ellint_1.hpp> +#include <boost/math/special_functions/ellint_2.hpp> +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'. +}; +//] [/root_finding_noderiv_1 + +template <class T> +std::uintmax_t cbrt_noderiv(T x, T guess) +{ + // return cube root of x using bracket_and_solve (no derivatives). + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For bracket_and_solve_root. + + T factor = 2; // How big steps to take when searching. + + const std::uintmax_t maxit = 20; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially 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 = digits - 3; // We have to have a non-zero interval at each step, so + // maximum accuracy is digits - 1. But we also have to + // allow for inaccuracy in f(x), otherwise the last few + // iterations just thrash around. + eps_tolerance<T> tol(get_digits); // Set the tolerance. + bracket_and_solve_root(cbrt_functor_noderiv<T>(x), guess, factor, is_rising, tol, it); + return it; +} + +template <class T> +struct cbrt_functor_deriv +{ // 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>(a) to use to get cube root of a. + } + 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; // Store value to be 'cube_rooted'. +}; + +template <class T> +std::uintmax_t cbrt_deriv(T x, T guess) +{ + // return cube root of x using 1st derivative and Newton_Raphson. + using namespace boost::math::tools; + T min = guess / 100; // We don't really know what this should be! + T max = guess * 100; // We don't really know what this should be! + const int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T. + int get_digits = static_cast<int>(digits * 0.6); // Accuracy doubles with each step, so stop when we have + // just over half the digits correct. + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + newton_raphson_iterate(cbrt_functor_deriv<T>(x), guess, min, max, get_digits, it); + return it; +} + +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, + } + 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). + 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. + } +private: + T a; // to be 'cube_rooted'. +}; + +template <class T> +std::uintmax_t cbrt_2deriv(T x, T guess) +{ + // 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; + T min = guess / 100; // We don't really know what this should be! + T max = guess * 100; // We don't really know what this should be! + 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 * 0.4); // Accuracy triples with each step, so stop when just + // over one third of the digits are correct. + std::uintmax_t maxit = 20; + halley_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, get_digits, maxit); + return maxit; +} + +template <class T> +std::uintmax_t cbrt_2deriv_s(T x, T guess) +{ + // 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; + T min = guess / 100; // We don't really know what this should be! + T max = guess * 100; // We don't really know what this should be! + 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 * 0.4); // Accuracy triples with each step, so stop when just + // over one third of the digits are correct. + std::uintmax_t maxit = 20; + schroder_iterate(cbrt_functor_2deriv<T>(x), guess, min, max, get_digits, maxit); + return maxit; +} + +template <typename T = double> +struct elliptic_root_functor_noderiv +{ + elliptic_root_functor_noderiv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) + { // Constructor just stores value a to find root of. + } + T operator()(T const& x) + { + // return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x: + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T k = sqrt(1 - b * b / (a * a)); + return 4 * a * boost::math::ellint_2(k) - m_arc; + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; // template <class T> struct elliptic_root_functor_noderiv + +template <class T = double> +std::uintmax_t elliptic_root_noderiv(T radius, T arc, T guess) +{ // return the other radius of an ellipse, given one radii and the arc-length + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For bracket_and_solve_root. + + T factor = 2; // How big steps to take when searching. + + const std::uintmax_t maxit = 50; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially our chosen max iterations, but updated with actual. + bool is_rising = true; // arc-length increases if one radii increases, so function is rising + // Define a termination condition, stop when nearly all digits are correct, but allow for + // the fact that we are returning a range, and must have some inaccuracy in the elliptic integral: + eps_tolerance<T> tol(std::numeric_limits<T>::digits - 2); + // Call bracket_and_solve_root to find the solution, note that this is a rising function: + bracket_and_solve_root(elliptic_root_functor_noderiv<T>(arc, radius), guess, factor, is_rising, tol, it); + return it; +} + +template <class T = double> +struct elliptic_root_functor_1deriv +{ // Functor also returning 1st derivative. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + elliptic_root_functor_1deriv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) + { // Constructor just stores value a to find root of. + } + std::pair<T, T> operator()(T const& x) + { + // Return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x, plus it's derivative. + // See http://www.wolframalpha.com/input/?i=d%2Fda+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29] + // We require two elliptic integral calls, but from these we can calculate both + // the function and it's derivative: + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T a2 = a * a; + T b2 = b * b; + T k = sqrt(1 - b2 / a2); + T Ek = boost::math::ellint_2(k); + T Kk = boost::math::ellint_1(k); + T fx = 4 * a * Ek - m_arc; + T dfx = 4 * (a2 * Ek - b2 * Kk) / (a2 - b2); + return std::make_pair(fx, dfx); + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; // struct elliptic_root__functor_1deriv + +template <class T = double> +std::uintmax_t elliptic_root_1deriv(T radius, T arc, T guess) +{ + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For newton_raphson_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T min = 0; // Minimum possible value is zero. + T max = arc; // Maximum possible value is the arc length. + + // Accuracy doubles at each step, so stop when just over half of the digits are + // correct, and rely on that step to polish off the remainder: + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.6); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + newton_raphson_iterate(elliptic_root_functor_1deriv<T>(arc, radius), guess, min, max, get_digits, it); + return it; +} + +template <class T = double> +struct elliptic_root_functor_2deriv +{ // Functor returning both 1st and 2nd derivatives. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + elliptic_root_functor_2deriv(T const& arc, T const& radius) : m_arc(arc), m_radius(radius) {} + std::tuple<T, T, T> operator()(T const& x) + { + // Return the difference between required arc-length, and the calculated arc-length for an + // ellipse with radii m_radius and x, plus it's derivative. + // See http://www.wolframalpha.com/input/?i=d^2%2Fda^2+[4+*+a+*+EllipticE%281+-+b^2%2Fa^2%29] + // for the second derivative. + T a = (std::max)(m_radius, x); + T b = (std::min)(m_radius, x); + T a2 = a * a; + T b2 = b * b; + T k = sqrt(1 - b2 / a2); + T Ek = boost::math::ellint_2(k); + T Kk = boost::math::ellint_1(k); + T fx = 4 * a * Ek - m_arc; + T dfx = 4 * (a2 * Ek - b2 * Kk) / (a2 - b2); + T dfx2 = 4 * b2 * ((a2 + b2) * Kk - 2 * a2 * Ek) / (a * (a2 - b2) * (a2 - b2)); + return std::make_tuple(fx, dfx, dfx2); + } +private: + T m_arc; // length of arc. + T m_radius; // one of the two radii of the ellipse +}; + +template <class T = double> +std::uintmax_t elliptic_root_2deriv(T radius, T arc, T guess) +{ + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For halley_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T min = 0; // Minimum possible value is zero. + T max = arc; // radius can't be larger than the arc length. + + // Accuracy triples at each step, so stop when just over one-third of the digits + // are correct, and the last iteration will polish off the remaining digits: + int get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + halley_iterate(elliptic_root_functor_2deriv<T>(arc, radius), guess, min, max, get_digits, it); + return it; +} // nth_2deriv Halley +//] +// Using 1st and 2nd derivatives using Schroder algorithm. + +template <class T = double> +std::uintmax_t elliptic_root_2deriv_s(T radius, T arc, T guess) +{ // return nth root of x using 1st and 2nd derivatives and Schroder. + + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For schroder_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + + T min = 0; // Minimum possible value is zero. + T max = arc; // radius can't be larger than the arc length. + + int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T. + int get_digits = static_cast<int>(digits * 0.4); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + schroder_iterate(elliptic_root_functor_2deriv<T>(arc, radius), guess, min, max, get_digits, it); + return it; +} // T elliptic_root_2deriv_s Schroder + + +int main() +{ + try + { + double to_root = 500; + double answer = 7.93700525984; + + std::cout << "[table\n" + << "[[Initial Guess=][-500% ([approx]1.323)][-100% ([approx]3.97)][-50% ([approx]3.96)][-20% ([approx]6.35)][-10% ([approx]7.14)][-5% ([approx]7.54)]" + "[5% ([approx]8.33)][10% ([approx]8.73)][20% ([approx]9.52)][50% ([approx]11.91)][100% ([approx]15.87)][500 ([approx]47.6)]]\n"; + std::cout << "[[bracket_and_solve_root][" + << cbrt_noderiv(to_root, answer / 6) + << "][" << cbrt_noderiv(to_root, answer / 2) + << "][" << cbrt_noderiv(to_root, answer - answer * 0.5) + << "][" << cbrt_noderiv(to_root, answer - answer * 0.2) + << "][" << cbrt_noderiv(to_root, answer - answer * 0.1) + << "][" << cbrt_noderiv(to_root, answer - answer * 0.05) + << "][" << cbrt_noderiv(to_root, answer + answer * 0.05) + << "][" << cbrt_noderiv(to_root, answer + answer * 0.1) + << "][" << cbrt_noderiv(to_root, answer + answer * 0.2) + << "][" << cbrt_noderiv(to_root, answer + answer * 0.5) + << "][" << cbrt_noderiv(to_root, answer + answer) + << "][" << cbrt_noderiv(to_root, answer + answer * 5) << "]]\n"; + + std::cout << "[[newton_iterate][" + << cbrt_deriv(to_root, answer / 6) + << "][" << cbrt_deriv(to_root, answer / 2) + << "][" << cbrt_deriv(to_root, answer - answer * 0.5) + << "][" << cbrt_deriv(to_root, answer - answer * 0.2) + << "][" << cbrt_deriv(to_root, answer - answer * 0.1) + << "][" << cbrt_deriv(to_root, answer - answer * 0.05) + << "][" << cbrt_deriv(to_root, answer + answer * 0.05) + << "][" << cbrt_deriv(to_root, answer + answer * 0.1) + << "][" << cbrt_deriv(to_root, answer + answer * 0.2) + << "][" << cbrt_deriv(to_root, answer + answer * 0.5) + << "][" << cbrt_deriv(to_root, answer + answer) + << "][" << cbrt_deriv(to_root, answer + answer * 5) << "]]\n"; + + std::cout << "[[halley_iterate][" + << cbrt_2deriv(to_root, answer / 6) + << "][" << cbrt_2deriv(to_root, answer / 2) + << "][" << cbrt_2deriv(to_root, answer - answer * 0.5) + << "][" << cbrt_2deriv(to_root, answer - answer * 0.2) + << "][" << cbrt_2deriv(to_root, answer - answer * 0.1) + << "][" << cbrt_2deriv(to_root, answer - answer * 0.05) + << "][" << cbrt_2deriv(to_root, answer + answer * 0.05) + << "][" << cbrt_2deriv(to_root, answer + answer * 0.1) + << "][" << cbrt_2deriv(to_root, answer + answer * 0.2) + << "][" << cbrt_2deriv(to_root, answer + answer * 0.5) + << "][" << cbrt_2deriv(to_root, answer + answer) + << "][" << cbrt_2deriv(to_root, answer + answer * 5) << "]]\n"; + + std::cout << "[[schr'''ö'''der_iterate][" + << cbrt_2deriv_s(to_root, answer / 6) + << "][" << cbrt_2deriv_s(to_root, answer / 2) + << "][" << cbrt_2deriv_s(to_root, answer - answer * 0.5) + << "][" << cbrt_2deriv_s(to_root, answer - answer * 0.2) + << "][" << cbrt_2deriv_s(to_root, answer - answer * 0.1) + << "][" << cbrt_2deriv_s(to_root, answer - answer * 0.05) + << "][" << cbrt_2deriv_s(to_root, answer + answer * 0.05) + << "][" << cbrt_2deriv_s(to_root, answer + answer * 0.1) + << "][" << cbrt_2deriv_s(to_root, answer + answer * 0.2) + << "][" << cbrt_2deriv_s(to_root, answer + answer * 0.5) + << "][" << cbrt_2deriv_s(to_root, answer + answer) + << "][" << cbrt_2deriv_s(to_root, answer + answer * 5) << "]]\n]\n\n"; + + + double radius_a = 10; + double arc_length = 500; + double radius_b = 123.6216507967705; + + std::cout << std::setprecision(4) << "[table\n" + << "[[Initial Guess=][-500% ([approx]" << radius_b / 6 << ")][-100% ([approx]" << radius_b / 2 << ")][-50% ([approx]" + << radius_b - radius_b * 0.5 << ")][-20% ([approx]" << radius_b - radius_b * 0.2 << ")][-10% ([approx]" << radius_b - radius_b * 0.1 << ")][-5% ([approx]" << radius_b - radius_b * 0.05 << ")]" + "[5% ([approx]" << radius_b + radius_b * 0.05 << ")][10% ([approx]" << radius_b + radius_b * 0.1 << ")][20% ([approx]" << radius_b + radius_b * 0.2 << ")][50% ([approx]" << radius_b + radius_b * 0.5 + << ")][100% ([approx]" << radius_b + radius_b << ")][500 ([approx]" << radius_b + radius_b * 5 << ")]]\n"; + std::cout << "[[bracket_and_solve_root][" + << elliptic_root_noderiv(radius_a, arc_length, radius_b / 6) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b / 2) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b - radius_b * 0.5) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b - radius_b * 0.2) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b - radius_b * 0.1) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b - radius_b * 0.05) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b * 0.05) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b * 0.1) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b * 0.2) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b * 0.5) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b) + << "][" << elliptic_root_noderiv(radius_a, arc_length, radius_b + radius_b * 5) << "]]\n"; + + std::cout << "[[newton_iterate][" + << elliptic_root_1deriv(radius_a, arc_length, radius_b / 6) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b / 2) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b - radius_b * 0.5) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b - radius_b * 0.2) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b - radius_b * 0.1) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b - radius_b * 0.05) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b * 0.05) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b * 0.1) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b * 0.2) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b * 0.5) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b) + << "][" << elliptic_root_1deriv(radius_a, arc_length, radius_b + radius_b * 5) << "]]\n"; + + std::cout << "[[halley_iterate][" + << elliptic_root_2deriv(radius_a, arc_length, radius_b / 6) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b / 2) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b - radius_b * 0.5) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b - radius_b * 0.2) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b - radius_b * 0.1) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b - radius_b * 0.05) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b * 0.05) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b * 0.1) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b * 0.2) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b * 0.5) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b) + << "][" << elliptic_root_2deriv(radius_a, arc_length, radius_b + radius_b * 5) << "]]\n"; + + std::cout << "[[schr'''ö'''der_iterate][" + << elliptic_root_2deriv_s(radius_a, arc_length, radius_b / 6) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b / 2) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b - radius_b * 0.5) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b - radius_b * 0.2) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b - radius_b * 0.1) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b - radius_b * 0.05) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b * 0.05) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b * 0.1) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b * 0.2) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b * 0.5) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b) + << "][" << elliptic_root_2deriv_s(radius_a, arc_length, radius_b + radius_b * 5) << "]]\n]\n\n"; + + return boost::exit_success; + } + catch(std::exception ex) + { + std::cout << "exception thrown: " << ex.what() << std::endl; + return boost::exit_failure; + } +} // int main() + diff --git a/src/boost/libs/math/example/root_n_finding_algorithms.cpp b/src/boost/libs/math/example/root_n_finding_algorithms.cpp new file mode 100644 index 000000000..0cf2a7c71 --- /dev/null +++ b/src/boost/libs/math/example/root_n_finding_algorithms.cpp @@ -0,0 +1,869 @@ +// 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 & Schroder 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/math/concepts/real_concept.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::schroder_iterate; + +#include <boost/math/special_functions/next.hpp> // For float_distance. +#include <boost/math/special_functions/pow.hpp> // For pow<N>. +#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/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(); +#include <type_traits> + +#ifdef __FILE__ + std::string sourcefilename = __FILE__; +#else + std::string sourcefilename(""); +#endif + + std::string chop_last(std::string s) + { + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(pos); + else if(s.empty()) + abort(); + else + s.erase(); + return s; + } + + std::string make_root() + { + std::string result; + if(sourcefilename.find_first_of(":") != std::string::npos) + { + result = chop_last(sourcefilename); // lose filename part + result = chop_last(result); // lose /example/ + result = chop_last(result); // lose /math/ + result = chop_last(result); // lose /libs/ + } + else + { + result = chop_last(sourcefilename); // lose filename part + if(result.empty()) + result = "."; + result += "/../../.."; + } + return result; + } + + std::string short_file_name(std::string s) + { + std::string::size_type pos = s.find_last_of("\\/"); + if(pos != std::string::npos) + s.erase(0, pos + 1); + return s; + } + + std::string boost_root = make_root(); + + +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; + +double digits_accuracy = 1.0; // 1 == maximum possible accuracy. + +std::stringstream ss; + +std::ofstream fout; + +std::vector<std::string> algo_names = +{ + "TOMS748", "Newton", "Halley", "Schr'''ö'''der" +}; + +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 & Schroder. + //std::vector< std::int_least64_t> times; converted to int. + std::vector<int> times; // arbitrary units (ticks). + //std::int_least64_t min_time = std::numeric_limits<std::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; +#if defined(_DEBUG) || !defined(NDEBUG) + result += "|"; + result += " debug"; +#else + result += "|"; + result += " release"; +#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 std::uintmax_t maxit = 50; // Limit to maximum iterations. + std::uintmax_t it = maxit; // Initially 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. + // Some fraction of digits is used to control how accurate to try to make the result. + int get_digits = std::numeric_limits<T>::digits - 2; + 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 derivative. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((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 p = pow<N - 1>(x); + return std::make_pair(p * x - a, N * p); // '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. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((N > 0) == true, "root N must be > 0!"); + static_assert((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 * 0.6); + const std::uintmax_t maxit = 20; + std::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. + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((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 p = pow<N - 2>(x); + + return std::make_tuple(p * x * x - a, p * x * N, p * N * (N - 1)); // '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. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((N > 0) == true, "root N must be > 0!"); + static_assert((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 * 0.4); + const std::uintmax_t maxit = 20; + std::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 + +template <int N, class T = double> +T nth_root_2deriv_s(T x) +{ // return nth root of x using 1st and 2nd derivatives and Schroder. + + using namespace std; // Help ADL of std functions. + using namespace boost::math::tools; // For schroder_iterate. + + static_assert(boost::is_integral<T>::value == false, "Only floating-point type types can be used!"); + static_assert((N > 0) == true, "root N must be > 0!"); + static_assert((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 get_digits = static_cast<int>(std::numeric_limits<T>::digits * 0.4); + const std::uintmax_t maxit = 20; + std::uintmax_t it = maxit; + T result = schroder_iterate(nth_root_functor_2deriv<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 sum = 0; + T ans = static_cast<T>(answer); + + using boost::timer::nanosecond_type; + using boost::timer::cpu_times; + using boost::timer::cpu_timer; + + int eval_count = std::is_floating_point<T>::value ? 10000000 : 100000; // 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); // + sum += result; + } + 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); // + sum += result; + } + 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); // + sum += result; + } + 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("Schroder"); // 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); // + sum += result; + } + 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); + } + + std::cout << "Accumulated result was: " << sum << std::endl; + + return 4; // eval_count of how many algorithms used. +} // test_root + +/*! Fill array of times, iterations, 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) +{ + using std::abs; + std::cout << nooftypes << " floating-point types tested:" << std::endl; +#if defined(_DEBUG) || !defined(NDEBUG) + std::cout << "Compiled in debug mode." << std::endl; +#else + std::cout << "Compiled in optimise mode." << std::endl; +#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); + + root_infos.clear(); // Erase any previous data. + // Fill the elements of the array for each floating-point type. + + test_root<N, float>(full_value, full_answer, "float", 0); + test_root<N, double>(full_value, full_answer, "double", 1); + test_root<N, long double>(full_value, full_answer, "long double", 2); + 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 :-( + +#if defined(_DEBUG) || !defined(NDEBUG) + std::string debug_or_optimize("Compiled in debug mode."); +#else + std::string debug_or_optimize("Compiled in optimise mode."); +#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)) +#ifndef _M_X64 +# define _M_X64 +#endif +#ifndef __SSE2__ +# define __SSE2__ +#endif +#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 const& ex) + { + std::cout << "exception thrown: " << ex.what() << std::endl; + return boost::exit_failure; + } +} // int main() + +/* + +*/ diff --git a/src/boost/libs/math/example/series.cpp b/src/boost/libs/math/example/series.cpp new file mode 100644 index 000000000..648f4ee02 --- /dev/null +++ b/src/boost/libs/math/example/series.cpp @@ -0,0 +1,107 @@ +// (C) Copyright John Maddock 2018. +// 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) + +#include <boost/math/tools/series.hpp> +#include <boost/math/tools/assert.hpp> + +#include <iostream> +#include <complex> +#include <cassert> + +//[series_log1p +template <class T> +struct log1p_series +{ + // we must define a result_type typedef: + typedef T result_type; + + log1p_series(T x) + : k(0), m_mult(-x), m_prod(-1) {} + + T operator()() + { + // This is the function operator invoked by the summation + // algorithm, the first call to this operator should return + // the first term of the series, the second call the second + // term and so on. + m_prod *= m_mult; + return m_prod / ++k; + } + +private: + int k; + const T m_mult; + T m_prod; +}; +//] + +//[series_log1p_func +template <class T> +T log1p(T x) +{ + // We really should add some error checking on x here! + BOOST_MATH_ASSERT(std::fabs(x) < 1); + + // Construct the series functor: + log1p_series<T> s(x); + // Set a limit on how many iterations we permit: + std::uintmax_t max_iter = 1000; + // Add it up, with enough precision for full machine precision: + return boost::math::tools::sum_series(s, std::numeric_limits<T>::epsilon(), max_iter); +} +//] + +//[series_clog1p_func +template <class T> +struct log1p_series<std::complex<T> > +{ + // we must define a result_type typedef: + typedef std::complex<T> result_type; + + log1p_series(std::complex<T> x) + : k(0), m_mult(-x), m_prod(-1) {} + + std::complex<T> operator()() + { + // This is the function operator invoked by the summation + // algorithm, the first call to this operator should return + // the first term of the series, the second call the second + // term and so on. + m_prod *= m_mult; + return m_prod / T(++k); + } + +private: + int k; + const std::complex<T> m_mult; + std::complex<T> m_prod; +}; + + +template <class T> +std::complex<T> log1p(std::complex<T> x) +{ + // We really should add some error checking on x here! + BOOST_MATH_ASSERT(abs(x) < 1); + + // Construct the series functor: + log1p_series<std::complex<T> > s(x); + // Set a limit on how many iterations we permit: + std::uintmax_t max_iter = 1000; + // Add it up, with enough precision for full machine precision: + return boost::math::tools::sum_series(s, std::complex<T>(std::numeric_limits<T>::epsilon()), max_iter); +} +//] + +int main() +{ + using namespace boost::math::tools; + + std::cout << log1p(0.25) << std::endl; + + std::cout << log1p(std::complex<double>(0.25, 0.25)) << std::endl; + + return 0; +} diff --git a/src/boost/libs/math/example/sines.hpp b/src/boost/libs/math/example/sines.hpp new file mode 100644 index 000000000..d4cbbbbf3 --- /dev/null +++ b/src/boost/libs/math/example/sines.hpp @@ -0,0 +1,47 @@ +// 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) + +// Copyright A N Other, 2019. + +// Table of 32 values with 50 decimal digits precision, +// generated by program fft_sines_table.cpp. + +#include <array> // std::array + +static const std::array<double, 32> sines = +{{ + 1, + 0.70710678118654752440084436210484903928483593768847, + 0.38268343236508977172845998403039886676134456248563, + 0.19509032201612826784828486847702224092769161775195, + 0.098017140329560601994195563888641845861136673167501, + 0.049067674327418014254954976942682658314745363025753, + 0.024541228522912288031734529459282925065466119239452, + 0.012271538285719926079408261951003212140372319591769, + 0.0061358846491544753596402345903725809170578863173913, + 0.003067956762965976270145365490919842518944610213452, + 0.0015339801862847656123036971502640790799548645752374, + 0.00076699031874270452693856835794857664314091945206328, + 0.00038349518757139558907246168118138126339502603496474, + 0.00019174759731070330743990956198900093346887403385916, + 9.5873799095977345870517210976476351187065612851145e-05, + 4.7936899603066884549003990494658872746866687685767e-05, + 2.3968449808418218729186577165021820094761474895673e-05, + 1.1984224905069706421521561596988984804731977538387e-05, + 5.9921124526424278428797118088908617299871778780951e-06, + 2.9960562263346607504548128083570598118251878683408e-06, + 1.4980281131690112288542788461553611206917585861527e-06, + 7.4901405658471572113049856673065563715595930217207e-07, + 3.7450702829238412390316917908463317739740476297248e-07, + 1.8725351414619534486882457659356361712045272098286e-07, + 9.3626757073098082799067286680885620193236507169473e-08, + 4.681337853654909269511551813854009695950362701667e-08, + 2.3406689268274552759505493419034844037886207223779e-08, + 1.1703344634137277181246213503238103798093456639976e-08, + 5.8516723170686386908097901008341396943900085051756e-09, + 2.9258361585343193579282304690689559020175857150074e-09, + 1.4629180792671596805295321618659637103742615227834e-09, + 7.3145903963357984046044319684941757518633453150407e-10 +}}; // array sines diff --git a/src/boost/libs/math/example/skew_normal_example.cpp b/src/boost/libs/math/example/skew_normal_example.cpp new file mode 100644 index 000000000..5858aff35 --- /dev/null +++ b/src/boost/libs/math/example/skew_normal_example.cpp @@ -0,0 +1,275 @@ +// Copyright Benjamin Sobotta 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) + + +#ifdef _MSC_VER +# pragma warning (disable : 4512) // assignment operator could not be generated +# pragma warning (disable : 4127) // conditional expression is constant. +#endif + +#include <boost/math/distributions/skew_normal.hpp> +using boost::math::skew_normal_distribution; +using boost::math::skew_normal; +#include <iostream> +#include <cmath> +#include <utility> + +void check(const double loc, const double sc, const double sh, + const double * const cumulants, const std::pair<double, double> qu, + const double x, const double tpdf, const double tcdf) +{ + using namespace boost::math; + + skew_normal D(loc, sc, sh); + + const double sk = cumulants[2] / (std::pow(cumulants[1], 1.5)); + const double kt = cumulants[3] / (cumulants[1] * cumulants[1]); + + // checks against tabulated values + std::cout << "mean: table=" << cumulants[0] << "\tcompute=" << mean(D) << "\tdiff=" << fabs(cumulants[0]-mean(D)) << std::endl; + std::cout << "var: table=" << cumulants[1] << "\tcompute=" << variance(D) << "\tdiff=" << fabs(cumulants[1]-variance(D)) << std::endl; + std::cout << "skew: table=" << sk << "\tcompute=" << skewness(D) << "\tdiff=" << fabs(sk-skewness(D)) << std::endl; + std::cout << "kur.: table=" << kt << "\tcompute=" << kurtosis_excess(D) << "\tdiff=" << fabs(kt-kurtosis_excess(D)) << std::endl; + std::cout << "mode: table=" << "N/A" << "\tcompute=" << mode(D) << "\tdiff=" << "N/A" << std::endl; + + const double q = quantile(D, qu.first); + const double cq = quantile(complement(D, qu.first)); + + std::cout << "quantile(" << qu.first << "): table=" << qu.second << "\tcompute=" << q << "\tdiff=" << fabs(qu.second-q) << std::endl; + + // consistency + std::cout << "cdf(quantile)=" << cdf(D, q) << "\tp=" << qu.first << "\tdiff=" << fabs(qu.first-cdf(D, q)) << std::endl; + std::cout << "ccdf(cquantile)=" << cdf(complement(D,cq)) << "\tp=" << qu.first << "\tdiff=" << fabs(qu.first-cdf(complement(D,cq))) << std::endl; + + // PDF & CDF + std::cout << "pdf(" << x << "): table=" << tpdf << "\tcompute=" << pdf(D,x) << "\tdiff=" << fabs(tpdf-pdf(D,x)) << std::endl; + std::cout << "cdf(" << x << "): table=" << tcdf << "\tcompute=" << cdf(D,x) << "\tdiff=" << fabs(tcdf-cdf(D,x)) << std::endl; + std::cout << "================================\n"; +} + +int main() +{ + using namespace boost::math; + + double sc = 0.0,loc,sh,x,dsn,qsn,psn,p; + std::cout << std::setprecision(20); + + double cumulants[4]; + + + /* R: + > install.packages("sn") + Warning in install.packages("sn") : + 'lib = "/usr/lib64/R/library"' is not writable + Would you like to create a personal library + '~/R/x86_64-unknown-linux-gnu-library/2.12' + to install packages into? (y/n) y + --- Please select a CRAN mirror for use in this session --- + Loading Tcl/Tk interface ... done + also installing the dependency mnormt + + trying URL 'http://mirrors.dotsrc.org/cran/src/contrib/mnormt_1.4-5.tar.gz' + Content type 'application/x-gzip' length 34049 bytes (33 Kb) + opened URL + ================================================== + downloaded 33 Kb + + trying URL 'http://mirrors.dotsrc.org/cran/src/contrib/sn_0.4-17.tar.gz' + Content type 'application/x-gzip' length 65451 bytes (63 Kb) + opened URL + ================================================== + downloaded 63 Kb + + + > library(sn) + > options(digits=22) + + + > sn.cumulants(1.1, 2.2, -3.3) + [1] -0.5799089925398568 2.0179057767837230 -2.0347951542374196 + [4] 2.2553488991015072 + > qsn(0.3, 1.1, 2.2, -3.3) + [1] -1.180104068086876 + > psn(0.4, 1.1, 2.2, -3.3) + [1] 0.733918618927874 + > dsn(0.4, 1.1, 2.2, -3.3) + [1] 0.2941401101565995 + + */ + + //1 st + loc = 1.1; sc = 2.2; sh = -3.3; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = -0.5799089925398568; + cumulants[1] = 2.0179057767837230; + cumulants[2] = -2.0347951542374196; + cumulants[3] = 2.2553488991015072; + x = 0.4; + p = 0.3; + qsn = -1.180104068086876; + psn = 0.733918618927874; + dsn = 0.2941401101565995; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + /* R: + + > sn.cumulants(1.1, .02, .03) + [1] 1.1004785154529559e+00 3.9977102296128255e-04 4.7027439329779991e-11 + [4] 1.4847542790693825e-14 + > qsn(0.01, 1.1, .02, .03) + [1] 1.053964962950150 + > psn(1.3, 1.1, .02, .03) + [1] 1 + > dsn(1.3, 1.1, .02, .03) + [1] 4.754580380601393e-21 + + */ + + // 2nd + loc = 1.1; sc = .02; sh = .03; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = 1.1004785154529559e+00; + cumulants[1] = 3.9977102296128255e-04; + cumulants[2] = 4.7027439329779991e-11; + cumulants[3] = 1.4847542790693825e-14; + x = 1.3; + p = 0.01; + qsn = 1.053964962950150; + psn = 1; + dsn = 4.754580380601393e-21; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + /* R: + + > sn.cumulants(10.1, 5, -.03) + [1] 9.980371136761052e+00 2.498568893508016e+01 -7.348037395278123e-04 + [4] 5.799821402614775e-05 + > qsn(.8, 10.1, 5, -.03) + [1] 14.18727407491953 + > psn(-1.3, 10.1, 5, -.03) + [1] 0.01201290665838824 + > dsn(-1.3, 10.1, 5, -.03) + [1] 0.006254346348897927 + + + */ + + // 3rd + loc = 10.1; sc = 5; sh = -.03; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = 9.980371136761052e+00; + cumulants[1] = 2.498568893508016e+01; + cumulants[2] = -7.348037395278123e-04; + cumulants[3] = 5.799821402614775e-05; + x = -1.3; + p = 0.8; + qsn = 14.18727407491953; + psn = 0.01201290665838824; + dsn = 0.006254346348897927; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + + /* R: + + > sn.cumulants(-10.1, 5, 30) + [1] -6.112791696741384 9.102169946425548 27.206345266148194 71.572537838642916 + > qsn(.8, -10.1, 5, 30) + [1] -3.692242172277 + > psn(-1.3, -10.1, 5, 30) + [1] 0.921592193425035 + > dsn(-1.3, -10.1, 5, 30) + [1] 0.0339105445232089 + + */ + + // 4th + loc = -10.1; sc = 5; sh = 30; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = -6.112791696741384; + cumulants[1] = 9.102169946425548; + cumulants[2] = 27.206345266148194; + cumulants[3] = 71.572537838642916; + x = -1.3; + p = 0.8; + qsn = -3.692242172277; + psn = 0.921592193425035; + dsn = 0.0339105445232089; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + + /* R: + + > sn.cumulants(0,1,5) + [1] 0.7823901817554269 0.3878656034927102 0.2055576317962637 0.1061119471655128 + > qsn(0.5,0,1,5) + [1] 0.674471117502844 + > psn(-0.5, 0,1,5) + [1] 0.0002731513884140924 + > dsn(-0.5, 0,1,5) + [1] 0.00437241570403263 + + */ + + // 5th + loc = 0; sc = 1; sh = 5; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = 0.7823901817554269; + cumulants[1] = 0.3878656034927102; + cumulants[2] = 0.2055576317962637; + cumulants[3] = 0.1061119471655128; + x = -0.5; + p = 0.5; + qsn = 0.674471117502844; + psn = 0.0002731513884140924; + dsn = 0.00437241570403263; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + /* R: + + > sn.cumulants(0,1,1e5) + [1] 0.7978845607629713 0.3633802276960805 0.2180136141122883 0.1147706820312645 + > qsn(0.5,0,1,1e5) + [1] 0.6744897501960818 + > psn(-0.5, 0,1,1e5) + [1] 0 + > dsn(-0.5, 0,1,1e5) + [1] 0 + + */ + + // 6th + loc = 0; sc = 1; sh = 1e5; + std::cout << "location: " << loc << "\tscale: " << sc << "\tshape: " << sh << std::endl; + cumulants[0] = 0.7978845607629713; + cumulants[1] = 0.3633802276960805; + cumulants[2] = 0.2180136141122883; + cumulants[3] = 0.1147706820312645; + x = -0.5; + p = 0.5; + qsn = 0.6744897501960818; + psn = 0.; + dsn = 0.; + + check(loc, sc, sh, cumulants, std::make_pair(p,qsn), x, dsn, psn); + + return 0; +} + + +// EOF + + + + + + + + diff --git a/src/boost/libs/math/example/special_data.cpp b/src/boost/libs/math/example/special_data.cpp new file mode 100644 index 000000000..159be5809 --- /dev/null +++ b/src/boost/libs/math/example/special_data.cpp @@ -0,0 +1,88 @@ +// Copyright John Maddock 2006. +// 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) + +//[special_data_example + +#ifndef BOOST_MATH_STANDALONE + +#include <boost/multiprecision/cpp_dec_float.hpp> +#include <boost/math/tools/test_data.hpp> +#include <boost/test/included/prg_exec_monitor.hpp> +#include <fstream> + +using namespace boost::math::tools; +using namespace boost::math; +using namespace std; +using namespace boost::multiprecision; + +template <class T> +T my_special(T a, T b) +{ + // Implementation of my_special here... + return a + b; +} + +int cpp_main(int argc, char*argv []) +{ + // + // We'll use so many digits of precision that any + // calculation errors will still leave us with + // 40-50 good digits. We'll only run this program + // once so it doesn't matter too much how long this takes! + // + typedef number<cpp_dec_float<500> > bignum; + + parameter_info<bignum> arg1, arg2; + test_data<bignum> data; + + bool cont; + std::string line; + + if(argc < 1) + return 1; + + do{ + // + // User interface which prompts for + // range of input parameters: + // + if(0 == get_user_parameter_info(arg1, "a")) + return 1; + if(0 == get_user_parameter_info(arg2, "b")) + return 1; + + // + // Get a pointer to the function and call + // test_data::insert to actually generate + // the values. + // + bignum (*fp)(bignum, bignum) = &my_special; + data.insert(fp, arg2, arg1); + + std::cout << "Any more data [y/n]?"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + cont = (line == "y"); + }while(cont); + // + // Just need to write the results to a file: + // + std::cout << "Enter name of test data file [default=my_special.ipp]"; + std::getline(std::cin, line); + boost::algorithm::trim(line); + if(line == "") + line = "my_special.ipp"; + std::ofstream ofs(line.c_str()); + line.erase(line.find('.')); + ofs << std::scientific << std::setprecision(50); + write_code(ofs, data, line.c_str()); + + return 0; +} + +//] + +#endif // BOOST_MATH_STANDALONE diff --git a/src/boost/libs/math/example/students_t_example1.cpp b/src/boost/libs/math/example/students_t_example1.cpp new file mode 100644 index 000000000..c86b89d5d --- /dev/null +++ b/src/boost/libs/math/example/students_t_example1.cpp @@ -0,0 +1,101 @@ +// students_t_example1.cpp + +// Copyright Paul A. Bristow 2006, 2007. + +// 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) + +// Example 1 of using Student's t + +// http://en.wikipedia.org/wiki/Student's_t-test says: +// The t statistic was invented by William Sealy Gosset +// for cheaply monitoring the quality of beer brews. +// "Student" was his pen name. +// WS Gosset was statistician for Guinness brewery in Dublin, Ireland, +// hired due to Claude Guinness's innovative policy of recruiting the +// best graduates from Oxford and Cambridge for applying biochemistry +// and statistics to Guinness's industrial processes. +// Gosset published the t test in Biometrika in 1908, +// but was forced to use a pen name by his employer who regarded the fact +// that they were using statistics as a trade secret. +// In fact, Gosset's identity was unknown not only to fellow statisticians +// but to his employer - the company insisted on the pseudonym +// so that it could turn a blind eye to the breach of its rules. + +// Data for this example from: +// P.K.Hou, O. W. Lau & M.C. Wong, Analyst (1983) vol. 108, p 64. +// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 54-55 +// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907 + +// Determination of mercury by cold-vapour atomic absorption, +// the following values were obtained fusing a trusted +// Standard Reference Material containing 38.9% mercury, +// which we assume is correct or 'true'. +double standard = 38.9; + +const int values = 3; +double value[values] = {38.9, 37.4, 37.1}; + +// Is there any evidence for systematic error? + +// The Students't distribution function is described at +// http://en.wikipedia.org/wiki/Student%27s_t_distribution +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; // Probability of students_t(df, t). + +#include <iostream> + using std::cout; using std::endl; +#include <iomanip> + using std::setprecision; +#include <cmath> + using std::sqrt; + +int main() +{ + cout << "Example 1 using Student's t function. " << endl; + + // Example/test using tabulated value + // (deliberately coded as naively as possible). + + // Null hypothesis is that there is no difference (greater or less) + // between measured and standard. + + double degrees_of_freedom = values-1; // 3-1 = 2 + cout << "Measurement 1 = " << value[0] << ", measurement 2 = " << value[1] << ", measurement 3 = " << value[2] << endl; + double mean = (value[0] + value[1] + value[2]) / static_cast<double>(values); + cout << "Standard = " << standard << ", mean = " << mean << ", (mean - standard) = " << mean - standard << endl; + double sd = sqrt(((value[0] - mean) * (value[0] - mean) + (value[1] - mean) * (value[1] - mean) + (value[2] - mean) * (value[2] - mean))/ static_cast<double>(values-1)); + cout << "Standard deviation = " << sd << endl; + if (sd == 0.) + { + cout << "Measured mean is identical to SRM value," << endl; + cout << "so probability of no difference between measured and standard (the 'null hypothesis') is unity." << endl; + return 0; + } + + double t = (mean - standard) * std::sqrt(static_cast<double>(values)) / sd; + cout << "Student's t = " << t << endl; + cout.precision(2); // Useful accuracy is only a few decimal digits. + cout << "Probability of Student's t is " << cdf(students_t(degrees_of_freedom), std::abs(t)) << endl; + // 0.91, is 1 tailed. + // So there is insufficient evidence of a difference to meet a 95% (1 in 20) criterion. + + return 0; +} // int main() + +/* + +Output is: + +Example 1 using Student's t function. +Measurement 1 = 38.9, measurement 2 = 37.4, measurement 3 = 37.1 +Standard = 38.9, mean = 37.8, (mean - standard) = -1.1 +Standard deviation = 0.964365 +Student's t = -1.97566 +Probability of Student's t is 0.91 + +*/ + + diff --git a/src/boost/libs/math/example/students_t_example2.cpp b/src/boost/libs/math/example/students_t_example2.cpp new file mode 100644 index 000000000..bbd423162 --- /dev/null +++ b/src/boost/libs/math/example/students_t_example2.cpp @@ -0,0 +1,126 @@ +// students_t_example2.cpp + +// Copyright Paul A. Bristow 2006. +// 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) + +// Example 2 of using Student's t + +// A general guide to Student's t is at +// http://en.wikipedia.org/wiki/Student's_t-test +// (and many other elementary and advanced statistics texts). +// It says: +// The t statistic was invented by William Sealy Gosset +// for cheaply monitoring the quality of beer brews. +// "Student" was his pen name. +// Gosset was statistician for Guinness brewery in Dublin, Ireland, +// hired due to Claude Guinness's innovative policy of recruiting the +// best graduates from Oxford and Cambridge for applying biochemistry +// and statistics to Guinness's industrial processes. +// Gosset published the t test in Biometrika in 1908, +// but was forced to use a pen name by his employer who regarded the fact +// that they were using statistics as a trade secret. +// In fact, Gosset's identity was unknown not only to fellow statisticians +// but to his employer - the company insisted on the pseudonym +// so that it could turn a blind eye to the breach of its rules. + +// The Students't distribution function is described at +// http://en.wikipedia.org/wiki/Student%27s_t_distribution + +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; // Probability of students_t(df, t). + +#include <iostream> + using std::cout; + using std::endl; +#include <iomanip> + using std::setprecision; + using std::setw; +#include <cmath> + using std::sqrt; + +// This example of a one-sided test is from: +// +// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 59-60 +// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907. + +// An acid-base titrimetric method has a significant indicator error and +// thus tends to give results with a positive systematic error (+bias). +// To test this an exactly 0.1 M solution of acid is used to titrate +// 25.00 ml of exactly 0.1 M solution of alkali, +// with the following results (ml): + +double reference = 25.00; // 'True' result. +const int values = 6; // titrations. +double data [values] = {25.06, 25.18, 24.87, 25.51, 25.34, 25.41}; + +int main() +{ + cout << "Example2 using Student's t function. "; +#if defined(__FILE__) && defined(__TIMESTAMP__) && defined(_MSC_FULL_VER) + cout << " " << __FILE__ << ' ' << __TIMESTAMP__ << ' '<< _MSC_FULL_VER; +#endif + cout << endl; + + double sum = 0.; + for (int value = 0; value < values; value++) + { // Echo data and calculate mean. + sum += data[value]; + cout << setw(4) << value << ' ' << setw(14) << data[value] << endl; + } + double mean = sum /static_cast<double>(values); + cout << "Mean = " << mean << endl; // 25.2283 + + double sd = 0.; + for (int value = 0; value < values; value++) + { // Calculate standard deviation. + sd +=(data[value] - mean) * (data[value] - mean); + } + int degrees_of_freedom = values - 1; // Use the n-1 formula. + sd /= degrees_of_freedom; // == variance. + sd= sqrt(sd); + cout << "Standard deviation = " << sd<< endl; // = 0.238279 + + double t = (mean - reference) * sqrt(static_cast<double>(values))/ sd; // + cout << "Student's t = " << t << ", with " << degrees_of_freedom << " degrees of freedom." << endl; // = 2.34725 + + cout << "Probability of positive bias is " << cdf(students_t(degrees_of_freedom), t) << "."<< endl; // = 0.967108. + // A 1-sided test because only testing for a positive bias. + // If > 0.95 then greater than 1 in 20 conventional (arbitrary) requirement. + + return 0; +} // int main() + +/* + +Output is: + +------ Build started: Project: students_t_example2, Configuration: Debug Win32 ------ +Compiling... +students_t_example2.cpp +Linking... +Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\students_t_example2.exe" +Example2 using Student's t function. ..\..\..\..\..\..\boost-sandbox\libs\math_functions\example\students_t_example2.cpp Sat Aug 12 16:55:59 2006 140050727 + 0 25.06 + 1 25.18 + 2 24.87 + 3 25.51 + 4 25.34 + 5 25.41 +Mean = 25.2283 +Standard deviation = 0.238279 +Student's t = 2.34725, with 5 degrees of freedom. +Probability of positive bias is 0.967108. +Build Time 0:03 +Build log was saved at "file://i:\boost-06-05-03-1300\libs\math\test\Math_test\students_t_example2\Debug\BuildLog.htm" +students_t_example2 - 0 error(s), 0 warning(s) +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + +*/ + + + + + diff --git a/src/boost/libs/math/example/students_t_example3.cpp b/src/boost/libs/math/example/students_t_example3.cpp new file mode 100644 index 000000000..289daec09 --- /dev/null +++ b/src/boost/libs/math/example/students_t_example3.cpp @@ -0,0 +1,120 @@ +// students_t_example3.cpp +// Copyright Paul A. Bristow 2006, 2007. + +// 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) + +// Example 3 of using Student's t. + +// A general guide to Student's t is at +// http://en.wikipedia.org/wiki/Student's_t-test +// (and many other elementary and advanced statistics texts). +// It says: +// The t statistic was invented by William Sealy Gosset +// for cheaply monitoring the quality of beer brews. +// "Student" was his pen name. +// Gosset was statistician for Guinness brewery in Dublin, Ireland, +// hired due to Claude Guinness's innovative policy of recruiting the +// best graduates from Oxford and Cambridge for applying biochemistry +// and statistics to Guinness's industrial processes. +// Gosset published the t test in Biometrika in 1908, +// but was forced to use a pen name by his employer who regarded the fact +// that they were using statistics as a trade secret. +// In fact, Gosset's identity was unknown not only to fellow statisticians +// but to his employer - the company insisted on the pseudonym +// so that it could turn a blind eye to the breach of its rules. + +// The Students't distribution function is described at +// http://en.wikipedia.org/wiki/Student%27s_t_distribution + +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; // Probability of students_t(df, t). + +#include <iostream> + using std::cout; using std::endl; +#include <iomanip> + using std::setprecision; using std::setw; +#include <cmath> + using std::sqrt; + +// This example of a two-sided test is from: +// B. M. Smith & M. B. Griffiths, Analyst, 1982, 107, 253, +// from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 58-59 +// J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907 + +// Concentrations of lead (ug/l) determined by two different methods +// for each of four test portions, +// the concentration of each portion is significantly different, +// the values may NOT be pooled. +// (Called a 'paired test' by Miller and Miller +// because each portion analysed has a different concentration.) + +// Portion Wet oxidation Direct Extraction +// 1 71 76 +// 2 61 68 +// 3 50 48 +// 4 60 57 + +const int portions = 4; +const int methods = 2; +float data [portions][methods] = {{71, 76}, {61,68}, {50, 48}, {60, 57}}; +float diffs[portions]; + +int main() +{ + cout << "Example3 using Student's t function. " << endl; + float mean_diff = 0.f; + cout << "\n""Portion wet_oxidation Direct_extraction difference" << endl; + for (int portion = 0; portion < portions; portion++) + { // Echo data and differences. + diffs[portion] = data[portion][0] - data[portion][1]; + mean_diff += diffs[portion]; + cout << setw(4) << portion << ' ' << setw(14) << data[portion][0] << ' ' << setw(18)<< data[portion][1] << ' ' << setw(9) << diffs[portion] << endl; + } + mean_diff /= portions; + cout << "Mean difference = " << mean_diff << endl; // -1.75 + + float sd_diffs = 0.f; + for (int portion = 0; portion < portions; portion++) + { // Calculate standard deviation of differences. + sd_diffs +=(diffs[portion] - mean_diff) * (diffs[portion] - mean_diff); + } + int degrees_of_freedom = portions-1; // Use the n-1 formula. + sd_diffs /= degrees_of_freedom; + sd_diffs = sqrt(sd_diffs); + cout << "Standard deviation of differences = " << sd_diffs << endl; // 4.99166 + // Standard deviation of differences = 4.99166 + double t = mean_diff * sqrt(static_cast<double>(portions))/ sd_diffs; // -0.70117 + cout << "Student's t = " << t << ", if " << degrees_of_freedom << " degrees of freedom." << endl; + // Student's t = -0.70117, if 3 degrees of freedom. + cout << "Probability of the means being different is " + << 2.F * cdf(students_t(degrees_of_freedom), t) << "."<< endl; // 0.266846 * 2 = 0.533692 + // Double the probability because using a 'two-sided test' because + // mean for 'Wet oxidation' could be either + // greater OR LESS THAN for 'Direct extraction'. + + return 0; +} // int main() + +/* + +Output is: + +Example3 using Student's t function. +Portion wet_oxidation Direct_extraction difference + 0 71 76 -5 + 1 61 68 -7 + 2 50 48 2 + 3 60 57 3 +Mean difference = -1.75 +Standard deviation of differences = 4.99166 +Student's t = -0.70117, if 3 degrees of freedom. +Probability of the means being different is 0.533692. + +*/ + + + + diff --git a/src/boost/libs/math/example/students_t_single_sample.cpp b/src/boost/libs/math/example/students_t_single_sample.cpp new file mode 100644 index 000000000..591466ae5 --- /dev/null +++ b/src/boost/libs/math/example/students_t_single_sample.cpp @@ -0,0 +1,424 @@ +// Copyright John Maddock 2006 +// Copyright Paul A. Bristow 2007, 2010 + +// 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) + +#ifdef _MSC_VER +# pragma warning(disable: 4512) // assignment operator could not be generated. +# pragma warning(disable: 4510) // default constructor could not be generated. +# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required. +#endif + +#include <boost/math/distributions/students_t.hpp> + +// avoid "using namespace std;" and "using namespace boost::math;" +// to avoid potential ambiguity with names in std random. +#include <iostream> +using std::cout; using std::endl; +using std::left; using std::fixed; using std::right; using std::scientific; +#include <iomanip> +using std::setw; +using std::setprecision; + +void confidence_limits_on_mean(double Sm, double Sd, unsigned Sn) +{ + // + // Sm = Sample Mean. + // Sd = Sample Standard Deviation. + // Sn = Sample Size. + // + // Calculate confidence intervals for the mean. + // For example if we set the confidence limit to + // 0.95, we know that if we repeat the sampling + // 100 times, then we expect that the true mean + // will be between out limits on 95 occasions. + // Note: this is not the same as saying a 95% + // confidence interval means that there is a 95% + // probability that the interval contains the true mean. + // The interval computed from a given sample either + // contains the true mean or it does not. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda352.htm + + using boost::math::students_t; + + // Print out general info: + cout << + "__________________________________\n" + "2-Sided Confidence Limits For Mean\n" + "__________________________________\n\n"; + cout << setprecision(7); + cout << setw(40) << left << "Number of Observations" << "= " << Sn << "\n"; + cout << setw(40) << left << "Mean" << "= " << Sm << "\n"; + cout << setw(40) << left << "Standard Deviation" << "= " << Sd << "\n"; + // + // Define a table of significance/risk levels: + // + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Start by declaring the distribution we'll need: + // + students_t dist(Sn - 1); + // + // Print table header: + // + cout << "\n\n" + "_______________________________________________________________\n" + "Confidence T Interval Lower Upper\n" + " Value (%) Value Width Limit Limit\n" + "_______________________________________________________________\n"; + // + // Now print out the data for the table rows. + // + for(unsigned i = 0; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // calculate T: + double T = quantile(complement(dist, alpha[i] / 2)); + // Print T: + cout << fixed << setprecision(3) << setw(10) << right << T; + // Calculate width of interval (one sided): + double w = T * Sd / sqrt(double(Sn)); + // Print width: + if(w < 0.01) + cout << scientific << setprecision(3) << setw(17) << right << w; + else + cout << fixed << setprecision(3) << setw(17) << right << w; + // Print Limits: + cout << fixed << setprecision(5) << setw(15) << right << Sm - w; + cout << fixed << setprecision(5) << setw(15) << right << Sm + w << endl; + } + cout << endl; +} // void confidence_limits_on_mean + +void single_sample_t_test(double M, double Sm, double Sd, unsigned Sn, double alpha) +{ + // + // M = true mean. + // Sm = Sample Mean. + // Sd = Sample Standard Deviation. + // Sn = Sample Size. + // alpha = Significance Level. + // + // A Students t test applied to a single set of data. + // We are testing the null hypothesis that the true + // mean of the sample is M, and that any variation is down + // to chance. We can also test the alternative hypothesis + // that any difference is not down to chance. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda352.htm + + using boost::math::students_t; + + // Print header: + cout << + "__________________________________\n" + "Student t test for a single sample\n" + "__________________________________\n\n"; + cout << setprecision(5); + cout << setw(55) << left << "Number of Observations" << "= " << Sn << "\n"; + cout << setw(55) << left << "Sample Mean" << "= " << Sm << "\n"; + cout << setw(55) << left << "Sample Standard Deviation" << "= " << Sd << "\n"; + cout << setw(55) << left << "Expected True Mean" << "= " << M << "\n\n"; + // + // Now we can calculate and output some stats: + // + // Difference in means: + double diff = Sm - M; + cout << setw(55) << left << "Sample Mean - Expected Test Mean" << "= " << diff << "\n"; + // Degrees of freedom: + unsigned v = Sn - 1; + cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n"; + // t-statistic: + double t_stat = diff * sqrt(double(Sn)) / Sd; + cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n"; + // + // Finally define our distribution, and get the probability: + // + students_t dist(v); + double q = cdf(complement(dist, fabs(t_stat))); + cout << setw(55) << left << "Probability that difference is due to chance" << "= " + << setprecision(3) << scientific << 2 * q << "\n\n"; + // + // Finally print out results of alternative hypothesis: + // + cout << setw(55) << left << + "Results for Alternative Hypothesis and alpha" << "= " + << setprecision(4) << fixed << alpha << "\n\n"; + cout << "Alternative Hypothesis Conclusion\n"; + cout << "Mean != " << setprecision(3) << fixed << M << " "; + if(q < alpha / 2) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Mean < " << setprecision(3) << fixed << M << " "; + if(cdf(complement(dist, t_stat)) > alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Mean > " << setprecision(3) << fixed << M << " "; + if(cdf(dist, t_stat) > alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << endl << endl; +} // void single_sample_t_test( + +void single_sample_find_df(double M, double Sm, double Sd) +{ + // + // M = true mean. + // Sm = Sample Mean. + // Sd = Sample Standard Deviation. + // + + using boost::math::students_t; + + // Print out general info: + cout << + "_____________________________________________________________\n" + "Estimated sample sizes required for various confidence levels\n" + "_____________________________________________________________\n\n"; + cout << setprecision(5); + cout << setw(40) << left << "True Mean" << "= " << M << "\n"; + cout << setw(40) << left << "Sample Mean" << "= " << Sm << "\n"; + cout << setw(40) << left << "Sample Standard Deviation" << "= " << Sd << "\n"; + // + // Define a table of significance intervals: + // + double alpha[] = { 0.5, 0.25, 0.1, 0.05, 0.01, 0.001, 0.0001, 0.00001 }; + // + // Print table header: + // + cout << "\n\n" + "_______________________________________________________________\n" + "Confidence Estimated Estimated\n" + " Value (%) Sample Size Sample Size\n" + " (one sided test) (two sided test)\n" + "_______________________________________________________________\n"; + // + // Now print out the data for the table rows. + // + for(unsigned i = 1; i < sizeof(alpha)/sizeof(alpha[0]); ++i) + { + // Confidence value: + cout << fixed << setprecision(3) << setw(10) << right << 100 * (1-alpha[i]); + // calculate df for single sided test: + double df = students_t::find_degrees_of_freedom( + fabs(M - Sm), alpha[i], alpha[i], Sd); + // convert to sample size, always one more than the degrees of freedom: + double size = ceil(df) + 1; + // Print size: + cout << fixed << setprecision(0) << setw(16) << right << size; + // calculate df for two sided test: + df = students_t::find_degrees_of_freedom( + fabs(M - Sm), alpha[i]/2, alpha[i], Sd); + // convert to sample size: + size = ceil(df) + 1; + // Print size: + cout << fixed << setprecision(0) << setw(16) << right << size << endl; + } + cout << endl; +} // void single_sample_find_df + +int main() +{ + // + // Run tests for Heat Flow Meter data + // see http://www.itl.nist.gov/div898/handbook/eda/section4/eda428.htm + // The data was collected while calibrating a heat flow meter + // against a known value. + // + confidence_limits_on_mean(9.261460, 0.2278881e-01, 195); + single_sample_t_test(5, 9.261460, 0.2278881e-01, 195, 0.05); + single_sample_find_df(5, 9.261460, 0.2278881e-01); + + // + // Data for this example from: + // P.K.Hou, O. W. Lau & M.C. Wong, Analyst (1983) vol. 108, p 64. + // from Statistics for Analytical Chemistry, 3rd ed. (1994), pp 54-55 + // J. C. Miller and J. N. Miller, Ellis Horwood ISBN 0 13 0309907 + // + // Determination of mercury by cold-vapour atomic absorption, + // the following values were obtained fusing a trusted + // Standard Reference Material containing 38.9% mercury, + // which we assume is correct or 'true'. + // + confidence_limits_on_mean(37.8, 0.964365, 3); + // 95% test: + single_sample_t_test(38.9, 37.8, 0.964365, 3, 0.05); + // 90% test: + single_sample_t_test(38.9, 37.8, 0.964365, 3, 0.1); + // parameter estimate: + single_sample_find_df(38.9, 37.8, 0.964365); + + return 0; +} // int main() + +/* + +Output: + +------ Rebuild All started: Project: students_t_single_sample, Configuration: Release Win32 ------ + students_t_single_sample.cpp + Generating code + Finished generating code + students_t_single_sample.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\students_t_single_sample.exe +__________________________________ +2-Sided Confidence Limits For Mean +__________________________________ + +Number of Observations = 195 +Mean = 9.26146 +Standard Deviation = 0.02278881 + + +_______________________________________________________________ +Confidence T Interval Lower Upper + Value (%) Value Width Limit Limit +_______________________________________________________________ + 50.000 0.676 1.103e-003 9.26036 9.26256 + 75.000 1.154 1.883e-003 9.25958 9.26334 + 90.000 1.653 2.697e-003 9.25876 9.26416 + 95.000 1.972 3.219e-003 9.25824 9.26468 + 99.000 2.601 4.245e-003 9.25721 9.26571 + 99.900 3.341 5.453e-003 9.25601 9.26691 + 99.990 3.973 6.484e-003 9.25498 9.26794 + 99.999 4.537 7.404e-003 9.25406 9.26886 + +__________________________________ +Student t test for a single sample +__________________________________ + +Number of Observations = 195 +Sample Mean = 9.26146 +Sample Standard Deviation = 0.02279 +Expected True Mean = 5.00000 + +Sample Mean - Expected Test Mean = 4.26146 +Degrees of Freedom = 194 +T Statistic = 2611.28380 +Probability that difference is due to chance = 0.000e+000 + +Results for Alternative Hypothesis and alpha = 0.0500 + +Alternative Hypothesis Conclusion +Mean != 5.000 NOT REJECTED +Mean < 5.000 REJECTED +Mean > 5.000 NOT REJECTED + + +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ + +True Mean = 5.00000 +Sample Mean = 9.26146 +Sample Standard Deviation = 0.02279 + + +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (one sided test) (two sided test) +_______________________________________________________________ + 75.000 2 2 + 90.000 2 2 + 95.000 2 2 + 99.000 2 2 + 99.900 3 3 + 99.990 3 3 + 99.999 4 4 + +__________________________________ +2-Sided Confidence Limits For Mean +__________________________________ + +Number of Observations = 3 +Mean = 37.8000000 +Standard Deviation = 0.9643650 + + +_______________________________________________________________ +Confidence T Interval Lower Upper + Value (%) Value Width Limit Limit +_______________________________________________________________ + 50.000 0.816 0.455 37.34539 38.25461 + 75.000 1.604 0.893 36.90717 38.69283 + 90.000 2.920 1.626 36.17422 39.42578 + 95.000 4.303 2.396 35.40438 40.19562 + 99.000 9.925 5.526 32.27408 43.32592 + 99.900 31.599 17.594 20.20639 55.39361 + 99.990 99.992 55.673 -17.87346 93.47346 + 99.999 316.225 176.067 -138.26683 213.86683 + +__________________________________ +Student t test for a single sample +__________________________________ + +Number of Observations = 3 +Sample Mean = 37.80000 +Sample Standard Deviation = 0.96437 +Expected True Mean = 38.90000 + +Sample Mean - Expected Test Mean = -1.10000 +Degrees of Freedom = 2 +T Statistic = -1.97566 +Probability that difference is due to chance = 1.869e-001 + +Results for Alternative Hypothesis and alpha = 0.0500 + +Alternative Hypothesis Conclusion +Mean != 38.900 REJECTED +Mean < 38.900 NOT REJECTED +Mean > 38.900 NOT REJECTED + + +__________________________________ +Student t test for a single sample +__________________________________ + +Number of Observations = 3 +Sample Mean = 37.80000 +Sample Standard Deviation = 0.96437 +Expected True Mean = 38.90000 + +Sample Mean - Expected Test Mean = -1.10000 +Degrees of Freedom = 2 +T Statistic = -1.97566 +Probability that difference is due to chance = 1.869e-001 + +Results for Alternative Hypothesis and alpha = 0.1000 + +Alternative Hypothesis Conclusion +Mean != 38.900 REJECTED +Mean < 38.900 NOT REJECTED +Mean > 38.900 REJECTED + + +_____________________________________________________________ +Estimated sample sizes required for various confidence levels +_____________________________________________________________ + +True Mean = 38.90000 +Sample Mean = 37.80000 +Sample Standard Deviation = 0.96437 + + +_______________________________________________________________ +Confidence Estimated Estimated + Value (%) Sample Size Sample Size + (one sided test) (two sided test) +_______________________________________________________________ + 75.000 3 4 + 90.000 7 9 + 95.000 11 13 + 99.000 20 22 + 99.900 35 37 + 99.990 50 53 + 99.999 66 68 + +*/ + diff --git a/src/boost/libs/math/example/students_t_two_samples.cpp b/src/boost/libs/math/example/students_t_two_samples.cpp new file mode 100644 index 000000000..66a9e7036 --- /dev/null +++ b/src/boost/libs/math/example/students_t_two_samples.cpp @@ -0,0 +1,245 @@ +// Copyright John Maddock 2006. +// Copyright Paul A. Bristow 2007, 2010 + +// 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) + +#ifdef _MSC_VER +# pragma warning(disable: 4512) // assignment operator could not be generated. +# pragma warning(disable: 4510) // default constructor could not be generated. +# pragma warning(disable: 4610) // can never be instantiated - user defined constructor required. +#endif + +#include <iostream> +using std::cout; using std::endl; +using std::left; using std::fixed; using std::right; using std::scientific; +#include <iomanip> +using std::setw; +using std::setprecision; + +#include <boost/math/distributions/students_t.hpp> + using boost::math::students_t; + + +void two_samples_t_test_equal_sd( + double Sm1, // Sm1 = Sample Mean 1. + double Sd1, // Sd1 = Sample Standard Deviation 1. + unsigned Sn1, // Sn1 = Sample Size 1. + double Sm2, // Sm2 = Sample Mean 2. + double Sd2, // Sd2 = Sample Standard Deviation 2. + unsigned Sn2, // Sn2 = Sample Size 2. + double alpha) // alpha = Significance Level. +{ + // A Students t test applied to two sets of data. + // We are testing the null hypothesis that the two + // samples have the same mean and that any difference + // if due to chance. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda353.htm + // + using namespace std; + // using namespace boost::math; + + using boost::math::students_t; + + // Print header: + cout << + "_______________________________________________\n" + "Student t test for two samples (equal variances)\n" + "_______________________________________________\n\n"; + cout << setprecision(5); + cout << setw(55) << left << "Number of Observations (Sample 1)" << "= " << Sn1 << "\n"; + cout << setw(55) << left << "Sample 1 Mean" << "= " << Sm1 << "\n"; + cout << setw(55) << left << "Sample 1 Standard Deviation" << "= " << Sd1 << "\n"; + cout << setw(55) << left << "Number of Observations (Sample 2)" << "= " << Sn2 << "\n"; + cout << setw(55) << left << "Sample 2 Mean" << "= " << Sm2 << "\n"; + cout << setw(55) << left << "Sample 2 Standard Deviation" << "= " << Sd2 << "\n"; + // + // Now we can calculate and output some stats: + // + // Degrees of freedom: + double v = Sn1 + Sn2 - 2; + cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n"; + // Pooled variance and hence standard deviation: + double sp = sqrt(((Sn1-1) * Sd1 * Sd1 + (Sn2-1) * Sd2 * Sd2) / v); + cout << setw(55) << left << "Pooled Standard Deviation" << "= " << sp << "\n"; + // t-statistic: + double t_stat = (Sm1 - Sm2) / (sp * sqrt(1.0 / Sn1 + 1.0 / Sn2)); + cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n"; + // + // Define our distribution, and get the probability: + // + students_t dist(v); + double q = cdf(complement(dist, fabs(t_stat))); + cout << setw(55) << left << "Probability that difference is due to chance" << "= " + << setprecision(3) << scientific << 2 * q << "\n\n"; + // + // Finally print out results of alternative hypothesis: + // + cout << setw(55) << left << + "Results for Alternative Hypothesis and alpha" << "= " + << setprecision(4) << fixed << alpha << "\n\n"; + cout << "Alternative Hypothesis Conclusion\n"; + cout << "Sample 1 Mean != Sample 2 Mean " ; + if(q < alpha / 2) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Sample 1 Mean < Sample 2 Mean "; + if(cdf(dist, t_stat) < alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Sample 1 Mean > Sample 2 Mean "; + if(cdf(complement(dist, t_stat)) < alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << endl << endl; +} + +void two_samples_t_test_unequal_sd( + double Sm1, // Sm1 = Sample Mean 1. + double Sd1, // Sd1 = Sample Standard Deviation 1. + unsigned Sn1, // Sn1 = Sample Size 1. + double Sm2, // Sm2 = Sample Mean 2. + double Sd2, // Sd2 = Sample Standard Deviation 2. + unsigned Sn2, // Sn2 = Sample Size 2. + double alpha) // alpha = Significance Level. +{ + // A Students t test applied to two sets of data. + // We are testing the null hypothesis that the two + // samples have the same mean and + // that any difference is due to chance. + // See http://www.itl.nist.gov/div898/handbook/eda/section3/eda353.htm + // + using namespace std; + using boost::math::students_t; + + // Print header: + cout << + "_________________________________________________\n" + "Student t test for two samples (unequal variances)\n" + "_________________________________________________\n\n"; + cout << setprecision(5); + cout << setw(55) << left << "Number of Observations (Sample 1)" << "= " << Sn1 << "\n"; + cout << setw(55) << left << "Sample 1 Mean" << "= " << Sm1 << "\n"; + cout << setw(55) << left << "Sample 1 Standard Deviation" << "= " << Sd1 << "\n"; + cout << setw(55) << left << "Number of Observations (Sample 2)" << "= " << Sn2 << "\n"; + cout << setw(55) << left << "Sample 2 Mean" << "= " << Sm2 << "\n"; + cout << setw(55) << left << "Sample 2 Standard Deviation" << "= " << Sd2 << "\n"; + // + // Now we can calculate and output some stats: + // + // Degrees of freedom: + double v = Sd1 * Sd1 / Sn1 + Sd2 * Sd2 / Sn2; + v *= v; + double t1 = Sd1 * Sd1 / Sn1; + t1 *= t1; + t1 /= (Sn1 - 1); + double t2 = Sd2 * Sd2 / Sn2; + t2 *= t2; + t2 /= (Sn2 - 1); + v /= (t1 + t2); + cout << setw(55) << left << "Degrees of Freedom" << "= " << v << "\n"; + // t-statistic: + double t_stat = (Sm1 - Sm2) / sqrt(Sd1 * Sd1 / Sn1 + Sd2 * Sd2 / Sn2); + cout << setw(55) << left << "T Statistic" << "= " << t_stat << "\n"; + // + // Define our distribution, and get the probability: + // + students_t dist(v); + double q = cdf(complement(dist, fabs(t_stat))); + cout << setw(55) << left << "Probability that difference is due to chance" << "= " + << setprecision(3) << scientific << 2 * q << "\n\n"; + // + // Finally print out results of alternative hypothesis: + // + cout << setw(55) << left << + "Results for Alternative Hypothesis and alpha" << "= " + << setprecision(4) << fixed << alpha << "\n\n"; + cout << "Alternative Hypothesis Conclusion\n"; + cout << "Sample 1 Mean != Sample 2 Mean " ; + if(q < alpha / 2) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Sample 1 Mean < Sample 2 Mean "; + if(cdf(dist, t_stat) < alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << "Sample 1 Mean > Sample 2 Mean "; + if(cdf(complement(dist, t_stat)) < alpha) + cout << "NOT REJECTED\n"; + else + cout << "REJECTED\n"; + cout << endl << endl; +} + +int main() +{ + // + // Run tests for Car Mileage sample data + // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3531.htm + // from the NIST website http://www.itl.nist.gov. The data compares + // miles per gallon of US cars with miles per gallon of Japanese cars. + // + two_samples_t_test_equal_sd(20.14458, 6.414700, 249, 30.48101, 6.107710, 79, 0.05); + two_samples_t_test_unequal_sd(20.14458, 6.414700, 249, 30.48101, 6.107710, 79, 0.05); + + return 0; +} // int main() + +/* +Output is: + + _______________________________________________ + Student t test for two samples (equal variances) + _______________________________________________ + + Number of Observations (Sample 1) = 249 + Sample 1 Mean = 20.145 + Sample 1 Standard Deviation = 6.4147 + Number of Observations (Sample 2) = 79 + Sample 2 Mean = 30.481 + Sample 2 Standard Deviation = 6.1077 + Degrees of Freedom = 326 + Pooled Standard Deviation = 6.3426 + T Statistic = -12.621 + Probability that difference is due to chance = 5.273e-030 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Sample 1 Mean != Sample 2 Mean NOT REJECTED + Sample 1 Mean < Sample 2 Mean NOT REJECTED + Sample 1 Mean > Sample 2 Mean REJECTED + + + _________________________________________________ + Student t test for two samples (unequal variances) + _________________________________________________ + + Number of Observations (Sample 1) = 249 + Sample 1 Mean = 20.14458 + Sample 1 Standard Deviation = 6.41470 + Number of Observations (Sample 2) = 79 + Sample 2 Mean = 30.48101 + Sample 2 Standard Deviation = 6.10771 + Degrees of Freedom = 136.87499 + T Statistic = -12.94627 + Probability that difference is due to chance = 1.571e-025 + + Results for Alternative Hypothesis and alpha = 0.0500 + + Alternative Hypothesis Conclusion + Sample 1 Mean != Sample 2 Mean NOT REJECTED + Sample 1 Mean < Sample 2 Mean NOT REJECTED + Sample 1 Mean > Sample 2 Mean REJECTED + + + +*/ + diff --git a/src/boost/libs/math/example/table_type.hpp b/src/boost/libs/math/example/table_type.hpp new file mode 100644 index 000000000..b8f16cfdf --- /dev/null +++ b/src/boost/libs/math/example/table_type.hpp @@ -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 diff --git a/src/boost/libs/math/example/test_cpp_float_close_fraction.cpp b/src/boost/libs/math/example/test_cpp_float_close_fraction.cpp new file mode 100644 index 000000000..b4699fad8 --- /dev/null +++ b/src/boost/libs/math/example/test_cpp_float_close_fraction.cpp @@ -0,0 +1,119 @@ +// 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) + +// Copyright Paul A. Bristow 2013 +// Copyright Christopher Kormanyos 2013. +// Copyright John Maddock 2013. + +#ifdef _MSC_VER +# pragma warning (disable : 4512) +# pragma warning (disable : 4996) +#endif + +#define BOOST_TEST_MAIN +#define BOOST_LIB_DIAGNOSTIC "on"// Show library file details. + +#include <boost/test/unit_test.hpp> +#include <boost/test/tools/floating_point_comparison.hpp> // Extra test tool for FP comparison. + +#include <iostream> +#include <limits> + +//[expression_template_1 + +#include <boost/multiprecision/cpp_dec_float.hpp> + +/*`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: + +`` +typedef boost::multiprecision::cpp_dec_float<50> mp_backend; +typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> cpp_dec_float_50_noet; +`` + +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> + cpp_dec_float_50_noet; + +You can reduce typing with a `using` directive `using namespace boost::multiprecision;` +if desired, as shown below. +*/ + +using namespace boost::multiprecision; + + +/*`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.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(); + + 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). + + + +} // 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) + +/* + +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 + + +*/ + diff --git a/src/boost/libs/math/example/test_nonfinite_loopback.cpp b/src/boost/libs/math/example/test_nonfinite_loopback.cpp new file mode 100644 index 000000000..c7b8e4204 --- /dev/null +++ b/src/boost/libs/math/example/test_nonfinite_loopback.cpp @@ -0,0 +1,97 @@ +// 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) + +// Copyright (c) 2006 Johan Rade +// Copyright (c) 2011 Paul A. Bristow + +/*! +\file +\brief Basic tests of native nonfinite loopback. + +\detail Basic loopback test outputs using the platforms built-in facets +and reads back in, and checks if loopback OK. + +Using MSVC this doesn't work OK: +input produces just "1" instead of "1.#QNAN", 1.#SNAN" or 1.#IND"! + +*/ + +#include <iostream> +using std::cout; +using std::endl; +#include <locale> +using std::locale; +#include <string> +using std::string; +#include <sstream> + using std::stringstream; +#include <limits> +using std::numeric_limits; + +int main() +{ + locale default_locale; // Current global locale. + // Try to use the default locale first. + // On MSVC this doesn't work. + + { // Try infinity. + stringstream ss; // Both input and output. + ss.imbue(default_locale); // Redundant, of course. + string infs; + if(numeric_limits<double>::has_infinity) + { // Make sure infinity is specialised for type double. + double inf = numeric_limits<double>::infinity(); + ss << inf; // Output infinity. + infs = ss.str(); // + } + else + { // Need to provide a suitable string for infinity. + infs = "1.#INF"; // Might suit MSVC? + ss << infs; + } + double r; + ss >> r; // Read back in. + + cout << "infinity output was " << infs << endl; // "1.#INF" + cout << "infinity input was " << r << endl; // "1" + } + + { // Try Quiet NaN + stringstream ss; // Both input and output. + ss.imbue(default_locale); // Redundant, of course. + string infs; + if(numeric_limits<double>::has_quiet_NaN) + { // Make sure quiet NaN is specialised for type double. + double qnan = numeric_limits<double>::quiet_NaN(); + ss << qnan; // Output quiet_NaN. + infs = ss.str(); // + } + else + { // Need to provide a suitable string for quiet_NAN. + infs = "1.#QNAN"; + ss << infs; + } + double r; + ss >> r; // Read back in. + + cout << "quiet_NaN output was " << infs << endl; // "1.#QNAN" + cout << "quiet_NaN input was " << r << endl; // "1#" + } + + +} // int main() + +/* + +Output (MSVC Version 10.0): + + + infinity output was 1.#INF + infinity input was 1 + quiet_NaN output was 1.#QNAN + quiet_NaN input was 1 + + +*/ + diff --git a/src/boost/libs/math/example/to_continued_fraction.cpp b/src/boost/libs/math/example/to_continued_fraction.cpp new file mode 100644 index 000000000..4eaa83050 --- /dev/null +++ b/src/boost/libs/math/example/to_continued_fraction.cpp @@ -0,0 +1,41 @@ +// (C) Copyright Nick Thompson 2020. +// 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) +// +// Deliberately contains some unicode characters: +// +// boost-no-inspect +// +#include <iostream> +#include <boost/math/constants/constants.hpp> +#include <boost/math/tools/simple_continued_fraction.hpp> +#include <boost/multiprecision/cpp_bin_float.hpp> + +using boost::math::constants::root_two; +using boost::math::constants::phi; +using boost::math::constants::pi; +using boost::math::constants::e; +using boost::math::constants::zeta_three; +using boost::math::tools::simple_continued_fraction; + +int main() +{ + using Real = boost::multiprecision::cpp_bin_float_100; + auto phi_cfrac = simple_continued_fraction(phi<Real>()); + std::cout << "φ ≈ " << phi_cfrac << "\n\n"; + + auto pi_cfrac = simple_continued_fraction(pi<Real>()); + std::cout << "Ï€ ≈ " << pi_cfrac << "\n"; + std::cout << "Known: [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2, 1, 84, 2, 1, 1, 15, 3, 13, 1, 4, 2, 6, 6, 99, 1, 2, 2, 6, 3, 5, 1, 1, 6, 8, 1, 7, 1, 2, 3, 7, 1, 2, 1, 1, 12, 1, 1, 1, 3, 1, 1, 8, 1, 1, 2, 1, 6, 1, 1, 5, 2, 2, 3, 1, 2, 4, 4, 16, 1, 161, 45, 1, 22, 1, 2, 2, 1, 4, 1, 2, 24, 1, 2, 1, 3, 1, 2, 1, ...]\n\n"; + + auto rt_cfrac = simple_continued_fraction(root_two<Real>()); + std::cout << "√2 ≈ " << rt_cfrac << "\n\n"; + + auto e_cfrac = simple_continued_fraction(e<Real>()); + std::cout << "e ≈ " << e_cfrac << "\n"; + + // Correctness can be checked in Mathematica via: ContinuedFraction[Zeta[3], 500] + auto z_cfrac = simple_continued_fraction(zeta_three<Real>()); + std::cout << "ζ(3) ≈ " << z_cfrac << "\n"; +} diff --git a/src/boost/libs/math/example/trapezoidal_example.cpp b/src/boost/libs/math/example/trapezoidal_example.cpp new file mode 100644 index 000000000..bbea64152 --- /dev/null +++ b/src/boost/libs/math/example/trapezoidal_example.cpp @@ -0,0 +1,29 @@ +/* + * Copyright Nick Thompson, 2017 + * 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) + * + * This example shows to to numerically integrate a periodic function using the adaptive_trapezoidal routine provided by boost. + */ + +#include <iostream> +#include <cmath> +#include <limits> +#include <boost/math/quadrature/trapezoidal.hpp> + +int main() +{ + using boost::math::constants::two_pi; + using boost::math::constants::third; + using boost::math::quadrature::trapezoidal; + // This function has an analytic form for its integral over a period: 2pi/3. + auto f = [](double x) { return 1/(5 - 4*cos(x)); }; + + double Q = trapezoidal(f, (double) 0, two_pi<double>()); + + std::cout << std::setprecision(std::numeric_limits<double>::digits10); + std::cout << "The adaptive trapezoidal rule gives the integral of our function as " << Q << "\n"; + std::cout << "The exact result is " << two_pi<double>()*third<double>() << "\n"; + +} |