summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/math/example/constants_eg1.cpp
blob: 53516145e183a2a2a12e4bf3135cb79531a519b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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]
*/