Skip to content

Commit

Permalink
Code changes mostly done.
Browse files Browse the repository at this point in the history
  • Loading branch information
casevh committed Apr 28, 2018
1 parent 4724164 commit 39a9e48
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/gmpy2.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,9 @@ static PyMethodDef Pygmpy_methods [] =
{ "mpfr_from_old_binary", GMPy_MPFR_From_Old_Binary, METH_O, doc_mpfr_from_old_binary },
{ "mpfr_random", GMPy_MPFR_random_Function, METH_VARARGS, GMPy_doc_mpfr_random_function },
{ "mpfr_grandom", GMPy_MPFR_grandom_Function, METH_VARARGS, GMPy_doc_mpfr_grandom_function },
#if MPFR_VERSION_MAJOR > 3
{ "mpfr_nrandom", GMPy_MPFR_nrandom_Function, METH_VARARGS, GMPy_doc_mpfr_nrandom_function },
#endif
{ "mul_2exp", GMPy_Context_Mul_2exp, METH_VARARGS, GMPy_doc_function_mul_2exp },
{ "nan", GMPy_MPFR_set_nan, METH_NOARGS, GMPy_doc_mpfr_set_nan },
{ "next_above", GMPy_Context_NextAbove, METH_O, GMPy_doc_function_next_above },
Expand All @@ -786,6 +789,7 @@ static PyMethodDef Pygmpy_methods [] =
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_function_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_function_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_function_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_function_rootn },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_function_round_away },
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_function_round2 },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_function_sec },
Expand Down Expand Up @@ -821,7 +825,7 @@ static PyMethodDef Pygmpy_methods [] =
};

static char _gmpy_docs[] =
"gmpy2 2.1.0a2 - General Multiple-precision arithmetic for Python\n"
"gmpy2 2.1.0a3 - General Multiple-precision arithmetic for Python\n"
"\n"
"gmpy2 supports several multiple-precision libraries. Integer and\n"
"rational arithmetic is provided by either the GMP or MPIR libraries.\n"
Expand Down
1 change: 1 addition & 0 deletions src/gmpy2_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,7 @@ static PyMethodDef GMPyContext_methods[] =
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_context_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_context_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_context_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_context_rootn },
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_context_round2 },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_context_round_away },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_context_sec },
Expand Down
202 changes: 199 additions & 3 deletions src/gmpy2_math.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,13 +1139,209 @@ GMPY_MPFR_MPC_UNIOP_TEMPLATE_EX(Sqrt, sqrt)

PyDoc_STRVAR(GMPy_doc_function_root,
"root(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.");
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See rootn().");

PyDoc_STRVAR(GMPy_doc_context_root,
"context.root(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.");
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See rootn().");

PyDoc_STRVAR(GMPy_doc_function_rootn,
"rootn(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: this is IEEE 754-2008 compliant version of root().");

PyDoc_STRVAR(GMPy_doc_context_rootn,
"context.rootn(x, n) -> mpfr\n\n"
"Return n-th root of x. The result always an 'mpfr'.\n"
"Note: this is IEEE 754-2008 compliant version of root().");

#if MPFR_VERSION_MAJOR > 3

/* Since mpfr_root is deprecated in MPFR 4, we use mpfr_rootn_ui to
* mimic the behavior of mpfr_root. And the converse will be true when
* using MPFR 3.
*/

static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;

CHECK_CONTEXT(context);

result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);

if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}

mpfr_clear_flags();
result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}

static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;

CHECK_CONTEXT(context);

result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);

if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}

mpfr_clear_flags();

/* Mimic the non-compliant IEEE 752-2008 behavior. */

if ((mpfr_zero_p(tempx->f) && (mpfr_sgn(tempx->f) < 0))) {
mpfr_set_zero(result->f, -1);
}

result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#else
static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;

CHECK_CONTEXT(context);

result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);

if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}

mpfr_clear_flags();

/* Mimic the compliant IEEE 752-2008 behavior. */

if ((mpfr_zero_p(tempx->f) && (mpfr_sgn(tempx->f) < 0))) {
if ((n & 1)) {
/* Odd, so result is -0. */
mpfr_set_zero(result->f, -1);
}
else {
/* Even, so result is 0. */
mpfr_set_zero(result->f, 1);
}
}

result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}

static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;

CHECK_CONTEXT(context);

result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = c_ulong_From_Integer(y);

if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}

mpfr_clear_flags();
result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#endif

static PyObject *
GMPy_Number_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyIntOrLong_Check(y))
return GMPy_Real_Rootn(x, y, context);
TYPE_ERROR("rootn() argument type not supported");
return NULL;
}

static PyObject *
GMPy_Context_Rootn(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("rootn() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Rootn(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}

static PyObject *
GMPy_Number_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyIntOrLong_Check(y))
return GMPy_Real_Root(x, y, context);
TYPE_ERROR("root() argument type not supported");
return NULL;
}

static PyObject *
GMPy_Context_Root(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("root() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Root(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}



GMPY_MPFR_BINOP_REAL_ULONG(Root, root)

PyDoc_STRVAR(GMPy_doc_function_jn,
"jn(x,n) -> mpfr\n\n"
Expand Down
9 changes: 5 additions & 4 deletions src/gmpy2_random.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ GMPy_MPFR_random_Function(PyObject *self, PyObject *args)
return (PyObject*)result;
}

#if MPFR_VERSION_MAJOR == 4
#if MPFR_VERSION_MAJOR > 3

PyDoc_STRVAR(GMPy_doc_mpfr_nrandom_function,
"mpfr_nrandom(random_state) -> (mpfr)\n\n"
"Return a random number with gaussian distribution.");
Expand All @@ -237,12 +238,12 @@ GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args)
return NULL;
}

if (result = GMPy_MPFR_New(0, context)) {
mpfr_grandom(result->f,
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_nrandom(result->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
}
return result;
return (PyObject*)result;
}

PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function,
Expand Down
3 changes: 3 additions & 0 deletions src/gmpy2_random.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ static PyObject * GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_random_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_random_Function(PyObject *self, PyObject *args);
#if MPFR_VERSION_MAJOR > 3
static PyObject * GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args);
#endif
static PyObject * GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_random_Function(PyObject *self, PyObject *args);

Expand Down

0 comments on commit 39a9e48

Please sign in to comment.