diff options
-rw-r--r-- | arraysetops.py | 9 | ||||
-rw-r--r-- | getlimits.py | 4 | ||||
-rw-r--r-- | index_tricks.py | 34 | ||||
-rw-r--r-- | scimath.py | 366 | ||||
-rw-r--r-- | tests/test_arraysetops.py | 4 | ||||
-rw-r--r-- | tests/test_getlimits.py | 10 | ||||
-rw-r--r-- | tests/test_polynomial.py | 8 |
7 files changed, 397 insertions, 38 deletions
diff --git a/arraysetops.py b/arraysetops.py index 6693fa81c..1d99f7a97 100644 --- a/arraysetops.py +++ b/arraysetops.py @@ -201,9 +201,13 @@ def setmember1d( ar1, ar2 ): numpy.lib.arraysetops has a number of other functions for performing set operations on arrays. """ - zlike = nm.zeros_like + ar1 = nm.asarray( ar1 ) + ar2 = nm.asarray( ar2 ) ar = nm.concatenate( (ar1, ar2 ) ) - tt = nm.concatenate( (zlike( ar1 ), zlike( ar2 ) + 1) ) + b1 = nm.zeros( ar1.shape, dtype = nm.int8 ) + b2 = nm.ones( ar2.shape, dtype = nm.int8 ) + tt = nm.concatenate( (b1, b2) ) + # We need this to be a stable sort, so always use 'mergesort' here. The # values from the first array should always come before the values from the # second array. @@ -212,7 +216,6 @@ def setmember1d( ar1, ar2 ): aux2 = tt[perm] # flag = ediff1d( aux, 1 ) == 0 flag = nm.concatenate( (aux[1:] == aux[:-1], [False] ) ) - ii = nm.where( flag * aux2 )[0] aux = perm[ii+1] perm[ii+1] = perm[ii] diff --git a/getlimits.py b/getlimits.py index 00c3ea846..89b40203f 100644 --- a/getlimits.py +++ b/getlimits.py @@ -7,7 +7,7 @@ from machar import MachAr import numpy.core.numeric as numeric import numpy.core.numerictypes as ntypes from numpy.core.numeric import array -import numpy as N +import numpy as np def _frz(a): """fix rank-0 --> rank-1""" @@ -128,7 +128,7 @@ class iinfo: _max_vals = {} def __init__(self, type): - self.dtype = N.dtype(type) + self.dtype = np.dtype(type) self.kind = self.dtype.kind self.bits = self.dtype.itemsize * 8 self.key = "%s%d" % (self.kind, self.bits) diff --git a/index_tricks.py b/index_tricks.py index 26a44976c..c45148057 100644 --- a/index_tricks.py +++ b/index_tricks.py @@ -1,5 +1,3 @@ -## Automatically adapted for numpy Sep 19, 2005 by convertcode.py - __all__ = ['unravel_index', 'mgrid', 'ogrid', @@ -48,7 +46,7 @@ def unravel_index(x,dims): # Reverse # [dcb,dc,d,1] dim_prod = _nx.cumprod([1] + list(dims)[:0:-1])[::-1] - # Indeces become [x/dcb % a, x/dc % b, x/d % c, x/1 % d] + # Indices become [x/dcb % a, x/dc % b, x/d % c, x/1 % d] return tuple(x/dim_prod % dims) def ix_(*args): @@ -193,7 +191,7 @@ class nd_grid(object): mgrid = nd_grid(sparse=False) ogrid = nd_grid(sparse=True) -class concatenator(object): +class AxisConcatenator(object): """Translates slice objects to concatenation along an axis. """ def _retval(self, res): @@ -313,26 +311,30 @@ class concatenator(object): # etc. because otherwise we couldn't get the doc string to come out right # in help(r_) -class r_class(concatenator): +class RClass(AxisConcatenator): """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]) + 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) + AxisConcatenator.__init__(self, 0) -r_ = r_class() +r_ = RClass() -class c_class(concatenator): +class CClass(AxisConcatenator): """Translates slice objects to concatenation along the second axis. + + For example: + >>> c_[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, -1, ndmin=2, trans1d=0) + AxisConcatenator.__init__(self, -1, ndmin=2, trans1d=0) -c_ = c_class() +c_ = CClass() class ndenumerate(object): """ @@ -423,7 +425,7 @@ class ndindex(object): # # -class _index_expression_class(object): +class IndexExpression(object): """ A nicer way to build up index tuples for arrays. @@ -451,7 +453,7 @@ class _index_expression_class(object): stop = None return self[start:stop:None] -index_exp = _index_expression_class(1) -s_ = _index_expression_class(0) +index_exp = IndexExpression(maketuple=True) +s_ = IndexExpression(maketuple=False) # End contribution from Konrad. diff --git a/scimath.py b/scimath.py index c15f254a3..429eac9c8 100644 --- a/scimath.py +++ b/scimath.py @@ -2,6 +2,17 @@ Wrapper functions to more user-friendly calling of certain math functions whose output data-type is different than the input data-type in certain domains of the input. + +For example, for functions like log() with branch cuts, the versions in this +module provide the mathematically valid answers in the complex plane: + +>>> import math +>>> from numpy.lib import scimath +>>> scimath.log(-math.exp(1)) == (1+1j*math.pi) +True + +Similarly, sqrt(), other base logarithms, power() and trig functions are +correctly handled. See their respective docstrings for specific examples. """ __all__ = ['sqrt', 'log', 'log2', 'logn','log10', 'power', 'arccos', @@ -12,51 +23,266 @@ import numpy.core.numerictypes as nt from numpy.core.numeric import asarray, any from numpy.lib.type_check import isreal - -#__all__.extend([key for key in dir(nx.umath) -# if key[0] != '_' and key not in __all__]) - _ln2 = nx.log(2.0) def _tocomplex(arr): - if isinstance(arr.dtype, (nt.single, nt.byte, nt.short, nt.ubyte, - nt.ushort)): + """Convert its input `arr` to a complex array. + + The input is returned as a complex array of the smallest type that will fit + the original data: types like single, byte, short, etc. become csingle, + while others become cdouble. + + A copy of the input is always made. + + Parameters + ---------- + arr : array + + Returns + ------- + array + An array with the same input data as the input but in complex form. + + Examples + -------- + + >>> import numpy as np + + First, consider an input of type short: + + >>> a = np.array([1,2,3],np.short) + + >>> ac = _tocomplex(a); ac + array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) + + >>> ac.dtype + dtype('complex64') + + If the input is of type double, the output is correspondingly of the + complex double type as well: + + >>> b = np.array([1,2,3],np.double) + + >>> bc = _tocomplex(b); bc + array([ 1.+0.j, 2.+0.j, 3.+0.j]) + + >>> bc.dtype + dtype('complex128') + + Note that even if the input was complex to begin with, a copy is still + made, since the astype() method always copies: + + >>> c = np.array([1,2,3],np.csingle) + + >>> cc = _tocomplex(c); cc + array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) + + >>> c *= 2; c + array([ 2.+0.j, 4.+0.j, 6.+0.j], dtype=complex64) + + >>> cc + array([ 1.+0.j, 2.+0.j, 3.+0.j], dtype=complex64) + """ + if issubclass(arr.dtype.type, (nt.single, nt.byte, nt.short, nt.ubyte, + nt.ushort,nt.csingle)): return arr.astype(nt.csingle) else: return arr.astype(nt.cdouble) def _fix_real_lt_zero(x): + """Convert `x` to complex if it has real, negative components. + + Otherwise, output is just the array version of the input (via asarray). + + Parameters + ---------- + x : array_like + + Returns + ------- + array + + Examples + -------- + >>> _fix_real_lt_zero([1,2]) + array([1, 2]) + + >>> _fix_real_lt_zero([-1,2]) + array([-1.+0.j, 2.+0.j]) + """ x = asarray(x) if any(isreal(x) & (x<0)): x = _tocomplex(x) return x def _fix_int_lt_zero(x): + """Convert `x` to double if it has real, negative components. + + Otherwise, output is just the array version of the input (via asarray). + + Parameters + ---------- + x : array_like + + Returns + ------- + array + + Examples + -------- + >>> _fix_int_lt_zero([1,2]) + array([1, 2]) + + >>> _fix_int_lt_zero([-1,2]) + array([-1., 2.]) + """ x = asarray(x) if any(isreal(x) & (x < 0)): x = x * 1.0 return x def _fix_real_abs_gt_1(x): + """Convert `x` to complex if it has real components x_i with abs(x_i)>1. + + Otherwise, output is just the array version of the input (via asarray). + + Parameters + ---------- + x : array_like + + Returns + ------- + array + + Examples + -------- + >>> _fix_real_abs_gt_1([0,1]) + array([0, 1]) + + >>> _fix_real_abs_gt_1([0,2]) + array([ 0.+0.j, 2.+0.j]) + """ x = asarray(x) if any(isreal(x) & (abs(x)>1)): x = _tocomplex(x) return x def sqrt(x): + """Return the square root of x. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like output. + + Examples + -------- + + For real, non-negative inputs this works just like numpy.sqrt(): + >>> sqrt(1) + 1.0 + + >>> sqrt([1,4]) + array([ 1., 2.]) + + But it automatically handles negative inputs: + >>> sqrt(-1) + (0.0+1.0j) + + >>> sqrt([-1,4]) + array([ 0.+1.j, 2.+0.j]) + """ x = _fix_real_lt_zero(x) return nx.sqrt(x) def log(x): + """Return the natural logarithm of x. + + If x contains negative inputs, the answer is computed and returned in the + complex domain. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + >>> import math + + >>> log(math.exp(1)) + 1.0 + + Negative arguments are correctly handled (recall that for negative + arguments, the identity exp(log(z))==z does not hold anymore): + + >>> log(-math.exp(1)) == (1+1j*math.pi) + True + """ x = _fix_real_lt_zero(x) return nx.log(x) def log10(x): + """Return the base 10 logarithm of x. + + If x contains negative inputs, the answer is computed and returned in the + complex domain. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> log10([10**1,10**2]) + array([ 1., 2.]) + + + >>> log10([-10**1,-10**2,10**2]) + array([ 1.+1.3644j, 2.+1.3644j, 2.+0.j ]) + """ x = _fix_real_lt_zero(x) return nx.log10(x) def logn(n, x): - """ Take log base n of x. + """Take log base n of x. + + If x contains negative inputs, the answer is computed and returned in the + complex domain. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> logn(2,[4,8]) + array([ 2., 3.]) + + >>> logn(2,[-4,-8,8]) + array([ 2.+4.5324j, 3.+4.5324j, 3.+0.j ]) """ x = _fix_real_lt_zero(x) n = _fix_real_lt_zero(n) @@ -64,23 +290,149 @@ def logn(n, x): def log2(x): """ Take log base 2 of x. + + If x contains negative inputs, the answer is computed and returned in the + complex domain. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> log2([4,8]) + array([ 2., 3.]) + + >>> log2([-4,-8,8]) + array([ 2.+4.5324j, 3.+4.5324j, 3.+0.j ]) """ x = _fix_real_lt_zero(x) return nx.log(x)/_ln2 def power(x, p): + """Return x**p. + + If x contains negative values, it is converted to the complex domain. + + If p contains negative values, it is converted to floating point. + + Parameters + ---------- + x : array_like + p : array_like of integers + + Returns + ------- + array_like + + Examples + -------- + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> power([2,4],2) + array([ 4, 16]) + + >>> power([2,4],-2) + array([ 0.25 , 0.0625]) + + >>> power([-2,4],2) + array([ 4.+0.j, 16.+0.j]) + """ x = _fix_real_lt_zero(x) p = _fix_int_lt_zero(p) return nx.power(x, p) def arccos(x): + """Compute the inverse cosine of x. + + For real x with abs(x)<=1, this returns the principal value. + + If abs(x)>1, the complex arccos() is computed. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> arccos(1) + 0.0 + + >>> arccos([1,2]) + array([ 0.-0.j , 0.+1.317j]) + """ x = _fix_real_abs_gt_1(x) return nx.arccos(x) def arcsin(x): + """Compute the inverse sine of x. + + For real x with abs(x)<=1, this returns the principal value. + + If abs(x)>1, the complex arcsin() is computed. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> arcsin(0) + 0.0 + + >>> arcsin([0,1]) + array([ 0. , 1.5708]) + """ x = _fix_real_abs_gt_1(x) return nx.arcsin(x) def arctanh(x): + """Compute the inverse hyperbolic tangent of x. + + For real x with abs(x)<=1, this returns the principal value. + + If abs(x)>1, the complex arctanh() is computed. + + Parameters + ---------- + x : array_like + + Returns + ------- + array_like + + Examples + -------- + (We set the printing precision so the example can be auto-tested) + >>> import numpy as np; np.set_printoptions(precision=4) + + >>> arctanh(0) + 0.0 + + >>> arctanh([0,2]) + array([ 0.0000+0.j , 0.5493-1.5708j]) + """ x = _fix_real_abs_gt_1(x) return nx.arctanh(x) diff --git a/tests/test_arraysetops.py b/tests/test_arraysetops.py index e2e703b9a..5a5a8fbd8 100644 --- a/tests/test_arraysetops.py +++ b/tests/test_arraysetops.py @@ -145,6 +145,10 @@ class TestAso(NumpyTestCase): assert_array_equal([], setdiff1d([],[])) + def check_setdiff1d_char_array(self): + a = numpy.array(['a','b','c']) + b = numpy.array(['a','b','s']) + assert_array_equal(setdiff1d(a,b),numpy.array(['c'])) ## # 03.11.2005, c diff --git a/tests/test_getlimits.py b/tests/test_getlimits.py index 3c53f3322..a85228689 100644 --- a/tests/test_getlimits.py +++ b/tests/test_getlimits.py @@ -2,12 +2,10 @@ """ from numpy.testing import * -set_package_path() import numpy.lib;reload(numpy.lib) from numpy.lib.getlimits import finfo, iinfo from numpy import single,double,longdouble -import numpy as N -restore_path() +import numpy as np ################################################## @@ -39,15 +37,15 @@ class TestIinfo(NumpyTestCase): def check_basic(self): dts = zip(['i1', 'i2', 'i4', 'i8', 'u1', 'u2', 'u4', 'u8'], - [N.int8, N.int16, N.int32, N.int64, - N.uint8, N.uint16, N.uint32, N.uint64]) + [np.int8, np.int16, np.int32, np.int64, + np.uint8, np.uint16, np.uint32, np.uint64]) for dt1, dt2 in dts: assert_equal(iinfo(dt1).min, iinfo(dt2).min) assert_equal(iinfo(dt1).max, iinfo(dt2).max) self.assertRaises(ValueError, iinfo, 'f4') def check_unsigned_max(self): - types = N.sctypes['uint'] + types = np.sctypes['uint'] for T in types: assert_equal(iinfo(T).max, T(-1)) diff --git a/tests/test_polynomial.py b/tests/test_polynomial.py index c9a230775..17d22e10e 100644 --- a/tests/test_polynomial.py +++ b/tests/test_polynomial.py @@ -74,22 +74,22 @@ poly1d([ 2.]) """ from numpy.testing import * -import numpy as N +import numpy as np class TestDocs(NumpyTestCase): def check_doctests(self): return self.rundocs() def check_roots(self): - assert_array_equal(N.roots([1,0,0]), [0,0]) + assert_array_equal(np.roots([1,0,0]), [0,0]) def check_str_leading_zeros(self): - p = N.poly1d([4,3,2,1]) + p = np.poly1d([4,3,2,1]) p[3] = 0 assert_equal(str(p), " 2\n" "3 x + 2 x + 1") - p = N.poly1d([1,2]) + p = np.poly1d([1,2]) p[0] = 0 p[1] = 0 assert_equal(str(p), " \n0") |