28#ifndef BERTINI_PATCH_HPP
29#define BERTINI_PATCH_HPP
43#include <boost/archive/text_oarchive.hpp>
44#include <boost/archive/text_iarchive.hpp>
46#include <boost/serialization/vector.hpp>
103 variable_group_sizes_ = other.variable_group_sizes_;
107 std::vector<Vec<complex_mp> >& coefficients_mpfr = std::get<std::vector<Vec<complex_mp> > >(this->coefficients_working_);
108 std::vector<Vec<complex_dbl> >& coefficients_dbl = std::get<std::vector<Vec<complex_dbl> > >(this->coefficients_working_);
111 coefficients_mpfr.resize(variable_group_sizes_.size());
112 coefficients_dbl.resize(variable_group_sizes_.size());
116 auto curr_size = variable_group_sizes_[ii];
118 coefficients_highest_precision_[ii].resize(curr_size);
119 coefficients_dbl[ii].resize(curr_size);
120 coefficients_mpfr[ii].resize(curr_size);
122 for (
unsigned jj(0); jj<curr_size; jj++)
124 coefficients_highest_precision_[ii](jj).precision(other.coefficients_highest_precision_[ii](jj).precision());
126 coefficients_highest_precision_[ii](jj) = other.coefficients_highest_precision_[ii](jj);
128 coefficients_dbl[ii](jj) =
complex_dbl(coefficients_highest_precision_[ii](jj));
129 coefficients_mpfr[ii](jj) =
complex_mp(coefficients_highest_precision_[ii](jj));
131 assert(coefficients_highest_precision_[ii](jj) == other.coefficients_highest_precision_[ii](jj));
152 Patch(std::vector<unsigned>
const& sizes) : coefficients_highest_precision_(sizes.size()), variable_group_sizes_(sizes), precision_(
DefaultPrecision())
157 std::vector<Vec<complex_mp> >& coefficients_mpfr = std::get<std::vector<Vec<complex_mp> > >(coefficients_working_);
158 std::vector<Vec<complex_dbl> >& coefficients_dbl = std::get<std::vector<Vec<complex_dbl> > >(coefficients_working_);
160 coefficients_highest_precision_.resize(sizes.size());
161 coefficients_dbl.resize(sizes.size());
162 coefficients_mpfr.resize(sizes.size());
164 for (
size_t ii=0; ii<sizes.size(); ++ii)
167 coefficients_highest_precision_[ii].resize(sizes[ii]);
168 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
176 coefficients_dbl[ii].resize(sizes[ii]);
177 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
179 coefficients_dbl[ii](jj) =
complex_dbl(coefficients_highest_precision_[ii](jj));
184 coefficients_mpfr[ii].resize(sizes[ii]);
185 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
187 coefficients_mpfr[ii](jj) = coefficients_highest_precision_[ii](jj);
188 coefficients_mpfr[ii](jj).precision(precision_);
191 assert(
Precision(coefficients_mpfr[ii](0))==precision_);
207 if (coefficients.size() != sizes.size())
208 throw std::invalid_argument(
"Patch: " + std::to_string(coefficients.size())
209 +
" coefficient vectors for " + std::to_string(sizes.size()) +
" variable groups");
214 coefficients_highest_precision_.resize(sizes.size());
215 coefficients_dbl.resize(sizes.size());
216 coefficients_mpfr.resize(sizes.size());
218 for (
size_t ii=0; ii<sizes.size(); ++ii)
220 if (
static_cast<size_t>(coefficients[ii].size()) != sizes[ii])
221 throw std::invalid_argument(
"Patch: group " + std::to_string(ii) +
" has "
222 + std::to_string(coefficients[ii].size()) +
" coefficients for "
223 + std::to_string(sizes[ii]) +
" variables");
225 coefficients_highest_precision_[ii].resize(sizes[ii]);
226 coefficients_dbl[ii].resize(sizes[ii]);
227 coefficients_mpfr[ii].resize(sizes[ii]);
228 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
231 coefficients_highest_precision_[ii](jj).precision(coefficients[ii](jj).precision());
232 coefficients_highest_precision_[ii](jj) = coefficients[ii](jj);
233 coefficients_dbl[ii](jj) =
complex_dbl(coefficients_highest_precision_[ii](jj));
234 coefficients_mpfr[ii](jj) = coefficients_highest_precision_[ii](jj);
235 coefficients_mpfr[ii](jj).precision(precision_);
260 p.variable_group_sizes_ = sizes;
264 std::vector<Vec<complex_mp> >& coefficients_mpfr = std::get<std::vector<Vec<complex_mp> > >(p.coefficients_working_);
265 std::vector<Vec<complex_dbl> >& coefficients_dbl = std::get<std::vector<Vec<complex_dbl> > >(p.coefficients_working_);
267 p.coefficients_highest_precision_.resize(sizes.size());
268 coefficients_mpfr.resize(sizes.size());
269 coefficients_dbl.resize(sizes.size());
271 for (
size_t ii=0; ii<sizes.size(); ++ii)
273 p.coefficients_highest_precision_[ii].resize(sizes[ii]);
274 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
279 coefficients_mpfr[ii] = p.coefficients_highest_precision_[ii];
283 coefficients_dbl[ii].resize(sizes[ii]);
284 for (
unsigned jj=0; jj<sizes[ii]; ++jj)
285 coefficients_dbl[ii](jj) =
complex_dbl(p.coefficients_highest_precision_[ii](jj));
306 template <
typename T>
309 if constexpr (!std::is_same<T, complex_dbl>::value)
329 if (precision_==new_precision)
333 std::vector<Vec<complex_mp> >& coefficients_mpfr = std::get<std::vector<Vec<complex_mp> > >(coefficients_working_);
337 for (
unsigned jj=0; jj<variable_group_sizes_[ii]; ++jj)
339 if (new_precision>precision_)
341 coefficients_mpfr[ii](jj) = coefficients_highest_precision_[ii](jj);
342 coefficients_mpfr[ii](jj).precision(new_precision);
345 coefficients_mpfr[ii](jj).precision(new_precision);
347 assert(
Precision(coefficients_mpfr[ii](jj))==new_precision);
351 precision_ = new_precision;
369 template<
typename Derived,
typename T>
372 static_assert(std::is_same<typename Derived::Scalar,T>::value,
"scalar types must match");
376 #ifndef BERTINI_DISABLE_ASSERTS
379 std::stringstream ss;
380 ss <<
"container for function values must be of length at least as long as the number of variable groups. the input vector into which to write is of length " << function_values.size();
381 throw std::runtime_error(ss.str());
390 const std::vector<Vec<T> >& coefficients = std::get<std::vector<Vec<T> > >(coefficients_working_);
392 unsigned offset(
static_cast<unsigned>(function_values.size() -
NumVariableGroups()));
396 T& value = function_values(ii+offset);
398 for (
unsigned jj=0; jj<variable_group_sizes_[ii]; ++jj)
400 value += x(counter)*coefficients[ii](jj);
417 return function_values;
430 template<
typename Derived,
typename T>
433 static_assert(std::is_same<typename Derived::Scalar,T>::value,
"scalar types must match");
439 #ifndef BERTINI_DISABLE_ASSERTS
440 assert(jacobian.rows()>=
NumVariableGroups() &&
"input jacobian must have at least as many rows as variable groups");
441 assert(jacobian.cols()==
NumVariables() &&
"input jacobian must have as many columns as the patch has variables");
444 &&
"precision of input vector must match current working precision of patch during evaluation"
448 const std::vector<Vec<T> >& coefficients = std::get<std::vector<Vec<T> > >(coefficients_working_);
463 for (
unsigned jj=0; jj<variable_group_sizes_[ii]; ++jj)
464 jacobian(ii+offset,counter++) = coefficients[ii](jj);
504 #ifndef BERTINI_DISABLE_ASSERTS
505 assert(x.size() ==
NumVariables() &&
"input point for rescaling to fit a patch must have same length as total number of variables being patched, in all variable groups.");
508 const std::vector<Vec<T> >& coefficients = std::get<std::vector<Vec<T> > >(coefficients_working_);
510 unsigned starting_index_counter(0);
513 auto subvec = x.segment(starting_index_counter,variable_group_sizes_[ii]);
514 subvec /= subvec.transpose() * coefficients[ii];
515 starting_index_counter += variable_group_sizes_[ii];
526 template <
typename T>
541 return static_cast<unsigned>(variable_group_sizes_.size());
550 unsigned num_vars(0);
551 for (
auto v : variable_group_sizes_)
566 return coefficients_highest_precision_;
572 return variable_group_sizes_;
581 for (
auto& c : p.coefficients_highest_precision_)
583 out <<
"patch " << counter++ <<
" has " << c.size() <<
" coefficients:\n";
586 out <<
"current patch precision: " << p.
Precision() <<
"\n";
602 if (variable_group_sizes_[ii]!=rhs.variable_group_sizes_[ii])
605 if (coefficients_highest_precision_[ii]!=rhs.coefficients_highest_precision_[ii])
617 return !(*
this==rhs);
628 std::vector< Vec< complex_mp > > coefficients_highest_precision_;
630 mutable std::tuple< std::vector< Vec< complex_mp > >, std::vector< Vec< complex_dbl > > > coefficients_working_;
632 std::vector<unsigned> variable_group_sizes_;
634 mutable unsigned precision_;
640 template <
typename Archive>
641 void serialize(Archive& ar,
const unsigned ) {
644 ar & coefficients_highest_precision_;
646 ar & std::get<0>(coefficients_working_);
647 ar & std::get<1>(coefficients_working_);
648 ar & variable_group_sizes_;
Vec< T > RescalePoint(Vec< T > const &x) const
Rescale a point so that it satisfies the patch equations herein contained.
Definition patch.hpp:527
void JacobianInPlace(Eigen::MatrixBase< Derived > &jacobian, Vec< T > const &x) const
Evaluate the Jacobian matrix, in place.
Definition patch.hpp:431
Vec< T > Eval(Vec< T > const &x) const
Evaluate the patch at a point.
Definition patch.hpp:413
friend std::ostream & operator<<(std::ostream &out, Patch const &p)
Stream-insertion for a Patch, summarizing its variable groups and coefficients.
Definition patch.hpp:577
void Precision(unsigned new_precision) const
Set the precision of the patch.
Definition patch.hpp:327
void RescalePointToFitInPlace(Vec< T > &x) const
Rescale a point so that it satisfies the patch equations herein contained.
Definition patch.hpp:493
static Patch RandomReal(std::vector< unsigned > const &sizes)
Construct random REAL patch on a space.
Definition patch.hpp:253
std::vector< unsigned > const & VariableGroupSizes() const
The number of variables in each variable group (homogenizing variable included).
Definition patch.hpp:570
Patch & operator=(Patch const &other)=default
Copy assignment.
unsigned NumVariableGroups() const
Get the number of variable groups.
Definition patch.hpp:539
void SyncPrecision(Vec< T > const &x) const
Materialize the working coefficients at the precision of the point being evaluated.
Definition patch.hpp:307
Patch()
Default constructor.
Definition patch.hpp:94
void EvalInPlace(Eigen::MatrixBase< Derived > &function_values, Vec< T > const &x) const
Evaluate the patch at a point, in place.
Definition patch.hpp:370
Patch(std::vector< unsigned > const &sizes)
Constructor making a random complex patch on a space whose structure is described by the input argume...
Definition patch.hpp:152
Mat< T > Jacobian(Vec< T > const &x) const
Evaluate the Jacobian matrix, in place.
Definition patch.hpp:474
std::vector< Vec< complex_mp > > const & Coefficients() const
The patch's highest-precision coefficients, one vector per variable group.
Definition patch.hpp:564
static Patch Random(std::vector< unsigned > const &sizes)
Construct a random complex patch on a space.
Definition patch.hpp:244
unsigned Precision() const
Get the current precision of the patch.
Definition patch.hpp:297
friend class boost::serialization::access
Definition patch.hpp:638
unsigned NumVariables() const
Get the number of variables in the patch.
Definition patch.hpp:548
bool operator==(Patch const &rhs) const
Check whether two patches are the same.
Definition patch.hpp:595
Patch(Patch const &other)
Custom copy constructor, ensuring the max-precision coefficients are copied in highest precision.
Definition patch.hpp:101
bool operator!=(Patch const &rhs) const
Check whether two patches are different.
Definition patch.hpp:615
Patch(std::vector< unsigned > const &sizes, std::vector< Vec< complex_mp > > const &coefficients)
Construct a patch from given coefficients – for a loader restoring an archived patch exactly (the can...
Definition patch.hpp:204
Bertini extensions of the Eigen linear algebra library.
The main multiprecision complex number type.
Extensions to the Boost.Multiprecision library.
complex RandomComplex(unsigned num_digits)
Produce a random complex number, at the given precision.
Definition random.hpp:465
void RandomComplexBoundedModulusAssign(complex &a, unsigned num_digits)
Assign to a a random complex number whose modulus is pulled toward 1, at the given precision.
Definition random.hpp:355
void RandomRealBoundedModulusAssign(complex &a, unsigned num_digits)
Assign to a a random REAL number (imaginary part 0) whose modulus is pulled toward 1,...
Definition random.hpp:415
complex RandomReal()
Produce a random real number , to current default precision.
Definition random.hpp:262
Definition algorithm_builder.hpp:36
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
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
Eigen::Matrix< NumT, Eigen::Dynamic, Eigen::Dynamic > Mat
A dynamically-sized matrix of NumT.
Definition eigen_extensions.hpp:298
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
auto DefaultPrecision()
Get the global default precision (digits) for multiprecision numbers.
Definition mpfr_complex.hpp:135
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
Provides an Eigen-like NumTraits struct for querying traits of a number type.