File:  [CENS] / python / pyGiNaC / wrappers3 / numeric_py.cpp
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Thu Apr 26 19:44:48 2001 UTC (16 years, 7 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
Impl. pseries,ncmul. Preparing for a release.

/*
# This file is part of the PyGiNaC package.
# http://cens.ioc.ee/projects/pyginac/
#
# $Revision: 1.4 $
# $Id: numeric_py.cpp,v 1.4 2001-04-26 19:44:48 pearu Exp $
#
# Copyright 2001 Pearu Peterson all rights reserved,
# Pearu Peterson <pearu@cens.ioc.ee>
# Permission to use, modify, and distribute this software is given under the
# terms of the LGPL.  See http://www.fsf.org
#
# NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
#
*/
/*DT
  Numeric
  -------

  >>> from ginac import numeric,symbol,is_numeric,I

  To construct numeric from Python objects:
  >>> numeric(3)
  numeric('3')
  >>> numeric(1.5)
  numeric('1.5')
  >>> numeric(1+2j)
  numeric('1.0+2.0*I')
  >>> numeric('2/6')
  numeric('1/3')
  >>> numeric(numeric('2/5'))
  numeric('2/5')
  >>> numeric(2,7)
  numeric('2/7')
  >>> numeric()
  numeric('0')
  >>> 2*I+3
  numeric('3+2*I')
  
  But it fails for other objects like lists, etc.:
  >>> numeric([2])
  Traceback (most recent call last):
  ...
  TypeError: numeric from_python() argument must be (number|string|ex(numeric)) (got <type 'list'>)

  To check whether an expression is numeric:
  >>> a,b=symbol(),numeric(2,3)
  >>> a.is_numeric(),b.is_numeric()
  (0, 1)
  >>> is_numeric(b), is_numeric([])
  (1, 0)

  Auxiliary functions (and methods):
  >>> from ginac import is_positive, is_integer, is_pos_integer,is_nonneg_integer
  >>> map(is_positive,[1,-1,numeric(2),ex(-1),symbol(),[]])
  [1, 0, 1, 0, 0, 0]
  >>> from ginac import is_even, is_odd, is_prime, is_rational, is_real
  >>> from ginac import is_cinteger, is_crational,is_negative
  >>> from ginac import real,imag
  >>> print int(numeric(23)),float(numeric(2.3))
  23 2.3
  
  Functions:
  >>> from ginac import doublefactorial, bernoulli, fibonacci, isqrt,mod
  >>> from ginac import gcd,lcm,irem,iquo

  Precision:
  >>> from ginac import set_Digits,get_Digits
*/

/*TODO Implement __long__ */

#ifdef PYGINAC_DEFS
this_module.def(&numeric_0, "numeric");
this_module.def(&numeric_1, "numeric");
this_module.def(&numeric_2, "numeric");

this_module.def(&GiNaC::doublefactorial, "doublefactorial");
this_module.def(&GiNaC::bernoulli, "bernoulli");
this_module.def(&GiNaC::fibonacci, "fibonacci");
this_module.def(&GiNaC::isqrt, "isqrt");
this_module.def(&GiNaC::mod, "mod");

this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &))&GiNaC::gcd, "gcd");
this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &))&GiNaC::lcm, "lcm");

this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &))&GiNaC::irem, "irem");
this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &, GiNaC::numeric &))&GiNaC::irem, "irem");

this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &))&GiNaC::iquo, "iquo");
this_module.def((const GiNaC::numeric (*)(const GiNaC::numeric &, const GiNaC::numeric &, GiNaC::numeric &))&GiNaC::iquo, "iquo");


ex_class.def(&ex::is_numeric, "is_numeric");
this_module.def(&ex::is_numeric, "is_numeric");
this_module.def(&return_false, "is_numeric");

