Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]Infinity Class #916

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -36,6 +36,9 @@ symengine/symengine_config.h
symengine/utilities/teuchos/Teuchos_config.h
symengine/python/symengine/lib/config.pxi

# Folder Customisation in Mac
*.DS_Store

# Python build files
build*
*__pycache__*
Expand Down Expand Up @@ -76,6 +79,7 @@ symengine/tests/eval/test_lambda_double
symengine/tests/expression/test_expression
symengine/tests/basic/test_series_expansion_UP
symengine/tests/basic/test_series_expansion_URatP
symengine/tests/basic/test_infinity

# Benchmarks executables
benchmarks/add1
Expand Down
3 changes: 2 additions & 1 deletion symengine/CMakeLists.txt
Expand Up @@ -43,6 +43,7 @@ set(SRC
parser.cpp
mp_wrapper.cpp
sets.cpp
infinity.cpp
)

if (WITH_MPFR)
Expand Down Expand Up @@ -74,7 +75,7 @@ set(HEADERS
visitor.h eval_double.h diophantine.h cwrapper.h printer.h real_double.h
eval_mpfr.h eval_arb.h eval_mpc.h complex_double.h series_visitor.h
real_mpfr.h complex_mpc.h type_codes.inc lambda_double.h series.h series_piranha.h
basic-methods.inc series_flint.h series_generic.h sets.h derivative.h
basic-methods.inc series_flint.h series_generic.h sets.h infinity.h derivative.h
)

# Configure SymEngine using our CMake options:
Expand Down
9 changes: 7 additions & 2 deletions symengine/constants.cpp
@@ -1,8 +1,9 @@
#include <symengine/constants.h>
#include <symengine/add.h>
#include <symengine/complex.h>
#include <symengine/constants.h>
#include <symengine/functions.h>
#include <symengine/infinity.h>
#include <symengine/mul.h>
#include <symengine/add.h>
#include <symengine/pow.h>

namespace SymEngine
Expand Down Expand Up @@ -44,6 +45,10 @@ RCP<const Constant> pi = constant("pi");
RCP<const Constant> E = constant("E");
RCP<const Constant> EulerGamma = constant("EulerGamma");

RCP<const Infinit> Inf = Infinit::from_int(1);
RCP<const Infinit> NegInf = Infinit::from_int(-1);
RCP<const Infinit> ComplexInf = Infinit::from_int(0);

// Global variables declared in functions.cpp
// Look over https://github.com/sympy/symengine/issues/272
// for further details
Expand Down
7 changes: 6 additions & 1 deletion symengine/constants.h
Expand Up @@ -8,8 +8,9 @@
#define SYMENGINE_CONSTANTS_H

#include <symengine/basic.h>
#include <symengine/number.h>
#include <symengine/infinity.h>
#include <symengine/integer.h>
#include <symengine/number.h>
#include <symengine/symbol.h>

namespace SymEngine
Expand Down Expand Up @@ -66,6 +67,10 @@ extern RCP<const Constant> pi;
extern RCP<const Constant> E;
extern RCP<const Constant> EulerGamma;

// Infinity
extern RCP<const Infinit> Inf;
extern RCP<const Infinit> NegInf;
extern RCP<const Infinit> ComplexInf;
} // SymEngine

#endif
154 changes: 154 additions & 0 deletions symengine/infinity.cpp
@@ -0,0 +1,154 @@
#include <symengine/complex.h>
#include <symengine/complex_double.h>
#include <symengine/constants.h>
#include <symengine/infinity.h>

namespace SymEngine
{

Infinit::Infinit()
{
_direction = integer(1);
}

Infinit::Infinit(const RCP<const Number> &direction)
{
_direction = direction;
SYMENGINE_ASSERT(is_canonical(_direction));
}

Infinit::Infinit(const int val)
{
_direction = integer(val);
SYMENGINE_ASSERT(is_canonical(_direction));
}

Infinit::Infinit(const Infinit &inf)
{
_direction = inf.get_direction();
SYMENGINE_ASSERT(is_canonical(_direction))
}

RCP<const Infinit> Infinit::from_direction(const RCP<const Number> &direction)
{
return make_rcp<Infinit>(direction);
}

RCP<const Infinit> Infinit::from_int(const int val)
{
SYMENGINE_ASSERT(val >= -1 && val <= 1)
return make_rcp<Infinit>(val);
}

//! Canonical when the direction is -1, 0 or 1.
bool Infinit::is_canonical(const RCP<const Number> &num) const
{
if (is_a<Complex>(*num) || is_a<ComplexDouble>(*num))
throw std::runtime_error("Not implemented for all directions");

if (num->is_one() || num->is_zero() || num->is_minus_one())
return true;

return false;
}

std::size_t Infinit::__hash__() const
{
std::size_t seed = INFINIT;
hash_combine<Basic>(seed, *_direction);
return seed;
}

bool Infinit::__eq__(const Basic &o) const
{
if (is_a<Infinit>(o)) {
const Infinit &s = static_cast<const Infinit &>(o);
return eq(*_direction, *(s.get_direction()));
}

return false;
}

int Infinit::compare(const Basic &o) const
{
SYMENGINE_ASSERT(is_a<Infinit>(o))
const Infinit &s = static_cast<const Infinit &>(o);
return _direction->compare(*(s.get_direction()));
}

bool Infinit::is_unsigned_infinity() const
{
return _direction->is_zero();
}

bool Infinit::is_positive_infinity() const
{
return _direction->is_positive();
}

bool Infinit::is_negative_infinity() const
{
return _direction->is_negative();
}

RCP<const Number> Infinit::add(const Number &other) const
{
if (not is_a<Infinit>(other))
return rcp_from_this_cast<Number>();

const Infinit &s = static_cast<const Infinit &>(other);

if (not eq(*s.get_direction(), *_direction)) {
if (is_unsigned_infinity() or s.is_unsigned_infinity())
throw std::runtime_error("Indeterminate Expression: "
"`unsigned_infinity +- infinity` "
"encountered");
else
throw std::runtime_error("Indeterminate Expression: `infinity +- "
"infinity` encountered. Directions don't "
"match");
} else if (is_unsigned_infinity()) {
throw std::runtime_error("Indeterminate Expression: "
"`unsigned_infinity +- unsigned infinity` "
"encountered");
} else
return rcp_from_this_cast<Number>();
}

RCP<const Number> Infinit::mul(const Number &other) const
{
if (is_a<Complex>(other))
throw std::runtime_error("Multiplation with Complex not implemented");

if (is_a<Infinit>(other)) {
const Infinit &s = static_cast<const Infinit &>(other);

return make_rcp<const Infinit>(this->_direction->mul(*(s._direction)));
} else {
if (other.is_positive())
return rcp_from_this_cast<Number>();
else if (other.is_negative())
return make_rcp<const Infinit>(this->_direction->mul(*minus_one));
else
throw std::runtime_error(
"Indeterminate Expression: `0 * Infinity` encountered");
}
}

// TODO
RCP<const Number> Infinit::div(const Number &other) const
{
return zero;
}
// TODO
RCP<const Number> Infinit::pow(const Number &other) const
{
return zero;
}
// TODO
RCP<const Number> Infinit::rpow(const Number &other) const
{
return zero;
}

} // SymEngine
110 changes: 110 additions & 0 deletions symengine/infinity.h
@@ -0,0 +1,110 @@
/**
* \file infinity.h
*
**/

