summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/setup.py7
-rw-r--r--numpy/core/src/multiarray/arrayobject.c28
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c16
-rw-r--r--numpy/core/src/multiarray/descriptor.c27
-rw-r--r--numpy/core/src/scalarmathmodule.c.src35
-rw-r--r--numpy/core/src/umath/loops.c.src6
-rw-r--r--numpy/core/tests/test_multiarray.py1
-rw-r--r--numpy/core/tests/test_regression.py18
-rw-r--r--numpy/distutils/command/config.py16
-rw-r--r--numpy/distutils/fcompiler/__init__.py4
-rw-r--r--numpy/distutils/fcompiler/pg.py23
-rw-r--r--numpy/f2py/capi_maps.py6
-rw-r--r--numpy/lib/index_tricks.py11
-rw-r--r--numpy/lib/npyio.py251
-rw-r--r--numpy/lib/tests/test_index_tricks.py15
-rw-r--r--numpy/linalg/linalg.py35
-rw-r--r--numpy/linalg/tests/test_linalg.py83
17 files changed, 423 insertions, 159 deletions
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index ad8d5cb3b..f71ec108a 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -215,10 +215,13 @@ def check_ieee_macros(config):
_macros = ["isnan", "isinf", "signbit", "isfinite"]
if sys.version_info[:2] >= (2, 6):
for f in _macros:
- already_declared = config.check_decl(fname2def("decl_%s" % f),
+ py_symbol = fname2def("decl_%s" % f)
+ already_declared = config.check_decl(py_symbol,
headers=["Python.h", "math.h"])
if already_declared:
- pub.append('NPY_%s' % fname2def("decl_%s" % f))
+ if config.check_macro_true(py_symbol,
+ headers=["Python.h", "math.h"]):
+ pub.append('NPY_%s' % fname2def("decl_%s" % f))
else:
macros.append(f)
else:
diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c
index ab1e824be..587e45d26 100644
--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -907,16 +907,15 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
array_other = PyArray_FromObject(other,
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 False.
+ * If not successful, indicate that the items cannot be compared
+ * this way.
*/
if ((array_other == NULL) ||
(array_other == Py_None)) {
Py_XDECREF(array_other);
PyErr_Clear();
- Py_INCREF(Py_False);
- return Py_False;
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
}
}
else {
@@ -952,14 +951,14 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
}
/*
* If the comparison results in NULL, then the
- * two array objects can not be compared together so
- * return zero
+ * two array objects can not be compared together;
+ * indicate that
*/
Py_DECREF(array_other);
if (result == NULL) {
PyErr_Clear();
- Py_INCREF(Py_False);
- return Py_False;
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
}
break;
case Py_NE:
@@ -976,14 +975,13 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
array_other = PyArray_FromObject(other, typenum, 0, 0);
/*
* If not successful, then objects cannot be
- * compared and cannot be equal, therefore,
- * return True;
+ * compared this way
*/
if ((array_other == NULL) || (array_other == Py_None)) {
Py_XDECREF(array_other);
PyErr_Clear();
- Py_INCREF(Py_True);
- return Py_True;
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
}
}
else {
@@ -1021,8 +1019,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
Py_DECREF(array_other);
if (result == NULL) {
PyErr_Clear();
- Py_INCREF(Py_True);
- return Py_True;
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
}
break;
case Py_GT:
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index 37b0e5e18..5cb62b82f 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -112,21 +112,25 @@ PyArray_GetCastFunc(PyArray_Descr *descr, int type_num)
PyTypeNum_ISNUMBER(type_num) &&
!PyTypeNum_ISBOOL(type_num)) {
PyObject *cls = NULL, *obj = NULL;
+ int ret;
obj = PyImport_ImportModule("numpy.core");
if (obj) {
cls = PyObject_GetAttrString(obj, "ComplexWarning");
Py_DECREF(obj);
}
#if PY_VERSION_HEX >= 0x02050000
- PyErr_WarnEx(cls,
- "Casting complex values to real discards the imaginary "
- "part", 0);
+ ret = PyErr_WarnEx(cls,
+ "Casting complex values to real discards the imaginary "
+ "part", 0);
#else
- PyErr_Warn(cls,
- "Casting complex values to real discards the imaginary "
- "part");
+ ret = PyErr_Warn(cls,
+ "Casting complex values to real discards the imaginary "
+ "part");
#endif
Py_XDECREF(cls);
+ if (ret < 0) {
+ return NULL;
+ }
}
if (castfunc) {
return castfunc;
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 74cb7da7a..f635e1c48 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1828,6 +1828,7 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
int N = 0;
int i;
PyObject *new_names;
+ PyObject *new_fields;
if (self->names == NULL) {
PyErr_SetString(PyExc_ValueError,
"there are no fields defined");
@@ -1857,26 +1858,38 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
}
/* Update dictionary keys in fields */
new_names = PySequence_Tuple(val);
+ new_fields = PyDict_New();
for (i = 0; i < N; i++) {
PyObject *key;
PyObject *item;
PyObject *new_key;
+ int ret;
key = PyTuple_GET_ITEM(self->names, i);
- /* Borrowed reference to item */
+ /* Borrowed references to item and new_key */
item = PyDict_GetItem(self->fields, key);
- /* Hold on to it even through DelItem */
- Py_INCREF(item);
new_key = PyTuple_GET_ITEM(new_names, i);
- PyDict_DelItem(self->fields, key);
- PyDict_SetItem(self->fields, new_key, item);
- /* self->fields now holds reference */
- Py_DECREF(item);
+ /* Check for duplicates */
+ ret = PyDict_Contains(new_fields, new_key);
+ if (ret != 0) {
+ if (ret < 0) {
+ PyErr_Clear();
+ }
+ PyErr_SetString(PyExc_ValueError, "Duplicate field names given.");
+ Py_DECREF(new_names);
+ Py_DECREF(new_fields);
+ return -1;
+ }
+ PyDict_SetItem(new_fields, new_key, item);
}
/* Replace names */
Py_DECREF(self->names);
self->names = new_names;
+ /* Replace fields */
+ Py_DECREF(self->fields);
+ self->fields = new_fields;
+
return 0;
}
diff --git a/numpy/core/src/scalarmathmodule.c.src b/numpy/core/src/scalarmathmodule.c.src
index f3ee6724e..6261c4c73 100644
--- a/numpy/core/src/scalarmathmodule.c.src
+++ b/numpy/core/src/scalarmathmodule.c.src
@@ -974,10 +974,11 @@ NONZERO_NAME(@name@_,)(PyObject *a)
/**end repeat**/
-static void
+static int
emit_complexwarning()
{
static PyObject *cls = NULL;
+ int ret;
if (cls == NULL) {
PyObject *mod;
mod = PyImport_ImportModule("numpy.core");
@@ -987,13 +988,13 @@ emit_complexwarning()
Py_DECREF(mod);
}
#if PY_VERSION_HEX >= 0x02050000
- PyErr_WarnEx(cls,
- "Casting complex values to real discards the imaginary "
- "part", 0);
+ return PyErr_WarnEx(cls,
+ "Casting complex values to real discards the imaginary "
+ "part", 0);
#else
- PyErr_Warn(cls,
- "Casting complex values to real discards the imaginary "
- "part");
+ return PyErr_Warn(cls,
+ "Casting complex values to real discards the imaginary "
+ "part");
#endif
}
@@ -1003,7 +1004,7 @@ emit_complexwarning()
* #Name=Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Float,Double,LongDouble,CFloat,CDouble,CLongDouble#
* #cmplx=0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1#
* #sign=(signed,unsigned)*5,,,,,,#
- * #unsigntyp=0,1,0,1,0,1,0,1,0,1,1*6#
+ * #unsigntyp=0,1,0,1,0,1,0,1,0,1,0*6#
* #ctype=long*8,PY_LONG_LONG*2,double*6#
* #realtyp=0*10,1*6#
* #func=(PyLong_FromLong,PyLong_FromUnsignedLong)*4,PyLong_FromLongLong,PyLong_FromUnsignedLongLong,PyLong_FromDouble*6#
@@ -1013,6 +1014,7 @@ static PyObject *
{
#if @cmplx@
@sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@).real;
+ int ret;
#else
@sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@);
#endif
@@ -1022,15 +1024,14 @@ static PyObject *
x = ix;
#endif
#if @cmplx@
- emit_complexwarning();
+ ret = emit_complexwarning();
+ if (ret < 0) {
+ return NULL;
+ }
#endif
-/*
- * For unsigned type, the (@ctype@) cast just does what is implicitely done by
- * the compiler.
- */
#if @unsigntyp@
- if(LONG_MIN < (@ctype@)x && (@ctype@)x < LONG_MAX)
+ if(x < LONG_MAX)
return PyInt_FromLong(x);
#else
if(LONG_MIN < x && x < LONG_MAX)
@@ -1052,7 +1053,11 @@ static PyObject *
@name@_@which@(PyObject *obj)
{
#if @cmplx@
- emit_complexwarning();
+ int ret;
+ ret = emit_complexwarning();
+ if (ret < 0) {
+ return NULL;
+ }
return @func@((PyArrayScalar_VAL(obj, @Name@)).real);
#else
return @func@((PyArrayScalar_VAL(obj, @Name@)));
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index e77da0691..850126482 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -1546,9 +1546,9 @@ C@TYPE@_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func))
UNARY_LOOP {
const @type@ in1r = ((@type@ *)ip1)[0];
const @type@ in1i = ((@type@ *)ip1)[1];
- ((@type@ *)op1)[0] = CGT(in1r, in1i, 0, 0) ? 1 :
- (CLT(in1r, in1i, 0, 0) ? -1 :
- (CEQ(in1r, in1i, 0, 0) ? 0 : NPY_NAN@C@));
+ ((@type@ *)op1)[0] = CGT(in1r, in1i, 0.0, 0.0) ? 1 :
+ (CLT(in1r, in1i, 0.0, 0.0) ? -1 :
+ (CEQ(in1r, in1i, 0.0, 0.0) ? 0 : NPY_NAN@C@));
((@type@ *)op1)[1] = 0;
}
}
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 45cc1c858..7c38fcf56 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1512,6 +1512,7 @@ class TestWarnings(object):
warnings.simplefilter("error", np.ComplexWarning)
assert_raises(np.ComplexWarning, x.__setitem__, slice(None), y)
+ assert_equal(x, [1,2])
warnings.simplefilter("default", np.ComplexWarning)
if sys.version_info >= (2, 6):
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 49490c05a..12fe089e6 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1416,5 +1416,23 @@ class TestRegression(TestCase):
x = tp(1+2j)
assert_equal(complex(x), 1+2j)
+ def test_uint_int_conversion(self):
+ x = 2**64 - 1
+ assert_equal(int(np.uint64(x)), x)
+
+ def test_duplicate_field_names_assign(self):
+ ra = np.fromiter(((i*3, i*2) for i in xrange(10)), dtype='i8,f8')
+ ra.dtype.names = ('f1', 'f2')
+ rep = repr(ra) # should not cause a segmentation fault
+ assert_raises(ValueError, setattr, ra.dtype, 'names', ('f1', 'f1'))
+
+ def test_eq_string_and_object_array(self):
+ # From e-mail thread "__eq__ with str and object" (Keith Goodman)
+ a1 = np.array(['a', 'b'], dtype=object)
+ a2 = np.array(['a', 'c'])
+ assert_array_equal(a1 == a2, [True, False])
+ assert_array_equal(a2 == a1, [True, False])
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py
index dafc7002f..85a86990f 100644
--- a/numpy/distutils/command/config.py
+++ b/numpy/distutils/command/config.py
@@ -169,6 +169,22 @@ int main()
return self.try_compile(body, headers, include_dirs)
+ def check_macro_true(self, symbol,
+ headers=None, include_dirs=None):
+ self._check_compiler()
+ body = """
+int main()
+{
+#if %s
+#else
+#error false or undefined macro
+#endif
+ ;
+ return 0;
+}""" % (symbol,)
+
+ return self.try_compile(body, headers, include_dirs)
+
def check_type(self, type_name, headers=None, include_dirs=None,
library_dirs=None):
"""Check type availability. Return True if the type can be compiled,
diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py
index 3fd3f22dc..5c9395869 100644
--- a/numpy/distutils/fcompiler/__init__.py
+++ b/numpy/distutils/fcompiler/__init__.py
@@ -695,14 +695,14 @@ _default_compilers = (
('cygwin.*', ('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')),
('linux.*', ('gnu','intel','lahey','pg','absoft','nag','vast','compaq',
'intele','intelem','gnu95','g95')),
- ('darwin.*', ('nag', 'absoft', 'ibm', 'intel', 'gnu', 'gnu95', 'g95')),
+ ('darwin.*', ('nag', 'absoft', 'ibm', 'intel', 'gnu', 'gnu95', 'g95', 'pg')),
('sunos.*', ('sun','gnu','gnu95','g95')),
('irix.*', ('mips','gnu','gnu95',)),
('aix.*', ('ibm','gnu','gnu95',)),
# os.name mappings
('posix', ('gnu','gnu95',)),
('nt', ('gnu','gnu95',)),
- ('mac', ('gnu','gnu95',)),
+ ('mac', ('gnu','gnu95','pg')),
)
fcompiler_class = None
diff --git a/numpy/distutils/fcompiler/pg.py b/numpy/distutils/fcompiler/pg.py
index 60c7f4e4b..a34669c36 100644
--- a/numpy/distutils/fcompiler/pg.py
+++ b/numpy/distutils/fcompiler/pg.py
@@ -2,6 +2,7 @@
# http://www.pgroup.com
from numpy.distutils.fcompiler import FCompiler
+from sys import platform
compilers = ['PGroupFCompiler']
@@ -11,7 +12,19 @@ class PGroupFCompiler(FCompiler):
description = 'Portland Group Fortran Compiler'
version_pattern = r'\s*pg(f77|f90|hpf) (?P<version>[\d.-]+).*'
- executables = {
+ if platform == 'darwin':
+ executables = {
+ 'version_cmd' : ["<F77>", "-V 2>/dev/null"],
+ 'compiler_f77' : ["pgf77", "-dynamiclib"],
+ 'compiler_fix' : ["pgf90", "-Mfixed", "-dynamiclib"],
+ 'compiler_f90' : ["pgf90", "-dynamiclib"],
+ 'linker_so' : ["libtool"],
+ 'archiver' : ["ar", "-cr"],
+ 'ranlib' : ["ranlib"]
+ }
+ pic_flags = ['']
+ else:
+ executables = {
'version_cmd' : ["<F77>", "-V 2>/dev/null"],
'compiler_f77' : ["pgf77"],
'compiler_fix' : ["pgf90", "-Mfixed"],
@@ -20,7 +33,9 @@ class PGroupFCompiler(FCompiler):
'archiver' : ["ar", "-cr"],
'ranlib' : ["ranlib"]
}
- pic_flags = ['-fpic']
+ pic_flags = ['-fpic']
+
+
module_dir_switch = '-module '
module_include_switch = '-I'
@@ -31,6 +46,10 @@ class PGroupFCompiler(FCompiler):
return ['-fast']
def get_flags_debug(self):
return ['-g']
+
+ if platform == 'darwin':
+ def get_flags_linker_so(self):
+ return ["-dynamic", '-undefined', 'dynamic_lookup']
if __name__ == '__main__':
from distutils import log
diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py
index cba98af2b..c10e3ee84 100644
--- a/numpy/f2py/capi_maps.py
+++ b/numpy/f2py/capi_maps.py
@@ -643,8 +643,10 @@ def modsign2map(m):
else:
ret['interface_usercode'] = ''
ret['pymethoddef'] = getpymethoddef(m) or ''
- ret['coutput'] = m['coutput']
- ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
+ if 'coutput' in m:
+ ret['coutput'] = m['coutput']
+ if 'f2py_wrapper_output' in m:
+ ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
return ret
def cb_sign2map(a,var,index=None):
diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py
index eb1ab22e9..264ebaad0 100644
--- a/numpy/lib/index_tricks.py
+++ b/numpy/lib/index_tricks.py
@@ -700,24 +700,15 @@ class IndexExpression(object):
array([2, 4])
"""
- maxint = sys.maxint
def __init__(self, maketuple):
self.maketuple = maketuple
def __getitem__(self, item):
- if self.maketuple and type(item) != type(()):
+ if self.maketuple and type(item) != tuple:
return (item,)
else:
return item
- def __len__(self):
- return self.maxint
-
- def __getslice__(self, start, stop):
- if stop == self.maxint:
- stop = None
- return self[start:stop:None]
-
index_exp = IndexExpression(maketuple=True)
s_ = IndexExpression(maketuple=False)
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 8c4a1a823..2668357bc 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -1,6 +1,6 @@
__all__ = ['savetxt', 'loadtxt', 'genfromtxt', 'ndfromtxt', 'mafromtxt',
- 'recfromtxt', 'recfromcsv', 'load', 'loads', 'save', 'savez',
- 'packbits', 'unpackbits', 'fromregex', 'DataSource']
+ 'recfromtxt', 'recfromcsv', 'load', 'loads', 'save', 'savez',
+ 'savez_compressed', 'packbits', 'unpackbits', 'fromregex', 'DataSource']
import numpy as np
import format
@@ -108,7 +108,11 @@ class BagObj(object):
except KeyError:
raise AttributeError, key
-
+def zipfile_factory(*args, **kwargs):
+ import zipfile
+ if sys.version_info >= (2, 5):
+ kwargs['allowZip64'] = True
+ return zipfile.ZipFile(*args, **kwargs)
class NpzFile(object):
"""
@@ -142,6 +146,9 @@ class NpzFile(object):
fid : file or str
The zipped archive to open. This is either a file-like object
or a string containing the path to the archive.
+ own_fid : bool, optional
+ Whether NpzFile should close the file handle.
+ Requires that `fid` is a file-like object.
Examples
--------
@@ -163,11 +170,10 @@ class NpzFile(object):
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
"""
- def __init__(self, fid):
+ def __init__(self, fid, own_fid=False):
# Import is postponed to here since zipfile depends on gzip, an optional
# component of the so-called standard library.
- import zipfile
- _zip = zipfile.ZipFile(fid)
+ _zip = zipfile_factory(fid)
self._files = _zip.namelist()
self.files = []
for x in self._files:
@@ -177,6 +183,25 @@ class NpzFile(object):
self.files.append(x)
self.zip = _zip
self.f = BagObj(self)
+ if own_fid:
+ self.fid = fid
+ else:
+ self.fid = None
+
+ def close(self):
+ """
+ Close the file.
+
+ """
+ if self.zip is not None:
+ self.zip.close()
+ self.zip = None
+ if self.fid is not None:
+ self.fid.close()
+ self.fid = None
+
+ def __del__(self):
+ self.close()
def __getitem__(self, key):
# FIXME: This seems like it will copy strings around
@@ -293,31 +318,39 @@ def load(file, mmap_mode=None):
"""
import gzip
+ own_fid = False
if isinstance(file, basestring):
fid = open(file, "rb")
+ own_fid = True
elif isinstance(file, gzip.GzipFile):
fid = seek_gzip_factory(file)
+ own_fid = True
else:
fid = file
- # Code to distinguish from NumPy binary files and pickles.
- _ZIP_PREFIX = asbytes('PK\x03\x04')
- N = len(format.MAGIC_PREFIX)
- magic = fid.read(N)
- fid.seek(-N, 1) # back-up
- if magic.startswith(_ZIP_PREFIX): # zip-file (assume .npz)
- return NpzFile(fid)
- elif magic == format.MAGIC_PREFIX: # .npy file
- if mmap_mode:
- return format.open_memmap(file, mode=mmap_mode)
- else:
- return format.read_array(fid)
- else: # Try a pickle
- try:
- return _cload(fid)
- except:
- raise IOError, \
- "Failed to interpret file %s as a pickle" % repr(file)
+ try:
+ # Code to distinguish from NumPy binary files and pickles.
+ _ZIP_PREFIX = asbytes('PK\x03\x04')
+ N = len(format.MAGIC_PREFIX)
+ magic = fid.read(N)
+ fid.seek(-N, 1) # back-up
+ if magic.startswith(_ZIP_PREFIX): # zip-file (assume .npz)
+ own_fid = False
+ return NpzFile(fid, own_fid=True)
+ elif magic == format.MAGIC_PREFIX: # .npy file
+ if mmap_mode:
+ return format.open_memmap(file, mode=mmap_mode)
+ else:
+ return format.read_array(fid)
+ else: # Try a pickle
+ try:
+ return _cload(fid)
+ except:
+ raise IOError, \
+ "Failed to interpret file %s as a pickle" % repr(file)
+ finally:
+ if own_fid:
+ fid.close()
def save(file, arr):
"""
@@ -335,7 +368,7 @@ def save(file, arr):
See Also
--------
- savez : Save several arrays into a ``.npz`` compressed archive
+ savez : Save several arrays into a ``.npz`` archive
savetxt, load
Notes
@@ -355,19 +388,25 @@ def save(file, arr):
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
"""
+ own_fid = False
if isinstance(file, basestring):
if not file.endswith('.npy'):
file = file + '.npy'
fid = open(file, "wb")
+ own_fid = True
else:
fid = file
- arr = np.asanyarray(arr)
- format.write_array(fid, arr)
+ try:
+ arr = np.asanyarray(arr)
+ format.write_array(fid, arr)
+ finally:
+ if own_fid:
+ fid.close()
def savez(file, *args, **kwds):
"""
- Save several arrays into a single, archive file in ``.npz`` format.
+ Save several arrays into a single file in uncompressed ``.npz`` format.
If arguments are passed in with no keywords, the corresponding variable
names, in the .npz file, are 'arr_0', 'arr_1', etc. If keyword arguments
@@ -380,12 +419,12 @@ def savez(file, *args, **kwds):
Either the file name (string) or an open file (file-like object)
where the data will be saved. If file is a string, the ``.npz``
extension will be appended to the file name if it is not already there.
- \\*args : Arguments, optional
+ *args : Arguments, optional
Arrays to save to the file. Since it is not possible for Python to
know the names of the arrays outside `savez`, the arrays will be saved
with names "arr_0", "arr_1", and so on. These arguments can be any
expression.
- \\*\\*kwds : Keyword arguments, optional
+ **kwds : Keyword arguments, optional
Arrays to save to the file. Arrays will be saved in the file with the
keyword names.
@@ -417,7 +456,7 @@ def savez(file, *args, **kwds):
>>> x = np.arange(10)
>>> y = np.sin(x)
- Using `savez` with \\*args, the arrays are saved with default names.
+ Using `savez` with *args, the arrays are saved with default names.
>>> np.savez(outfile, x, y)
>>> outfile.seek(0) # Only needed here to simulate closing & reopening file
@@ -427,7 +466,7 @@ def savez(file, *args, **kwds):
>>> npzfile['arr_0']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
- Using `savez` with \\*\\*kwds, the arrays are saved with the keyword names.
+ Using `savez` with **kwds, the arrays are saved with the keyword names.
>>> outfile = TemporaryFile()
>>> np.savez(outfile, x=x, y=y)
@@ -438,8 +477,38 @@ def savez(file, *args, **kwds):
>>> npzfile['x']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+ See Also
+ --------
+ numpy.savez_compressed : Save several arrays into a compressed .npz file format
+
+ """
+ _savez(file, args, kwds, False)
+
+def savez_compressed(file, *args, **kwds):
"""
+ Save several arrays into a single file in compressed ``.npz`` format.
+
+ If keyword arguments are given, then filenames are taken from the keywords.
+ If arguments are passed in with no keywords, then stored file names are
+ arr_0, arr_1, etc.
+ Parameters
+ ----------
+ file : string
+ File name of .npz file.
+ args : Arguments
+ Function arguments.
+ kwds : Keyword arguments
+ Keywords.
+
+ See Also
+ --------
+ numpy.savez : Save several arrays into an uncompressed .npz file format
+
+ """
+ _savez(file, args, kwds, True)
+
+def _savez(file, args, kwds, compress):
# Import is postponed to here since zipfile depends on gzip, an optional
# component of the so-called standard library.
import zipfile
@@ -457,7 +526,12 @@ def savez(file, *args, **kwds):
raise ValueError, "Cannot use un-named variables and keyword %s" % key
namedict[key] = val
- zip = zipfile.ZipFile(file, mode="w")
+ if compress:
+ compression = zipfile.ZIP_DEFLATED
+ else:
+ compression = zipfile.ZIP_STORED
+
+ zip = zipfile_factory(file, mode="w", compression=compression)
# Stage arrays in a temporary file on disk, before writing to zip.
fd, tmpfile = tempfile.mkstemp(suffix='-numpy.npy')
@@ -586,9 +660,9 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
if usecols is not None:
usecols = list(usecols)
- isstring = False
+ own_fh = False
if _is_string_like(fname):
- isstring = True
+ own_fh = True
if fname.endswith('.gz'):
import gzip
fh = seek_gzip_factory(fname)
@@ -676,7 +750,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
# Convert each value according to its column and store
X.append(tuple([conv(val) for (conv, val) in zip(converters, vals)]))
finally:
- if isstring:
+ if own_fh:
fh.close()
if len(dtype_types) > 1:
@@ -798,7 +872,9 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n'):
fmt = asstr(fmt)
delimiter = asstr(delimiter)
+ own_fh = False
if _is_string_like(fname):
+ own_fh = True
if fname.endswith('.gz'):
import gzip
fh = gzip.open(fname, 'wb')
@@ -812,39 +888,43 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n'):
else:
raise ValueError('fname must be a string or file handle')
- X = np.asarray(X)
+ try:
+ X = np.asarray(X)
- # Handle 1-dimensional arrays
- if X.ndim == 1:
- # Common case -- 1d array of numbers
- if X.dtype.names is None:
- X = np.atleast_2d(X).T
- ncol = 1
+ # Handle 1-dimensional arrays
+ if X.ndim == 1:
+ # Common case -- 1d array of numbers
+ if X.dtype.names is None:
+ X = np.atleast_2d(X).T
+ ncol = 1
- # Complex dtype -- each field indicates a separate column
- else:
- ncol = len(X.dtype.descr)
- else:
- ncol = X.shape[1]
-
- # `fmt` can be a string with multiple insertion points or a list of formats.
- # E.g. '%10.5f\t%10d' or ('%10.5f', '$10d')
- if type(fmt) in (list, tuple):
- if len(fmt) != ncol:
- raise AttributeError('fmt has wrong shape. %s' % str(fmt))
- format = asstr(delimiter).join(map(asstr, fmt))
- elif type(fmt) is str:
- if fmt.count('%') == 1:
- fmt = [fmt, ]*ncol
- format = delimiter.join(fmt)
- elif fmt.count('%') != ncol:
- raise AttributeError('fmt has wrong number of %% formats. %s'
- % fmt)
+ # Complex dtype -- each field indicates a separate column
+ else:
+ ncol = len(X.dtype.descr)
else:
- format = fmt
+ ncol = X.shape[1]
+
+ # `fmt` can be a string with multiple insertion points or a
+ # list of formats. E.g. '%10.5f\t%10d' or ('%10.5f', '$10d')
+ if type(fmt) in (list, tuple):
+ if len(fmt) != ncol:
+ raise AttributeError('fmt has wrong shape. %s' % str(fmt))
+ format = asstr(delimiter).join(map(asstr, fmt))
+ elif type(fmt) is str:
+ if fmt.count('%') == 1:
+ fmt = [fmt, ]*ncol
+ format = delimiter.join(fmt)
+ elif fmt.count('%') != ncol:
+ raise AttributeError('fmt has wrong number of %% formats. %s'
+ % fmt)
+ else:
+ format = fmt
- for row in X:
- fh.write(asbytes(format % tuple(row) + newline))
+ for row in X:
+ fh.write(asbytes(format % tuple(row) + newline))
+ finally:
+ if own_fh:
+ fh.close()
import re
def fromregex(file, regexp, dtype):
@@ -902,25 +982,32 @@ def fromregex(file, regexp, dtype):
array([1312, 1534, 444], dtype=int64)
"""
+ own_fh = False
if not hasattr(file, "read"):
file = open(file, 'rb')
- if not hasattr(regexp, 'match'):
- regexp = re.compile(asbytes(regexp))
- if not isinstance(dtype, np.dtype):
- dtype = np.dtype(dtype)
+ own_fh = True
- seq = regexp.findall(file.read())
- if seq and not isinstance(seq[0], tuple):
- # Only one group is in the regexp.
- # Create the new array as a single data-type and then
- # re-interpret as a single-field structured array.
- newdtype = np.dtype(dtype[dtype.names[0]])
- output = np.array(seq, dtype=newdtype)
- output.dtype = dtype
- else:
- output = np.array(seq, dtype=dtype)
+ try:
+ if not hasattr(regexp, 'match'):
+ regexp = re.compile(asbytes(regexp))
+ if not isinstance(dtype, np.dtype):
+ dtype = np.dtype(dtype)
+
+ seq = regexp.findall(file.read())
+ if seq and not isinstance(seq[0], tuple):
+ # Only one group is in the regexp.
+ # Create the new array as a single data-type and then
+ # re-interpret as a single-field structured array.
+ newdtype = np.dtype(dtype[dtype.names[0]])
+ output = np.array(seq, dtype=newdtype)
+ output.dtype = dtype
+ else:
+ output = np.array(seq, dtype=dtype)
- return output
+ return output
+ finally:
+ if own_fh:
+ fh.close()
@@ -1092,8 +1179,10 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
raise TypeError(errmsg % type(user_converters))
# Initialize the filehandle, the LineSplitter and the NameValidator
+ own_fhd = False
if isinstance(fname, basestring):
fhd = np.lib._datasource.open(fname, 'U')
+ own_fhd = True
elif not hasattr(fname, 'read'):
raise TypeError("The input should be a string or a filehandle. "\
"(got %s instead)" % type(fname))
@@ -1354,6 +1443,8 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
append_to_masks(tuple([v.strip() in m
for (v, m) in zip(values, missing_values)]))
+ if own_fhd:
+ fhd.close()
# Upgrade the converters (if needed)
if dtype is None:
diff --git a/numpy/lib/tests/test_index_tricks.py b/numpy/lib/tests/test_index_tricks.py
index 3307cef3e..c17ee5d6a 100644
--- a/numpy/lib/tests/test_index_tricks.py
+++ b/numpy/lib/tests/test_index_tricks.py
@@ -2,7 +2,7 @@ from numpy.testing import *
import numpy as np
from numpy import ( array, ones, r_, mgrid, unravel_index, zeros, where,
ndenumerate, fill_diagonal, diag_indices,
- diag_indices_from )
+ diag_indices_from, s_, index_exp )
class TestUnravelIndex(TestCase):
def test_basic(self):
@@ -77,6 +77,19 @@ class TestNdenumerate(TestCase):
[((0,0), 1), ((0,1), 2), ((1,0), 3), ((1,1), 4)])
+class TestIndexExpression(TestCase):
+ def test_regression_1(self):
+ # ticket #1196
+ a = np.arange(2)
+ assert_equal(a[:-1], a[s_[:-1]])
+ assert_equal(a[:-1], a[index_exp[:-1]])
+
+ def test_simple_1(self):
+ a = np.random.rand(4,5,6)
+
+ assert_equal(a[:,:3,[1,2]], a[index_exp[:,:3,[1,2]]])
+ assert_equal(a[:,:3,[1,2]], a[s_[:,:3,[1,2]]])
+
def test_fill_diagonal():
a = zeros((3, 3),int)
fill_diagonal(a, 5)
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py
index eb8c8379a..c044176cf 100644
--- a/numpy/linalg/linalg.py
+++ b/numpy/linalg/linalg.py
@@ -1680,12 +1680,13 @@ def lstsq(a, b, rcond=-1):
"""
Return the least-squares solution to a linear matrix equation.
- Solves the equation `a x = b` by computing a vector `x` that minimizes
- the norm `|| b - a x ||`. The equation may be under-, well-, or over-
- determined (i.e., the number of linearly independent rows of `a` can be
- less than, equal to, or greater than its number of linearly independent
- columns). If `a` is square and of full rank, then `x` (but for round-off
- error) is the "exact" solution of the equation.
+ Solves the equation `a x = b` by computing a vector `x` that
+ minimizes the Euclidean 2-norm `|| b - a x ||^2`. The equation may
+ be under-, well-, or over- determined (i.e., the number of
+ linearly independent rows of `a` can be less than, equal to, or
+ greater than its number of linearly independent columns). If `a`
+ is square and of full rank, then `x` (but for round-off error) is
+ the "exact" solution of the equation.
Parameters
----------
@@ -1706,7 +1707,7 @@ def lstsq(a, b, rcond=-1):
Least-squares solution. The shape of `x` depends on the shape of
`b`.
residues : ndarray, shape (), (1,), or (K,)
- Sums of residues; squared Euclidean norm for each column in
+ Sums of residues; squared Euclidean 2-norm for each column in
``b - a*x``.
If the rank of `a` is < N or > M, this is an empty array.
If `b` is 1-dimensional, this is a (1,) shape array.
@@ -1772,6 +1773,7 @@ def lstsq(a, b, rcond=-1):
if m != b.shape[0]:
raise LinAlgError, 'Incompatible dimensions'
t, result_t = _commonType(a, b)
+ result_real_t = _realType(result_t)
real_t = _linalgRealType(t)
bstar = zeros((ldb, n_rhs), t)
bstar[:b.shape[0],:n_rhs] = b.copy()
@@ -1811,16 +1813,27 @@ def lstsq(a, b, rcond=-1):
0, work, lwork, iwork, 0)
if results['info'] > 0:
raise LinAlgError, 'SVD did not converge in Linear Least Squares'
- resids = array([], t)
+ resids = array([], result_real_t)
if is_1d:
x = array(ravel(bstar)[:n], dtype=result_t, copy=True)
if results['rank'] == n and m > n:
- resids = array([sum((ravel(bstar)[n:])**2)], dtype=result_t)
+ if isComplexType(t):
+ resids = array([sum(abs(ravel(bstar)[n:])**2)],
+ dtype=result_real_t)
+ else:
+ resids = array([sum((ravel(bstar)[n:])**2)],
+ dtype=result_real_t)
else:
x = array(transpose(bstar)[:n,:], dtype=result_t, copy=True)
if results['rank'] == n and m > n:
- resids = sum((transpose(bstar)[n:,:])**2, axis=0).astype(result_t)
- st = s[:min(n, m)].copy().astype(_realType(result_t))
+ if isComplexType(t):
+ resids = sum(abs(transpose(bstar)[n:,:])**2, axis=0).astype(
+ result_real_t)
+ else:
+ resids = sum((transpose(bstar)[n:,:])**2, axis=0).astype(
+ result_real_t)
+
+ st = s[:min(n, m)].copy().astype(result_real_t)
return wrap(x), wrap(resids), results['rank'], st
def norm(x, ord=None):
diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py
index 3a9584dd6..a672ed08a 100644
--- a/numpy/linalg/tests/test_linalg.py
+++ b/numpy/linalg/tests/test_linalg.py
@@ -33,6 +33,11 @@ class LinalgTestCase:
b = array([2., 1.], dtype=double)
self.do(a, b)
+ def test_double_2(self):
+ a = array([[1.,2.], [3.,4.]], dtype=double)
+ b = array([[2., 1., 4.], [3., 4., 6.]], dtype=double)
+ self.do(a, b)
+
def test_csingle(self):
a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=csingle)
b = array([2.+1j, 1.+2j], dtype=csingle)
@@ -43,6 +48,11 @@ class LinalgTestCase:
b = array([2.+1j, 1.+2j], dtype=cdouble)
self.do(a, b)
+ def test_cdouble_2(self):
+ a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=cdouble)
+ b = array([[2.+1j, 1.+2j, 1+3j], [1-2j, 1-3j, 1-6j]], dtype=cdouble)
+ self.do(a, b)
+
def test_empty(self):
a = atleast_2d(array([], dtype = double))
b = atleast_2d(array([], dtype = double))
@@ -70,6 +80,58 @@ class LinalgTestCase:
self.do(a, b)
+class LinalgNonsquareTestCase:
+ def test_single_nsq_1(self):
+ a = array([[1.,2.,3.], [3.,4.,6.]], dtype=single)
+ b = array([2., 1.], dtype=single)
+ self.do(a, b)
+
+ def test_single_nsq_2(self):
+ a = array([[1.,2.], [3.,4.], [5.,6.]], dtype=single)
+ b = array([2., 1., 3.], dtype=single)
+ self.do(a, b)
+
+ def test_double_nsq_1(self):
+ a = array([[1.,2.,3.], [3.,4.,6.]], dtype=double)
+ b = array([2., 1.], dtype=double)
+ self.do(a, b)
+
+ def test_double_nsq_2(self):
+ a = array([[1.,2.], [3.,4.], [5.,6.]], dtype=double)
+ b = array([2., 1., 3.], dtype=double)
+ self.do(a, b)
+
+ def test_csingle_nsq_1(self):
+ a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=csingle)
+ b = array([2.+1j, 1.+2j], dtype=csingle)
+ self.do(a, b)
+
+ def test_csingle_nsq_2(self):
+ a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=csingle)
+ b = array([2.+1j, 1.+2j, 3.-3j], dtype=csingle)
+ self.do(a, b)
+
+ def test_cdouble_nsq_1(self):
+ a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=cdouble)
+ b = array([2.+1j, 1.+2j], dtype=cdouble)
+ self.do(a, b)
+
+ def test_cdouble_nsq_2(self):
+ a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=cdouble)
+ b = array([2.+1j, 1.+2j, 3.-3j], dtype=cdouble)
+ self.do(a, b)
+
+ def test_cdouble_nsq_1_2(self):
+ a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=cdouble)
+ b = array([[2.+1j, 1.+2j], [1-1j, 2-2j]], dtype=cdouble)
+ self.do(a, b)
+
+ def test_cdouble_nsq_2_2(self):
+ a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=cdouble)
+ b = array([[2.+1j, 1.+2j], [1-1j, 2-2j], [1-1j, 2-2j]], dtype=cdouble)
+ self.do(a, b)
+
+
class TestSolve(LinalgTestCase, TestCase):
def do(self, a, b):
x = linalg.solve(a, b)
@@ -153,13 +215,28 @@ class TestDet(LinalgTestCase, TestCase):
assert_equal(type(linalg.slogdet([[0.0j]])[0]), cdouble)
assert_equal(type(linalg.slogdet([[0.0j]])[1]), double)
-class TestLstsq(LinalgTestCase, TestCase):
+class TestLstsq(LinalgTestCase, LinalgNonsquareTestCase, TestCase):
def do(self, a, b):
+ arr = np.asarray(a)
+ m, n = arr.shape
u, s, vt = linalg.svd(a, 0)
x, residuals, rank, sv = linalg.lstsq(a, b)
- assert_almost_equal(b, dot(a, x))
- assert_equal(rank, asarray(a).shape[0])
+ if m <= n:
+ assert_almost_equal(b, dot(a, x))
+ assert_equal(rank, m)
+ else:
+ assert_equal(rank, n)
assert_almost_equal(sv, sv.__array_wrap__(s))
+ if rank == n and m > n:
+ expect_resids = (np.asarray(abs(np.dot(a, x) - b))**2).sum(axis=0)
+ expect_resids = np.asarray(expect_resids)
+ if len(np.asarray(b).shape) == 1:
+ expect_resids.shape = (1,)
+ assert_equal(residuals.shape, expect_resids.shape)
+ else:
+ expect_resids = type(x)([])
+ assert_almost_equal(residuals, expect_resids)
+ assert_(np.issubdtype(residuals.dtype, np.floating))
assert imply(isinstance(b, matrix), isinstance(x, matrix))
assert imply(isinstance(b, matrix), isinstance(residuals, matrix))