1
#define PY_SSIZE_T_CLEAN
3
#include "structmember.h"
5
#define _MULTIARRAYMODULE
7
#include "numpy/arrayobject.h"
9
#include "npy_config.h"
14
#include "calculation.h"
16
/* FIXME: just remove _check_axis ? */
17
#define _check_axis PyArray_CheckAxis
18
#define PyAO PyArrayObject
23
static const double p10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};
40
NPY_NO_EXPORT PyObject *
41
PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
43
PyArrayObject *ap = NULL, *rp = NULL;
44
PyArray_ArgFunc* arg_func;
50
NPY_BEGIN_THREADS_DEF;
52
if ((ap=(PyAO *)_check_axis(op, &axis, 0)) == NULL) {
56
* We need to permute the array so that axis is placed at the end.
57
* And all other dimensions are shifted left.
59
if (axis != ap->nd-1) {
66
for (i = 0; i < axis; i++) dims[i] = i;
67
for (i = axis; i < ap->nd - 1; i++) dims[i] = i + 1;
68
dims[ap->nd - 1] = axis;
69
op = (PyAO *)PyArray_Transpose(ap, &newaxes);
79
/* Will get native-byte order contiguous copy. */
80
ap = (PyArrayObject *)
81
PyArray_ContiguousFromAny((PyObject *)op,
82
op->descr->type_num, 1, 0);
87
arg_func = ap->descr->f->argmax;
88
if (arg_func == NULL) {
89
PyErr_SetString(PyExc_TypeError, "data type not ordered");
92
elsize = ap->descr->elsize;
93
m = ap->dimensions[ap->nd-1];
95
PyErr_SetString(PyExc_ValueError,
96
"attempt to get argmax/argmin "\
97
"of an empty sequence");
102
rp = (PyArrayObject *)PyArray_New(ap->ob_type, ap->nd-1,
103
ap->dimensions, PyArray_INTP,
111
if (PyArray_SIZE(out) !=
112
PyArray_MultiplyList(ap->dimensions, ap->nd - 1)) {
113
PyErr_SetString(PyExc_TypeError,
114
"invalid shape for output array.");
116
rp = (PyArrayObject *)\
117
PyArray_FromArray(out,
118
PyArray_DescrFromType(PyArray_INTP),
119
NPY_CARRAY | NPY_UPDATEIFCOPY);
128
NPY_BEGIN_THREADS_DESCR(ap->descr);
129
n = PyArray_SIZE(ap)/m;
130
rptr = (intp *)rp->data;
131
for (ip = ap->data, i = 0; i < n; i++, ip += elsize*m) {
132
arg_func(ip, m, rptr, ap);
135
NPY_END_THREADS_DESCR(ap->descr);
140
obj = (PyArrayObject *)rp->base;
145
return (PyObject *)rp;
156
NPY_NO_EXPORT PyObject *
157
PyArray_ArgMin(PyArrayObject *ap, int axis, PyArrayObject *out)
159
PyObject *obj, *new, *ret;
161
if (PyArray_ISFLEXIBLE(ap)) {
162
PyErr_SetString(PyExc_TypeError,
163
"argmax is unsupported for this type");
166
else if (PyArray_ISUNSIGNED(ap)) {
167
obj = PyInt_FromLong((long) -1);
169
else if (PyArray_TYPE(ap) == PyArray_BOOL) {
170
obj = PyInt_FromLong((long) 1);
173
obj = PyInt_FromLong((long) 0);
175
new = PyArray_EnsureAnyArray(PyNumber_Subtract(obj, (PyObject *)ap));
180
ret = PyArray_ArgMax((PyArrayObject *)new, axis, out);
188
NPY_NO_EXPORT PyObject *
189
PyArray_Max(PyArrayObject *ap, int axis, PyArrayObject *out)
194
if ((arr=(PyArrayObject *)_check_axis(ap, &axis, 0)) == NULL) {
197
ret = PyArray_GenericReduceFunction(arr, n_ops.maximum, axis,
198
arr->descr->type_num, out);
206
NPY_NO_EXPORT PyObject *
207
PyArray_Min(PyArrayObject *ap, int axis, PyArrayObject *out)
212
if ((arr=(PyArrayObject *)_check_axis(ap, &axis, 0)) == NULL) {
215
ret = PyArray_GenericReduceFunction(arr, n_ops.minimum, axis,
216
arr->descr->type_num, out);
224
NPY_NO_EXPORT PyObject *
225
PyArray_Ptp(PyArrayObject *ap, int axis, PyArrayObject *out)
229
PyObject *obj1 = NULL, *obj2 = NULL;
231
if ((arr=(PyArrayObject *)_check_axis(ap, &axis, 0)) == NULL) {
234
obj1 = PyArray_Max(arr, axis, out);
238
obj2 = PyArray_Min(arr, axis, NULL);
244
ret = PyObject_CallFunction(n_ops.subtract, "OOO", out, obj2, out);
247
ret = PyNumber_Subtract(obj1, obj2);
263
* Set variance to 1 to by-pass square-root calculation and return variance
266
NPY_NO_EXPORT PyObject *
267
PyArray_Std(PyArrayObject *self, int axis, int rtype, PyArrayObject *out,
270
return __New_PyArray_Std(self, axis, rtype, out, variance, 0);
273
NPY_NO_EXPORT PyObject *
274
__New_PyArray_Std(PyArrayObject *self, int axis, int rtype, PyArrayObject *out,
275
int variance, int num)
277
PyObject *obj1 = NULL, *obj2 = NULL, *obj3 = NULL, *new = NULL;
278
PyObject *ret = NULL, *newshape = NULL;
282
if ((new = _check_axis(self, &axis, 0)) == NULL) {
285
/* Compute and reshape mean */
286
obj1 = PyArray_EnsureAnyArray(PyArray_Mean((PyAO *)new, axis, rtype, NULL));
291
n = PyArray_NDIM(new);
292
newshape = PyTuple_New(n);
293
if (newshape == NULL) {
298
for (i = 0; i < n; i++) {
303
val = PyArray_DIM(new,i);
305
PyTuple_SET_ITEM(newshape, i, PyInt_FromLong((long)val));
307
obj2 = PyArray_Reshape((PyAO *)obj1, newshape);
315
/* Compute x = x - mx */
316
obj1 = PyArray_EnsureAnyArray(PyNumber_Subtract((PyObject *)new, obj2));
323
if (PyArray_ISCOMPLEX(obj1)) {
324
obj3 = PyArray_Conjugate((PyAO *)obj1, NULL);
334
obj2 = PyArray_EnsureAnyArray \
335
(PyArray_GenericBinaryFunction((PyAO *)obj1, obj3, n_ops.multiply));
342
if (PyArray_ISCOMPLEX(obj2)) {
343
obj3 = PyObject_GetAttrString(obj2, "real");
351
case NPY_CLONGDOUBLE:
352
rtype = NPY_LONGDOUBLE;
364
/* Compute add.reduce(x*x,axis) */
365
obj1 = PyArray_GenericReduceFunction((PyAO *)obj3, n_ops.add,
373
n = PyArray_DIM(new,axis);
379
obj2 = PyFloat_FromDouble(1.0/((double )n));
384
ret = PyNumber_Multiply(obj1, obj2);
389
obj1 = PyArray_EnsureAnyArray(ret);
391
ret = PyArray_GenericUnaryFunction((PyAO *)obj1, n_ops.sqrt);
394
if (ret == NULL || PyArray_CheckExact(self)) {
397
if (PyArray_Check(self) && self->ob_type == ret->ob_type) {
400
obj1 = PyArray_EnsureArray(ret);
404
ret = PyArray_View((PyAO *)obj1, NULL, self->ob_type);
407
if (PyArray_CopyAnyInto(out, (PyArrayObject *)ret) < 0) {
413
return (PyObject *)out;
422
NPY_NO_EXPORT PyObject *
423
PyArray_Sum(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
427
if ((new = _check_axis(self, &axis, 0)) == NULL) {
430
ret = PyArray_GenericReduceFunction((PyAO *)new, n_ops.add, axis,
439
NPY_NO_EXPORT PyObject *
440
PyArray_Prod(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
444
if ((new = _check_axis(self, &axis, 0)) == NULL) {
447
ret = PyArray_GenericReduceFunction((PyAO *)new, n_ops.multiply, axis,
456
NPY_NO_EXPORT PyObject *
457
PyArray_CumSum(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
461
if ((new = _check_axis(self, &axis, 0)) == NULL) {
464
ret = PyArray_GenericAccumulateFunction((PyAO *)new, n_ops.add, axis,
473
NPY_NO_EXPORT PyObject *
474
PyArray_CumProd(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
478
if ((new = _check_axis(self, &axis, 0)) == NULL) {
482
ret = PyArray_GenericAccumulateFunction((PyAO *)new,
483
n_ops.multiply, axis,
492
NPY_NO_EXPORT PyObject *
493
PyArray_Round(PyArrayObject *a, int decimals, PyArrayObject *out)
495
PyObject *f, *ret = NULL, *tmp, *op1, *op2;
497
PyArray_Descr *my_descr;
498
if (out && (PyArray_SIZE(out) != PyArray_SIZE(a))) {
499
PyErr_SetString(PyExc_ValueError,
500
"invalid output shape");
503
if (PyArray_ISCOMPLEX(a)) {
505
PyObject *round_part;
510
new = (PyObject *)out;
514
new = PyArray_Copy(a);
520
/* new.real = a.real.round(decimals) */
521
part = PyObject_GetAttrString(new, "real");
526
part = PyArray_EnsureAnyArray(part);
527
round_part = PyArray_Round((PyArrayObject *)part,
530
if (round_part == NULL) {
534
res = PyObject_SetAttrString(new, "real", round_part);
535
Py_DECREF(round_part);
541
/* new.imag = a.imag.round(decimals) */
542
part = PyObject_GetAttrString(new, "imag");
547
part = PyArray_EnsureAnyArray(part);
548
round_part = PyArray_Round((PyArrayObject *)part,
551
if (round_part == NULL) {
555
res = PyObject_SetAttrString(new, "imag", round_part);
556
Py_DECREF(round_part);
563
/* do the most common case first */
565
if (PyArray_ISINTEGER(a)) {
567
if (PyArray_CopyAnyInto(out, a) < 0) {
571
return (PyObject *)out;
575
return (PyObject *)a;
580
return PyObject_CallFunction(n_ops.rint, "OO", a, out);
582
return PyObject_CallFunction(n_ops.rint, "O", a);
584
op1 = n_ops.multiply;
585
op2 = n_ops.true_divide;
588
op1 = n_ops.true_divide;
589
op2 = n_ops.multiply;
590
decimals = -decimals;
593
if (PyArray_ISINTEGER(a)) {
595
my_descr = PyArray_DescrFromType(NPY_DOUBLE);
601
out = (PyArrayObject *)PyArray_Empty(a->nd, a->dimensions,
603
PyArray_ISFORTRAN(a));
611
f = PyFloat_FromDouble(power_of_ten(decimals));
615
ret = PyObject_CallFunction(op1, "OOO", a, f, out);
619
tmp = PyObject_CallFunction(n_ops.rint, "OO", ret, ret);
626
tmp = PyObject_CallFunction(op2, "OOO", ret, f, ret);
639
tmp = PyArray_CastToType((PyArrayObject *)ret,
640
a->descr, PyArray_ISFORTRAN(a));
651
NPY_NO_EXPORT PyObject *
652
PyArray_Mean(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
654
PyObject *obj1 = NULL, *obj2 = NULL;
657
if ((new = _check_axis(self, &axis, 0)) == NULL) {
660
obj1 = PyArray_GenericReduceFunction((PyAO *)new, n_ops.add, axis,
662
obj2 = PyFloat_FromDouble((double) PyArray_DIM(new,axis));
664
if (obj1 == NULL || obj2 == NULL) {
670
ret = PyNumber_Divide(obj1, obj2);
673
ret = PyObject_CallFunction(n_ops.divide, "OOO", out, obj2, out);
683
NPY_NO_EXPORT PyObject *
684
PyArray_Any(PyArrayObject *self, int axis, PyArrayObject *out)
688
if ((new = _check_axis(self, &axis, 0)) == NULL) {
691
ret = PyArray_GenericReduceFunction((PyAO *)new,
692
n_ops.logical_or, axis,
701
NPY_NO_EXPORT PyObject *
702
PyArray_All(PyArrayObject *self, int axis, PyArrayObject *out)
706
if ((new = _check_axis(self, &axis, 0)) == NULL) {
709
ret = PyArray_GenericReduceFunction((PyAO *)new,
710
n_ops.logical_and, axis,
718
_GenericBinaryOutFunction(PyArrayObject *m1, PyObject *m2, PyArrayObject *out,
722
return PyObject_CallFunction(op, "OO", m1, m2);
725
return PyObject_CallFunction(op, "OOO", m1, m2, out);
730
_slow_array_clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out)
732
PyObject *res1=NULL, *res2=NULL;
735
res1 = _GenericBinaryOutFunction(self, max, out, n_ops.minimum);
741
res1 = (PyObject *)self;
746
res2 = _GenericBinaryOutFunction((PyArrayObject *)res1,
747
min, out, n_ops.maximum);
764
NPY_NO_EXPORT PyObject *
765
PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out)
767
PyArray_FastClipFunc *func;
768
int outgood = 0, ingood = 0;
769
PyArrayObject *maxa = NULL;
770
PyArrayObject *mina = NULL;
771
PyArrayObject *newout = NULL, *newin = NULL;
772
PyArray_Descr *indescr, *newdescr;
773
char *max_data, *min_data;
776
if ((max == NULL) && (min == NULL)) {
777
PyErr_SetString(PyExc_ValueError, "array_clip: must set either max "\
782
func = self->descr->f->fastclip;
783
if (func == NULL || (min != NULL && !PyArray_CheckAnyScalar(min)) ||
784
(max != NULL && !PyArray_CheckAnyScalar(max))) {
785
return _slow_array_clip(self, min, max, out);
787
/* Use the fast scalar clip function */
789
/* First we need to figure out the correct type */
792
indescr = PyArray_DescrFromObject(min, NULL);
793
if (indescr == NULL) {
798
newdescr = PyArray_DescrFromObject(max, indescr);
800
if (newdescr == NULL) {
805
/* Steal the reference */
811
* Use the scalar descriptor only if it is of a bigger
812
* KIND than the input array (and then find the
813
* type that matches both).
815
if (PyArray_ScalarKind(newdescr->type_num, NULL) >
816
PyArray_ScalarKind(self->descr->type_num, NULL)) {
817
indescr = _array_small_type(newdescr, self->descr);
818
func = indescr->f->fastclip;
820
return _slow_array_clip(self, min, max, out);
824
indescr = self->descr;
829
if (!PyDataType_ISNOTSWAPPED(indescr)) {
830
PyArray_Descr *descr2;
831
descr2 = PyArray_DescrNewByteorder(indescr, '=');
833
if (descr2 == NULL) {
839
/* Convert max to an array */
841
maxa = (NPY_AO *)PyArray_FromAny(max, indescr, 0, 0,
848
/* Side-effect of PyArray_FromAny */
853
* If we are unsigned, then make sure min is not < 0
854
* This is to match the behavior of _slow_array_clip
856
* We allow min and max to go beyond the limits
857
* for other data-types in which case they
858
* are interpreted as their modular counterparts.
861
if (PyArray_ISUNSIGNED(self)) {
863
zero = PyInt_FromLong(0);
864
cmp = PyObject_RichCompareBool(min, zero, Py_LT);
881
/* Convert min to an array */
883
mina = (NPY_AO *)PyArray_FromAny(min, indescr, 0, 0,
893
* Check to see if input is single-segment, aligned,
894
* and in native byteorder
896
if (PyArray_ISONESEGMENT(self) && PyArray_CHKFLAGS(self, ALIGNED) &&
897
PyArray_ISNOTSWAPPED(self) && (self->descr == indescr)) {
903
if (PyArray_ISFORTRAN(self)) {
910
newin = (NPY_AO *)PyArray_FromArray(self, indescr, flags);
921
* At this point, newin is a single-segment, aligned, and correct
922
* byte-order array of the correct type
924
* if ingood == 0, then it is a copy, otherwise,
925
* it is the original input.
929
* If we have already made a copy of the data, then use
930
* that as the output array
932
if (out == NULL && !ingood) {
937
* Now, we know newin is a usable array for fastclip,
938
* we need to make sure the output array is available
943
out = (NPY_AO*)PyArray_NewFromDescr(self->ob_type,
947
PyArray_ISFORTRAN(self),
955
/* Input is good at this point */
959
if (!outgood && PyArray_ISONESEGMENT(out) &&
960
PyArray_CHKFLAGS(out, ALIGNED) && PyArray_ISNOTSWAPPED(out) &&
961
PyArray_EquivTypes(out->descr, indescr)) {
966
* Do we still not have a suitable output array?
971
if (PyArray_ISFORTRAN(out))
975
oflags |= NPY_UPDATEIFCOPY | NPY_FORCECAST;
977
newout = (NPY_AO*)PyArray_FromArray(out, indescr, oflags);
978
if (newout == NULL) {
987
/* make sure the shape of the output array is the same */
988
if (!PyArray_SAMESHAPE(newin, newout)) {
989
PyErr_SetString(PyExc_ValueError, "clip: Output array must have the"
990
"same shape as the input.");
993
if (newout->data != newin->data) {
994
memcpy(newout->data, newin->data, PyArray_NBYTES(newin));
997
/* Now we can call the fast-clip function */
998
min_data = max_data = NULL;
1000
min_data = mina->data;
1003
max_data = maxa->data;
1005
func(newin->data, PyArray_SIZE(newin), min_data, max_data, newout->data);
1007
/* Clean up temporary variables */
1011
/* Copy back into out if out was not already a nice array. */
1013
return (PyObject *)out;
1019
PyArray_XDECREF_ERR(newout);
1027
NPY_NO_EXPORT PyObject *
1028
PyArray_Conjugate(PyArrayObject *self, PyArrayObject *out)
1030
if (PyArray_ISCOMPLEX(self)) {
1032
return PyArray_GenericUnaryFunction(self,
1036
return PyArray_GenericBinaryFunction(self,
1044
if (PyArray_CopyAnyInto(out, self) < 0) {
1053
return (PyObject *)ret;
1060
NPY_NO_EXPORT PyObject *
1061
PyArray_Trace(PyArrayObject *self, int offset, int axis1, int axis2,
1062
int rtype, PyArrayObject *out)
1064
PyObject *diag = NULL, *ret = NULL;
1066
diag = PyArray_Diagonal(self, offset, axis1, axis2);
1070
ret = PyArray_GenericReduceFunction((PyAO *)diag, n_ops.add, -1, rtype, out);