File: mathtest.cc

package info (click to toggle)
dune-common 2.11.0-1~exp2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 6,056 kB
  • sloc: cpp: 54,404; python: 4,136; sh: 1,657; makefile: 17
file content (150 lines) | stat: -rw-r--r-- 5,491 bytes parent folder | download | duplicates (2)
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
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception

#include <iomanip>
#include <iostream>
#include <sstream>

#include <dune/common/classname.hh>
#include <dune/common/gmpfield.hh>
#include <dune/common/hybridutilities.hh>
#include <dune/common/indices.hh>
#include <dune/common/math.hh>
#include <dune/common/quadmath.hh>
#include <dune/common/test/testsuite.hh>


using namespace Dune::Hybrid;
using namespace Dune::Indices;
using Dune::TestSuite;

template<class T, T n>
constexpr inline static auto next(std::integral_constant<T, n>)
  -> std::integral_constant<T, n+1>
{
  return {};
}

template<class T, T k>
auto testStaticFactorial (std::integral_constant<T, k> _k = {}) -> TestSuite
{
  TestSuite t;

  std::cout << "test factorial\n{";

  forEach(integralRange(_k), [&](auto _i) {

    const auto value = Dune::factorial(_i);
    const auto control = _i() == 0 ? 1 : _i() * Dune::factorial(_i() - 1);

    t.check( value() == control );

    std::cout<< ' ' << value() << ',';
  });

  std::cout << "};\n\n";

  return t;
}

template<class T, T k>
auto testStaticBinomial (std::integral_constant<T, k> _k = {}) -> TestSuite
{
  TestSuite t;

  std::cout << "test binomial\n";

  forEach(integralRange(_k), [&](auto _i) {
    std::cout << "{";
    forEach(integralRange(next(_i)), [&](auto _j) {

      const auto value = Dune::binomial(_i, _j);
      const auto control = Dune::factorial(_i) / ( Dune::factorial(_j) * Dune::factorial(_i() - _j()) );

      t.check( value() == control );

      std::cout<< ' ' << value() << ',';
    });

    std::cout << "};\n";
  });

  std::cout << "\n";

  return t;
}

template <class T>
struct Digits10
{
  static int value () {
    return std::numeric_limits<T>::digits10;
  }
};

#if HAVE_GMP
template< unsigned int precision >
struct Digits10<Dune::GMPField<precision>>
{
  static int value () {
    return int(precision * std::log10(2));
  }
};
#endif

// check the correct definition of mathematical constants by comparing the
// digits against an explicit value provided as a string constant
template<class T>
auto testMathematicalConstants () -> TestSuite
{
  TestSuite t;

  const auto digits10 = Digits10<T>::value();

  static const std::string e = "2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354";

  {
    std::stringstream e_sstr;
    e_sstr << std::setprecision(digits10+2) << Dune::MathematicalConstants<T>::e();
    std::string e_T = e_sstr.str();

    auto [it1,it2] = std::mismatch(e_T.begin(), e_T.end(), e.begin());
    auto pos = std::distance(e_T.begin(), it1);
    t.check(pos >= digits10);
  }

  static const std::string pi = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989";

  {
    std::stringstream pi_sstr;
    pi_sstr << std::setprecision(digits10+2) << Dune::MathematicalConstants<T>::pi();
    std::string pi_T = pi_sstr.str();

    auto [it1,it2] = std::mismatch(pi_T.begin(), pi_T.end(), pi.begin());
    auto pos = std::distance(pi_T.begin(), it1);
    t.check(pos >= digits10);
  }
  return t;
}

int main(int argc, char** argv)
{
  TestSuite t;

  t.subTest(testStaticFactorial(_5));
  t.subTest(testStaticBinomial(_5));

  t.subTest(testMathematicalConstants<float>());
  t.subTest(testMathematicalConstants<double>());
  t.subTest(testMathematicalConstants<long double>());

#if HAVE_QUADMATH
  t.subTest(testMathematicalConstants<Dune::Float128>());
#endif

#if HAVE_GMP
  t.subTest(testMathematicalConstants<Dune::GMPField<3318>>());
#endif

  return t.exit();
}