ex_class.def(&is_positive, "is_positive");
this_module.def(&is_positive, "is_positive");
ex_class.def(&is_negative, "is_negative");
this_module.def(&is_negative, "is_negative");
ex_class.def(&is_integer, "is_integer");
this_module.def(&is_integer, "is_integer");
ex_class.def(&is_pos_integer, "is_pos_integer");
this_module.def(&is_pos_integer, "is_pos_integer");
ex_class.def(&is_nonneg_integer, "is_nonneg_integer");
this_module.def(&is_nonneg_integer, "is_nonneg_integer");
ex_class.def(&is_even, "is_even");
this_module.def(&is_even, "is_even");
ex_class.def(&is_odd, "is_odd");
this_module.def(&is_odd, "is_odd");
ex_class.def(&is_prime, "is_prime");
this_module.def(&is_prime, "is_prime");
ex_class.def(&is_rational, "is_rational");
this_module.def(&is_rational, "is_rational");
ex_class.def(&is_real, "is_real");
this_module.def(&is_real, "is_real");
ex_class.def(&is_cinteger, "is_cinteger");
this_module.def(&is_cinteger, "is_cinteger");
ex_class.def(&is_crational, "is_crational");
this_module.def(&is_crational, "is_crational");

ex_class.def(&ex::real, "real");
this_module.def(&GiNaC::real, "real");
ex_class.def(&ex::imag, "imag");
this_module.def(&GiNaC::imag, "imag");

ex_class.def(&ex::to_long, "__int__");
ex_class.def(&ex::to_double, "__float__");
ex_class.def(&ex::to_complex, "__complex__");

ex_class.def(&ex::cmp, "__cmp__");

this_module.def(&get_Digits, "get_Digits");
this_module.def(&set_Digits_0, "set_Digits");
this_module.def(&set_Digits, "set_Digits");

this_module.add(BOOST_PYTHON_CONVERSION::to_python(GiNaC::I), "I");

