Program Listing for File basic.h

Return to documentation for file (symengine/symengine/basic.h)

#ifndef SYMENGINE_BASIC_H
#define SYMENGINE_BASIC_H

// Include all C++ headers here
#include <sstream>
#include <typeinfo>
#include <map>
#include <vector>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>
#include <type_traits>
#include <functional>
#include <algorithm>

#include <symengine/symengine_config.h>
#include <symengine/symengine_exception.h>

#ifdef WITH_SYMENGINE_THREAD_SAFE
#include <atomic>
#endif

#include <symengine/dict.h>

namespace SymEngine
{

enum TypeID {
#define SYMENGINE_INCLUDE_ALL
#define SYMENGINE_ENUM(type, Class) type,
#include "symengine/type_codes.inc"
#undef SYMENGINE_ENUM
#undef SYMENGINE_INCLUDE_ALL
    // The 'TypeID_Count' returns the number of elements in 'TypeID'. For this
    // to work, do not assign numbers to the elements above (or if you do, you
    // must assign the correct count below).
    TypeID_Count
};

#include "basic-methods.inc"

class Visitor;
class Symbol;

class Basic : public EnableRCPFromThis<Basic>
{
private:
// The hash_ is defined as mutable, because its value is initialized to 0
// in the constructor and then it can be changed in Basic::hash() to the
// current hash (which is always the same for the given instance). The
// state of the instance does not change, so we define hash_ as mutable.
#if defined(WITH_SYMENGINE_THREAD_SAFE)
    mutable std::atomic<hash_t> hash_; // This holds the hash value
#else
    mutable hash_t hash_; // This holds the hash value
#endif // WITH_SYMENGINE_THREAD_SAFE
public:
#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
    virtual TypeID get_type_code() const = 0;
#else
    TypeID type_code_;
    inline TypeID get_type_code() const
    {
        return type_code_;
    };
#endif
    Basic() : hash_{0}
    {
    }
    // Destructor must be explicitly defined as virtual here to avoid problems
    // with undefined behavior while deallocating derived classes.
    virtual ~Basic()
    {
    }

    Basic(const Basic &) = delete;
    Basic &operator=(const Basic &) = delete;

    Basic(Basic &&) = delete;
    Basic &operator=(Basic &&) = delete;

    virtual hash_t __hash__() const = 0;

    hash_t hash() const;

    virtual bool __eq__(const Basic &o) const = 0;

    bool __neq__(const Basic &o) const;

    int __cmp__(const Basic &o) const;

    virtual int compare(const Basic &o) const = 0;

    std::string __str__() const;

    RCP<const Basic> subs(const map_basic_basic &subs_dict) const;

    RCP<const Basic> xreplace(const map_basic_basic &subs_dict) const;

    virtual RCP<const Basic> expand_as_exp() const
    {
        throw NotImplementedError("Not Implemented");
    }

    virtual vec_basic get_args() const = 0;

    SYMENGINE_INCLUDE_METHODS(= 0;)

    RCP<const Basic> diff(const RCP<const Symbol> &x, bool cache = true) const;
};

struct RCPBasicHash {
    size_t operator()(const RCP<const Basic> &k) const
    {
        return static_cast<size_t>(k->hash());
    }
};

struct RCPBasicKeyEq {
    bool operator()(const RCP<const Basic> &x, const RCP<const Basic> &y) const
    {
        return eq(*x, *y);
    }
};

struct RCPBasicKeyLess {
    bool operator()(const RCP<const Basic> &x, const RCP<const Basic> &y) const
    {
        hash_t xh = x->hash(), yh = y->hash();
        if (xh != yh)
            return xh < yh;
        if (eq(*x, *y))
            return false;
        return x->__cmp__(*y) == -1;
    }
};

enum tribool { indeterminate = -1, trifalse = 0, tritrue = 1 };

inline bool is_true(tribool x)
{
    return x == tribool::tritrue;
};

// Convenience functions
bool eq(const Basic &a, const Basic &b);

bool neq(const Basic &a, const Basic &b);

template <class T>
bool is_a(const Basic &b);

bool is_a_Atom(const Basic &b);

template <class T>
bool is_a_sub(const Basic &b);

bool is_same_type(const Basic &a, const Basic &b);

RCP<const Basic> expand(const RCP<const Basic> &self, bool deep = true);
void as_numer_denom(const RCP<const Basic> &x,
                    const Ptr<RCP<const Basic>> &numer,
                    const Ptr<RCP<const Basic>> &denom);

void as_real_imag(const RCP<const Basic> &x, const Ptr<RCP<const Basic>> &real,
                  const Ptr<RCP<const Basic>> &imag);

RCP<const Basic> rewrite_as_exp(const RCP<const Basic> &x);

// Common subexpression elimination of symbolic expressions
// Return a vector of replacement pairs and a vector of reduced exprs
void cse(vec_pair &replacements, vec_basic &reduced_exprs,
         const vec_basic &exprs);

std::ostream &operator<<(std::ostream &out, const SymEngine::Basic &p);

template <class T>
void hash_combine(hash_t &seed, const T &v);

const char *get_version();

} // SymEngine

namespace std
{
template <>
struct hash<SymEngine::Basic>;
}

#include "basic-inl.h"

// Macro to define the type_code_id variable and its getter method
#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
#define IMPLEMENT_TYPEID(SYMENGINE_ID)                                         \
                                \
    const static TypeID type_code_id = SYMENGINE_ID;                           \
          \
    virtual TypeID get_type_code() const                                       \
    {                                                                          \
        return type_code_id;                                                   \
    };                                                                         \
    SYMENGINE_INCLUDE_METHODS(;)
#else
#define IMPLEMENT_TYPEID(SYMENGINE_ID)                                         \
                                \
    const static TypeID type_code_id = SYMENGINE_ID;                           \
    SYMENGINE_INCLUDE_METHODS(;)
#endif

#ifdef WITH_SYMENGINE_VIRTUAL_TYPEID
#define SYMENGINE_ASSIGN_TYPEID()
#else
#define SYMENGINE_ASSIGN_TYPEID() this->type_code_ = type_code_id;
#endif

#endif