Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
num_traits.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//num_traits.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//num_traits.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 num_traits.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
29
30#ifndef BERTINI_NUM_TRAITS_HPP
31#define BERTINI_NUM_TRAITS_HPP
32
33#include <random>
35#include <complex>
36#include <cmath>
38#include "bertini2/random.hpp"
39
40
41namespace bertini
42{
48 using NumErrorT = double;
49
51 template<typename T>
53
55 template<typename T>
56 struct NumTraits
57 {};
58
59
60
62 template <> struct NumTraits<double>
63 {
65 inline static unsigned NumDigits()
66 {
67 return 16;
68 }
69
71 inline static unsigned NumFuzzyDigits()
72 {
73 return 14;
74 }
75
77 inline
78 static unsigned TolToDigits(NumErrorT tol)
79 {
80 return static_cast<unsigned>(ceil(-log10(tol)));
81 }
82
84 inline static
85 double FromString(std::string const& s)
86 {
87 return boost::lexical_cast<double>(s);
88 }
89
91 inline static
92 double FromRational(mpq_rational const& n, unsigned /* precision */)
93 {
94 return double(n);
95 }
96
97 using Real = double;
99 };
100
101
103 template <> struct NumTraits<complex_dbl >
104 {
106 inline static unsigned NumDigits()
107 {
108 return 16;
109 }
110
112 inline static unsigned NumFuzzyDigits()
113 {
114 return 14;
115 }
116
118 inline static
119 complex_dbl FromString(std::string const& s)
120 {
121 return boost::lexical_cast<complex_dbl>(s);
122 }
123
125 inline static
126 complex_dbl FromString(std::string const& s, std::string const& t)
127 {
128 return complex_dbl(boost::lexical_cast<double>(s),boost::lexical_cast<double>(t));
129 }
130
132 inline static
133 complex_dbl FromRational(mpq_rational const& n, unsigned /* precision */)
134 {
135 return complex_dbl(static_cast<double>(n),0);
136 }
137
138 using Real = double;
140 };
141
142
144 inline
146 {
147 return 10;
148 }
149
151 constexpr
153 {
154 return 16;
155 }
156
158 constexpr
160 {
161 return 20;
162 }
163
165 constexpr
167 {
168 return 1000;
169 }
170
176 inline
177 unsigned Precision(double)
178 {
179 return DoublePrecision();
180 }
181
185 inline
186 void Precision(double, unsigned prec)
187 {
188 if (prec!=DoublePrecision())
189 {
190 std::stringstream err_msg;
191 err_msg << "trying to change precision of a double to " << prec;
192 throw std::runtime_error(err_msg.str());
193 }
194 }
195
201 inline
203 {
204 return DoublePrecision();
205 }
206
210 inline
211 void Precision(complex_dbl, unsigned prec)
212 {
213 if (prec!=DoublePrecision())
214 {
215 std::stringstream err_msg;
216 err_msg << "trying to change precision of a double to " << prec;
217 throw std::runtime_error(err_msg.str());
218 }
219 }
220
222 inline
224 {
225 using std::abs;
226 using std::sqrt;
227 // DRAW ORDER IS A CONTRACT (cross-platform reproducibility, 2026-07-03): the two
228 // component draws are sequenced EXPLICITLY -- real first, then imaginary. Never
229 // put two draws in one full-expression: C++ argument evaluation order is
230 // unspecified, and gcc really does order them differently on x86_64 vs aarch64
231 // (found as an architecture-split seeded-homotopy digest: every (re, im) pair of
232 // every seeded coefficient was transposed between the two).
233 double const re = records::DrawSymmetricDouble();
234 double const im = records::DrawSymmetricDouble();
235 complex_dbl returnme(re, im);
236 return returnme / sqrt( abs(returnme));
237 }
238
240 template <> inline
242 {
243 // draw order is a contract: real first, then imaginary (see rand_complex)
244 double const re = records::DrawSymmetricDouble();
245 double const im = records::DrawSymmetricDouble();
246 complex_dbl returnme(re, im);
247 return returnme / abs(returnme);
248 }
249
251 template <>
252 inline
257
261 template <>
262 inline
264 {
265 return real_mp( records::DrawSymmetricDouble() < 0.0 ? -1 : 1 );
266 }
267
278 template <typename NumberType>
279 inline
281 {
282 return RandomUnit<NumberType>();
283 }
284
286 template <>
287 inline
292}// re: namespace bertini
293
294
295
296
297
298
299
300
301
302
303
304
305namespace bertini {
306
307
308
310 template <> struct NumTraits<real_mp>
311 {
313 inline static unsigned NumDigits()
314 {
315 return ThreadPrecision();
316 }
317
319 inline static unsigned NumFuzzyDigits()
320 {
321 return ThreadPrecision()-3;
322 }
323
325 inline
326 static unsigned TolToDigits(real_mp tol)
327 {
328 real_mp b = ceil(-log10(tol));
329 return b.convert_to<unsigned int>();
330 }
331
333 inline static
334 real_mp FromString(std::string const& s)
335 {
336 return real_mp(s);
337 }
338
340 inline static
341 real_mp FromRational(mpq_rational const& n, unsigned precision)
342 {
343 return real_mp(n,precision);
344 }
345
346 using Real = real_mp;
348 };
349
350
351
353 template <> struct NumTraits<complex_mp>
354 {
356 inline static unsigned NumDigits()
357 {
358 return ThreadPrecision();
359 }
360
362 inline static
363 complex_mp FromString(std::string const& s)
364 {
365 return complex_mp(s);
366 }
367
369 inline static
370 complex_mp FromString(std::string const& s, std::string const& t)
371 {
372 return complex_mp(s,t);
373 }
374
376 inline static
377 complex_mp FromRational(mpq_rational const& n, unsigned precision)
378 {
379 return complex_mp(n,0,precision);
380 }
381
382 using Real = real_mp;
384 };
385
387 template <> struct NumTraits<mpq_rational>
388 {
399 inline static
400 mpq_rational FromString(std::string const& str)
401 {
402 std::string s = str;
403 bool negative = false;
404 if (!s.empty() && s[0] == '-') { negative = true; s = s.substr(1); }
405 else if (!s.empty() && s[0] == '+') { s = s.substr(1); }
406
407 int exp_shift = 0;
408 auto e_pos = s.find_first_of("eE");
409 if (e_pos != std::string::npos) {
410 exp_shift = std::stoi(s.substr(e_pos + 1));
411 s = s.substr(0, e_pos);
412 }
413
414 auto dot_pos = s.find('.');
415 int decimal_places = 0;
416 if (dot_pos != std::string::npos) {
417 decimal_places = static_cast<int>(s.size()) - static_cast<int>(dot_pos) - 1;
418 s.erase(dot_pos, 1);
419 }
420
421 if (s.empty() || s.find_first_not_of('0') == std::string::npos) {
422 s = "0";
423 } else {
424 s = s.substr(s.find_first_not_of('0'));
425 }
426 mpz_int numer(s);
427 if (negative) numer = -numer;
428
429 int net_exp = decimal_places - exp_shift;
430 if (net_exp > 0) {
431 mpz_int denom = 1;
432 for (int i = 0; i < net_exp; ++i) denom *= 10;
433 return mpq_rational(numer, denom);
434 } else if (net_exp < 0) {
435 mpz_int mult = 1;
436 for (int i = 0; i < -net_exp; ++i) mult *= 10;
437 return mpq_rational(numer * mult, 1);
438 } else {
439 return mpq_rational(numer, 1);
440 }
441 }
442 };
443
444}
445
446#endif
Dependency-free declarations of the pinned draw primitives (ADR-0044).
The main multiprecision complex number type.
complex RandomUnit()
Produce a random unit-modulus complex number, to default precision.
Definition random.hpp:315
double DrawSymmetricDouble()
A draw from this thread's pinned stream, uniform on [-1,1].
Definition algorithm_builder.hpp:36
complex_dbl rand_complex()
Get a random double-precision complex number (not unit modulus; see RandomUnit).
Definition num_traits.hpp:223
constexpr unsigned DoublePrecision()
The number of digits considered "double precision" (16).
Definition num_traits.hpp:152
std::complex< double > complex_dbl
The double-precision complex number type.
Definition double_extensions.hpp:47
T RandomUnit()
Get a random complex number of unit modulus, in number type T.
boost::multiprecision::number< boost::multiprecision::backends::gmp_int, boost::multiprecision::et_on > mpz_int
The arbitrary-precision integer type.
Definition mpfr_extensions.hpp:54
unsigned PrecisionIncrement()
The number of digits by which adaptive precision is increased at each step.
Definition num_traits.hpp:145
real_mp RandomUnit< real_mp >()
Get a random multiprecision real number of unit modulus (i.e.
Definition num_traits.hpp:263
NumberType RandomOrthonormalSeed()
The entry a random orthonormal matrix is seeded with before its QR factorization: a unit draw for the...
Definition num_traits.hpp:280
real_mp RandomOrthonormalSeed< real_mp >()
A real orthonormal seed entry: uniform on [-1, 1], never a bare sign.
Definition num_traits.hpp:288
double NumErrorT
The numeric type used to hold error/tolerance magnitudes throughout Bertini2 – tracking tolerances,...
Definition num_traits.hpp:48
constexpr unsigned MaxPrecisionAllowed()
The maximum precision (digits) the library will escalate to.
Definition num_traits.hpp:166
bmp::number< mpc_complex_backend< 0 >, bmp::et_on > complex_mp
The arbitrary-precision complex number type.
Definition mpfr_complex.hpp:58
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
complex_mp RandomUnit< complex_mp >()
Get a random multiprecision complex number of unit modulus.
Definition num_traits.hpp:253
constexpr unsigned LowestMultiplePrecision()
The lowest multiple-precision digit count used (20).
Definition num_traits.hpp:159
unsigned ThreadPrecision()
Get the current thread's precision (digits).
Definition mpfr_complex.hpp:183
boost::multiprecision::number< boost::multiprecision::backends::gmp_rational, boost::multiprecision::et_on > mpq_rational
The exact rational number type.
Definition mpfr_extensions.hpp:55
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
complex_dbl RandomUnit< complex_dbl >()
Get a random double-precision complex number of unit modulus.
Definition num_traits.hpp:241
stuff for generating random numbers
double Real
The real companion type.
Definition num_traits.hpp:138
complex_dbl Complex
The complex companion type.
Definition num_traits.hpp:139
static complex_dbl FromRational(mpq_rational const &n, unsigned)
Convert an exact rational to a complex double (precision ignored).
Definition num_traits.hpp:133
static unsigned NumDigits()
The number of significant digits (16).
Definition num_traits.hpp:106
static complex_dbl FromString(std::string const &s, std::string const &t)
Build a complex number from real and imaginary string parts.
Definition num_traits.hpp:126
static unsigned NumFuzzyDigits()
The number of digits to trust for fuzzy comparisons.
Definition num_traits.hpp:112
static complex_dbl FromString(std::string const &s)
Parse a complex number from a single string.
Definition num_traits.hpp:119
static complex_mp FromString(std::string const &s)
Parse a complex number from a single string.
Definition num_traits.hpp:363
static unsigned NumDigits()
The number of significant digits (the current thread precision).
Definition num_traits.hpp:356
static complex_mp FromRational(mpq_rational const &n, unsigned precision)
Convert an exact rational to a multiprecision complex number at the given precision.
Definition num_traits.hpp:377
real_mp Real
The real companion type.
Definition num_traits.hpp:382
static complex_mp FromString(std::string const &s, std::string const &t)
Build a complex number from real and imaginary string parts.
Definition num_traits.hpp:370
complex_mp Complex
The complex companion type.
Definition num_traits.hpp:383
static unsigned NumFuzzyDigits()
The number of digits to trust for fuzzy comparisons.
Definition num_traits.hpp:71
double Real
The real companion type.
Definition num_traits.hpp:97
static unsigned TolToDigits(NumErrorT tol)
Convert a tracking tolerance to a number of significant digits.
Definition num_traits.hpp:78
static double FromString(std::string const &s)
Parse a double from a string.
Definition num_traits.hpp:85
complex_dbl Complex
The complex companion type.
Definition num_traits.hpp:98
static unsigned NumDigits()
The number of significant digits (16 for double).
Definition num_traits.hpp:65
static double FromRational(mpq_rational const &n, unsigned)
Convert an exact rational to a double (precision ignored).
Definition num_traits.hpp:92
static mpq_rational FromString(std::string const &str)
Parse a decimal string to an exact mpq_rational.
Definition num_traits.hpp:400
static unsigned NumFuzzyDigits()
The number of digits to trust for fuzzy comparisons.
Definition num_traits.hpp:319
real_mp Real
The real companion type.
Definition num_traits.hpp:346
static real_mp FromString(std::string const &s)
Parse a multiprecision real from a string.
Definition num_traits.hpp:334
static unsigned TolToDigits(real_mp tol)
Convert a tracking tolerance to a number of significant digits.
Definition num_traits.hpp:326
static real_mp FromRational(mpq_rational const &n, unsigned precision)
Convert an exact rational to a multiprecision real at the given precision.
Definition num_traits.hpp:341
static unsigned NumDigits()
The number of significant digits (the current thread precision).
Definition num_traits.hpp:313
complex_mp Complex
The complex companion type.
Definition num_traits.hpp:347
Numeric traits for a bertini number type: digit counts, conversions, and companion types.
Definition num_traits.hpp:57