31#ifndef BERTINI_EIGEN_EXTENSIONS_HPP
32#define BERTINI_EIGEN_EXTENSIONS_HPP
37#include <boost/serialization/complex.hpp>
38#include <boost/serialization/array.hpp>
39#include <boost/serialization/split_member.hpp>
41#define EIGEN_DENSEBASE_PLUGIN "bertini2/eigen_serialization_addon.hpp"
46using mpfr_real = bertini::mpfr_float;
47using mpfr_complex = bertini::mpfr_complex;
52 template<>
struct NumTraits<mpfr_real> : GenericNumTraits<mpfr_real>
55 typedef mpfr_real Real;
56 typedef mpfr_real NonInteger;
57 typedef mpfr_real Nested;
62 RequireInitialization = 1,
69 inline static Real highest() {
71 return (mpfr_real(1) - epsilon()) *
pow(mpfr_real(2),mpfr_get_emax()-1);
74 inline static Real lowest() {
78 inline static Real dummy_precision()
80 using bertini::DefaultPrecision;
81 return pow( mpfr_real(10),-
int(DefaultPrecision()-3));
84 inline static Real epsilon()
86 using bertini::DefaultPrecision;
87 return pow(mpfr_real(10),-
int(DefaultPrecision()));
90 static inline int digits10()
92 return bertini::DefaultPrecision();
99 template<
typename Expr1,
typename Expr2,
typename Expr3>
101 boost::multiprecision::detail::expression<Expr1,
102 Expr2, Expr3, void, void>
103 > : NumTraits<mpfr_real>
106 typedef mpfr_real Real;
107 typedef mpfr_real NonInteger;
108 typedef mpfr_real Nested;
120 template<>
struct NumTraits<mpfr_complex> : NumTraits<mpfr_real>
122 typedef mpfr_real Real;
123 typedef mpfr_real NonInteger;
124 typedef mpfr_complex Nested;
129 RequireInitialization = 1,
130 ReadCost = 2 * NumTraits<Real>::ReadCost,
131 AddCost = 2 * NumTraits<Real>::AddCost,
132 MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
139 struct abs2_impl<mpfr_complex>
141 static inline mpfr_real run(
const mpfr_complex& x)
143 return real(x)*real(x) + imag(x)*imag(x);
148 template<>
inline mpfr_complex random<mpfr_complex>()
153 template<>
inline mpfr_complex random<mpfr_complex>(
const mpfr_complex& a,
const mpfr_complex& b)
155 return a + (b-a) * random<mpfr_complex>();
159 struct conj_helper<mpfr_complex, mpfr_complex, false, true>
161 typedef mpfr_complex Scalar;
162 EIGEN_STRONG_INLINE Scalar pmadd(
const Scalar& x,
const Scalar& y,
const Scalar& c)
const
163 {
return c + pmul(x,y); }
165 EIGEN_STRONG_INLINE Scalar pmul(
const Scalar& x,
const Scalar& y)
const
166 {
return Scalar(real(x)*real(y) + imag(x)*imag(y), imag(x)*real(y) - real(x)*imag(y)); }
170 struct conj_helper<mpfr_complex, mpfr_complex, true, false>
172 typedef mpfr_complex Scalar;
173 EIGEN_STRONG_INLINE Scalar pmadd(
const Scalar& x,
const Scalar& y,
const Scalar& c)
const
174 {
return c + pmul(x,y); }
176 EIGEN_STRONG_INLINE Scalar pmul(
const Scalar& x,
const Scalar& y)
const
177 {
return Scalar(real(x)*real(y) + imag(x)*imag(y), real(x)*imag(y) - imag(x)*real(y)); }
184 struct scalar_product_traits<int,mpfr_complex>
186 enum { Defined = 1 };
187 typedef mpfr_complex ReturnType;
191 struct scalar_product_traits<mpfr_complex, int>
193 enum { Defined = 1 };
194 typedef mpfr_complex ReturnType;
199 struct scalar_product_traits<long,mpfr_complex>
201 enum { Defined = 1 };
202 typedef mpfr_complex ReturnType;
206 struct scalar_product_traits<mpfr_complex, long>
208 enum { Defined = 1 };
209 typedef mpfr_complex ReturnType;
214 struct scalar_product_traits<long long,mpfr_complex>
216 enum { Defined = 1 };
217 typedef mpfr_complex ReturnType;
221 struct scalar_product_traits<mpfr_complex, long long>
223 enum { Defined = 1 };
224 typedef mpfr_complex ReturnType;
230 struct scalar_product_traits<mpfr_real,mpfr_complex>
232 enum { Defined = 1 };
233 typedef mpfr_complex ReturnType;
237 struct scalar_product_traits<mpfr_complex, mpfr_real>
239 enum { Defined = 1 };
240 typedef mpfr_complex ReturnType;
245 struct scalar_product_traits<bertini::mpz_int,mpfr_complex>
247 enum { Defined = 1 };
248 typedef mpfr_complex ReturnType;
252 struct scalar_product_traits<mpfr_complex, bertini::mpz_int>
254 enum { Defined = 1 };
255 typedef mpfr_complex ReturnType;
263#include <Eigen/Geometry>
264#include <Eigen/Eigenvalues>
266#include <Eigen/Dense>
270 template<
typename NumType>
using Vec = Eigen::Matrix<NumType, Eigen::Dynamic, 1>;
271 template<
typename NumType>
using Mat = Eigen::Matrix<NumType, Eigen::Dynamic, Eigen::Dynamic>;
277 template<
typename Derived>
279 bool IsEmpty(Eigen::MatrixBase<Derived>
const & v)
281 return (v.rows()==0) || (v.cols()==0);
290 template<
typename Derived>
292 unsigned Precision(Eigen::MatrixBase<Derived>
const & v)
295 throw std::runtime_error(
"getting precision of empty object");
307 template<
typename Derived>
311 for (
int ii=0; ii<v.cols(); ++ii)
312 for (
int jj=0; jj<v.rows(); ++jj)
316 std::stringstream ss;
317 ss <<
"non-uniform precision in object! (" << a <<
"!=" <<
Precision(v(jj,ii)) <<
") at position " << jj <<
"," << ii;
318 throw std::runtime_error(ss.str());
331 template<
typename Derived>
332 void Precision(Eigen::MatrixBase<Derived> & v,
unsigned prec)
335 for (
int ii=0; ii<v.cols(); ++ii)
336 for (
int jj=0; jj<v.rows(); ++jj)
358 return abs(testme) <= Eigen::NumTraits<T>::epsilon()*100;
375 typename Eigen::NumTraits<T>::Real c = abs(a-b);
376 return (c/abs(a) <= e) || (c/abs(b) <= e) ;
395 static_assert(!Eigen::NumTraits<T>::IsInteger,
"IsLargeChange cannot be used safely on non-integral types");
397 return abs(numerator/denomenator) >= 1/Eigen::NumTraits<T>::dummy_precision();
400 enum class MatrixSuccessCode
416 template <
typename Derived>
419 #ifndef BERTINI_DISABLE_ASSERTS
420 assert(LU.rows()==LU.cols() &&
"non-square matrix in LUPartialPivotDecompositionSuccessful");
421 assert(LU.rows()>0 &&
"empty matrix in LUPartialPivotDecompositionSuccessful");
425 for (
unsigned int ii = LU.rows()-1; ii > 0; ii--)
429 return MatrixSuccessCode::SmallValue;
434 return MatrixSuccessCode::LargeChange;
441 return MatrixSuccessCode::SmallValue;
444 return MatrixSuccessCode::Success;
450 template <
typename NumberType>
451 Eigen::Matrix<NumberType, Eigen::Dynamic, Eigen::Dynamic>
KahanMatrix(
unsigned int mat_size, NumberType c)
454 NumberType s, scale(1.0);
455 s = sqrt( (NumberType(1.0)-c) * (NumberType(1.0)+c) );
458 Eigen::Matrix<NumberType, Eigen::Dynamic, Eigen::Dynamic> A(mat_size,mat_size);
461 for (
unsigned int ii=0; ii<mat_size; ii++) {
462 for (
unsigned int jj=0; jj<ii; jj++) {
463 A(ii,jj) = NumberType(0.0);
465 for (
unsigned int jj=ii; jj<mat_size; jj++) {
466 A(ii,jj) = -c * NumberType(1.0);
471 for (
unsigned int ii=0; ii<mat_size; ii++) {
472 A(ii,ii) += NumberType(1)+c;
475 for (
unsigned int jj=0; jj<mat_size; jj++){
476 for (
unsigned int kk=0;kk<mat_size;kk++){
482 for (
unsigned int jj=0;jj<mat_size;jj++){
483 for (
unsigned int kk=0;kk<mat_size;kk++){
484 A(kk,jj)/= NumberType(jj) + NumberType(1);
500 template <
typename NumberType>
504 return Mat<NumberType>(rows,cols).unaryExpr([](NumberType
const& x) {
return RandomUnit<NumberType>(); });
515 template <
typename NumberType>
519 return Vec<NumberType>(size).unaryExpr([](NumberType
const& x) {
return RandomUnit<NumberType>(); });
dbl pow(const dbl &z, int power)
Definition double_extensions.hpp:88
bool IsLargeChange(T const &numerator, T const &denomenator)
Definition eigen_extensions.hpp:393
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:369
Mat< NumberType > RandomOfUnits(uint rows, uint cols)
Make a random matrix of units (numbers with norm 1).
Definition eigen_extensions.hpp:502
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:417
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:308
bool IsSmallValue(T const &testme)
Definition eigen_extensions.hpp:355
bool IsEmpty(Eigen::MatrixBase< Derived > const &v)
Checks whether the number of rows and columns are either 0.
Definition eigen_extensions.hpp:279
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object. If the object is empty, it's the precision of a default-constru...
Definition eigen_extensions.hpp:292
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:451
Provides an Eigen-like NumTraits struct for querying traits of a number type.
complex rand()
Definition random.hpp:206