diff options
author | cookedm <cookedm@localhost> | 2006-03-07 22:02:23 +0000 |
---|---|---|
committer | cookedm <cookedm@localhost> | 2006-03-07 22:02:23 +0000 |
commit | c9d2cdc913171d079eabb6b71405d7101041356b (patch) | |
tree | a66f5fe7b0d197b434e83fe3e17dbd87076f3839 /numpy | |
parent | e3a1d502e5d08a755dd1d91eb74341c7617adbdd (diff) | |
parent | 5bb7342c6c2fa9757edc28df0dbbc8d433ac50d8 (diff) | |
download | numpy-c9d2cdc913171d079eabb6b71405d7101041356b.tar.gz |
Merge trunk (r2142:2204) to power_optimization branch
Diffstat (limited to 'numpy')
45 files changed, 1203 insertions, 522 deletions
diff --git a/numpy/__init__.py b/numpy/__init__.py index a945c75a5..17202cd95 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -31,20 +31,26 @@ else: del _os from _import_tools import PackageLoader pkgload = PackageLoader() - pkgload('testing','core','linalg','lib','dft','random','f2py','distutils', + pkgload('testing','core','lib','linalg','dft','random','f2py', + 'distutils', verbose=NUMPY_IMPORT_VERBOSE,postpone=False) - __doc__ += """ + if __doc__ is not None: + __doc__ += """ Available subpackages --------------------- """ - __doc__ += pkgload.get_pkgdocs() + if __doc__ is not None: + __doc__ += pkgload.get_pkgdocs() + + def test(level=1, verbosity=1): + return NumpyTest().test(level, verbosity) - test = ScipyTest('numpy').test import add_newdocs - __doc__ += """ + if __doc__ is not None: + __doc__ += """ Utility tools ------------- diff --git a/numpy/_import_tools.py b/numpy/_import_tools.py index 5d4e66de1..4989ab340 100644 --- a/numpy/_import_tools.py +++ b/numpy/_import_tools.py @@ -327,3 +327,17 @@ class PackageLoader: self._format_titles(symbols,'-->') return retstr + +class PackageLoaderDebug(PackageLoader): + def _execcmd(self,cmdstr): + """ Execute command in parent_frame.""" + frame = self.parent_frame + print 'Executing',`cmdstr`,'...', + sys.stdout.flush() + exec (cmdstr, frame.f_globals,frame.f_locals) + print 'ok' + sys.stdout.flush() + return + +if int(os.environ.get('NUMPY_IMPORT_DEBUG','0')): + PackageLoader = PackageLoaderDebug diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index af57f0f69..429e423c5 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -25,5 +25,6 @@ __all__ += defmatrix.__all__ __all__ += rec.__all__ __all__ += char.__all__ -from numpy.testing import ScipyTest -test = ScipyTest().test +def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index 4e5db082a..a78601188 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -79,7 +79,7 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth the number of characters per line for the purpose of inserting line breaks. (default 75) - supress Boolean value indicating whether or not suppress printing + suppress Boolean value indicating whether or not suppress printing of small floating point values using scientific notation (default False) """ @@ -95,7 +95,7 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None, if (precision is not None): _float_output_precision = precision if (suppress is not None): - _float_output_supress_small = not not suppress + _float_output_suppress_small = not not suppress return def get_printoptions(): @@ -139,8 +139,6 @@ def _array2string(a, max_line_width, precision, suppress_small, separator=' ', else: summary_insert = "" data = a.ravel() - - items_per_line = a.shape[-1] try: format_function = a._format @@ -168,9 +166,9 @@ def _array2string(a, max_line_width, precision, suppress_small, separator=' ', format = "%s" format_function = lambda x, f = format: repr(x) else: - format = '%s' - format_function = lambda x, f = format: format % str(x) - + format = '%s' + format_function = lambda x, f = format: format % str(x) + next_line_prefix = " " # skip over "[" next_line_prefix += " "*len(prefix) # skip over array( @@ -252,7 +250,7 @@ def _formatArray(a, format_function, rank, max_line_len, s += _formatArray(a[i], format_function, rank-1, max_line_len, " " + next_line_prefix, separator, edge_items, summary_insert) - s = s.rstrip()+ sep.rstrip() + '\n'*max(rank-1,1) + s = s.rstrip() + sep.rstrip() + '\n'*max(rank-1,1) if summary_insert1: s += next_line_prefix + summary_insert1 + "\n" diff --git a/numpy/core/blasdot/_dotblas.c b/numpy/core/blasdot/_dotblas.c index 6490e40e7..d1971fa0f 100644 --- a/numpy/core/blasdot/_dotblas.c +++ b/numpy/core/blasdot/_dotblas.c @@ -229,6 +229,10 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) ap1shape = ap2shape; ap2shape = _scalar; } + + if (ap1shape == _row) ap1stride = ap1->strides[1]; + else ap1stride = ap1->strides[0]; + /* Fix it so that dot(shape=(N,1), shape=(1,)) and dot(shape=(1,), shape=(1,N)) both return an (N,) array (but use the fast scalar code) @@ -238,16 +242,13 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) nd = 1; if (ap1shape == _column) { dimensions[0] = ap1->dimensions[0]; - ap1stride = ap1->strides[0] / sizeof(double); } else { dimensions[0] = ap1->dimensions[1]; - ap1stride = ap1->strides[1] / sizeof(double); } l = dimensions[0]; } else { - ap1stride = ap1->strides[0] / sizeof(double); nd = ap1->nd; for (l = 1, j = 0; j < nd; j++) { dimensions[j] = ap1->dimensions[j]; @@ -310,7 +311,7 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) } else if (ap1shape != _matrix) { cblas_daxpy(l, *((double *)ap2->data), (double *)ap1->data, - ap1stride, (double *)ret->data, 1); + ap1stride/sizeof(double), (double *)ret->data, 1); } else { int maxind, oind, i, a1s, rets; @@ -343,7 +344,7 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) } else if (ap1shape != _matrix) { cblas_zaxpy(l, (double *)ap2->data, (double *)ap1->data, - ap1stride, (double *)ret->data, 1); + ap1stride/sizeof(cdouble), (double *)ret->data, 1); } else { int maxind, oind, i, a1s, rets; @@ -372,7 +373,7 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) } else if (ap1shape != _matrix) { cblas_saxpy(l, *((float *)ap2->data), (float *)ap1->data, - ap1stride, (float *)ret->data, 1); + ap1stride/sizeof(float), (float *)ret->data, 1); } else { int maxind, oind, i, a1s, rets; @@ -405,7 +406,7 @@ dotblas_matrixproduct(PyObject *dummy, PyObject *args) } else if (ap1shape != _matrix) { cblas_caxpy(l, (float *)ap2->data, (float *)ap1->data, - ap1stride, (float *)ret->data, 1); + ap1stride/sizeof(cfloat), (float *)ret->data, 1); } else { int maxind, oind, i, a1s, rets; diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index ac26cc6cc..4edbb5363 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -432,6 +432,12 @@ defdict = { TD(flts, f='floor'), TD(M, f='floor'), ), +'rint' : + Ufunc(1, 1, None, + 'round x elementwise to the nearest integer, round halfway cases away from zero', + TD(flts, f='rint'), + TD(M, f='rint'), + ), 'arctan2' : Ufunc(2, 1, None, 'a safe and correct arctan(x1/x2)', diff --git a/numpy/core/code_generators/multiarray_api_order.txt b/numpy/core/code_generators/multiarray_api_order.txt index d328ad7fc..c558b636b 100644 --- a/numpy/core/code_generators/multiarray_api_order.txt +++ b/numpy/core/code_generators/multiarray_api_order.txt @@ -65,4 +65,5 @@ PyArray_ArangeObj PyArray_SortkindConverter PyArray_LexSort PyArray_GetNDArrayCVersion +PyArray_Round diff --git a/numpy/core/defmatrix.py b/numpy/core/defmatrix.py index 9234d2f53..d89260ef6 100644 --- a/numpy/core/defmatrix.py +++ b/numpy/core/defmatrix.py @@ -2,8 +2,7 @@ __all__ = ['matrix', 'bmat', 'mat', 'asmatrix'] import numeric as N -from numeric import ArrayType, concatenate, integer, multiply, power, \ - isscalar, binary_repr +from numeric import ArrayType, concatenate, isscalar, binary_repr import types import string as str_ import sys @@ -101,6 +100,16 @@ class matrix(N.ndarray): def __array_finalize__(self, obj): ndim = self.ndim + if (ndim == 2): + return + if (ndim > 2): + newshape = tuple([x for x in self.shape if x > 1]) + ndim = len(newshape) + if ndim == 2: + self.shape = newshape + return + elif (ndim > 2): + raise ValueError, "shape too large to be a matrix." if ndim == 0: self.shape = (1,1) elif ndim == 1: @@ -135,7 +144,11 @@ class matrix(N.ndarray): return truend def __mul__(self, other): - return N.dot(self, other) + if isinstance(other, N.ndarray) or N.isscalar(other) or \ + not hasattr(other, '__rmul__'): + return N.dot(self, other) + else: + return NotImplemented def __rmul__(self, other): return N.dot(other, self) @@ -180,7 +193,7 @@ class matrix(N.ndarray): raise TypeError, "exponent must be an integer" def __rpow__(self, other): - raise NotImplementedError + return NotImplemented def __repr__(self): return repr(self.__array__()).replace('array','matrix') @@ -251,7 +264,7 @@ def _from_string(str,gdict,ldict): return concatenate(rowtup,axis=0) -def bmat(obj,ldict=None, gdict=None): +def bmat(obj, ldict=None, gdict=None): """Build a matrix object from string, nested sequence, or array. Ex: F = bmat('A, B; C, D') diff --git a/numpy/core/include/numpy/arrayobject.h b/numpy/core/include/numpy/arrayobject.h index 264e2649b..c380b3837 100644 --- a/numpy/core/include/numpy/arrayobject.h +++ b/numpy/core/include/numpy/arrayobject.h @@ -1,3 +1,4 @@ + /* This expects the following variables to be defined (besides the usual ones from pyconfig.h @@ -77,8 +78,8 @@ extern "C" CONFUSE_EMACS #define PY_FAIL 0 #define PY_SUCCEED 1 - /* Helpful to distinguish what is installed */ -#define NDARRAY_VERSION 0x00090500 + /* Helpful to distinguish what is installed */ +#define NDARRAY_VERSION 0x00090504 /* Some platforms don't define bool, long long, or long double. Handle that here. @@ -224,6 +225,17 @@ typedef enum { } PyArray_SORTKIND; #define PyArray_NSORTS PyArray_TIMSORT + 1 + +typedef enum { + PyArray_NOSCALAR=0, + PyArray_BOOL_SCALAR=1, + PyArray_INTPOS_SCALAR=2, + PyArray_INTNEG_SCALAR=3, + PyArray_FLOAT_SCALAR=4, + PyArray_COMPLEX_SCALAR=5, + PyArray_OBJECT_SCALAR=6, +} PyArray_SCALARKIND; + /* Define bit-width array types and typedefs */ #define MAX_INT8 127 @@ -799,6 +811,8 @@ typedef int (PyArray_FillFunc)(void *, intp, void *); typedef int (PyArray_SortFunc)(void *, intp, void *); typedef int (PyArray_ArgSortFunc)(void *, intp *, intp, void *); +typedef int (PyArray_FillWithScalarFunc)(void *, intp, void *, void *); + typedef struct { intp *ptr; int len; @@ -841,6 +855,9 @@ typedef struct { /* Used for arange */ PyArray_FillFunc *fill; + /* Function to fill arrays with scalar values */ + PyArray_FillWithScalarFunc *fillwithscalar; + /* Sorting functions */ PyArray_SortFunc *sort[PyArray_NSORTS]; PyArray_ArgSortFunc *argsort[PyArray_NSORTS]; @@ -905,6 +922,7 @@ typedef struct PyArrayObject { PyObject *weakreflist; /* For weakreferences */ } PyArrayObject; + #define fortran fortran_ /* For some compilers */ /* Mirrors buffer object to ptr */ @@ -1018,13 +1036,6 @@ typedef struct { #endif -#define UFUNC_NOSCALAR 0 -#define UFUNC_BOOL_SCALAR 1 -#define UFUNC_INTPOS_SCALAR 2 -#define UFUNC_INTNEG_SCALAR 3 -#define UFUNC_FLOAT_SCALAR 4 -#define UFUNC_COMPLEX_SCALAR 5 -#define UFUNC_OBJECT_SCALAR 6 typedef struct { @@ -1397,9 +1408,8 @@ typedef struct { #define PyArray_DescrCheck(op) ((op)->ob_type == &PyArrayDescr_Type) -#define PyArray_Check(op) ((op)->ob_type == &PyArray_Type || \ - PyObject_TypeCheck((op), &PyBigArray_Type)) -#define PyBigArray_CheckExact(op) ((op)->ob_type == &PyBigArray_Type) +#define PyArray_Check(op) ((op)->ob_type == &PyArray_Type || \ + PyObject_TypeCheck((op), &PyArray_Type)) #define PyArray_CheckExact(op) ((op)->ob_type == &PyArray_Type) #define PyArray_IsZeroDim(op) (PyArray_Check(op) && (PyArray_NDIM(op) == 0)) diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h index eb195a4ab..84b8661c5 100644 --- a/numpy/core/include/numpy/ufuncobject.h +++ b/numpy/core/include/numpy/ufuncobject.h @@ -301,7 +301,7 @@ typedef struct { } #define generate_divbyzero_error() fp_raise_xcp(FP_DIV_BY_ZERO) -#define generate_overflow_error() fp_raise_xcp(FE_OVERFLOW) +#define generate_overflow_error() fp_raise_xcp(FP_OVERFLOW) #else diff --git a/numpy/core/ma.py b/numpy/core/ma.py index ae10ca681..36cf32c90 100644 --- a/numpy/core/ma.py +++ b/numpy/core/ma.py @@ -7,11 +7,11 @@ Released for unlimited redistribution. Adapted for numpy_core 2005 by Travis Oliphant and (mainly) Paul Dubois. """ -import string, types, sys +import types, sys import umath import oldnumeric -from numeric import e, pi, newaxis, ndarray, inf +from numeric import newaxis, ndarray, inf from oldnumeric import typecodes, amax, amin from numerictypes import * import numeric @@ -21,7 +21,7 @@ ufunc_domain = {} # Ufunc fills lookup for __array__ ufunc_fills = {} -MaskType=bool_ +MaskType = bool_ nomask = MaskType(0) divide_tolerance = 1.e-35 @@ -77,11 +77,11 @@ def default_fill_value (obj): if isinstance(obj, types.FloatType): return default_real_fill_value elif isinstance(obj, types.IntType) or isinstance(obj, types.LongType): - return default_integer_fill_value + return default_integer_fill_value elif isinstance(obj, types.StringType): - return default_character_fill_value + return default_character_fill_value elif isinstance(obj, types.ComplexType): - return default_complex_fill_value + return default_complex_fill_value elif isinstance(obj, MaskedArray) or isinstance(obj, ndarray): x = obj.dtype.char if x in typecodes['Float']: @@ -120,7 +120,7 @@ def maximum_fill_value (obj): if isinstance(obj, types.FloatType): return -inf elif isinstance(obj, types.IntType) or isinstance(obj, types.LongType): - return -sys.maxint + return -sys.maxint elif isinstance(obj, MaskedArray) or isinstance(obj, ndarray): x = obj.dtype.char if x in typecodes['Float']: @@ -183,7 +183,7 @@ def make_mask (m, copy=0, flag=0): else: result = m.astype(MaskType) else: - result = filled(m,True).astype(MaskType) + result = filled(m, True).astype(MaskType) if flag and not oldnumeric.sometrue(oldnumeric.ravel(result)): return nomask @@ -298,6 +298,7 @@ class masked_unary_operation: self.fill = fill self.domain = domain self.__doc__ = getattr(aufunc, "__doc__", str(aufunc)) + self.__name__ = getattr(aufunc, "__name__", str(aufunc)) ufunc_domain[aufunc] = domain ufunc_fills[aufunc] = fill, @@ -309,14 +310,6 @@ class masked_unary_operation: if self.domain is not None: m = mask_or(m, self.domain(d1)) result = self.f(d1, *args, **kwargs) - if m is not nomask: - try: - shape = result.shape - except AttributeError: - pass - else: - if m.shape != shape: - m = mask_or(getmaskarray(a), getmaskarray(b)) return masked_array(result, m) def __str__ (self): @@ -330,8 +323,8 @@ class domain_safe_divide: return umath.absolute(a) * self.tolerance >= umath.absolute(b) class domained_binary_operation: - """Binary operations that have a domain, like divide. These are complicated so they - are a separate class. They have no reduce, outer or accumulate. + """Binary operations that have a domain, like divide. These are complicated + so they are a separate class. They have no reduce, outer or accumulate. """ def __init__ (self, abfunc, domain, fillx=0, filly=0): """abfunc(fillx, filly) must be defined. @@ -342,8 +335,9 @@ class domained_binary_operation: self.fillx = fillx self.filly = filly self.__doc__ = getattr(abfunc, "__doc__", str(abfunc)) + self.__name__ = getattr(abfunc, "__name__", str(abfunc)) ufunc_domain[abfunc] = domain - ufunc_fills[abfunc] = fillx,filly + ufunc_fills[abfunc] = fillx, filly def __call__(self, a, b): "Execute the call behavior." @@ -358,14 +352,6 @@ class domained_binary_operation: mb = mask_or(mb, t) m = mask_or(ma, mb) result = self.f(d1, d2) - if m is not nomask: - try: - shape = result.shape - except AttributeError: - pass - else: - if m.shape != shape: - m = mask_or(getmaskarray(a), getmaskarray(b)) return masked_array(result, m) def __str__ (self): @@ -381,7 +367,7 @@ class masked_binary_operation: self.filly = filly self.__doc__ = getattr(abfunc, "__doc__", str(abfunc)) ufunc_domain[abfunc] = None - ufunc_fills[abfunc] = fillx,filly + ufunc_fills[abfunc] = fillx, filly def __call__ (self, a, b, *args, **kwargs): "Execute the call behavior." @@ -389,14 +375,6 @@ class masked_binary_operation: d1 = filled(a, self.fillx) d2 = filled(b, self.filly) result = self.f(d1, d2, *args, **kwargs) - if m is not nomask: - try: - shape = result.shape - except AttributeError: - pass - else: - if m.shape != shape: - m = mask_or(getmaskarray(a), getmaskarray(b)) return masked_array(result, m) def reduce (self, target, axis=0): @@ -406,8 +384,8 @@ class masked_binary_operation: if t.shape == (): t = t.reshape(1) if m is not nomask: - m = make_mask(m, copy=1) - m.shape = (1,) + m = make_mask(m, copy=1) + m.shape = (1,) if m is nomask: return masked_array (self.f.reduce (t, axis)) else: @@ -462,7 +440,14 @@ tanh = masked_unary_operation(umath.tanh) absolute = masked_unary_operation(umath.absolute) fabs = masked_unary_operation(umath.fabs) negative = masked_unary_operation(umath.negative) -nonzero = masked_unary_operation(oldnumeric.nonzero) + +def nonzero(a): + """returns the indices of the elements of a which are not zero and not masked + + a must be 1d + """ + return asarray(filled(a, 0).nonzero()) + around = masked_unary_operation(oldnumeric.round_) floor = masked_unary_operation(umath.floor) ceil = masked_unary_operation(umath.ceil) @@ -751,11 +736,11 @@ array(data = %(data)s, n = len(self.shape) if self._mask is nomask: - if n <=1: + if n <= 1: return without_mask1 % {'data':str(self.filled())} return without_mask % {'data':str(self.filled())} else: - if n <=1: + if n <= 1: return with_mask % { 'data': str(self.filled()), 'mask': str(self._mask), @@ -976,7 +961,7 @@ array(data = %(data)s, "Return divide(other, self)" return floor_divide(other, self) - def __pow__(self,other, third=None): + def __pow__(self, other, third=None): "Return power(self, other, third)" return power(self, other, third) @@ -987,7 +972,7 @@ array(data = %(data)s, def __iadd__(self, other): "Add other to self in place." t = self._data.dtype.char - f = filled(other,0) + f = filled(other, 0) t1 = f.dtype.char if t == t1: pass @@ -1030,7 +1015,7 @@ array(data = %(data)s, def __imul__(self, other): "Add other to self in place." t = self._data.dtype.char - f = filled(other,0) + f = filled(other, 0) t1 = f.dtype.char if t == t1: pass @@ -1073,7 +1058,7 @@ array(data = %(data)s, def __isub__(self, other): "Subtract other from self in place." t = self._data.dtype.char - f = filled(other,0) + f = filled(other, 0) t1 = f.dtype.char if t == t1: pass @@ -1118,7 +1103,7 @@ array(data = %(data)s, def __idiv__(self, other): "Divide self by other in place." t = self._data.dtype.char - f = filled(other,0) + f = filled(other, 0) t1 = f.dtype.char if t == t1: pass @@ -1154,22 +1139,22 @@ array(data = %(data)s, self._shared_mask = 1 return self - def __eq__(self,other): + def __eq__(self, other): return equal(self,other) - def __ne__(self,other): + def __ne__(self, other): return not_equal(self,other) - def __lt__(self,other): + def __lt__(self, other): return less(self,other) - def __le__(self,other): + def __le__(self, other): return less_equal(self,other) - def __gt__(self,other): + def __gt__(self, other): return greater(self,other) - def __ge__(self,other): + def __ge__(self, other): return greater_equal(self,other) def astype (self, tc): @@ -1204,7 +1189,7 @@ array(data = %(data)s, if ls == 1: return s[0] if axis is None: - return reduce(lambda x,y:x*y, s) + return reduce(lambda x, y:x*y, s) else: n = s[axis] t = list(s) @@ -1214,9 +1199,9 @@ array(data = %(data)s, w = oldnumeric.ravel(m).astype(int) n1 = size(w) if n1 == 1: - n2 = w[0] + n2 = w[0] else: - n2 = umath.add.reduce(w) + n2 = umath.add.reduce(w) return n1 - n2 else: n1 = size(m, axis) @@ -1350,6 +1335,10 @@ array(data = %(data)s, v = default_fill_value (self.raw_data()) self._fill_value = v + def _get_ndim(self): + return self._data.ndim + ndim = property(_get_ndim, doc=numeric.ndarray.ndim.__doc__) + def _get_size (self): return self._data.size size = property(fget=_get_size, doc="Number of elements in the array.") @@ -1500,7 +1489,7 @@ def left_shift (a, n): d = umath.left_shift(filled(a), n) return masked_array(d) else: - d = umath.left_shift(filled(a,0), n) + d = umath.left_shift(filled(a, 0), n) return masked_array(d, m) def right_shift (a, n): @@ -1510,7 +1499,7 @@ def right_shift (a, n): d = umath.right_shift(filled(a), n) return masked_array(d) else: - d = umath.right_shift(filled(a,0), n) + d = umath.right_shift(filled(a, 0), n) return masked_array(d, m) def resize (a, new_shape): @@ -1628,7 +1617,7 @@ def average (a, axis=0, weights=None, returned = 0): else: if weights is None: n = add.reduce(a.ravel()) - w = oldnumeric.choose(mask, (1.0,0.0)).ravel() + w = oldnumeric.choose(mask, (1.0, 0.0)).ravel() d = umath.add.reduce(w) del w else: @@ -1654,7 +1643,7 @@ def average (a, axis=0, weights=None, returned = 0): elif wsh == (ash[axis],): ni = ash[axis] r = [newaxis]*len(ash) - r[axis] = slice(None,None,1) + r[axis] = slice(None, None, 1) w = eval ("w["+ repr(tuple(r)) + "] * ones(ash, float)") n = add.reduce(a*w, axis) d = add.reduce(w, axis) @@ -1679,7 +1668,7 @@ def average (a, axis=0, weights=None, returned = 0): elif wsh == (ash[axis],): ni = ash[axis] r = [newaxis]*len(ash) - r[axis] = slice(None,None,1) + r[axis] = slice(None, None, 1) w = eval ("w["+ repr(tuple(r)) + "] * masked_array(ones(ash, float), mask)") n = add.reduce(a*w, axis) d = add.reduce(w, axis) @@ -1711,7 +1700,7 @@ def where (condition, x, y): The type depends on x and y. It is integer if both x and y are the value masked. """ - fc = filled(not_equal(condition,0), 0) + fc = filled(not_equal(condition, 0), 0) xv = filled(x) xm = getmask(x) yv = filled(y) @@ -1732,7 +1721,7 @@ def choose (indices, t): m = getmask(x) if m is nomask: return 0 return m - c = filled(indices,0) + c = filled(indices, 0) masks = [nmask(x) for x in t] a = [fmask(x) for x in t] d = numeric.choose(c, a) @@ -1766,7 +1755,7 @@ def masked_less_equal(x, value, copy=1): def masked_not_equal(x, value, copy=1): "masked_not_equal(x, value) = x masked where x != value" - d = filled(x,0) + d = filled(x, 0) c = umath.not_equal(d, value) m = mask_or(c, getmask(x)) return array(d, mask=m, copy=copy) @@ -1775,7 +1764,7 @@ def masked_equal(x, value, copy=1): """masked_equal(x, value) = x masked where x == value For floating point consider masked_values(x, value) instead. """ - d = filled(x,0) + d = filled(x, 0) c = umath.equal(d, value) m = mask_or(c, getmask(x)) return array(d, mask=m, copy=copy) @@ -1788,7 +1777,7 @@ def masked_inside(x, v1, v2, copy=1): t = v2 v2 = v1 v1 = t - d=filled(x, 0) + d = filled(x, 0) c = umath.logical_and(umath.less_equal(d, v2), umath.greater_equal(d, v1)) m = mask_or(c, getmask(x)) return array(d, mask = m, copy=copy) @@ -1801,7 +1790,7 @@ def masked_outside(x, v1, v2, copy=1): t = v2 v2 = v1 v1 = t - d = filled(x,0) + d = filled(x, 0) c = umath.logical_or(umath.less(d, v1), umath.greater(d, v2)) m = mask_or(c, getmask(x)) return array(d, mask = m, copy=copy) @@ -1886,7 +1875,7 @@ def putmask(a, mask, values): a.unshare_mask() numeric.putmask(a.raw_mask(), mask, 0) -def innerproduct(a,b): +def innerproduct(a, b): """innerproduct(a,b) returns the dot product of two arrays, which has shape a.shape[:-1] + b.shape[:-1] with elements computed by summing the product of the elements from the last dimensions of a and b. @@ -1900,8 +1889,8 @@ def innerproduct(a,b): def outerproduct(a, b): """outerproduct(a,b) = {a[i]*b[j]}, has shape (len(a),len(b))""" - fa = filled(a,0).ravel() - fb = filled(b,0).ravel() + fa = filled(a, 0).ravel() + fb = filled(b, 0).ravel() d = numeric.outerproduct(fa, fb) ma = getmask(a) mb = getmask(b) @@ -1909,7 +1898,7 @@ def outerproduct(a, b): return masked_array(d) ma = getmaskarray(a) mb = getmaskarray(b) - m = make_mask(1-numeric.outerproduct(1-ma,1-mb), copy=0) + m = make_mask(1-numeric.outerproduct(1-ma, 1-mb), copy=0) return masked_array(d, m) def dot(a, b): @@ -1917,7 +1906,7 @@ def dot(a, b): is over the last dimension of a and the second-to-last dimension of b. Masked values are replaced by zeros. See also innerproduct. """ - return innerproduct(filled(a,0), numeric.swapaxes(filled(b,0), -1, -2)) + return innerproduct(filled(a, 0), numeric.swapaxes(filled(b, 0), -1, -2)) def compress(condition, x, dimension=-1): """Select those parts of x for which condition is true. @@ -1926,7 +1915,7 @@ def compress(condition, x, dimension=-1): c = filled(condition, 0) m = getmask(x) if m is not nomask: - m=numeric.compress(c, m, dimension) + m = numeric.compress(c, m, dimension) d = numeric.compress(c, filled(x), dimension) return masked_array(d, m) @@ -2093,7 +2082,7 @@ def argmax (x, axis = -1, fill_value=None): def fromfunction (f, s): """apply f to s to create array as in umath.""" - return masked_array(numeric.fromfunction(f,s)) + return masked_array(numeric.fromfunction(f, s)) def asarray(data, dtype=None): """asarray(data, dtype) = array(data, dtype, copy=0) @@ -2158,7 +2147,6 @@ array.min = _m(_min) del _min array.mean = _m(average) array.nbytes = property(_m(not_implemented)) -array.ndim = _m(not_implemented) array.newbyteorder = _m(not_implemented) array.nonzero = _m(nonzero) array.prod = _m(product) @@ -2180,6 +2168,7 @@ array.trace = _m(not_implemented) array.transpose = _m(transpose) array.var = _m(not_implemented) array.view = _m(not_implemented) +array.round = _m(around) del _m, MethodType, not_implemented diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py index f4dc0b463..8e9faa5b0 100644 --- a/numpy/core/memmap.py +++ b/numpy/core/memmap.py @@ -80,7 +80,7 @@ class memmap(ndarray): return self def __array_finalize__(self, obj): - if not isinstance(obj, memmap): + if obj is not None and not isinstance(obj, memmap): raise ValueError, "Cannot create a memmap array that way" self._mmap = None diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index cc1b0b1de..4ba599081 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -1,4 +1,4 @@ -__all__ = ['newaxis', 'ndarray', 'bigndarray', 'flatiter', 'ufunc', +__all__ = ['newaxis', 'ndarray', 'flatiter', 'ufunc', 'arange', 'array', 'zeros', 'empty', 'broadcast', 'dtype', 'fromstring', 'fromfile', 'frombuffer','newbuffer', 'getbuffer', @@ -43,10 +43,9 @@ extend_all(numerictypes) newaxis = None ndarray = multiarray.ndarray -bigndarray = multiarray.bigndarray flatiter = multiarray.flatiter broadcast = multiarray.broadcast -dtype=multiarray.dtype +dtype = multiarray.dtype ufunc = type(sin) arange = multiarray.arange @@ -176,7 +175,7 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): returned. """ if axis is not None: - axisa,axisb,axisc=(axis,)*3 + axisa,axisb,axisc=(axis,)*3 a = _move_axis_to_0(asarray(a), axisa) b = _move_axis_to_0(asarray(b), axisb) msg = "incompatible dimensions for cross product\n"\ @@ -236,15 +235,11 @@ def array_repr(arr, max_line_width=None, precision=None, suppress_small=None): return cName + "(%s)" % lst else: typename=arr.dtype.type.__name__[:-6] + lf = '' if issubclass(arr.dtype.type, flexible): - if typename not in ['unicode','string','void']: - typename = arr.dtype.type.__name__ - if typename == 'unicode': - size = arr.itemsize >> 2 - else: - size = arr.itemsize; - typename = "(%s,%d)" % (typename, size) - return cName + "(%s, dtype=%s)" % (lst, typename) + typename = str(arr.dtype) + lf = '\n'+' '*len("array(") + return cName + "(%s, %sdtype=%s)" % (lst, lf, typename) def array_str(a, max_line_width=None, precision=None, suppress_small=None): return array2string(a, max_line_width, precision, suppress_small, ' ', "", str) @@ -344,11 +339,11 @@ def ones(shape, dtype=int_, fortran=False): """ones(shape, dtype=int_) returns an array of the given dimensions which is initialized to all ones. """ - # This appears to be slower... - #a = empty(shape, dtype, fortran) - #a.fill(1) - a = zeros(shape, dtype, fortran) - a+=1 + a = empty(shape, dtype, fortran) + a.fill(1) + # Above is faster now after addition of fast loops. + #a = zeros(shape, dtype, fortran) + #a+=1 return a def identity(n,dtype=int_): diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py index aeb2c5225..d7df600c4 100644 --- a/numpy/core/numerictypes.py +++ b/numpy/core/numerictypes.py @@ -1,5 +1,3 @@ -# Borrowed and adapted from numarray - """numerictypes: Define the numeric type objects This module is designed so 'from numerictypes import *' is safe. @@ -78,7 +76,8 @@ $Id: numerictypes.py,v 1.17 2005/09/09 22:20:06 teoliphant Exp $ """ # we add more at the bottom -__all__ = ['typeDict', 'typeNA', 'sctypes', 'ScalarType', 'obj2sctype', 'cast', 'nbytes', 'sctype2char','maximum_sctype', 'issctype'] +__all__ = ['typeDict', 'typeNA', 'sctypes', 'ScalarType', 'obj2sctype', 'cast', 'nbytes', + 'sctype2char', 'maximum_sctype', 'issctype'] from multiarray import typeinfo, ndarray, array, empty import types as _types @@ -233,7 +232,7 @@ def _construct_char_code_lookup(): for name in typeinfo.keys(): tup = typeinfo[name] if isinstance(tup, tuple): - if tup[0] not in ['p','P']: + if tup[0] not in ['p','P']: _sctype2char_dict[tup[-1]] = tup[0] _construct_char_code_lookup() @@ -368,7 +367,7 @@ for key in _sctype2char_dict.keys(): cast[key] = lambda x, k=key : array(x, copy=False).astype(k) -_unicodesize = array('u','U').itemsize +_unicodesize = array('u','U1').itemsize # Create the typestring lookup dictionary _typestr = _typedict() diff --git a/numpy/core/records.py b/numpy/core/records.py index fa901482e..f389388d7 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -1,12 +1,10 @@ -__all__ = ['record', 'recarray','format_parser'] +__all__ = ['record', 'recarray', 'format_parser'] import numeric as sb from defchararray import chararray import numerictypes as nt -import sys import types import stat, os -import _internal _byteorderconv = {'b':'>', 'l':'<', diff --git a/numpy/core/setup.py b/numpy/core/setup.py index dce7477d1..75e21551a 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -73,6 +73,8 @@ def configuration(parent_package='',top_path=None): moredefs.append('HAVE_ISNAN') if config_cmd.check_func('isinf', **kws_args): moredefs.append('HAVE_ISINF') + if config_cmd.check_func('rint', **kws_args): + moredefs.append('HAVE_RINT') if sys.version[:3] < '2.4': kws_args['headers'].append('stdlib.h') diff --git a/numpy/core/src/arraymethods.c b/numpy/core/src/arraymethods.c index fe87009e0..c48904f25 100644 --- a/numpy/core/src/arraymethods.c +++ b/numpy/core/src/arraymethods.c @@ -21,7 +21,7 @@ array_take(PyArrayObject *self, PyObject *args, PyObject *kwds) return _ARET(PyArray_Take(self, indices, dimension)); } -static char doc_fill[] = "a.fill(value) places the scalar value at every"\ +static char doc_fill[] = "a.fill(value) places the scalar value at every "\ "position in the array."; static PyObject * @@ -166,9 +166,9 @@ array_view(PyArrayObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "|O", &otype)) return NULL; if (otype) { - if (PyType_Check(otype) && \ + if (PyType_Check(otype) && \ PyType_IsSubtype((PyTypeObject *)otype, - &PyBigArray_Type)) { + &PyArray_Type)) { return PyArray_View(self, NULL, (PyTypeObject *)otype); } @@ -183,12 +183,15 @@ array_view(PyArrayObject *self, PyObject *args) static char doc_argmax[] = "a.argmax(axis=None)"; static PyObject * -array_argmax(PyArrayObject *self, PyObject *args) +array_argmax(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; return _ARET(PyArray_ArgMax(self, axis)); } @@ -196,12 +199,15 @@ array_argmax(PyArrayObject *self, PyObject *args) static char doc_argmin[] = "a.argmin(axis=None)"; static PyObject * -array_argmin(PyArrayObject *self, PyObject *args) +array_argmin(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; return _ARET(PyArray_ArgMin(self, axis)); } @@ -209,12 +215,15 @@ array_argmin(PyArrayObject *self, PyObject *args) static char doc_max[] = "a.max(axis=None)"; static PyObject * -array_max(PyArrayObject *self, PyObject *args) +array_max(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; return PyArray_Max(self, axis); } @@ -222,13 +231,16 @@ array_max(PyArrayObject *self, PyObject *args) static char doc_ptp[] = "a.ptp(axis=None) a.max(axis)-a.min(axis)"; static PyObject * -array_ptp(PyArrayObject *self, PyObject *args) +array_ptp(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; - + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; + return PyArray_Ptp(self, axis); } @@ -236,17 +248,19 @@ array_ptp(PyArrayObject *self, PyObject *args) static char doc_min[] = "a.min(axis=None)"; static PyObject * -array_min(PyArrayObject *self, PyObject *args) +array_min(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; return PyArray_Min(self, axis); } - static char doc_swapaxes[] = "a.swapaxes(axis1, axis2) returns new view with axes swapped."; static PyObject * @@ -590,13 +604,13 @@ array_getarray(PyArrayObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "|O&", PyArray_DescrConverter, &newtype)) return NULL; - /* convert to PyArray_Type or PyBigArray_Type */ - if (!PyArray_CheckExact(self) || !PyBigArray_CheckExact(self)) { + /* convert to PyArray_Type */ + if (!PyArray_CheckExact(self)) { PyObject *new; PyTypeObject *subtype = &PyArray_Type; if (!PyType_IsSubtype(self->ob_type, &PyArray_Type)) { - subtype = &PyBigArray_Type; + subtype = &PyArray_Type; } Py_INCREF(PyArray_DESCR(self)); @@ -642,18 +656,29 @@ array_copy(PyArrayObject *self, PyObject *args) return PyArray_NewCopy(self, fortran); } -static char doc_resize[] = "self.resize(new_shape). "\ +static char doc_resize[] = "self.resize(new_shape, refcheck=True). "\ "Change size and shape of self inplace.\n"\ "\n Array must own its own memory and not be referenced by other " \ "arrays\n Returns None."; static PyObject * -array_resize(PyArrayObject *self, PyObject *args) +array_resize(PyArrayObject *self, PyObject *args, PyObject *kwds) { PyArray_Dims newshape; PyObject *ret; int n; - + int refcheck = 1; + + if (kwds != NULL) { + PyObject *ref; + ref = PyDict_GetItemString(kwds, "refcheck"); + if (ref) { + refcheck = PyInt_AsLong(ref); + if (refcheck==-1 && PyErr_Occurred()) { + return NULL; + } + } + } n = PyTuple_Size(args); if (n <= 1) { if (!PyArg_ParseTuple(args, "O&", PyArray_IntpConverter, @@ -668,7 +693,8 @@ array_resize(PyArrayObject *self, PyObject *args) return NULL; } } - ret = PyArray_Resize(self, &newshape); + + ret = PyArray_Resize(self, &newshape, refcheck); PyDimMem_FREE(newshape.ptr); if (ret == NULL) return NULL; Py_DECREF(ret); @@ -741,7 +767,7 @@ array_sort(PyArrayObject *self, PyObject *args, PyObject *kwds) static char doc_argsort[] = "a.argsort(axis=-1,kind='quicksort')\n"\ " Return the indexes into a that would sort it along the"\ - " given axis; kind can be 'quicksort', 'mergesort', or 'heapsort'"; + " given axis; kind can be 'quicksort', 'mergesort', or 'heapsort'"; static PyObject * array_argsort(PyArrayObject *self, PyObject *args, PyObject *kwds) @@ -1013,7 +1039,8 @@ array_setstate(PyArrayObject *self, PyObject *args) self->strides = self->dimensions + nd; memcpy(self->dimensions, dimensions, sizeof(intp)*nd); (void) _array_fill_strides(self->strides, dimensions, nd, - self->descr->elsize, fortran, + self->descr->elsize, + (fortran ? FORTRAN : CONTIGUOUS), &(self->flags)); } @@ -1275,12 +1302,15 @@ array_cumprod(PyArrayObject *self, PyObject *args, PyObject *kwds) static char doc_any[] = "a.any(axis=None)"; static PyObject * -array_any(PyArrayObject *self, PyObject *args) +array_any(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; return PyArray_Any(self, axis); } @@ -1288,13 +1318,16 @@ array_any(PyArrayObject *self, PyObject *args) static char doc_all[] = "a.all(axis=None)"; static PyObject * -array_all(PyArrayObject *self, PyObject *args) +array_all(PyArrayObject *self, PyObject *args, PyObject *kwds) { int axis=MAX_DIMS; + static char *kwlist[] = {"axis", NULL}; - if (!PyArg_ParseTuple(args, "|O&", PyArray_AxisConverter, - &axis)) return NULL; - + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + PyArray_AxisConverter, + &axis)) + return NULL; + return PyArray_All(self, axis); } @@ -1348,7 +1381,7 @@ array_compress(PyArrayObject *self, PyObject *args, PyObject *kwds) return _ARET(PyArray_Compress(self, condition, axis)); } -static char doc_nonzero[] = "a.nonzero() return a tuple of indices referencing"\ +static char doc_nonzero[] = "a.nonzero() return a tuple of indices referencing "\ "the elements of a that are nonzero."; static PyObject * @@ -1360,7 +1393,7 @@ array_nonzero(PyArrayObject *self, PyObject *args) } -static char doc_trace[] = "a.trace(offset=0, axis1=0, axis2=1, dtype=None) \n"\ +static char doc_trace[] = "a.trace(offset=0, axis1=0, axis2=1, dtype=None)\n"\ "return the sum along the offset diagonal of the arrays indicated\n" \ "axis1 and axis2."; @@ -1451,6 +1484,20 @@ array_ravel(PyArrayObject *self, PyObject *args) return PyArray_Ravel(self, fortran); } +static char doc_round[] = "a.round(decimals=0)"; + +static PyObject * +array_round(PyArrayObject *self, PyObject *args, PyObject *kwds) +{ + int decimals = 0; + static char *kwlist[] = {"decimals", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, + &decimals)) + return NULL; + + return _ARET(PyArray_Round(self, decimals)); +} static char doc_setflags[] = "a.setflags(write=None, align=None, uic=None)"; @@ -1549,7 +1596,8 @@ static PyMethodDef array_methods[] = { {"setfield", (PyCFunction)array_setfield, METH_VARARGS | METH_KEYWORDS, doc_setfield}, {"copy", (PyCFunction)array_copy, 1, doc_copy}, - {"resize", (PyCFunction)array_resize, 1, doc_resize}, + {"resize", (PyCFunction)array_resize, + METH_VARARGS | METH_KEYWORDS, doc_resize}, /* for subtypes */ {"__array__", (PyCFunction)array_getarray, 1, doc_array_getarray}, @@ -1590,9 +1638,9 @@ static PyMethodDef array_methods[] = { {"searchsorted", (PyCFunction)array_searchsorted, METH_VARARGS, doc_searchsorted}, {"argmax", (PyCFunction)array_argmax, - METH_VARARGS, doc_argmax}, + METH_VARARGS|METH_KEYWORDS, doc_argmax}, {"argmin", (PyCFunction)array_argmin, - METH_VARARGS, doc_argmin}, + METH_VARARGS|METH_KEYWORDS, doc_argmin}, {"reshape", (PyCFunction)array_reshape, METH_VARARGS, doc_reshape}, {"squeeze", (PyCFunction)array_squeeze, @@ -1602,11 +1650,11 @@ static PyMethodDef array_methods[] = { {"swapaxes", (PyCFunction)array_swapaxes, METH_VARARGS, doc_swapaxes}, {"max", (PyCFunction)array_max, - METH_VARARGS, doc_max}, + METH_VARARGS|METH_KEYWORDS, doc_max}, {"min", (PyCFunction)array_min, - METH_VARARGS, doc_min}, + METH_VARARGS|METH_KEYWORDS, doc_min}, {"ptp", (PyCFunction)array_ptp, - METH_VARARGS, doc_ptp}, + METH_VARARGS|METH_KEYWORDS, doc_ptp}, {"mean", (PyCFunction)array_mean, METH_VARARGS|METH_KEYWORDS, doc_mean}, {"trace", (PyCFunction)array_trace, @@ -1634,15 +1682,17 @@ static PyMethodDef array_methods[] = { {"cumprod", (PyCFunction)array_cumprod, METH_VARARGS|METH_KEYWORDS, doc_cumprod}, {"all", (PyCFunction)array_all, - METH_VARARGS, doc_all}, + METH_VARARGS|METH_KEYWORDS, doc_all}, {"any", (PyCFunction)array_any, - METH_VARARGS, doc_any}, + METH_VARARGS|METH_KEYWORDS, doc_any}, {"compress", (PyCFunction)array_compress, METH_VARARGS|METH_KEYWORDS, doc_compress}, {"flatten", (PyCFunction)array_flatten, METH_VARARGS, doc_flatten}, {"ravel", (PyCFunction)array_ravel, METH_VARARGS, doc_ravel}, + {"round", (PyCFunction)array_round, + METH_VARARGS|METH_KEYWORDS, doc_round}, {"setflags", (PyCFunction)array_setflags, METH_VARARGS|METH_KEYWORDS, doc_setflags}, {"newbyteorder", (PyCFunction)array_newbyteorder, diff --git a/numpy/core/src/arrayobject.c b/numpy/core/src/arrayobject.c index 2e2f6021b..8ef1758e1 100644 --- a/numpy/core/src/arrayobject.c +++ b/numpy/core/src/arrayobject.c @@ -32,8 +32,6 @@ PyArray_GetPriority(PyObject *obj, double default_) if (PyArray_CheckExact(obj)) return priority; - if (PyBigArray_CheckExact(obj)) - return PyArray_BIG_PRIORITY; ret = PyObject_GetAttrString(obj, "__array_priority__"); if (ret != NULL) priority = PyFloat_AsDouble(ret); @@ -1995,13 +1993,20 @@ array_subscript(PyArrayObject *self, PyObject *op) return NULL; } if (self->nd == 0) { - if (op == Py_Ellipsis) - return PyArray_ToScalar(self->data, self); + if (op == Py_Ellipsis) { + /* XXX: This leads to a small inconsistency + XXX: with the nd>0 case where (x[...] is x) + XXX: is false for nd>0 case. */ + Py_INCREF(self); + return (PyObject *)self; + } if (op == Py_None) return add_new_axes_0d(self, 1); if (PyTuple_Check(op)) { - if (0 == PyTuple_GET_SIZE(op)) - return PyArray_ToScalar(self->data, self); + if (0 == PyTuple_GET_SIZE(op)) { + Py_INCREF(self); + return (PyObject *)self; + } if ((nd = count_new_axes_0d(op)) == -1) return NULL; return add_new_axes_0d(self, nd); @@ -2211,7 +2216,43 @@ array_ass_sub(PyArrayObject *self, PyObject *index, PyObject *op) static PyObject * array_subscript_nice(PyArrayObject *self, PyObject *op) { - return PyArray_Return((PyArrayObject *)array_subscript(self, op)); + /* The following is just a copy of PyArray_Return with an + additional logic in the nd == 0 case. More efficient + implementation may be possible by refactoring + array_subscript */ + + PyArrayObject *mp = (PyArrayObject *)array_subscript(self, op); + + if (mp == NULL) return NULL; + + if (PyErr_Occurred()) { + Py_XDECREF(mp); + return NULL; + } + + if (!PyArray_Check(mp)) return (PyObject *)mp; + + if (mp->nd == 0) { + Bool noellipses = TRUE; + if (op == Py_Ellipsis) + noellipses = FALSE; + else if (PySequence_Check(op)) { + int n, i; + n = PySequence_Size(op); + for (i = 0; i < n; ++i) + if (PySequence_GetItem(op, i) == Py_Ellipsis) { + noellipses = FALSE; + break; + } + } + if (noellipses) { + PyObject *ret; + ret = PyArray_ToScalar(mp->data, mp); + Py_DECREF(mp); + return ret; + } + } + return (PyObject *)mp; } @@ -2337,14 +2378,11 @@ typedef struct { *floor, *ceil, *maximum, - *minimum; - + *minimum, + *rint; } NumericOps; -static NumericOps n_ops = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +static NumericOps n_ops; /* NB: static objects inlitialized to zero */ /* Dictionary can contain any of the numeric operations, by name. Those not present will not be changed @@ -2397,6 +2435,7 @@ PyArray_SetNumericOps(PyObject *dict) SET(ceil); SET(maximum); SET(minimum); + SET(rint); return 0; } @@ -2445,6 +2484,7 @@ PyArray_GetNumericOps(void) GET(ceil); GET(maximum); GET(minimum); + GET(rint); return dict; fail: @@ -3099,8 +3139,8 @@ array_slice(PyArrayObject *self, int ilow, int ihigh) self->nd, self->dimensions, self->strides, data, self->flags, (PyObject *)self); - self->dimensions[0] = l; + if (r == NULL) return NULL; r->base = (PyObject *)self; Py_INCREF(self); PyArray_UpdateFlags(r, UPDATE_ALL_FLAGS); @@ -3314,6 +3354,7 @@ static PyObject * array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) { PyObject *array_other, *result; + int typenum; switch (cmp_op) { @@ -3330,13 +3371,17 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) } /* Try to convert other to an array */ if (!PyArray_Check(other)) { + typenum = self->descr->type_num; + if (typenum != PyArray_OBJECT) { + typenum = PyArray_NOTYPE; + } array_other = PyArray_FromObject(other, - self->descr->type_num, 0, 0); - /* If not successful, then return the integer - object 0. This fixes code that used to + typenum, 0, 0); + /* If not successful, then return False + This fixes code that used to allow equality comparisons between arrays and other objects which would give a result - of 0 + of False */ if ((array_other == NULL) || \ (array_other == Py_None)) { @@ -3371,8 +3416,12 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) } /* Try to convert other to an array */ if (!PyArray_Check(other)) { + typenum = self->descr->type_num; + if (typenum != PyArray_OBJECT) { + typenum = PyArray_NOTYPE; + } array_other = PyArray_FromObject(other, - self->descr->type_num, 0, 0); + typenum, 0, 0); /* If not successful, then objects cannot be compared and cannot be equal, therefore, return True; @@ -3649,49 +3698,40 @@ PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) } /* This routine checks to see if newstrides (of length nd) will not - walk outside of the memory implied by a single segment array of the provided - dimensions and element size. If numbytes is 0 it will be calculated from - the provided shape and element size. - - For axes with a positive stride this function checks for a walk - beyond the right end of the buffer, for axes with a negative stride, - it checks for a walk beyond the left end of the buffer. Zero strides - are disallowed. + ever be able to walk outside of the memory implied numbytes and offset. + + The available memory is assumed to start at -offset and proceed + to numbytes-offset. The strides are checked to ensure + that accessing memory using striding will not try to reach beyond + this memory for any of the axes. + + If numbytes is 0 it will be calculated using the dimensions and + element-size. + + This function checks for walking beyond the beginning and right-end + of the buffer and therefore works for any integer stride (positive + or negative). */ + /*OBJECT_API*/ static Bool PyArray_CheckStrides(int elsize, int nd, intp numbytes, intp offset, intp *dims, intp *newstrides) { int i; + intp byte_begin; + intp begin; + intp end; if (numbytes == 0) numbytes = PyArray_MultiplyList(dims, nd) * elsize; + begin = -offset; + end = numbytes - offset - elsize; for (i=0; i<nd; i++) { - intp stride = newstrides[i]; - if (stride > 0) { - /* The last stride does not need to be fully inside - the buffer, only its first elsize bytes */ - if (offset + stride*(dims[i]-1)+elsize > numbytes) { - return FALSE; - } - } - else if (stride < 0) { - if (offset + stride*dims[i] < 0) { - return FALSE; - } - } else { - /* XXX: Zero strides may be useful, but currently - XXX: allowing them would lead to strange results, - XXX: for example : - XXX: >>> x = arange(5) - XXX: >>> x.strides = 0 - XXX: >>> x += 1 - XXX: >>> x - XXX: array([5, 5, 5, 5, 5]) */ + byte_begin = newstrides[i]*(dims[i]-1); + if ((byte_begin < begin) || (byte_begin > end)) return FALSE; - } } return TRUE; @@ -3911,7 +3951,7 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd, self->nd = nd; self->dimensions = NULL; self->data = NULL; - if (data == NULL) { /* strides is NULL too */ + if (data == NULL) { self->flags = DEFAULT_FLAGS; if (flags) { self->flags |= FORTRAN; @@ -3938,14 +3978,9 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd, sd = _array_fill_strides(self->strides, dims, nd, sd, flags, &(self->flags)); } - else { - if (data == NULL) { - PyErr_SetString(PyExc_ValueError, - "if 'strides' is given in " \ - "array creation, data must " \ - "be given too"); - goto fail; - } + else { /* we allow strides even when we create + the memory, but be careful with this... + */ memcpy(self->strides, strides, sizeof(intp)*nd); } } @@ -3988,22 +4023,23 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd, /* call the __array_finalize__ method if a subtype and some object passed in */ - if ((obj != NULL) && (subtype != &PyArray_Type) && - (subtype != &PyBigArray_Type)) { + if ((subtype != &PyArray_Type)) { PyObject *res, *func, *args; static PyObject *str=NULL; if (str == NULL) { str = PyString_InternFromString("__array_finalize__"); } - if (!(self->flags & OWNDATA)) { /* did not allocate own data */ - /* update flags before calling back into - Python */ + if (strides != NULL) { /* did not allocate own data + or funny strides */ + /* update flags before calling back into + Python */ PyArray_UpdateFlags(self, UPDATE_ALL_FLAGS); } func = PyObject_GetAttr((PyObject *)self, str); if (func) { args = PyTuple_New(1); + if (obj == NULL) obj=Py_None; Py_INCREF(obj); PyTuple_SET_ITEM(args, 0, obj); res = PyObject_Call(func, args, NULL); @@ -4026,9 +4062,13 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd, /*OBJECT_API Resize (reallocate data). Only works if nothing else is referencing this array and it is contiguous. + If refcheck is 0, then the reference count is not checked + and assumed to be 1. + You still must own this data and have no weak-references and no base + object. */ static PyObject * -PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape) +PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape, int refcheck) { intp oldsize, newsize; int new_nd=newshape->len, k, n, elsize; @@ -4039,9 +4079,9 @@ PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape) intp *dimptr; char *new_data; - if (!PyArray_ISCONTIGUOUS(self)) { + if (!PyArray_ISONESEGMENT(self)) { PyErr_SetString(PyExc_ValueError, - "resize only works on contiguous arrays"); + "resize only works on single-segment arrays"); return NULL; } @@ -4056,7 +4096,8 @@ PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape) return NULL; } - refcnt = REFCOUNT(self); + if (refcheck) refcnt = REFCOUNT(self); + else refcnt = 1; if ((refcnt > 2) || (self->base != NULL) || \ (self->weakreflist != NULL)) { PyErr_SetString(PyExc_ValueError, @@ -4117,7 +4158,7 @@ PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape) /* make new_strides variable */ sd = (intp) self->descr->elsize; sd = _array_fill_strides(new_strides, new_dimensions, new_nd, sd, - 0, &(self->flags)); + self->flags, &(self->flags)); memmove(self->dimensions, new_dimensions, new_nd*sizeof(intp)); @@ -4173,9 +4214,17 @@ PyArray_FillWithScalar(PyArrayObject *arr, PyObject *obj) copyswap = arr->descr->f->copyswap; if (PyArray_ISONESEGMENT(arr)) { char *toptr=PyArray_DATA(arr); - while (size--) { - copyswap(toptr, fromptr, swap, itemsize); - toptr += itemsize; + PyArray_FillWithScalarFunc* fillwithscalar = + arr->descr->f->fillwithscalar; + if (fillwithscalar && PyArray_ISALIGNED(arr)) { + copyswap(fromptr, NULL, swap, itemsize); + fillwithscalar(toptr, size, fromptr, arr); + } + else { + while (size--) { + copyswap(toptr, fromptr, swap, itemsize); + toptr += itemsize; + } } } else { @@ -4242,14 +4291,44 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) type_num = descr->type_num; itemsize = descr->elsize; - if (dims.ptr == NULL) { - PyErr_SetString(PyExc_ValueError, "need to give a "\ - "valid shape as the first argument"); - goto fail; - } + if (itemsize == 0) { + PyErr_SetString(PyExc_ValueError, + "data-type with unspecified variable length"); + goto fail; + } + + if (strides.ptr != NULL) { + intp nb, off; + if (strides.len != dims.len) { + PyErr_SetString(PyExc_ValueError, + "strides, if given, must be " \ + "the same length as shape"); + goto fail; + } + if (buffer.ptr == NULL) { + nb = 0; + off = 0; + } + else { + nb = buffer.len; + off = offset; + } + + + if (!PyArray_CheckStrides(itemsize, dims.len, + nb, off, + dims.ptr, strides.ptr)) { + PyErr_SetString(PyExc_ValueError, + "strides is incompatible " \ + "with shape of requested " \ + "array and size of buffer"); + goto fail; + } + } + if (buffer.ptr == NULL) { - ret = (PyArrayObject *)\ + ret = (PyArrayObject *) \ PyArray_NewFromDescr(subtype, descr, (int)dims.len, dims.ptr, @@ -4261,32 +4340,16 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) } else { /* buffer given -- use it */ if (dims.len == 1 && dims.ptr[0] == -1) { - dims.ptr[offset] = buffer.len / itemsize; + dims.ptr[0] = (buffer.len-offset) / itemsize; } - else if (buffer.len < itemsize* \ + else if ((strides.ptr == NULL) && \ + buffer.len < itemsize* \ PyArray_MultiplyList(dims.ptr, dims.len)) { PyErr_SetString(PyExc_TypeError, "buffer is too small for " \ "requested array"); goto fail; } - if (strides.ptr != NULL) { - if (strides.len != dims.len) { - PyErr_SetString(PyExc_ValueError, - "strides, if given, must be "\ - "the same length as shape"); - goto fail; - } - if (!PyArray_CheckStrides(itemsize, strides.len, - buffer.len, offset, - dims.ptr, strides.ptr)) { - PyErr_SetString(PyExc_ValueError, - "strides is incompatible "\ - "with shape of requested "\ - "array and size of buffer"); - goto fail; - } - } if (type_num == PyArray_OBJECT) { PyErr_SetString(PyExc_TypeError, "cannot construct "\ "an object array from buffer data"); @@ -4396,7 +4459,10 @@ array_strides_set(PyArrayObject *self, PyObject *obj) { PyArray_Dims newstrides = {NULL, 0}; PyArrayObject *new; - intp numbytes; + intp numbytes=0; + intp offset=0; + int buf_len; + char *buf; if (!PyArray_IntpConverter(obj, &newstrides) || \ newstrides.ptr == NULL) { @@ -4409,15 +4475,27 @@ array_strides_set(PyArrayObject *self, PyObject *obj) goto fail; } new = self; - while(new->base != NULL) { - if (PyArray_Check(new->base)) - new = (PyArrayObject *)new->base; + while(new->base && PyArray_Check(new->base)) { + new = (PyArrayObject *)(new->base); + } + /* Get the available memory through the buffer + interface on new->base or if that fails + from the current new */ + if (new->base && PyObject_AsReadBuffer(new->base, + (const void **)&buf, + &buf_len) >= 0) { + offset = self->data - buf; + numbytes = buf_len + offset; + } + else { + PyErr_Clear(); + numbytes = PyArray_MultiplyList(new->dimensions, + new->nd)*new->descr->elsize; + offset = self->data - new->data; } - numbytes = PyArray_MultiplyList(new->dimensions, - new->nd)*new->descr->elsize; if (!PyArray_CheckStrides(self->descr->elsize, self->nd, numbytes, - self->data - new->data, + offset, self->dimensions, newstrides.ptr)) { PyErr_SetString(PyExc_ValueError, "strides is not "\ "compatible with available memory"); @@ -4449,8 +4527,6 @@ array_priority_get(PyArrayObject *self) { if (PyArray_CheckExact(self)) return PyFloat_FromDouble(PyArray_PRIORITY); - else if (PyBigArray_CheckExact(self)) - return PyFloat_FromDouble(PyArray_BIG_PRIORITY); else return PyFloat_FromDouble(PyArray_SUBTYPE_PRIORITY); } @@ -5055,10 +5131,10 @@ static char Arraytype__doc__[] = " No __init__ method is needed because the array is fully \n" " initialized after the __new__ method."; -static PyTypeObject PyBigArray_Type = { +static PyTypeObject PyArray_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ - "numpy.bigndarray", /*tp_name*/ + "numpy.ndarray", /*tp_name*/ sizeof(PyArrayObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ @@ -5069,7 +5145,7 @@ static PyTypeObject PyBigArray_Type = { (cmpfunc)0, /*tp_compare*/ (reprfunc)array_repr, /*tp_repr*/ &array_as_number, /*tp_as_number*/ - NULL, /*tp_as_sequence*/ + &array_as_sequence, /*tp_as_sequence*/ &array_as_mapping, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ @@ -5077,7 +5153,7 @@ static PyTypeObject PyBigArray_Type = { (getattrofunc)0, /*tp_getattro*/ (setattrofunc)0, /*tp_setattro*/ - NULL, /*tp_as_buffer*/ + &array_as_buffer, /*tp_as_buffer*/ (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /*tp_flags*/ @@ -5116,20 +5192,6 @@ static PyTypeObject PyBigArray_Type = { 0 /* tp_weaklist */ }; -/* A standard array will subclass from the Big Array and - add the array_as_sequence table - and the array_as_buffer table - */ - -static PyTypeObject PyArray_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "numpy.ndarray", /*tp_name*/ - sizeof(PyArrayObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ -}; - - /* The rest of this code is to build the right kind of array from a python */ /* object. */ @@ -5474,12 +5536,16 @@ Array_FromScalar(PyObject *op, PyArray_Descr *typecode) if (itemsize == 0 && PyTypeNum_ISEXTENDED(type)) { itemsize = PyObject_Length(op); if (type == PyArray_UNICODE) itemsize *= 4; + + if (itemsize != typecode->elsize) { + PyArray_DESCR_REPLACE(typecode); + typecode->elsize = itemsize; + } } - ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, typecode, + ret = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type, typecode, 0, NULL, NULL, NULL, 0, NULL); - if (ret == NULL) return NULL; if (ret->nd > 0) { PyErr_SetString(PyExc_ValueError, @@ -5823,7 +5889,7 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) itemsize = newtype->elsize; /* Don't copy if sizes are compatible */ - if (PyArray_EquivTypes(oldtype, newtype)) { + if ((flags & ENSURECOPY) || PyArray_EquivTypes(oldtype, newtype)) { arrflags = arr->flags; copy = (flags & ENSURECOPY) || \ @@ -5840,8 +5906,7 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) PyErr_SetString(PyExc_ValueError, msg); return NULL; } - if ((flags & ENSUREARRAY) && \ - (subtype != &PyBigArray_Type)) { + if ((flags & ENSUREARRAY)) { subtype = &PyArray_Type; } ret = (PyArrayObject *) \ @@ -5864,8 +5929,7 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) /* If no copy then just increase the reference count and return the input */ else { - if ((flags & ENSUREARRAY) && \ - (subtype != &PyBigArray_Type)) { + if ((flags & ENSUREARRAY)) { Py_DECREF(newtype); Py_INCREF(arr->descr); ret = (PyArrayObject *) \ @@ -5900,8 +5964,7 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) PyErr_SetString(PyExc_ValueError, msg); return NULL; } - if ((flags & ENSUREARRAY) && \ - (subtype != &PyBigArray_Type)) { + if ((flags & ENSUREARRAY)) { subtype = &PyArray_Type; } ret = (PyArrayObject *)\ @@ -6242,22 +6305,28 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) array_meth = PyObject_GetAttrString(op, "__array__"); if (array_meth == NULL) {PyErr_Clear(); return Py_NotImplemented;} if (context == NULL) { - if (typecode == NULL) new = PyObject_CallFunction(array_meth, NULL); + if (typecode == NULL) new = PyObject_CallFunction(array_meth, + NULL); else new = PyObject_CallFunction(array_meth, "O", typecode); } else { if (typecode == NULL) { - new = PyObject_CallFunction(array_meth, "OO", Py_None, context); - if (new == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { + new = PyObject_CallFunction(array_meth, "OO", Py_None, + context); + if (new == NULL && \ + PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Clear(); new = PyObject_CallFunction(array_meth, ""); } } else { - new = PyObject_CallFunction(array_meth, "OO", typecode, context); - if (new == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { + new = PyObject_CallFunction(array_meth, "OO", + typecode, context); + if (new == NULL && \ + PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Clear(); - new = PyObject_CallFunction(array_meth, "O", typecode); + new = PyObject_CallFunction(array_meth, "O", + typecode); } } } @@ -6305,7 +6374,8 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth, PyObject *new; if (r == NULL) return NULL; if (newtype != NULL || flags != 0) { - new = PyArray_FromArray((PyArrayObject *)r, newtype, flags); + new = PyArray_FromArray((PyArrayObject *)r, newtype, + flags); Py_DECREF(r); r = new; } @@ -6456,7 +6526,7 @@ PyArray_CheckFromAny(PyObject *op, PyArray_Descr *descr, int min_depth, ENSUREARRAY) */ /* that special cases Arrays and PyArray_Scalars up front */ /* It *steals a reference* to the object */ -/* It also guarantees that the result is PyArray_Type or PyBigArray_Type */ +/* It also guarantees that the result is PyArray_Type */ /* Because it decrefs op if any conversion needs to take place so it can be used like PyArray_EnsureArray(some_function(...)) */ @@ -6469,7 +6539,7 @@ PyArray_EnsureArray(PyObject *op) if (op == NULL) return NULL; - if (PyArray_CheckExact(op) || PyBigArray_CheckExact(op)) return op; + if (PyArray_CheckExact(op)) return op; if (PyArray_IsScalar(op, Generic)) { new = PyArray_FromScalar(op, NULL); @@ -7577,8 +7647,19 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr) therefore we can extract the subspace with a simple getitem call which will use view semantics */ + /* But, be sure to do it with a true array. + */ + if (PyArray_CheckExact(arr)) { + sub = array_subscript(arr, mit->indexobj); + } + else { + Py_INCREF(arr); + obj = PyArray_EnsureArray((PyObject *)arr); + if (obj == NULL) goto fail; + sub = array_subscript((PyArrayObject *)obj, mit->indexobj); + Py_DECREF(obj); + } - sub = PyObject_GetItem((PyObject *)arr, mit->indexobj); if (sub == NULL) goto fail; mit->subspace = (PyArrayIterObject *)PyArray_IterNew(sub); Py_DECREF(sub); diff --git a/numpy/core/src/arraytypes.inc.src b/numpy/core/src/arraytypes.inc.src index 0fd105ab1..4bd24904a 100644 --- a/numpy/core/src/arraytypes.inc.src +++ b/numpy/core/src/arraytypes.inc.src @@ -1713,6 +1713,45 @@ static void /**end repeat**/ +/* this requires buffer to be filled with objects or NULL */ +static void +OBJECT_fillwithscalar(PyObject **buffer, intp length, PyObject **value, void *ignored) +{ + intp i; + PyObject *val = *value; + for (i=0; i<length; i++) { + Py_XDECREF(buffer[i]); + Py_INCREF(val); + buffer[i] = val; + } +} +/**begin repeat +#NAME=BOOL,BYTE,UBYTE# +#typ=Bool,byte,ubyte# +*/ +static void +@NAME@_fillwithscalar(@typ@ *buffer, intp length, @typ@ *value, void *ignored) +{ + memset(buffer, *value, length); +} +/**end repeat**/ + +/**begin repeat +#NAME=SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG,FLOAT,DOUBLE,LONGDOUBLE,CFLOAT,CDOUBLE,CLONGDOUBLE# +#typ=short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble,cfloat,cdouble,clongdouble# +*/ +static void +@NAME@_fillwithscalar(@typ@ *buffer, intp length, @typ@ *value, void *ignored) +{ + register intp i; + @typ@ val = *value; + for (i=0; i<length; ++i) { + buffer[i] = val; + } +} + +/**end repeat**/ + #define _ALIGN(type) offsetof(struct {char c; type v;},v) /**begin repeat @@ -1758,6 +1797,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { (PyArray_FromStrFunc*)@from@_fromstr, (PyArray_NonzeroFunc*)@from@_nonzero, (PyArray_FillFunc*)NULL, + (PyArray_FillWithScalarFunc*)NULL, { NULL, NULL, NULL, NULL }, @@ -1828,6 +1868,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { (PyArray_FromStrFunc*)@from@_fromstr, (PyArray_NonzeroFunc*)@from@_nonzero, (PyArray_FillFunc*)@from@_fill, + (PyArray_FillWithScalarFunc*)@from@_fillwithscalar, { NULL, NULL, NULL, NULL }, diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c index 481e5709a..3e3f71527 100644 --- a/numpy/core/src/multiarraymodule.c +++ b/numpy/core/src/multiarraymodule.c @@ -195,6 +195,87 @@ PyArray_Ravel(PyArrayObject *a, int fortran) return PyArray_Flatten(a, fortran); } +static double +power_of_ten(int n) +{ + static const double p10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8}; + double ret; + if (n < 9) + ret = p10[n]; + else { + ret = 1e9; + while (n-- > 9) + ret *= 10.; + } + return ret; +} + +/*MULTIARRAY_API + Round +*/ +static PyObject * +PyArray_Round(PyArrayObject *a, int decimals) +{ + /* do the most common case first */ + if (decimals == 0) { + if (PyArray_ISINTEGER(a)) { + Py_INCREF(a); + return (PyObject *)a; + } + return PyArray_GenericUnaryFunction((PyAO *)a, n_ops.rint); + } + if (decimals > 0) { + PyObject *f, *ret; + if (PyArray_ISINTEGER(a)) { + Py_INCREF(a); + return (PyObject *)a; + } + f = PyFloat_FromDouble(power_of_ten(decimals)); + if (f==NULL) return NULL; + ret = PyNumber_Multiply((PyObject *)a, f); + if (ret==NULL) {Py_DECREF(f); return NULL;} + if (PyArray_IsScalar(ret, Generic)) { + /* array scalars cannot be modified inplace */ + PyObject *tmp; + tmp = PyObject_CallFunction(n_ops.rint, "O", ret); + Py_DECREF(ret); + ret = PyObject_CallFunction(n_ops.divide, "OO", + tmp, f); + Py_DECREF(tmp); + } else { + PyObject_CallFunction(n_ops.rint, "OO", ret, ret); + PyObject_CallFunction(n_ops.divide, "OOO", ret, + f, ret); + } + Py_DECREF(f); + return ret; + } + else { + /* remaining case: decimals < 0 */ + PyObject *f, *ret; + f = PyFloat_FromDouble(power_of_ten(-decimals)); + if (f==NULL) return NULL; + ret = PyNumber_Divide((PyObject *)a, f); + if (ret==NULL) {Py_DECREF(f); return NULL;} + if (PyArray_IsScalar(ret, Generic)) { + /* array scalars cannot be modified inplace */ + PyObject *tmp; + tmp = PyObject_CallFunction(n_ops.rint, "O", ret); + Py_DECREF(ret); + ret = PyObject_CallFunction(n_ops.multiply, "OO", + tmp, f); + Py_DECREF(tmp); + } else { + PyObject_CallFunction(n_ops.rint, "OO", ret, ret); + PyObject_CallFunction(n_ops.multiply, "OOO", ret, + f, ret); + } + Py_DECREF(f); + return ret; + } +} + + /*MULTIARRAY_API Flatten */ @@ -1434,40 +1515,40 @@ _signbit_set(PyArrayObject *arr) /*OBJECT_API*/ -static char +static PyArray_SCALARKIND PyArray_ScalarKind(int typenum, PyArrayObject **arr) { if (PyTypeNum_ISSIGNED(typenum)) { - if (arr && _signbit_set(*arr)) return UFUNC_INTNEG_SCALAR; - else return UFUNC_INTPOS_SCALAR; + if (arr && _signbit_set(*arr)) return PyArray_INTNEG_SCALAR; + else return PyArray_INTPOS_SCALAR; } - if (PyTypeNum_ISFLOAT(typenum)) return UFUNC_FLOAT_SCALAR; - if (PyTypeNum_ISUNSIGNED(typenum)) return UFUNC_INTPOS_SCALAR; - if (PyTypeNum_ISCOMPLEX(typenum)) return UFUNC_COMPLEX_SCALAR; - if (PyTypeNum_ISBOOL(typenum)) return UFUNC_BOOL_SCALAR; + if (PyTypeNum_ISFLOAT(typenum)) return PyArray_FLOAT_SCALAR; + if (PyTypeNum_ISUNSIGNED(typenum)) return PyArray_INTPOS_SCALAR; + if (PyTypeNum_ISCOMPLEX(typenum)) return PyArray_COMPLEX_SCALAR; + if (PyTypeNum_ISBOOL(typenum)) return PyArray_BOOL_SCALAR; - return UFUNC_OBJECT_SCALAR; + return PyArray_OBJECT_SCALAR; } - /*OBJECT_API*/ static int -PyArray_CanCoerceScalar(char thistype, char neededtype, char scalar) +PyArray_CanCoerceScalar(char thistype, char neededtype, + PyArray_SCALARKIND scalar) { switch(scalar) { - case UFUNC_NOSCALAR: - case UFUNC_BOOL_SCALAR: - case UFUNC_OBJECT_SCALAR: + case PyArray_NOSCALAR: + case PyArray_BOOL_SCALAR: + case PyArray_OBJECT_SCALAR: return PyArray_CanCastSafely(thistype, neededtype); - case UFUNC_INTPOS_SCALAR: + case PyArray_INTPOS_SCALAR: return (neededtype >= PyArray_UBYTE); - case UFUNC_INTNEG_SCALAR: + case PyArray_INTNEG_SCALAR: return (neededtype >= PyArray_BYTE) && \ !(PyTypeNum_ISUNSIGNED(neededtype)); - case UFUNC_FLOAT_SCALAR: + case PyArray_FLOAT_SCALAR: return (neededtype >= PyArray_FLOAT); - case UFUNC_COMPLEX_SCALAR: + case PyArray_COMPLEX_SCALAR: return (neededtype >= PyArray_CFLOAT); } fprintf(stderr, "\n**Error** coerce fall through: %d %d %d\n\n", @@ -4246,7 +4327,7 @@ _array_fromobject(PyObject *ignored, PyObject *args, PyObject *kws) return NULL; /* fast exit if simple call */ - if ((PyArray_CheckExact(op) || PyBigArray_CheckExact(op))) { + if (PyArray_CheckExact(op)) { if (type==NULL) { if (!copy && fortran==PyArray_ISFORTRAN(op)) { Py_INCREF(op); @@ -5750,25 +5831,6 @@ DL_EXPORT(void) initmultiarray(void) { d = PyModule_GetDict(m); if (!d) goto err; - /* Create the module and add the functions */ - if (PyType_Ready(&PyBigArray_Type) < 0) - return; - - PyArray_Type.tp_base = &PyBigArray_Type; - - PyArray_Type.tp_as_mapping = &array_as_mapping; - /* Even though, this would be inherited, it needs to be set now - so that the __getitem__ will map to the as_mapping descriptor - */ - PyArray_Type.tp_as_number = &array_as_number; - /* For good measure */ - PyArray_Type.tp_as_sequence = &array_as_sequence; - PyArray_Type.tp_as_buffer = &array_as_buffer; - PyArray_Type.tp_flags = (Py_TPFLAGS_DEFAULT - | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_CHECKTYPES); - PyArray_Type.tp_doc = Arraytype__doc__; - if (PyType_Ready(&PyArray_Type) < 0) return; @@ -5800,8 +5862,6 @@ DL_EXPORT(void) initmultiarray(void) { s = PyString_FromString("3.0"); PyDict_SetItemString(d, "__version__", s); Py_DECREF(s); - Py_INCREF(&PyBigArray_Type); - PyDict_SetItemString(d, "bigndarray", (PyObject *)&PyBigArray_Type); Py_INCREF(&PyArray_Type); PyDict_SetItemString(d, "ndarray", (PyObject *)&PyArray_Type); Py_INCREF(&PyArrayIter_Type); diff --git a/numpy/core/src/scalartypes.inc.src b/numpy/core/src/scalartypes.inc.src index 9926cd83c..b984cf81a 100644 --- a/numpy/core/src/scalartypes.inc.src +++ b/numpy/core/src/scalartypes.inc.src @@ -459,14 +459,11 @@ gentype_multiply(PyObject *m1, PyObject *m2) Py_DECREF(arr); Py_DECREF(tup); return ret; - } - - /**begin repeat -#name=negative, absolute, invert, int, long, float, oct, hex# +#name=positive, negative, absolute, invert, int, long, float, oct, hex# */ static PyObject * @@ -639,7 +636,6 @@ static PyObject * /**end repeat**/ -static PyObject *gentype_copy(PyObject *, PyObject *); static PyNumberMethods gentype_as_number = { (binaryfunc)gentype_add, /*nb_add*/ @@ -650,7 +646,7 @@ static PyNumberMethods gentype_as_number = { (binaryfunc)gentype_divmod, /*nb_divmod*/ (ternaryfunc)gentype_power, /*nb_power*/ (unaryfunc)gentype_negative, - (unaryfunc)gentype_copy, /*nb_pos*/ + (unaryfunc)gentype_positive, /*nb_pos*/ (unaryfunc)gentype_absolute, /*(unaryfunc)gentype_abs,*/ (inquiry)gentype_nonzero_number, /*nb_nonzero*/ (unaryfunc)gentype_invert, /*nb_invert*/ @@ -1065,7 +1061,7 @@ gentype_wraparray(PyObject *scalar, PyObject *args) /**begin repeat -#name=tolist, item, tostring, astype, copy, resize, __deepcopy__, choose, searchsorted, argmax, argmin, reshape, view, swapaxes, max, min, ptp, conj, conjugate, nonzero, all, any, flatten, ravel, fill, transpose, newbyteorder# +#name=tolist, item, tostring, astype, copy, __deepcopy__, choose, searchsorted, reshape, view, swapaxes, conj, conjugate, nonzero, flatten, ravel, fill, transpose, newbyteorder# */ static PyObject * @@ -1124,7 +1120,7 @@ gentype_byteswap(PyObject *self, PyObject *args) /**begin repeat -#name=take, getfield, put, putmask, repeat, tofile, mean, trace, diagonal, clip, std, var, sum, cumsum, prod, cumprod, compress, sort, argsort# +#name=take, getfield, put, putmask, repeat, tofile, mean, trace, diagonal, clip, std, var, sum, cumsum, prod, cumprod, compress, sort, argsort, round, argmax, argmin, max, min, ptp, any, all, resize# */ static PyObject * @@ -1338,9 +1334,9 @@ static PyMethodDef gentype_methods[] = { {"searchsorted", (PyCFunction)gentype_searchsorted, METH_VARARGS, NULL}, {"argmax", (PyCFunction)gentype_argmax, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"argmin", (PyCFunction)gentype_argmin, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"reshape", (PyCFunction)gentype_reshape, METH_VARARGS, NULL}, {"squeeze", (PyCFunction)gentype_squeeze, @@ -1350,11 +1346,11 @@ static PyMethodDef gentype_methods[] = { {"swapaxes", (PyCFunction)gentype_swapaxes, METH_VARARGS, NULL}, {"max", (PyCFunction)gentype_max, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"min", (PyCFunction)gentype_min, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"ptp", (PyCFunction)gentype_ptp, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"mean", (PyCFunction)gentype_mean, METH_VARARGS|METH_KEYWORDS, NULL}, {"trace", (PyCFunction)gentype_trace, @@ -1382,15 +1378,17 @@ static PyMethodDef gentype_methods[] = { {"cumprod", (PyCFunction)gentype_cumprod, METH_VARARGS|METH_KEYWORDS, NULL}, {"all", (PyCFunction)gentype_all, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"any", (PyCFunction)gentype_any, - METH_VARARGS, NULL}, + METH_VARARGS|METH_KEYWORDS, NULL}, {"compress", (PyCFunction)gentype_compress, METH_VARARGS|METH_KEYWORDS, NULL}, {"flatten", (PyCFunction)gentype_flatten, METH_VARARGS, NULL}, {"ravel", (PyCFunction)gentype_ravel, METH_VARARGS, NULL}, + {"round", (PyCFunction)gentype_round, + METH_VARARGS|METH_KEYWORDS, NULL}, {"setflags", (PyCFunction)gentype_setflags, METH_VARARGS|METH_KEYWORDS, NULL}, {"newbyteorder", (PyCFunction)gentype_newbyteorder, @@ -2423,8 +2421,8 @@ PyArray_TypeObjectFromType(int type) descr = PyArray_DescrFromType(type); if (descr == NULL) return NULL; - Py_INCREF((PyObject *)descr->typeobj); obj = (PyObject *)descr->typeobj; + Py_INCREF(obj); Py_DECREF(descr); return obj; } diff --git a/numpy/core/src/ufuncobject.c b/numpy/core/src/ufuncobject.c index e09b1ffd5..3083bb461 100644 --- a/numpy/core/src/ufuncobject.c +++ b/numpy/core/src/ufuncobject.c @@ -610,7 +610,7 @@ _lowest_type(char intype) static int select_types(PyUFuncObject *self, int *arg_types, PyUFuncGenericFunction *function, void **data, - char *scalars) + PyArray_SCALARKIND *scalars) { int i=0, j; @@ -663,7 +663,7 @@ select_types(PyUFuncObject *self, int *arg_types, /* If the first argument is a scalar we need to place the start type as the lowest type in the class */ - if (scalars[0] != UFUNC_NOSCALAR) { + if (scalars[0] != PyArray_NOSCALAR) { start_type = _lowest_type(start_type); } @@ -850,7 +850,7 @@ construct_matrices(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps) { int nargs, i, maxsize; int arg_types[MAX_ARGS]; - char scalars[MAX_ARGS]; + PyArray_SCALARKIND scalars[MAX_ARGS]; PyUFuncObject *self=loop->ufunc; Bool allscalars=TRUE; PyTypeObject *subtype=&PyArray_Type; @@ -889,21 +889,17 @@ construct_matrices(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps) at this point */ if (mps[i]->nd > 0) { - scalars[i] = UFUNC_NOSCALAR; + scalars[i] = PyArray_NOSCALAR; allscalars=FALSE; } else scalars[i] = PyArray_ScalarKind(arg_types[i], &(mps[i])); - /* If any input is a big-array */ - if (!PyType_IsSubtype(mps[i]->ob_type, &PyArray_Type)) { - subtype = &PyBigArray_Type; - } } /* If everything is a scalar, then use normal coercion rules */ if (allscalars) { for (i=0; i<self->nin; i++) { - scalars[i] = UFUNC_NOSCALAR; + scalars[i] = PyArray_NOSCALAR; } } @@ -921,7 +917,6 @@ construct_matrices(PyUFuncLoopObject *loop, PyObject *args, PyArrayObject **mps) (loop->ufunc->nin==2) && (loop->ufunc->nout == 1)) { PyObject *_obj = PyTuple_GET_ITEM(args, 1); if (!PyArray_CheckExact(_obj) && \ - !PyBigArray_CheckExact(_obj) && \ PyObject_HasAttrString(_obj, "__array_priority__") && \ _has_reflected_op(_obj, loop->ufunc->name)) { loop->notimplemented = 1; @@ -1716,7 +1711,8 @@ construct_reduce(PyUFuncObject *self, PyArrayObject **arr, int axis, PyArrayObject *aar; intp loop_i[MAX_DIMS]; int arg_types[3] = {otype, otype, otype}; - char scalars[3] = {UFUNC_NOSCALAR, UFUNC_NOSCALAR, UFUNC_NOSCALAR}; + PyArray_SCALARKIND scalars[3] = {PyArray_NOSCALAR, PyArray_NOSCALAR, + PyArray_NOSCALAR}; int i, j; int nd = (*arr)->nd; /* Reduce type is the type requested of the input @@ -2535,7 +2531,7 @@ _find_array_wrap(PyObject *args, PyObject **output_wrap, int nin, int nout) nargs = PyTuple_GET_SIZE(args); for (i=0; i<nin; i++) { obj = PyTuple_GET_ITEM(args, i); - if (PyArray_CheckExact(obj) || PyBigArray_CheckExact(obj) || \ + if (PyArray_CheckExact(obj) || \ PyArray_IsAnyScalar(obj)) continue; wrap = PyObject_GetAttrString(obj, "__array_wrap__"); @@ -2546,6 +2542,7 @@ _find_array_wrap(PyObject *args, PyObject **output_wrap, int nin, int nout) ++np; } else { + Py_DECREF(wrap); wrap = NULL; } } @@ -2594,8 +2591,7 @@ _find_array_wrap(PyObject *args, PyObject **output_wrap, int nin, int nout) obj = PyTuple_GET_ITEM(args, j); if (obj == Py_None) continue; - if (PyArray_CheckExact(obj) || - PyBigArray_CheckExact(obj)) { + if (PyArray_CheckExact(obj)) { output_wrap[i] = Py_None; } else { @@ -2616,7 +2612,8 @@ _find_array_wrap(PyObject *args, PyObject **output_wrap, int nin, int nout) Py_XINCREF(output_wrap[i]); } } - + + Py_XDECREF(wrap); return; } @@ -2691,9 +2688,12 @@ ufunc_generic_call(PyUFuncObject *self, PyObject *args) } res = PyObject_CallFunction(wrap, "O(OOi)", mps[j], self, args, i); - if (res == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { + if (res == NULL && \ + PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Clear(); - res = PyObject_CallFunctionObjArgs(wrap, mps[j], NULL); + res = PyObject_CallFunctionObjArgs(wrap, + mps[j], + NULL); } Py_DECREF(wrap); if (res == NULL) goto fail; diff --git a/numpy/core/src/umathmodule.c.src b/numpy/core/src/umathmodule.c.src index 11d7c0c7b..0da04e53f 100644 --- a/numpy/core/src/umathmodule.c.src +++ b/numpy/core/src/umathmodule.c.src @@ -222,7 +222,7 @@ static longdouble atanhl(longdouble x) extern double hypot(double, double); #endif #else -double hypot(double x, double y) +static double hypot(double x, double y) { double yx; @@ -243,6 +243,30 @@ double hypot(double x, double y) #endif +#ifndef HAVE_RINT +static double +rint (double x) +{ + double y, r; + + y = floor(x); + r = x - y; + + if (r > 0.5) goto rndup; + + /* Round to nearest even */ + if (r==0.5) { + r = y - 2.0*floor(0.5*y); + if (r==1.0) { + rndup: + y+=1.0; + } + } + return y; +} +#endif + + /* Define isnan, isinf, isfinite, signbit if needed */ /* Use fpclassify if possible */ @@ -287,7 +311,6 @@ double hypot(double x, double y) #include "_signbit.c" #endif - /* Now defined the extended type macros */ #if !defined(isnan) @@ -357,10 +380,10 @@ double hypot(double x, double y) /**begin repeat -#kind=(sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,sqrt,log10,log,exp,asin,acos,atan)*2# -#typ=longdouble*16, float*16# -#c=l*16,f*16# -#TYPE=LONGDOUBLE*16, FLOAT*16# +#kind=(sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,sqrt,log10,log,exp,asin,acos,atan,rint)*2# +#typ=longdouble*17, float*17# +#c=l*17,f*17# +#TYPE=LONGDOUBLE*17, FLOAT*17# */ #ifndef HAVE_@TYPE@_FUNCS #ifdef @kind@@c@ @@ -659,19 +682,19 @@ nc_pow@c@(c@typ@ *a, c@typ@ *b, c@typ@ *r) } if (bi == 0 && (n=(intp)br) == br) { if (n > -100 && n < 100) { - c@typ@ p, a; + c@typ@ p, aa; intp mask = 1; if (n < 0) n = -n; - a = nc_1@c@; + aa = nc_1@c@; p.real = ar; p.imag = ai; while (1) { if (n & mask) - nc_prod@c@(&a,&p,&a); + nc_prod@c@(&aa,&p,&aa); mask <<= 1; if (n < mask || mask <= 0) break; nc_prod@c@(&p,&p,&p); } - r->real = a.real; r->imag = a.imag; + r->real = aa.real; r->imag = aa.imag; if (bi < 0) nc_quot@c@(&nc_1@c@, r, r); return; } diff --git a/numpy/core/tests/test_ma.py b/numpy/core/tests/test_ma.py index 03274237e..abee7d91f 100644 --- a/numpy/core/tests/test_ma.py +++ b/numpy/core/tests/test_ma.py @@ -2,6 +2,7 @@ import numpy import types, time from numpy.core.ma import * from numpy.testing import ScipyTestCase, ScipyTest +pi = numpy.pi def eq(v,w, msg=''): result = allclose(v,w) if not result: @@ -620,7 +621,12 @@ class test_ma(ScipyTestCase): self.failUnless(eq(a.sum(), a.data.sum())) self.failUnless(eq(a.take([1,2]), a.data.take([1,2]))) self.failUnless(eq(m.transpose(), m.data.transpose())) - + + def check_testArrayAttributes(self): + a = array([1,3,2]) + b = array([1,3,2], mask=[1,0,1]) + self.failUnlessEqual(a.ndim, 1) + def check_testAPI(self): self.failIf([m for m in dir(numpy.ndarray) if m not in dir(array) and not m.startswith('_')]) @@ -685,7 +691,12 @@ class test_ufuncs(ScipyTestCase): self.failUnless((amask.min(0) == [5,6,7,8]).all()) self.failUnless(amask.max(1)[0].mask) self.failUnless(amask.min(1)[0].mask) - + + def test_nonzero(self): + for t in "?bhilqpBHILQPfdgFDGO": + x = array([1,0,2,0], mask=[0,0,1,1]) + self.failUnless(eq(nonzero(x), [0])) + def eqmask(m1, m2): if m1 is nomask: return m2 is nomask diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 72672bf0d..f220a949a 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -70,10 +70,10 @@ class test_attributes(ScipyTestCase): strides=strides*x.itemsize) assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1])) self.failUnlessRaises(ValueError, make_array, 4, 4, -2) - self.failUnlessRaises(ValueError, make_array, 4, 3, -1) + self.failUnlessRaises(ValueError, make_array, 4, 2, -1) self.failUnlessRaises(ValueError, make_array, 8, 3, 1) - self.failUnlessRaises(ValueError, make_array, 8, 3, 0) - self.failUnlessRaises(ValueError, lambda: ndarray([1], strides=4)) + #self.failUnlessRaises(ValueError, make_array, 8, 3, 0) + #self.failUnlessRaises(ValueError, lambda: ndarray([1], strides=4)) def check_set_stridesattr(self): @@ -87,10 +87,21 @@ class test_attributes(ScipyTestCase): return r assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1])) self.failUnlessRaises(ValueError, make_array, 4, 4, -2) - self.failUnlessRaises(ValueError, make_array, 4, 3, -1) + self.failUnlessRaises(ValueError, make_array, 4, 2, -1) self.failUnlessRaises(ValueError, make_array, 8, 3, 1) - self.failUnlessRaises(ValueError, make_array, 8, 3, 0) - + #self.failUnlessRaises(ValueError, make_array, 8, 3, 0) + + def check_fill(self): + for t in "?bhilqpBHILQPfdgFDGO": + x = empty((3,2,1), t) + y = empty((3,2,1), t) + x.fill(1) + y[...] = 1 + assert_equal(x,y) + + x = array([(0,0.0), (1,1.0)], dtype='i4,f8') + x.fill(x[0]) + assert_equal(x['f1'][1], x['f1'][0]) class test_dtypedescr(ScipyTestCase): def check_construction(self): @@ -117,8 +128,8 @@ class test_zero_rank(ScipyTestCase): a,b = self.d self.failUnlessEqual(a[...], 0) self.failUnlessEqual(b[...], 'x') - self.failUnless(type(a[...]) is a.dtype.type) - self.failUnless(type(b[...]) is str) + self.failUnless(a[...] is a) + self.failUnless(b[...] is b) def check_empty_subscript(self): a,b = self.d @@ -173,6 +184,14 @@ class test_zero_rank(ScipyTestCase): self.failUnlessRaises(IndexError, subscript, a, (newaxis, 0)) self.failUnlessRaises(IndexError, subscript, a, (newaxis,)*50) + def check_constructor(self): + x = ndarray(()) + x[()] = 5 + self.failUnlessEqual(x[()], 5) + y = ndarray((),buffer=x) + y[()] = 6 + self.failUnlessEqual(x[()], 6) + class test_creation(ScipyTestCase): def check_from_attribute(self): class x(object): @@ -189,8 +208,33 @@ class test_bool(ScipyTestCase): b1 = bool_(True) self.failUnless(a1 is b1) self.failUnless(array([True])[0] is a1) - self.failUnless(array(True)[...] is a1) + self.failUnless(array(True)[()] is a1) + + +class test_methods(ScipyTestCase): + def check_test_round(self): + assert_equal(array([1.2,1.5]).round(), [1,2]) + assert_equal(array(1.5).round(), 2) + assert_equal(array([12.2,15.5]).round(-1), [10,20]) + assert_equal(array([12.15,15.51]).round(1), [12.2,15.5]) + +class test_subscripting(ScipyTestCase): + def check_test_zero_rank(self): + x = array([1,2,3]) + self.failUnless(isinstance(x[0], int)) + self.failUnless(type(x[0, ...]) is ndarray) + +class test_pickling(ScipyTestCase): + def setUp(self): + self.carray = array([[2,9],[7,0],[3,8]]) + self.tarray = transpose(self.carray) + + def check_both(self): + import pickle + assert_equal(self.carray, pickle.loads(self.carray.dumps())) + assert_equal(self.tarray, pickle.loads(self.tarray.dumps())) + # Import tests from unicode set_local_path() from test_unicode import * diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index a29a5ecca..204c88dab 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -23,6 +23,8 @@ class test_power(ScipyTestCase): assert_almost_equal(x**(-1), [1/(1+2j), 1/(2+3j), 1/(3+4j)]) assert_almost_equal(x**(0.5), [ncu.sqrt(1+2j), ncu.sqrt(2+3j), ncu.sqrt(3+4j)]) + assert_almost_equal(x**14, [-76443+16124j, 23161315+58317492j, + 5583548873 + 2465133864j]) class test_log1p(ScipyTestCase): def check_log1p(self): diff --git a/numpy/dft/__init__.py b/numpy/dft/__init__.py index 236aefdcb..817c99bc8 100644 --- a/numpy/dft/__init__.py +++ b/numpy/dft/__init__.py @@ -4,5 +4,7 @@ from info import __doc__ from fftpack import * from helper import * -from numpy.testing import ScipyTest -test = ScipyTest().test +def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) + diff --git a/numpy/distutils/__init__.py b/numpy/distutils/__init__.py index 3094541c1..3af26ac41 100644 --- a/numpy/distutils/__init__.py +++ b/numpy/distutils/__init__.py @@ -14,5 +14,6 @@ except ImportError: _INSTALLED = False if _INSTALLED: - from numpy.testing import ScipyTest - test = ScipyTest().test + def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) diff --git a/numpy/distutils/ccompiler.py b/numpy/distutils/ccompiler.py index efd458897..3e5d25dce 100644 --- a/numpy/distutils/ccompiler.py +++ b/numpy/distutils/ccompiler.py @@ -13,6 +13,14 @@ from exec_command import exec_command from misc_util import cyg2win32, is_sequence, mingw32 from distutils.spawn import _nt_quote_args +# hack to set compiler optimizing options. Needs to integrated with something. +import distutils.sysconfig +_old_init_posix = distutils.sysconfig._init_posix +def _new_init_posix(): + _old_init_posix() + distutils.sysconfig._config_vars['OPT'] = '-Wall -g -O2' +#distutils.sysconfig._init_posix = _new_init_posix + # Using customized CCompiler.spawn. def CCompiler_spawn(self, cmd, display=None): if display is None: diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index 0de24cc94..c32b2f23c 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -293,7 +293,7 @@ def is_local_src_dir(directory): def general_source_files(top_path): pruned_directories = {'CVS':1, '.svn':1, 'build':1} - prune_file_pat = re.compile(r'(?:[~#]|\.py[co]|\.o)$') + prune_file_pat = re.compile(r'(?:^\..*|[~#]|\.py[co]|\.o)$') for dirpath, dirnames, filenames in os.walk(top_path, topdown=True): pruned = [ d for d in dirnames if d not in pruned_directories ] dirnames[:] = pruned diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py index 4f5963dff..e4aeeffe2 100755 --- a/numpy/f2py/f2py2e.py +++ b/numpy/f2py/f2py2e.py @@ -162,7 +162,7 @@ Extra options (only effective with -c): Version: %s numpy Version: %s Requires: Python 2.3 or higher. -License: LGPL (see http://www.fsf.org) +License: NumPy license (see LICENSE.txt in the NumPy source code) Copyright 1999 - 2005 Pearu Peterson all rights reserved. http://cens.ioc.ee/projects/f2py2e/"""%(f2py_version, numpy_version) diff --git a/numpy/lib/UserArray.py b/numpy/lib/UserArray.py new file mode 100644 index 000000000..26b4b6578 --- /dev/null +++ b/numpy/lib/UserArray.py @@ -0,0 +1,217 @@ +# Standard container-class for easy backward compatibility +# with Numeric. +# Try to inherit from the ndarray instead of using this +# class as this is not complete. + +from numpy.core import * +import string + +class UserArray(object): + def __init__(self, data, dtype=None, copy=True): + self.array = array(data, dtype, copy) + + def __repr__(self): + if len(self.shape) > 0: + return self.__class__.__name__+repr(self.array)[len("array"):] + else: + return self.__class__.__name__+"("+repr(self.array)+")" + + def __array__(self,t=None): + if t: return self.array.astype(t) + return self.array + + def __float__(self): + return float(self.array) + + # Array as sequence + def __len__(self): return len(self.array) + + def __getitem__(self, index): + return self._rc(self.array[index]) + + def __getslice__(self, i, j): + return self._rc(self.array[i:j]) + + + def __setitem__(self, index, value): + self.array[index] = asarray(value,self.dtype) + def __setslice__(self, i, j, value): + self.array[i:j] = asarray(value,self.dtype) + + def __abs__(self): + return self._rc(absolute(self.array)) + def __neg__(self): + return self._rc(-self.array) + + def __add__(self, other): + return self._rc(self.array+asarray(other)) + __radd__ = __add__ + + def __iadd__(self, other): + add(self.array, other, self.array) + return self + + def __sub__(self, other): + return self._rc(self.array-asarray(other)) + def __rsub__(self, other): + return self._rc(asarray(other)-self.array) + def __isub__(self, other): + subtract(self.array, other, self.array) + return self + + def __mul__(self, other): + return self._rc(multiply(self.array,asarray(other))) + __rmul__ = __mul__ + def __imul__(self, other): + multiply(self.array, other, self.array) + return self + + def __div__(self, other): + return self._rc(divide(self.array,asarray(other))) + def __rdiv__(self, other): + return self._rc(divide(asarray(other),self.array)) + def __idiv__(self, other): + divide(self.array, other, self.array) + return self + + def __mod__(self, other): + return self._rc(remainder(self.array, other)) + def __rmod__(self, other): + return self._rc(remainder(other, self.array)) + def __imod__(self, other): + remainder(self.array, other, self.array) + return self + + def __divmod__(self, other): + return (self._rc(divide(self.array,other)), + self._rc(remainder(self.array, other))) + def __rdivmod__(self, other): + return (self._rc(divide(other, self.array)), + self._rc(remainder(other, self.array))) + + def __pow__(self,other): + return self._rc(power(self.array,asarray(other))) + def __rpow__(self,other): + return self._rc(power(asarray(other),self.array)) + def __ipow__(self,other): + power(self.array, other, self.array) + return self + + def __lshift__(self,other): + return self._rc(left_shift(self.array, other)) + def __rshift__(self,other): + return self._rc(right_shift(self.array, other)) + def __rlshift__(self,other): + return self._rc(left_shift(other, self.array)) + def __rrshift__(self,other): + return self._rc(right_shift(other, self.array)) + def __ilshift__(self,other): + left_shift(self.array, other, self.array) + return self + def __irshift__(self,other): + right_shift(self.array, other, self.array) + return self + + def __and__(self, other): + return self._rc(bitwise_and(self.array, other)) + def __rand__(self, other): + return self._rc(bitwise_and(other, self.array)) + def __iand__(self, other): + bitwise_and(self.array, other, self.array) + return self + + def __xor__(self, other): + return self._rc(bitwise_xor(self.array, other)) + def __rxor__(self, other): + return self._rc(bitwise_xor(other, self.array)) + def __ixor__(self, other): + bitwise_xor(self.array, other, self.array) + return self + + def __or__(self, other): + return self._rc(bitwise_or(self.array, other)) + def __ror__(self, other): + return self._rc(bitwise_or(other, self.array)) + def __ior__(self, other): + bitwise_or(self.array, other, self.array) + return self + + def __neg__(self): + return self._rc(-self.array) + def __pos__(self): + return self._rc(self.array) + def __abs__(self): + return self._rc(abs(self.array)) + def __invert__(self): + return self._rc(invert(self.array)) + + def _scalarfunc(a, func): + if len(a.shape) == 0: + return func(a[0]) + else: + raise TypeError, "only rank-0 arrays can be converted to Python scalars." + + def __complex__(self): return self._scalarfunc(complex) + def __float__(self): return self._scalarfunc(float) + def __int__(self): return self._scalarfunc(int) + def __long__(self): return self._scalarfunc(long) + def __hex__(self): return self._scalarfunc(hex) + def __oct__(self): return self._scalarfunc(oct) + + def __lt__(self,other): return self._rc(less(self.array,other)) + def __le__(self,other): return self._rc(less_equal(self.array,other)) + def __eq__(self,other): return self._rc(equal(self.array,other)) + def __ne__(self,other): return self._rc(not_equal(self.array,other)) + def __gt__(self,other): return self._rc(greater(self.array,other)) + def __ge__(self,other): return self._rc(greater_equal(self.array,other)) + + def copy(self): return self._rc(self.array.copy()) + + def tostring(self): return self.array.tostring() + + def byteswap(self): return self._rc(self.array.byteswap()) + + def astype(self, typecode): return self._rc(self.array.astype(typecode)) + + def _rc(self, a): + if len(shape(a)) == 0: return a + else: return self.__class__(a) + + def __array_wrap__(self, *args): + return self.__class__(args[0]) + + def __setattr__(self,attr,value): + if attr == 'array': + object.__setattr__(self, attr, value) + return + try: + self.array.__setattr__(attr, value) + except AttributeError: + object.__setattr__(self, attr, value) + + # Only called after other approaches fail. + def __getattr__(self,attr): + return self.array.__getattribute__(attr) + +############################################################# +# Test of class UserArray +############################################################# +if __name__ == '__main__': + import numpy + + temp=reshape(arange(10000),(100,100)) + + ua=UserArray(temp) + # new object created begin test + print dir(ua) + print shape(ua),ua.shape # I have changed Numeric.py + + ua_small=ua[:3,:5] + print ua_small + ua_small[0,0]=10 # this did not change ua[0,0], which is not normal behavior + print ua_small[0,0],ua[0,0] + print sin(ua_small)/3.*6.+sqrt(ua_small**2) + print less(ua_small,103),type(less(ua_small,103)) + print type(ua_small*reshape(arange(15),shape(ua_small))) + print reshape(ua_small,(5,3)) + print transpose(ua_small) diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py index 8b470d07f..a7de2e13f 100644 --- a/numpy/lib/__init__.py +++ b/numpy/lib/__init__.py @@ -30,5 +30,6 @@ __all__ += getlimits.__all__ __all__ += utils.__all__ __all__ += arraysetops.__all__ -from numpy.testing import ScipyTest -test = ScipyTest().test +def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index cee17b0aa..e44e37027 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -11,7 +11,6 @@ __all__ = ['logspace', 'linspace', ] import types -import math import numpy.core.numeric as _nx from numpy.core.numeric import ones, zeros, arange, concatenate, array, \ asarray, empty, empty_like, asanyarray @@ -210,7 +209,7 @@ def piecewise(x, condlist, funclist, *args, **kw): if n == n2-1: # compute the "otherwise" condition. totlist = condlist[0] for k in range(1, n): - totlist |= condlist + totlist |= condlist[k] condlist.append(~totlist) n += 1 if (n != n2): diff --git a/numpy/lib/getlimits.py b/numpy/lib/getlimits.py index 921baebe2..776e2550c 100644 --- a/numpy/lib/getlimits.py +++ b/numpy/lib/getlimits.py @@ -75,13 +75,15 @@ class finfo(object): else: raise ValueError,`dtype` - for word in ['tiny', 'precision', 'resolution','iexp', - 'maxexp','minexp','epsneg','negep', + for word in ['precision', 'iexp', + 'maxexp','minexp','negep', 'machep']: setattr(self,word,getattr(machar, word)) - self.max = machar.huge + for word in ['tiny','resolution','epsneg']: + setattr(self,word,getattr(machar, word).squeeze()) + self.max = machar.huge.squeeze() self.min = -self.max - self.eps = machar.epsilon + self.eps = machar.epsilon.squeeze() self.nexp = machar.iexp self.nmant = machar.it self.machar = machar diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py index 899fd5f47..15aae9949 100644 --- a/numpy/lib/index_tricks.py +++ b/numpy/lib/index_tricks.py @@ -223,24 +223,35 @@ class concatenator(object): def __len__(self): return 0 -r_=concatenator(0) -r_.__doc__ = """Translates slice objects to concatenation along the first axis. - - For example: - >>> r_[array([1,2,3]), 0, 0, array([4,5,6])] - array([1, 2, 3, 0, 0, 4, 5, 6]) -""" -c_=concatenator(-1) -c_.__doc__ = """Translates slice objects to concatenation along the second axis. - - For example: - >>> c_[array([[1],[2],[3]]), array([[4],[5],[6]])] - array([[1, 4], - [2, 5], - [3, 6]]) -""" -#row = concatenator(0,1) -#col = concatenator(-1,1) +# separate classes are used here instead of just making r_ = concatentor(0), +# etc. because otherwise we couldn't get the doc string to come out right +# in help(r_) + +class r_class(concatenator): + """Translates slice objects to concatenation along the first axis. + + For example: + >>> r_[array([1,2,3]), 0, 0, array([4,5,6])] + array([1, 2, 3, 0, 0, 4, 5, 6]) + """ + def __init__(self): + concatenator.__init__(self, 0) + +r_ = r_class() + +class c_class(concatenator): + """Translates slice objects to concatenation along the second axis. + + For example: + >>> c_[array([[1],[2],[3]]), array([[4],[5],[6]])] + array([[1, 4], + [2, 5], + [3, 6]]) + """ + def __init__(self): + concatenator.__init__(self, -1) + +c_ = c_class() class ndenumerate(object): diff --git a/numpy/lib/polynomial.py b/numpy/lib/polynomial.py index 5bd393cd5..c0c7c2229 100644 --- a/numpy/lib/polynomial.py +++ b/numpy/lib/polynomial.py @@ -493,6 +493,12 @@ class poly1d(object): other = poly1d(other) return polydiv(other, self) + def __eq__(self, other): + return (self.coeffs == other.coeffs).all() + + def __ne__(self, other): + return (self.coeffs != other.coeffs).any() + def __setattr__(self, key, val): raise ValueError, "Attributes cannot be changed this way." diff --git a/numpy/lib/shape_base.py b/numpy/lib/shape_base.py index 74d763821..cbcfa9e70 100644 --- a/numpy/lib/shape_base.py +++ b/numpy/lib/shape_base.py @@ -1,11 +1,11 @@ __all__ = ['atleast_1d','atleast_2d','atleast_3d','vstack','hstack', 'column_stack','dstack','array_split','split','hsplit', 'vsplit','dsplit','apply_over_axes','expand_dims', - 'apply_along_axis'] + 'apply_along_axis', 'repmat', 'kron'] import numpy.core.numeric as _nx from numpy.core.numeric import * -from numpy.core.oldnumeric import product +from numpy.core.oldnumeric import product, reshape def apply_along_axis(func1d,axis,arr,*args): """ Execute func1d(arr[i],*args) where func1d takes 1-D arrays @@ -525,3 +525,36 @@ def dsplit(ary,indices_or_sections): raise ValueError, 'vsplit only works on arrays of 3 or more dimensions' return split(ary,indices_or_sections,2) +# should figure out how to generalize this one. +def repmat(a, m, n): + """Repeat a 0-d to 2-d array mxn times + """ + a = asarray(a) + ndim = a.ndim + if ndim == 0: + origrows, origcols = (1,1) + elif ndim == 1: + origrows, origcols = (1, a.shape[0]) + else: + origrows, origcols = a.shape + rows = origrows * m + cols = origcols * n + c = a.reshape(1,a.size).repeat(m, 0).reshape(rows, origcols).repeat(n,0) + return c.reshape(rows, cols) + + +def kron(a,b): + """kronecker product of a and b + + Kronecker product of two matrices is block matrix + [[ a[ 0 ,0]*b, a[ 0 ,1]*b, ... , a[ 0 ,n-1]*b ], + [ ... ... ], + [ a[m-1,0]*b, a[m-1,1]*b, ... , a[m-1,n-1]*b ]] + """ + if not a.flags.contiguous: + a = reshape(a, a.shape) + if not b.flags.contiguous: + b = reshape(b, b.shape) + o = outerproduct(a,b) + o=o.reshape(a.shape + b.shape) + return concatenate(concatenate(o, axis=1), axis=1) diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py index 5b4574089..39a908268 100644 --- a/numpy/lib/twodim_base.py +++ b/numpy/lib/twodim_base.py @@ -12,7 +12,7 @@ def fliplr(m): """ returns an array m with the rows preserved and columns flipped in the left/right direction. Works on the first two dimensions of m. """ - m = asarray(m) + m = asanyarray(m) if m.ndim < 2: raise ValueError, "Input must be >= 2-d." return m[:, ::-1] @@ -21,17 +21,17 @@ def flipud(m): """ returns an array with the columns preserved and rows flipped in the up/down direction. Works on the first dimension of m. """ - m = asarray(m) + m = asanyarray(m) if m.ndim < 1: raise ValueError, "Input must be >= 1-d." - return m[::-1] + return m[::-1,...] def rot90(m, k=1): """ returns the array found by rotating m by k*90 degrees in the counterclockwise direction. Works on the first two dimensions of m. """ - m = asarray(m) + m = asanyarray(m) if m.ndim < 2: raise ValueError, "Input must >= 2-d." k = k % 4 @@ -92,7 +92,7 @@ def tril(m, k=0): """ returns the elements on and below the k-th diagonal of m. k=0 is the main diagonal, k > 0 is above and k < 0 is below the main diagonal. """ - m = asarray(m) + m = asanyarray(m) out = multiply(tri(m.shape[0], m.shape[1], k=k, dtype=m.dtype),m) return out @@ -100,11 +100,10 @@ def triu(m, k=0): """ returns the elements on and above the k-th diagonal of m. k=0 is the main diagonal, k > 0 is above and k < 0 is below the main diagonal. """ - m = asarray(m) + m = asanyarray(m) out = multiply((1-tri(m.shape[0], m.shape[1], k-1, m.dtype)),m) return out - # borrowed from John Hunter and matplotlib def vander(x, N=None): """ diff --git a/numpy/linalg/__init__.py b/numpy/linalg/__init__.py index 42df37663..287b3959e 100644 --- a/numpy/linalg/__init__.py +++ b/numpy/linalg/__init__.py @@ -3,5 +3,6 @@ from info import __doc__ from linalg import * -from numpy.testing import ScipyTest -test = ScipyTest().test +def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index abb65be18..58bc9fbff 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -1,6 +1,7 @@ -"""Lite version of numpy.linalg. + +"""Lite version of scipy.linalg. """ -# This module is a lite version of LinAlg.py module which contains +# This module is a lite version of the linalg.py module in SciPy which contains # high-level Python interface to the LAPACK library. The lite version # only accesses the following LAPACK functions: dgesv, zgesv, dgeev, # zgeev, dgesdd, zgesdd, dgelsd, zgelsd, dsyevd, zheevd, dgetrf, dpotrf. @@ -9,12 +10,12 @@ __all__ = ['LinAlgError', 'solve_linear_equations', 'solve', 'inverse', 'inv', 'cholesky_decomposition', 'cholesky', 'eigenvalues', 'eigvals', 'Heigenvalues', 'eigvalsh', 'generalized_inverse', 'pinv', 'determinant', 'det', 'singular_value_decomposition', 'svd', - 'eigenvectors', 'eig', 'Heigenvectors', 'eigh','lstsq', 'linear_least_squares' + 'eigenvectors', 'eig', 'Heigenvectors', 'eigh','lstsq', + 'linear_least_squares' ] -from numpy import * +from numpy.core import * import lapack_lite -import math # Error object class LinAlgError(Exception): @@ -27,6 +28,11 @@ _array_kind = {'i':0, 'l': 0, 'f': 0, 'd': 0, 'F': 1, 'D': 1} _array_precision = {'i': 1, 'l': 1, 'f': 0, 'd': 1, 'F': 0, 'D': 1} _array_type = [['f', 'd'], ['F', 'D']] +def _makearray(a): + new = asarray(a) + wrap = getattr(a, "__array_wrap__", new.__array_wrap__) + return new, wrap + def _commonType(*arrays): kind = 0 # precision = 0 @@ -227,11 +233,10 @@ def eig(a): v is a matrix of eigenvectors with vector v[:,i] corresponds to eigenvalue u[i]. Satisfies the equation dot(a, v[:,i]) = u[i]*v[:,i] """ - a = asarray(a) + a, wrap = _makearray(a) _assertRank2(a) _assertSquareness(a) a,t = _convertarray(a) # convert to float_ or complex_ type - wrap = a.__array_wrap__ real_t = 'd' n = a.shape[0] dummy = zeros((1,), t) @@ -281,12 +286,12 @@ eigenvalue u[i]. Satisfies the equation dot(a, v[:,i]) = u[i]*v[:,i] def eigh(a, UPLO='L'): + a, wrap = _makearray(a) _assertRank2(a) _assertSquareness(a) t =_commonType(a) real_t = _array_type[0][_array_precision[t]] a = _castCopyAndTranspose(t, a) - wrap = a.__array_wrap__ n = a.shape[0] liwork = 5*n+3 iwork = zeros((liwork,),'i') @@ -319,14 +324,13 @@ def eigh(a, UPLO='L'): # Singular value decomposition -def svd(a, full_matrices = 1): +def svd(a, full_matrices=1): + a, wrap = _makearray(a) _assertRank2(a) - n = a.shape[1] - m = a.shape[0] + m, n = a.shape t =_commonType(a) real_t = _array_type[0][_array_precision[t]] a = _fastCopyAndTranspose(t, a) - wrap = a.__array_wrap__ if full_matrices: nu = m nvt = n @@ -369,7 +373,7 @@ def svd(a, full_matrices = 1): # Generalized inverse def generalized_inverse(a, rcond = 1.e-10): - a = array(a, copy=0) + a, wrap = _makearray(a) if a.dtype.char in typecodes['Complex']: a = conjugate(a) u, s, vt = svd(a, 0) @@ -381,13 +385,13 @@ def generalized_inverse(a, rcond = 1.e-10): s[i] = 1./s[i] else: s[i] = 0.; - wrap = a.__array_wrap__ return wrap(dot(transpose(vt), multiply(s[:, NewAxis],transpose(u)))) # Determinant def determinant(a): + a = asarray(a) _assertRank2(a) _assertSquareness(a) t =_commonType(a) @@ -418,8 +422,9 @@ the number of rows, then residuals will be returned as an empty array otherwise resids = sum((b-dot(A,x)**2). Singular values less than s[0]*rcond are treated as zero. """ + import math a = asarray(a) - b = asarray(b) + b, wrap = _makearray(b) one_eq = len(b.shape) == 1 if one_eq: b = b[:, NewAxis] @@ -477,10 +482,10 @@ Singular values less than s[0]*rcond are treated as zero. x = transpose(bstar)[:n,:].copy() if (results['rank']==n) and (m>n): resids = sum((transpose(bstar)[n:,:])**2).copy() - return x,resids,results['rank'],s[:min(n,m)].copy() + return wrap(x),resids,results['rank'],s[:min(n,m)].copy() def singular_value_decomposition(A, full_matrices=0): - return svd(A, 0) + return svd(A, full_matrices) def eigenvectors(A): w, v = eig(A) diff --git a/numpy/random/__init__.py b/numpy/random/__init__.py index 8dc354e81..13d0e3a22 100644 --- a/numpy/random/__init__.py +++ b/numpy/random/__init__.py @@ -13,5 +13,6 @@ def __RandomState_ctor(): """ return RandomState() -from numpy.testing import ScipyTest -test = ScipyTest().test +def test(level=1, verbosity=1): + from numpy.testing import NumpyTest + return NumpyTest().test(level, verbosity) diff --git a/numpy/testing/info.py b/numpy/testing/info.py index 9b5caa074..80dc00ddf 100644 --- a/numpy/testing/info.py +++ b/numpy/testing/info.py @@ -27,4 +27,4 @@ Utility functions """ -global_symbols = ['ScipyTest'] +global_symbols = ['ScipyTest','NumpyTest'] diff --git a/numpy/testing/numpytest.py b/numpy/testing/numpytest.py index 127a5d3e2..4b43c428e 100644 --- a/numpy/testing/numpytest.py +++ b/numpy/testing/numpytest.py @@ -3,6 +3,7 @@ import os import re import sys import imp +import glob import types import unittest import traceback @@ -50,7 +51,7 @@ def set_package_path(level=1): if not os.path.isdir(d1): d1 = os.path.dirname(d) if DEBUG: - print 'Inserting %r to sys.path' % (d1) + print 'Inserting %r to sys.path for test_file %r' % (d1, testfile) sys.path.insert(0,d1) return @@ -156,7 +157,8 @@ class NumpyTestCase (unittest.TestCase): result.stream = save_stream def warn(self, message): - print>>sys.stderr,'Warning: %s' % (message) + from numpy.distutils.misc_util import yellow_text + print>>sys.stderr,yellow_text('Warning: %s' % (message)) sys.stderr.flush() def info(self, message): print>>sys.stdout, message @@ -224,10 +226,30 @@ class NumpyTest: """ _check_testcase_name = re.compile(r'test.*').match def check_testcase_name(self, name): - return self._check_testcase_name(name) is not None + """ Return True if name matches TestCase class. + """ + return not not self._check_testcase_name(name) - def get_testfile(self, short_module_name): - return 'test_' + short_module_name + '.py' + testfile_patterns = ['test_%(modulename)s.py'] + def get_testfile(self, module, verbosity = 0): + """ Return path to module test file. + """ + mstr = self._module_str + short_module_name = self._get_short_module_name(module) + d = os.path.split(module.__file__)[0] + test_dir = os.path.join(d,'tests') + local_test_dir = os.path.join(os.getcwd(),'tests') + if os.path.basename(os.path.dirname(local_test_dir)) \ + == os.path.basename(os.path.dirname(test_dir)): + test_dir = local_test_dir + for pat in self.testfile_patterns: + fn = os.path.join(test_dir, pat % {'modulename':short_module_name}) + if os.path.isfile(fn): + return fn + if verbosity>1: + self.warn('No test file found in %s for module %s' \ + % (test_dir, mstr(module))) + return def __init__(self, package=None): if package is None: @@ -276,29 +298,25 @@ class NumpyTest: names.append(n) return names - def _get_module_tests(self,module,level,verbosity): - mstr = self._module_str + def _get_short_module_name(self, module): d,f = os.path.split(module.__file__) - short_module_name = os.path.splitext(os.path.basename(f))[0] if short_module_name=='__init__': short_module_name = module.__name__.split('.')[-1] - short_module_name = self._rename_map.get(short_module_name,short_module_name) + return short_module_name + + def _get_module_tests(self,module,level,verbosity): + mstr = self._module_str + + short_module_name = self._get_short_module_name(module) if short_module_name is None: return [] - full_module_name = module.__name__+'.'+short_module_name - test_dir = os.path.join(d,'tests') - fn = self.get_testfile(short_module_name) - test_file = os.path.join(test_dir,fn) + test_file = self.get_testfile(module, verbosity) - local_test_dir = os.path.join(os.getcwd(),'tests') - local_test_file = os.path.join(local_test_dir, fn) - if os.path.basename(os.path.dirname(local_test_dir)) \ - == os.path.basename(os.path.dirname(test_dir)) \ - and os.path.isfile(local_test_file): - test_file = local_test_file + if test_file is None: + return [] if not os.path.isfile(test_file): if short_module_name[:5]=='info_' \ @@ -317,22 +335,34 @@ class NumpyTest: if test_file in self.test_files: return [] - + + parent_module_name = '.'.join(module.__name__.split('.')[:-1]) + test_module_name,ext = os.path.splitext(os.path.basename(test_file)) + test_dir_module = parent_module_name+'.tests' + test_module_name = test_dir_module+'.'+test_module_name + + if not sys.modules.has_key(test_dir_module): + sys.modules[test_dir_module] = imp.new_module(test_dir_module) + + old_sys_path = sys.path[:] try: f = open(test_file,'r') - test_module = imp.load_module(full_module_name, - f, test_file, ('.py', 'r', 1)) + test_module = imp.load_module(test_module_name, f, + test_file, ('.py', 'r', 1)) f.close() except: - self.warn(' !! FAILURE importing tests for %s' % mstr(module)) + sys.path[:] = old_sys_path + self.warn('FAILURE importing tests for %s' % (mstr(module))) output_exception(sys.stderr) return [] + sys.path[:] = old_sys_path self.test_files.append(test_file) return self._get_suite_list(test_module, level, module.__name__) - def _get_suite_list(self, test_module, level, module_name='__main__'): + def _get_suite_list(self, test_module, level, module_name='__main__', + verbosity=1): mstr = self._module_str suite_list = [] if hasattr(test_module,'test_suite'): @@ -347,13 +377,28 @@ class NumpyTest: suite = obj(mthname) if getattr(suite,'isrunnable',lambda mthname:1)(mthname): suite_list.append(suite) - self.info(' Found %s tests for %s' % (len(suite_list),module_name)) + if verbosity>=0: + self.info(' Found %s tests for %s' % (len(suite_list),module_name)) return suite_list def test(self,level=1,verbosity=1): """ Run Numpy module test suite with level and verbosity. + + level: + None --- do nothing, return None + < 0 --- scan for tests of level=abs(level), + don't run them, return TestSuite-list + > 0 --- scan for tests of level, run them, + return TestRunner + + verbosity: + >= 0 --- show information messages + > 1 --- show warnings on missing tests """ - if type(self.package) is type(''): + if level is None: # Do nothing. + return + + if isinstance(self.package, str): exec 'import %s as this_package' % (self.package) else: this_package = self.package @@ -374,14 +419,15 @@ class NumpyTest: self.test_files = [] suites = [] for module in modules: - suites.extend(self._get_module_tests(module, level, verbosity)) + suites.extend(self._get_module_tests(module, abs(level), verbosity)) - suites.extend(self._get_suite_list(sys.modules[package_name], level)) + suites.extend(self._get_suite_list(sys.modules[package_name], + abs(level), verbosity=verbosity)) all_tests = unittest.TestSuite(suites) - #if hasattr(sys,'getobjects'): - # runner = SciPyTextTestRunner(verbosity=verbosity) - #else: + if level<0: + return all_tests + runner = unittest.TextTestRunner(verbosity=verbosity) # Use the builtin displayhook. If the tests are being run # under IPython (for instance), any doctest test suites will @@ -420,7 +466,8 @@ class NumpyTest: return def warn(self, message): - print>>sys.stderr,'Warning: %s' % (message) + from numpy.distutils.misc_util import yellow_text + print>>sys.stderr,yellow_text('Warning: %s' % (message)) sys.stderr.flush() def info(self, message): print>>sys.stdout, message diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index 4ea19c270..fe3a3c093 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -4,8 +4,6 @@ Utility function to facilitate testing. import os import sys -import time -import math __all__ = ['assert_equal', 'assert_almost_equal','assert_approx_equal', 'assert_array_equal', 'assert_array_less', @@ -27,16 +25,19 @@ def rand(*args): if sys.platform[:5]=='linux': def jiffies(_proc_pid_stat = '/proc/%s/stat'%(os.getpid()), - _load_time=time.time()): + _load_time=[]): """ Return number of jiffies (1/100ths of a second) that this process has been scheduled in user mode. See man 5 proc. """ + import time + if not _load_time: + _load_time.append(time.time()) try: f=open(_proc_pid_stat,'r') l = f.readline().split(' ') f.close() return int(l[13]) except: - return int(100*(time.time()-_load_time)) + return int(100*(time.time()-_load_time[0])) def memusage(_proc_pid_stat = '/proc/%s/stat'%(os.getpid())): """ Return virtual memory size in bytes of the running python. @@ -52,10 +53,13 @@ else: # os.getpid is not in all platforms available. # Using time is safe but inaccurate, especially when process # was suspended or sleeping. - def jiffies(_load_time=time.time()): + def jiffies(_load_time=[]): """ Return number of jiffies (1/100ths of a second) that this process has been scheduled in user mode. [Emulation with time.time]. """ - return int(100*(time.time()-_load_time)) + import time + if not _load_time: + _load_time.append(time.time()) + return int(100*(time.time()-_load_time[0])) def memusage(): """ Return memory usage of running python. [Not implemented]""" return @@ -150,6 +154,7 @@ def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=1): Approximately equal is defined as the number of significant digits correct """ + import math msg = '\nItems are not equal to %d significant digits:\n' % significant msg += err_msg actual, desired = map(float, (actual, desired)) |