#ifndef SYMENGINE_INFINITY_H
#define SYMENGINE_INFINITY_H

#include <symengine/basic.h>
#include <symengine/number.h>

namespace SymEngine
{

/** This class holds "infinity"
* It includes a direction (like -infinity).
**/
class Infinit : public Number
{
RCP<const Number> _direction;

public:
IMPLEMENT_TYPEID(INFINIT)
//! Constructors

//! Default Constructor gives +infinity(direction = +1)
Infinit();
//! Constructs Infinit using the sign of `_direction`
Infinit(const RCP<const Number> &direction);
Infinit(const int val);
//! Copy Constructor
Infinit(const Infinit &inf);
static RCP<const Infinit>
from_direction(const RCP<const Number> &direction);
//! Constructs Infinit using sign of `val`
static RCP<const Infinit> from_int(const int val);

//! \return true if canonical
bool is_canonical(const RCP<const Number> &num) const;
//! \return size of the hash
std::size_t __hash__() const;

/*! Equality comparator
* \param o - Object to be compared with
* \return whether the 2 objects are equal
* */
// Implement these
bool __eq__(const Basic &o) const;
int compare(const Basic &o) const;

virtual vec_basic get_args() const
{
return {_direction};
}

//! \return `true` if `0`
inline bool is_zero() const
{
return false;
}
//! \return `true` if `1`
inline bool is_one() const
{
return false;
}
//! \return `true` if `-1`
inline bool is_minus_one() const
{
return false;
}

inline RCP<const Number> get_direction() const
{
return _direction;
}

bool is_unsigned_infinity() const;
bool is_positive_infinity() const;
bool is_negative_infinity() const;

inline bool is_positive() const
{
return is_positive_infinity();
}

inline bool is_negative() const
{
return is_negative_infinity();
}

// Think about it again
RCP<const Number> add(const Number &other) const;
RCP<const Number> mul(const Number &other) const;
RCP<const Number> div(const Number &other) const; // TODO
RCP<const Number> pow(const Number &other) const; // TODO
RCP<const Number> rpow(const Number &other) const; // TODO
};

inline RCP<const Infinit> infinit(const int &n = 1)
{
return make_rcp<Infinit>(n);
}

inline RCP<const Infinit> infinit(const RCP<const Number> &direction)
{
return make_rcp<Infinit>(direction);
}

} // SymEngine
#endif
12 changes: 12 additions & 0 deletions symengine/printer.cpp
Expand Up @@ -28,6 +28,18 @@ void StrPrinter::bvisit(const Symbol &x)
str_ = x.get_name();
}

void StrPrinter::bvisit(const Infinit &x)
{
std::ostringstream s;
if (x.is_negative_infinity())
s << "-oo";
else if (x.is_positive_infinity())
s << "+oo";
else
s << "zoo";
str_ = s.str();
}

void StrPrinter::bvisit(const Integer &x)
{
std::ostringstream s;
Expand Down
1 change: 1 addition & 0 deletions symengine/printer.h
Expand Up @@ -170,6 +170,7 @@ class StrPrinter : public BaseVisitor<StrPrinter>
void bvisit(const Add &x);
void bvisit(const Mul &x);
void bvisit(const Pow &x);
void bvisit(const Infinit &x);
void bvisit(const UnivariateIntPolynomial &x);
void bvisit(const UnivariatePolynomial &x);
void bvisit(const UnivariateSeries &x);
Expand Down
4 changes: 4 additions & 0 deletions symengine/tests/basic/CMakeLists.txt
Expand Up @@ -71,3 +71,7 @@ add_test(test_parser ${PROJECT_BINARY_DIR}/test_parser)
add_executable(test_sets test_sets.cpp)
target_link_libraries(test_sets symengine catch)
add_test(test_sets ${PROJECT_BINARY_DIR}/test_sets)

add_executable(test_infinity test_infinity.cpp)
target_link_libraries(test_infinity symengine catch)
add_test(test_infinity ${PROJECT_BINARY_DIR}/test_infinity)