def inner(a, b): """Computes an inner product of two arrays. Ordinary inner product of vectors for 1-D arrays (without complex conjugation). Parameters ---------- a, b : array_like If *a* and *b* are nonscalar, their shape must match. Returns ------- out : ndarray out.shape = a.shape[:-1] + b.shape[:-1] Restriction ----------- If *a* or *b* is not 1-D array : *NotImplementedError* occurs. Note ---- For vectors (1-D arrays) it computes the ordinary inner-product:: import nlcpy as vp vp.inner(a, b) # equivalent to sum(a[:]*b[:]) if *a* or *b* is scalar, in which case:: vp.inner(a, b) # equivalent to a*b See Also -------- dot : Computes a dot product of two arrays. Examples -------- Ordinary inner product for vectors: >>> import nlcpy as vp >>> a = vp.array([1,2,3]) >>> b = vp.array([0,1,0]) >>> vp.inner(a, b) array(2) An example where b is a scalar: >>> vp.inner(vp.eye(2), 7) array([[7., 0.], [0., 7.]]) """ a = nlcpy.asanyarray(a) b = nlcpy.asanyarray(b) if a.ndim == 0 or b.ndim == 0: return ufunc_op.multiply(a, b) elif a.ndim == 1 and b.ndim == 1: return cblas_wrapper.cblas_dot(a, b) else: raise NotImplementedError("Only 1-D array is supported.")
def broadcast_to(array, shape, subok=False): """Broadcasts an array to a new shape. Parameters ---------- array : array_like The array to broadcast. shape : sequence of ints The shape of the desired array. subok : bool, optional Not implemented. Returns ------- broadcast : ndarray A readonly view on the original array with the given shape. It is typically not contiguous. Furthermore, more than one element of a broadcasted array may refer to a single memory location. Examples -------- >>> import nlcpy as vp >>> x = vp.array([1, 2, 3]) >>> vp.broadcast_to(x, (3, 3)) array([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) """ if subok: raise NotImplementedError('subok in broadcast_to is not implemented yet.') array = nlcpy.asanyarray(array) return core.broadcast_to(array, shape)
def tril(m, k=0): """Lower triangle of an array. Returns a copy of an array with elements above the *k*-th diagonal zeroed. Parameters ---------- m : array_like Input array. k : int, optional Diagonal above which to zero elements. *k* = 0 (the default) is the main diagonal, *k* < 0 is below it and *k* > 0 is above. Returns ------- tri : ndarray Lower triangle of *m*, of same shape and data-type as *m*. See Also -------- triu : Upper triangle of an array. Examples -------- >>> import nlcpy as vp >>> vp.tril([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], -1) array([[ 0, 0, 0], [ 4, 0, 0], [ 7, 8, 0], [10, 11, 12]]) """ m = nlcpy.asanyarray(m) mask = nlcpy.tri(*m.shape[-2:], k=k, dtype=bool) return nlcpy.where(mask, m, numpy.dtype(m.dtype).type(0))
def shape(a): """Returns the shape of an array. Parameters ---------- a : array_like Input array. Returns ------- shape : tuple of ints The elements of the shape tuple give the lengths of the corresponding array dimensions. See Also -------- ndarray.shape : Equivalent the array attribute. Examples -------- >>> import nlcpy as vp >>> vp.shape(vp.eye(3)) (3, 3) >>> vp.shape([[1, 2]]) (1, 2) >>> vp.shape([0]) (1,) >>> vp.shape(0) () """ a = nlcpy.asanyarray(a) return a.shape
def vstack(tup): """Stacks arrays in sequence vertically (row wise). This is equivalent to concatenation along the first axis after 1-D arrays of shape (N,) have been reshaped to (1,N). Rebuilds arrays divided by vsplit. This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis). The functions concatenate, stack and block provide more general stacking and concatenation operations. Parameters ---------- tup : sequence of array_like The arrays must have the same shape along all but the first axis. 1-D arrays must have the same length. Returns ------- stacked : `ndarray` The array formed by stacking the given arrays, will be at least 2-D. See Also -------- stack : Joins a sequence of arrays along a new axis. hstack : Stacks arrays in sequence horizontally (column wise). concatenate : Joins a sequence of arrays along an existing axis. Examples -------- >>> import nlcpy as vp >>> a = vp.array([1, 2, 3]) >>> b = vp.array([2, 3, 4]) >>> vp.vstack((a,b)) array([[1, 2, 3], [2, 3, 4]]) >>> a = vp.array([[1], [2], [3]]) >>> b = vp.array([[2], [3], [4]]) >>> vp.vstack((a,b)) array([[1], [2], [3], [2], [3], [4]]) """ if hasattr(tup, '__iter__'): arrays = [] for array in tup: array = nlcpy.asanyarray(array) if array.ndim < 2: array = array.reshape([1, array.size]) arrays.append(array) else: arrays = tup return manipulation._ndarray_concatenate(arrays, 0, None)
def append(arr, values, axis=None): """Appends values to the end of an array. Parameters ---------- arr : array_like Values are appended to a copy of this array. values : array_like These values are appended to a copy of arr. It must be of the correct shape (the same shape as arr, excluding axis). If axis is not specified, values can be any shape and will be flattened before use. axis : int, optional The axis along which values are appended. If axis is not given, both arr and values are flattened before use. Returns ------- append : ndarray A copy of arr with values appended to axis. Note that append does not occur in-place: a new array is allocated and filled. If axis is None, out is a flattened array. See Also -------- insert : Inserts values along the given axis before the given indices. delete : Returns a new array with sub-arrays along an axis deleted. Examples -------- >>> import nlcpy as vp >>> vp.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]) array([1, 2, 3, 4, 5, 6, 7, 8, 9]) When axis is specified, values must have the correct shape. >>> vp.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0) array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> vp.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0) # doctest: +SKIP Traceback (most recent call last): ... ValueError: all the input arrays must have same number of dimensions """ arr = nlcpy.asanyarray(arr) if axis is None: if arr.ndim != 1: arr = arr.ravel() values = nlcpy.ravel(values) axis = arr.ndim - 1 return nlcpy.concatenate((arr, values), axis=axis)
def copy(a, order='K', subok=False): """Returns an array copy of the given object. Parameters ---------- a : array_like Input data. order : {'C', 'F', 'A', 'K'}, optional Controls the memory layout of the copy. 'C' means C-order, 'F' means F-order, 'A' means 'F' if *a* is Fortran contiguous, 'C' otherwise. 'K' means match the layout of *a* as closely as possible. (Note that this function and :func:`ndarray.copy` are very similar, but have different default values for their order= arguments.) subok : bool, optional If True, then sub-classes will be passed-through, otherwise the returned array will be forced to be a base-class array (defaults to False). Returns ------- arr : ndarray Array interpretation of *a*. Note ---- This is equivalent to: >>> import nlcpy as vp >>> a = vp.array([1, 2, 3]) >>> vp.array(a, copy=True) array([1, 2, 3]) Examples -------- Create an array x, with a reference y and a copy z: >>> import nlcpy as vp >>> x = vp.array([1, 2, 3]) >>> y = x >>> z = vp.copy(x) Note that when we modify x, y changes, but not z: >>> x[0] = 10 >>> x[0] == y[0] array(True) >>> x[0] == z[0] array(False) """ if subok is not False: raise NotImplementedError('subok in array is not implemented yet.') a = nlcpy.asanyarray(a) return a.copy(order=order)
def vsplit(ary, indices_or_sections): """Splits an array into multiple sub-arrays vertically (row-wise). Please refer to the :func:`split` documentation. vsplit is equivalent to :func:`split` with ``axis=0`` (default), the array is always split along the first axis regardless of the array dimension. See Also -------- split : Splits an array into multiple sub-arrays. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(16.0).reshape(4, 4) >>> x array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.]]) >>> vp.vsplit(x, 2) [array([[0., 1., 2., 3.], [4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.], [12., 13., 14., 15.]])] >>> z1, z2, z3 = vp.vsplit(x, vp.array([3, 6])) >>> z1; z2; z3; array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]]) array([[12., 13., 14., 15.]]) array([], shape=(0, 4), dtype=float64) With a higher dimensional array the split is still along the first axis. >>> x = vp.arange(8.0).reshape(2, 2, 2) >>> x array([[[0., 1.], [2., 3.]], <BLANKLINE> [[4., 5.], [6., 7.]]]) >>> vp.vsplit(x, 2) [array([[[0., 1.], [2., 3.]]]), array([[[4., 5.], [6., 7.]]])] """ ary = nlcpy.asanyarray(ary) if ary.ndim < 2: raise ValueError('vsplit only works on arrays of 2 or more dimensions') return split(ary, indices_or_sections, 0)
def atleast_1d(*arys): """Converts inputs to arrays with at least one dimension. Scalar inputs are converted to 1-dimensional arrays, whilst higher-dimensional inputs are preserved. Parameters ---------- arys1, arys2, ... : array_like One or more input arrays. Returns ------- ret : ndarrays An array, or list of arrays, each with ``ndim >= 1``. Copies are made only if necessary. See Also -------- atleast_2d : Views inputs as arrays with at least two dimensions. atleast_3d : Views inputs as arrays with at least three dimensions. Examples -------- >>> import nlcpy as vp >>> vp.atleast_1d(1.0) array([1.]) >>> x = vp.arange(9.0).reshape(3,3) >>> vp.atleast_1d(x) array([[0., 1., 2.], [3., 4., 5.], [6., 7., 8.]]) >>> vp.atleast_1d(x) is x True >>> vp.atleast_1d(1, [3, 4]) [array([1]), array([3, 4])] """ res = [] for ary in arys: ary = nlcpy.asanyarray(ary) if ary.ndim == 0: res.append(ary.reshape(1)) else: res.append(ary) if len(res) == 1: return res[0] else: return res
def flipud(m): """Flips array in the up/down direction. Flip the entries in each column in the up/down direction. Rows are preserved, but appear in a different order than before. Parameters ---------- m : array_like Input array. Returns ------- out : `ndarray` A view of *m* with the rows reversed. Since a view is returned, this operation is done in constant time. Note ---- Equivalent to ``m[::-1,...]``. Does not require the array to be two-dimensional. See Also -------- fliplr : Flips array in the left/right direction. Examples -------- >>> import nlcpy as vp >>> A = vp.diag([1.0, 2, 3]) >>> A array([[1., 0., 0.], [0., 2., 0.], [0., 0., 3.]]) >>> vp.flipud(A) array([[0., 0., 3.], [0., 2., 0.], [1., 0., 0.]]) >>> A = vp.random.randn(2, 3, 5) >>> vp.all(vp.flipud(A) == A[::-1, ...]) array(True) >>> vp.flipud([1,2]) array([2, 1]) """ m = nlcpy.asanyarray(m) if m.ndim < 1: raise ValueError("Input must be >= 1-d.") return m[::-1, ...]
def atleast_2d(*arys): """Views inputs as arrays with at least two dimensions. Parameters ---------- arys1, arys2, ... : array_like One or more array-like sequences. Non-array inputs are converted to arrays. Arrays that already have two or more dimensions are preserved. Returns ------- res1, res2, ... : ndarray An array, or list of arrays, each with ``ndim >= 2``. Copies are avoided where possible, and views with two or more dimensions are returned. See Also -------- atleast_1d : Converts inputs to arrays with at least one dimension. atleast_3d : Views inputs as arrays with at least three dimensions. Examples -------- >>> import nlcpy as vp >>> vp.atleast_2d(3.0) array([[3.]]) >>> x = vp.arange(3.0) >>> vp.atleast_2d(x) array([[0., 1., 2.]]) >>> vp.atleast_2d(x).base is x True >>> vp.atleast_2d(1, [1, 2], [[1, 2]]) [array([[1]]), array([[1, 2]]), array([[1, 2]])] """ res = [] for ary in arys: ary = nlcpy.asanyarray(ary) if ary.ndim == 0: res.append(ary.reshape(1, 1)) elif ary.ndim == 1: res.append(ary[nlcpy.newaxis, :]) else: res.append(ary) if len(res) == 1: return res[0] else: return res
def fliplr(m): """Flips array in the left/right direction. Flip the entries in each row in the left/right direction. Columns are preserved, but appear in a different order than before. Parameters ---------- m : array_like Input array, must be at least 2-D. Returns ------- out : ndarray A view of *m* with the columns reversed. Since a view is returned, this operation is done in constant time. Note ---- Equivalent to ``m[:,::-1]``. Requires the array to be at least 2-D. See Also -------- flipud : Flips array in the up/down direction. Examples -------- >>> import nlcpy as vp >>> A = vp.diag([1., 2., 3.]) >>> A array([[1., 0., 0.], [0., 2., 0.], [0., 0., 3.]]) >>> vp.fliplr(A) array([[0., 0., 1.], [0., 2., 0.], [3., 0., 0.]]) >>> A = vp.random.randn(2, 3, 5) >>> vp.all(vp.fliplr(A) == A[:, ::-1, ...]) array(True) """ m = nlcpy.asanyarray(m) if m.ndim < 2: raise ValueError("Input must be >= 2-d.") return m[:, ::-1]
def transpose(a, axes=None): """Permutes the dimensions of an array. Parameters ---------- a : array_like Input array. axes : list of ints, optional By default, reverse the dimensions, otherwise permute the axes according to the values given. Returns ------- p : ndarray *a* with its axes permuted. A view is returned whenever possible. Note ---- Use `transpose(a, argsort(axes))` to invert the transposition of tensors when using the `axes` keyword argument. Transposing a 1-D array returns an unchanged view of the original array. See Also -------- moveaxis : Moves axes of an array to new positions. argsort : Returns the indices that would sort an array. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(4).reshape((2,2)) >>> x array([[0, 1], [2, 3]]) >>> vp.transpose(x) array([[0, 2], [1, 3]]) >>> x = vp.ones((1, 2, 3)) >>> vp.transpose(x, (1, 0, 2)).shape (2, 1, 3) """ a = nlcpy.asanyarray(a) return a.transpose(axes)
def hsplit(ary, indices_or_sections): """Splits an array into multiple sub-arrays horizontally (column-wise). Please refer to the :func:`split` documentation. hsplit is equivalent to :func:`split` with ``axis=1``, the array is always split along the second axis regardless of the array dimension. See Also -------- split : Splits an array into multiple sub-arrays. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(16.0).reshape(4, 4) >>> x array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.]]) >>> vp.hsplit(x, 2) [array([[ 0., 1.], [ 4., 5.], [ 8., 9.], [12., 13.]]), array([[ 2., 3.], [ 6., 7.], [10., 11.], [14., 15.]])] >>> vp.hsplit(x, vp.array([3, 6])) [array([[ 0., 1., 2.], [ 4., 5., 6.], [ 8., 9., 10.], [12., 13., 14.]]), array([[ 3.], [ 7.], [11.], [15.]]), array([], shape=(4, 0), dtype=float64)] """ ary = nlcpy.asanyarray(ary) if ary.ndim == 0: raise ValueError('hsplit only works on arrays of 1 or more dimensions') if ary.ndim > 1: return split(ary, indices_or_sections, 1) else: return split(ary, indices_or_sections, 0)
def moveaxis(a, source, destination): """Moves axes of an array to new positions. Other axes remain in their original order. Parameters ---------- a : ndarray The array whose axes should be reordered. source : int or sequence of ints Original positions of the axes to move. These must be unique. destination : int or sequence of ints Destination positions for each of the original axes. These must also be unique. Returns ------- result : ndarray Array with moved axes. This array is a view of the input array. See Also -------- transpose : Permutes the dimensions of an array. Examples -------- >>> import nlcpy as vp >>> x = vp.zeros((3, 4, 5)) >>> vp.moveaxis(x, 0, -1).shape (4, 5, 3) >>> vp.moveaxis(x, -1, 0).shape (5, 3, 4) # These all achieve the same result: >>> vp.transpose(x).shape (5, 4, 3) >>> vp.moveaxis(x, [0, 1], [-1, -2]).shape (5, 4, 3) >>> vp.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape (5, 4, 3) """ a = nlcpy.asanyarray(a) return manipulation._moveaxis(a, source, destination)
def rollaxis(a, axis, start=0): """Rolls the specified axis backwards, until it lies in a given position. This function is implemented for backward compatibility of numpy. You should use :func:`moveaxis`. Parameters ---------- a : ndarray Input array. axis : int The axis to roll backwards. The positions of the other axes do not change relative to one another. start : int, optional The axis is rolled until it lies before this position. The default, 0, results in a "complete" roll. Returns ------- res : ndarray Array with moved axes. This array is a view of the input array. See Also -------- moveaxis : Moves axes of an array to new positions. Examples -------- >>> import nlcpy as vp >>> a = vp.ones((3,4,5,6)) >>> vp.rollaxis(a, 3, 1).shape (3, 6, 4, 5) >>> vp.rollaxis(a, 2).shape (5, 3, 4, 6) >>> vp.rollaxis(a, 1, 4).shape (3, 5, 6, 4) """ a = nlcpy.asanyarray(a) if isinstance(axis, numpy.ndarray) or isinstance(axis, nlcpy.ndarray): axis = int(axis) return manipulation._rollaxis(a, axis, start=start)
def repeat(a, repeats, axis=None): """Repeats elements of an array. Parameters ---------- a : array_like Input array. repeats : int or sequence of ints The number of repetitions for each element. *repeats* is broadcasted to fit the shape of the given axis. axis : int, optional The axis along which to repeat values. By default, use the flattened input array, and return a flat output array. Returns ------- c : ndarray Output array which has the same shape as a, except along the given axis. See Also -------- tile : Constructs an array by repeating A the number of times given by reps. Examples -------- >>> import nlcpy as vp >>> vp.repeat(3, 4) array([3, 3, 3, 3]) >>> x = vp.array([[1, 2], [3, 4]]) >>> vp.repeat(x, 2) array([1, 1, 2, 2, 3, 3, 4, 4]) >>> vp.repeat(x, 3, axis=1) array([[1, 1, 1, 2, 2, 2], [3, 3, 3, 4, 4, 4]]) >>> vp.repeat(x, [1, 2], axis=0) array([[1, 2], [3, 4], [3, 4]]) """ a = nlcpy.asanyarray(a) return a.repeat(repeats, axis)
def swapaxes(a, axis1, axis2): """ Interchanges two axes of an array. Parameters ---------- a : array_like Input array. axis1 : int First axis. axis2 : int Second axis. Returns ------- a_swapped : ndarray If *a* is an ndarray, then a view of *a* is returned; otherwise a new array is created. Examples -------- >>> import nlcpy as vp >>> x = vp.array([[1, 2, 3]]) >>> vp.swapaxes(x, 0, 1) array([[1], [2], [3]]) >>> x = vp.array([[[0,1],[2,3]],[[4,5],[6,7]]]) >>> x array([[[0, 1], [2, 3]], <BLANKLINE> [[4, 5], [6, 7]]]) >>> vp.swapaxes(x,0,2) array([[[0, 4], [2, 6]], <BLANKLINE> [[1, 5], [3, 7]]]) """ a = nlcpy.asanyarray(a) return a.swapaxes(axis1, axis2)
def squeeze(a, axis=None): """Removes single-dimensional entries from the shape of an array. Parameters ---------- a : array_like Input data. axis : None or int or tuple of ints, optional Selects a subset of the single-dimensional entries in the shape. If an axis is selected with shape entry greater than one, an error is raised. Returns ------- squeezed : ndarray The input array, but with all or a subset of the dimensions of length 1 removed. This is always *a* itself or a view into *a*. See Also -------- expand_dims : Expands the shape of an array. reshape : Gives a new shape to an array without changing its data. Examples -------- >>> import nlcpy as vp >>> x = vp.array([[[0], [1], [2]]]) >>> x.shape (1, 3, 1) >>> vp.squeeze(x).shape (3,) >>> vp.squeeze(x, axis=0).shape (3, 1) >>> vp.squeeze(x, axis=1).shape # doctest: +SKIP Traceback (most recent call last): ... ValueError: cannot select an axis to squeeze out which has size not equal to one >>> vp.squeeze(x, axis=2).shape (1, 3) """ a = nlcpy.asanyarray(a) return a.squeeze(axis)
def triu(m, k=0): """Upper triangle of an array. Returns a copy of a matrix with the elements below the *k*-th diagonal zeroed. Please refer to the documentation for tril for further details. See Also -------- tril : Lower triangle of an array. Examples -------- >>> import nlcpy as vp >>> vp.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], -1) array([[ 1, 2, 3], [ 4, 5, 6], [ 0, 8, 9], [ 0, 0, 12]]) """ m = nlcpy.asanyarray(m) mask = nlcpy.tri(*m.shape[-2:], k=k - 1, dtype=bool) return nlcpy.where(mask, numpy.dtype(m.dtype).type(0), m)
def diagflat(v, k=0): """Creates a two-dimensional array with the flattened input as a diagonal. Parameters ---------- v : array_like Input data, which is flattened and set as the *k*-th diagonal of the output. k : int, optional Diagonal to set; 0, the default, corresponds to the "main" diagonal, a positive (negative) *k* giving the number of the diagonal above (below) the main. Returns ------- out : ndarray The 2-D output array. See Also -------- diag : Extracts a diagonal or construct a diagonal array. diagonal : Returns specified diagonals. Examples -------- >>> import nlcpy as vp >>> vp.diagflat([[1,2], [3,4]]) array([[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]]) >>> vp.diagflat([1,2], 1) array([[0, 1, 0], [0, 0, 2], [0, 0, 0]]) """ v = nlcpy.asanyarray(v).ravel() return diag(v, k)
def expand_dims(a, axis): """Expands the shape of an array. Insert a new axis that will appear at the *axis* position in the expanded array shape. Parameters ---------- a : array_like Input array. axis : int or tuple of ints Position in the expanded axes where the new axis is placed. Returns ------- res : ndarray View of *a* with the number of dimensions increased by one. See Also -------- squeeze : Removes single-dimensional entries from the shape of an array. reshape : Gives a new shape to an array without changing its data. Examples -------- >>> import nlcpy as vp >>> x = vp.array([1,2]) >>> x.shape (2,) The following is equivalent to x[vp.newaxis,:] or x[vp.newaxis]: >>> y = vp.expand_dims(x, axis=0) >>> y array([[1, 2]]) >>> y.shape (1, 2) >>> y = vp.expand_dims(x, axis=1) # Equivalent to x[:,vp.newaxis] >>> y array([[1], [2]]) >>> y.shape (2, 1) axis may also be a tuple: >>> y = vp.expand_dims(x, axis=(0, 1)) >>> y array([[[1, 2]]]) >>> y = vp.expand_dims(x, axis=(2, 0)) >>> y array([[[1], [2]]]) Note that some examples may use None instead of vp.newaxis. These are the same objects: >>> vp.newaxis is None True """ a = nlcpy.asanyarray(a) return core.manipulation._expand_dims(a, axis)
def dot(a, b, out=None): """Computes a dot product of two arrays. - If both *a* and *b* are 1-D arrays, it is inner product of vectors (without complex conjugation). - If both *a* and *b* are 2-D arrays, it is matrix multiplication, but using :func:`nlcpy.matmul` or ``a @ b`` is preferred. - If either *a* or *b* is 0-D (scalar), it is equivalent to multiply and using ``nlcpy.multiply(a,b)`` or ``a * b`` is preferred. - If *a* is an N-D array and *b* is a 1-D array, it is a sum product over the last axis of *a* and *b*. - If *a* is an N-D array and *b* is an M-D array (where ``M>=2``), it is a sum product over the last axis of *a* and the second-to-last axis of *b*: ``dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])`` Parameters ---------- a : array_like Input arrays or scalars. b : array_like Input arrays or scalars. out : ndarray, optional Output argument. This must have the exact kind that would be returned if it was not used. In particular, *out.dtype* must be the dtype that would be returned for *dot(a,b)*. Returns ------- output : ndarray Returns the dot product of *a* and *b*. If *a* and *b* are both scalars or both 1-D arrays then this function returns the result as a 0-dimention array. Examples -------- >>> import nlcpy as vp >>> vp.dot(3, 4) array(12) Neither argument is complex-conjugated: >>> vp.dot([2j, 3j], [2j, 3j]) array(-13.+0.j) For 2-D arrays it is the matrix product: >>> a = [[1, 0], [0, 1]] >>> b = [[4, 1], [2, 2]] >>> vp.dot(a,b) array([[4, 1], [2, 2]]) >>> a = vp.arange(3*4*5*6).reshape((3, 4, 5, 6)) >>> b = vp.arange(3*4*5*6)[::-1].reshape((5, 4, 6, 3)) >>> vp.dot(a, b)[2, 3, 2, 1, 2, 2] array(499128) >>> sum(a[2, 3, 2, :] * b[1, 2, :, 2]) array(499128) """ a = nlcpy.asanyarray(a) b = nlcpy.asanyarray(b) dtype_out = numpy.result_type(a.dtype, b.dtype) if out is not None: if not isinstance(out, nlcpy.ndarray): raise TypeError("'out' must be an array") if dtype_out != out.dtype: raise ValueError('output array is incorrect dtype') # if either a or b is 0-D array, it is equivalent to nlcpy.multiply if a.ndim == 0 or b.ndim == 0: return nlcpy.asanyarray(ufunc_op.multiply(a, b, out=out), order='C') # if both a and b are 1-D arrays, it is inner product of vectors if a.ndim == 1 and b.ndim == 1: return cblas_wrapper.cblas_dot(a, b, out=out) # if both a and b are 2-D arrays, it is matrix multiplication if a.ndim == 2 and b.ndim == 2: return cblas_wrapper.cblas_gemm(a, b, out=out, dtype=numpy.result_type( a.dtype, b.dtype)) # if either a or b are N-D array, it is sum product over the # last(or second-last) axis. if b.ndim > 1: if a.shape[-1] != b.shape[-2]: raise ValueError('mismatch input shape') shape_out = a.shape[:-1] + b.shape[:-2] + (b.shape[-1], ) else: if a.shape[-1] != b.shape[-1]: raise ValueError('mismatch input shape') shape_out = a.shape[:-1] if out is None: out = nlcpy.empty(shape_out, dtype=dtype_out) if out.dtype in (numpy.int8, numpy.int16, numpy.uint8, numpy.uint16, numpy.float16): raise TypeError('output dtype \'%s\' is not supported' % dtype_out) elif out.shape != shape_out or not out.flags.c_contiguous: raise ValueError( 'output array is not acceptable (must have the right datatype, ' 'number of dimensions, and be a C-Array)') out.fill(0) if a.size > 0 and b.size > 0: request._push_request( "nlcpy_dot", "linalg_op", (a, b, out), ) return out
def outer(a, b, out=None): """Computes an outer product of two vectors. Given two vectors, ``a = [a0, a1, ..., aM]`` and ``b = [b0, b1, ..., bN]``, the outer produce is:: [[a0*b0 a0*b1 ... a0*bN] [a1*b0 . ] [ ... . ] [aM*b0 aM*bN]] Parameters ---------- a : (M,) array_like First input vector. Input is flattened if not already 1-dimensional. b : (N,) array_like Second input vector. Input is flattened if not already 1-dimensional. out : (M, N) ndarray, optional A location where the result is stored. Returns ------- out : ndarray ``out[i, j] = a[i] * b[j]`` See Also -------- inner : Computes an inner product of two arrays. ufunc.outer : Applies the ufunc *op* to all pairs (a, b) with a in *A* and b in *B*. Examples -------- Make a (*very* coarse) grid for computing a Mandelbrot set: >>> import nlcpy as vp >>> rl = vp.outer(vp.ones((5,)), vp.linspace(-2, 2, 5)) >>> rl array([[-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.]]) >>> im = vp.outer(1j*vp.linspace(2, -2, 5), vp.ones((5,))) >>> im array([[0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j], [0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j], [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], [0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j], [0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]]) >>> grid = rl + im >>> grid array([[-2.+2.j, -1.+2.j, 0.+2.j, 1.+2.j, 2.+2.j], [-2.+1.j, -1.+1.j, 0.+1.j, 1.+1.j, 2.+1.j], [-2.+0.j, -1.+0.j, 0.+0.j, 1.+0.j, 2.+0.j], [-2.-1.j, -1.-1.j, 0.-1.j, 1.-1.j, 2.-1.j], [-2.-2.j, -1.-2.j, 0.-2.j, 1.-2.j, 2.-2.j]]) """ a = nlcpy.asanyarray(a) b = nlcpy.asanyarray(b) return nlcpy.multiply.outer(a.ravel(), b.ravel(), out=out, order='C')
def atleast_3d(*arys): """Views inputs as arrays with at least three dimensions. Parameters ---------- arys1, arys2, ... : array_like One or more array-like sequences. Non-array inputs are converted to arrays. Arrays that already have three or more dimensions are preserved. Returns ------- res1, res2, ... : ndarray An array, or list of arrays, each with ``ndim >= 3``. Copies are avoided where possible, and views with three or more dimensions are returned. For example, a 1-D array of shape ``(N,)`` becomes a view of shape ``(1, N, 1)``, and a 2-D array of shape ``(M, N)`` becomes a view of shape ``(M, N, 1)``. See Also -------- atleast_1d : Converts inputs to arrays with at least one dimension. atleast_2d : Views inputs as arrays with at least two dimensions. Examples -------- >>> import nlcpy as vp >>> vp.atleast_3d(3.0) array([[[3.]]]) >>> x = vp.arange(3.0) >>> vp.atleast_3d(x).shape (1, 3, 1) >>> x = vp.arange(12.0).reshape(4,3) >>> vp.atleast_3d(x).shape (4, 3, 1) >>> vp.atleast_3d(x).base is x.base # x is a reshape, so not base itself True >>> for arr in vp.atleast_3d([1, 2], [[1, 2]], [[[1, 2]]]): ... print(arr, arr.shape) # doctest: +SKIP ... [[[1] [2]]] (1, 2, 1) [[[1] [2]]] (1, 2, 1) [[[1 2]]] (1, 1, 2) """ res = [] for ary in arys: ary = nlcpy.asanyarray(ary) if ary.ndim == 0: res.append(ary.reshape(1, 1, 1)) elif ary.ndim == 1: res.append(ary[nlcpy.newaxis, :, nlcpy.newaxis]) elif ary.ndim == 2: res.append(ary[:, :, nlcpy.newaxis]) else: res.append(ary) if len(res) == 1: return res[0] else: return res
def unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None): """Finds the unique elements of an array. Returns the sorted unique elements of an array. There are three optional outputs in addition to the unique elements: - the indices of the input array that give the unique values - the indices of the unique array that reconstruct the input array - the number of times each unique value comes up in the input array Parameters ---------- ar : array_like Input array. Unless *axis* is specified, this will be flattened if it is not already 1-D. return_index : bool, optional If True, also return the indices of *ar* (along the specified axis, if provided, or in the flattened array) that result in the unique array. return_inverse : bool, optional If True, also return the indices of the unique array (for the specified axis, if provided) that can be used to reconstruct *ar*. return_counts : bool, optional If True, also return the number of times each unique item appears in *ar*. axis : int or None, optional The axis to operate on. If None, *ar* will be flattened. If an integer, the subarrays indexed by the given axis will be flattened and treated as the elements of a 1-D array with the dimension of the given axis, see the notes for more details. Object arrays or structured arrays that contain objects are not supported if the *axis* kwarg is used. The default is None. Returns ------- unique : ndarray The sorted unique values. unique_indices : ndarray, optional The indices of the first occurrences of the unique values in the original array. Only provided if *return_index* is True. unique_inverse : ndarray, optional The indices to reconstruct the original array from the unique array. Only provided if *return_inverse* is True. unique_count : ndarray, optional The number of times each of the unique values comes up in the original array. Only provided if *return_counts* is True. Restriction ----------- *NotImplementedError*: - If 'c' is contained in *ar.dtype.kind*. Note ---- When an axis is specified the subarrays indexed by the axis are sorted. This is done by making the specified axis the first dimension of the array and then flattening the subarrays in C order. The flattened subarrays are then viewed as a structured type with each element given a label, with the effect that we end up with a 1-D array of structured types that can be treated in the same way as any other 1-D array. The result is that the flattened subarrays are sorted in lexicographic order starting with the first element. Examples -------- >>> import nlcpy as vp >>> vp.unique([1, 1, 2, 2, 3, 3]) array([1, 2, 3]) >>> a =vp.array([[1, 1], [2, 3]]) >>> vp.unique(a) array([1, 2, 3]) Return the unique rows of a 2D array >>> a = vp.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]]) >>> vp.unique(a, axis=0) array([[1, 0, 0], [2, 3, 4]]) Return the indices of the original array that give the unique values: >>> a = vp.array([1, 2, 2, 3, 1]) >>> u, indices = vp.unique(a, return_index=True) >>> u array([1, 2, 3]) >>> indices array([0, 1, 3]) >>> a[indices] array([1, 2, 3]) Reconstruct the input array from the unique values: >>> a = vp.array([1, 2, 6, 4, 2, 3, 2]) >>> u, indices = vp.unique(a, return_inverse=True) >>> u array([1, 2, 3, 4, 6]) >>> indices array([0, 1, 4, 3, 1, 2, 1]) >>> u[indices] array([1, 2, 6, 4, 2, 3, 2]) """ ar = nlcpy.asanyarray(ar) if axis is not None: if axis < 0: axis = axis + ar.ndim if axis < 0 or axis >= ar.ndim: raise AxisError('Axis out of range') if ar.ndim > 1 and axis is not None: if ar.size == 0: if axis is None: shape = () else: shape = list(ar.shape) shape[axis] = int(shape[axis] / 2) return nlcpy.empty(shape, dtype=ar.dtype) ar = nlcpy.moveaxis(ar, axis, 0) orig_shape = ar.shape ar = ar.reshape(orig_shape[0], -1) aux = nlcpy.array(ar) perm = nlcpy.empty(ar.shape[0], dtype='l') request._push_request( 'nlcpy_sort_multi', 'sorting_op', (ar, aux, perm, return_index) ) mask = nlcpy.empty(aux.shape[0], dtype='?') mask[0] = True mask[1:] = nlcpy.any(aux[1:] != aux[:-1], axis=1) ret = aux[mask] ret = ret.reshape(-1, *orig_shape[1:]) ret = nlcpy.moveaxis(ret, 0, axis) else: ar = ar.flatten() if return_index or return_inverse: perm = ar.argsort(kind='stable' if return_index else None) aux = ar[perm] else: ar.sort() aux = ar mask = nlcpy.empty(aux.shape[0], dtype='?') if mask.size: mask[0] = True mask[1:] = aux[1:] != aux[:-1] ret = aux[mask] if not return_index and not return_inverse and not return_counts: return ret ret = (ret,) if return_index: ret += (perm[mask],) if return_inverse: imask = nlcpy.cumsum(mask) - 1 inv_idx = nlcpy.empty(mask.shape, dtype=nlcpy.intp) inv_idx[perm] = imask ret += (inv_idx,) if return_counts: nonzero = nlcpy.nonzero(mask)[0] idx = nlcpy.empty((nonzero.size + 1,), nonzero.dtype) idx[:-1] = nonzero idx[-1] = mask.size ret += (idx[1:] - idx[:-1],) return ret
def stack(arrays, axis=0, out=None): """Joins a sequence of arrays along a new axis. The axis parameter specifies the index of the new axis in the dimensions of the result. For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension. Parameters ---------- arrays : sequence of array_like Each array must have the same shape. axis : int, optional The axis in the result array along which the input arrays are stacked. out : `ndarray`, optional If provided, the destination to place the result. The shape must be correct, matching that of what stack would have returned if no out argument were specified. Returns ------- stacked : ndarray The stacked array has one more dimension than the input arrays. See Also -------- concatenate : Joins a sequence of arrays along an existing axis. Examples -------- >>> import nlcpy as vp >>> arrays = [vp.random.randn(3, 4) for _ in range(10)] >>> vp.stack(arrays, axis=0).shape (10, 3, 4) >>> vp.stack(arrays, axis=1).shape (3, 10, 4) >>> vp.stack(arrays, axis=2).shape (3, 4, 10) >>> a = vp.array([1, 2, 3]) >>> b = vp.array([2, 3, 4]) >>> vp.stack((a, b)) array([[1, 2, 3], [2, 3, 4]]) >>> vp.stack((a, b), axis=-1) array([[1, 2], [2, 3], [3, 4]]) """ arrays = [nlcpy.asanyarray(arr) for arr in arrays] if not arrays: raise ValueError('need at least one array to stack') shapes = {arr.shape for arr in arrays} if len(shapes) != 1: raise ValueError('all input arrays must have the same shape') if isinstance(axis, numpy.ndarray) or isinstance(axis, nlcpy.ndarray): axis = int(axis) elif not isinstance(axis, int): raise TypeError("an integer is required (got type {})" .format(type(axis).__name__)) result_ndim = arrays[0].ndim + 1 if axis >= result_ndim or axis < -result_ndim: raise numpy.AxisError("axis {} is out of bounds for array of dimension {}" .format(axis, result_ndim)) axis = axis if axis >= 0 else result_ndim + axis sl = (slice(None),) * axis + (None,) expanded_arrays = [arr[sl] for arr in arrays] return nlcpy.concatenate(expanded_arrays, axis=axis, out=out)
def zeros_like(a, dtype=None, order='K', subok=False, shape=None): """Returns an array of zeros with the same shape and type as a given array. Parameters ---------- a : array_like The shape and dtype of *a* define these same attributes of the returned array. dtype : dtype, optional Overrides the data type of the result. order : {'C', 'F', 'A', or 'K'}, optional Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order, 'A' means 'F' if *a* is Fortran contiguous, 'C' otherwise. 'K' means match the layout of *a* as closely as possible. subok : bool, optional Not implemented. shape : int or sequence of ints, optional Overrides the shape of the result. If order='K' and the number of dimensions is unchanged, will try to keep order, otherwise, order='C' is implied. Returns ------- out : ndarray Array of zeros with the same shape and type as *a*. See Also -------- empty_like : Returns a new array with the same shape and type as a given array. ones_like : Returns an array of ones with the same shape and type as a given array. full_like : Returns a full array with the same shape and type as a given array. zeros : Returns a new array of given shape and type, filled with zeros. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(6) >>> x = x.reshape((2, 3)) >>> x array([[0, 1, 2], [3, 4, 5]]) >>> vp.zeros_like(x) array([[0, 0, 0], [0, 0, 0]]) >>> y = vp.arange(3, dtype=float) >>> y array([0., 1., 2.]) >>> vp.zeros_like(y) array([0., 0., 0.]) """ if subok is not False: raise NotImplementedError( 'subok in zeros_like is not implemented yet.') a = nlcpy.asanyarray(a) if shape is None: shape = a.shape if dtype is None: dtype = a.dtype if numpy.dtype(dtype).kind == 'V': raise NotImplementedError( 'void dtype in zeros_like is not implemented yet.') if order is None or order in 'kKaA': if a._f_contiguous and not a._c_contiguous: order = 'F' else: order = 'C' out = nlcpy.ndarray(shape=shape, dtype=dtype, order=order) out.fill(0) return out
def empty_like(prototype, dtype=None, order='K', subok=False, shape=None): """Returns a new array with the same shape and type as a given array. Parameters ---------- prototype : array_like The shape and dtype of *prototype* define these same attributes of the returned array. dtype : dtype, optional Overrides the data type of the result. order : {'C', 'F'}, optional Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order, 'A' means 'F' if *prototype* is Fortran contiguous, 'C' otherwise. 'K' means match the layout of *prototype* as closely as possible. subok : bool, optional Not implemented. shape : int or sequence of ints, optional Overrides the shape of the result. If order='K' and the number of dimensions is unchanged, will try to keep order, otherwise, order='C' is implied. Returns ------- out : ndarray Array of uninitialized (arbitrary) data with the same shape and type as *prototype*. Note ---- This function does not initialize the returned array; to do that use :func:`zeros_like` or :func:`ones_like` instead. It may be marginally faster than the functions that do set the array values. See Also -------- ones_like : Returns an array of ones with the same shape and type as a given array. zeros_like : Returns an array of zeros with the same shape and type as a given array. full_like : Returns a full array with the same shape and type as a given array. empty : Returns a new array of given shape and type, without initializing entries. Examples -------- >>> import nlcpy as vp >>> a = ([1,2,3], [4,5,6]) # a is array-like >>> vp.empty_like(a) # doctest: +SKIP array([[0, 0, 0], [0, 0, 0]]) # uninitialized >>> a = vp.array([[1., 2., 3.],[4.,5.,6.]]) >>> vp.empty_like(a) # doctest: +SKIP array([[0., 0., 0.], [0., 0., 0.]]) # uninitialized """ if subok is not False: raise NotImplementedError( 'subok in empty_like is not implemented yet.') prototype = nlcpy.asanyarray(prototype) if shape is None: shape = prototype.shape if dtype is None: dtype = prototype.dtype if order is None or order in 'kKaA': if prototype._f_contiguous and not prototype._c_contiguous: order = 'F' else: order = 'C' if numpy.dtype(dtype).kind == 'V': raise NotImplementedError( 'void dtype in empty_like is not implemented yet.') out = nlcpy.ndarray(shape=shape, dtype=dtype, order=order) return out
def full_like(a, fill_value, dtype=None, order='K', subok=False, shape=None): """Returns a full array with the same shape and type as a given array. Parameters ---------- a : array_like The shape and dtype of *a* define these same attributes of the returned array. fill_value : scalar Fill value. dtype : dtype, optional Overrides the data type of the result. order : {'C', 'F', 'A', or 'K'}, optional Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order, 'A' means 'F' if *a* is Fortran contiguous, 'C' otherwise. 'K' means match the layout of *a* as closely as possible. subok : bool, optional Not implemented. shape : int or sequence of ints, optional Overrides the shape of the result. If order='K' and the number of dimensions is unchanged, will try to keep order, otherwise, order='C' is implied. Returns ------- out : ndarray Array of *fill_value* with the same shape and type as *a*. See Also -------- empty_like : Returns a new array with the same shape and type as a given array. ones_like : Returns an array of ones with the same shape and type as a given array. zeros_like : Returns an array of zeros with the same shape and type as a given array. full : Returns a new array of given shape and type, filled with fill_value. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(6, dtype=int) >>> vp.full_like(x, 1) array([1, 1, 1, 1, 1, 1]) >>> vp.full_like(x, 0.1) array([0, 0, 0, 0, 0, 0]) >>> vp.full_like(x, 0.1, dtype=vp.double) array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) >>> vp.full_like(x, vp.nan, dtype=vp.double) array([nan, nan, nan, nan, nan, nan]) >>> y = vp.arange(6, dtype=vp.double) >>> vp.full_like(y, 0.1) array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) """ if subok is not False: raise NotImplementedError('subok in full_like is not implemented yet.') a = nlcpy.asanyarray(a) if shape is None: shape = a.shape if dtype is None: dtype = a.dtype else: dtype = nlcpy.dtype(dtype) if numpy.dtype(dtype).kind == 'V': raise NotImplementedError( 'void dtype in full_like is not implemented yet.') if order is None or order in 'kKaA': if a._f_contiguous and not a._c_contiguous: order = 'F' else: order = 'C' if numpy.isscalar(fill_value): if numpy.iscomplex(fill_value): if dtype in ('complex64', 'complex128'): pass else: fill_value = numpy.real(fill_value) warnings.warn( 'Casting complex values to real discards the imaginary part', numpy.ComplexWarning, stacklevel=2) out = nlcpy.ndarray(shape=shape, dtype=dtype, order=order) out.fill(fill_value) elif fill_value is None: raise NotImplementedError('fill_value in nlcpy.full_like is None') else: fill_value = nlcpy.asarray(fill_value) out = nlcpy.array(nlcpy.broadcast_to(fill_value, shape=shape), dtype=dtype, order=order) return out