#else
#ifdef PYGINAC_EX_PROTOS
#define PYGINAC_PROTOS
#endif
#ifdef PYGINAC_PROTOS
#ifdef PYGINAC_EX_PROTOS
bool is_numeric(void) const;
GiNaC::numeric ex::real(void) const;
GiNaC::numeric ex::imag(void) const;
long ex::to_long(void) const;
double ex::to_double(void) const;
PyObject* ex::to_complex(void) const;
int ex::cmp(py::ref other) const;
#else // PYGINAC_EX_PROTOS
void set_Digits_0(void);
void set_Digits(long);
long get_Digits(void);
bool is_positive(py::ref);
bool is_negative(py::ref);
bool is_integer(py::ref);
bool is_pos_integer(py::ref);
bool is_nonneg_integer(py::ref);
bool is_even(py::ref);
bool is_odd(py::ref);
bool is_prime(py::ref);
bool is_rational(py::ref);
bool is_real(py::ref);
bool is_cinteger(py::ref);
bool is_crational(py::ref);
GiNaC::ex numeric_0(void);
GiNaC::ex numeric_1(const GiNaC::numeric & n);
GiNaC::ex numeric_2(const GiNaC::numeric & n, const GiNaC::numeric & d);
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
GiNaC::numeric from_python (PyObject* o, py::type<const GiNaC::numeric &>);
GiNaC::numeric & from_python (PyObject* o, py::type<GiNaC::numeric &>);
BOOST_PYTHON_END_CONVERSION_NAMESPACE
#endif // !PYGINAC_EX_PROTOS
#else  // PYGINAC_PROTOS
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
GiNaC::numeric from_python (PyObject* o, py::type<const GiNaC::numeric &>) {
  if (ExInstance_Check(o)) {
    GiNaC::ex e = BOOST_PYTHON_CONVERSION::from_python(o, py::type<const GiNaC::ex &>());
    if (is_ex_exactly_of_type(e, numeric))
      return ex_to_numeric(e);
  }
  if (PyInt_Check(o))
    return GiNaC::numeric(PyInt_AS_LONG(o));
  if (PyFloat_Check(o))
    return GiNaC::numeric(PyFloat_AS_DOUBLE(o));
  if (PyComplex_Check(o))
    return GiNaC::numeric(cln::complex(PyComplex_RealAsDouble(o),PyComplex_ImagAsDouble(o)));
  if (PyString_Check(o))
    return GiNaC::numeric(PyString_AS_STRING(o));
  PYGINAC_FROMPYTHON_TYPEERROR(numeric,(number|string|ex(numeric)));
}
GiNaC::numeric & from_python (PyObject* o, py::type<GiNaC::numeric &>) {
  if (ExInstance_Check(o)) {
    GiNaC::ex e = from_python(o, py::type<GiNaC::ex &>());
    if (is_ex_exactly_of_type(e, numeric))
      return (GiNaC::numeric &)*e.bp;
  }
  PYGINAC_FROMPYTHON_TYPEERROR(&numeric,ex(numeric));
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
#define PYGINAC_FUNC_1P_N(NAME) \
GiNaC::ex NAME##_1(py::ref obj) { \
  GiNaC::ex x = ex_from_ref(obj); \
  if (is_ex_exactly_of_type(x, numeric)) \
    return GiNaC::NAME(ex_to_numeric(x)); \
  PyErr_SetString(PyExc_TypeError, #NAME"() requires numeric argument."); \
  throw py::error_already_set(); \
}

/*F_DTis_numeric(obj)
  Check if `obj' is numeric.
*/
/*M_DTis_numeric(self)
  Check if object is numeric.
*/
bool ex::is_numeric(void) const { return is_ex_exactly_of_type(*this, numeric); }
/*F_DTnumeric(*args)
  numeric() - return numeric('0')
  numeric(i) - construct numeric from Python int `i'
  numeric(f) - construct numeric from Python float `f'
  numeric(c) - construct numeric from Python complex `c'
  numeric(s) - construct numeric from Python string `s'
  numeric(n,d) - construct numeric as numeric(n)/numeric(d)
  numeric(numeric(...)) -> numeric(...)
*/
GiNaC::ex numeric_0(void) {
  return GiNaC::numeric();
}
GiNaC::ex numeric_1(const GiNaC::numeric & n) {
  return n;
}
GiNaC::ex numeric_2(const GiNaC::numeric & n, const GiNaC::numeric & d) {
  return n/d;
}


#define PYGINAC_IS_N(NAME) \
bool is_##NAME(py::ref obj) { \
  PyObject *o = obj.get(); \
  if (ExInstance_Check(o)) { \
    GiNaC::ex e = from_python(o, py::type<GiNaC::ex &>()); \
    if (is_ex_exactly_of_type(e, numeric)) \
      return ex_to_numeric(e).is_##NAME(); \
  } \
  if (Number_Check(o) || PyString_Check(o)) \
    return from_python(o, py::type<const GiNaC::numeric &>()).is_##NAME(); \
  return false; \
}
/*M_DT is_positive(self)
  Check if positive number.
*/
/*F_DT is_positive(obj)
  Check if positive number.
*/
PYGINAC_IS_N(positive);
/*M_DT is_negative(self)
  Check if negative number.
*/
/*F_DT is_positive(obj)
  Check if negative number.
*/
PYGINAC_IS_N(negative);
/*M_DT is_integer(self)
  Check if integer.
*/
/*F_DT is_integer(obj)
  Check if integer.
*/
PYGINAC_IS_N(integer);
/*M_DT is_pos_integer(self)
  Check if positive integer.
*/
/*F_DT is_pos_integer(obj)
  Check if positive integer.
*/
PYGINAC_IS_N(pos_integer);
/*M_DT is_nonneg_integer(self)
  Check if nonnegative integer.
*/
/*F_DT is_nonneg_integer(obj)
  Check if nonnegative integer.
*/
PYGINAC_IS_N(nonneg_integer);
/*M_DT is_even(self)
  Check if even integer.
*/
/*F_DT is_even(obj)
  Check if even integer.
*/
PYGINAC_IS_N(even);
/*M_DT is_odd(self)
  Check if odd integer.
*/
/*F_DT is_odd(obj)
  Check if odd integer.
*/
PYGINAC_IS_N(odd);
/*M_DT is_prime(self)
  Check if integer prime.
*/
/*F_DT is_prime(obj)
  Check if integer prime.
*/
PYGINAC_IS_N(prime);
/*M_DT is_rational(self)
  Check if rational.
*/
/*F_DT is_rational(obj)
  Check if rational.
*/
PYGINAC_IS_N(rational);
/*M_DT is_real(self)
  Check if real.
*/
/*F_DT is_real(obj)
  Check if real.
*/
PYGINAC_IS_N(real);
/*M_DT is_crational(self)
  Check if complex rational.
*/
/*F_DT is_crational(obj)
  Check if complex rational.
*/
PYGINAC_IS_N(crational);
/*M_DT is_cinteger(self)
  Check if complex integer.
*/
/*F_DT is_cinteger(obj)
  Check if complex integer.
*/
PYGINAC_IS_N(cinteger);


