You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
9.9 KiB
356 lines
9.9 KiB
// This file is part of Bertini 2.
|
|
//
|
|
// number.hpp is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
//(at your option) any later version.
|
|
//
|
|
// number.hpp is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with number.hpp. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
// Copyright(C) 2015 - 2023 by Bertini2 Development Team
|
|
//
|
|
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
|
// as well as COPYING. Bertini2 is provided with permitted
|
|
// additional terms in the b2/licenses/ directory.
|
|
|
|
// individual authors of this file include:
|
|
// James Collins
|
|
// West Texas A&M University
|
|
// Spring, Summer 2015
|
|
//
|
|
//
|
|
// silviana amethyst
|
|
// University of Wisconsin - Eau Claire
|
|
//
|
|
// Created by Collins, James B. on 4/30/15.
|
|
//
|
|
//
|
|
// number.hpp: Declares the class Number.
|
|
|
|
/**
|
|
\file number.hpp
|
|
|
|
\brief Provides the Number Node types, including Rational, Float, and Integer
|
|
|
|
*/
|
|
|
|
#ifndef BERTINI_NODE_NUMBER_HPP
|
|
#define BERTINI_NODE_NUMBER_HPP
|
|
|
|
#include "function_tree/symbols/symbol.hpp"
|
|
|
|
namespace bertini {
|
|
namespace node {
|
|
|
|
/**
|
|
\brief Abstract Number type from which other Numbers derive.
|
|
|
|
This class represents constant leaves to a function tree. FreshEval simply
|
|
returns the value of the constant.
|
|
*/
|
|
class Number : public virtual Symbol {
|
|
public:
|
|
virtual ~Number() = default;
|
|
|
|
void Reset() const override;
|
|
|
|
/**
|
|
\brief Get the degree of this node.
|
|
|
|
The degree of a number is always 0. It's a number.
|
|
*/
|
|
inline int Degree(
|
|
std::shared_ptr<Variable> const& v = nullptr) const override {
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
\brief Get the degree of this node.
|
|
|
|
The degree of a number is always 0. It's a number.
|
|
*/
|
|
inline int Degree(VariableGroup const& vars) const override { return 0; }
|
|
|
|
/**
|
|
\brief Get the multidegree of this node.
|
|
|
|
The degree of a number is always 0. It's a number.
|
|
*/
|
|
inline std::vector<int> MultiDegree(
|
|
VariableGroup const& vars) const override {
|
|
return std::vector<int>(vars.size(), 0);
|
|
}
|
|
|
|
/**
|
|
\brief Homogenize this node.
|
|
|
|
Homogenization of a number is a trivial operation. Don't do anything.
|
|
*/
|
|
void Homogenize(VariableGroup const& vars,
|
|
std::shared_ptr<Variable> const& homvar) override {}
|
|
|
|
/**
|
|
\brief Is this node homogeneous?
|
|
|
|
Numbers are always homogeneous
|
|
*/
|
|
bool IsHomogeneous(
|
|
std::shared_ptr<Variable> const& v = nullptr) const override {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Check for homogeneity, with respect to a variable group.
|
|
*/
|
|
bool IsHomogeneous(VariableGroup const& vars) const override { return true; }
|
|
|
|
/**
|
|
Change the precision of this variable-precision tree node.
|
|
|
|
\param prec the number of digits to change precision to.
|
|
*/
|
|
void precision(unsigned int prec) const override;
|
|
|
|
/**
|
|
\brief Differentiate a number.
|
|
*/
|
|
std::shared_ptr<Node> Differentiate(
|
|
std::shared_ptr<Variable> const& v = nullptr) const override;
|
|
|
|
protected:
|
|
private:
|
|
friend class boost::serialization::access;
|
|
|
|
template <typename Archive>
|
|
void serialize(Archive& ar, const unsigned version) {
|
|
ar& boost::serialization::base_object<Symbol>(*this);
|
|
}
|
|
};
|
|
|
|
/**
|
|
\brief Signed real Integer storage in an expression tree.
|
|
|
|
Signed real Integer storage in an expression tree. Consider using a Rational
|
|
type.
|
|
*/
|
|
class Integer : public virtual Number,
|
|
public virtual EnableSharedFromThisVirtual<Integer> {
|
|
public:
|
|
BERTINI_DEFAULT_VISITABLE()
|
|
|
|
Integer(Integer const&) = default;
|
|
|
|
~Integer() = default;
|
|
|
|
void print(std::ostream& target) const override;
|
|
|
|
template <typename... Ts>
|
|
static std::shared_ptr<Integer> Make(Ts&&... ts) {
|
|
return std::shared_ptr<Integer>(new Integer(ts...));
|
|
}
|
|
|
|
private:
|
|
// https://stackoverflow.com/questions/33933550/exception-bad-weak-ptr-while-shared-from-this
|
|
// struct MakeConstructorPublic;
|
|
|
|
explicit Integer(int val) : true_value_(val) {}
|
|
|
|
explicit Integer(mpz_int val) : true_value_(val) {}
|
|
|
|
explicit Integer(std::string const& val) : true_value_(val) {}
|
|
|
|
// Return value of constant
|
|
dbl FreshEval_d(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_d(
|
|
dbl& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpfr_complex FreshEval_mp(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_mp(
|
|
mpfr_complex& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpz_int true_value_;
|
|
|
|
friend class boost::serialization::access;
|
|
|
|
Integer() = default;
|
|
|
|
template <typename Archive>
|
|
void serialize(Archive& ar, const unsigned version) {
|
|
ar& boost::serialization::base_object<Number>(*this);
|
|
ar & true_value_;
|
|
}
|
|
};
|
|
|
|
// struct Integer::MakeConstructorPublic : public Integer {
|
|
// template <typename... Args>
|
|
// MakeConstructorPublic(Args&& ...args) :
|
|
// Integer(std::forward<Args>(args)...)
|
|
// {}
|
|
// };
|
|
|
|
/**
|
|
\brief Number type for storing floating point numbers within an expression tree.
|
|
|
|
Number type for storing floating point numbers within an expression tree. The
|
|
number passed in at construct time is stored as the true value, and evaluation
|
|
down or up samples from this 'true value'. Consider using a Rational or Integer
|
|
if possible.
|
|
*/
|
|
class Float : public virtual Number,
|
|
public virtual EnableSharedFromThisVirtual<Float> {
|
|
public:
|
|
BERTINI_DEFAULT_VISITABLE()
|
|
|
|
~Float() = default;
|
|
|
|
void print(std::ostream& target) const override;
|
|
|
|
template <typename... Ts>
|
|
static std::shared_ptr<Float> Make(Ts&&... ts) {
|
|
return std::shared_ptr<Float>(new Float(ts...));
|
|
}
|
|
|
|
private:
|
|
explicit Float(mpfr_complex const& val) : highest_precision_value_(val) {}
|
|
|
|
explicit Float(mpfr_float const& rval, mpfr_float const& ival = 0)
|
|
: highest_precision_value_(rval, ival) {}
|
|
|
|
explicit Float(std::string const& val) : highest_precision_value_(val) {}
|
|
|
|
explicit Float(std::string const& rval, std::string const& ival)
|
|
: highest_precision_value_(rval, ival) {}
|
|
|
|
dbl FreshEval_d(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_d(
|
|
dbl& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpfr_complex FreshEval_mp(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_mp(
|
|
mpfr_complex& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpfr_complex highest_precision_value_;
|
|
|
|
friend class boost::serialization::access;
|
|
Float() = default;
|
|
template <typename Archive>
|
|
void serialize(Archive& ar, const unsigned version) {
|
|
ar& boost::serialization::base_object<Number>(*this);
|
|
ar& const_cast<mpfr_complex&>(highest_precision_value_);
|
|
}
|
|
};
|
|
|
|
/**
|
|
\brief The Rational number type for Bertini2 expression trees.
|
|
|
|
The Rational number type for Bertini2 expression trees. The `true value' is
|
|
stored using two mpq_rational numbers from the Boost.Multiprecision library, and
|
|
the ratio is converted into a double or a mpfr_complex at evaluate time.
|
|
*/
|
|
class Rational : public virtual Number,
|
|
public virtual EnableSharedFromThisVirtual<Rational> {
|
|
public:
|
|
BERTINI_DEFAULT_VISITABLE()
|
|
|
|
using mpq_rational = bertini::mpq_rational;
|
|
|
|
Rational(int, int) = delete;
|
|
|
|
~Rational() = default;
|
|
|
|
/**
|
|
\brief Get a random complex rational node. Numerator and denominator will
|
|
have about 50 digits.
|
|
|
|
\see RandomRat()
|
|
*/
|
|
template <unsigned long Digits = 50>
|
|
static Rational Rand() {
|
|
return Rational(RandomRat<Digits>(), RandomRat<Digits>());
|
|
}
|
|
|
|
/**
|
|
\brief Get a random real rational node. Numerator and denominator will have
|
|
about 50 digits.
|
|
|
|
\see RandomRat()
|
|
*/
|
|
template <int Digits = 50>
|
|
static Rational rand_real() {
|
|
return Rational(RandomRat<Digits>(), 0);
|
|
}
|
|
|
|
void print(std::ostream& target) const override;
|
|
|
|
template <typename... Ts>
|
|
static std::shared_ptr<Rational> Make(Ts&&... ts) {
|
|
return std::shared_ptr<Rational>(new Rational(ts...));
|
|
}
|
|
|
|
private:
|
|
explicit Rational(int val) : true_value_real_(val), true_value_imag_(0) {}
|
|
|
|
explicit Rational(int val_real_numerator, int val_real_denomenator,
|
|
int val_imag_numerator, int val_imag_denomenator)
|
|
: true_value_real_(val_real_numerator, val_real_denomenator),
|
|
true_value_imag_(val_imag_numerator, val_imag_denomenator) {}
|
|
|
|
explicit Rational(std::string val)
|
|
: true_value_real_(val), true_value_imag_(0) {}
|
|
|
|
explicit Rational(std::string val_real, std::string val_imag)
|
|
: true_value_real_(val_real), true_value_imag_(val_imag) {}
|
|
|
|
explicit Rational(mpq_rational const& val_real,
|
|
mpq_rational const& val_imag = 0)
|
|
: true_value_real_(val_real), true_value_imag_(val_imag) {}
|
|
|
|
// Return value of constant
|
|
dbl FreshEval_d(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_d(
|
|
dbl& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpfr_complex FreshEval_mp(
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
void FreshEval_mp(
|
|
mpfr_complex& evaluation_value,
|
|
std::shared_ptr<Variable> const& diff_variable) const override;
|
|
|
|
mpq_rational true_value_real_, true_value_imag_;
|
|
Rational() = default;
|
|
friend class boost::serialization::access;
|
|
|
|
template <typename Archive>
|
|
void serialize(Archive& ar, const unsigned version) {
|
|
ar& boost::serialization::base_object<Number>(*this);
|
|
ar& const_cast<mpq_rational&>(true_value_real_);
|
|
ar& const_cast<mpq_rational&>(true_value_imag_);
|
|
}
|
|
};
|
|
|
|
} // namespace node
|
|
} // namespace bertini
|
|
|
|
#endif
|
|
|