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
def insert(arr, obj, values, axis=None): """Inserts values along the given axis before the given indices. Parameters ---------- arr : array_like Input array. obj : int, slice or sequence of ints Object that defines the index or indices before which values is inserted. Support for multiple insertions when obj is a single scalar or a sequence with one element (similar to calling insert multiple times). values : array_like Values to insert into arr. If the type of values is different from that of arr, values is converted to the type of arr. values should be shaped so that arr[...,obj,...] = values is legal. axis : int, optional Axis along which to insert values. If axis is None then arr is flattened first. Returns ------- out : ndarray A copy of arr with values inserted. Note that insert does not occur in-place: a new array is returned. If axis is None, out is a flattened array. Note: Note that for higher dimensional inserts obj=0 behaves very different from obj=[0] just like arr[:,0,:] = values is different from arr[:,[0],:] = values. See Also -------- append : Appends values to the end of an array. concatenate : Joins a sequence of arrays along an existing axis. delete : Returns a new array with sub-arrays along an axis deleted. Examples -------- >>> import nlcpy as vp >>> from nlcpy import testing >>> a = vp.array([[1, 1], [2, 2], [3, 3]]) >>> a array([[1, 1], [2, 2], [3, 3]]) >>> vp.insert(a, 1, 5) array([1, 5, 1, 2, 2, 3, 3]) >>> vp.insert(a, 1, 5, axis=1) array([[1, 5, 1], [2, 5, 2], [3, 5, 3]]) Difference between sequence and scalars: >>> vp.insert(a, [1], [[1],[2],[3]], axis=1) array([[1, 1, 1], [2, 2, 2], [3, 3, 3]]) >>> vp.testing.assert_array_equal( ... vp.insert(a, 1, [1, 2, 3], axis=1), ... vp.insert(a, [1], [[1],[2],[3]], axis=1)) >>> b = a.flatten() >>> b array([1, 1, 2, 2, 3, 3]) >>> vp.insert(b, [2, 2], [5, 6]) array([1, 1, 5, 6, 2, 2, 3, 3]) >>> vp.insert(b, slice(2, 4), [5, 6]) array([1, 1, 5, 2, 6, 2, 3, 3]) >>> vp.insert(b, [2, 2], [7.13, False]) # type casting array([1, 1, 7, 0, 2, 2, 3, 3]) >>> x = vp.arange(8).reshape(2, 4) >>> idx = (1, 3) >>> vp.insert(x, idx, 999, axis=1) array([[ 0, 999, 1, 2, 999, 3], [ 4, 999, 5, 6, 999, 7]]) """ a = nlcpy.asarray(arr) if axis is None: if a.ndim != 1: a = a.ravel() axis = 0 elif isinstance(axis, nlcpy.ndarray) or isinstance(axis, numpy.ndarray): axis = int(axis) elif not isinstance(axis, int): raise TypeError("an integer is required " "(got type {0})".format(type(axis).__name__)) if axis < -a.ndim or axis >= a.ndim: raise nlcpy.AxisError( "axis {0} is out of bounds for array of dimension {1}".format(axis, a.ndim)) if axis < 0: axis += a.ndim if type(obj) is slice: start, stop, step = obj.indices(a.shape[axis]) obj = nlcpy.arange(start, stop, step) else: obj = nlcpy.array(obj) if obj.dtype.char == '?': warnings.warn( "in the future insert will treat boolean arrays and " "array-likes as a boolean index instead of casting it to " "integer", FutureWarning, stacklevel=3) elif obj.dtype.char in 'fdFD': if obj.size == 1: raise TypeError( "slice indices must be integers or " "None or have an __index__ method") elif obj.size > 0: raise IndexError( 'arrays used as indices must be of integer (or boolean) type') elif obj.dtype.char in 'IL': if obj.size == 1: objval = obj[()] if obj.ndim == 0 else obj[0] if objval > a.shape[axis]: raise IndexError( "index {0} is out of bounds for axis {1} with size {2}".format( objval, axis, a.shape[axis])) else: tmp = 'float64' if obj.dtype.char == 'L' else 'int64' raise UFuncTypeError( "Cannot cast ufunc 'add' output from dtype('{0}') to " "dtype('{1}') with casting rule 'same_kind'".format(tmp, obj.dtype)) obj = obj.astype('l') if obj.ndim > 1: raise ValueError( "index array argument obj to insert must be one dimensional or scalar") if obj.ndim == 0: if obj > a.shape[axis] or obj < -a.shape[axis]: raise IndexError( "index {0} is out of bounds for axis {1} with size {2}".format( obj[()] if obj > 0 else obj[()] + a.shape[axis], axis, a.shape[axis])) newshape = list(a.shape) if obj.size == 1: values = nlcpy.array(values, copy=False, ndmin=a.ndim, dtype=a.dtype) if obj.ndim == 0: values = nlcpy.moveaxis(values, 0, axis) newshape[axis] += values.shape[axis] obj = nlcpy.array(nlcpy.broadcast_to(obj, values.shape[axis])) val_shape = list(a.shape) val_shape[axis] = values.shape[axis] values = nlcpy.broadcast_to(values, val_shape) else: newshape[axis] += obj.size values = nlcpy.array(values, copy=False, ndmin=a.ndim, dtype=a.dtype) val_shape = list(a.shape) val_shape[axis] = obj.size values = nlcpy.broadcast_to(values, val_shape) out = nlcpy.empty(newshape, dtype=a.dtype) work = nlcpy.zeros(obj.size + out.shape[axis] + 2, dtype='l') work[-1] = -1 request._push_request( 'nlcpy_insert', 'manipulation_op', (a, obj, values, out, axis, work) ) if work[-1] != -1: raise IndexError( "index {0} is out of bounds for axis {1} with size {2}" .format(obj[work[-1]], axis, out.shape[axis])) return out
def full(shape, fill_value, dtype=None, order='C'): """Returns a new array of given shape and type, filled with *fill_value*. Parameters ---------- shape : int or sequence of ints Shape of the new array, e.g., ``(2, 3)`` or ``2``. fill_value : scalar Fill value. dtype : dtype, optional The desired dtype for the array, e.g, ``nlcpy.int64``. Default is ``nlcpy.float64``. order : {'C', 'F'}, optional Whether to store multidimensional data in C- or Fortran-contiguous (row- or column-wise) order in memory. Returns ------- out : ndarray Array of *fill_value* with the given shape, dtype, and order. See Also -------- 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. ones : Returns a new array of given shape and type, filled with ones. zeros : Returns a new array of given shape and type, filled with zeros. Examples -------- >>> import nlcpy as vp >>> vp.full((2, 2), vp.inf) array([[inf, inf], [inf, inf]]) >>> vp.full((2, 2), 10) array([[10, 10], [10, 10]]) """ if numpy.dtype(dtype).kind == 'V': raise NotImplementedError('void dtype in full is not implemented yet.') if dtype is None: dtype = numpy.result_type(fill_value) else: dtype = nlcpy.dtype(dtype) 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 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
def meshgrid(*xi, **kwargs): """Returns coordinate matrices from coordinate vectors. Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given one-dimensional coordinate arrays x1, x2,..., xn. Parameters ---------- x1, x2, ..., xn : array_like 1-D arrays representing the coordinates of a grid. indexing : {'xy', 'ij'}, optional Cartesian ('xy', default) or matrix ('ij') indexing of output. See Notes for more details. sparse : bool, optional If True a sparse grid is returned in order to conserve memory. Default is False. copy : bool, optional If False, a view into the original arrays are returned in order to conserve memory. Default is True. Please note that ``sparse=False, copy=False`` will likely return non-contiguous arrays. Furthermore, more than one element of a broadcast array may refer to a single memory location. If you need to write to the arrays, make copies first. Returns ------- X1, X2, ..., XN : ndarray For vectors x1, x2, ..., 'xn' with lengths ``Ni=len(xi)``, return ``(N1, N2, N3, ..., Nn)`` shaped arrays if indexing='ij' or (N2, N1, N3, ..., Nn) shaped arrays if indexing='xy' with the elements of xi repeated to fill the matrix along the first dimension for x1, the second for x2 and so on. Note ---- This function supports both indexing conventions through the indexing keyword argument. Giving the string 'ij' returns a meshgrid with matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing. In the 2-D case with inputs of length M and N, the outputs are of shape (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case with inputs of length M, N and P, outputs are of shape (N, M, P) for 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is illustrated by the following code snippet:: import nlcpy as vp xv, yv = vp.meshgrid(x, y, sparse=False, indexing='ij') for i in range(nx): for j in range(ny): # treat xv[i,j], yv[i,j] xv, yv = vp.meshgrid(x, y, sparse=False, indexing='xy') for i in range(nx): for j in range(ny): # treat xv[j,i], yv[j,i] In the 1-D and 0-D case, the indexing and sparse keywords have no effect. Examples -------- >>> import nlcpy as vp >>> nx, ny = (3, 2) >>> x = vp.linspace(0, 1, nx) >>> y = vp.linspace(0, 1, ny) >>> xv, yv = vp.meshgrid(x, y) >>> xv array([[0. , 0.5, 1. ], [0. , 0.5, 1. ]]) >>> yv array([[0., 0., 0.], [1., 1., 1.]]) >>> xv, yv = vp.meshgrid(x, y, sparse=True) # make sparse output arrays >>> xv array([[0. , 0.5, 1. ]]) >>> yv array([[0.], [1.]]) meshgrid is very useful to evaluate functions on a grid. >>> import matplotlib.pyplot as plt >>> x = vp.arange(-5, 5, 0.1) >>> y = vp.arange(-5, 5, 0.1) >>> xx, yy = vp.meshgrid(x, y, sparse=True) >>> z = vp.sin(xx**2 + yy**2) / (xx**2 + yy**2) >>> h = plt.contourf(x,y,z) >>> plt.show() """ copy_ = kwargs.pop('copy', True) sparse = kwargs.pop('sparse', False) indexing = kwargs.pop('indexing', 'xy') if kwargs: raise TypeError("meshgrid() got an unexpected keyword argument '%s'" % (list(kwargs)[0], )) if indexing not in ['xy', 'ij']: raise ValueError("Valid values for `indexing` are 'xy' and 'ij'.") ndim = len(xi) s0 = (1, ) * ndim output = [ nlcpy.asanyarray(x).reshape(s0[:i] + (-1, ) + s0[i + 1:]) for i, x in enumerate(xi) ] if not sparse: shape = [output[i].shape[i] for i in range(len(output))] if indexing == 'xy' and ndim > 1: output[0].shape = (1, -1) + s0[2:] output[1].shape = (-1, 1) + s0[2:] if not sparse: shape[0], shape[1] = shape[1], shape[0] if not sparse: output = [nlcpy.broadcast_to(x, shape) for x in output] if copy_: output = [x.copy() for x in output] return output
def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0): """Returns evenly spaced numbers over a specified interval. Returns *num* evenly spaced samples, calculated over the interval ``[start, stop]``. The endpoint of the interval can optionally be excluded. Parameters ---------- start : array_like The starting value of the sequence. stop : array_like The end value of the sequence, unless *endpoint* is set to False. In that case, the sequence consists of all but the last of ``num + 1`` evenly spaced samples, so that *stop* is excluded. Note that the step size changes when *endpoint* is False. num : int, optional Number of samples to generate. Default is 50. Must be non-negative. endpoint : bool, optional If True, *stop* is the last sample. Otherwise, it is not included. Default is True. retstep : bool, optional If True, return (*samples*, *step*) where *step* is the spacing between samples. dtype : dtype, optional The type of the output array. If *dtype* is not given, infer the data type from the other input arguments. axis : int, optional The axis in the result to store the samples. Relevant only if start or stop are array-like. By default (0), the samples will be along a new axis inserted at the beginning. Use -1 to get an axis at the end. Returns ------- samples : ndarray There are *num* equally spaced samples in the closed interval ``[start, stop]`` or the half-open interval ``[start, stop)`` (depending on whether *endpoint* is True or False). step : float, optional Only returned if *retstep* is True Size of spacing between samples. See Also -------- arange : Returns evenly spaced values within a given interval. Examples -------- >>> import nlcpy as vp >>> vp.linspace(2.0, 3.0, num=5) array([2. , 2.25, 2.5 , 2.75, 3. ]) >>> vp.linspace(2.0, 3.0, num=5, endpoint=False) array([2. , 2.2, 2.4, 2.6, 2.8]) >>> vp.linspace(2.0, 3.0, num=5, retstep=True) (array([2. , 2.25, 2.5 , 2.75, 3. ]), array([0.25])) """ num = operator.index(num) if num < 0: raise ValueError("Number of samples, %s, must be non-negative." % num) dtype_kind = numpy.dtype(dtype).kind if dtype_kind == 'V': raise NotImplementedError( 'void dtype in linspace is not implemented yet.') start = nlcpy.asarray(start) stop = nlcpy.asarray(stop) dt = numpy.result_type(start, stop, float(num)) if start.dtype.char in '?iIlL' or stop.dtype.char in '?iIlL': dt = 'D' if dt.char in 'FD' else 'd' if dtype is None: dtype = dt start = nlcpy.asarray(start, dtype=dt) stop = nlcpy.asarray(stop, dtype=dt) delta = stop - start div = (num - 1) if endpoint else num if num == 0: ret = nlcpy.empty((num, ) + delta.shape, dtype=dtype) if retstep: ret = (ret, nlcpy.NaN) return ret elif div == 0 or num == 1: ret = nlcpy.resize(start, (1, ) + delta.shape).astype(dtype) if retstep: ret = (ret, stop) return ret else: ret = nlcpy.empty((num, ) + delta.shape, dtype=dtype) retdata = ret delta = delta[nlcpy.newaxis] start = nlcpy.array(nlcpy.broadcast_to(start, delta.shape)) stop = nlcpy.array(nlcpy.broadcast_to(stop, delta.shape)) step = delta / div if div > 1 else delta if retdata._memloc in {on_VE, on_VE_VH}: denormal = nlcpy.zeros(1, dtype='l') request._push_request( "nlcpy_linspace", "creation_op", (ret, start, stop, delta, step, int(endpoint), denormal)) if axis != 0: ret = nlcpy.moveaxis(ret, 0, axis) if retstep: ret = (ret, step) if retdata._memloc in {on_VH, on_VE_VH}: del retdata.vh_data del step.vh_data typ = numpy.dtype(dtype).type if retstep: (retdata.vh_data, step.vh_data) = numpy.linspace(typ(start), typ(stop), num, endpoint, typ(retstep), dtype, axis) else: retdata.vh_data = numpy.linspace(typ(start), typ(stop), num, endpoint, typ(retstep), dtype, axis) return ret
def solve(a, b): """Solves a linear matrix equation, or system of linear scalar equations. Computes the "exact" solution, *x*, of the well-determined, i.e., full rank, linear matrix equation :math:`ax = b`. Parameters ---------- a : (..., M, M) array_like Coefficient matrix. b : {(..., M,), (..., M, K)} array_like Ordinate or "dependent variable" values. Returns ------- x : {(..., M,), (..., M, K)} ndarray Solution to the system a x = b. Returned shape is identical to *b*. Note ---- The solutions are computed using LAPACK routine ``_gesv``. `a` must be square and of full-rank, i.e., all rows (or, equivalently, columns) must be linearly independent; if either is not true, use :func:`lstsq` for the least-squares best "solution" of the system/equation. Examples -------- Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``: >>> import nlcpy as vp >>> a = vp.array([[3,1], [1,2]]) >>> b = vp.array([9,8]) >>> x = vp.linalg.solve(a, b) >>> x array([2., 3.]) """ a = nlcpy.asarray(a) b = nlcpy.asarray(b) c_order = (a.flags.c_contiguous or a.ndim < 4 or a.ndim - b.ndim < 2 and b.flags.c_contiguous) and \ not (a.ndim < b.ndim and not b.flags.c_contiguous) util._assertRankAtLeast2(a) util._assertNdSquareness(a) if a.ndim - 1 == b.ndim: if a.shape[-1] != b.shape[-1]: raise ValueError( 'solve1: Input operand 1 has a mismatch in ' 'its core dimension 0, with gufunc signature (m,m),(m)->(m) ' '(size {0} is different from {1})'.format( b.shape[-1], a.shape[-1])) elif b.ndim == 1: raise ValueError( 'solve: Input operand 1 does not have enough dimensions ' '(has 1, gufunc core with signature (m,m),(m,n)->(m,n) requires 2)' ) else: if a.shape[-1] != b.shape[-2]: raise ValueError( 'solve: Input operand 1 has a mismatch in ' 'its core dimension 0, with gufunc signature (m,m),(m,n)->(m,n) ' '(size {0} is different from {1})'.format( b.shape[-2], a.shape[-1])) if b.ndim == 1 or a.ndim - 1 == b.ndim and a.shape[-1] == b.shape[-1]: tmp = 1 _newaxis = (None, ) else: tmp = 2 _newaxis = (None, None) for i in range(1, min(a.ndim - 2, b.ndim - tmp) + 1): if a.shape[-2 - i] != b.shape[-tmp - i] and \ 1 not in (a.shape[-2 - i], b.shape[-tmp - i]): raise ValueError( 'operands could not be broadcast together with ' 'remapped shapes [original->remapped]: {0}->({1}) ' '{2}->({3}) and requested shape ({4})'.format( str(a.shape).replace(' ', ''), str(a.shape[:-2] + _newaxis).replace(' ', '').replace( 'None', 'newaxis').strip('(,)'), str(b.shape).replace(' ', ''), str(b.shape[:-tmp] + _newaxis).replace(' ', '').replace( 'None', 'newaxis').replace('None', 'newaxis').strip('(,)'), str(b.shape[-tmp:]).replace(' ', '').strip('(,)'))) if a.dtype.char in 'FD' or b.dtype.char in 'FD': dtype = 'complex128' if a.dtype.char in 'fF' and b.dtype.char in 'fF': x_dtype = 'complex64' else: x_dtype = 'complex128' else: dtype = 'float64' if a.dtype.char == 'f' and b.dtype.char == 'f': x_dtype = 'float32' else: x_dtype = 'float64' x_shape = b.shape if b.ndim == a.ndim - 1: b = b[..., nlcpy.newaxis] diff = abs(a.ndim - b.ndim) if a.ndim < b.ndim: bcast_shape = [ b.shape[i] if b.shape[i] != 1 or i < diff else a.shape[i - diff] for i in range(b.ndim - 2) ] else: bcast_shape = [ a.shape[i] if a.shape[i] != 1 or i < diff else b.shape[i - diff] for i in range(a.ndim - 2) ] bcast_shape_a = bcast_shape + list(a.shape[-2:]) bcast_shape_b = bcast_shape + list(b.shape[-2:]) a = nlcpy.broadcast_to(a, bcast_shape_a) if bcast_shape_b != list(b.shape): b = nlcpy.broadcast_to(b, bcast_shape_b) x_shape = b.shape if b.size == 0: return nlcpy.empty(x_shape, dtype=x_dtype) a = nlcpy.array(nlcpy.moveaxis(a, (-1, -2), (1, 0)), dtype=dtype, order='F') b = nlcpy.array(nlcpy.moveaxis(b, (-1, -2), (1, 0)), dtype=dtype, order='F') info = numpy.empty(1, dtype='l') fpe = request._get_fpe_flag() args = ( a._ve_array, b._ve_array, veo.OnStack(info, inout=veo.INTENT_OUT), veo.OnStack(fpe, inout=veo.INTENT_OUT), ) request._push_and_flush_request('nlcpy_solve', args, callback=util._assertNotSingular(info)) if c_order: x = nlcpy.moveaxis(b, (1, 0), (-1, -2)).reshape(x_shape) return nlcpy.asarray(x, x_dtype, 'C') else: x = nlcpy.asarray(b, x_dtype) return nlcpy.moveaxis(x, (1, 0), (-1, -2)).reshape(x_shape)
def test_broadcast_to_fail_numpy19(self, dtype): # Note that broadcast_to is only supported on numpy>=1.10 a = testing.shaped_arange((3, 1, 4), nlcpy, dtype) with self.assertRaises(ValueError): nlcpy.broadcast_to(a, (1, 3, 4))
def roll(a, shift, axis=None): """Rolls array elements along a given axis. Elements that roll beyond the last position are re-introduced at the first. Parameters ---------- a : array_like Input array. shift : int or tuple of ints The number of places by which elements are shifted. If a tuple, then *axis* must be a tuple of the same size, and each of the given axes is shifted by the corresponding number. If an int while *axis* is a tuple of ints, then the same value is used for all given axes. axis : int or tuple of ints, optional Axis or axes along which elements are shifted. By default, the array is flattened before shifting, after which the original shape is restored. Returns ------- res : ndarray Output array, with the same shape as *a*. See Also -------- rollaxis : Rolls the specified axis backwards, until it lies in a given position. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(10) >>> vp.roll(x, 2) array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7]) >>> vp.roll(x, -2) array([2, 3, 4, 5, 6, 7, 8, 9, 0, 1]) >>> x2 = vp.reshape(x, (2,5)) >>> x2 array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) >>> vp.roll(x2, 1) array([[9, 0, 1, 2, 3], [4, 5, 6, 7, 8]]) >>> vp.roll(x2, -1) array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 0]]) >>> vp.roll(x2, 1, axis=0) array([[5, 6, 7, 8, 9], [0, 1, 2, 3, 4]]) >>> vp.roll(x2, -1, axis=0) array([[5, 6, 7, 8, 9], [0, 1, 2, 3, 4]]) >>> vp.roll(x2, 1, axis=1) array([[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]) >>> vp.roll(x2, -1, axis=1) array([[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]) """ a = nlcpy.asanyarray(a) if axis is None: return roll(a.ravel(), shift, 0).reshape(a.shape) if type(axis) not in (tuple, list): try: axis = [operator.index(axis)] except TypeError: pass _axis = axis.get() if isinstance(axis, nlcpy.ndarray) else axis axis = [ax + a.ndim if ax < 0 else ax for ax in _axis] for ax in axis: if ax < 0 or ax >= a.ndim: raise AxisError( 'axis {} is out of bounds for array of dimension {}'.format( ax, a.ndim)) shift = nlcpy.asanyarray(shift) axis = nlcpy.asanyarray(axis) if shift.ndim > 1 or axis.ndim > 1: raise ValueError( "'shift' and 'axis' should be scalars or 1D sequences") if shift.size > axis.size: axis = nlcpy.broadcast_to(axis, shift.shape) else: shift = nlcpy.broadcast_to(shift, axis.shape) shift = nlcpy.array(shift, dtype='l') axis = nlcpy.array(axis, dtype='l') result = nlcpy.empty(a.shape, dtype=a.dtype) work = nlcpy.zeros(a.ndim, dtype='l') request._push_request('nlcpy_roll', 'manipulation_op', (a, shift, axis, work, result)) return result