From fbb29df68bd7f330d5a5ced2c20e9244f12f9648 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Fri, 23 Mar 2018 06:50:00 -0600 Subject: TST: Rename some compiled c test modules The renamed C modules provide low level functions for testing. The rename marks them as private functions and makes them invisible to pytest by default. --- numpy/conftest.py | 4 +- numpy/core/setup.py | 20 +- numpy/core/src/multiarray/_multiarray_tests.c.src | 1906 +++++++++++++++++++++ numpy/core/src/multiarray/multiarray_tests.c.src | 1906 --------------------- numpy/core/src/umath/_operand_flag_tests.c.src | 105 ++ numpy/core/src/umath/_rational_tests.c.src | 1409 +++++++++++++++ numpy/core/src/umath/_struct_ufunc_tests.c.src | 124 ++ numpy/core/src/umath/_umath_tests.c.src | 413 +++++ numpy/core/src/umath/operand_flag_tests.c.src | 105 -- numpy/core/src/umath/struct_ufunc_test.c.src | 124 -- numpy/core/src/umath/test_rational.c.src | 1409 --------------- numpy/core/src/umath/umath_tests.c.src | 413 ----- numpy/core/tests/test_deprecations.py | 6 +- numpy/core/tests/test_dtype.py | 2 +- numpy/core/tests/test_extint128.py | 2 +- numpy/core/tests/test_indexing.py | 2 +- numpy/core/tests/test_mem_overlap.py | 6 +- numpy/core/tests/test_multiarray.py | 20 +- numpy/core/tests/test_nditer.py | 2 +- numpy/core/tests/test_ufunc.py | 10 +- numpy/core/tests/test_umath.py | 2 +- numpy/lib/tests/test_stride_tricks.py | 2 +- numpy/testing/nose_tools/noseclasses.py | 2 +- 23 files changed, 3997 insertions(+), 3997 deletions(-) create mode 100644 numpy/core/src/multiarray/_multiarray_tests.c.src delete mode 100644 numpy/core/src/multiarray/multiarray_tests.c.src create mode 100644 numpy/core/src/umath/_operand_flag_tests.c.src create mode 100644 numpy/core/src/umath/_rational_tests.c.src create mode 100644 numpy/core/src/umath/_struct_ufunc_tests.c.src create mode 100644 numpy/core/src/umath/_umath_tests.c.src delete mode 100644 numpy/core/src/umath/operand_flag_tests.c.src delete mode 100644 numpy/core/src/umath/struct_ufunc_test.c.src delete mode 100644 numpy/core/src/umath/test_rational.c.src delete mode 100644 numpy/core/src/umath/umath_tests.c.src diff --git a/numpy/conftest.py b/numpy/conftest.py index 15985a75b..ce985d079 100644 --- a/numpy/conftest.py +++ b/numpy/conftest.py @@ -8,7 +8,7 @@ import pytest import numpy import importlib -from numpy.core.multiarray_tests import get_fpu_mode +from numpy.core._multiarray_tests import get_fpu_mode _old_fpu_mode = None @@ -21,7 +21,7 @@ def pytest_itemcollected(item): Check FPU precision mode was not changed during test collection. The clumsy way we do it here is mainly necessary because numpy - still uses yield tests, which can execute code at test collection + still uses yield tests, which can execute code at test collection time. """ global _old_fpu_mode diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 11b1acb07..d519e0eb8 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -924,29 +924,29 @@ def configuration(parent_package='',top_path=None): # umath_tests module # ####################################################################### - config.add_extension('umath_tests', - sources=[join('src', 'umath', 'umath_tests.c.src')]) + config.add_extension('_umath_tests', + sources=[join('src', 'umath', '_umath_tests.c.src')]) ####################################################################### # custom rational dtype module # ####################################################################### - config.add_extension('test_rational', - sources=[join('src', 'umath', 'test_rational.c.src')]) + config.add_extension('_rational_tests', + sources=[join('src', 'umath', '_rational_tests.c.src')]) ####################################################################### # struct_ufunc_test module # ####################################################################### - config.add_extension('struct_ufunc_test', - sources=[join('src', 'umath', 'struct_ufunc_test.c.src')]) + config.add_extension('_struct_ufunc_tests', + sources=[join('src', 'umath', '_struct_ufunc_tests.c.src')]) ####################################################################### # multiarray_tests module # ####################################################################### - config.add_extension('multiarray_tests', - sources=[join('src', 'multiarray', 'multiarray_tests.c.src'), + config.add_extension('_multiarray_tests', + sources=[join('src', 'multiarray', '_multiarray_tests.c.src'), join('src', 'private', 'mem_overlap.c')], depends=[join('src', 'private', 'mem_overlap.h'), join('src', 'private', 'npy_extint128.h')], @@ -956,8 +956,8 @@ def configuration(parent_package='',top_path=None): # operand_flag_tests module # ####################################################################### - config.add_extension('operand_flag_tests', - sources=[join('src', 'umath', 'operand_flag_tests.c.src')]) + config.add_extension('_operand_flag_tests', + sources=[join('src', 'umath', '_operand_flag_tests.c.src')]) config.add_data_dir('tests') config.add_data_dir('tests/data') diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src new file mode 100644 index 000000000..afc6db1aa --- /dev/null +++ b/numpy/core/src/multiarray/_multiarray_tests.c.src @@ -0,0 +1,1906 @@ +/* -*-c-*- */ +#define NPY_NO_DEPRECATED_API NPY_API_VERSION +#include +#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */ +#include "numpy/arrayobject.h" +#include "numpy/npy_math.h" +#include "mem_overlap.h" +#include "npy_extint128.h" +#include "common.h" + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* test PyArray_IsPythonScalar, before including private py3 compat header */ +static PyObject * +IsPythonScalar(PyObject * dummy, PyObject *args) +{ + PyObject *arg = NULL; + if (!PyArg_ParseTuple(args, "O", &arg)) { + return NULL; + } + if (PyArray_IsPythonScalar(arg)) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } +} + +#include "npy_pycompat.h" + +/* + * TODO: + * - Handle mode + */ + +/**begin repeat + * #name = double, int# + * #type = npy_double, npy_int# + * #typenum = NPY_DOUBLE, NPY_INT# + */ +static int copy_@name@(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx, + npy_intp *bounds, + PyObject **out) +{ + npy_intp i, j; + @type@ *ptr; + npy_intp odims[NPY_MAXDIMS]; + PyArrayObject *aout; + + /* + * For each point in itx, copy the current neighborhood into an array which + * is appended at the output list + */ + for (i = 0; i < itx->size; ++i) { + PyArrayNeighborhoodIter_Reset(niterx); + + for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { + odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; + } + aout = (PyArrayObject*)PyArray_SimpleNew( + PyArray_NDIM(itx->ao), odims, @typenum@); + if (aout == NULL) { + return -1; + } + + ptr = (@type@*)PyArray_DATA(aout); + + for (j = 0; j < niterx->size; ++j) { + *ptr = *((@type@*)niterx->dataptr); + PyArrayNeighborhoodIter_Next(niterx); + ptr += 1; + } + + PyList_Append(*out, (PyObject*)aout); + Py_DECREF(aout); + PyArray_ITER_NEXT(itx); + } + + return 0; +} +/**end repeat**/ + +static int copy_object(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx, + npy_intp *bounds, + PyObject **out) +{ + npy_intp i, j; + npy_intp odims[NPY_MAXDIMS]; + PyArrayObject *aout; + PyArray_CopySwapFunc *copyswap = PyArray_DESCR(itx->ao)->f->copyswap; + npy_int itemsize = PyArray_ITEMSIZE(itx->ao); + + /* + * For each point in itx, copy the current neighborhood into an array which + * is appended at the output list + */ + for (i = 0; i < itx->size; ++i) { + PyArrayNeighborhoodIter_Reset(niterx); + + for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { + odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; + } + aout = (PyArrayObject*)PyArray_SimpleNew(PyArray_NDIM(itx->ao), odims, NPY_OBJECT); + if (aout == NULL) { + return -1; + } + + for (j = 0; j < niterx->size; ++j) { + copyswap(PyArray_BYTES(aout) + j * itemsize, niterx->dataptr, 0, NULL); + PyArrayNeighborhoodIter_Next(niterx); + } + + PyList_Append(*out, (PyObject*)aout); + Py_DECREF(aout); + PyArray_ITER_NEXT(itx); + } + + return 0; +} + +static PyObject* +test_neighborhood_iterator(PyObject* NPY_UNUSED(self), PyObject* args) +{ + PyObject *x, *fill, *out, *b; + PyArrayObject *ax, *afill; + PyArrayIterObject *itx; + int i, typenum, mode, st; + npy_intp bounds[NPY_MAXDIMS*2]; + PyArrayNeighborhoodIterObject *niterx; + + if (!PyArg_ParseTuple(args, "OOOi", &x, &b, &fill, &mode)) { + return NULL; + } + + if (!PySequence_Check(b)) { + return NULL; + } + + typenum = PyArray_ObjectType(x, 0); + typenum = PyArray_ObjectType(fill, typenum); + + ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10); + if (ax == NULL) { + return NULL; + } + if (PySequence_Size(b) != 2 * PyArray_NDIM(ax)) { + PyErr_SetString(PyExc_ValueError, + "bounds sequence size not compatible with x input"); + goto clean_ax; + } + + out = PyList_New(0); + if (out == NULL) { + goto clean_ax; + } + + itx = (PyArrayIterObject*)PyArray_IterNew(x); + if (itx == NULL) { + goto clean_out; + } + + /* Compute boundaries for the neighborhood iterator */ + for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { + PyObject* bound; + bound = PySequence_GetItem(b, i); + if (bound == NULL) { + goto clean_itx; + } + if (!PyInt_Check(bound)) { + PyErr_SetString(PyExc_ValueError, + "bound not long"); + Py_DECREF(bound); + goto clean_itx; + } + bounds[i] = PyInt_AsLong(bound); + Py_DECREF(bound); + } + + /* Create the neighborhood iterator */ + afill = NULL; + if (mode == NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING) { + afill = (PyArrayObject *)PyArray_FromObject(fill, typenum, 0, 0); + if (afill == NULL) { + goto clean_itx; + } + } + + niterx = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( + (PyArrayIterObject*)itx, bounds, mode, afill); + if (niterx == NULL) { + goto clean_afill; + } + + switch (typenum) { + case NPY_OBJECT: + st = copy_object(itx, niterx, bounds, &out); + break; + case NPY_INT: + st = copy_int(itx, niterx, bounds, &out); + break; + case NPY_DOUBLE: + st = copy_double(itx, niterx, bounds, &out); + break; + default: + PyErr_SetString(PyExc_ValueError, + "Type not supported"); + goto clean_niterx; + } + + if (st) { + goto clean_niterx; + } + + Py_DECREF(niterx); + Py_XDECREF(afill); + Py_DECREF(itx); + + Py_DECREF(ax); + + return out; + +clean_niterx: + Py_DECREF(niterx); +clean_afill: + Py_XDECREF(afill); +clean_itx: + Py_DECREF(itx); +clean_out: + Py_DECREF(out); +clean_ax: + Py_DECREF(ax); + return NULL; +} + +static int +copy_double_double(PyArrayNeighborhoodIterObject *itx, + PyArrayNeighborhoodIterObject *niterx, + npy_intp *bounds, + PyObject **out) +{ + npy_intp i, j; + double *ptr; + npy_intp odims[NPY_MAXDIMS]; + PyArrayObject *aout; + + /* + * For each point in itx, copy the current neighborhood into an array which + * is appended at the output list + */ + PyArrayNeighborhoodIter_Reset(itx); + for (i = 0; i < itx->size; ++i) { + for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { + odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; + } + aout = (PyArrayObject*)PyArray_SimpleNew( + PyArray_NDIM(itx->ao), odims, NPY_DOUBLE); + if (aout == NULL) { + return -1; + } + + ptr = (double*)PyArray_DATA(aout); + + PyArrayNeighborhoodIter_Reset(niterx); + for (j = 0; j < niterx->size; ++j) { + *ptr = *((double*)niterx->dataptr); + ptr += 1; + PyArrayNeighborhoodIter_Next(niterx); + } + PyList_Append(*out, (PyObject*)aout); + Py_DECREF(aout); + PyArrayNeighborhoodIter_Next(itx); + } + return 0; +} + +static PyObject* +test_neighborhood_iterator_oob(PyObject* NPY_UNUSED(self), PyObject* args) +{ + PyObject *x, *out, *b1, *b2; + PyArrayObject *ax; + PyArrayIterObject *itx; + int i, typenum, mode1, mode2, st; + npy_intp bounds[NPY_MAXDIMS*2]; + PyArrayNeighborhoodIterObject *niterx1, *niterx2; + + if (!PyArg_ParseTuple(args, "OOiOi", &x, &b1, &mode1, &b2, &mode2)) { + return NULL; + } + + if (!PySequence_Check(b1) || !PySequence_Check(b2)) { + return NULL; + } + + typenum = PyArray_ObjectType(x, 0); + + ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10); + if (ax == NULL) { + return NULL; + } + if (PySequence_Size(b1) != 2 * PyArray_NDIM(ax)) { + PyErr_SetString(PyExc_ValueError, + "bounds sequence 1 size not compatible with x input"); + goto clean_ax; + } + if (PySequence_Size(b2) != 2 * PyArray_NDIM(ax)) { + PyErr_SetString(PyExc_ValueError, + "bounds sequence 2 size not compatible with x input"); + goto clean_ax; + } + + out = PyList_New(0); + if (out == NULL) { + goto clean_ax; + } + + itx = (PyArrayIterObject*)PyArray_IterNew(x); + if (itx == NULL) { + goto clean_out; + } + + /* Compute boundaries for the neighborhood iterator */ + for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { + PyObject* bound; + bound = PySequence_GetItem(b1, i); + if (bound == NULL) { + goto clean_itx; + } + if (!PyInt_Check(bound)) { + PyErr_SetString(PyExc_ValueError, + "bound not long"); + Py_DECREF(bound); + goto clean_itx; + } + bounds[i] = PyInt_AsLong(bound); + Py_DECREF(bound); + } + + /* Create the neighborhood iterator */ + niterx1 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( + (PyArrayIterObject*)itx, bounds, + mode1, NULL); + if (niterx1 == NULL) { + goto clean_out; + } + + for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { + PyObject* bound; + bound = PySequence_GetItem(b2, i); + if (bound == NULL) { + goto clean_itx; + } + if (!PyInt_Check(bound)) { + PyErr_SetString(PyExc_ValueError, + "bound not long"); + Py_DECREF(bound); + goto clean_itx; + } + bounds[i] = PyInt_AsLong(bound); + Py_DECREF(bound); + } + + niterx2 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( + (PyArrayIterObject*)niterx1, bounds, + mode2, NULL); + if (niterx1 == NULL) { + goto clean_niterx1; + } + + switch (typenum) { + case NPY_DOUBLE: + st = copy_double_double(niterx1, niterx2, bounds, &out); + break; + default: + PyErr_SetString(PyExc_ValueError, + "Type not supported"); + goto clean_niterx2; + } + + if (st) { + goto clean_niterx2; + } + + Py_DECREF(niterx2); + Py_DECREF(niterx1); + Py_DECREF(itx); + Py_DECREF(ax); + return out; + +clean_niterx2: + Py_DECREF(niterx2); +clean_niterx1: + Py_DECREF(niterx1); +clean_itx: + Py_DECREF(itx); +clean_out: + Py_DECREF(out); +clean_ax: + Py_DECREF(ax); + return NULL; +} + +/* PyDataMem_SetHook tests */ +static int malloc_free_counts[2]; +static PyDataMem_EventHookFunc *old_hook = NULL; +static void *old_data; + +static void test_hook(void *old, void *new, size_t size, void *user_data) +{ + int* counters = (int *) user_data; + if (old == NULL) { + counters[0]++; /* malloc counter */ + } + if (size == 0) { + counters[1]++; /* free counter */ + } +} + +static PyObject* +test_pydatamem_seteventhook_start(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) +{ + malloc_free_counts[0] = malloc_free_counts[1] = 0; + old_hook = PyDataMem_SetEventHook(test_hook, (void *) malloc_free_counts, &old_data); + Py_RETURN_NONE; +} + +static PyObject* +test_pydatamem_seteventhook_end(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) +{ + PyDataMem_EventHookFunc *my_hook; + void *my_data; + + my_hook = PyDataMem_SetEventHook(old_hook, old_data, &my_data); + if ((my_hook != test_hook) || (my_data != (void *) malloc_free_counts)) { + PyErr_SetString(PyExc_ValueError, + "hook/data was not the expected test hook"); + return NULL; + } + + if (malloc_free_counts[0] == 0) { + PyErr_SetString(PyExc_ValueError, + "malloc count is zero after test"); + return NULL; + } + if (malloc_free_counts[1] == 0) { + PyErr_SetString(PyExc_ValueError, + "free count is zero after test"); + return NULL; + } + + Py_RETURN_NONE; +} + + +typedef void (*inplace_map_binop)(PyArrayMapIterObject *, PyArrayIterObject *); + +static void npy_float64_inplace_add(PyArrayMapIterObject *mit, PyArrayIterObject *it) +{ + int index = mit->size; + while (index--) { + ((npy_float64*)mit->dataptr)[0] = ((npy_float64*)mit->dataptr)[0] + ((npy_float64*)it->dataptr)[0]; + + PyArray_MapIterNext(mit); + PyArray_ITER_NEXT(it); + } +} + +inplace_map_binop addition_funcs[] = { +npy_float64_inplace_add, +NULL}; + +int type_numbers[] = { +NPY_FLOAT64, +-1000}; + + + +static int +map_increment(PyArrayMapIterObject *mit, PyObject *op, inplace_map_binop add_inplace) +{ + PyArrayObject *arr = NULL; + PyArrayIterObject *it; + PyArray_Descr *descr; + + if (mit->ait == NULL) { + return -1; + } + descr = PyArray_DESCR(mit->ait->ao); + Py_INCREF(descr); + arr = (PyArrayObject *)PyArray_FromAny(op, descr, + 0, 0, NPY_ARRAY_FORCECAST, NULL); + if (arr == NULL) { + return -1; + } + + if ((mit->subspace != NULL) && (mit->consec)) { + PyArray_MapIterSwapAxes(mit, (PyArrayObject **)&arr, 0); + if (arr == NULL) { + return -1; + } + } + + if ((it = (PyArrayIterObject *)\ + PyArray_BroadcastToShape((PyObject *)arr, mit->dimensions, + mit->nd)) == NULL) { + Py_DECREF(arr); + + return -1; + } + + (*add_inplace)(mit, it); + + Py_DECREF(arr); + Py_DECREF(it); + return 0; +} + + +static PyObject * +inplace_increment(PyObject *dummy, PyObject *args) +{ + PyObject *arg_a = NULL, *index=NULL, *inc=NULL; + PyArrayObject *a; + inplace_map_binop add_inplace = NULL; + int type_number = -1; + int i =0; + PyArrayMapIterObject * mit; + + if (!PyArg_ParseTuple(args, "OOO", &arg_a, &index, + &inc)) { + return NULL; + } + if (!PyArray_Check(arg_a)) { + PyErr_SetString(PyExc_ValueError, "needs an ndarray as first argument"); + return NULL; + } + a = (PyArrayObject *) arg_a; + + if (PyArray_FailUnlessWriteable(a, "input/output array") < 0) { + return NULL; + } + + if (PyArray_NDIM(a) == 0) { + PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed."); + return NULL; + } + type_number = PyArray_TYPE(a); + + while (type_numbers[i] >= 0 && addition_funcs[i] != NULL){ + if (type_number == type_numbers[i]) { + add_inplace = addition_funcs[i]; + break; + } + i++ ; + } + + if (add_inplace == NULL) { + PyErr_SetString(PyExc_TypeError, "unsupported type for a"); + return NULL; + } + + mit = (PyArrayMapIterObject *) PyArray_MapIterArray(a, index); + if (mit == NULL) { + goto fail; + } + + if (map_increment(mit, inc, add_inplace) != 0) { + goto fail; + } + + Py_DECREF(mit); + + Py_RETURN_NONE; + +fail: + Py_XDECREF(mit); + + return NULL; +} + +/* check no elison for avoided increfs */ +static PyObject * +incref_elide(PyObject *dummy, PyObject *args) +{ + PyObject *arg = NULL, *res, *tup; + if (!PyArg_ParseTuple(args, "O", &arg)) { + return NULL; + } + + /* refcount 1 array but should not be elided */ + arg = PyArray_NewCopy((PyArrayObject*)arg, NPY_KEEPORDER); + res = PyNumber_Add(arg, arg); + + /* return original copy, should be equal to input */ + tup = PyTuple_Pack(2, arg, res); + Py_DECREF(arg); + Py_DECREF(res); + return tup; +} + +/* check no elison for get from list without incref */ +static PyObject * +incref_elide_l(PyObject *dummy, PyObject *args) +{ + PyObject *arg = NULL, *r, *res; + if (!PyArg_ParseTuple(args, "O", &arg)) { + return NULL; + } + /* get item without increasing refcount, item may still be on the python + * stack but above the inaccessible top */ + r = PyList_GetItem(arg, 4); + res = PyNumber_Add(r, r); + + return res; +} + +/* used to test NPY_CHAR usage emits deprecation warning */ +static PyObject* +npy_char_deprecation(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) +{ + PyArray_Descr * descr = PyArray_DescrFromType(NPY_CHAR); + return (PyObject *)descr; +} + +/* used to test UPDATEIFCOPY usage emits deprecation warning */ +static PyObject* +npy_updateifcopy_deprecation(PyObject* NPY_UNUSED(self), PyObject* args) +{ + int flags; + PyObject* array; + if (!PyArray_Check(args)) { + PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); + return NULL; + } + flags = NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY; + array = PyArray_FromArray((PyArrayObject*)args, NULL, flags); + if (array == NULL) + return NULL; + PyArray_ResolveWritebackIfCopy((PyArrayObject*)array); + Py_DECREF(array); + Py_RETURN_NONE; +} + +/* used to create array with WRITEBACKIFCOPY flag */ +static PyObject* +npy_create_writebackifcopy(PyObject* NPY_UNUSED(self), PyObject* args) +{ + int flags; + PyObject* array; + if (!PyArray_Check(args)) { + PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); + return NULL; + } + flags = NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY; + array = PyArray_FromArray((PyArrayObject*)args, NULL, flags); + if (array == NULL) + return NULL; + return array; +} + +/* resolve WRITEBACKIFCOPY */ +static PyObject* +npy_resolve(PyObject* NPY_UNUSED(self), PyObject* args) +{ + if (!PyArray_Check(args)) { + PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); + return NULL; + } + PyArray_ResolveWritebackIfCopy((PyArrayObject*)args); + Py_RETURN_NONE; +} + +#if !defined(NPY_PY3K) +static PyObject * +int_subclass(PyObject *dummy, PyObject *args) +{ + + PyObject *result = NULL; + PyObject *scalar_object = NULL; + + if (!PyArg_UnpackTuple(args, "test_int_subclass", 1, 1, &scalar_object)) + return NULL; + + if (PyInt_Check(scalar_object)) + result = Py_True; + else + result = Py_False; + + Py_INCREF(result); + + return result; + +} +#endif + + +/* + * Create python string from a FLAG and or the corresponding PyBuf flag + * for the use in get_buffer_info. + */ +#define GET_PYBUF_FLAG(FLAG) \ + buf_flag = PyUnicode_FromString(#FLAG); \ + flag_matches = PyObject_RichCompareBool(buf_flag, tmp, Py_EQ); \ + Py_DECREF(buf_flag); \ + if (flag_matches == 1) { \ + Py_DECREF(tmp); \ + flags |= PyBUF_##FLAG; \ + continue; \ + } \ + else if (flag_matches == -1) { \ + Py_DECREF(tmp); \ + return NULL; \ + } + + +/* + * Get information for a buffer through PyBuf_GetBuffer with the + * corresponding flags or'ed. Note that the python caller has to + * make sure that or'ing those flags actually makes sense. + * More information should probably be returned for future tests. + */ +static PyObject * +get_buffer_info(PyObject *NPY_UNUSED(self), PyObject *args) +{ + PyObject *buffer_obj, *pyflags; + PyObject *tmp, *buf_flag; + Py_buffer buffer; + PyObject *shape, *strides; + Py_ssize_t i, n; + int flag_matches; + int flags = 0; + + if (!PyArg_ParseTuple(args, "OO", &buffer_obj, &pyflags)) { + return NULL; + } + + n = PySequence_Length(pyflags); + if (n < 0) { + return NULL; + } + + for (i=0; i < n; i++) { + tmp = PySequence_GetItem(pyflags, i); + if (tmp == NULL) { + return NULL; + } + + GET_PYBUF_FLAG(SIMPLE); + GET_PYBUF_FLAG(WRITABLE); + GET_PYBUF_FLAG(STRIDES); + GET_PYBUF_FLAG(ND); + GET_PYBUF_FLAG(C_CONTIGUOUS); + GET_PYBUF_FLAG(F_CONTIGUOUS); + GET_PYBUF_FLAG(ANY_CONTIGUOUS); + GET_PYBUF_FLAG(INDIRECT); + GET_PYBUF_FLAG(FORMAT); + GET_PYBUF_FLAG(STRIDED); + GET_PYBUF_FLAG(STRIDED_RO); + GET_PYBUF_FLAG(RECORDS); + GET_PYBUF_FLAG(RECORDS_RO); + GET_PYBUF_FLAG(FULL); + GET_PYBUF_FLAG(FULL_RO); + GET_PYBUF_FLAG(CONTIG); + GET_PYBUF_FLAG(CONTIG_RO); + + Py_DECREF(tmp); + + /* One of the flags must match */ + PyErr_SetString(PyExc_ValueError, "invalid flag used."); + return NULL; + } + + if (PyObject_GetBuffer(buffer_obj, &buffer, flags) < 0) { + return NULL; + } + + if (buffer.shape == NULL) { + Py_INCREF(Py_None); + shape = Py_None; + } + else { + shape = PyTuple_New(buffer.ndim); + for (i=0; i < buffer.ndim; i++) { + PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(buffer.shape[i])); + } + } + + if (buffer.strides == NULL) { + Py_INCREF(Py_None); + strides = Py_None; + } + else { + strides = PyTuple_New(buffer.ndim); + for (i=0; i < buffer.ndim; i++) { + PyTuple_SET_ITEM(strides, i, PyLong_FromSsize_t(buffer.strides[i])); + } + } + + PyBuffer_Release(&buffer); + return Py_BuildValue("(NN)", shape, strides); +} + +#undef GET_PYBUF_FLAG + + +/* + * Test C-api level item getting. + */ +static PyObject * +array_indexing(PyObject *NPY_UNUSED(self), PyObject *args) +{ + int mode; + Py_ssize_t i; + PyObject *arr, *op = NULL; + + if (!PyArg_ParseTuple(args, "iOn|O", &mode, &arr, &i, &op)) { + return NULL; + } + + if (mode == 0) { + return PySequence_GetItem(arr, i); + } + if (mode == 1) { + if (PySequence_SetItem(arr, i, op) < 0) { + return NULL; + } + Py_RETURN_NONE; + } + + PyErr_SetString(PyExc_ValueError, + "invalid mode. 0: item 1: assign"); + return NULL; +} + +/* + * Test C-api PyArray_AsCArray item getter + */ +static PyObject * +test_as_c_array(PyObject *NPY_UNUSED(self), PyObject *args) +{ + PyArrayObject *array_obj; + npy_intp dims[3]; /* max 3-dim */ + npy_intp i=0, j=0, k=0; + npy_intp num_dims = 0; + PyArray_Descr *descr = NULL; + double *array1 = NULL; + double **array2 = NULL; + double ***array3 = NULL; + double temp = 9999; + + if (!PyArg_ParseTuple(args, "O!l|ll", + &PyArray_Type, &array_obj, + &i, &j, &k)) { + return NULL; + } + + if (NULL == array_obj) { + return NULL; + } + + num_dims = PyArray_NDIM(array_obj); + descr = PyArray_DESCR(array_obj); + + switch (num_dims) { + case 1: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void *) &array1, + dims, + 1, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 1D array"); + return NULL; + } + temp = array1[i]; + PyArray_Free((PyObject *) array_obj, (void *) array1); + break; + case 2: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void **) &array2, + dims, + 2, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 2D array"); + return NULL; + } + temp = array2[i][j]; + PyArray_Free((PyObject *) array_obj, (void *) array2); + break; + case 3: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void ***) &array3, + dims, + 3, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 3D array"); + return NULL; + } + temp = array3[i][j][k]; + PyArray_Free((PyObject *) array_obj, (void *) array3); + break; + default: + PyErr_SetString(PyExc_ValueError, "array.ndim not in [1, 3]"); + return NULL; + } + return Py_BuildValue("f", temp); +} + +/* + * Test nditer of too large arrays using remove axis, etc. + */ +static PyObject * +test_nditer_too_large(PyObject *NPY_UNUSED(self), PyObject *args) { + NpyIter *iter; + PyObject *array_tuple, *arr; + PyArrayObject *arrays[NPY_MAXARGS]; + npy_uint32 op_flags[NPY_MAXARGS]; + Py_ssize_t nop; + int i, axis, mode; + + npy_intp index[NPY_MAXARGS] = {0}; + char *msg; + + if (!PyArg_ParseTuple(args, "Oii", &array_tuple, &axis, &mode)) { + return NULL; + } + + if (!PyTuple_CheckExact(array_tuple)) { + PyErr_SetString(PyExc_ValueError, "tuple required as first argument"); + return NULL; + } + nop = PyTuple_Size(array_tuple); + if (nop > NPY_MAXARGS) { + PyErr_SetString(PyExc_ValueError, "tuple must be smaller then maxargs"); + return NULL; + } + + for (i=0; i < nop; i++) { + arr = PyTuple_GET_ITEM(array_tuple, i); + if (!PyArray_CheckExact(arr)) { + PyErr_SetString(PyExc_ValueError, "require base class ndarray"); + return NULL; + } + arrays[i] = (PyArrayObject *)arr; + op_flags[i] = NPY_ITER_READONLY; + } + + iter = NpyIter_MultiNew(nop, arrays, NPY_ITER_MULTI_INDEX | NPY_ITER_RANGED, + NPY_KEEPORDER, NPY_NO_CASTING, op_flags, NULL); + + if (iter == NULL) { + return NULL; + } + + /* Remove an axis (negative, do not remove any) */ + if (axis >= 0) { + if (!NpyIter_RemoveAxis(iter, axis)) { + goto fail; + } + } + + switch (mode) { + /* Test IterNext getting */ + case 0: + if (NpyIter_GetIterNext(iter, NULL) == NULL) { + goto fail; + } + break; + case 1: + if (NpyIter_GetIterNext(iter, &msg) == NULL) { + PyErr_SetString(PyExc_ValueError, msg); + goto fail; + } + break; + /* Test Multi Index removal */ + case 2: + if (!NpyIter_RemoveMultiIndex(iter)) { + goto fail; + } + break; + /* Test GotoMultiIndex (just 0 hardcoded) */ + case 3: + if (!NpyIter_GotoMultiIndex(iter, index)) { + goto fail; + } + break; + /* Test setting iterrange (hardcoded range of 0, 1) */ + case 4: + if (!NpyIter_ResetToIterIndexRange(iter, 0, 1, NULL)) { + goto fail; + } + break; + case 5: + if (!NpyIter_ResetToIterIndexRange(iter, 0, 1, &msg)) { + PyErr_SetString(PyExc_ValueError, msg); + goto fail; + } + break; + /* Do nothing */ + default: + break; + } + + NpyIter_Deallocate(iter); + Py_RETURN_NONE; + fail: + NpyIter_Deallocate(iter); + return NULL; +} + + +static PyObject * +array_solve_diophantine(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) +{ + PyObject *A = NULL; + PyObject *U = NULL; + Py_ssize_t b_input = 0; + Py_ssize_t max_work = -1; + int simplify = 0; + int require_ub_nontrivial = 0; + static char *kwlist[] = {"A", "U", "b", "max_work", "simplify", + "require_ub_nontrivial", NULL}; + + diophantine_term_t terms[2*NPY_MAXDIMS+2]; + npy_int64 x[2*NPY_MAXDIMS+2]; + npy_int64 b; + unsigned int nterms, j; + mem_overlap_t result = MEM_OVERLAP_YES; + PyObject *retval = NULL; + NPY_BEGIN_THREADS_DEF; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!n|nii", kwlist, + &PyTuple_Type, &A, + &PyTuple_Type, &U, + &b_input, &max_work, &simplify, + &require_ub_nontrivial)) { + return NULL; + } + + if (PyTuple_GET_SIZE(A) > (Py_ssize_t)ARRAY_SIZE(terms)) { + PyErr_SetString(PyExc_ValueError, "too many terms in equation"); + goto fail; + } + + nterms = PyTuple_GET_SIZE(A); + + if (PyTuple_GET_SIZE(U) != nterms) { + PyErr_SetString(PyExc_ValueError, "A, U must be tuples of equal length"); + goto fail; + } + + for (j = 0; j < nterms; ++j) { + terms[j].a = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(A, j)); + if (error_converting(terms[j].a)) { + goto fail; + } + terms[j].ub = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(U, j)); + if (error_converting(terms[j].ub)) { + goto fail; + } + } + + b = b_input; + + NPY_BEGIN_THREADS; + if (simplify && !require_ub_nontrivial) { + if (diophantine_simplify(&nterms, terms, b)) { + result = MEM_OVERLAP_OVERFLOW; + } + } + if (result == MEM_OVERLAP_YES) { + result = solve_diophantine(nterms, terms, b, max_work, require_ub_nontrivial, x); + } + NPY_END_THREADS; + + if (result == MEM_OVERLAP_YES) { + retval = PyTuple_New(nterms); + if (retval == NULL) { + goto fail; + } + + for (j = 0; j < nterms; ++j) { + PyObject *obj; +#if defined(NPY_PY3K) + obj = PyLong_FromSsize_t(x[j]); +#else + obj = PyInt_FromSsize_t(x[j]); +#endif + if (obj == NULL) { + goto fail; + } + PyTuple_SET_ITEM(retval, j, obj); + } + } + else if (result == MEM_OVERLAP_NO) { + retval = Py_None; + Py_INCREF(retval); + } + else if (result == MEM_OVERLAP_ERROR) { + PyErr_SetString(PyExc_ValueError, "Invalid arguments"); + } + else if (result == MEM_OVERLAP_OVERFLOW) { + PyErr_SetString(PyExc_OverflowError, "Integer overflow"); + } + else if (result == MEM_OVERLAP_TOO_HARD) { + PyErr_SetString(PyExc_RuntimeError, "Too much work done"); + } + else { + PyErr_SetString(PyExc_RuntimeError, "Unknown error"); + } + + return retval; + +fail: + Py_XDECREF(retval); + return NULL; +} + + +static PyObject * +array_internal_overlap(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) +{ + PyArrayObject * self = NULL; + static char *kwlist[] = {"self", "max_work", NULL}; + + mem_overlap_t result; + Py_ssize_t max_work = NPY_MAY_SHARE_EXACT; + NPY_BEGIN_THREADS_DEF; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|n", kwlist, + PyArray_Converter, &self, + &max_work)) { + return NULL; + } + + if (max_work < -2) { + PyErr_SetString(PyExc_ValueError, "Invalid value for max_work"); + goto fail; + } + + NPY_BEGIN_THREADS; + result = solve_may_have_internal_overlap(self, max_work); + NPY_END_THREADS; + + Py_XDECREF(self); + + if (result == MEM_OVERLAP_NO) { + Py_RETURN_FALSE; + } + else if (result == MEM_OVERLAP_YES) { + Py_RETURN_TRUE; + } + else if (result == MEM_OVERLAP_OVERFLOW) { + PyErr_SetString(PyExc_OverflowError, + "Integer overflow in computing overlap"); + return NULL; + } + else if (result == MEM_OVERLAP_TOO_HARD) { + PyErr_SetString(PyExc_ValueError, + "Exceeded max_work"); + return NULL; + } + else { + /* Doesn't happen usually */ + PyErr_SetString(PyExc_RuntimeError, + "Error in computing overlap"); + return NULL; + } + +fail: + Py_XDECREF(self); + return NULL; +} + + +static PyObject * +pylong_from_int128(npy_extint128_t value) +{ + PyObject *val_64 = NULL, *val = NULL, *tmp = NULL, *tmp2 = NULL; + + val_64 = PyLong_FromLong(64); + if (val_64 == NULL) { + goto fail; + } + + val = PyLong_FromUnsignedLongLong(value.hi); + if (val == NULL) { + goto fail; + } + + tmp = PyNumber_Lshift(val, val_64); + if (tmp == NULL) { + goto fail; + } + + Py_DECREF(val); + val = tmp; + + tmp = PyLong_FromUnsignedLongLong(value.lo); + if (tmp == NULL) { + goto fail; + } + + tmp2 = PyNumber_Or(val, tmp); + if (tmp2 == NULL) { + goto fail; + } + + Py_DECREF(val); + Py_DECREF(tmp); + + val = NULL; + tmp = NULL; + + if (value.sign < 0) { + val = PyNumber_Negative(tmp2); + if (val == NULL) { + goto fail; + } + Py_DECREF(tmp2); + return val; + } + else { + val = tmp2; + } + return val; + +fail: + Py_XDECREF(val_64); + Py_XDECREF(tmp); + Py_XDECREF(tmp2); + Py_XDECREF(val); + return NULL; +} + + +static int +int128_from_pylong(PyObject *obj, npy_extint128_t *result) +{ + PyObject *long_obj = NULL, *val_64 = NULL, *val_0 = NULL, + *mask_64 = NULL, *max_128 = NULL, *hi_bits = NULL, + *lo_bits = NULL, *tmp = NULL; + int cmp; + int negative_zero = 0; + + if (PyBool_Check(obj)) { + /* False means negative zero */ + negative_zero = 1; + } + + long_obj = PyObject_CallFunction((PyObject*)&PyLong_Type, "O", obj); + if (long_obj == NULL) { + goto fail; + } + + val_0 = PyLong_FromLong(0); + if (val_0 == NULL) { + goto fail; + } + + val_64 = PyLong_FromLong(64); + if (val_64 == NULL) { + goto fail; + } + + mask_64 = PyLong_FromUnsignedLongLong(0xffffffffffffffffULL); + if (mask_64 == NULL) { + goto fail; + } + + tmp = PyNumber_Lshift(mask_64, val_64); + if (tmp == NULL) { + goto fail; + } + max_128 = PyNumber_Or(tmp, mask_64); + if (max_128 == NULL) { + goto fail; + } + Py_DECREF(tmp); + tmp = NULL; + + cmp = PyObject_RichCompareBool(long_obj, val_0, Py_LT); + if (cmp == -1) { + goto fail; + } + else if (cmp == 1) { + tmp = PyNumber_Negative(long_obj); + if (tmp == NULL) { + goto fail; + } + Py_DECREF(long_obj); + long_obj = tmp; + tmp = NULL; + result->sign = -1; + } + else { + result->sign = 1; + } + + cmp = PyObject_RichCompareBool(long_obj, max_128, Py_GT); + if (cmp == 1) { + PyErr_SetString(PyExc_OverflowError, ""); + goto fail; + } + else if (cmp == -1) { + goto fail; + } + + hi_bits = PyNumber_Rshift(long_obj, val_64); + if (hi_bits == NULL) { + goto fail; + } + + lo_bits = PyNumber_And(long_obj, mask_64); + if (lo_bits == NULL) { + goto fail; + } + + result->hi = PyLong_AsUnsignedLongLong(hi_bits); + if (result->hi == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { + goto fail; + } + + result->lo = PyLong_AsUnsignedLongLong(lo_bits); + if (result->lo == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { + goto fail; + } + + if (negative_zero && result->hi == 0 && result->lo == 0) { + result->sign = -1; + } + + Py_XDECREF(long_obj); + Py_XDECREF(val_64); + Py_XDECREF(val_0); + Py_XDECREF(mask_64); + Py_XDECREF(max_128); + Py_XDECREF(hi_bits); + Py_XDECREF(lo_bits); + Py_XDECREF(tmp); + return 0; + +fail: + Py_XDECREF(long_obj); + Py_XDECREF(val_64); + Py_XDECREF(val_0); + Py_XDECREF(mask_64); + Py_XDECREF(max_128); + Py_XDECREF(hi_bits); + Py_XDECREF(lo_bits); + Py_XDECREF(tmp); + return -1; +} + + +static PyObject * +extint_safe_binop(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a, b, c; + int op; + char overflow = 0; + if (!PyArg_ParseTuple(args, "LLi", &a, &b, &op)) { + return NULL; + } + if (op == 1) { + c = safe_add(a, b, &overflow); + } + else if (op == 2) { + c = safe_sub(a, b, &overflow); + } + else if (op == 3) { + c = safe_mul(a, b, &overflow); + } + else { + PyErr_SetString(PyExc_ValueError, "invalid op"); + return NULL; + } + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return PyLong_FromLongLong(c); +} + + +static PyObject * +extint_to_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a; + if (!PyArg_ParseTuple(args, "L", &a)) { + return NULL; + } + return pylong_from_int128(to_128(a)); +} + + +static PyObject * +extint_to_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a; + PY_LONG_LONG r; + char overflow = 0; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + r = to_64(a, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return PyLong_FromLongLong(r); +} + + +static PyObject * +extint_mul_64_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a, b; + npy_extint128_t c; + if (!PyArg_ParseTuple(args, "LL", &a, &b)) { + return NULL; + } + c = mul_64_64(a, b); + return pylong_from_int128(c); +} + + +static PyObject * +extint_add_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b, c; + char overflow = 0; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + c = add_128(a, b, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return pylong_from_int128(c); +} + + +static PyObject * +extint_sub_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b, c; + char overflow = 0; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + c = sub_128(a, b, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return pylong_from_int128(c); +} + + +static PyObject * +extint_neg_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = neg_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_shl_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = shl_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_shr_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = shr_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_gt_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + if (gt_128(a, b)) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } +} + + +static PyObject * +extint_divmod_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *ret = NULL, *tmp = NULL; + npy_extint128_t a, c; + PY_LONG_LONG b; + npy_int64 mod; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + goto fail; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + goto fail; + } + if (int128_from_pylong(a_obj, &a)) { + goto fail; + } + + c = divmod_128_64(a, b, &mod); + + ret = PyTuple_New(2); + + tmp = pylong_from_int128(c); + if (tmp == NULL) { + goto fail; + } + PyTuple_SET_ITEM(ret, 0, tmp); + + tmp = PyLong_FromLongLong(mod); + if (tmp == NULL) { + goto fail; + } + PyTuple_SET_ITEM(ret, 1, tmp); + return ret; + +fail: + Py_XDECREF(ret); + Py_XDECREF(tmp); + return NULL; +} + + +static PyObject * +extint_floordiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, c; + PY_LONG_LONG b; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + return NULL; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + c = floordiv_128_64(a, b); + return pylong_from_int128(c); +} + + +static PyObject * +extint_ceildiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, c; + PY_LONG_LONG b; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + return NULL; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + c = ceildiv_128_64(a, b); + return pylong_from_int128(c); +} + + +static char get_fpu_mode_doc[] = ( + "get_fpu_mode()\n" + "\n" + "Get the current FPU control word, in a platform-dependent format.\n" + "Returns None if not implemented on current platform."); + +static PyObject * +get_fpu_mode(PyObject *NPY_UNUSED(self), PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + +#if defined(_MSC_VER) + { + unsigned int result = 0; + result = _controlfp(0, 0); + return PyLong_FromLongLong(result); + } +#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) + { + unsigned short cw = 0; + __asm__("fstcw %w0" : "=m" (cw)); + return PyLong_FromLongLong(cw); + } +#else + Py_RETURN_NONE; +#endif +} + +/* + * npymath wrappers + */ + +/**begin repeat + * #name = cabs, carg# + */ + +/**begin repeat1 + * #itype = npy_cfloat, npy_cdouble, npy_clongdouble# + * #ITYPE = NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE# + * #otype = npy_float, npy_double, npy_longdouble# + * #OTYPE = NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE# + * #suffix= f, , l# + */ + +static PyObject * +call_npy_@name@@suffix@(PyObject *NPY_UNUSED(self), PyObject *args) +{ + PyObject *z_py = NULL, *z_arr = NULL, *w_arr = NULL; + + if (!PyArg_ParseTuple(args, "O", &z_py)) { + return NULL; + } + + z_arr = PyArray_FROMANY(z_py, @ITYPE@, 0, 0, NPY_ARRAY_CARRAY_RO); + if (z_arr == NULL) { + return NULL; + } + + w_arr = PyArray_SimpleNew(0, NULL, @OTYPE@); + if (w_arr == NULL) { + Py_DECREF(z_arr); + return NULL; + } + + *(@otype@*)PyArray_DATA((PyArrayObject *)w_arr) = + npy_@name@@suffix@(*(@itype@*)PyArray_DATA((PyArrayObject *)z_arr)); + + Py_DECREF(z_arr); + return w_arr; +} + +/**end repeat1**/ + +/**end repeat**/ + +/**begin repeat + * #name = log10, cosh, sinh, tan, tanh# + */ + +/**begin repeat1 + * #type = npy_float, npy_double, npy_longdouble# + * #TYPE = NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE# + * #suffix= f, , l# + */ + +static PyObject * +call_npy_@name@@suffix@(PyObject *NPY_UNUSED(self), PyObject *args) +{ + PyObject *z_py = NULL, *z_arr = NULL, *w_arr = NULL; + + if (!PyArg_ParseTuple(args, "O", &z_py)) { + return NULL; + } + + z_arr = PyArray_FROMANY(z_py, @TYPE@, 0, 0, NPY_ARRAY_CARRAY_RO); + if (z_arr == NULL) { + return NULL; + } + + w_arr = PyArray_SimpleNew(0, NULL, @TYPE@); + if (w_arr == NULL) { + Py_DECREF(z_arr); + return NULL; + } + + *(@type@*)PyArray_DATA((PyArrayObject *)w_arr) = + npy_@name@@suffix@(*(@type@*)PyArray_DATA((PyArrayObject *)z_arr)); + + Py_DECREF(z_arr); + return w_arr; +} + +/**end repeat1**/ + +/**end repeat**/ + + +static PyMethodDef Multiarray_TestsMethods[] = { + {"IsPythonScalar", + IsPythonScalar, + METH_VARARGS, NULL}, + {"test_neighborhood_iterator", + test_neighborhood_iterator, + METH_VARARGS, NULL}, + {"test_neighborhood_iterator_oob", + test_neighborhood_iterator_oob, + METH_VARARGS, NULL}, + {"test_pydatamem_seteventhook_start", + test_pydatamem_seteventhook_start, + METH_NOARGS, NULL}, + {"test_pydatamem_seteventhook_end", + test_pydatamem_seteventhook_end, + METH_NOARGS, NULL}, + {"test_inplace_increment", + inplace_increment, + METH_VARARGS, NULL}, + {"incref_elide", + incref_elide, + METH_VARARGS, NULL}, + {"incref_elide_l", + incref_elide_l, + METH_VARARGS, NULL}, + {"npy_char_deprecation", + npy_char_deprecation, + METH_NOARGS, NULL}, + {"npy_updateifcopy_deprecation", + npy_updateifcopy_deprecation, + METH_O, NULL}, + {"npy_create_writebackifcopy", + npy_create_writebackifcopy, + METH_O, NULL}, + {"npy_resolve", + npy_resolve, + METH_O, NULL}, +#if !defined(NPY_PY3K) + {"test_int_subclass", + int_subclass, + METH_VARARGS, NULL}, +#endif + {"get_buffer_info", + get_buffer_info, + METH_VARARGS, NULL}, + {"array_indexing", + array_indexing, + METH_VARARGS, NULL}, + {"test_as_c_array", + test_as_c_array, + METH_VARARGS, NULL}, + {"test_nditer_too_large", + test_nditer_too_large, + METH_VARARGS, NULL}, + {"solve_diophantine", + (PyCFunction)array_solve_diophantine, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"internal_overlap", + (PyCFunction)array_internal_overlap, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"extint_safe_binop", + extint_safe_binop, + METH_VARARGS, NULL}, + {"extint_to_128", + extint_to_128, + METH_VARARGS, NULL}, + {"extint_to_64", + extint_to_64, + METH_VARARGS, NULL}, + {"extint_mul_64_64", + extint_mul_64_64, + METH_VARARGS, NULL}, + {"extint_add_128", + extint_add_128, + METH_VARARGS, NULL}, + {"extint_sub_128", + extint_sub_128, + METH_VARARGS, NULL}, + {"extint_neg_128", + extint_neg_128, + METH_VARARGS, NULL}, + {"extint_shl_128", + extint_shl_128, + METH_VARARGS, NULL}, + {"extint_shr_128", + extint_shr_128, + METH_VARARGS, NULL}, + {"extint_gt_128", + extint_gt_128, + METH_VARARGS, NULL}, + {"extint_divmod_128_64", + extint_divmod_128_64, + METH_VARARGS, NULL}, + {"extint_floordiv_128_64", + extint_floordiv_128_64, + METH_VARARGS, NULL}, + {"extint_ceildiv_128_64", + extint_ceildiv_128_64, + METH_VARARGS, NULL}, + {"get_fpu_mode", + get_fpu_mode, + METH_VARARGS, get_fpu_mode_doc}, +/**begin repeat + * #name = cabs, carg# + */ + +/**begin repeat1 + * #suffix = f, , l# + */ + {"npy_@name@@suffix@", + call_npy_@name@@suffix@, + METH_VARARGS, NULL}, +/**end repeat1**/ + +/**end repeat**/ + +/**begin repeat + * #name = log10, cosh, sinh, tan, tanh# + */ + +/**begin repeat1 + * #suffix= f, , l# + */ + {"npy_@name@@suffix@", + call_npy_@name@@suffix@, + METH_VARARGS, NULL}, +/**end repeat1**/ + +/**end repeat**/ + + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_multiarray_tests", + NULL, + -1, + Multiarray_TestsMethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +#if defined(NPY_PY3K) +#define RETVAL m +PyMODINIT_FUNC PyInit__multiarray_tests(void) +#else +#define RETVAL +PyMODINIT_FUNC +init_multiarray_tests(void) +#endif +{ + PyObject *m; + +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_multiarray_tests", Multiarray_TestsMethods); +#endif + if (m == NULL) { + return RETVAL; + } + import_array(); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "cannot load _multiarray_tests module."); + } + return RETVAL; +} diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src deleted file mode 100644 index d63349560..000000000 --- a/numpy/core/src/multiarray/multiarray_tests.c.src +++ /dev/null @@ -1,1906 +0,0 @@ -/* -*-c-*- */ -#define NPY_NO_DEPRECATED_API NPY_API_VERSION -#include -#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */ -#include "numpy/arrayobject.h" -#include "numpy/npy_math.h" -#include "mem_overlap.h" -#include "npy_extint128.h" -#include "common.h" - -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) - -/* test PyArray_IsPythonScalar, before including private py3 compat header */ -static PyObject * -IsPythonScalar(PyObject * dummy, PyObject *args) -{ - PyObject *arg = NULL; - if (!PyArg_ParseTuple(args, "O", &arg)) { - return NULL; - } - if (PyArray_IsPythonScalar(arg)) { - Py_RETURN_TRUE; - } - else { - Py_RETURN_FALSE; - } -} - -#include "npy_pycompat.h" - -/* - * TODO: - * - Handle mode - */ - -/**begin repeat - * #name = double, int# - * #type = npy_double, npy_int# - * #typenum = NPY_DOUBLE, NPY_INT# - */ -static int copy_@name@(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx, - npy_intp *bounds, - PyObject **out) -{ - npy_intp i, j; - @type@ *ptr; - npy_intp odims[NPY_MAXDIMS]; - PyArrayObject *aout; - - /* - * For each point in itx, copy the current neighborhood into an array which - * is appended at the output list - */ - for (i = 0; i < itx->size; ++i) { - PyArrayNeighborhoodIter_Reset(niterx); - - for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { - odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; - } - aout = (PyArrayObject*)PyArray_SimpleNew( - PyArray_NDIM(itx->ao), odims, @typenum@); - if (aout == NULL) { - return -1; - } - - ptr = (@type@*)PyArray_DATA(aout); - - for (j = 0; j < niterx->size; ++j) { - *ptr = *((@type@*)niterx->dataptr); - PyArrayNeighborhoodIter_Next(niterx); - ptr += 1; - } - - PyList_Append(*out, (PyObject*)aout); - Py_DECREF(aout); - PyArray_ITER_NEXT(itx); - } - - return 0; -} -/**end repeat**/ - -static int copy_object(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx, - npy_intp *bounds, - PyObject **out) -{ - npy_intp i, j; - npy_intp odims[NPY_MAXDIMS]; - PyArrayObject *aout; - PyArray_CopySwapFunc *copyswap = PyArray_DESCR(itx->ao)->f->copyswap; - npy_int itemsize = PyArray_ITEMSIZE(itx->ao); - - /* - * For each point in itx, copy the current neighborhood into an array which - * is appended at the output list - */ - for (i = 0; i < itx->size; ++i) { - PyArrayNeighborhoodIter_Reset(niterx); - - for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { - odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; - } - aout = (PyArrayObject*)PyArray_SimpleNew(PyArray_NDIM(itx->ao), odims, NPY_OBJECT); - if (aout == NULL) { - return -1; - } - - for (j = 0; j < niterx->size; ++j) { - copyswap(PyArray_BYTES(aout) + j * itemsize, niterx->dataptr, 0, NULL); - PyArrayNeighborhoodIter_Next(niterx); - } - - PyList_Append(*out, (PyObject*)aout); - Py_DECREF(aout); - PyArray_ITER_NEXT(itx); - } - - return 0; -} - -static PyObject* -test_neighborhood_iterator(PyObject* NPY_UNUSED(self), PyObject* args) -{ - PyObject *x, *fill, *out, *b; - PyArrayObject *ax, *afill; - PyArrayIterObject *itx; - int i, typenum, mode, st; - npy_intp bounds[NPY_MAXDIMS*2]; - PyArrayNeighborhoodIterObject *niterx; - - if (!PyArg_ParseTuple(args, "OOOi", &x, &b, &fill, &mode)) { - return NULL; - } - - if (!PySequence_Check(b)) { - return NULL; - } - - typenum = PyArray_ObjectType(x, 0); - typenum = PyArray_ObjectType(fill, typenum); - - ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10); - if (ax == NULL) { - return NULL; - } - if (PySequence_Size(b) != 2 * PyArray_NDIM(ax)) { - PyErr_SetString(PyExc_ValueError, - "bounds sequence size not compatible with x input"); - goto clean_ax; - } - - out = PyList_New(0); - if (out == NULL) { - goto clean_ax; - } - - itx = (PyArrayIterObject*)PyArray_IterNew(x); - if (itx == NULL) { - goto clean_out; - } - - /* Compute boundaries for the neighborhood iterator */ - for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { - PyObject* bound; - bound = PySequence_GetItem(b, i); - if (bound == NULL) { - goto clean_itx; - } - if (!PyInt_Check(bound)) { - PyErr_SetString(PyExc_ValueError, - "bound not long"); - Py_DECREF(bound); - goto clean_itx; - } - bounds[i] = PyInt_AsLong(bound); - Py_DECREF(bound); - } - - /* Create the neighborhood iterator */ - afill = NULL; - if (mode == NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING) { - afill = (PyArrayObject *)PyArray_FromObject(fill, typenum, 0, 0); - if (afill == NULL) { - goto clean_itx; - } - } - - niterx = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( - (PyArrayIterObject*)itx, bounds, mode, afill); - if (niterx == NULL) { - goto clean_afill; - } - - switch (typenum) { - case NPY_OBJECT: - st = copy_object(itx, niterx, bounds, &out); - break; - case NPY_INT: - st = copy_int(itx, niterx, bounds, &out); - break; - case NPY_DOUBLE: - st = copy_double(itx, niterx, bounds, &out); - break; - default: - PyErr_SetString(PyExc_ValueError, - "Type not supported"); - goto clean_niterx; - } - - if (st) { - goto clean_niterx; - } - - Py_DECREF(niterx); - Py_XDECREF(afill); - Py_DECREF(itx); - - Py_DECREF(ax); - - return out; - -clean_niterx: - Py_DECREF(niterx); -clean_afill: - Py_XDECREF(afill); -clean_itx: - Py_DECREF(itx); -clean_out: - Py_DECREF(out); -clean_ax: - Py_DECREF(ax); - return NULL; -} - -static int -copy_double_double(PyArrayNeighborhoodIterObject *itx, - PyArrayNeighborhoodIterObject *niterx, - npy_intp *bounds, - PyObject **out) -{ - npy_intp i, j; - double *ptr; - npy_intp odims[NPY_MAXDIMS]; - PyArrayObject *aout; - - /* - * For each point in itx, copy the current neighborhood into an array which - * is appended at the output list - */ - PyArrayNeighborhoodIter_Reset(itx); - for (i = 0; i < itx->size; ++i) { - for (j = 0; j < PyArray_NDIM(itx->ao); ++j) { - odims[j] = bounds[2 * j + 1] - bounds[2 * j] + 1; - } - aout = (PyArrayObject*)PyArray_SimpleNew( - PyArray_NDIM(itx->ao), odims, NPY_DOUBLE); - if (aout == NULL) { - return -1; - } - - ptr = (double*)PyArray_DATA(aout); - - PyArrayNeighborhoodIter_Reset(niterx); - for (j = 0; j < niterx->size; ++j) { - *ptr = *((double*)niterx->dataptr); - ptr += 1; - PyArrayNeighborhoodIter_Next(niterx); - } - PyList_Append(*out, (PyObject*)aout); - Py_DECREF(aout); - PyArrayNeighborhoodIter_Next(itx); - } - return 0; -} - -static PyObject* -test_neighborhood_iterator_oob(PyObject* NPY_UNUSED(self), PyObject* args) -{ - PyObject *x, *out, *b1, *b2; - PyArrayObject *ax; - PyArrayIterObject *itx; - int i, typenum, mode1, mode2, st; - npy_intp bounds[NPY_MAXDIMS*2]; - PyArrayNeighborhoodIterObject *niterx1, *niterx2; - - if (!PyArg_ParseTuple(args, "OOiOi", &x, &b1, &mode1, &b2, &mode2)) { - return NULL; - } - - if (!PySequence_Check(b1) || !PySequence_Check(b2)) { - return NULL; - } - - typenum = PyArray_ObjectType(x, 0); - - ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10); - if (ax == NULL) { - return NULL; - } - if (PySequence_Size(b1) != 2 * PyArray_NDIM(ax)) { - PyErr_SetString(PyExc_ValueError, - "bounds sequence 1 size not compatible with x input"); - goto clean_ax; - } - if (PySequence_Size(b2) != 2 * PyArray_NDIM(ax)) { - PyErr_SetString(PyExc_ValueError, - "bounds sequence 2 size not compatible with x input"); - goto clean_ax; - } - - out = PyList_New(0); - if (out == NULL) { - goto clean_ax; - } - - itx = (PyArrayIterObject*)PyArray_IterNew(x); - if (itx == NULL) { - goto clean_out; - } - - /* Compute boundaries for the neighborhood iterator */ - for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { - PyObject* bound; - bound = PySequence_GetItem(b1, i); - if (bound == NULL) { - goto clean_itx; - } - if (!PyInt_Check(bound)) { - PyErr_SetString(PyExc_ValueError, - "bound not long"); - Py_DECREF(bound); - goto clean_itx; - } - bounds[i] = PyInt_AsLong(bound); - Py_DECREF(bound); - } - - /* Create the neighborhood iterator */ - niterx1 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( - (PyArrayIterObject*)itx, bounds, - mode1, NULL); - if (niterx1 == NULL) { - goto clean_out; - } - - for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { - PyObject* bound; - bound = PySequence_GetItem(b2, i); - if (bound == NULL) { - goto clean_itx; - } - if (!PyInt_Check(bound)) { - PyErr_SetString(PyExc_ValueError, - "bound not long"); - Py_DECREF(bound); - goto clean_itx; - } - bounds[i] = PyInt_AsLong(bound); - Py_DECREF(bound); - } - - niterx2 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew( - (PyArrayIterObject*)niterx1, bounds, - mode2, NULL); - if (niterx1 == NULL) { - goto clean_niterx1; - } - - switch (typenum) { - case NPY_DOUBLE: - st = copy_double_double(niterx1, niterx2, bounds, &out); - break; - default: - PyErr_SetString(PyExc_ValueError, - "Type not supported"); - goto clean_niterx2; - } - - if (st) { - goto clean_niterx2; - } - - Py_DECREF(niterx2); - Py_DECREF(niterx1); - Py_DECREF(itx); - Py_DECREF(ax); - return out; - -clean_niterx2: - Py_DECREF(niterx2); -clean_niterx1: - Py_DECREF(niterx1); -clean_itx: - Py_DECREF(itx); -clean_out: - Py_DECREF(out); -clean_ax: - Py_DECREF(ax); - return NULL; -} - -/* PyDataMem_SetHook tests */ -static int malloc_free_counts[2]; -static PyDataMem_EventHookFunc *old_hook = NULL; -static void *old_data; - -static void test_hook(void *old, void *new, size_t size, void *user_data) -{ - int* counters = (int *) user_data; - if (old == NULL) { - counters[0]++; /* malloc counter */ - } - if (size == 0) { - counters[1]++; /* free counter */ - } -} - -static PyObject* -test_pydatamem_seteventhook_start(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) -{ - malloc_free_counts[0] = malloc_free_counts[1] = 0; - old_hook = PyDataMem_SetEventHook(test_hook, (void *) malloc_free_counts, &old_data); - Py_RETURN_NONE; -} - -static PyObject* -test_pydatamem_seteventhook_end(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) -{ - PyDataMem_EventHookFunc *my_hook; - void *my_data; - - my_hook = PyDataMem_SetEventHook(old_hook, old_data, &my_data); - if ((my_hook != test_hook) || (my_data != (void *) malloc_free_counts)) { - PyErr_SetString(PyExc_ValueError, - "hook/data was not the expected test hook"); - return NULL; - } - - if (malloc_free_counts[0] == 0) { - PyErr_SetString(PyExc_ValueError, - "malloc count is zero after test"); - return NULL; - } - if (malloc_free_counts[1] == 0) { - PyErr_SetString(PyExc_ValueError, - "free count is zero after test"); - return NULL; - } - - Py_RETURN_NONE; -} - - -typedef void (*inplace_map_binop)(PyArrayMapIterObject *, PyArrayIterObject *); - -static void npy_float64_inplace_add(PyArrayMapIterObject *mit, PyArrayIterObject *it) -{ - int index = mit->size; - while (index--) { - ((npy_float64*)mit->dataptr)[0] = ((npy_float64*)mit->dataptr)[0] + ((npy_float64*)it->dataptr)[0]; - - PyArray_MapIterNext(mit); - PyArray_ITER_NEXT(it); - } -} - -inplace_map_binop addition_funcs[] = { -npy_float64_inplace_add, -NULL}; - -int type_numbers[] = { -NPY_FLOAT64, --1000}; - - - -static int -map_increment(PyArrayMapIterObject *mit, PyObject *op, inplace_map_binop add_inplace) -{ - PyArrayObject *arr = NULL; - PyArrayIterObject *it; - PyArray_Descr *descr; - - if (mit->ait == NULL) { - return -1; - } - descr = PyArray_DESCR(mit->ait->ao); - Py_INCREF(descr); - arr = (PyArrayObject *)PyArray_FromAny(op, descr, - 0, 0, NPY_ARRAY_FORCECAST, NULL); - if (arr == NULL) { - return -1; - } - - if ((mit->subspace != NULL) && (mit->consec)) { - PyArray_MapIterSwapAxes(mit, (PyArrayObject **)&arr, 0); - if (arr == NULL) { - return -1; - } - } - - if ((it = (PyArrayIterObject *)\ - PyArray_BroadcastToShape((PyObject *)arr, mit->dimensions, - mit->nd)) == NULL) { - Py_DECREF(arr); - - return -1; - } - - (*add_inplace)(mit, it); - - Py_DECREF(arr); - Py_DECREF(it); - return 0; -} - - -static PyObject * -inplace_increment(PyObject *dummy, PyObject *args) -{ - PyObject *arg_a = NULL, *index=NULL, *inc=NULL; - PyArrayObject *a; - inplace_map_binop add_inplace = NULL; - int type_number = -1; - int i =0; - PyArrayMapIterObject * mit; - - if (!PyArg_ParseTuple(args, "OOO", &arg_a, &index, - &inc)) { - return NULL; - } - if (!PyArray_Check(arg_a)) { - PyErr_SetString(PyExc_ValueError, "needs an ndarray as first argument"); - return NULL; - } - a = (PyArrayObject *) arg_a; - - if (PyArray_FailUnlessWriteable(a, "input/output array") < 0) { - return NULL; - } - - if (PyArray_NDIM(a) == 0) { - PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed."); - return NULL; - } - type_number = PyArray_TYPE(a); - - while (type_numbers[i] >= 0 && addition_funcs[i] != NULL){ - if (type_number == type_numbers[i]) { - add_inplace = addition_funcs[i]; - break; - } - i++ ; - } - - if (add_inplace == NULL) { - PyErr_SetString(PyExc_TypeError, "unsupported type for a"); - return NULL; - } - - mit = (PyArrayMapIterObject *) PyArray_MapIterArray(a, index); - if (mit == NULL) { - goto fail; - } - - if (map_increment(mit, inc, add_inplace) != 0) { - goto fail; - } - - Py_DECREF(mit); - - Py_RETURN_NONE; - -fail: - Py_XDECREF(mit); - - return NULL; -} - -/* check no elison for avoided increfs */ -static PyObject * -incref_elide(PyObject *dummy, PyObject *args) -{ - PyObject *arg = NULL, *res, *tup; - if (!PyArg_ParseTuple(args, "O", &arg)) { - return NULL; - } - - /* refcount 1 array but should not be elided */ - arg = PyArray_NewCopy((PyArrayObject*)arg, NPY_KEEPORDER); - res = PyNumber_Add(arg, arg); - - /* return original copy, should be equal to input */ - tup = PyTuple_Pack(2, arg, res); - Py_DECREF(arg); - Py_DECREF(res); - return tup; -} - -/* check no elison for get from list without incref */ -static PyObject * -incref_elide_l(PyObject *dummy, PyObject *args) -{ - PyObject *arg = NULL, *r, *res; - if (!PyArg_ParseTuple(args, "O", &arg)) { - return NULL; - } - /* get item without increasing refcount, item may still be on the python - * stack but above the inaccessible top */ - r = PyList_GetItem(arg, 4); - res = PyNumber_Add(r, r); - - return res; -} - -/* used to test NPY_CHAR usage emits deprecation warning */ -static PyObject* -npy_char_deprecation(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) -{ - PyArray_Descr * descr = PyArray_DescrFromType(NPY_CHAR); - return (PyObject *)descr; -} - -/* used to test UPDATEIFCOPY usage emits deprecation warning */ -static PyObject* -npy_updateifcopy_deprecation(PyObject* NPY_UNUSED(self), PyObject* args) -{ - int flags; - PyObject* array; - if (!PyArray_Check(args)) { - PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); - return NULL; - } - flags = NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY; - array = PyArray_FromArray((PyArrayObject*)args, NULL, flags); - if (array == NULL) - return NULL; - PyArray_ResolveWritebackIfCopy((PyArrayObject*)array); - Py_DECREF(array); - Py_RETURN_NONE; -} - -/* used to create array with WRITEBACKIFCOPY flag */ -static PyObject* -npy_create_writebackifcopy(PyObject* NPY_UNUSED(self), PyObject* args) -{ - int flags; - PyObject* array; - if (!PyArray_Check(args)) { - PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); - return NULL; - } - flags = NPY_ARRAY_CARRAY | NPY_ARRAY_WRITEBACKIFCOPY; - array = PyArray_FromArray((PyArrayObject*)args, NULL, flags); - if (array == NULL) - return NULL; - return array; -} - -/* resolve WRITEBACKIFCOPY */ -static PyObject* -npy_resolve(PyObject* NPY_UNUSED(self), PyObject* args) -{ - if (!PyArray_Check(args)) { - PyErr_SetString(PyExc_TypeError, "test needs ndarray input"); - return NULL; - } - PyArray_ResolveWritebackIfCopy((PyArrayObject*)args); - Py_RETURN_NONE; -} - -#if !defined(NPY_PY3K) -static PyObject * -int_subclass(PyObject *dummy, PyObject *args) -{ - - PyObject *result = NULL; - PyObject *scalar_object = NULL; - - if (!PyArg_UnpackTuple(args, "test_int_subclass", 1, 1, &scalar_object)) - return NULL; - - if (PyInt_Check(scalar_object)) - result = Py_True; - else - result = Py_False; - - Py_INCREF(result); - - return result; - -} -#endif - - -/* - * Create python string from a FLAG and or the corresponding PyBuf flag - * for the use in get_buffer_info. - */ -#define GET_PYBUF_FLAG(FLAG) \ - buf_flag = PyUnicode_FromString(#FLAG); \ - flag_matches = PyObject_RichCompareBool(buf_flag, tmp, Py_EQ); \ - Py_DECREF(buf_flag); \ - if (flag_matches == 1) { \ - Py_DECREF(tmp); \ - flags |= PyBUF_##FLAG; \ - continue; \ - } \ - else if (flag_matches == -1) { \ - Py_DECREF(tmp); \ - return NULL; \ - } - - -/* - * Get information for a buffer through PyBuf_GetBuffer with the - * corresponding flags or'ed. Note that the python caller has to - * make sure that or'ing those flags actually makes sense. - * More information should probably be returned for future tests. - */ -static PyObject * -get_buffer_info(PyObject *NPY_UNUSED(self), PyObject *args) -{ - PyObject *buffer_obj, *pyflags; - PyObject *tmp, *buf_flag; - Py_buffer buffer; - PyObject *shape, *strides; - Py_ssize_t i, n; - int flag_matches; - int flags = 0; - - if (!PyArg_ParseTuple(args, "OO", &buffer_obj, &pyflags)) { - return NULL; - } - - n = PySequence_Length(pyflags); - if (n < 0) { - return NULL; - } - - for (i=0; i < n; i++) { - tmp = PySequence_GetItem(pyflags, i); - if (tmp == NULL) { - return NULL; - } - - GET_PYBUF_FLAG(SIMPLE); - GET_PYBUF_FLAG(WRITABLE); - GET_PYBUF_FLAG(STRIDES); - GET_PYBUF_FLAG(ND); - GET_PYBUF_FLAG(C_CONTIGUOUS); - GET_PYBUF_FLAG(F_CONTIGUOUS); - GET_PYBUF_FLAG(ANY_CONTIGUOUS); - GET_PYBUF_FLAG(INDIRECT); - GET_PYBUF_FLAG(FORMAT); - GET_PYBUF_FLAG(STRIDED); - GET_PYBUF_FLAG(STRIDED_RO); - GET_PYBUF_FLAG(RECORDS); - GET_PYBUF_FLAG(RECORDS_RO); - GET_PYBUF_FLAG(FULL); - GET_PYBUF_FLAG(FULL_RO); - GET_PYBUF_FLAG(CONTIG); - GET_PYBUF_FLAG(CONTIG_RO); - - Py_DECREF(tmp); - - /* One of the flags must match */ - PyErr_SetString(PyExc_ValueError, "invalid flag used."); - return NULL; - } - - if (PyObject_GetBuffer(buffer_obj, &buffer, flags) < 0) { - return NULL; - } - - if (buffer.shape == NULL) { - Py_INCREF(Py_None); - shape = Py_None; - } - else { - shape = PyTuple_New(buffer.ndim); - for (i=0; i < buffer.ndim; i++) { - PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(buffer.shape[i])); - } - } - - if (buffer.strides == NULL) { - Py_INCREF(Py_None); - strides = Py_None; - } - else { - strides = PyTuple_New(buffer.ndim); - for (i=0; i < buffer.ndim; i++) { - PyTuple_SET_ITEM(strides, i, PyLong_FromSsize_t(buffer.strides[i])); - } - } - - PyBuffer_Release(&buffer); - return Py_BuildValue("(NN)", shape, strides); -} - -#undef GET_PYBUF_FLAG - - -/* - * Test C-api level item getting. - */ -static PyObject * -array_indexing(PyObject *NPY_UNUSED(self), PyObject *args) -{ - int mode; - Py_ssize_t i; - PyObject *arr, *op = NULL; - - if (!PyArg_ParseTuple(args, "iOn|O", &mode, &arr, &i, &op)) { - return NULL; - } - - if (mode == 0) { - return PySequence_GetItem(arr, i); - } - if (mode == 1) { - if (PySequence_SetItem(arr, i, op) < 0) { - return NULL; - } - Py_RETURN_NONE; - } - - PyErr_SetString(PyExc_ValueError, - "invalid mode. 0: item 1: assign"); - return NULL; -} - -/* - * Test C-api PyArray_AsCArray item getter - */ -static PyObject * -test_as_c_array(PyObject *NPY_UNUSED(self), PyObject *args) -{ - PyArrayObject *array_obj; - npy_intp dims[3]; /* max 3-dim */ - npy_intp i=0, j=0, k=0; - npy_intp num_dims = 0; - PyArray_Descr *descr = NULL; - double *array1 = NULL; - double **array2 = NULL; - double ***array3 = NULL; - double temp = 9999; - - if (!PyArg_ParseTuple(args, "O!l|ll", - &PyArray_Type, &array_obj, - &i, &j, &k)) { - return NULL; - } - - if (NULL == array_obj) { - return NULL; - } - - num_dims = PyArray_NDIM(array_obj); - descr = PyArray_DESCR(array_obj); - - switch (num_dims) { - case 1: - if (PyArray_AsCArray( - (PyObject **) &array_obj, - (void *) &array1, - dims, - 1, - descr) < 0) { - PyErr_SetString(PyExc_RuntimeError, "error converting 1D array"); - return NULL; - } - temp = array1[i]; - PyArray_Free((PyObject *) array_obj, (void *) array1); - break; - case 2: - if (PyArray_AsCArray( - (PyObject **) &array_obj, - (void **) &array2, - dims, - 2, - descr) < 0) { - PyErr_SetString(PyExc_RuntimeError, "error converting 2D array"); - return NULL; - } - temp = array2[i][j]; - PyArray_Free((PyObject *) array_obj, (void *) array2); - break; - case 3: - if (PyArray_AsCArray( - (PyObject **) &array_obj, - (void ***) &array3, - dims, - 3, - descr) < 0) { - PyErr_SetString(PyExc_RuntimeError, "error converting 3D array"); - return NULL; - } - temp = array3[i][j][k]; - PyArray_Free((PyObject *) array_obj, (void *) array3); - break; - default: - PyErr_SetString(PyExc_ValueError, "array.ndim not in [1, 3]"); - return NULL; - } - return Py_BuildValue("f", temp); -} - -/* - * Test nditer of too large arrays using remove axis, etc. - */ -static PyObject * -test_nditer_too_large(PyObject *NPY_UNUSED(self), PyObject *args) { - NpyIter *iter; - PyObject *array_tuple, *arr; - PyArrayObject *arrays[NPY_MAXARGS]; - npy_uint32 op_flags[NPY_MAXARGS]; - Py_ssize_t nop; - int i, axis, mode; - - npy_intp index[NPY_MAXARGS] = {0}; - char *msg; - - if (!PyArg_ParseTuple(args, "Oii", &array_tuple, &axis, &mode)) { - return NULL; - } - - if (!PyTuple_CheckExact(array_tuple)) { - PyErr_SetString(PyExc_ValueError, "tuple required as first argument"); - return NULL; - } - nop = PyTuple_Size(array_tuple); - if (nop > NPY_MAXARGS) { - PyErr_SetString(PyExc_ValueError, "tuple must be smaller then maxargs"); - return NULL; - } - - for (i=0; i < nop; i++) { - arr = PyTuple_GET_ITEM(array_tuple, i); - if (!PyArray_CheckExact(arr)) { - PyErr_SetString(PyExc_ValueError, "require base class ndarray"); - return NULL; - } - arrays[i] = (PyArrayObject *)arr; - op_flags[i] = NPY_ITER_READONLY; - } - - iter = NpyIter_MultiNew(nop, arrays, NPY_ITER_MULTI_INDEX | NPY_ITER_RANGED, - NPY_KEEPORDER, NPY_NO_CASTING, op_flags, NULL); - - if (iter == NULL) { - return NULL; - } - - /* Remove an axis (negative, do not remove any) */ - if (axis >= 0) { - if (!NpyIter_RemoveAxis(iter, axis)) { - goto fail; - } - } - - switch (mode) { - /* Test IterNext getting */ - case 0: - if (NpyIter_GetIterNext(iter, NULL) == NULL) { - goto fail; - } - break; - case 1: - if (NpyIter_GetIterNext(iter, &msg) == NULL) { - PyErr_SetString(PyExc_ValueError, msg); - goto fail; - } - break; - /* Test Multi Index removal */ - case 2: - if (!NpyIter_RemoveMultiIndex(iter)) { - goto fail; - } - break; - /* Test GotoMultiIndex (just 0 hardcoded) */ - case 3: - if (!NpyIter_GotoMultiIndex(iter, index)) { - goto fail; - } - break; - /* Test setting iterrange (hardcoded range of 0, 1) */ - case 4: - if (!NpyIter_ResetToIterIndexRange(iter, 0, 1, NULL)) { - goto fail; - } - break; - case 5: - if (!NpyIter_ResetToIterIndexRange(iter, 0, 1, &msg)) { - PyErr_SetString(PyExc_ValueError, msg); - goto fail; - } - break; - /* Do nothing */ - default: - break; - } - - NpyIter_Deallocate(iter); - Py_RETURN_NONE; - fail: - NpyIter_Deallocate(iter); - return NULL; -} - - -static PyObject * -array_solve_diophantine(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) -{ - PyObject *A = NULL; - PyObject *U = NULL; - Py_ssize_t b_input = 0; - Py_ssize_t max_work = -1; - int simplify = 0; - int require_ub_nontrivial = 0; - static char *kwlist[] = {"A", "U", "b", "max_work", "simplify", - "require_ub_nontrivial", NULL}; - - diophantine_term_t terms[2*NPY_MAXDIMS+2]; - npy_int64 x[2*NPY_MAXDIMS+2]; - npy_int64 b; - unsigned int nterms, j; - mem_overlap_t result = MEM_OVERLAP_YES; - PyObject *retval = NULL; - NPY_BEGIN_THREADS_DEF; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!n|nii", kwlist, - &PyTuple_Type, &A, - &PyTuple_Type, &U, - &b_input, &max_work, &simplify, - &require_ub_nontrivial)) { - return NULL; - } - - if (PyTuple_GET_SIZE(A) > (Py_ssize_t)ARRAY_SIZE(terms)) { - PyErr_SetString(PyExc_ValueError, "too many terms in equation"); - goto fail; - } - - nterms = PyTuple_GET_SIZE(A); - - if (PyTuple_GET_SIZE(U) != nterms) { - PyErr_SetString(PyExc_ValueError, "A, U must be tuples of equal length"); - goto fail; - } - - for (j = 0; j < nterms; ++j) { - terms[j].a = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(A, j)); - if (error_converting(terms[j].a)) { - goto fail; - } - terms[j].ub = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(U, j)); - if (error_converting(terms[j].ub)) { - goto fail; - } - } - - b = b_input; - - NPY_BEGIN_THREADS; - if (simplify && !require_ub_nontrivial) { - if (diophantine_simplify(&nterms, terms, b)) { - result = MEM_OVERLAP_OVERFLOW; - } - } - if (result == MEM_OVERLAP_YES) { - result = solve_diophantine(nterms, terms, b, max_work, require_ub_nontrivial, x); - } - NPY_END_THREADS; - - if (result == MEM_OVERLAP_YES) { - retval = PyTuple_New(nterms); - if (retval == NULL) { - goto fail; - } - - for (j = 0; j < nterms; ++j) { - PyObject *obj; -#if defined(NPY_PY3K) - obj = PyLong_FromSsize_t(x[j]); -#else - obj = PyInt_FromSsize_t(x[j]); -#endif - if (obj == NULL) { - goto fail; - } - PyTuple_SET_ITEM(retval, j, obj); - } - } - else if (result == MEM_OVERLAP_NO) { - retval = Py_None; - Py_INCREF(retval); - } - else if (result == MEM_OVERLAP_ERROR) { - PyErr_SetString(PyExc_ValueError, "Invalid arguments"); - } - else if (result == MEM_OVERLAP_OVERFLOW) { - PyErr_SetString(PyExc_OverflowError, "Integer overflow"); - } - else if (result == MEM_OVERLAP_TOO_HARD) { - PyErr_SetString(PyExc_RuntimeError, "Too much work done"); - } - else { - PyErr_SetString(PyExc_RuntimeError, "Unknown error"); - } - - return retval; - -fail: - Py_XDECREF(retval); - return NULL; -} - - -static PyObject * -array_internal_overlap(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) -{ - PyArrayObject * self = NULL; - static char *kwlist[] = {"self", "max_work", NULL}; - - mem_overlap_t result; - Py_ssize_t max_work = NPY_MAY_SHARE_EXACT; - NPY_BEGIN_THREADS_DEF; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|n", kwlist, - PyArray_Converter, &self, - &max_work)) { - return NULL; - } - - if (max_work < -2) { - PyErr_SetString(PyExc_ValueError, "Invalid value for max_work"); - goto fail; - } - - NPY_BEGIN_THREADS; - result = solve_may_have_internal_overlap(self, max_work); - NPY_END_THREADS; - - Py_XDECREF(self); - - if (result == MEM_OVERLAP_NO) { - Py_RETURN_FALSE; - } - else if (result == MEM_OVERLAP_YES) { - Py_RETURN_TRUE; - } - else if (result == MEM_OVERLAP_OVERFLOW) { - PyErr_SetString(PyExc_OverflowError, - "Integer overflow in computing overlap"); - return NULL; - } - else if (result == MEM_OVERLAP_TOO_HARD) { - PyErr_SetString(PyExc_ValueError, - "Exceeded max_work"); - return NULL; - } - else { - /* Doesn't happen usually */ - PyErr_SetString(PyExc_RuntimeError, - "Error in computing overlap"); - return NULL; - } - -fail: - Py_XDECREF(self); - return NULL; -} - - -static PyObject * -pylong_from_int128(npy_extint128_t value) -{ - PyObject *val_64 = NULL, *val = NULL, *tmp = NULL, *tmp2 = NULL; - - val_64 = PyLong_FromLong(64); - if (val_64 == NULL) { - goto fail; - } - - val = PyLong_FromUnsignedLongLong(value.hi); - if (val == NULL) { - goto fail; - } - - tmp = PyNumber_Lshift(val, val_64); - if (tmp == NULL) { - goto fail; - } - - Py_DECREF(val); - val = tmp; - - tmp = PyLong_FromUnsignedLongLong(value.lo); - if (tmp == NULL) { - goto fail; - } - - tmp2 = PyNumber_Or(val, tmp); - if (tmp2 == NULL) { - goto fail; - } - - Py_DECREF(val); - Py_DECREF(tmp); - - val = NULL; - tmp = NULL; - - if (value.sign < 0) { - val = PyNumber_Negative(tmp2); - if (val == NULL) { - goto fail; - } - Py_DECREF(tmp2); - return val; - } - else { - val = tmp2; - } - return val; - -fail: - Py_XDECREF(val_64); - Py_XDECREF(tmp); - Py_XDECREF(tmp2); - Py_XDECREF(val); - return NULL; -} - - -static int -int128_from_pylong(PyObject *obj, npy_extint128_t *result) -{ - PyObject *long_obj = NULL, *val_64 = NULL, *val_0 = NULL, - *mask_64 = NULL, *max_128 = NULL, *hi_bits = NULL, - *lo_bits = NULL, *tmp = NULL; - int cmp; - int negative_zero = 0; - - if (PyBool_Check(obj)) { - /* False means negative zero */ - negative_zero = 1; - } - - long_obj = PyObject_CallFunction((PyObject*)&PyLong_Type, "O", obj); - if (long_obj == NULL) { - goto fail; - } - - val_0 = PyLong_FromLong(0); - if (val_0 == NULL) { - goto fail; - } - - val_64 = PyLong_FromLong(64); - if (val_64 == NULL) { - goto fail; - } - - mask_64 = PyLong_FromUnsignedLongLong(0xffffffffffffffffULL); - if (mask_64 == NULL) { - goto fail; - } - - tmp = PyNumber_Lshift(mask_64, val_64); - if (tmp == NULL) { - goto fail; - } - max_128 = PyNumber_Or(tmp, mask_64); - if (max_128 == NULL) { - goto fail; - } - Py_DECREF(tmp); - tmp = NULL; - - cmp = PyObject_RichCompareBool(long_obj, val_0, Py_LT); - if (cmp == -1) { - goto fail; - } - else if (cmp == 1) { - tmp = PyNumber_Negative(long_obj); - if (tmp == NULL) { - goto fail; - } - Py_DECREF(long_obj); - long_obj = tmp; - tmp = NULL; - result->sign = -1; - } - else { - result->sign = 1; - } - - cmp = PyObject_RichCompareBool(long_obj, max_128, Py_GT); - if (cmp == 1) { - PyErr_SetString(PyExc_OverflowError, ""); - goto fail; - } - else if (cmp == -1) { - goto fail; - } - - hi_bits = PyNumber_Rshift(long_obj, val_64); - if (hi_bits == NULL) { - goto fail; - } - - lo_bits = PyNumber_And(long_obj, mask_64); - if (lo_bits == NULL) { - goto fail; - } - - result->hi = PyLong_AsUnsignedLongLong(hi_bits); - if (result->hi == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { - goto fail; - } - - result->lo = PyLong_AsUnsignedLongLong(lo_bits); - if (result->lo == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { - goto fail; - } - - if (negative_zero && result->hi == 0 && result->lo == 0) { - result->sign = -1; - } - - Py_XDECREF(long_obj); - Py_XDECREF(val_64); - Py_XDECREF(val_0); - Py_XDECREF(mask_64); - Py_XDECREF(max_128); - Py_XDECREF(hi_bits); - Py_XDECREF(lo_bits); - Py_XDECREF(tmp); - return 0; - -fail: - Py_XDECREF(long_obj); - Py_XDECREF(val_64); - Py_XDECREF(val_0); - Py_XDECREF(mask_64); - Py_XDECREF(max_128); - Py_XDECREF(hi_bits); - Py_XDECREF(lo_bits); - Py_XDECREF(tmp); - return -1; -} - - -static PyObject * -extint_safe_binop(PyObject *NPY_UNUSED(self), PyObject *args) { - PY_LONG_LONG a, b, c; - int op; - char overflow = 0; - if (!PyArg_ParseTuple(args, "LLi", &a, &b, &op)) { - return NULL; - } - if (op == 1) { - c = safe_add(a, b, &overflow); - } - else if (op == 2) { - c = safe_sub(a, b, &overflow); - } - else if (op == 3) { - c = safe_mul(a, b, &overflow); - } - else { - PyErr_SetString(PyExc_ValueError, "invalid op"); - return NULL; - } - if (overflow) { - PyErr_SetString(PyExc_OverflowError, ""); - return NULL; - } - return PyLong_FromLongLong(c); -} - - -static PyObject * -extint_to_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PY_LONG_LONG a; - if (!PyArg_ParseTuple(args, "L", &a)) { - return NULL; - } - return pylong_from_int128(to_128(a)); -} - - -static PyObject * -extint_to_64(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a; - PY_LONG_LONG r; - char overflow = 0; - if (!PyArg_ParseTuple(args, "O", &a_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - r = to_64(a, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, ""); - return NULL; - } - return PyLong_FromLongLong(r); -} - - -static PyObject * -extint_mul_64_64(PyObject *NPY_UNUSED(self), PyObject *args) { - PY_LONG_LONG a, b; - npy_extint128_t c; - if (!PyArg_ParseTuple(args, "LL", &a, &b)) { - return NULL; - } - c = mul_64_64(a, b); - return pylong_from_int128(c); -} - - -static PyObject * -extint_add_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj, *b_obj; - npy_extint128_t a, b, c; - char overflow = 0; - if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { - return NULL; - } - c = add_128(a, b, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, ""); - return NULL; - } - return pylong_from_int128(c); -} - - -static PyObject * -extint_sub_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj, *b_obj; - npy_extint128_t a, b, c; - char overflow = 0; - if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { - return NULL; - } - c = sub_128(a, b, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, ""); - return NULL; - } - return pylong_from_int128(c); -} - - -static PyObject * -extint_neg_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a, b; - if (!PyArg_ParseTuple(args, "O", &a_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - b = neg_128(a); - return pylong_from_int128(b); -} - - -static PyObject * -extint_shl_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a, b; - if (!PyArg_ParseTuple(args, "O", &a_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - b = shl_128(a); - return pylong_from_int128(b); -} - - -static PyObject * -extint_shr_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a, b; - if (!PyArg_ParseTuple(args, "O", &a_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - b = shr_128(a); - return pylong_from_int128(b); -} - - -static PyObject * -extint_gt_128(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj, *b_obj; - npy_extint128_t a, b; - if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { - return NULL; - } - if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { - return NULL; - } - if (gt_128(a, b)) { - Py_RETURN_TRUE; - } - else { - Py_RETURN_FALSE; - } -} - - -static PyObject * -extint_divmod_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj, *ret = NULL, *tmp = NULL; - npy_extint128_t a, c; - PY_LONG_LONG b; - npy_int64 mod; - if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { - goto fail; - } - if (b <= 0) { - PyErr_SetString(PyExc_ValueError, ""); - goto fail; - } - if (int128_from_pylong(a_obj, &a)) { - goto fail; - } - - c = divmod_128_64(a, b, &mod); - - ret = PyTuple_New(2); - - tmp = pylong_from_int128(c); - if (tmp == NULL) { - goto fail; - } - PyTuple_SET_ITEM(ret, 0, tmp); - - tmp = PyLong_FromLongLong(mod); - if (tmp == NULL) { - goto fail; - } - PyTuple_SET_ITEM(ret, 1, tmp); - return ret; - -fail: - Py_XDECREF(ret); - Py_XDECREF(tmp); - return NULL; -} - - -static PyObject * -extint_floordiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a, c; - PY_LONG_LONG b; - if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { - return NULL; - } - if (b <= 0) { - PyErr_SetString(PyExc_ValueError, ""); - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - c = floordiv_128_64(a, b); - return pylong_from_int128(c); -} - - -static PyObject * -extint_ceildiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { - PyObject *a_obj; - npy_extint128_t a, c; - PY_LONG_LONG b; - if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { - return NULL; - } - if (b <= 0) { - PyErr_SetString(PyExc_ValueError, ""); - return NULL; - } - if (int128_from_pylong(a_obj, &a)) { - return NULL; - } - c = ceildiv_128_64(a, b); - return pylong_from_int128(c); -} - - -static char get_fpu_mode_doc[] = ( - "get_fpu_mode()\n" - "\n" - "Get the current FPU control word, in a platform-dependent format.\n" - "Returns None if not implemented on current platform."); - -static PyObject * -get_fpu_mode(PyObject *NPY_UNUSED(self), PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) { - return NULL; - } - -#if defined(_MSC_VER) - { - unsigned int result = 0; - result = _controlfp(0, 0); - return PyLong_FromLongLong(result); - } -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) - { - unsigned short cw = 0; - __asm__("fstcw %w0" : "=m" (cw)); - return PyLong_FromLongLong(cw); - } -#else - Py_RETURN_NONE; -#endif -} - -/* - * npymath wrappers - */ - -/**begin repeat - * #name = cabs, carg# - */ - -/**begin repeat1 - * #itype = npy_cfloat, npy_cdouble, npy_clongdouble# - * #ITYPE = NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE# - * #otype = npy_float, npy_double, npy_longdouble# - * #OTYPE = NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE# - * #suffix= f, , l# - */ - -static PyObject * -call_npy_@name@@suffix@(PyObject *NPY_UNUSED(self), PyObject *args) -{ - PyObject *z_py = NULL, *z_arr = NULL, *w_arr = NULL; - - if (!PyArg_ParseTuple(args, "O", &z_py)) { - return NULL; - } - - z_arr = PyArray_FROMANY(z_py, @ITYPE@, 0, 0, NPY_ARRAY_CARRAY_RO); - if (z_arr == NULL) { - return NULL; - } - - w_arr = PyArray_SimpleNew(0, NULL, @OTYPE@); - if (w_arr == NULL) { - Py_DECREF(z_arr); - return NULL; - } - - *(@otype@*)PyArray_DATA((PyArrayObject *)w_arr) = - npy_@name@@suffix@(*(@itype@*)PyArray_DATA((PyArrayObject *)z_arr)); - - Py_DECREF(z_arr); - return w_arr; -} - -/**end repeat1**/ - -/**end repeat**/ - -/**begin repeat - * #name = log10, cosh, sinh, tan, tanh# - */ - -/**begin repeat1 - * #type = npy_float, npy_double, npy_longdouble# - * #TYPE = NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE# - * #suffix= f, , l# - */ - -static PyObject * -call_npy_@name@@suffix@(PyObject *NPY_UNUSED(self), PyObject *args) -{ - PyObject *z_py = NULL, *z_arr = NULL, *w_arr = NULL; - - if (!PyArg_ParseTuple(args, "O", &z_py)) { - return NULL; - } - - z_arr = PyArray_FROMANY(z_py, @TYPE@, 0, 0, NPY_ARRAY_CARRAY_RO); - if (z_arr == NULL) { - return NULL; - } - - w_arr = PyArray_SimpleNew(0, NULL, @TYPE@); - if (w_arr == NULL) { - Py_DECREF(z_arr); - return NULL; - } - - *(@type@*)PyArray_DATA((PyArrayObject *)w_arr) = - npy_@name@@suffix@(*(@type@*)PyArray_DATA((PyArrayObject *)z_arr)); - - Py_DECREF(z_arr); - return w_arr; -} - -/**end repeat1**/ - -/**end repeat**/ - - -static PyMethodDef Multiarray_TestsMethods[] = { - {"IsPythonScalar", - IsPythonScalar, - METH_VARARGS, NULL}, - {"test_neighborhood_iterator", - test_neighborhood_iterator, - METH_VARARGS, NULL}, - {"test_neighborhood_iterator_oob", - test_neighborhood_iterator_oob, - METH_VARARGS, NULL}, - {"test_pydatamem_seteventhook_start", - test_pydatamem_seteventhook_start, - METH_NOARGS, NULL}, - {"test_pydatamem_seteventhook_end", - test_pydatamem_seteventhook_end, - METH_NOARGS, NULL}, - {"test_inplace_increment", - inplace_increment, - METH_VARARGS, NULL}, - {"incref_elide", - incref_elide, - METH_VARARGS, NULL}, - {"incref_elide_l", - incref_elide_l, - METH_VARARGS, NULL}, - {"npy_char_deprecation", - npy_char_deprecation, - METH_NOARGS, NULL}, - {"npy_updateifcopy_deprecation", - npy_updateifcopy_deprecation, - METH_O, NULL}, - {"npy_create_writebackifcopy", - npy_create_writebackifcopy, - METH_O, NULL}, - {"npy_resolve", - npy_resolve, - METH_O, NULL}, -#if !defined(NPY_PY3K) - {"test_int_subclass", - int_subclass, - METH_VARARGS, NULL}, -#endif - {"get_buffer_info", - get_buffer_info, - METH_VARARGS, NULL}, - {"array_indexing", - array_indexing, - METH_VARARGS, NULL}, - {"test_as_c_array", - test_as_c_array, - METH_VARARGS, NULL}, - {"test_nditer_too_large", - test_nditer_too_large, - METH_VARARGS, NULL}, - {"solve_diophantine", - (PyCFunction)array_solve_diophantine, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"internal_overlap", - (PyCFunction)array_internal_overlap, - METH_VARARGS | METH_KEYWORDS, NULL}, - {"extint_safe_binop", - extint_safe_binop, - METH_VARARGS, NULL}, - {"extint_to_128", - extint_to_128, - METH_VARARGS, NULL}, - {"extint_to_64", - extint_to_64, - METH_VARARGS, NULL}, - {"extint_mul_64_64", - extint_mul_64_64, - METH_VARARGS, NULL}, - {"extint_add_128", - extint_add_128, - METH_VARARGS, NULL}, - {"extint_sub_128", - extint_sub_128, - METH_VARARGS, NULL}, - {"extint_neg_128", - extint_neg_128, - METH_VARARGS, NULL}, - {"extint_shl_128", - extint_shl_128, - METH_VARARGS, NULL}, - {"extint_shr_128", - extint_shr_128, - METH_VARARGS, NULL}, - {"extint_gt_128", - extint_gt_128, - METH_VARARGS, NULL}, - {"extint_divmod_128_64", - extint_divmod_128_64, - METH_VARARGS, NULL}, - {"extint_floordiv_128_64", - extint_floordiv_128_64, - METH_VARARGS, NULL}, - {"extint_ceildiv_128_64", - extint_ceildiv_128_64, - METH_VARARGS, NULL}, - {"get_fpu_mode", - get_fpu_mode, - METH_VARARGS, get_fpu_mode_doc}, -/**begin repeat - * #name = cabs, carg# - */ - -/**begin repeat1 - * #suffix = f, , l# - */ - {"npy_@name@@suffix@", - call_npy_@name@@suffix@, - METH_VARARGS, NULL}, -/**end repeat1**/ - -/**end repeat**/ - -/**begin repeat - * #name = log10, cosh, sinh, tan, tanh# - */ - -/**begin repeat1 - * #suffix= f, , l# - */ - {"npy_@name@@suffix@", - call_npy_@name@@suffix@, - METH_VARARGS, NULL}, -/**end repeat1**/ - -/**end repeat**/ - - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - - -#if defined(NPY_PY3K) -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "multiarray_tests", - NULL, - -1, - Multiarray_TestsMethods, - NULL, - NULL, - NULL, - NULL -}; -#endif - -#if defined(NPY_PY3K) -#define RETVAL m -PyMODINIT_FUNC PyInit_multiarray_tests(void) -#else -#define RETVAL -PyMODINIT_FUNC -initmultiarray_tests(void) -#endif -{ - PyObject *m; - -#if defined(NPY_PY3K) - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule("multiarray_tests", Multiarray_TestsMethods); -#endif - if (m == NULL) { - return RETVAL; - } - import_array(); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, - "cannot load umath_tests module."); - } - return RETVAL; -} diff --git a/numpy/core/src/umath/_operand_flag_tests.c.src b/numpy/core/src/umath/_operand_flag_tests.c.src new file mode 100644 index 000000000..551a9c632 --- /dev/null +++ b/numpy/core/src/umath/_operand_flag_tests.c.src @@ -0,0 +1,105 @@ +#define NPY_NO_DEPRECATED_API NPY_API_VERSION + +#include +#include +#include +#include "numpy/npy_3kcompat.h" +#include +#include + + +static PyMethodDef TestMethods[] = { + {NULL, NULL, 0, NULL} +}; + + +static void +inplace_add(char **args, npy_intp *dimensions, npy_intp *steps, void *data) +{ + npy_intp i; + npy_intp n = dimensions[0]; + char *in1 = args[0]; + char *in2 = args[1]; + npy_intp in1_step = steps[0]; + npy_intp in2_step = steps[1]; + + for (i = 0; i < n; i++) { + (*(long *)in1) = *(long*)in1 + *(long*)in2; + in1 += in1_step; + in2 += in2_step; + } +} + + +/*This a pointer to the above function*/ +PyUFuncGenericFunction funcs[1] = {&inplace_add}; + +/* These are the input and return dtypes of logit.*/ +static char types[2] = {NPY_LONG, NPY_LONG}; + +static void *data[1] = {NULL}; + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_operand_flag_tests", + NULL, + -1, + TestMethods, + NULL, + NULL, + NULL, + NULL +}; + +#define RETVAL m +PyMODINIT_FUNC PyInit__operand_flag_tests(void) +{ +#else +#define RETVAL +PyMODINIT_FUNC init_operand_flag_tests(void) +{ +#endif + PyObject *m = NULL; + PyObject *ufunc; + +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_operand_flag_tests", TestMethods); +#endif + if (m == NULL) { + goto fail; + } + + import_array(); + import_umath(); + + ufunc = PyUFunc_FromFuncAndData(funcs, data, types, 1, 2, 0, + PyUFunc_None, "inplace_add", + "inplace_add_docstring", 0); + + /* + * Set flags to turn off buffering for first input operand, + * so that result can be written back to input operand. + */ + ((PyUFuncObject*)ufunc)->op_flags[0] = NPY_ITER_READWRITE; + ((PyUFuncObject*)ufunc)->iter_flags = NPY_ITER_REDUCE_OK; + PyModule_AddObject(m, "inplace_add", (PyObject*)ufunc); + + return RETVAL; + +fail: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "cannot load _operand_flag_tests module."); + } +#if defined(NPY_PY3K) + if (m) { + Py_DECREF(m); + m = NULL; + } +#endif + return RETVAL; + +} diff --git a/numpy/core/src/umath/_rational_tests.c.src b/numpy/core/src/umath/_rational_tests.c.src new file mode 100644 index 000000000..9e74845df --- /dev/null +++ b/numpy/core/src/umath/_rational_tests.c.src @@ -0,0 +1,1409 @@ +/* Fixed size rational numbers exposed to Python */ + +#define NPY_NO_DEPRECATED_API NPY_API_VERSION + +#include +#include +#include +#include +#include +#include + +#include "common.h" /* for error_converting */ + + +/* Relevant arithmetic exceptions */ + +/* Uncomment the following line to work around a bug in numpy */ +/* #define ACQUIRE_GIL */ + +static void +set_overflow(void) { +#ifdef ACQUIRE_GIL + /* Need to grab the GIL to dodge a bug in numpy */ + PyGILState_STATE state = PyGILState_Ensure(); +#endif + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_OverflowError, + "overflow in rational arithmetic"); + } +#ifdef ACQUIRE_GIL + PyGILState_Release(state); +#endif +} + +static void +set_zero_divide(void) { +#ifdef ACQUIRE_GIL + /* Need to grab the GIL to dodge a bug in numpy */ + PyGILState_STATE state = PyGILState_Ensure(); +#endif + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ZeroDivisionError, + "zero divide in rational arithmetic"); + } +#ifdef ACQUIRE_GIL + PyGILState_Release(state); +#endif +} + +/* Integer arithmetic utilities */ + +static NPY_INLINE npy_int32 +safe_neg(npy_int32 x) { + if (x==(npy_int32)1<<31) { + set_overflow(); + } + return -x; +} + +static NPY_INLINE npy_int32 +safe_abs32(npy_int32 x) { + npy_int32 nx; + if (x>=0) { + return x; + } + nx = -x; + if (nx<0) { + set_overflow(); + } + return nx; +} + +static NPY_INLINE npy_int64 +safe_abs64(npy_int64 x) { + npy_int64 nx; + if (x>=0) { + return x; + } + nx = -x; + if (nx<0) { + set_overflow(); + } + return nx; +} + +static NPY_INLINE npy_int64 +gcd(npy_int64 x, npy_int64 y) { + x = safe_abs64(x); + y = safe_abs64(y); + if (x < y) { + npy_int64 t = x; + x = y; + y = t; + } + while (y) { + npy_int64 t; + x = x%y; + t = x; + x = y; + y = t; + } + return x; +} + +static NPY_INLINE npy_int64 +lcm(npy_int64 x, npy_int64 y) { + npy_int64 lcm; + if (!x || !y) { + return 0; + } + x /= gcd(x,y); + lcm = x*y; + if (lcm/y!=x) { + set_overflow(); + } + return safe_abs64(lcm); +} + +/* Fixed precision rational numbers */ + +typedef struct { + /* numerator */ + npy_int32 n; + /* + * denominator minus one: numpy.zeros() uses memset(0) for non-object + * types, so need to ensure that rational(0) has all zero bytes + */ + npy_int32 dmm; +} rational; + +static NPY_INLINE rational +make_rational_int(npy_int64 n) { + rational r = {(npy_int32)n,0}; + if (r.n != n) { + set_overflow(); + } + return r; +} + +static rational +make_rational_slow(npy_int64 n_, npy_int64 d_) { + rational r = {0}; + if (!d_) { + set_zero_divide(); + } + else { + npy_int64 g = gcd(n_,d_); + npy_int32 d; + n_ /= g; + d_ /= g; + r.n = (npy_int32)n_; + d = (npy_int32)d_; + if (r.n!=n_ || d!=d_) { + set_overflow(); + } + else { + if (d <= 0) { + d = -d; + r.n = safe_neg(r.n); + } + r.dmm = d-1; + } + } + return r; +} + +static NPY_INLINE npy_int32 +d(rational r) { + return r.dmm+1; +} + +/* Assumes d_ > 0 */ +static rational +make_rational_fast(npy_int64 n_, npy_int64 d_) { + npy_int64 g = gcd(n_,d_); + rational r; + n_ /= g; + d_ /= g; + r.n = (npy_int32)n_; + r.dmm = (npy_int32)(d_-1); + if (r.n!=n_ || r.dmm+1!=d_) { + set_overflow(); + } + return r; +} + +static NPY_INLINE rational +rational_negative(rational r) { + rational x; + x.n = safe_neg(r.n); + x.dmm = r.dmm; + return x; +} + +static NPY_INLINE rational +rational_add(rational x, rational y) { + /* + * Note that the numerator computation can never overflow int128_t, + * since each term is strictly under 2**128/4 (since d > 0). + */ + return make_rational_fast((npy_int64)x.n*d(y)+(npy_int64)d(x)*y.n, + (npy_int64)d(x)*d(y)); +} + +static NPY_INLINE rational +rational_subtract(rational x, rational y) { + /* We're safe from overflow as with + */ + return make_rational_fast((npy_int64)x.n*d(y)-(npy_int64)d(x)*y.n, + (npy_int64)d(x)*d(y)); +} + +static NPY_INLINE rational +rational_multiply(rational x, rational y) { + /* We're safe from overflow as with + */ + return make_rational_fast((npy_int64)x.n*y.n,(npy_int64)d(x)*d(y)); +} + +static NPY_INLINE rational +rational_divide(rational x, rational y) { + return make_rational_slow((npy_int64)x.n*d(y),(npy_int64)d(x)*y.n); +} + +static NPY_INLINE npy_int64 +rational_floor(rational x) { + /* Always round down */ + if (x.n>=0) { + return x.n/d(x); + } + /* + * This can be done without casting up to 64 bits, but it requires + * working out all the sign cases + */ + return -((-(npy_int64)x.n+d(x)-1)/d(x)); +} + +static NPY_INLINE npy_int64 +rational_ceil(rational x) { + return -rational_floor(rational_negative(x)); +} + +static NPY_INLINE rational +rational_remainder(rational x, rational y) { + return rational_subtract(x, rational_multiply(y,make_rational_int( + rational_floor(rational_divide(x,y))))); +} + +static NPY_INLINE rational +rational_abs(rational x) { + rational y; + y.n = safe_abs32(x.n); + y.dmm = x.dmm; + return y; +} + +static NPY_INLINE npy_int64 +rational_rint(rational x) { + /* + * Round towards nearest integer, moving exact half integers towards + * zero + */ + npy_int32 d_ = d(x); + return (2*(npy_int64)x.n+(x.n<0?-d_:d_))/(2*(npy_int64)d_); +} + +static NPY_INLINE int +rational_sign(rational x) { + return x.n<0?-1:x.n==0?0:1; +} + +static NPY_INLINE rational +rational_inverse(rational x) { + rational y = {0}; + if (!x.n) { + set_zero_divide(); + } + else { + npy_int32 d_; + y.n = d(x); + d_ = x.n; + if (d_ <= 0) { + d_ = safe_neg(d_); + y.n = -y.n; + } + y.dmm = d_-1; + } + return y; +} + +static NPY_INLINE int +rational_eq(rational x, rational y) { + /* + * Since we enforce d > 0, and store fractions in reduced form, + * equality is easy. + */ + return x.n==y.n && x.dmm==y.dmm; +} + +static NPY_INLINE int +rational_ne(rational x, rational y) { + return !rational_eq(x,y); +} + +static NPY_INLINE int +rational_lt(rational x, rational y) { + return (npy_int64)x.n*d(y) < (npy_int64)y.n*d(x); +} + +static NPY_INLINE int +rational_gt(rational x, rational y) { + return rational_lt(y,x); +} + +static NPY_INLINE int +rational_le(rational x, rational y) { + return !rational_lt(y,x); +} + +static NPY_INLINE int +rational_ge(rational x, rational y) { + return !rational_lt(x,y); +} + +static NPY_INLINE npy_int32 +rational_int(rational x) { + return x.n/d(x); +} + +static NPY_INLINE double +rational_double(rational x) { + return (double)x.n/d(x); +} + +static NPY_INLINE int +rational_nonzero(rational x) { + return x.n!=0; +} + +static int +scan_rational(const char** s, rational* x) { + long n,d; + int offset; + const char* ss; + if (sscanf(*s,"%ld%n",&n,&offset)<=0) { + return 0; + } + ss = *s+offset; + if (*ss!='/') { + *s = ss; + *x = make_rational_int(n); + return 1; + } + ss++; + if (sscanf(ss,"%ld%n",&d,&offset)<=0 || d<=0) { + return 0; + } + *s = ss+offset; + *x = make_rational_slow(n,d); + return 1; +} + +/* Expose rational to Python as a numpy scalar */ + +typedef struct { + PyObject_HEAD + rational r; +} PyRational; + +static PyTypeObject PyRational_Type; + +static NPY_INLINE int +PyRational_Check(PyObject* object) { + return PyObject_IsInstance(object,(PyObject*)&PyRational_Type); +} + +static PyObject* +PyRational_FromRational(rational x) { + PyRational* p = (PyRational*)PyRational_Type.tp_alloc(&PyRational_Type,0); + if (p) { + p->r = x; + } + return (PyObject*)p; +} + +static PyObject* +pyrational_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + Py_ssize_t size; + PyObject* x[2]; + long n[2]={0,1}; + int i; + rational r; + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "constructor takes no keyword arguments"); + return 0; + } + size = PyTuple_GET_SIZE(args); + if (size > 2) { + PyErr_SetString(PyExc_TypeError, + "expected rational or numerator and optional denominator"); + return 0; + } + + if (size == 1) { + x[0] = PyTuple_GET_ITEM(args, 0); + if (PyRational_Check(x[0])) { + Py_INCREF(x[0]); + return x[0]; + } + else if (PyString_Check(x[0])) { + const char* s = PyString_AS_STRING(x[0]); + rational x; + if (scan_rational(&s,&x)) { + const char* p; + for (p = s; *p; p++) { + if (!isspace(*p)) { + goto bad; + } + } + return PyRational_FromRational(x); + } + bad: + PyErr_Format(PyExc_ValueError, + "invalid rational literal '%s'",s); + return 0; + } + } + + for (i=0; iob_type->tp_name); + } + return 0; + } + /* Check that we had an exact integer */ + y = PyInt_FromLong(n[i]); + if (!y) { + return 0; + } + eq = PyObject_RichCompareBool(x[i],y,Py_EQ); + Py_DECREF(y); + if (eq<0) { + return 0; + } + if (!eq) { + PyErr_Format(PyExc_TypeError, + "expected integer %s, got %s", + (i ? "denominator" : "numerator"), + x[i]->ob_type->tp_name); + return 0; + } + } + r = make_rational_slow(n[0],n[1]); + if (PyErr_Occurred()) { + return 0; + } + return PyRational_FromRational(r); +} + +/* + * Returns Py_NotImplemented on most conversion failures, or raises an + * overflow error for too long ints + */ +#define AS_RATIONAL(dst,object) \ + { \ + dst.n = 0; \ + if (PyRational_Check(object)) { \ + dst = ((PyRational*)object)->r; \ + } \ + else { \ + PyObject* y_; \ + int eq_; \ + long n_ = PyInt_AsLong(object); \ + if (error_converting(n_)) { \ + if (PyErr_ExceptionMatches(PyExc_TypeError)) { \ + PyErr_Clear(); \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + return 0; \ + } \ + y_ = PyInt_FromLong(n_); \ + if (!y_) { \ + return 0; \ + } \ + eq_ = PyObject_RichCompareBool(object,y_,Py_EQ); \ + Py_DECREF(y_); \ + if (eq_<0) { \ + return 0; \ + } \ + if (!eq_) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + dst = make_rational_int(n_); \ + } \ + } + +static PyObject* +pyrational_richcompare(PyObject* a, PyObject* b, int op) { + rational x, y; + int result = 0; + AS_RATIONAL(x,a); + AS_RATIONAL(y,b); + #define OP(py,op) case py: result = rational_##op(x,y); break; + switch (op) { + OP(Py_LT,lt) + OP(Py_LE,le) + OP(Py_EQ,eq) + OP(Py_NE,ne) + OP(Py_GT,gt) + OP(Py_GE,ge) + }; + #undef OP + return PyBool_FromLong(result); +} + +static PyObject* +pyrational_repr(PyObject* self) { + rational x = ((PyRational*)self)->r; + if (d(x)!=1) { + return PyUString_FromFormat( + "rational(%ld,%ld)",(long)x.n,(long)d(x)); + } + else { + return PyUString_FromFormat( + "rational(%ld)",(long)x.n); + } +} + +static PyObject* +pyrational_str(PyObject* self) { + rational x = ((PyRational*)self)->r; + if (d(x)!=1) { + return PyString_FromFormat( + "%ld/%ld",(long)x.n,(long)d(x)); + } + else { + return PyString_FromFormat( + "%ld",(long)x.n); + } +} + +static npy_hash_t +pyrational_hash(PyObject* self) { + rational x = ((PyRational*)self)->r; + /* Use a fairly weak hash as Python expects */ + long h = 131071*x.n+524287*x.dmm; + /* Never return the special error value -1 */ + return h==-1?2:h; +} + +#define RATIONAL_BINOP_2(name,exp) \ + static PyObject* \ + pyrational_##name(PyObject* a, PyObject* b) { \ + rational x, y, z; \ + AS_RATIONAL(x,a); \ + AS_RATIONAL(y,b); \ + z = exp; \ + if (PyErr_Occurred()) { \ + return 0; \ + } \ + return PyRational_FromRational(z); \ + } +#define RATIONAL_BINOP(name) RATIONAL_BINOP_2(name,rational_##name(x,y)) +RATIONAL_BINOP(add) +RATIONAL_BINOP(subtract) +RATIONAL_BINOP(multiply) +RATIONAL_BINOP(divide) +RATIONAL_BINOP(remainder) +RATIONAL_BINOP_2(floor_divide, + make_rational_int(rational_floor(rational_divide(x,y)))) + +#define RATIONAL_UNOP(name,type,exp,convert) \ + static PyObject* \ + pyrational_##name(PyObject* self) { \ + rational x = ((PyRational*)self)->r; \ + type y = exp; \ + if (PyErr_Occurred()) { \ + return 0; \ + } \ + return convert(y); \ + } +RATIONAL_UNOP(negative,rational,rational_negative(x),PyRational_FromRational) +RATIONAL_UNOP(absolute,rational,rational_abs(x),PyRational_FromRational) +RATIONAL_UNOP(int,long,rational_int(x),PyInt_FromLong) +RATIONAL_UNOP(float,double,rational_double(x),PyFloat_FromDouble) + +static PyObject* +pyrational_positive(PyObject* self) { + Py_INCREF(self); + return self; +} + +static int +pyrational_nonzero(PyObject* self) { + rational x = ((PyRational*)self)->r; + return rational_nonzero(x); +} + +static PyNumberMethods pyrational_as_number = { + pyrational_add, /* nb_add */ + pyrational_subtract, /* nb_subtract */ + pyrational_multiply, /* nb_multiply */ +#if PY_MAJOR_VERSION < 3 + pyrational_divide, /* nb_divide */ +#endif + pyrational_remainder, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + pyrational_negative, /* nb_negative */ + pyrational_positive, /* nb_positive */ + pyrational_absolute, /* nb_absolute */ + pyrational_nonzero, /* nb_nonzero */ + 0, /* nb_invert */ + 0, /* nb_lshift */ + 0, /* nb_rshift */ + 0, /* nb_and */ + 0, /* nb_xor */ + 0, /* nb_or */ +#if PY_MAJOR_VERSION < 3 + 0, /* nb_coerce */ +#endif + pyrational_int, /* nb_int */ +#if PY_MAJOR_VERSION < 3 + pyrational_int, /* nb_long */ +#else + 0, /* reserved */ +#endif + pyrational_float, /* nb_float */ +#if PY_MAJOR_VERSION < 3 + 0, /* nb_oct */ + 0, /* nb_hex */ +#endif + + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ +#if PY_MAJOR_VERSION < 3 + 0, /* nb_inplace_divide */ +#endif + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + + pyrational_floor_divide, /* nb_floor_divide */ + pyrational_divide, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; + +static PyObject* +pyrational_n(PyObject* self, void* closure) { + return PyInt_FromLong(((PyRational*)self)->r.n); +} + +static PyObject* +pyrational_d(PyObject* self, void* closure) { + return PyInt_FromLong(d(((PyRational*)self)->r)); +} + +static PyGetSetDef pyrational_getset[] = { + {(char*)"n",pyrational_n,0,(char*)"numerator",0}, + {(char*)"d",pyrational_d,0,(char*)"denominator",0}, + {0} /* sentinel */ +}; + +static PyTypeObject PyRational_Type = { +#if defined(NPY_PY3K) + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + "rational", /* tp_name */ + sizeof(PyRational), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ +#if defined(NPY_PY3K) + 0, /* tp_reserved */ +#else + 0, /* tp_compare */ +#endif + pyrational_repr, /* tp_repr */ + &pyrational_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + pyrational_hash, /* tp_hash */ + 0, /* tp_call */ + pyrational_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Fixed precision rational numbers", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + pyrational_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + pyrational_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + pyrational_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +}; + +/* NumPy support */ + +static PyObject* +npyrational_getitem(void* data, void* arr) { + rational r; + memcpy(&r,data,sizeof(rational)); + return PyRational_FromRational(r); +} + +static int +npyrational_setitem(PyObject* item, void* data, void* arr) { + rational r; + if (PyRational_Check(item)) { + r = ((PyRational*)item)->r; + } + else { + long n = PyInt_AsLong(item); + PyObject* y; + int eq; + if (error_converting(n)) { + return -1; + } + y = PyInt_FromLong(n); + if (!y) { + return -1; + } + eq = PyObject_RichCompareBool(item,y,Py_EQ); + Py_DECREF(y); + if (eq<0) { + return -1; + } + if (!eq) { + PyErr_Format(PyExc_TypeError, + "expected rational, got %s", item->ob_type->tp_name); + return -1; + } + r = make_rational_int(n); + } + memcpy(data,&r,sizeof(rational)); + return 0; +} + +static NPY_INLINE void +byteswap(npy_int32* x) { + char* p = (char*)x; + size_t i; + for (i = 0; i < sizeof(*x)/2; i++) { + size_t j = sizeof(*x)-1-i; + char t = p[i]; + p[i] = p[j]; + p[j] = t; + } +} + +static void +npyrational_copyswapn(void* dst_, npy_intp dstride, void* src_, + npy_intp sstride, npy_intp n, int swap, void* arr) { + char *dst = (char*)dst_, *src = (char*)src_; + npy_intp i; + if (!src) { + return; + } + if (swap) { + for (i = 0; i < n; i++) { + rational* r = (rational*)(dst+dstride*i); + memcpy(r,src+sstride*i,sizeof(rational)); + byteswap(&r->n); + byteswap(&r->dmm); + } + } + else if (dstride == sizeof(rational) && sstride == sizeof(rational)) { + memcpy(dst, src, n*sizeof(rational)); + } + else { + for (i = 0; i < n; i++) { + memcpy(dst + dstride*i, src + sstride*i, sizeof(rational)); + } + } +} + +static void +npyrational_copyswap(void* dst, void* src, int swap, void* arr) { + rational* r; + if (!src) { + return; + } + r = (rational*)dst; + memcpy(r,src,sizeof(rational)); + if (swap) { + byteswap(&r->n); + byteswap(&r->dmm); + } +} + +static int +npyrational_compare(const void* d0, const void* d1, void* arr) { + rational x = *(rational*)d0, + y = *(rational*)d1; + return rational_lt(x,y)?-1:rational_eq(x,y)?0:1; +} + +#define FIND_EXTREME(name,op) \ + static int \ + npyrational_##name(void* data_, npy_intp n, \ + npy_intp* max_ind, void* arr) { \ + const rational* data; \ + npy_intp best_i; \ + rational best_r; \ + npy_intp i; \ + if (!n) { \ + return 0; \ + } \ + data = (rational*)data_; \ + best_i = 0; \ + best_r = data[0]; \ + for (i = 1; i < n; i++) { \ + if (rational_##op(data[i],best_r)) { \ + best_i = i; \ + best_r = data[i]; \ + } \ + } \ + *max_ind = best_i; \ + return 0; \ + } +FIND_EXTREME(argmin,lt) +FIND_EXTREME(argmax,gt) + +static void +npyrational_dot(void* ip0_, npy_intp is0, void* ip1_, npy_intp is1, + void* op, npy_intp n, void* arr) { + rational r = {0}; + const char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_; + npy_intp i; + for (i = 0; i < n; i++) { + r = rational_add(r,rational_multiply(*(rational*)ip0,*(rational*)ip1)); + ip0 += is0; + ip1 += is1; + } + *(rational*)op = r; +} + +static npy_bool +npyrational_nonzero(void* data, void* arr) { + rational r; + memcpy(&r,data,sizeof(r)); + return rational_nonzero(r)?NPY_TRUE:NPY_FALSE; +} + +static int +npyrational_fill(void* data_, npy_intp length, void* arr) { + rational* data = (rational*)data_; + rational delta = rational_subtract(data[1],data[0]); + rational r = data[1]; + npy_intp i; + for (i = 2; i < length; i++) { + r = rational_add(r,delta); + data[i] = r; + } + return 0; +} + +static int +npyrational_fillwithscalar(void* buffer_, npy_intp length, + void* value, void* arr) { + rational r = *(rational*)value; + rational* buffer = (rational*)buffer_; + npy_intp i; + for (i = 0; i < length; i++) { + buffer[i] = r; + } + return 0; +} + +static PyArray_ArrFuncs npyrational_arrfuncs; + +typedef struct { char c; rational r; } align_test; + +PyArray_Descr npyrational_descr = { + PyObject_HEAD_INIT(0) + &PyRational_Type, /* typeobj */ + 'V', /* kind */ + 'r', /* type */ + '=', /* byteorder */ + /* + * For now, we need NPY_NEEDS_PYAPI in order to make numpy detect our + * exceptions. This isn't technically necessary, + * since we're careful about thread safety, and hopefully future + * versions of numpy will recognize that. + */ + NPY_NEEDS_PYAPI | NPY_USE_GETITEM | NPY_USE_SETITEM, /* hasobject */ + 0, /* type_num */ + sizeof(rational), /* elsize */ + offsetof(align_test,r), /* alignment */ + 0, /* subarray */ + 0, /* fields */ + 0, /* names */ + &npyrational_arrfuncs, /* f */ +}; + +#define DEFINE_CAST(From,To,statement) \ + static void \ + npycast_##From##_##To(void* from_, void* to_, npy_intp n, \ + void* fromarr, void* toarr) { \ + const From* from = (From*)from_; \ + To* to = (To*)to_; \ + npy_intp i; \ + for (i = 0; i < n; i++) { \ + From x = from[i]; \ + statement \ + to[i] = y; \ + } \ + } +#define DEFINE_INT_CAST(bits) \ + DEFINE_CAST(npy_int##bits,rational,rational y = make_rational_int(x);) \ + DEFINE_CAST(rational,npy_int##bits,npy_int32 z = rational_int(x); \ + npy_int##bits y = z; if (y != z) set_overflow();) +DEFINE_INT_CAST(8) +DEFINE_INT_CAST(16) +DEFINE_INT_CAST(32) +DEFINE_INT_CAST(64) +DEFINE_CAST(rational,float,double y = rational_double(x);) +DEFINE_CAST(rational,double,double y = rational_double(x);) +DEFINE_CAST(npy_bool,rational,rational y = make_rational_int(x);) +DEFINE_CAST(rational,npy_bool,npy_bool y = rational_nonzero(x);) + +#define BINARY_UFUNC(name,intype0,intype1,outtype,exp) \ + void name(char** args, npy_intp* dimensions, \ + npy_intp* steps, void* data) { \ + npy_intp is0 = steps[0], is1 = steps[1], \ + os = steps[2], n = *dimensions; \ + char *i0 = args[0], *i1 = args[1], *o = args[2]; \ + int k; \ + for (k = 0; k < n; k++) { \ + intype0 x = *(intype0*)i0; \ + intype1 y = *(intype1*)i1; \ + *(outtype*)o = exp; \ + i0 += is0; i1 += is1; o += os; \ + } \ + } +#define RATIONAL_BINARY_UFUNC(name,type,exp) \ + BINARY_UFUNC(rational_ufunc_##name,rational,rational,type,exp) +RATIONAL_BINARY_UFUNC(add,rational,rational_add(x,y)) +RATIONAL_BINARY_UFUNC(subtract,rational,rational_subtract(x,y)) +RATIONAL_BINARY_UFUNC(multiply,rational,rational_multiply(x,y)) +RATIONAL_BINARY_UFUNC(divide,rational,rational_divide(x,y)) +RATIONAL_BINARY_UFUNC(remainder,rational,rational_remainder(x,y)) +RATIONAL_BINARY_UFUNC(floor_divide,rational, + make_rational_int(rational_floor(rational_divide(x,y)))) +PyUFuncGenericFunction rational_ufunc_true_divide = rational_ufunc_divide; +RATIONAL_BINARY_UFUNC(minimum,rational,rational_lt(x,y)?x:y) +RATIONAL_BINARY_UFUNC(maximum,rational,rational_lt(x,y)?y:x) +RATIONAL_BINARY_UFUNC(equal,npy_bool,rational_eq(x,y)) +RATIONAL_BINARY_UFUNC(not_equal,npy_bool,rational_ne(x,y)) +RATIONAL_BINARY_UFUNC(less,npy_bool,rational_lt(x,y)) +RATIONAL_BINARY_UFUNC(greater,npy_bool,rational_gt(x,y)) +RATIONAL_BINARY_UFUNC(less_equal,npy_bool,rational_le(x,y)) +RATIONAL_BINARY_UFUNC(greater_equal,npy_bool,rational_ge(x,y)) + +BINARY_UFUNC(gcd_ufunc,npy_int64,npy_int64,npy_int64,gcd(x,y)) +BINARY_UFUNC(lcm_ufunc,npy_int64,npy_int64,npy_int64,lcm(x,y)) + +#define UNARY_UFUNC(name,type,exp) \ + void rational_ufunc_##name(char** args, npy_intp* dimensions, \ + npy_intp* steps, void* data) { \ + npy_intp is = steps[0], os = steps[1], n = *dimensions; \ + char *i = args[0], *o = args[1]; \ + int k; \ + for (k = 0; k < n; k++) { \ + rational x = *(rational*)i; \ + *(type*)o = exp; \ + i += is; o += os; \ + } \ + } +UNARY_UFUNC(negative,rational,rational_negative(x)) +UNARY_UFUNC(absolute,rational,rational_abs(x)) +UNARY_UFUNC(floor,rational,make_rational_int(rational_floor(x))) +UNARY_UFUNC(ceil,rational,make_rational_int(rational_ceil(x))) +UNARY_UFUNC(trunc,rational,make_rational_int(x.n/d(x))) +UNARY_UFUNC(square,rational,rational_multiply(x,x)) +UNARY_UFUNC(rint,rational,make_rational_int(rational_rint(x))) +UNARY_UFUNC(sign,rational,make_rational_int(rational_sign(x))) +UNARY_UFUNC(reciprocal,rational,rational_inverse(x)) +UNARY_UFUNC(numerator,npy_int64,x.n) +UNARY_UFUNC(denominator,npy_int64,d(x)) + +static NPY_INLINE void +rational_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps) +{ + /* pointers to data for input and output arrays */ + char *ip1 = args[0]; + char *ip2 = args[1]; + char *op = args[2]; + + /* lengths of core dimensions */ + npy_intp dm = dimensions[0]; + npy_intp dn = dimensions[1]; + npy_intp dp = dimensions[2]; + + /* striding over core dimensions */ + npy_intp is1_m = steps[0]; + npy_intp is1_n = steps[1]; + npy_intp is2_n = steps[2]; + npy_intp is2_p = steps[3]; + npy_intp os_m = steps[4]; + npy_intp os_p = steps[5]; + + /* core dimensions counters */ + npy_intp m, p; + + /* calculate dot product for each row/column vector pair */ + for (m = 0; m < dm; m++) { + for (p = 0; p < dp; p++) { + npyrational_dot(ip1, is1_n, ip2, is2_n, op, dn, NULL); + + /* advance to next column of 2nd input array and output array */ + ip2 += is2_p; + op += os_p; + } + + /* reset to first column of 2nd input array and output array */ + ip2 -= is2_p * p; + op -= os_p * p; + + /* advance to next row of 1st input array and output array */ + ip1 += is1_m; + op += os_m; + } +} + + +static void +rational_gufunc_matrix_multiply(char **args, npy_intp *dimensions, + npy_intp *steps, void *NPY_UNUSED(func)) +{ + /* outer dimensions counter */ + npy_intp N_; + + /* length of flattened outer dimensions */ + npy_intp dN = dimensions[0]; + + /* striding over flattened outer dimensions for input and output arrays */ + npy_intp s0 = steps[0]; + npy_intp s1 = steps[1]; + npy_intp s2 = steps[2]; + + /* + * loop through outer dimensions, performing matrix multiply on + * core dimensions for each loop + */ + for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2) { + rational_matrix_multiply(args, dimensions+1, steps+3); + } +} + + +static void +rational_ufunc_test_add(char** args, npy_intp* dimensions, + npy_intp* steps, void* data) { + npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions; + char *i0 = args[0], *i1 = args[1], *o = args[2]; + int k; + for (k = 0; k < n; k++) { + npy_int64 x = *(npy_int64*)i0; + npy_int64 y = *(npy_int64*)i1; + *(rational*)o = rational_add(make_rational_fast(x, 1), + make_rational_fast(y, 1)); + i0 += is0; i1 += is1; o += os; + } +} + + +static void +rational_ufunc_test_add_rationals(char** args, npy_intp* dimensions, + npy_intp* steps, void* data) { + npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions; + char *i0 = args[0], *i1 = args[1], *o = args[2]; + int k; + for (k = 0; k < n; k++) { + rational x = *(rational*)i0; + rational y = *(rational*)i1; + *(rational*)o = rational_add(x, y); + i0 += is0; i1 += is1; o += os; + } +} + + +PyMethodDef module_methods[] = { + {0} /* sentinel */ +}; + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_rational_tests", + NULL, + -1, + module_methods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +#if defined(NPY_PY3K) +#define RETVAL m +PyMODINIT_FUNC PyInit__rational_tests(void) { +#else +#define RETVAL +PyMODINIT_FUNC init_rational_tests(void) { +#endif + + PyObject *m = NULL; + PyObject* numpy_str; + PyObject* numpy; + int npy_rational; + + import_array(); + if (PyErr_Occurred()) { + goto fail; + } + import_umath(); + if (PyErr_Occurred()) { + goto fail; + } + numpy_str = PyUString_FromString("numpy"); + if (!numpy_str) { + goto fail; + } + numpy = PyImport_Import(numpy_str); + Py_DECREF(numpy_str); + if (!numpy) { + goto fail; + } + + /* Can't set this until we import numpy */ + PyRational_Type.tp_base = &PyGenericArrType_Type; + + /* Initialize rational type object */ + if (PyType_Ready(&PyRational_Type) < 0) { + goto fail; + } + + /* Initialize rational descriptor */ + PyArray_InitArrFuncs(&npyrational_arrfuncs); + npyrational_arrfuncs.getitem = npyrational_getitem; + npyrational_arrfuncs.setitem = npyrational_setitem; + npyrational_arrfuncs.copyswapn = npyrational_copyswapn; + npyrational_arrfuncs.copyswap = npyrational_copyswap; + npyrational_arrfuncs.compare = npyrational_compare; + npyrational_arrfuncs.argmin = npyrational_argmin; + npyrational_arrfuncs.argmax = npyrational_argmax; + npyrational_arrfuncs.dotfunc = npyrational_dot; + npyrational_arrfuncs.nonzero = npyrational_nonzero; + npyrational_arrfuncs.fill = npyrational_fill; + npyrational_arrfuncs.fillwithscalar = npyrational_fillwithscalar; + /* Left undefined: scanfunc, fromstr, sort, argsort */ + Py_TYPE(&npyrational_descr) = &PyArrayDescr_Type; + npy_rational = PyArray_RegisterDataType(&npyrational_descr); + if (npy_rational<0) { + goto fail; + } + + /* Support dtype(rational) syntax */ + if (PyDict_SetItemString(PyRational_Type.tp_dict, "dtype", + (PyObject*)&npyrational_descr) < 0) { + goto fail; + } + + /* Register casts to and from rational */ + #define REGISTER_CAST(From,To,from_descr,to_typenum,safe) { \ + PyArray_Descr* from_descr_##From##_##To = (from_descr); \ + if (PyArray_RegisterCastFunc(from_descr_##From##_##To, \ + (to_typenum), \ + npycast_##From##_##To) < 0) { \ + goto fail; \ + } \ + if (safe && PyArray_RegisterCanCast(from_descr_##From##_##To, \ + (to_typenum), \ + NPY_NOSCALAR) < 0) { \ + goto fail; \ + } \ + } + #define REGISTER_INT_CASTS(bits) \ + REGISTER_CAST(npy_int##bits, rational, \ + PyArray_DescrFromType(NPY_INT##bits), npy_rational, 1) \ + REGISTER_CAST(rational, npy_int##bits, &npyrational_descr, \ + NPY_INT##bits, 0) + REGISTER_INT_CASTS(8) + REGISTER_INT_CASTS(16) + REGISTER_INT_CASTS(32) + REGISTER_INT_CASTS(64) + REGISTER_CAST(rational,float,&npyrational_descr,NPY_FLOAT,0) + REGISTER_CAST(rational,double,&npyrational_descr,NPY_DOUBLE,1) + REGISTER_CAST(npy_bool,rational, PyArray_DescrFromType(NPY_BOOL), + npy_rational,1) + REGISTER_CAST(rational,npy_bool,&npyrational_descr,NPY_BOOL,0) + + /* Register ufuncs */ + #define REGISTER_UFUNC(name,...) { \ + PyUFuncObject* ufunc = \ + (PyUFuncObject*)PyObject_GetAttrString(numpy, #name); \ + int _types[] = __VA_ARGS__; \ + if (!ufunc) { \ + goto fail; \ + } \ + if (sizeof(_types)/sizeof(int)!=ufunc->nargs) { \ + PyErr_Format(PyExc_AssertionError, \ + "ufunc %s takes %d arguments, our loop takes %lu", \ + #name, ufunc->nargs, (unsigned long) \ + (sizeof(_types)/sizeof(int))); \ + Py_DECREF(ufunc); \ + goto fail; \ + } \ + if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \ + rational_ufunc_##name, _types, 0) < 0) { \ + Py_DECREF(ufunc); \ + goto fail; \ + } \ + Py_DECREF(ufunc); \ + } + #define REGISTER_UFUNC_BINARY_RATIONAL(name) \ + REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational}) + #define REGISTER_UFUNC_BINARY_COMPARE(name) \ + REGISTER_UFUNC(name, {npy_rational, npy_rational, NPY_BOOL}) + #define REGISTER_UFUNC_UNARY(name) \ + REGISTER_UFUNC(name, {npy_rational, npy_rational}) + /* Binary */ + REGISTER_UFUNC_BINARY_RATIONAL(add) + REGISTER_UFUNC_BINARY_RATIONAL(subtract) + REGISTER_UFUNC_BINARY_RATIONAL(multiply) + REGISTER_UFUNC_BINARY_RATIONAL(divide) + REGISTER_UFUNC_BINARY_RATIONAL(remainder) + REGISTER_UFUNC_BINARY_RATIONAL(true_divide) + REGISTER_UFUNC_BINARY_RATIONAL(floor_divide) + REGISTER_UFUNC_BINARY_RATIONAL(minimum) + REGISTER_UFUNC_BINARY_RATIONAL(maximum) + /* Comparisons */ + REGISTER_UFUNC_BINARY_COMPARE(equal) + REGISTER_UFUNC_BINARY_COMPARE(not_equal) + REGISTER_UFUNC_BINARY_COMPARE(less) + REGISTER_UFUNC_BINARY_COMPARE(greater) + REGISTER_UFUNC_BINARY_COMPARE(less_equal) + REGISTER_UFUNC_BINARY_COMPARE(greater_equal) + /* Unary */ + REGISTER_UFUNC_UNARY(negative) + REGISTER_UFUNC_UNARY(absolute) + REGISTER_UFUNC_UNARY(floor) + REGISTER_UFUNC_UNARY(ceil) + REGISTER_UFUNC_UNARY(trunc) + REGISTER_UFUNC_UNARY(rint) + REGISTER_UFUNC_UNARY(square) + REGISTER_UFUNC_UNARY(reciprocal) + REGISTER_UFUNC_UNARY(sign) + + /* Create module */ +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_rational_tests", module_methods); +#endif + + if (!m) { + goto fail; + } + + /* Add rational type */ + Py_INCREF(&PyRational_Type); + PyModule_AddObject(m,"rational",(PyObject*)&PyRational_Type); + + /* Create matrix multiply generalized ufunc */ + { + int types2[3] = {npy_rational,npy_rational,npy_rational}; + PyObject* gufunc = PyUFunc_FromFuncAndDataAndSignature(0,0,0,0,2,1, + PyUFunc_None,(char*)"matrix_multiply", + (char*)"return result of multiplying two matrices of rationals", + 0,"(m,n),(n,p)->(m,p)"); + if (!gufunc) { + goto fail; + } + if (PyUFunc_RegisterLoopForType((PyUFuncObject*)gufunc, npy_rational, + rational_gufunc_matrix_multiply, types2, 0) < 0) { + goto fail; + } + PyModule_AddObject(m,"matrix_multiply",(PyObject*)gufunc); + } + + /* Create test ufunc with built in input types and rational output type */ + { + int types3[3] = {NPY_INT64,NPY_INT64,npy_rational}; + + PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,2,1, + PyUFunc_None,(char*)"test_add", + (char*)"add two matrices of int64 and return rational matrix",0); + if (!ufunc) { + goto fail; + } + if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, + rational_ufunc_test_add, types3, 0) < 0) { + goto fail; + } + PyModule_AddObject(m,"test_add",(PyObject*)ufunc); + } + + /* Create test ufunc with rational types using RegisterLoopForDescr */ + { + PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,2,1, + PyUFunc_None,(char*)"test_add_rationals", + (char*)"add two matrices of rationals and return rational matrix",0); + PyArray_Descr* types[3] = {&npyrational_descr, + &npyrational_descr, + &npyrational_descr}; + + if (!ufunc) { + goto fail; + } + if (PyUFunc_RegisterLoopForDescr((PyUFuncObject*)ufunc, &npyrational_descr, + rational_ufunc_test_add_rationals, types, 0) < 0) { + goto fail; + } + PyModule_AddObject(m,"test_add_rationals",(PyObject*)ufunc); + } + + /* Create numerator and denominator ufuncs */ + #define NEW_UNARY_UFUNC(name,type,doc) { \ + int types[2] = {npy_rational,type}; \ + PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,1,1, \ + PyUFunc_None,(char*)#name,(char*)doc,0); \ + if (!ufunc) { \ + goto fail; \ + } \ + if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, \ + npy_rational,rational_ufunc_##name,types,0)<0) { \ + goto fail; \ + } \ + PyModule_AddObject(m,#name,(PyObject*)ufunc); \ + } + NEW_UNARY_UFUNC(numerator,NPY_INT64,"rational number numerator"); + NEW_UNARY_UFUNC(denominator,NPY_INT64,"rational number denominator"); + + /* Create gcd and lcm ufuncs */ + #define GCD_LCM_UFUNC(name,type,doc) { \ + static const PyUFuncGenericFunction func[1] = {name##_ufunc}; \ + static const char types[3] = {type,type,type}; \ + static void* data[1] = {0}; \ + PyObject* ufunc = PyUFunc_FromFuncAndData( \ + (PyUFuncGenericFunction*)func, data,(char*)types, \ + 1,2,1,PyUFunc_One,(char*)#name,(char*)doc,0); \ + if (!ufunc) { \ + goto fail; \ + } \ + PyModule_AddObject(m,#name,(PyObject*)ufunc); \ + } + GCD_LCM_UFUNC(gcd,NPY_INT64,"greatest common denominator of two integers"); + GCD_LCM_UFUNC(lcm,NPY_INT64,"least common multiple of two integers"); + + return RETVAL; + +fail: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "cannot load _rational_tests module."); + } +#if defined(NPY_PY3K) + if (m) { + Py_DECREF(m); + m = NULL; + } +#endif + return RETVAL; +} diff --git a/numpy/core/src/umath/_struct_ufunc_tests.c.src b/numpy/core/src/umath/_struct_ufunc_tests.c.src new file mode 100644 index 000000000..b831d5c2a --- /dev/null +++ b/numpy/core/src/umath/_struct_ufunc_tests.c.src @@ -0,0 +1,124 @@ +#define NPY_NO_DEPRECATED_API NPY_API_VERSION + +#include "Python.h" +#include "math.h" +#include "numpy/ndarraytypes.h" +#include "numpy/ufuncobject.h" +#include "numpy/npy_3kcompat.h" + + +/* + * struct_ufunc_test.c + * This is the C code for creating your own + * NumPy ufunc for a structured array dtype. + * + * Details explaining the Python-C API can be found under + * 'Extending and Embedding' and 'Python/C API' at + * docs.python.org . + */ + +static PyMethodDef StructUfuncTestMethods[] = { + {NULL, NULL, 0, NULL} +}; + +/* The loop definition must precede the PyMODINIT_FUNC. */ + +static void add_uint64_triplet(char **args, npy_intp *dimensions, + npy_intp* steps, void* data) +{ + npy_intp i; + npy_intp is1=steps[0]; + npy_intp is2=steps[1]; + npy_intp os=steps[2]; + npy_intp n=dimensions[0]; + npy_uint64 *x, *y, *z; + + char *i1=args[0]; + char *i2=args[1]; + char *op=args[2]; + + for (i = 0; i < n; i++) { + + x = (npy_uint64*)i1; + y = (npy_uint64*)i2; + z = (npy_uint64*)op; + + z[0] = x[0] + y[0]; + z[1] = x[1] + y[1]; + z[2] = x[2] + y[2]; + + i1 += is1; + i2 += is2; + op += os; + } +} + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_struct_ufunc_tests", + NULL, + -1, + StructUfuncTestMethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +#if defined(NPY_PY3K) +PyMODINIT_FUNC PyInit__struct_ufunc_tests(void) +#else +PyMODINIT_FUNC init_struct_ufunc_tests(void) +#endif +{ + PyObject *m, *add_triplet, *d; + PyObject *dtype_dict; + PyArray_Descr *dtype; + PyArray_Descr *dtypes[3]; + +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_struct_ufunc_tests", StructUfuncTestMethods); +#endif + + if (m == NULL) { +#if defined(NPY_PY3K) + return NULL; +#else + return; +#endif + } + + import_array(); + import_umath(); + + add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1, + PyUFunc_None, "add_triplet", + "add_triplet_docstring", 0); + + dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]", + "f0", "u8", "f1", "u8", "f2", "u8"); + PyArray_DescrConverter(dtype_dict, &dtype); + Py_DECREF(dtype_dict); + + dtypes[0] = dtype; + dtypes[1] = dtype; + dtypes[2] = dtype; + + PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet, + dtype, + &add_uint64_triplet, + dtypes, + NULL); + + d = PyModule_GetDict(m); + + PyDict_SetItemString(d, "add_triplet", add_triplet); + Py_DECREF(add_triplet); +#if defined(NPY_PY3K) + return m; +#endif +} diff --git a/numpy/core/src/umath/_umath_tests.c.src b/numpy/core/src/umath/_umath_tests.c.src new file mode 100644 index 000000000..120ce0332 --- /dev/null +++ b/numpy/core/src/umath/_umath_tests.c.src @@ -0,0 +1,413 @@ +/* -*- c -*- */ + +/* + ***************************************************************************** + ** INCLUDES ** + ***************************************************************************** + */ +#define NPY_NO_DEPRECATED_API NPY_API_VERSION + +#include "Python.h" +#include "numpy/arrayobject.h" +#include "numpy/ufuncobject.h" +#include "numpy/npy_math.h" + +#include "npy_pycompat.h" + +#include "npy_config.h" + +/* + ***************************************************************************** + ** BASICS ** + ***************************************************************************** + */ + +#define INIT_OUTER_LOOP_1 \ + npy_intp dN = *dimensions++;\ + npy_intp N_; \ + npy_intp s0 = *steps++; + +#define INIT_OUTER_LOOP_2 \ + INIT_OUTER_LOOP_1 \ + npy_intp s1 = *steps++; + +#define INIT_OUTER_LOOP_3 \ + INIT_OUTER_LOOP_2 \ + npy_intp s2 = *steps++; + +#define INIT_OUTER_LOOP_4 \ + INIT_OUTER_LOOP_3 \ + npy_intp s3 = *steps++; + +#define BEGIN_OUTER_LOOP_2 \ + for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1) { + +#define BEGIN_OUTER_LOOP_3 \ + for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2) { + +#define BEGIN_OUTER_LOOP_4 \ + for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2, args[3] += s3) { + +#define END_OUTER_LOOP } + + +/* + ***************************************************************************** + ** UFUNC LOOPS ** + ***************************************************************************** + */ + +char *inner1d_signature = "(i),(i)->()"; + +/**begin repeat + + #TYPE=LONG,DOUBLE# + #typ=npy_long,npy_double# +*/ + +/* + * This implements the function + * out[n] = sum_i { in1[n, i] * in2[n, i] }. + */ + +static void +@TYPE@_inner1d(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) +{ + INIT_OUTER_LOOP_3 + npy_intp di = dimensions[0]; + npy_intp i; + npy_intp is1=steps[0], is2=steps[1]; + BEGIN_OUTER_LOOP_3 + char *ip1=args[0], *ip2=args[1], *op=args[2]; + @typ@ sum = 0; + for (i = 0; i < di; i++) { + sum += (*(@typ@ *)ip1) * (*(@typ@ *)ip2); + ip1 += is1; + ip2 += is2; + } + *(@typ@ *)op = sum; + END_OUTER_LOOP +} + +/**end repeat**/ + +char *innerwt_signature = "(i),(i),(i)->()"; + +/**begin repeat + + #TYPE=LONG,DOUBLE# + #typ=npy_long,npy_double# +*/ + + +/* + * This implements the function + * out[n] = sum_i { in1[n, i] * in2[n, i] * in3[n, i] }. + */ + +static void +@TYPE@_innerwt(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) +{ + INIT_OUTER_LOOP_4 + npy_intp di = dimensions[0]; + npy_intp i; + npy_intp is1=steps[0], is2=steps[1], is3=steps[2]; + BEGIN_OUTER_LOOP_4 + char *ip1=args[0], *ip2=args[1], *ip3=args[2], *op=args[3]; + @typ@ sum = 0; + for (i = 0; i < di; i++) { + sum += (*(@typ@ *)ip1) * (*(@typ@ *)ip2) * (*(@typ@ *)ip3); + ip1 += is1; + ip2 += is2; + ip3 += is3; + } + *(@typ@ *)op = sum; + END_OUTER_LOOP +} + +/**end repeat**/ + +char *matrix_multiply_signature = "(m,n),(n,p)->(m,p)"; + +/**begin repeat + + #TYPE=FLOAT,DOUBLE,LONG# + #typ=npy_float,npy_double,npy_long# +*/ + +/* + * This implements the function + * out[k, m, p] = sum_n { in1[k, m, n] * in2[k, n, p] }. + */ + +static void +@TYPE@_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) +{ + /* no BLAS is available */ + INIT_OUTER_LOOP_3 + npy_intp dm = dimensions[0]; + npy_intp dn = dimensions[1]; + npy_intp dp = dimensions[2]; + npy_intp m,n,p; + npy_intp is1_m=steps[0], is1_n=steps[1], is2_n=steps[2], is2_p=steps[3], + os_m=steps[4], os_p=steps[5]; + npy_intp ib1_n = is1_n*dn; + npy_intp ib2_n = is2_n*dn; + npy_intp ib2_p = is2_p*dp; + npy_intp ob_p = os_p *dp; + if (dn == 0) { + /* No operand, need to zero the output */ + BEGIN_OUTER_LOOP_3 + char *op=args[2]; + for (m = 0; m < dm; m++) { + for (p = 0; p < dp; p++) { + *(@typ@ *)op = 0; + op += os_p; + } + op += os_m - ob_p; + } + END_OUTER_LOOP + return; + } + BEGIN_OUTER_LOOP_3 + char *ip1=args[0], *ip2=args[1], *op=args[2]; + for (m = 0; m < dm; m++) { + for (n = 0; n < dn; n++) { + @typ@ val1 = (*(@typ@ *)ip1); + for (p = 0; p < dp; p++) { + if (n == 0) *(@typ@ *)op = 0; + *(@typ@ *)op += val1 * (*(@typ@ *)ip2); + ip2 += is2_p; + op += os_p; + } + ip2 -= ib2_p; + op -= ob_p; + ip1 += is1_n; + ip2 += is2_n; + } + ip1 -= ib1_n; + ip2 -= ib2_n; + ip1 += is1_m; + op += os_m; + } + END_OUTER_LOOP +} + +/**end repeat**/ + +char *euclidean_pdist_signature = "(n,d)->(p)"; + +/**begin repeat + + #TYPE=FLOAT,DOUBLE# + #typ=npy_float,npy_double# + #sqrt_func=sqrtf,sqrt# +*/ + +/* + * This implements the function + * out[j*(2*n-3-j)+k-1] = sum_d { (in1[j, d] - in1[k, d])^2 } + * with 0 < k < j < n, i.e. computes all unique pairwise euclidean distances. + */ + +static void +@TYPE@_euclidean_pdist(char **args, npy_intp *dimensions, npy_intp *steps, + void *NPY_UNUSED(func)) +{ + INIT_OUTER_LOOP_2 + npy_intp len_n = *dimensions++; + npy_intp len_d = *dimensions++; + npy_intp stride_n = *steps++; + npy_intp stride_d = *steps++; + npy_intp stride_p = *steps; + + assert(len_n * (len_n - 1) / 2 == *dimensions); + + BEGIN_OUTER_LOOP_2 + const char *data_this = (const char *)args[0]; + char *data_out = args[1]; + npy_intp n; + for (n = 0; n < len_n; ++n) { + const char *data_that = data_this + stride_n; + npy_intp nn; + for (nn = n + 1; nn < len_n; ++nn) { + const char *ptr_this = data_this; + const char *ptr_that = data_that; + @typ@ out = 0; + npy_intp d; + for (d = 0; d < len_d; ++d) { + const @typ@ delta = *(const @typ@ *)ptr_this - + *(const @typ@ *)ptr_that; + out += delta * delta; + ptr_this += stride_d; + ptr_that += stride_d; + } + *(@typ@ *)data_out = npy_@sqrt_func@(out); + data_that += stride_n; + data_out += stride_p; + } + data_this += stride_n; + } + END_OUTER_LOOP +} + +/**end repeat**/ + + +static PyUFuncGenericFunction inner1d_functions[] = { LONG_inner1d, DOUBLE_inner1d }; +static void * inner1d_data[] = { (void *)NULL, (void *)NULL }; +static char inner1d_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static PyUFuncGenericFunction innerwt_functions[] = { LONG_innerwt, DOUBLE_innerwt }; +static void * innerwt_data[] = { (void *)NULL, (void *)NULL }; +static char innerwt_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static PyUFuncGenericFunction matrix_multiply_functions[] = { LONG_matrix_multiply, FLOAT_matrix_multiply, DOUBLE_matrix_multiply }; +static void *matrix_multiply_data[] = { (void *)NULL, (void *)NULL, (void *)NULL }; +static char matrix_multiply_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; + +static PyUFuncGenericFunction euclidean_pdist_functions[] = + { FLOAT_euclidean_pdist, DOUBLE_euclidean_pdist }; +static void *eucldiean_pdist_data[] = { (void *)NULL, (void *)NULL }; +static char euclidean_pdist_signatures[] = { NPY_FLOAT, NPY_FLOAT, + NPY_DOUBLE, NPY_DOUBLE }; + + +static void +addUfuncs(PyObject *dictionary) { + PyObject *f; + + f = PyUFunc_FromFuncAndDataAndSignature(inner1d_functions, inner1d_data, + inner1d_signatures, 2, 2, 1, PyUFunc_None, "inner1d", + "inner on the last dimension and broadcast on the rest \n" + " \"(i),(i)->()\" \n", + 0, inner1d_signature); + PyDict_SetItemString(dictionary, "inner1d", f); + Py_DECREF(f); + f = PyUFunc_FromFuncAndDataAndSignature(innerwt_functions, innerwt_data, + innerwt_signatures, 2, 3, 1, PyUFunc_None, "innerwt", + "inner1d with a weight argument \n" + " \"(i),(i),(i)->()\" \n", + 0, innerwt_signature); + PyDict_SetItemString(dictionary, "innerwt", f); + Py_DECREF(f); + f = PyUFunc_FromFuncAndDataAndSignature(matrix_multiply_functions, + matrix_multiply_data, matrix_multiply_signatures, + 3, 2, 1, PyUFunc_None, "matrix_multiply", + "matrix multiplication on last two dimensions \n" + " \"(m,n),(n,p)->(m,p)\" \n", + 0, matrix_multiply_signature); + PyDict_SetItemString(dictionary, "matrix_multiply", f); + Py_DECREF(f); + f = PyUFunc_FromFuncAndDataAndSignature(euclidean_pdist_functions, + eucldiean_pdist_data, euclidean_pdist_signatures, + 2, 1, 1, PyUFunc_None, "euclidean_pdist", + "pairwise euclidean distance on last two dimensions \n" + " \"(n,d)->(p)\" \n", + 0, euclidean_pdist_signature); + PyDict_SetItemString(dictionary, "euclidean_pdist", f); + Py_DECREF(f); + f = PyUFunc_FromFuncAndDataAndSignature(inner1d_functions, inner1d_data, + inner1d_signatures, 2, 2, 1, PyUFunc_None, "inner1d_no_doc", + NULL, + 0, inner1d_signature); + PyDict_SetItemString(dictionary, "inner1d_no_doc", f); + Py_DECREF(f); +} + + +static PyObject * +UMath_Tests_test_signature(PyObject *NPY_UNUSED(dummy), PyObject *args) +{ + int nin, nout; + PyObject *signature, *sig_str; + PyObject *f; + int core_enabled; + + if (!PyArg_ParseTuple(args, "iiO", &nin, &nout, &signature)) return NULL; + + + if (PyString_Check(signature)) { + sig_str = signature; + } else if (PyUnicode_Check(signature)) { + sig_str = PyUnicode_AsUTF8String(signature); + } else { + PyErr_SetString(PyExc_ValueError, "signature should be a string"); + return NULL; + } + + f = PyUFunc_FromFuncAndDataAndSignature(NULL, NULL, NULL, + 0, nin, nout, PyUFunc_None, "no name", + "doc:none", + 1, PyString_AS_STRING(sig_str)); + if (sig_str != signature) { + Py_DECREF(sig_str); + } + if (f == NULL) return NULL; + core_enabled = ((PyUFuncObject*)f)->core_enabled; + Py_DECREF(f); + return Py_BuildValue("i", core_enabled); +} + +static PyMethodDef UMath_TestsMethods[] = { + {"test_signature", UMath_Tests_test_signature, METH_VARARGS, + "Test signature parsing of ufunc. \n" + "Arguments: nin nout signature \n" + "If fails, it returns NULL. Otherwise it will returns 0 for scalar ufunc " + "and 1 for generalized ufunc. \n", + }, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +#if defined(NPY_PY3K) +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_umath_tests", + NULL, + -1, + UMath_TestsMethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +#if defined(NPY_PY3K) +#define RETVAL m +PyMODINIT_FUNC PyInit__umath_tests(void) +#else +#define RETVAL +PyMODINIT_FUNC +init_umath_tests(void) +#endif +{ + PyObject *m; + PyObject *d; + PyObject *version; + +#if defined(NPY_PY3K) + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_umath_tests", UMath_TestsMethods); +#endif + if (m == NULL) + return RETVAL; + + import_array(); + import_ufunc(); + + d = PyModule_GetDict(m); + + version = PyString_FromString("0.1"); + PyDict_SetItemString(d, "__version__", version); + Py_DECREF(version); + + /* Load the ufunc operators into the module's namespace */ + addUfuncs(d); + + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, + "cannot load _umath_tests module."); + } + + return RETVAL; +} diff --git a/numpy/core/src/umath/operand_flag_tests.c.src b/numpy/core/src/umath/operand_flag_tests.c.src deleted file mode 100644 index 046c37595..000000000 --- a/numpy/core/src/umath/operand_flag_tests.c.src +++ /dev/null @@ -1,105 +0,0 @@ -#define NPY_NO_DEPRECATED_API NPY_API_VERSION - -#include -#include -#include -#include "numpy/npy_3kcompat.h" -#include -#include - - -static PyMethodDef TestMethods[] = { - {NULL, NULL, 0, NULL} -}; - - -static void -inplace_add(char **args, npy_intp *dimensions, npy_intp *steps, void *data) -{ - npy_intp i; - npy_intp n = dimensions[0]; - char *in1 = args[0]; - char *in2 = args[1]; - npy_intp in1_step = steps[0]; - npy_intp in2_step = steps[1]; - - for (i = 0; i < n; i++) { - (*(long *)in1) = *(long*)in1 + *(long*)in2; - in1 += in1_step; - in2 += in2_step; - } -} - - -/*This a pointer to the above function*/ -PyUFuncGenericFunction funcs[1] = {&inplace_add}; - -/* These are the input and return dtypes of logit.*/ -static char types[2] = {NPY_LONG, NPY_LONG}; - -static void *data[1] = {NULL}; - -#if defined(NPY_PY3K) -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "operand_flag_tests", - NULL, - -1, - TestMethods, - NULL, - NULL, - NULL, - NULL -}; - -#define RETVAL m -PyMODINIT_FUNC PyInit_operand_flag_tests(void) -{ -#else -#define RETVAL -PyMODINIT_FUNC initoperand_flag_tests(void) -{ -#endif - PyObject *m = NULL; - PyObject *ufunc; - -#if defined(NPY_PY3K) - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule("operand_flag_tests", TestMethods); -#endif - if (m == NULL) { - goto fail; - } - - import_array(); - import_umath(); - - ufunc = PyUFunc_FromFuncAndData(funcs, data, types, 1, 2, 0, - PyUFunc_None, "inplace_add", - "inplace_add_docstring", 0); - - /* - * Set flags to turn off buffering for first input operand, - * so that result can be written back to input operand. - */ - ((PyUFuncObject*)ufunc)->op_flags[0] = NPY_ITER_READWRITE; - ((PyUFuncObject*)ufunc)->iter_flags = NPY_ITER_REDUCE_OK; - PyModule_AddObject(m, "inplace_add", (PyObject*)ufunc); - - return RETVAL; - -fail: - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, - "cannot load operand_flag_tests module."); - } -#if defined(NPY_PY3K) - if (m) { - Py_DECREF(m); - m = NULL; - } -#endif - return RETVAL; - -} diff --git a/numpy/core/src/umath/struct_ufunc_test.c.src b/numpy/core/src/umath/struct_ufunc_test.c.src deleted file mode 100644 index 9a6318f47..000000000 --- a/numpy/core/src/umath/struct_ufunc_test.c.src +++ /dev/null @@ -1,124 +0,0 @@ -#define NPY_NO_DEPRECATED_API NPY_API_VERSION - -#include "Python.h" -#include "math.h" -#include "numpy/ndarraytypes.h" -#include "numpy/ufuncobject.h" -#include "numpy/npy_3kcompat.h" - - -/* - * struct_ufunc_test.c - * This is the C code for creating your own - * NumPy ufunc for a structured array dtype. - * - * Details explaining the Python-C API can be found under - * 'Extending and Embedding' and 'Python/C API' at - * docs.python.org . - */ - -static PyMethodDef StructUfuncTestMethods[] = { - {NULL, NULL, 0, NULL} -}; - -/* The loop definition must precede the PyMODINIT_FUNC. */ - -static void add_uint64_triplet(char **args, npy_intp *dimensions, - npy_intp* steps, void* data) -{ - npy_intp i; - npy_intp is1=steps[0]; - npy_intp is2=steps[1]; - npy_intp os=steps[2]; - npy_intp n=dimensions[0]; - npy_uint64 *x, *y, *z; - - char *i1=args[0]; - char *i2=args[1]; - char *op=args[2]; - - for (i = 0; i < n; i++) { - - x = (npy_uint64*)i1; - y = (npy_uint64*)i2; - z = (npy_uint64*)op; - - z[0] = x[0] + y[0]; - z[1] = x[1] + y[1]; - z[2] = x[2] + y[2]; - - i1 += is1; - i2 += is2; - op += os; - } -} - -#if defined(NPY_PY3K) -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "struct_ufunc_test", - NULL, - -1, - StructUfuncTestMethods, - NULL, - NULL, - NULL, - NULL -}; -#endif - -#if defined(NPY_PY3K) -PyMODINIT_FUNC PyInit_struct_ufunc_test(void) -#else -PyMODINIT_FUNC initstruct_ufunc_test(void) -#endif -{ - PyObject *m, *add_triplet, *d; - PyObject *dtype_dict; - PyArray_Descr *dtype; - PyArray_Descr *dtypes[3]; - -#if defined(NPY_PY3K) - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule("struct_ufunc_test", StructUfuncTestMethods); -#endif - - if (m == NULL) { -#if defined(NPY_PY3K) - return NULL; -#else - return; -#endif - } - - import_array(); - import_umath(); - - add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1, - PyUFunc_None, "add_triplet", - "add_triplet_docstring", 0); - - dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]", - "f0", "u8", "f1", "u8", "f2", "u8"); - PyArray_DescrConverter(dtype_dict, &dtype); - Py_DECREF(dtype_dict); - - dtypes[0] = dtype; - dtypes[1] = dtype; - dtypes[2] = dtype; - - PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet, - dtype, - &add_uint64_triplet, - dtypes, - NULL); - - d = PyModule_GetDict(m); - - PyDict_SetItemString(d, "add_triplet", add_triplet); - Py_DECREF(add_triplet); -#if defined(NPY_PY3K) - return m; -#endif -} diff --git a/numpy/core/src/umath/test_rational.c.src b/numpy/core/src/umath/test_rational.c.src deleted file mode 100644 index ffc92b732..000000000 --- a/numpy/core/src/umath/test_rational.c.src +++ /dev/null @@ -1,1409 +0,0 @@ -/* Fixed size rational numbers exposed to Python */ - -#define NPY_NO_DEPRECATED_API NPY_API_VERSION - -#include -#include -#include -#include -#include -#include - -#include "common.h" /* for error_converting */ - - -/* Relevant arithmetic exceptions */ - -/* Uncomment the following line to work around a bug in numpy */ -/* #define ACQUIRE_GIL */ - -static void -set_overflow(void) { -#ifdef ACQUIRE_GIL - /* Need to grab the GIL to dodge a bug in numpy */ - PyGILState_STATE state = PyGILState_Ensure(); -#endif - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_OverflowError, - "overflow in rational arithmetic"); - } -#ifdef ACQUIRE_GIL - PyGILState_Release(state); -#endif -} - -static void -set_zero_divide(void) { -#ifdef ACQUIRE_GIL - /* Need to grab the GIL to dodge a bug in numpy */ - PyGILState_STATE state = PyGILState_Ensure(); -#endif - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ZeroDivisionError, - "zero divide in rational arithmetic"); - } -#ifdef ACQUIRE_GIL - PyGILState_Release(state); -#endif -} - -/* Integer arithmetic utilities */ - -static NPY_INLINE npy_int32 -safe_neg(npy_int32 x) { - if (x==(npy_int32)1<<31) { - set_overflow(); - } - return -x; -} - -static NPY_INLINE npy_int32 -safe_abs32(npy_int32 x) { - npy_int32 nx; - if (x>=0) { - return x; - } - nx = -x; - if (nx<0) { - set_overflow(); - } - return nx; -} - -static NPY_INLINE npy_int64 -safe_abs64(npy_int64 x) { - npy_int64 nx; - if (x>=0) { - return x; - } - nx = -x; - if (nx<0) { - set_overflow(); - } - return nx; -} - -static NPY_INLINE npy_int64 -gcd(npy_int64 x, npy_int64 y) { - x = safe_abs64(x); - y = safe_abs64(y); - if (x < y) { - npy_int64 t = x; - x = y; - y = t; - } - while (y) { - npy_int64 t; - x = x%y; - t = x; - x = y; - y = t; - } - return x; -} - -static NPY_INLINE npy_int64 -lcm(npy_int64 x, npy_int64 y) { - npy_int64 lcm; - if (!x || !y) { - return 0; - } - x /= gcd(x,y); - lcm = x*y; - if (lcm/y!=x) { - set_overflow(); - } - return safe_abs64(lcm); -} - -/* Fixed precision rational numbers */ - -typedef struct { - /* numerator */ - npy_int32 n; - /* - * denominator minus one: numpy.zeros() uses memset(0) for non-object - * types, so need to ensure that rational(0) has all zero bytes - */ - npy_int32 dmm; -} rational; - -static NPY_INLINE rational -make_rational_int(npy_int64 n) { - rational r = {(npy_int32)n,0}; - if (r.n != n) { - set_overflow(); - } - return r; -} - -static rational -make_rational_slow(npy_int64 n_, npy_int64 d_) { - rational r = {0}; - if (!d_) { - set_zero_divide(); - } - else { - npy_int64 g = gcd(n_,d_); - npy_int32 d; - n_ /= g; - d_ /= g; - r.n = (npy_int32)n_; - d = (npy_int32)d_; - if (r.n!=n_ || d!=d_) { - set_overflow(); - } - else { - if (d <= 0) { - d = -d; - r.n = safe_neg(r.n); - } - r.dmm = d-1; - } - } - return r; -} - -static NPY_INLINE npy_int32 -d(rational r) { - return r.dmm+1; -} - -/* Assumes d_ > 0 */ -static rational -make_rational_fast(npy_int64 n_, npy_int64 d_) { - npy_int64 g = gcd(n_,d_); - rational r; - n_ /= g; - d_ /= g; - r.n = (npy_int32)n_; - r.dmm = (npy_int32)(d_-1); - if (r.n!=n_ || r.dmm+1!=d_) { - set_overflow(); - } - return r; -} - -static NPY_INLINE rational -rational_negative(rational r) { - rational x; - x.n = safe_neg(r.n); - x.dmm = r.dmm; - return x; -} - -static NPY_INLINE rational -rational_add(rational x, rational y) { - /* - * Note that the numerator computation can never overflow int128_t, - * since each term is strictly under 2**128/4 (since d > 0). - */ - return make_rational_fast((npy_int64)x.n*d(y)+(npy_int64)d(x)*y.n, - (npy_int64)d(x)*d(y)); -} - -static NPY_INLINE rational -rational_subtract(rational x, rational y) { - /* We're safe from overflow as with + */ - return make_rational_fast((npy_int64)x.n*d(y)-(npy_int64)d(x)*y.n, - (npy_int64)d(x)*d(y)); -} - -static NPY_INLINE rational -rational_multiply(rational x, rational y) { - /* We're safe from overflow as with + */ - return make_rational_fast((npy_int64)x.n*y.n,(npy_int64)d(x)*d(y)); -} - -static NPY_INLINE rational -rational_divide(rational x, rational y) { - return make_rational_slow((npy_int64)x.n*d(y),(npy_int64)d(x)*y.n); -} - -static NPY_INLINE npy_int64 -rational_floor(rational x) { - /* Always round down */ - if (x.n>=0) { - return x.n/d(x); - } - /* - * This can be done without casting up to 64 bits, but it requires - * working out all the sign cases - */ - return -((-(npy_int64)x.n+d(x)-1)/d(x)); -} - -static NPY_INLINE npy_int64 -rational_ceil(rational x) { - return -rational_floor(rational_negative(x)); -} - -static NPY_INLINE rational -rational_remainder(rational x, rational y) { - return rational_subtract(x, rational_multiply(y,make_rational_int( - rational_floor(rational_divide(x,y))))); -} - -static NPY_INLINE rational -rational_abs(rational x) { - rational y; - y.n = safe_abs32(x.n); - y.dmm = x.dmm; - return y; -} - -static NPY_INLINE npy_int64 -rational_rint(rational x) { - /* - * Round towards nearest integer, moving exact half integers towards - * zero - */ - npy_int32 d_ = d(x); - return (2*(npy_int64)x.n+(x.n<0?-d_:d_))/(2*(npy_int64)d_); -} - -static NPY_INLINE int -rational_sign(rational x) { - return x.n<0?-1:x.n==0?0:1; -} - -static NPY_INLINE rational -rational_inverse(rational x) { - rational y = {0}; - if (!x.n) { - set_zero_divide(); - } - else { - npy_int32 d_; - y.n = d(x); - d_ = x.n; - if (d_ <= 0) { - d_ = safe_neg(d_); - y.n = -y.n; - } - y.dmm = d_-1; - } - return y; -} - -static NPY_INLINE int -rational_eq(rational x, rational y) { - /* - * Since we enforce d > 0, and store fractions in reduced form, - * equality is easy. - */ - return x.n==y.n && x.dmm==y.dmm; -} - -static NPY_INLINE int -rational_ne(rational x, rational y) { - return !rational_eq(x,y); -} - -static NPY_INLINE int -rational_lt(rational x, rational y) { - return (npy_int64)x.n*d(y) < (npy_int64)y.n*d(x); -} - -static NPY_INLINE int -rational_gt(rational x, rational y) { - return rational_lt(y,x); -} - -static NPY_INLINE int -rational_le(rational x, rational y) { - return !rational_lt(y,x); -} - -static NPY_INLINE int -rational_ge(rational x, rational y) { - return !rational_lt(x,y); -} - -static NPY_INLINE npy_int32 -rational_int(rational x) { - return x.n/d(x); -} - -static NPY_INLINE double -rational_double(rational x) { - return (double)x.n/d(x); -} - -static NPY_INLINE int -rational_nonzero(rational x) { - return x.n!=0; -} - -static int -scan_rational(const char** s, rational* x) { - long n,d; - int offset; - const char* ss; - if (sscanf(*s,"%ld%n",&n,&offset)<=0) { - return 0; - } - ss = *s+offset; - if (*ss!='/') { - *s = ss; - *x = make_rational_int(n); - return 1; - } - ss++; - if (sscanf(ss,"%ld%n",&d,&offset)<=0 || d<=0) { - return 0; - } - *s = ss+offset; - *x = make_rational_slow(n,d); - return 1; -} - -/* Expose rational to Python as a numpy scalar */ - -typedef struct { - PyObject_HEAD - rational r; -} PyRational; - -static PyTypeObject PyRational_Type; - -static NPY_INLINE int -PyRational_Check(PyObject* object) { - return PyObject_IsInstance(object,(PyObject*)&PyRational_Type); -} - -static PyObject* -PyRational_FromRational(rational x) { - PyRational* p = (PyRational*)PyRational_Type.tp_alloc(&PyRational_Type,0); - if (p) { - p->r = x; - } - return (PyObject*)p; -} - -static PyObject* -pyrational_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { - Py_ssize_t size; - PyObject* x[2]; - long n[2]={0,1}; - int i; - rational r; - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "constructor takes no keyword arguments"); - return 0; - } - size = PyTuple_GET_SIZE(args); - if (size > 2) { - PyErr_SetString(PyExc_TypeError, - "expected rational or numerator and optional denominator"); - return 0; - } - - if (size == 1) { - x[0] = PyTuple_GET_ITEM(args, 0); - if (PyRational_Check(x[0])) { - Py_INCREF(x[0]); - return x[0]; - } - else if (PyString_Check(x[0])) { - const char* s = PyString_AS_STRING(x[0]); - rational x; - if (scan_rational(&s,&x)) { - const char* p; - for (p = s; *p; p++) { - if (!isspace(*p)) { - goto bad; - } - } - return PyRational_FromRational(x); - } - bad: - PyErr_Format(PyExc_ValueError, - "invalid rational literal '%s'",s); - return 0; - } - } - - for (i=0; iob_type->tp_name); - } - return 0; - } - /* Check that we had an exact integer */ - y = PyInt_FromLong(n[i]); - if (!y) { - return 0; - } - eq = PyObject_RichCompareBool(x[i],y,Py_EQ); - Py_DECREF(y); - if (eq<0) { - return 0; - } - if (!eq) { - PyErr_Format(PyExc_TypeError, - "expected integer %s, got %s", - (i ? "denominator" : "numerator"), - x[i]->ob_type->tp_name); - return 0; - } - } - r = make_rational_slow(n[0],n[1]); - if (PyErr_Occurred()) { - return 0; - } - return PyRational_FromRational(r); -} - -/* - * Returns Py_NotImplemented on most conversion failures, or raises an - * overflow error for too long ints - */ -#define AS_RATIONAL(dst,object) \ - { \ - dst.n = 0; \ - if (PyRational_Check(object)) { \ - dst = ((PyRational*)object)->r; \ - } \ - else { \ - PyObject* y_; \ - int eq_; \ - long n_ = PyInt_AsLong(object); \ - if (error_converting(n_)) { \ - if (PyErr_ExceptionMatches(PyExc_TypeError)) { \ - PyErr_Clear(); \ - Py_INCREF(Py_NotImplemented); \ - return Py_NotImplemented; \ - } \ - return 0; \ - } \ - y_ = PyInt_FromLong(n_); \ - if (!y_) { \ - return 0; \ - } \ - eq_ = PyObject_RichCompareBool(object,y_,Py_EQ); \ - Py_DECREF(y_); \ - if (eq_<0) { \ - return 0; \ - } \ - if (!eq_) { \ - Py_INCREF(Py_NotImplemented); \ - return Py_NotImplemented; \ - } \ - dst = make_rational_int(n_); \ - } \ - } - -static PyObject* -pyrational_richcompare(PyObject* a, PyObject* b, int op) { - rational x, y; - int result = 0; - AS_RATIONAL(x,a); - AS_RATIONAL(y,b); - #define OP(py,op) case py: result = rational_##op(x,y); break; - switch (op) { - OP(Py_LT,lt) - OP(Py_LE,le) - OP(Py_EQ,eq) - OP(Py_NE,ne) - OP(Py_GT,gt) - OP(Py_GE,ge) - }; - #undef OP - return PyBool_FromLong(result); -} - -static PyObject* -pyrational_repr(PyObject* self) { - rational x = ((PyRational*)self)->r; - if (d(x)!=1) { - return PyUString_FromFormat( - "rational(%ld,%ld)",(long)x.n,(long)d(x)); - } - else { - return PyUString_FromFormat( - "rational(%ld)",(long)x.n); - } -} - -static PyObject* -pyrational_str(PyObject* self) { - rational x = ((PyRational*)self)->r; - if (d(x)!=1) { - return PyString_FromFormat( - "%ld/%ld",(long)x.n,(long)d(x)); - } - else { - return PyString_FromFormat( - "%ld",(long)x.n); - } -} - -static npy_hash_t -pyrational_hash(PyObject* self) { - rational x = ((PyRational*)self)->r; - /* Use a fairly weak hash as Python expects */ - long h = 131071*x.n+524287*x.dmm; - /* Never return the special error value -1 */ - return h==-1?2:h; -} - -#define RATIONAL_BINOP_2(name,exp) \ - static PyObject* \ - pyrational_##name(PyObject* a, PyObject* b) { \ - rational x, y, z; \ - AS_RATIONAL(x,a); \ - AS_RATIONAL(y,b); \ - z = exp; \ - if (PyErr_Occurred()) { \ - return 0; \ - } \ - return PyRational_FromRational(z); \ - } -#define RATIONAL_BINOP(name) RATIONAL_BINOP_2(name,rational_##name(x,y)) -RATIONAL_BINOP(add) -RATIONAL_BINOP(subtract) -RATIONAL_BINOP(multiply) -RATIONAL_BINOP(divide) -RATIONAL_BINOP(remainder) -RATIONAL_BINOP_2(floor_divide, - make_rational_int(rational_floor(rational_divide(x,y)))) - -#define RATIONAL_UNOP(name,type,exp,convert) \ - static PyObject* \ - pyrational_##name(PyObject* self) { \ - rational x = ((PyRational*)self)->r; \ - type y = exp; \ - if (PyErr_Occurred()) { \ - return 0; \ - } \ - return convert(y); \ - } -RATIONAL_UNOP(negative,rational,rational_negative(x),PyRational_FromRational) -RATIONAL_UNOP(absolute,rational,rational_abs(x),PyRational_FromRational) -RATIONAL_UNOP(int,long,rational_int(x),PyInt_FromLong) -RATIONAL_UNOP(float,double,rational_double(x),PyFloat_FromDouble) - -static PyObject* -pyrational_positive(PyObject* self) { - Py_INCREF(self); - return self; -} - -static int -pyrational_nonzero(PyObject* self) { - rational x = ((PyRational*)self)->r; - return rational_nonzero(x); -} - -static PyNumberMethods pyrational_as_number = { - pyrational_add, /* nb_add */ - pyrational_subtract, /* nb_subtract */ - pyrational_multiply, /* nb_multiply */ -#if PY_MAJOR_VERSION < 3 - pyrational_divide, /* nb_divide */ -#endif - pyrational_remainder, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - pyrational_negative, /* nb_negative */ - pyrational_positive, /* nb_positive */ - pyrational_absolute, /* nb_absolute */ - pyrational_nonzero, /* nb_nonzero */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ -#if PY_MAJOR_VERSION < 3 - 0, /* nb_coerce */ -#endif - pyrational_int, /* nb_int */ -#if PY_MAJOR_VERSION < 3 - pyrational_int, /* nb_long */ -#else - 0, /* reserved */ -#endif - pyrational_float, /* nb_float */ -#if PY_MAJOR_VERSION < 3 - 0, /* nb_oct */ - 0, /* nb_hex */ -#endif - - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ -#if PY_MAJOR_VERSION < 3 - 0, /* nb_inplace_divide */ -#endif - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - - pyrational_floor_divide, /* nb_floor_divide */ - pyrational_divide, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - 0, /* nb_index */ -}; - -static PyObject* -pyrational_n(PyObject* self, void* closure) { - return PyInt_FromLong(((PyRational*)self)->r.n); -} - -static PyObject* -pyrational_d(PyObject* self, void* closure) { - return PyInt_FromLong(d(((PyRational*)self)->r)); -} - -static PyGetSetDef pyrational_getset[] = { - {(char*)"n",pyrational_n,0,(char*)"numerator",0}, - {(char*)"d",pyrational_d,0,(char*)"denominator",0}, - {0} /* sentinel */ -}; - -static PyTypeObject PyRational_Type = { -#if defined(NPY_PY3K) - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - "rational", /* tp_name */ - sizeof(PyRational), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ -#if defined(NPY_PY3K) - 0, /* tp_reserved */ -#else - 0, /* tp_compare */ -#endif - pyrational_repr, /* tp_repr */ - &pyrational_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - pyrational_hash, /* tp_hash */ - 0, /* tp_call */ - pyrational_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - "Fixed precision rational numbers", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - pyrational_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - pyrational_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - pyrational_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ -}; - -/* NumPy support */ - -static PyObject* -npyrational_getitem(void* data, void* arr) { - rational r; - memcpy(&r,data,sizeof(rational)); - return PyRational_FromRational(r); -} - -static int -npyrational_setitem(PyObject* item, void* data, void* arr) { - rational r; - if (PyRational_Check(item)) { - r = ((PyRational*)item)->r; - } - else { - long n = PyInt_AsLong(item); - PyObject* y; - int eq; - if (error_converting(n)) { - return -1; - } - y = PyInt_FromLong(n); - if (!y) { - return -1; - } - eq = PyObject_RichCompareBool(item,y,Py_EQ); - Py_DECREF(y); - if (eq<0) { - return -1; - } - if (!eq) { - PyErr_Format(PyExc_TypeError, - "expected rational, got %s", item->ob_type->tp_name); - return -1; - } - r = make_rational_int(n); - } - memcpy(data,&r,sizeof(rational)); - return 0; -} - -static NPY_INLINE void -byteswap(npy_int32* x) { - char* p = (char*)x; - size_t i; - for (i = 0; i < sizeof(*x)/2; i++) { - size_t j = sizeof(*x)-1-i; - char t = p[i]; - p[i] = p[j]; - p[j] = t; - } -} - -static void -npyrational_copyswapn(void* dst_, npy_intp dstride, void* src_, - npy_intp sstride, npy_intp n, int swap, void* arr) { - char *dst = (char*)dst_, *src = (char*)src_; - npy_intp i; - if (!src) { - return; - } - if (swap) { - for (i = 0; i < n; i++) { - rational* r = (rational*)(dst+dstride*i); - memcpy(r,src+sstride*i,sizeof(rational)); - byteswap(&r->n); - byteswap(&r->dmm); - } - } - else if (dstride == sizeof(rational) && sstride == sizeof(rational)) { - memcpy(dst, src, n*sizeof(rational)); - } - else { - for (i = 0; i < n; i++) { - memcpy(dst + dstride*i, src + sstride*i, sizeof(rational)); - } - } -} - -static void -npyrational_copyswap(void* dst, void* src, int swap, void* arr) { - rational* r; - if (!src) { - return; - } - r = (rational*)dst; - memcpy(r,src,sizeof(rational)); - if (swap) { - byteswap(&r->n); - byteswap(&r->dmm); - } -} - -static int -npyrational_compare(const void* d0, const void* d1, void* arr) { - rational x = *(rational*)d0, - y = *(rational*)d1; - return rational_lt(x,y)?-1:rational_eq(x,y)?0:1; -} - -#define FIND_EXTREME(name,op) \ - static int \ - npyrational_##name(void* data_, npy_intp n, \ - npy_intp* max_ind, void* arr) { \ - const rational* data; \ - npy_intp best_i; \ - rational best_r; \ - npy_intp i; \ - if (!n) { \ - return 0; \ - } \ - data = (rational*)data_; \ - best_i = 0; \ - best_r = data[0]; \ - for (i = 1; i < n; i++) { \ - if (rational_##op(data[i],best_r)) { \ - best_i = i; \ - best_r = data[i]; \ - } \ - } \ - *max_ind = best_i; \ - return 0; \ - } -FIND_EXTREME(argmin,lt) -FIND_EXTREME(argmax,gt) - -static void -npyrational_dot(void* ip0_, npy_intp is0, void* ip1_, npy_intp is1, - void* op, npy_intp n, void* arr) { - rational r = {0}; - const char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_; - npy_intp i; - for (i = 0; i < n; i++) { - r = rational_add(r,rational_multiply(*(rational*)ip0,*(rational*)ip1)); - ip0 += is0; - ip1 += is1; - } - *(rational*)op = r; -} - -static npy_bool -npyrational_nonzero(void* data, void* arr) { - rational r; - memcpy(&r,data,sizeof(r)); - return rational_nonzero(r)?NPY_TRUE:NPY_FALSE; -} - -static int -npyrational_fill(void* data_, npy_intp length, void* arr) { - rational* data = (rational*)data_; - rational delta = rational_subtract(data[1],data[0]); - rational r = data[1]; - npy_intp i; - for (i = 2; i < length; i++) { - r = rational_add(r,delta); - data[i] = r; - } - return 0; -} - -static int -npyrational_fillwithscalar(void* buffer_, npy_intp length, - void* value, void* arr) { - rational r = *(rational*)value; - rational* buffer = (rational*)buffer_; - npy_intp i; - for (i = 0; i < length; i++) { - buffer[i] = r; - } - return 0; -} - -static PyArray_ArrFuncs npyrational_arrfuncs; - -typedef struct { char c; rational r; } align_test; - -PyArray_Descr npyrational_descr = { - PyObject_HEAD_INIT(0) - &PyRational_Type, /* typeobj */ - 'V', /* kind */ - 'r', /* type */ - '=', /* byteorder */ - /* - * For now, we need NPY_NEEDS_PYAPI in order to make numpy detect our - * exceptions. This isn't technically necessary, - * since we're careful about thread safety, and hopefully future - * versions of numpy will recognize that. - */ - NPY_NEEDS_PYAPI | NPY_USE_GETITEM | NPY_USE_SETITEM, /* hasobject */ - 0, /* type_num */ - sizeof(rational), /* elsize */ - offsetof(align_test,r), /* alignment */ - 0, /* subarray */ - 0, /* fields */ - 0, /* names */ - &npyrational_arrfuncs, /* f */ -}; - -#define DEFINE_CAST(From,To,statement) \ - static void \ - npycast_##From##_##To(void* from_, void* to_, npy_intp n, \ - void* fromarr, void* toarr) { \ - const From* from = (From*)from_; \ - To* to = (To*)to_; \ - npy_intp i; \ - for (i = 0; i < n; i++) { \ - From x = from[i]; \ - statement \ - to[i] = y; \ - } \ - } -#define DEFINE_INT_CAST(bits) \ - DEFINE_CAST(npy_int##bits,rational,rational y = make_rational_int(x);) \ - DEFINE_CAST(rational,npy_int##bits,npy_int32 z = rational_int(x); \ - npy_int##bits y = z; if (y != z) set_overflow();) -DEFINE_INT_CAST(8) -DEFINE_INT_CAST(16) -DEFINE_INT_CAST(32) -DEFINE_INT_CAST(64) -DEFINE_CAST(rational,float,double y = rational_double(x);) -DEFINE_CAST(rational,double,double y = rational_double(x);) -DEFINE_CAST(npy_bool,rational,rational y = make_rational_int(x);) -DEFINE_CAST(rational,npy_bool,npy_bool y = rational_nonzero(x);) - -#define BINARY_UFUNC(name,intype0,intype1,outtype,exp) \ - void name(char** args, npy_intp* dimensions, \ - npy_intp* steps, void* data) { \ - npy_intp is0 = steps[0], is1 = steps[1], \ - os = steps[2], n = *dimensions; \ - char *i0 = args[0], *i1 = args[1], *o = args[2]; \ - int k; \ - for (k = 0; k < n; k++) { \ - intype0 x = *(intype0*)i0; \ - intype1 y = *(intype1*)i1; \ - *(outtype*)o = exp; \ - i0 += is0; i1 += is1; o += os; \ - } \ - } -#define RATIONAL_BINARY_UFUNC(name,type,exp) \ - BINARY_UFUNC(rational_ufunc_##name,rational,rational,type,exp) -RATIONAL_BINARY_UFUNC(add,rational,rational_add(x,y)) -RATIONAL_BINARY_UFUNC(subtract,rational,rational_subtract(x,y)) -RATIONAL_BINARY_UFUNC(multiply,rational,rational_multiply(x,y)) -RATIONAL_BINARY_UFUNC(divide,rational,rational_divide(x,y)) -RATIONAL_BINARY_UFUNC(remainder,rational,rational_remainder(x,y)) -RATIONAL_BINARY_UFUNC(floor_divide,rational, - make_rational_int(rational_floor(rational_divide(x,y)))) -PyUFuncGenericFunction rational_ufunc_true_divide = rational_ufunc_divide; -RATIONAL_BINARY_UFUNC(minimum,rational,rational_lt(x,y)?x:y) -RATIONAL_BINARY_UFUNC(maximum,rational,rational_lt(x,y)?y:x) -RATIONAL_BINARY_UFUNC(equal,npy_bool,rational_eq(x,y)) -RATIONAL_BINARY_UFUNC(not_equal,npy_bool,rational_ne(x,y)) -RATIONAL_BINARY_UFUNC(less,npy_bool,rational_lt(x,y)) -RATIONAL_BINARY_UFUNC(greater,npy_bool,rational_gt(x,y)) -RATIONAL_BINARY_UFUNC(less_equal,npy_bool,rational_le(x,y)) -RATIONAL_BINARY_UFUNC(greater_equal,npy_bool,rational_ge(x,y)) - -BINARY_UFUNC(gcd_ufunc,npy_int64,npy_int64,npy_int64,gcd(x,y)) -BINARY_UFUNC(lcm_ufunc,npy_int64,npy_int64,npy_int64,lcm(x,y)) - -#define UNARY_UFUNC(name,type,exp) \ - void rational_ufunc_##name(char** args, npy_intp* dimensions, \ - npy_intp* steps, void* data) { \ - npy_intp is = steps[0], os = steps[1], n = *dimensions; \ - char *i = args[0], *o = args[1]; \ - int k; \ - for (k = 0; k < n; k++) { \ - rational x = *(rational*)i; \ - *(type*)o = exp; \ - i += is; o += os; \ - } \ - } -UNARY_UFUNC(negative,rational,rational_negative(x)) -UNARY_UFUNC(absolute,rational,rational_abs(x)) -UNARY_UFUNC(floor,rational,make_rational_int(rational_floor(x))) -UNARY_UFUNC(ceil,rational,make_rational_int(rational_ceil(x))) -UNARY_UFUNC(trunc,rational,make_rational_int(x.n/d(x))) -UNARY_UFUNC(square,rational,rational_multiply(x,x)) -UNARY_UFUNC(rint,rational,make_rational_int(rational_rint(x))) -UNARY_UFUNC(sign,rational,make_rational_int(rational_sign(x))) -UNARY_UFUNC(reciprocal,rational,rational_inverse(x)) -UNARY_UFUNC(numerator,npy_int64,x.n) -UNARY_UFUNC(denominator,npy_int64,d(x)) - -static NPY_INLINE void -rational_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps) -{ - /* pointers to data for input and output arrays */ - char *ip1 = args[0]; - char *ip2 = args[1]; - char *op = args[2]; - - /* lengths of core dimensions */ - npy_intp dm = dimensions[0]; - npy_intp dn = dimensions[1]; - npy_intp dp = dimensions[2]; - - /* striding over core dimensions */ - npy_intp is1_m = steps[0]; - npy_intp is1_n = steps[1]; - npy_intp is2_n = steps[2]; - npy_intp is2_p = steps[3]; - npy_intp os_m = steps[4]; - npy_intp os_p = steps[5]; - - /* core dimensions counters */ - npy_intp m, p; - - /* calculate dot product for each row/column vector pair */ - for (m = 0; m < dm; m++) { - for (p = 0; p < dp; p++) { - npyrational_dot(ip1, is1_n, ip2, is2_n, op, dn, NULL); - - /* advance to next column of 2nd input array and output array */ - ip2 += is2_p; - op += os_p; - } - - /* reset to first column of 2nd input array and output array */ - ip2 -= is2_p * p; - op -= os_p * p; - - /* advance to next row of 1st input array and output array */ - ip1 += is1_m; - op += os_m; - } -} - - -static void -rational_gufunc_matrix_multiply(char **args, npy_intp *dimensions, - npy_intp *steps, void *NPY_UNUSED(func)) -{ - /* outer dimensions counter */ - npy_intp N_; - - /* length of flattened outer dimensions */ - npy_intp dN = dimensions[0]; - - /* striding over flattened outer dimensions for input and output arrays */ - npy_intp s0 = steps[0]; - npy_intp s1 = steps[1]; - npy_intp s2 = steps[2]; - - /* - * loop through outer dimensions, performing matrix multiply on - * core dimensions for each loop - */ - for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2) { - rational_matrix_multiply(args, dimensions+1, steps+3); - } -} - - -static void -rational_ufunc_test_add(char** args, npy_intp* dimensions, - npy_intp* steps, void* data) { - npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions; - char *i0 = args[0], *i1 = args[1], *o = args[2]; - int k; - for (k = 0; k < n; k++) { - npy_int64 x = *(npy_int64*)i0; - npy_int64 y = *(npy_int64*)i1; - *(rational*)o = rational_add(make_rational_fast(x, 1), - make_rational_fast(y, 1)); - i0 += is0; i1 += is1; o += os; - } -} - - -static void -rational_ufunc_test_add_rationals(char** args, npy_intp* dimensions, - npy_intp* steps, void* data) { - npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions; - char *i0 = args[0], *i1 = args[1], *o = args[2]; - int k; - for (k = 0; k < n; k++) { - rational x = *(rational*)i0; - rational y = *(rational*)i1; - *(rational*)o = rational_add(x, y); - i0 += is0; i1 += is1; o += os; - } -} - - -PyMethodDef module_methods[] = { - {0} /* sentinel */ -}; - -#if defined(NPY_PY3K) -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "test_rational", - NULL, - -1, - module_methods, - NULL, - NULL, - NULL, - NULL -}; -#endif - -#if defined(NPY_PY3K) -#define RETVAL m -PyMODINIT_FUNC PyInit_test_rational(void) { -#else -#define RETVAL -PyMODINIT_FUNC inittest_rational(void) { -#endif - - PyObject *m = NULL; - PyObject* numpy_str; - PyObject* numpy; - int npy_rational; - - import_array(); - if (PyErr_Occurred()) { - goto fail; - } - import_umath(); - if (PyErr_Occurred()) { - goto fail; - } - numpy_str = PyUString_FromString("numpy"); - if (!numpy_str) { - goto fail; - } - numpy = PyImport_Import(numpy_str); - Py_DECREF(numpy_str); - if (!numpy) { - goto fail; - } - - /* Can't set this until we import numpy */ - PyRational_Type.tp_base = &PyGenericArrType_Type; - - /* Initialize rational type object */ - if (PyType_Ready(&PyRational_Type) < 0) { - goto fail; - } - - /* Initialize rational descriptor */ - PyArray_InitArrFuncs(&npyrational_arrfuncs); - npyrational_arrfuncs.getitem = npyrational_getitem; - npyrational_arrfuncs.setitem = npyrational_setitem; - npyrational_arrfuncs.copyswapn = npyrational_copyswapn; - npyrational_arrfuncs.copyswap = npyrational_copyswap; - npyrational_arrfuncs.compare = npyrational_compare; - npyrational_arrfuncs.argmin = npyrational_argmin; - npyrational_arrfuncs.argmax = npyrational_argmax; - npyrational_arrfuncs.dotfunc = npyrational_dot; - npyrational_arrfuncs.nonzero = npyrational_nonzero; - npyrational_arrfuncs.fill = npyrational_fill; - npyrational_arrfuncs.fillwithscalar = npyrational_fillwithscalar; - /* Left undefined: scanfunc, fromstr, sort, argsort */ - Py_TYPE(&npyrational_descr) = &PyArrayDescr_Type; - npy_rational = PyArray_RegisterDataType(&npyrational_descr); - if (npy_rational<0) { - goto fail; - } - - /* Support dtype(rational) syntax */ - if (PyDict_SetItemString(PyRational_Type.tp_dict, "dtype", - (PyObject*)&npyrational_descr) < 0) { - goto fail; - } - - /* Register casts to and from rational */ - #define REGISTER_CAST(From,To,from_descr,to_typenum,safe) { \ - PyArray_Descr* from_descr_##From##_##To = (from_descr); \ - if (PyArray_RegisterCastFunc(from_descr_##From##_##To, \ - (to_typenum), \ - npycast_##From##_##To) < 0) { \ - goto fail; \ - } \ - if (safe && PyArray_RegisterCanCast(from_descr_##From##_##To, \ - (to_typenum), \ - NPY_NOSCALAR) < 0) { \ - goto fail; \ - } \ - } - #define REGISTER_INT_CASTS(bits) \ - REGISTER_CAST(npy_int##bits, rational, \ - PyArray_DescrFromType(NPY_INT##bits), npy_rational, 1) \ - REGISTER_CAST(rational, npy_int##bits, &npyrational_descr, \ - NPY_INT##bits, 0) - REGISTER_INT_CASTS(8) - REGISTER_INT_CASTS(16) - REGISTER_INT_CASTS(32) - REGISTER_INT_CASTS(64) - REGISTER_CAST(rational,float,&npyrational_descr,NPY_FLOAT,0) - REGISTER_CAST(rational,double,&npyrational_descr,NPY_DOUBLE,1) - REGISTER_CAST(npy_bool,rational, PyArray_DescrFromType(NPY_BOOL), - npy_rational,1) - REGISTER_CAST(rational,npy_bool,&npyrational_descr,NPY_BOOL,0) - - /* Register ufuncs */ - #define REGISTER_UFUNC(name,...) { \ - PyUFuncObject* ufunc = \ - (PyUFuncObject*)PyObject_GetAttrString(numpy, #name); \ - int _types[] = __VA_ARGS__; \ - if (!ufunc) { \ - goto fail; \ - } \ - if (sizeof(_types)/sizeof(int)!=ufunc->nargs) { \ - PyErr_Format(PyExc_AssertionError, \ - "ufunc %s takes %d arguments, our loop takes %lu", \ - #name, ufunc->nargs, (unsigned long) \ - (sizeof(_types)/sizeof(int))); \ - Py_DECREF(ufunc); \ - goto fail; \ - } \ - if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \ - rational_ufunc_##name, _types, 0) < 0) { \ - Py_DECREF(ufunc); \ - goto fail; \ - } \ - Py_DECREF(ufunc); \ - } - #define REGISTER_UFUNC_BINARY_RATIONAL(name) \ - REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational}) - #define REGISTER_UFUNC_BINARY_COMPARE(name) \ - REGISTER_UFUNC(name, {npy_rational, npy_rational, NPY_BOOL}) - #define REGISTER_UFUNC_UNARY(name) \ - REGISTER_UFUNC(name, {npy_rational, npy_rational}) - /* Binary */ - REGISTER_UFUNC_BINARY_RATIONAL(add) - REGISTER_UFUNC_BINARY_RATIONAL(subtract) - REGISTER_UFUNC_BINARY_RATIONAL(multiply) - REGISTER_UFUNC_BINARY_RATIONAL(divide) - REGISTER_UFUNC_BINARY_RATIONAL(remainder) - REGISTER_UFUNC_BINARY_RATIONAL(true_divide) - REGISTER_UFUNC_BINARY_RATIONAL(floor_divide) - REGISTER_UFUNC_BINARY_RATIONAL(minimum) - REGISTER_UFUNC_BINARY_RATIONAL(maximum) - /* Comparisons */ - REGISTER_UFUNC_BINARY_COMPARE(equal) - REGISTER_UFUNC_BINARY_COMPARE(not_equal) - REGISTER_UFUNC_BINARY_COMPARE(less) - REGISTER_UFUNC_BINARY_COMPARE(greater) - REGISTER_UFUNC_BINARY_COMPARE(less_equal) - REGISTER_UFUNC_BINARY_COMPARE(greater_equal) - /* Unary */ - REGISTER_UFUNC_UNARY(negative) - REGISTER_UFUNC_UNARY(absolute) - REGISTER_UFUNC_UNARY(floor) - REGISTER_UFUNC_UNARY(ceil) - REGISTER_UFUNC_UNARY(trunc) - REGISTER_UFUNC_UNARY(rint) - REGISTER_UFUNC_UNARY(square) - REGISTER_UFUNC_UNARY(reciprocal) - REGISTER_UFUNC_UNARY(sign) - - /* Create module */ -#if defined(NPY_PY3K) - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule("test_rational", module_methods); -#endif - - if (!m) { - goto fail; - } - - /* Add rational type */ - Py_INCREF(&PyRational_Type); - PyModule_AddObject(m,"rational",(PyObject*)&PyRational_Type); - - /* Create matrix multiply generalized ufunc */ - { - int types2[3] = {npy_rational,npy_rational,npy_rational}; - PyObject* gufunc = PyUFunc_FromFuncAndDataAndSignature(0,0,0,0,2,1, - PyUFunc_None,(char*)"matrix_multiply", - (char*)"return result of multiplying two matrices of rationals", - 0,"(m,n),(n,p)->(m,p)"); - if (!gufunc) { - goto fail; - } - if (PyUFunc_RegisterLoopForType((PyUFuncObject*)gufunc, npy_rational, - rational_gufunc_matrix_multiply, types2, 0) < 0) { - goto fail; - } - PyModule_AddObject(m,"matrix_multiply",(PyObject*)gufunc); - } - - /* Create test ufunc with built in input types and rational output type */ - { - int types3[3] = {NPY_INT64,NPY_INT64,npy_rational}; - - PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,2,1, - PyUFunc_None,(char*)"test_add", - (char*)"add two matrices of int64 and return rational matrix",0); - if (!ufunc) { - goto fail; - } - if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, - rational_ufunc_test_add, types3, 0) < 0) { - goto fail; - } - PyModule_AddObject(m,"test_add",(PyObject*)ufunc); - } - - /* Create test ufunc with rational types using RegisterLoopForDescr */ - { - PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,2,1, - PyUFunc_None,(char*)"test_add_rationals", - (char*)"add two matrices of rationals and return rational matrix",0); - PyArray_Descr* types[3] = {&npyrational_descr, - &npyrational_descr, - &npyrational_descr}; - - if (!ufunc) { - goto fail; - } - if (PyUFunc_RegisterLoopForDescr((PyUFuncObject*)ufunc, &npyrational_descr, - rational_ufunc_test_add_rationals, types, 0) < 0) { - goto fail; - } - PyModule_AddObject(m,"test_add_rationals",(PyObject*)ufunc); - } - - /* Create numerator and denominator ufuncs */ - #define NEW_UNARY_UFUNC(name,type,doc) { \ - int types[2] = {npy_rational,type}; \ - PyObject* ufunc = PyUFunc_FromFuncAndData(0,0,0,0,1,1, \ - PyUFunc_None,(char*)#name,(char*)doc,0); \ - if (!ufunc) { \ - goto fail; \ - } \ - if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, \ - npy_rational,rational_ufunc_##name,types,0)<0) { \ - goto fail; \ - } \ - PyModule_AddObject(m,#name,(PyObject*)ufunc); \ - } - NEW_UNARY_UFUNC(numerator,NPY_INT64,"rational number numerator"); - NEW_UNARY_UFUNC(denominator,NPY_INT64,"rational number denominator"); - - /* Create gcd and lcm ufuncs */ - #define GCD_LCM_UFUNC(name,type,doc) { \ - static const PyUFuncGenericFunction func[1] = {name##_ufunc}; \ - static const char types[3] = {type,type,type}; \ - static void* data[1] = {0}; \ - PyObject* ufunc = PyUFunc_FromFuncAndData( \ - (PyUFuncGenericFunction*)func, data,(char*)types, \ - 1,2,1,PyUFunc_One,(char*)#name,(char*)doc,0); \ - if (!ufunc) { \ - goto fail; \ - } \ - PyModule_AddObject(m,#name,(PyObject*)ufunc); \ - } - GCD_LCM_UFUNC(gcd,NPY_INT64,"greatest common denominator of two integers"); - GCD_LCM_UFUNC(lcm,NPY_INT64,"least common multiple of two integers"); - - return RETVAL; - -fail: - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, - "cannot load test_rational module."); - } -#if defined(NPY_PY3K) - if (m) { - Py_DECREF(m); - m = NULL; - } -#endif - return RETVAL; -} diff --git a/numpy/core/src/umath/umath_tests.c.src b/numpy/core/src/umath/umath_tests.c.src deleted file mode 100644 index 8d9009a1a..000000000 --- a/numpy/core/src/umath/umath_tests.c.src +++ /dev/null @@ -1,413 +0,0 @@ -/* -*- c -*- */ - -/* - ***************************************************************************** - ** INCLUDES ** - ***************************************************************************** - */ -#define NPY_NO_DEPRECATED_API NPY_API_VERSION - -#include "Python.h" -#include "numpy/arrayobject.h" -#include "numpy/ufuncobject.h" -#include "numpy/npy_math.h" - -#include "npy_pycompat.h" - -#include "npy_config.h" - -/* - ***************************************************************************** - ** BASICS ** - ***************************************************************************** - */ - -#define INIT_OUTER_LOOP_1 \ - npy_intp dN = *dimensions++;\ - npy_intp N_; \ - npy_intp s0 = *steps++; - -#define INIT_OUTER_LOOP_2 \ - INIT_OUTER_LOOP_1 \ - npy_intp s1 = *steps++; - -#define INIT_OUTER_LOOP_3 \ - INIT_OUTER_LOOP_2 \ - npy_intp s2 = *steps++; - -#define INIT_OUTER_LOOP_4 \ - INIT_OUTER_LOOP_3 \ - npy_intp s3 = *steps++; - -#define BEGIN_OUTER_LOOP_2 \ - for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1) { - -#define BEGIN_OUTER_LOOP_3 \ - for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2) { - -#define BEGIN_OUTER_LOOP_4 \ - for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2, args[3] += s3) { - -#define END_OUTER_LOOP } - - -/* - ***************************************************************************** - ** UFUNC LOOPS ** - ***************************************************************************** - */ - -char *inner1d_signature = "(i),(i)->()"; - -/**begin repeat - - #TYPE=LONG,DOUBLE# - #typ=npy_long,npy_double# -*/ - -/* - * This implements the function - * out[n] = sum_i { in1[n, i] * in2[n, i] }. - */ - -static void -@TYPE@_inner1d(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) -{ - INIT_OUTER_LOOP_3 - npy_intp di = dimensions[0]; - npy_intp i; - npy_intp is1=steps[0], is2=steps[1]; - BEGIN_OUTER_LOOP_3 - char *ip1=args[0], *ip2=args[1], *op=args[2]; - @typ@ sum = 0; - for (i = 0; i < di; i++) { - sum += (*(@typ@ *)ip1) * (*(@typ@ *)ip2); - ip1 += is1; - ip2 += is2; - } - *(@typ@ *)op = sum; - END_OUTER_LOOP -} - -/**end repeat**/ - -char *innerwt_signature = "(i),(i),(i)->()"; - -/**begin repeat - - #TYPE=LONG,DOUBLE# - #typ=npy_long,npy_double# -*/ - - -/* - * This implements the function - * out[n] = sum_i { in1[n, i] * in2[n, i] * in3[n, i] }. - */ - -static void -@TYPE@_innerwt(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) -{ - INIT_OUTER_LOOP_4 - npy_intp di = dimensions[0]; - npy_intp i; - npy_intp is1=steps[0], is2=steps[1], is3=steps[2]; - BEGIN_OUTER_LOOP_4 - char *ip1=args[0], *ip2=args[1], *ip3=args[2], *op=args[3]; - @typ@ sum = 0; - for (i = 0; i < di; i++) { - sum += (*(@typ@ *)ip1) * (*(@typ@ *)ip2) * (*(@typ@ *)ip3); - ip1 += is1; - ip2 += is2; - ip3 += is3; - } - *(@typ@ *)op = sum; - END_OUTER_LOOP -} - -/**end repeat**/ - -char *matrix_multiply_signature = "(m,n),(n,p)->(m,p)"; - -/**begin repeat - - #TYPE=FLOAT,DOUBLE,LONG# - #typ=npy_float,npy_double,npy_long# -*/ - -/* - * This implements the function - * out[k, m, p] = sum_n { in1[k, m, n] * in2[k, n, p] }. - */ - -static void -@TYPE@_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) -{ - /* no BLAS is available */ - INIT_OUTER_LOOP_3 - npy_intp dm = dimensions[0]; - npy_intp dn = dimensions[1]; - npy_intp dp = dimensions[2]; - npy_intp m,n,p; - npy_intp is1_m=steps[0], is1_n=steps[1], is2_n=steps[2], is2_p=steps[3], - os_m=steps[4], os_p=steps[5]; - npy_intp ib1_n = is1_n*dn; - npy_intp ib2_n = is2_n*dn; - npy_intp ib2_p = is2_p*dp; - npy_intp ob_p = os_p *dp; - if (dn == 0) { - /* No operand, need to zero the output */ - BEGIN_OUTER_LOOP_3 - char *op=args[2]; - for (m = 0; m < dm; m++) { - for (p = 0; p < dp; p++) { - *(@typ@ *)op = 0; - op += os_p; - } - op += os_m - ob_p; - } - END_OUTER_LOOP - return; - } - BEGIN_OUTER_LOOP_3 - char *ip1=args[0], *ip2=args[1], *op=args[2]; - for (m = 0; m < dm; m++) { - for (n = 0; n < dn; n++) { - @typ@ val1 = (*(@typ@ *)ip1); - for (p = 0; p < dp; p++) { - if (n == 0) *(@typ@ *)op = 0; - *(@typ@ *)op += val1 * (*(@typ@ *)ip2); - ip2 += is2_p; - op += os_p; - } - ip2 -= ib2_p; - op -= ob_p; - ip1 += is1_n; - ip2 += is2_n; - } - ip1 -= ib1_n; - ip2 -= ib2_n; - ip1 += is1_m; - op += os_m; - } - END_OUTER_LOOP -} - -/**end repeat**/ - -char *euclidean_pdist_signature = "(n,d)->(p)"; - -/**begin repeat - - #TYPE=FLOAT,DOUBLE# - #typ=npy_float,npy_double# - #sqrt_func=sqrtf,sqrt# -*/ - -/* - * This implements the function - * out[j*(2*n-3-j)+k-1] = sum_d { (in1[j, d] - in1[k, d])^2 } - * with 0 < k < j < n, i.e. computes all unique pairwise euclidean distances. - */ - -static void -@TYPE@_euclidean_pdist(char **args, npy_intp *dimensions, npy_intp *steps, - void *NPY_UNUSED(func)) -{ - INIT_OUTER_LOOP_2 - npy_intp len_n = *dimensions++; - npy_intp len_d = *dimensions++; - npy_intp stride_n = *steps++; - npy_intp stride_d = *steps++; - npy_intp stride_p = *steps; - - assert(len_n * (len_n - 1) / 2 == *dimensions); - - BEGIN_OUTER_LOOP_2 - const char *data_this = (const char *)args[0]; - char *data_out = args[1]; - npy_intp n; - for (n = 0; n < len_n; ++n) { - const char *data_that = data_this + stride_n; - npy_intp nn; - for (nn = n + 1; nn < len_n; ++nn) { - const char *ptr_this = data_this; - const char *ptr_that = data_that; - @typ@ out = 0; - npy_intp d; - for (d = 0; d < len_d; ++d) { - const @typ@ delta = *(const @typ@ *)ptr_this - - *(const @typ@ *)ptr_that; - out += delta * delta; - ptr_this += stride_d; - ptr_that += stride_d; - } - *(@typ@ *)data_out = npy_@sqrt_func@(out); - data_that += stride_n; - data_out += stride_p; - } - data_this += stride_n; - } - END_OUTER_LOOP -} - -/**end repeat**/ - - -static PyUFuncGenericFunction inner1d_functions[] = { LONG_inner1d, DOUBLE_inner1d }; -static void * inner1d_data[] = { (void *)NULL, (void *)NULL }; -static char inner1d_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction innerwt_functions[] = { LONG_innerwt, DOUBLE_innerwt }; -static void * innerwt_data[] = { (void *)NULL, (void *)NULL }; -static char innerwt_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction matrix_multiply_functions[] = { LONG_matrix_multiply, FLOAT_matrix_multiply, DOUBLE_matrix_multiply }; -static void *matrix_multiply_data[] = { (void *)NULL, (void *)NULL, (void *)NULL }; -static char matrix_multiply_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; - -static PyUFuncGenericFunction euclidean_pdist_functions[] = - { FLOAT_euclidean_pdist, DOUBLE_euclidean_pdist }; -static void *eucldiean_pdist_data[] = { (void *)NULL, (void *)NULL }; -static char euclidean_pdist_signatures[] = { NPY_FLOAT, NPY_FLOAT, - NPY_DOUBLE, NPY_DOUBLE }; - - -static void -addUfuncs(PyObject *dictionary) { - PyObject *f; - - f = PyUFunc_FromFuncAndDataAndSignature(inner1d_functions, inner1d_data, - inner1d_signatures, 2, 2, 1, PyUFunc_None, "inner1d", - "inner on the last dimension and broadcast on the rest \n" - " \"(i),(i)->()\" \n", - 0, inner1d_signature); - PyDict_SetItemString(dictionary, "inner1d", f); - Py_DECREF(f); - f = PyUFunc_FromFuncAndDataAndSignature(innerwt_functions, innerwt_data, - innerwt_signatures, 2, 3, 1, PyUFunc_None, "innerwt", - "inner1d with a weight argument \n" - " \"(i),(i),(i)->()\" \n", - 0, innerwt_signature); - PyDict_SetItemString(dictionary, "innerwt", f); - Py_DECREF(f); - f = PyUFunc_FromFuncAndDataAndSignature(matrix_multiply_functions, - matrix_multiply_data, matrix_multiply_signatures, - 3, 2, 1, PyUFunc_None, "matrix_multiply", - "matrix multiplication on last two dimensions \n" - " \"(m,n),(n,p)->(m,p)\" \n", - 0, matrix_multiply_signature); - PyDict_SetItemString(dictionary, "matrix_multiply", f); - Py_DECREF(f); - f = PyUFunc_FromFuncAndDataAndSignature(euclidean_pdist_functions, - eucldiean_pdist_data, euclidean_pdist_signatures, - 2, 1, 1, PyUFunc_None, "euclidean_pdist", - "pairwise euclidean distance on last two dimensions \n" - " \"(n,d)->(p)\" \n", - 0, euclidean_pdist_signature); - PyDict_SetItemString(dictionary, "euclidean_pdist", f); - Py_DECREF(f); - f = PyUFunc_FromFuncAndDataAndSignature(inner1d_functions, inner1d_data, - inner1d_signatures, 2, 2, 1, PyUFunc_None, "inner1d_no_doc", - NULL, - 0, inner1d_signature); - PyDict_SetItemString(dictionary, "inner1d_no_doc", f); - Py_DECREF(f); -} - - -static PyObject * -UMath_Tests_test_signature(PyObject *NPY_UNUSED(dummy), PyObject *args) -{ - int nin, nout; - PyObject *signature, *sig_str; - PyObject *f; - int core_enabled; - - if (!PyArg_ParseTuple(args, "iiO", &nin, &nout, &signature)) return NULL; - - - if (PyString_Check(signature)) { - sig_str = signature; - } else if (PyUnicode_Check(signature)) { - sig_str = PyUnicode_AsUTF8String(signature); - } else { - PyErr_SetString(PyExc_ValueError, "signature should be a string"); - return NULL; - } - - f = PyUFunc_FromFuncAndDataAndSignature(NULL, NULL, NULL, - 0, nin, nout, PyUFunc_None, "no name", - "doc:none", - 1, PyString_AS_STRING(sig_str)); - if (sig_str != signature) { - Py_DECREF(sig_str); - } - if (f == NULL) return NULL; - core_enabled = ((PyUFuncObject*)f)->core_enabled; - Py_DECREF(f); - return Py_BuildValue("i", core_enabled); -} - -static PyMethodDef UMath_TestsMethods[] = { - {"test_signature", UMath_Tests_test_signature, METH_VARARGS, - "Test signature parsing of ufunc. \n" - "Arguments: nin nout signature \n" - "If fails, it returns NULL. Otherwise it will returns 0 for scalar ufunc " - "and 1 for generalized ufunc. \n", - }, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -#if defined(NPY_PY3K) -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "umath_tests", - NULL, - -1, - UMath_TestsMethods, - NULL, - NULL, - NULL, - NULL -}; -#endif - -#if defined(NPY_PY3K) -#define RETVAL m -PyMODINIT_FUNC PyInit_umath_tests(void) -#else -#define RETVAL -PyMODINIT_FUNC -initumath_tests(void) -#endif -{ - PyObject *m; - PyObject *d; - PyObject *version; - -#if defined(NPY_PY3K) - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule("umath_tests", UMath_TestsMethods); -#endif - if (m == NULL) - return RETVAL; - - import_array(); - import_ufunc(); - - d = PyModule_GetDict(m); - - version = PyString_FromString("0.1"); - PyDict_SetItemString(d, "__version__", version); - Py_DECREF(version); - - /* Load the ufunc operators into the module's namespace */ - addUfuncs(d); - - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, - "cannot load umath_tests module."); - } - - return RETVAL; -} diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index fe0c7cc5f..2c2900e6c 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -429,7 +429,7 @@ class TestNonNumericConjugate(_DeprecationTestCase): class TestNPY_CHAR(_DeprecationTestCase): # 2017-05-03, 1.13.0 def test_npy_char_deprecation(self): - from numpy.core.multiarray_tests import npy_char_deprecation + from numpy.core._multiarray_tests import npy_char_deprecation self.assert_deprecated(npy_char_deprecation) assert_(npy_char_deprecation() == 'S1') @@ -440,11 +440,11 @@ class Test_UPDATEIFCOPY(_DeprecationTestCase): WRITEBACKIFCOPY instead """ def test_npy_updateifcopy_deprecation(self): - from numpy.core.multiarray_tests import npy_updateifcopy_deprecation + from numpy.core._multiarray_tests import npy_updateifcopy_deprecation arr = np.arange(9).reshape(3, 3) v = arr.T self.assert_deprecated(npy_updateifcopy_deprecation, args=(v,)) - + class TestDatetimeEvent(_DeprecationTestCase): # 2017-08-11, 1.14.0 diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 2f997b4f7..c924e6f43 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -5,7 +5,7 @@ import sys import operator import numpy as np -from numpy.core.test_rational import rational +from numpy.core._rational_tests import rational from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, dec diff --git a/numpy/core/tests/test_extint128.py b/numpy/core/tests/test_extint128.py index d87585dcf..31786124d 100644 --- a/numpy/core/tests/test_extint128.py +++ b/numpy/core/tests/test_extint128.py @@ -6,7 +6,7 @@ import contextlib import operator import numpy as np -import numpy.core.multiarray_tests as mt +import numpy.core._multiarray_tests as mt from numpy.compat import long from numpy.testing import assert_raises, assert_equal, dec diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 3a02c9fce..082ecb496 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -6,7 +6,7 @@ import functools import operator import numpy as np -from numpy.core.multiarray_tests import array_indexing +from numpy.core._multiarray_tests import array_indexing from itertools import product from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py index 9c17ed210..92baa0896 100644 --- a/numpy/core/tests/test_mem_overlap.py +++ b/numpy/core/tests/test_mem_overlap.py @@ -7,8 +7,8 @@ import numpy as np from numpy.testing import (run_module_suite, assert_, assert_raises, assert_equal, assert_array_equal, assert_allclose, dec) -from numpy.core.multiarray_tests import solve_diophantine, internal_overlap -from numpy.core import umath_tests +from numpy.core._multiarray_tests import solve_diophantine, internal_overlap +from numpy.core import _umath_tests from numpy.lib.stride_tricks import as_strided from numpy.compat import long @@ -749,7 +749,7 @@ class TestUFunc(object): def test_unary_gufunc_fuzz(self): shapes = [7, 13, 8, 21, 29, 32] - gufunc = umath_tests.euclidean_pdist + gufunc = _umath_tests.euclidean_pdist rng = np.random.RandomState(1234) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index da0ccf9eb..44e934585 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -26,7 +26,7 @@ from decimal import Decimal import numpy as np from numpy.compat import strchar, unicode -from numpy.core.multiarray_tests import ( +from numpy.core._multiarray_tests import ( test_neighborhood_iterator, test_neighborhood_iterator_oob, test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end, test_inplace_increment, get_buffer_info, test_as_c_array, @@ -193,7 +193,7 @@ class TestAttributes(object): assert_equal(isinstance(numpy_int, int), True) # ... and fast-path checks on C-API level should also work - from numpy.core.multiarray_tests import test_int_subclass + from numpy.core._multiarray_tests import test_int_subclass assert_equal(test_int_subclass(numpy_int), True) def test_stridesattr(self): @@ -3344,7 +3344,7 @@ class TestTemporaryElide(object): # def incref_elide(a): # d = input.copy() # refcount 1 # return d, d + d # PyNumber_Add without increasing refcount - from numpy.core.multiarray_tests import incref_elide + from numpy.core._multiarray_tests import incref_elide d = np.ones(100000) orig, res = incref_elide(d) d + d @@ -3359,7 +3359,7 @@ class TestTemporaryElide(object): # # def incref_elide_l(d): # return l[4] + l[4] # PyNumber_Add without increasing refcount - from numpy.core.multiarray_tests import incref_elide_l + from numpy.core._multiarray_tests import incref_elide_l # padding with 1 makes sure the object on the stack is not overwritten l = [1, 1, 1, 1, np.ones(100000)] res = incref_elide_l(l) @@ -3438,7 +3438,7 @@ class TestTemporaryElide(object): class TestCAPI(object): def test_IsPythonScalar(self): - from numpy.core.multiarray_tests import IsPythonScalar + from numpy.core._multiarray_tests import IsPythonScalar assert_(IsPythonScalar(b'foobar')) assert_(IsPythonScalar(1)) assert_(IsPythonScalar(2**80)) @@ -6633,7 +6633,7 @@ def test_scalar_element_deletion(): class TestMemEventHook(object): def test_mem_seteventhook(self): # The actual tests are within the C code in - # multiarray/multiarray_tests.c.src + # multiarray/_multiarray_tests.c.src test_pydatamem_seteventhook_start() # force an allocation and free of a numpy array # needs to be larger then limit of small memory cacher in ctors.c @@ -6645,7 +6645,7 @@ class TestMemEventHook(object): class TestMapIter(object): def test_mapiter(self): # The actual tests are within the C code in - # multiarray/multiarray_tests.c.src + # multiarray/_multiarray_tests.c.src a = np.arange(12).reshape((3, 4)).astype(float) index = ([1, 1, 2, 0], @@ -7237,7 +7237,7 @@ class TestWritebackIfCopy(object): assert_equal(b, np.array([[15, 18, 21], [42, 54, 66], [69, 90, 111]])) def test_view_assign(self): - from numpy.core.multiarray_tests import npy_create_writebackifcopy, npy_resolve + from numpy.core._multiarray_tests import npy_create_writebackifcopy, npy_resolve arr = np.arange(9).reshape(3, 3).T arr_wb = npy_create_writebackifcopy(arr) assert_(arr_wb.flags.writebackifcopy) @@ -7307,7 +7307,7 @@ def test_equal_override(): def test_npymath_complex(): # Smoketest npymath functions - from numpy.core.multiarray_tests import ( + from numpy.core._multiarray_tests import ( npy_cabs, npy_carg) funcs = {npy_cabs: np.absolute, @@ -7326,7 +7326,7 @@ def test_npymath_complex(): def test_npymath_real(): # Smoketest npymath functions - from numpy.core.multiarray_tests import ( + from numpy.core._multiarray_tests import ( npy_log10, npy_cosh, npy_sinh, npy_tan, npy_tanh) funcs = {npy_log10: np.log10, diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index 1b2485a87..6b1152e09 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -5,7 +5,7 @@ import warnings import numpy as np from numpy import array, arange, nditer, all -from numpy.core.multiarray_tests import test_nditer_too_large +from numpy.core._multiarray_tests import test_nditer_too_large from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_array_equal, assert_raises, assert_warns, dec, HAS_REFCOUNT, suppress_warnings diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index 7e1bfbdbe..0dc12b144 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -4,9 +4,9 @@ import warnings import itertools import numpy as np -import numpy.core.umath_tests as umt -import numpy.core.operand_flag_tests as opflag_tests -from numpy.core.test_rational import rational, test_add, test_add_rationals +import numpy.core._umath_tests as umt +import numpy.core._operand_flag_tests as opflag_tests +from numpy.core._rational_tests import rational, test_add, test_add_rationals from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, assert_array_equal, assert_almost_equal, assert_array_almost_equal, @@ -42,7 +42,7 @@ class TestUfunc(object): assert_(pickle.loads(pickle.dumps(np.sin)) is np.sin) # Check that ufunc not defined in the top level numpy namespace such as - # numpy.core.test_rational.test_add can also be pickled + # numpy.core._rational_tests.test_add can also be pickled assert_(pickle.loads(pickle.dumps(test_add)) is test_add) def test_pickle_withstring(self): @@ -1167,7 +1167,7 @@ class TestUfunc(object): assert_equal(a, 10) def test_struct_ufunc(self): - import numpy.core.struct_ufunc_test as struct_ufunc + import numpy.core._struct_ufunc_tests as struct_ufunc a = np.array([(1, 2, 3)], dtype='u8,u8,u8') b = np.array([(1, 2, 3)], dtype='u8,u8,u8') diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 4b6b26cbf..fe7768e53 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -7,7 +7,7 @@ import fnmatch import itertools import numpy.core.umath as ncu -from numpy.core import umath_tests as ncu_tests +from numpy.core import _umath_tests as ncu_tests import numpy as np from numpy.testing import ( run_module_suite, assert_, assert_equal, assert_raises, diff --git a/numpy/lib/tests/test_stride_tricks.py b/numpy/lib/tests/test_stride_tricks.py index 0599324d7..475119481 100644 --- a/numpy/lib/tests/test_stride_tricks.py +++ b/numpy/lib/tests/test_stride_tricks.py @@ -1,7 +1,7 @@ from __future__ import division, absolute_import, print_function import numpy as np -from numpy.core.test_rational import rational +from numpy.core._rational_tests import rational from numpy.testing import ( run_module_suite, assert_equal, assert_array_equal, assert_raises, assert_ diff --git a/numpy/testing/nose_tools/noseclasses.py b/numpy/testing/nose_tools/noseclasses.py index 9756b9b45..08dec0ca9 100644 --- a/numpy/testing/nose_tools/noseclasses.py +++ b/numpy/testing/nose_tools/noseclasses.py @@ -325,7 +325,7 @@ class FPUModeCheckPlugin(Plugin): """ def prepareTestCase(self, test): - from numpy.core.multiarray_tests import get_fpu_mode + from numpy.core._multiarray_tests import get_fpu_mode def run(result): old_mode = get_fpu_mode() -- cgit v1.2.3