LIBINT 2.9.0
numeric.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint library.
5 *
6 * Libint library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with Libint library. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef _libint2_include_numeric_h_
22#define _libint2_include_numeric_h_
23
24#include <libint2/config.h>
25
26#include <cmath>
27#include <iomanip>
28#include <limits>
29#include <sstream>
30#include <type_traits>
31
32#if LIBINT_HAS_MPFR
33#include <gmpxx.h>
34#include <mpfr.h>
35
36#include <cstddef>
37#endif
38
39#include <libint2/util/generated/libint2_params.h>
40#include <libint2/util/type_traits.h>
41
42#if LIBINT_HAS_MPFR
45inline mpf_class exp(mpf_class x) {
46 const auto prec = x.get_prec();
47 mpfr_t x_r;
48 mpfr_init2(x_r, prec);
49 mpfr_set_f(x_r, x.get_mpf_t(), MPFR_RNDN);
50
51 mpfr_t expx_r;
52 mpfr_init2(expx_r, prec);
53 mpfr_exp(expx_r, x_r, MPFR_RNDN);
54
55 mpf_t expx;
56 mpf_init2(expx, prec);
57 mpfr_get_f(expx, expx_r, MPFR_RNDN);
58 mpf_class result(expx, prec);
59
60 mpfr_clear(x_r);
61 mpfr_clear(expx_r);
62 mpf_clear(expx);
63
64 return result;
65}
68inline mpf_class pow(mpf_class x, int a) {
69 const auto prec = x.get_prec();
70 mpf_t x_to_a;
71 mpf_init2(x_to_a, prec);
72 if (a >= 0)
73 mpf_pow_ui(x_to_a, x.get_mpf_t(), (unsigned int)a);
74 else
75 mpf_pow_ui(x_to_a, x.get_mpf_t(), (unsigned int)(-a));
76 mpf_class result(x_to_a, prec);
77 if (a < 0) result = 1.0 / result;
78 mpf_clear(x_to_a);
79 return result;
80}
81#ifndef _MSC_VER
84inline double pow(double x, int a) {
85 return std::pow(x, static_cast<double>(a));
86}
87#endif
90inline mpf_class erf(mpf_class x) {
91 const auto prec = x.get_prec();
92 mpfr_t x_r;
93 mpfr_init2(x_r, prec);
94 mpfr_set_f(x_r, x.get_mpf_t(), MPFR_RNDN);
95
96 mpfr_t erfx_r;
97 mpfr_init2(erfx_r, prec);
98 mpfr_erf(erfx_r, x_r, MPFR_RNDN);
99
100 mpf_t erfx;
101 mpf_init2(erfx, prec);
102 mpfr_get_f(erfx, erfx_r, MPFR_RNDN);
103 mpf_class result(erfx, prec);
104
105 mpfr_clear(x_r);
106 mpfr_clear(erfx_r);
107 mpf_clear(erfx);
108
109 return result;
110}
113inline mpf_class acos(mpf_class x) {
114 const auto prec = x.get_prec();
115 mpfr_t x_r;
116 mpfr_init2(x_r, prec);
117 mpfr_set_f(x_r, x.get_mpf_t(), MPFR_RNDN);
118
119 mpfr_t acosx_r;
120 mpfr_init2(acosx_r, prec);
121 mpfr_acos(acosx_r, x_r, MPFR_RNDN);
122
123 mpf_t acosx;
124 mpf_init2(acosx, prec);
125 mpfr_get_f(acosx, acosx_r, MPFR_RNDN);
126 mpf_class result(acosx, prec);
127
128 mpfr_clear(x_r);
129 mpfr_clear(acosx_r);
130 mpf_clear(acosx);
131
132 return result;
133}
136inline mpf_class log(mpf_class x) {
137 const auto prec = x.get_prec();
138 mpfr_t x_r;
139 mpfr_init2(x_r, prec);
140 mpfr_set_f(x_r, x.get_mpf_t(), MPFR_RNDN);
141
142 mpfr_t logx_r;
143 mpfr_init2(logx_r, prec);
144 mpfr_log(logx_r, x_r, MPFR_RNDN);
145
146 mpf_t logx;
147 mpf_init2(logx, prec);
148 mpfr_get_f(logx, logx_r, MPFR_RNDN);
149 mpf_class result(logx, prec);
150
151 mpfr_clear(x_r);
152 mpfr_clear(logx_r);
153 mpf_clear(logx);
154
155 return result;
156}
157#endif
158
159#ifdef LIBINT_HAS_MPFR
160using LIBINT2_REF_REALTYPE = mpf_class;
161#else
162using LIBINT2_REF_REALTYPE = double;
163#endif
164
165namespace libint2 {
166using value_type = LIBINT2_REALTYPE;
167using scalar_type = libint2::vector_traits<value_type>::scalar_type;
168
169template <typename Real>
170inline Real get_epsilon(const Real& value);
171
172#ifdef LIBINT_HAS_MPFR
173template <>
174inline mpf_class get_epsilon(const mpf_class& value) {
175 const auto nbits = value.get_prec();
176 return pow(mpf_class(2, nbits), -nbits);
177};
178#endif
179
180template <typename Real>
181inline Real get_epsilon(const Real& value) {
182 return std::numeric_limits<Real>::epsilon();
183}
184
185template <typename Real>
186inline int get_max_digits10(const Real& value);
187
188#ifdef LIBINT_HAS_MPFR
189template <>
190inline int get_max_digits10(const mpf_class& value) {
191 const auto nbits = value.get_prec();
192 return std::ceil(nbits * std::log10(2) + 1);
193};
194#endif
195
196template <typename Real>
197inline int get_max_digits10(const Real& value) {
198 return std::numeric_limits<Real>::max_digits10;
199}
200
201template <typename To, typename From>
202typename std::enable_if<!std::is_same<typename std::decay<To>::type,
203 typename std::decay<From>::type>::value,
204 To>::type
205sstream_convert(From&& from) {
206 std::stringstream ss;
207 ss << std::scientific << std::setprecision(get_max_digits10(from)) << from;
208 To to(ss.str().c_str());
209 return to;
210}
211
212template <typename To>
213To sstream_convert(const To& from) {
214 return from;
215}
216
217}; // namespace libint2
218
219#endif // _libint2_include_numeric_h_
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24