28#ifndef BERTINI_EIGEN_EXTENSIONS_HPP
29#define BERTINI_EIGEN_EXTENSIONS_HPP
34#include <boost/serialization/complex.hpp>
35#include <boost/serialization/array.hpp>
36#include <boost/serialization/split_member.hpp>
39#define EIGEN_DENSEBASE_PLUGIN "bertini2/eigen_serialization_addon.hpp"
51 template<>
struct NumTraits<mpfr_real> : GenericNumTraits<mpfr_real>
54 typedef mpfr_real Real;
55 typedef mpfr_real NonInteger;
56 typedef mpfr_real Nested;
61 RequireInitialization = 1,
68 inline static Real highest() {
70 return (mpfr_real(1) - epsilon()) * pow(mpfr_real(2),mpfr_get_emax()-1);
73 inline static Real lowest() {
86 inline static Real dummy_precision()
89 thread_local unsigned cached_prec = 0;
90 thread_local Real cached_val;
91 const unsigned p = ThreadPrecision();
94 cached_val = pow(mpfr_real(10), -
int(p-3));
100 inline static Real epsilon()
103 thread_local unsigned cached_prec = 0;
104 thread_local Real cached_val;
105 const unsigned p = ThreadPrecision();
106 if (p != cached_prec)
108 cached_val = pow(mpfr_real(10), -
int(p));
114 static inline int digits10()
123 template<
typename Expr1,
typename Expr2,
typename Expr3>
125 boost::multiprecision::detail::expression<Expr1,
126 Expr2, Expr3, void, void>
127 > : NumTraits<mpfr_real>
130 typedef mpfr_real Real;
131 typedef mpfr_real NonInteger;
132 typedef mpfr_real Nested;
144 template<>
struct NumTraits<complex_mp> : NumTraits<mpfr_real>
146 typedef mpfr_real Real;
147 typedef mpfr_real NonInteger;
148 typedef complex_mp Nested;
153 RequireInitialization = 1,
154 ReadCost = 2 * NumTraits<Real>::ReadCost,
155 AddCost = 2 * NumTraits<Real>::AddCost,
156 MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
163 struct abs2_impl<complex_mp>
165 static inline mpfr_real run(
const complex_mp& x)
167 return real(x)*real(x) + imag(x)*imag(x);
172 template<>
inline complex_mp random<complex_mp>()
177 template<>
inline complex_mp random<complex_mp>(
const complex_mp& a,
const complex_mp& b)
179 return a + (b-a) * random<complex_mp>();
183 struct conj_helper<complex_mp, complex_mp, false, true>
185 typedef complex_mp Scalar;
186 EIGEN_STRONG_INLINE Scalar pmadd(
const Scalar& x,
const Scalar& y,
const Scalar& c)
const
187 {
return c + pmul(x,y); }
189 EIGEN_STRONG_INLINE Scalar pmul(
const Scalar& x,
const Scalar& y)
const
190 {
return Scalar(real(x)*real(y) + imag(x)*imag(y), imag(x)*real(y) - real(x)*imag(y)); }
194 struct conj_helper<complex_mp, complex_mp, true, false>
196 typedef complex_mp Scalar;
197 EIGEN_STRONG_INLINE Scalar pmadd(
const Scalar& x,
const Scalar& y,
const Scalar& c)
const
198 {
return c + pmul(x,y); }
200 EIGEN_STRONG_INLINE Scalar pmul(
const Scalar& x,
const Scalar& y)
const
201 {
return Scalar(real(x)*real(y) + imag(x)*imag(y), real(x)*imag(y) - imag(x)*real(y)); }
208 struct scalar_product_traits<int,complex_mp>
210 enum { Defined = 1 };
211 typedef complex_mp ReturnType;
215 struct scalar_product_traits<complex_mp, int>
217 enum { Defined = 1 };
218 typedef complex_mp ReturnType;
223 struct scalar_product_traits<long,complex_mp>
225 enum { Defined = 1 };
226 typedef complex_mp ReturnType;
230 struct scalar_product_traits<complex_mp, long>
232 enum { Defined = 1 };
233 typedef complex_mp ReturnType;
238 struct scalar_product_traits<long long,complex_mp>
240 enum { Defined = 1 };
241 typedef complex_mp ReturnType;
245 struct scalar_product_traits<complex_mp, long long>
247 enum { Defined = 1 };
248 typedef complex_mp ReturnType;
254 struct scalar_product_traits<mpfr_real,complex_mp>
256 enum { Defined = 1 };
257 typedef complex_mp ReturnType;
261 struct scalar_product_traits<complex_mp, mpfr_real>
263 enum { Defined = 1 };
264 typedef complex_mp ReturnType;
269 struct scalar_product_traits<
bertini::mpz_int,complex_mp>
271 enum { Defined = 1 };
272 typedef complex_mp ReturnType;
276 struct scalar_product_traits<complex_mp,
bertini::mpz_int>
278 enum { Defined = 1 };
279 typedef complex_mp ReturnType;
288#include <Eigen/Geometry>
289#include <Eigen/Eigenvalues>
291#include <Eigen/Dense>
296 template<
typename NumT>
using Vec = Eigen::Matrix<NumT, Eigen::Dynamic, 1>;
298 template<
typename NumT>
using Mat = Eigen::Matrix<NumT, Eigen::Dynamic, Eigen::Dynamic>;
304 template<
typename Derived>
306 bool IsEmpty(Eigen::MatrixBase<Derived>
const & v)
308 return (v.rows()==0) || (v.cols()==0);
319 template<
typename Derived>
324 for (Eigen::Index ii = 0; ii < v.rows(); ++ii)
325 for (Eigen::Index jj = 0; jj < v.cols(); ++jj)
326 if (
isnan(v(ii,jj).real()) ||
isnan(v(ii,jj).imag()))
337 template<
typename Derived>
339 unsigned Precision(Eigen::MatrixBase<Derived>
const & v)
342 throw std::runtime_error(
"getting precision of empty object");
354 template<
typename Derived>
358 for (
int ii=0; ii<v.cols(); ++ii)
359 for (
int jj=0; jj<v.rows(); ++jj)
363 std::stringstream ss;
364 ss <<
"non-uniform precision in object! (" << a <<
"!=" <<
Precision(v(jj,ii)) <<
") at position " << jj <<
"," << ii;
365 throw std::runtime_error(ss.str());
378 template<
typename Derived>
379 void Precision(Eigen::MatrixBase<Derived> & v,
unsigned prec)
382 for (
int ii=0; ii<v.cols(); ++ii)
383 for (
int jj=0; jj<v.rows(); ++jj)
408 using Real =
typename Eigen::NumTraits<T>::Real;
409 const Real thresh = Eigen::NumTraits<T>::epsilon() * 100;
410 return Eigen::numext::abs2(testme) <= thresh * thresh;
431 typename Eigen::NumTraits<T>::Real c = abs(a-b);
432 return (c/abs(a) <= e) || (c/abs(b) <= e) ;
451 static_assert(!Eigen::NumTraits<T>::IsInteger,
"IsLargeChange cannot be used safely on non-integral types");
457 using Real =
typename Eigen::NumTraits<T>::Real;
458 const Real d = Eigen::NumTraits<T>::dummy_precision();
459 return Eigen::numext::abs2(numerator) * (d * d) >= Eigen::numext::abs2(denomenator);
479 template <
typename Derived>
482 #ifndef BERTINI_DISABLE_ASSERTS
483 assert(LU.rows()==LU.cols() &&
"non-square matrix in LUPartialPivotDecompositionSuccessful");
484 assert(LU.rows()>0 &&
"empty matrix in LUPartialPivotDecompositionSuccessful");
488 for (Eigen::Index ii = LU.rows()-1; ii > 0; ii--)
513 template <
typename NumberType>
514 Eigen::Matrix<NumberType, Eigen::Dynamic, Eigen::Dynamic>
KahanMatrix(
unsigned int mat_size, NumberType c)
517 NumberType s, scale(1.0);
518 s = sqrt( (NumberType(1.0)-c) * (NumberType(1.0)+c) );
521 Eigen::Matrix<NumberType, Eigen::Dynamic, Eigen::Dynamic> A(mat_size,mat_size);
524 for (
unsigned int ii=0; ii<mat_size; ii++) {
525 for (
unsigned int jj=0; jj<ii; jj++) {
526 A(ii,jj) = NumberType(0.0);
528 for (
unsigned int jj=ii; jj<mat_size; jj++) {
529 A(ii,jj) = -c * NumberType(1.0);
534 for (
unsigned int ii=0; ii<mat_size; ii++) {
535 A(ii,ii) += NumberType(1)+c;
538 for (
unsigned int jj=0; jj<mat_size; jj++){
539 for (
unsigned int kk=0;kk<mat_size;kk++){
545 for (
unsigned int jj=0;jj<mat_size;jj++){
546 for (
unsigned int kk=0;kk<mat_size;kk++){
547 A(kk,jj)/= NumberType(jj) + NumberType(1);
563 template <
typename NumberType>
600 template <
typename NumberType>
606 const unsigned int tall =
max(rows, cols);
607 const unsigned int thin = min(rows, cols);
610 Eigen::HouseholderQR<Mat<NumberType> > qr(seed);
614 return Q.transpose();
625 template <
typename NumberType>
644 template <
typename DerivedA,
typename DerivedB>
648 if (a.size() != b.size())
652 return (a - b).template lpNorm<Eigen::Infinity>() <= tol;
663 template <
typename DerivedA,
typename DerivedB>
665 bool IsDistinct(Eigen::MatrixBase<DerivedA>
const& a, Eigen::MatrixBase<DerivedB>
const& b,
NumErrorT tol)
Definition eigen_extensions.hpp:48
complex rand()
Produce a random complex number, to default precision.
Definition random.hpp:288
Definition algorithm_builder.hpp:36
MatrixSuccessCode
Outcome of a matrix-decomposition sanity check (e.g. LU pivot magnitude).
Definition eigen_extensions.hpp:464
@ Success
The decomposition looks healthy.
Definition eigen_extensions.hpp:465
@ SmallValue
A pivot is suspiciously small (near-singular).
Definition eigen_extensions.hpp:467
@ LargeChange
A pivot changed by a suspiciously large amount.
Definition eigen_extensions.hpp:466
bool isnan(std::complex< double > const &z)
an overload of isnan, for std::complex<double>
Definition double_extensions.hpp:63
bool IsLargeChange(T const &numerator, T const &denomenator)
Test two numbers for having large ratio.
Definition eigen_extensions.hpp:449
bool IsSymmRelDiffSmall(T const &a, T const &b, typename Eigen::NumTraits< T >::Real const &e)
Check whether two values are very close to each other.
Definition eigen_extensions.hpp:425
bool IsSamePoint(Eigen::MatrixBase< DerivedA > const &a, Eigen::MatrixBase< DerivedB > const &b, NumErrorT tol)
True if two points are the same to within tol in the infinity norm.
Definition eigen_extensions.hpp:646
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
T RandomUnit()
Get a random complex number of unit modulus, in number type T.
Mat< NumberType > RandomOfUnits(unsigned int rows, unsigned int cols)
Make a random matrix of units (numbers with norm 1).
Definition eigen_extensions.hpp:565
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
MatrixSuccessCode LUPartialPivotDecompositionSuccessful(Eigen::MatrixBase< Derived > const &LU)
Check the diagonal elements of an LU decomposition for small values and large ratios.
Definition eigen_extensions.hpp:480
Eigen::Matrix< NumT, Eigen::Dynamic, Eigen::Dynamic > Mat
A dynamically-sized matrix of NumT.
Definition eigen_extensions.hpp:298
double NumErrorT
The numeric type used to hold error/tolerance magnitudes throughout Bertini2 – tracking tolerances,...
Definition num_traits.hpp:48
unsigned PrecisionRequireUniform(Eigen::MatrixBase< Derived > const &v)
Query the precision of an Eigen object, requiring it to be non-empty, and of uniform precision.
Definition eigen_extensions.hpp:355
bmp::number< mpc_complex_backend< 0 >, bmp::et_on > complex_mp
The arbitrary-precision complex number type.
Definition mpfr_complex.hpp:58
@ Success
Definition config.hpp:51
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
bool IsSmallValue(T const &testme)
Test a numbers being very small.
Definition eigen_extensions.hpp:402
bool IsEmpty(Eigen::MatrixBase< Derived > const &v)
Checks whether the number of rows and columns are either 0.
Definition eigen_extensions.hpp:306
bool IsDistinct(Eigen::MatrixBase< DerivedA > const &a, Eigen::MatrixBase< DerivedB > const &b, NumErrorT tol)
True if two points differ by more than tol in the infinity norm (the negation of :func:IsSamePoint).
Definition eigen_extensions.hpp:665
unsigned ThreadPrecision()
Get the current thread's precision (digits).
Definition mpfr_complex.hpp:183
Mat< NumberType > RandomConjugateOrthonormalMatrix(unsigned int rows, unsigned int cols)
Make a random conjugate-orthonormal matrix (orthonormal rows when rows<=cols, orthonormal columns whe...
Definition eigen_extensions.hpp:602
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
T max(T const &a, T const &b, T const &c)
Three-argument form of max.
Definition mpfr_extensions.hpp:96
@ Real
Definition straight_line_program.hpp:165
Eigen::Matrix< NumberType, Eigen::Dynamic, Eigen::Dynamic > KahanMatrix(unsigned int mat_size, NumberType c)
Make a Kahan matrix with a given number type.
Definition eigen_extensions.hpp:514
bool ContainsNaN(Eigen::MatrixBase< Derived > const &v)
True when any entry of a complex-valued Eigen object has a NaN real or imaginary part.
Definition eigen_extensions.hpp:321
Definition forbid_mixed_arithmetic.hpp:27
Provides an Eigen-like NumTraits struct for querying traits of a number type.