/*F_DT doublefactorial(n)
  `n' must be integer.
 */
/*F_DT bernoulli(n)
  `n' must be integer.
 */
/*F_DT fibonacci(n)
  `n' must be integer.
 */
/*F_DT isqrt(n)
  `n' must be integer.
 */
/*F_DT mod(n,m)
  `n' and `m' must be integers.
 */
/*F_DT gcd(n,m)
  `n' and `m' must be integers.
 */
/*F_DT lcm(n,m)
  `n' and `m' must be integers.
 */
/*F_DT irem(n,m,k=None)
  `n' and `m' must be integers. `k' must be ex(numeric).
 */
/*F_DT iquo(n,m,k=None)
  `n' and `m' must be integers. `k' must be ex(numeric).
 */
/*M_DT real(self)
  Return real part.
  `self' must be ex(numeric).
*/
/*F_DT real(expr)
  Return real part.
  `expr' must be number.
*/
GiNaC::numeric ex::real(void) const
{
  if (is_numeric())
    return ex_to_numeric(*this).real();
  PyErr_SetString(PyExc_NotImplementedError, "ex.real() can be used only for ex(numeric)");
  throw py::error_already_set();
}
/*M_DT imag(self)
  Return imaginary part.
  `self' must be ex(numeric).
*/
/*F_DT imag(expr)
  Return imaginary part.
  `expr' must be number.
*/
GiNaC::numeric ex::imag(void) const
{
  if (is_numeric())
    return ex_to_numeric(*this).imag();
  PyErr_SetString(PyExc_NotImplementedError, "ex.imag() can be used only for ex(numeric)");
  throw py::error_already_set();
}
/*M_DT __int__(self)
  `self' must be ex(numeric).
 */
long ex::to_long(void) const
{
  if (is_numeric()) {
    const GiNaC::numeric & n = ex_to_numeric(*this);
    return cln::cl_I_to_long(cln::truncate1(cln::the<cln::cl_R>(n.real().to_cl_N())));
  }
  PyErr_SetString(PyExc_NotImplementedError, "int(ex) can be used only for ex(numeric)");
  throw py::error_already_set();
}
/*M_DT __float__(self)
  `self' must be ex(numeric).
 */
double ex::to_double(void) const
{
  if (is_numeric())
    return ex_to_numeric(*this).to_double();
  PyErr_SetString(PyExc_NotImplementedError, "float(ex) can be used only for ex(numeric)");
  throw py::error_already_set();
}
/*M_DT __complex__(self)
  `self' must be ex(numeric).
*/
/*TODO __complex__ is not supported in Boost.Python */
PyObject* ex::to_complex(void) const
{
  if (is_numeric()) {
    const GiNaC::numeric & n = ex_to_numeric(*this);
    double r = n.real().to_double();
    double i = n.imag().to_double();
    return Py_BuildValue("O", PyComplex_FromDoubles(r,i));
  }
  PyErr_SetString(PyExc_NotImplementedError, "complex(ex) can be used only for ex(numeric)");
  throw py::error_already_set();
}
/*M_DT __cmp__(self,other)
  Return `numeric(self-other).csgn()'.
  If `self-other' is not ex(numeric), ValueError is raised
  about indeterminate result.
 */
int ex::cmp(py::ref other) const
{
  GiNaC::ex e = *this - ex_from_ref(other);
  if (is_ex_exactly_of_type(e, numeric))
    return ex_to_numeric(e).csgn();
  PyErr_SetString(PyExc_ValueError, "ex.cmp(ref) is indeterminate.");
  throw py::error_already_set();
}
/*F_DT set_Digits(prec = 17)
  Set the number of decimal digits.
 */
/*F_DT get_Digits()
  Return the number of decimal digits.
 */
void set_Digits(long prec) {
  GiNaC::Digits = prec;
}
void set_Digits_0(void) {
  GiNaC::Digits = 17;
}
long get_Digits(void) {
  return GiNaC::Digits;
}
#endif // !PYGINAC_PROTOS
#endif // !PYGINAC_DEFS




FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>