Program Listing for File integer.h

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

#ifndef SYMENGINE_INTEGER_H
#define SYMENGINE_INTEGER_H

#include <symengine/number.h>
#include <symengine/symengine_exception.h>
#include <symengine/symengine_casts.h>

namespace SymEngine
{

class Integer : public Number
{
private:
    integer_class i;

public:
    IMPLEMENT_TYPEID(SYMENGINE_INTEGER)
    // explicit Integer(integer_class i);
    Integer(const integer_class &_i) : i(_i)
    {
        SYMENGINE_ASSIGN_TYPEID()
    }
    Integer(integer_class &&_i) : i(std::move(_i))
    {
        SYMENGINE_ASSIGN_TYPEID()
    }
    virtual hash_t __hash__() const;
    virtual bool __eq__(const Basic &o) const;
    virtual int compare(const Basic &o) const;

    signed long int as_int() const;
    unsigned long int as_uint() const;
    inline const integer_class &as_integer_class() const
    {
        return this->i;
    }
    inline virtual bool is_zero() const
    {
        return this->i == 0u;
    }
    inline virtual bool is_one() const
    {
        return this->i == 1u;
    }
    inline virtual bool is_minus_one() const
    {
        return this->i == -1;
    }
    inline virtual bool is_positive() const
    {
        return this->i > 0u;
    }
    inline virtual bool is_negative() const
    {
        return this->i < 0u;
    }
    // False is returned because a pure integer cannot have an imaginary part
    inline virtual bool is_complex() const
    {
        return false;
    }

    /* These are very fast methods for add/sub/mul/div/pow on Integers only */
    inline RCP<const Integer> addint(const Integer &other) const
    {
        return make_rcp<const Integer>(this->i + other.i);
    }
    inline RCP<const Integer> subint(const Integer &other) const
    {
        return make_rcp<const Integer>(this->i - other.i);
    }
    inline RCP<const Integer> mulint(const Integer &other) const
    {
        return make_rcp<const Integer>(this->i * other.i);
    }
    RCP<const Number> divint(const Integer &other) const;
    RCP<const Number> pow_negint(const Integer &other) const;
    inline RCP<const Number> powint(const Integer &other) const
    {
        if (not(mp_fits_ulong_p(other.i))) {
            if (other.i > 0u)
                throw SymEngineException(
                    "powint: 'exp' does not fit unsigned long.");
            else
                return pow_negint(other);
        }
        integer_class tmp;
        mp_pow_ui(tmp, i, mp_get_ui(other.i));
        return make_rcp<const Integer>(std::move(tmp));
    }
    inline RCP<const Integer> neg() const
    {
        return make_rcp<const Integer>(-i);
    }

    /* These are general methods, overriden from the Number class, that need to
     * check types to decide what operation to do, and so are a bit slower. */
    virtual RCP<const Number> add(const Number &other) const
    {
        if (is_a<Integer>(other)) {
            return addint(down_cast<const Integer &>(other));
        } else {
            return other.add(*this);
        }
    };
    virtual RCP<const Number> sub(const Number &other) const
    {
        if (is_a<Integer>(other)) {
            return subint(down_cast<const Integer &>(other));
        } else {
            return other.rsub(*this);
        }
    };

    virtual RCP<const Number> rsub(const Number &other) const
    {
        throw NotImplementedError("Not Implemented");
    };

    virtual RCP<const Number> mul(const Number &other) const
    {
        if (is_a<Integer>(other)) {
            return mulint(down_cast<const Integer &>(other));
        } else {
            return other.mul(*this);
        }
    };
    virtual RCP<const Number> div(const Number &other) const
    {
        if (is_a<Integer>(other)) {
            return divint(down_cast<const Integer &>(other));
        } else {
            return other.rdiv(*this);
        }
    };

    virtual RCP<const Number> rdiv(const Number &other) const;

    virtual RCP<const Number> pow(const Number &other) const
    {
        if (is_a<Integer>(other)) {
            return powint(down_cast<const Integer &>(other));
        } else {
            return other.rpow(*this);
        }
    };

    virtual RCP<const Number> rpow(const Number &other) const
    {
        throw NotImplementedError("Not Implemented");
    };
};

struct RCPIntegerKeyLess {
    bool operator()(const RCP<const Integer> &a,
                    const RCP<const Integer> &b) const
    {
        return a->as_integer_class() < b->as_integer_class();
    }
};
template <typename T>
inline typename std::enable_if<std::is_integral<T>::value,
                               RCP<const Integer>>::type
integer(T i)
{
    return make_rcp<const Integer>(integer_class(i));
}

inline RCP<const Integer> integer(integer_class i)
{
    return make_rcp<const Integer>(std::move(i));
}

RCP<const Integer> isqrt(const Integer &n);
int i_nth_root(const Ptr<RCP<const Integer>> &r, const Integer &a,
               unsigned long int n);
bool perfect_square(const Integer &n);
bool perfect_power(const Integer &n);
RCP<const Integer> iabs(const Integer &n);

} // SymEngine

#endif