Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
mpfr_complex.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//mpfr_complex.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//mpfr_complex.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with mpfr_complex.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
27
28
29#ifndef BERTINI_MPFR_COMPLEX_HPP
30#define BERTINI_MPFR_COMPLEX_HPP
31
32
33
34
35
36#include <boost/archive/text_oarchive.hpp>
37#include <boost/archive/text_iarchive.hpp>
38#include <boost/serialization/split_member.hpp>
39
40#include <string>
41#include <assert.h>
42
43
44
46
47
48
49
50#include <boost/multiprecision/mpc.hpp>
51
52namespace bertini{
53
54namespace bmp = boost::multiprecision;
55using bmp::backends::mpc_complex_backend;
56
57#ifdef BMP_EXPRESSION_TEMPLATES
58 using complex_mp = bmp::number<mpc_complex_backend<0>, bmp::et_on >;
59#else
60 using complex_mp = bmp::number<mpc_complex_backend<0>, bmp::et_off >;
61#endif
62
65 return bmp::variable_precision_options::preserve_related_precision;
66 }
67
68
69
70
72 // shamelessly adapted from the documentation for variable precision in Boost.Multiprecision.
73 // see https://www.boost.org/doc/libs/1_82_0/libs/multiprecision/doc/html/boost_multiprecision/tut/variable.html
75 {
76 boost::multiprecision::variable_precision_options saved_options;
77
79 scoped_mpfr_precision_options_this_thread(boost::multiprecision::variable_precision_options opts) : saved_options(real_mp::thread_default_variable_precision_options())
80 {
81 real_mp::thread_default_variable_precision_options(opts);
82 }
83
85 {
86 real_mp::thread_default_variable_precision_options(saved_options);
87 }
88
90 void reset(boost::multiprecision::variable_precision_options opts)
91 {
92 real_mp::thread_default_variable_precision_options(opts);
93 }
94
95 };
96
97
98
101 {
102 boost::multiprecision::variable_precision_options saved_options_all_threads;
103 boost::multiprecision::variable_precision_options saved_options_this_thread;
104
106 scoped_mpfr_precision_options_all_threads(boost::multiprecision::variable_precision_options opts) :
107 saved_options_all_threads(real_mp::default_variable_precision_options()),
108 saved_options_this_thread(real_mp::default_variable_precision_options())
109 {
110 real_mp::default_variable_precision_options(opts);
111 real_mp::thread_default_variable_precision_options(opts);
112 }
113
115 {
116 real_mp::default_variable_precision_options(saved_options_all_threads);
117 real_mp::thread_default_variable_precision_options(saved_options_this_thread);
118 }
119
121 void reset(boost::multiprecision::variable_precision_options opts)
122 {
123 real_mp::default_variable_precision_options(opts);
124 real_mp::thread_default_variable_precision_options(opts);
125 }
126
127 };
128
129
130
131
132
133
135 inline auto DefaultPrecision()
136 {
137 auto p = real_mp::default_precision();
138 assert(p==complex_mp::default_precision() && "precision of real and complex multiprecision numbers have drifted...");
139 return p;
140 }
141
143 inline void DefaultPrecision(unsigned prec)
144 {
145 real_mp::default_precision(prec);
146 complex_mp::default_precision(prec);
147 // Boost.Multiprecision >= 1.87 reads thread_default_precision when
148 // default-constructing mpfr temporaries (including those created by
149 // boost::python const& extractors). If left at 0, mpfr_init2 aborts.
150 // Set both so that calls to default_precision() align thread-local
151 // with the static default. See commit 3111255b for original context.
152 real_mp::thread_default_precision(prec);
153 complex_mp::thread_default_precision(prec);
154#ifdef BMP_EXPRESSION_TEMPLATES
155 // With ET on, the default global policy for mpc_complex_backend is preserve_related_precision
156 // and for mpfr_float_backend it is preserve_target_precision. Both differ from what we want.
157 // Setting preserve_related_precision per-thread mirrors the mpc_complex_backend global default
158 // and ensures copy/construction semantics match the et_off behavior. Specifically:
159 // - mpc_complex copy ctor uses preserve_related_precision() (>= 3) to preserve source precision
160 // - assign_components_set_precision uses preserve_component_precision() (>= 2) to resize
161 // a complex from real components at higher-than-default precision
162 // - mpc_complex = real_mp uses preserve_component_precision() (>= 2) to resize
163 // preserve_related_precision satisfies all three thresholds.
164 // For real_mp, preserve_related_precision also enables source-precision-preserving copies.
165 real_mp::thread_default_variable_precision_options(
166 bmp::variable_precision_options::preserve_related_precision);
167 complex_mp::thread_default_variable_precision_options(
168 bmp::variable_precision_options::preserve_related_precision);
169#endif
170 }
171
172 // Sets thread-local precision only — does NOT write the global default_precision.
173 // Safe to call concurrently from multiple std::thread workers tracking at different
174 // precisions. Use instead of DefaultPrecision() inside per-thread tracking loops.
176 inline void SetThreadPrecision(unsigned prec)
177 {
178 real_mp::thread_default_precision(prec);
179 complex_mp::thread_default_precision(prec);
180 }
181
183 inline unsigned ThreadPrecision()
184 {
185 return static_cast<unsigned>(real_mp::thread_default_precision());
186 }
187
188}
189
190
191namespace boost { namespace serialization {
195 template <typename Archive>
196 void save(Archive& ar, ::boost::multiprecision::backends::mpc_complex_backend<0> const& r, unsigned /*version*/)
197 {
198 unsigned num_digits(r.precision());
199 ar & num_digits;
200 std::string tmp = r.str(0,std::ios::scientific);
201 ar & tmp;
202 }
203
207 template <typename Archive>
208 void load(Archive& ar, ::boost::multiprecision::backends::mpc_complex_backend<0>& r, unsigned /*version*/)
209 {
210 unsigned num_digits;
211 ar & num_digits;
212 r.precision(num_digits);
213 std::string tmp;
214 ar & tmp;
215 r = tmp.c_str();
216 }
217
218}} // re: namespace boost::serialization
219
220
222BOOST_SERIALIZATION_SPLIT_FREE(::boost::multiprecision::backends::mpc_complex_backend<0>);
224
225
226
227
228
229
230namespace bertini{
231
237 inline
238 auto Precision(complex_mp const& num)
239 {
240 return num.precision();
241 }
242
243
249 inline void Precision(complex_mp & num, unsigned prec)
250 {
251 num.precision(prec);
252 }
253
255 inline
256 bool isnan(complex_mp const& num){return isnan(num.real()) || isnan(num.imag());};
257
258
259
260 using std::polar;
261} // re: namespace bertini
262
263
264
265
266
267
268
269
270
271
272
273#endif
Extensions to the Boost.Multiprecision library.
Definition algorithm_builder.hpp:36
bool isnan(std::complex< double > const &z)
an overload of isnan, for std::complex<double>
Definition double_extensions.hpp:63
void SetThreadPrecision(unsigned prec)
Set the precision (digits) for the current thread only (does not touch the global default).
Definition mpfr_complex.hpp:176
bmp::number< mpc_complex_backend< 0 >, bmp::et_on > complex_mp
The arbitrary-precision complex number type.
Definition mpfr_complex.hpp:58
auto DefaultPrecision()
Get the global default precision (digits) for multiprecision numbers.
Definition mpfr_complex.hpp:135
boost::multiprecision::number< boost::multiprecision::mpfr_float_backend< 0 >, boost::multiprecision::et_on > real_mp
The arbitrary-precision real number type.
Definition mpfr_extensions.hpp:53
unsigned ThreadPrecision()
Get the current thread's precision (digits).
Definition mpfr_complex.hpp:183
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
auto DefaultPrecisionPolicy()
The default Boost.Multiprecision variable-precision policy used by bertini.
Definition mpfr_complex.hpp:64
Definition forbid_mixed_arithmetic.hpp:29
Definition mpfr_complex.hpp:191
void load(Archive &ar, ::boost::multiprecision::backends::mpc_complex_backend< 0 > &r, unsigned)
Load a mpc_complex type from a boost archive.
Definition mpfr_complex.hpp:208
void save(Archive &ar, ::boost::multiprecision::backends::mpc_complex_backend< 0 > const &r, unsigned)
Save a mpc_complex type to a boost archive.
Definition mpfr_complex.hpp:196
Definition forbid_mixed_arithmetic.hpp:27
boost::multiprecision::variable_precision_options saved_options_all_threads
The all-thread options to restore.
Definition mpfr_complex.hpp:102
void reset(boost::multiprecision::variable_precision_options opts)
Set both the global and thread options again (without changing what will be restored).
Definition mpfr_complex.hpp:121
scoped_mpfr_precision_options_all_threads(boost::multiprecision::variable_precision_options opts)
Save the current global and thread options and set the given ones for both.
Definition mpfr_complex.hpp:106
~scoped_mpfr_precision_options_all_threads()
Definition mpfr_complex.hpp:114
boost::multiprecision::variable_precision_options saved_options_this_thread
The current-thread options to restore.
Definition mpfr_complex.hpp:103
boost::multiprecision::variable_precision_options saved_options
The options to restore on destruction.
Definition mpfr_complex.hpp:76
~scoped_mpfr_precision_options_this_thread()
Definition mpfr_complex.hpp:84
scoped_mpfr_precision_options_this_thread(boost::multiprecision::variable_precision_options opts)
Save the current thread options and set the given ones.
Definition mpfr_complex.hpp:79
void reset(boost::multiprecision::variable_precision_options opts)
Set the thread options again (without changing what will be restored).
Definition mpfr_complex.hpp:90