# Copyright (C) 2020 NumS Development Team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# pylint: disable = redefined-builtin, too-many-lines, anomalous-backslash-in-string, unused-wildcard-import, wildcard-import, unused-import
import scipy
from scipy import stats
from nums.core.application_manager import instance as _instance
from nums.core.array.blockarray import BlockArray
from nums.numpy.api.logic import *
############################################
# Manipulation Ops
############################################
[docs]def atleast_1d(*arys):
"""Convert inputs to arrays with at least one dimension.
This docstring was copied from numpy.atleast_1d.
Some inconsistencies with the NumS version may exist.
Scalar inputs are converted to 1-dimensional arrays, whilst
higher-dimensional inputs are preserved.
Parameters
----------
arys1, arys2, ... : BlockArray
One or more input arrays.
Returns
-------
ret : BlockArray
An array, or list of arrays, each with ``a.ndim >= 1``.
Copies are made only if necessary.
See Also
--------
atleast_2d, atleast_3d
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> nps.atleast_1d(1.0).get() # doctest: +SKIP
array([1.])
>>> x = nps.arange(9.0).reshape(3,3) # doctest: +SKIP
>>> nps.atleast_1d(x).get() # doctest: +SKIP
array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]])
>>> [a.get() for a in nps.atleast_1d(1, [3, 4])] # doctest: +SKIP
[array([1]), array([3, 4])]
"""
return _instance().atleast_1d(*arys)
[docs]def atleast_2d(*arys):
"""View inputs as arrays with at least two dimensions.
This docstring was copied from numpy.atleast_2d.
Some inconsistencies with the NumS version may exist.
Parameters
----------
arys1, arys2, ... : BlockArray
One or more array-like sequences. Non-array inputs are converted
to arrays. Arrays that already have two or more dimensions are
preserved.
Returns
-------
res, res2, ... : BlockArray
An array, or list of arrays, each with ``a.ndim >= 2``.
Copies are avoided where possible, and views with two or more
dimensions are returned.
See Also
--------
atleast_1d, atleast_3d
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> nps.atleast_2d(3.0).get() # doctest: +SKIP
array([[3.]])
>>> x = nps.arange(3.0) # doctest: +SKIP
>>> nps.atleast_2d(x).get() # doctest: +SKIP
array([[0., 1., 2.]])
>>> [a.get() for a in nps.atleast_2d(1, [1, 2], [[1, 3]])] # doctest: +SKIP
[array([[1]]), array([[1, 2]]), array([[1, 2]])]
"""
return _instance().atleast_2d(*arys)
[docs]def atleast_3d(*arys):
"""View inputs as arrays with at least three dimensions.
This docstring was copied from numpy.atleast_3d.
Some inconsistencies with the NumS version may exist.
Parameters
----------
arys1, arys2, ... : BlockArray
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, ... : BlockArray
An array, or list of arrays, each with ``a.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, atleast_2d
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> nps.atleast_3d(3.0).get() # doctest: +SKIP
array([[[3.]]])
>>> x = nps.arange(3.0) # doctest: +SKIP
>>> nps.atleast_3d(x).shape # doctest: +SKIP
(1, 3, 1)
>>> x = nps.arange(12.0).reshape(4,3) # doctest: +SKIP
>>> nps.atleast_3d(x).shape # doctest: +SKIP
(4, 3, 1)
>>> for arr in nps.atleast_3d([1, 2], [[1, 2]], [[[1, 2]]]): # doctest: +SKIP
... print(arr.get(), arr.shape) # doctest: +SKIP
...
[[[1]
[2]]] (1, 2, 1)
[[[1]
[2]]] (1, 2, 1)
[[[1 2]]] (1, 1, 2)
"""
return _instance().atleast_3d(*arys)
[docs]def column_stack(tup):
"""Stack 1-D arrays as columns into a 2-D array.
This docstring was copied from numpy.column_stack.
Some inconsistencies with the NumS version may exist.
Take a sequence of 1-D arrays and stack them as columns
to make a single 2-D array. 2-D arrays are stacked as-is,
just like with `hstack`. 1-D arrays are turned into 2-D columns
first.
Parameters
----------
tup : sequence of 1-D or 2-D arrays.
Arrays to stack. All of them must have the same first dimension.
Returns
-------
stacked : 2-D array
The array formed by stacking the given arrays.
See Also
--------
stack, hstack, vstack, concatenate
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array((1,2,3)) # doctest: +SKIP
>>> b = nps.array((2,3,4)) # doctest: +SKIP
>>> nps.column_stack((a,b)).get() # doctest: +SKIP
array([[1, 2],
[2, 3],
[3, 4]])
"""
return _instance().column_stack(tup)
[docs]def concatenate(arrays, axis=0, out=None):
"""Join a sequence of arrays along an existing axis.
This docstring was copied from numpy.concatenate.
Some inconsistencies with the NumS version may exist.
Parameters
----------
a1, a2, ... : sequence of array_like
The arrays must have the same shape, except in the dimension
corresponding to `axis` (the first, by default).
axis : int, optional
The axis along which the arrays will be joined. If axis is None,
arrays are flattened before use. Default is 0.
out : BlockArray, optional
If provided, the destination to place the result. The shape must be
correct, matching that of what concatenate would have returned if no
out argument were specified.
Returns
-------
res : BlockArray
The concatenated array.
See Also
--------
ma.concatenate : Concatenate function that preserves input masks.
array_split : Split an array into multiple sub-arrays of equal or
near-equal size.
split : Split array into a list of multiple sub-arrays of equal size.
hsplit : Split array into multiple sub-arrays horizontally (column wise).
vsplit : Split array into multiple sub-arrays vertically (row wise).
dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
stack : Stack a sequence of arrays along a new axis.
block : Assemble arrays from blocks.
hstack : Stack arrays in sequence horizontally (column wise).
vstack : Stack arrays in sequence vertically (row wise).
dstack : Stack arrays in sequence depth wise (along third dimension).
column_stack : Stack 1-D arrays as columns into a 2-D array.
Notes
-----
When one or more of the arrays to be concatenated is a MaskedArray,
this function will return a MaskedArray object instead of an BlockArray,
but the input masks are *not* preserved. In cases where a MaskedArray
is expected as input, use the ma.concatenate function from the masked
array module instead.
out is currently not supported for concatenate.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array([[1, 2], [3, 4]]) # doctest: +SKIP
>>> b = nps.array([[5, 6]]) # doctest: +SKIP
>>> nps.concatenate((a, b), axis=0).get() # doctest: +SKIP
array([[1, 2],
[3, 4],
[5, 6]])
>>> nps.concatenate((a, b.T), axis=1).get() # doctest: +SKIP
array([[1, 2, 5],
[3, 4, 6]])
"""
if out is not None:
raise NotImplementedError("out is currently not supported for concatenate.")
# Pick the mode along specified axis.
axis_block_size = stats.mode(
list(map(lambda arr: arr.block_shape[axis], arrays))
).mode.item()
return _instance().concatenate(arrays, axis=axis, axis_block_size=axis_block_size)
[docs]def dstack(tup):
"""Stack arrays in sequence depth wise (along third axis).
This docstring was copied from numpy.dstack.
Some inconsistencies with the NumS version may exist.
This is equivalent to concatenation along the third axis after 2-D arrays
of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape
`(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by
`dsplit`.
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 arrays
The arrays must have the same shape along all but the third axis.
1-D or 2-D arrays must have the same shape.
Returns
-------
stacked : BlockArray
The array formed by stacking the given arrays, will be at least 3-D.
See Also
--------
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
block : Assemble an nd-array from nested lists of blocks.
vstack : Stack arrays in sequence vertically (row wise).
hstack : Stack arrays in sequence horizontally (column wise).
column_stack : Stack 1-D arrays as columns into a 2-D array.
dsplit : Split array along third axis.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array((1,2,3)) # doctest: +SKIP
>>> b = nps.array((2,3,4)) # doctest: +SKIP
>>> nps.dstack((a,b)).get() # doctest: +SKIP
array([[[1, 2],
[2, 3],
[3, 4]]])
>>> a = nps.array([[1],[2],[3]]) # doctest: +SKIP
>>> b = nps.array([[2],[3],[4]]) # doctest: +SKIP
>>> nps.dstack((a,b)).get() # doctest: +SKIP
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
"""
return _instance().dstack(tup)
[docs]def expand_dims(a: BlockArray, axis):
"""Expand the shape of an array.
This docstring was copied from numpy.expand_dims.
Some inconsistencies with the NumS version may exist.
Insert a new axis that will appear at the `axis` position in the expanded
array shape.
Parameters
----------
a : BlockArray
Input array.
axis : int or tuple of ints
Position in the expanded axes where the new axis (or axes) is placed.
Returns
-------
result : BlockArray
View of `a` with the number of dimensions increased.
See Also
--------
squeeze : The inverse operation, removing singleton dimensions
reshape : Insert, remove, and combine dimensions, and resize existing ones
atleast_1d, atleast_2d, atleast_3d
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> x = nps.array([1, 2]) # doctest: +SKIP
>>> x.shape # doctest: +SKIP
(2,)
The following is equivalent to ``x[nps.newaxis, :]`` or ``x[nps.newaxis]``:
>>> y = nps.expand_dims(x, axis=0) # doctest: +SKIP
>>> y.get() # doctest: +SKIP
array([[1, 2]])
>>> y.shape # doctest: +SKIP
(1, 2)
The following is equivalent to ``x[:, nps.newaxis]``:
>>> y = nps.expand_dims(x, axis=1) # doctest: +SKIP
>>> y.get() # doctest: +SKIP
array([[1],
[2]])
>>> y.shape # doctest: +SKIP
(2, 1)
``axis`` may also be a tuple:
>>> y = nps.expand_dims(x, axis=(0, 1)) # doctest: +SKIP
>>> y.get() # doctest: +SKIP
array([[[1, 2]]])
>>> y = nps.expand_dims(x, axis=(2, 0)) # doctest: +SKIP
>>> y.get() # doctest: +SKIP
array([[[1],
[2]]])
"""
return a.expand_dims(axis)
[docs]def hstack(tup):
"""Stack arrays in sequence horizontally (column wise).
This docstring was copied from numpy.hstack.
Some inconsistencies with the NumS version may exist.
This is equivalent to concatenation along the second axis, except for 1-D
arrays where it concatenates along the first axis. Rebuilds arrays divided
by `hsplit`.
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 BlockArray
The arrays must have the same shape along all but the second axis,
except 1-D arrays which can be any length.
Returns
-------
stacked : BlockArray
The array formed by stacking the given arrays.
See Also
--------
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
block : Assemble an nd-array from nested lists of blocks.
vstack : Stack arrays in sequence vertically (row wise).
dstack : Stack arrays in sequence depth wise (along third axis).
column_stack : Stack 1-D arrays as columns into a 2-D array.
hsplit : Split an array into multiple sub-arrays horizontally (column-wise).
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array((1,2,3)) # doctest: +SKIP
>>> b = nps.array((2,3,4)) # doctest: +SKIP
>>> nps.hstack((a,b)).get() # doctest: +SKIP
array([1, 2, 3, 2, 3, 4])
>>> a = nps.array([[1],[2],[3]]) # doctest: +SKIP
>>> b = nps.array([[2],[3],[4]]) # doctest: +SKIP
>>> nps.hstack((a,b)).get() # doctest: +SKIP
array([[1, 2],
[2, 3],
[3, 4]])
"""
return _instance().hstack(tup)
[docs]def reshape(a: BlockArray, shape):
"""Gives a new shape to an array without changing its data.
This docstring was copied from numpy.reshape.
Some inconsistencies with the NumS version may exist.
Parameters
----------
a : BlockArray
Array to be reshaped.
Returns
-------
reshaped_array : BlockArray
This will be a new view object if possible; otherwise, it will
be a copy.
"""
block_shape = _instance().compute_block_shape(shape, a.dtype)
return a.reshape(shape, block_shape=block_shape)
[docs]def row_stack(tup):
"""Stack arrays in sequence vertically (row wise).
This docstring was copied from numpy.row_stack.
Some inconsistencies with the NumS version may exist.
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 BlockArrays
The arrays must have the same shape along all but the first axis.
1-D arrays must have the same length.
Returns
-------
stacked : BlockArray
The array formed by stacking the given arrays, will be at least 2-D.
See Also
--------
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
block : Assemble an nd-array from nested lists of blocks.
hstack : Stack arrays in sequence horizontally (column wise).
dstack : Stack arrays in sequence depth wise (along third axis).
column_stack : Stack 1-D arrays as columns into a 2-D array.
vsplit : Split an array into multiple sub-arrays vertically (row-wise).
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array([1, 2, 3]) # doctest: +SKIP
>>> b = nps.array([2, 3, 4]) # doctest: +SKIP
>>> nps.vstack((a,b)).get() # doctest: +SKIP
array([[1, 2, 3],
[2, 3, 4]])
>>> a = nps.array([[1], [2], [3]]) # doctest: +SKIP
>>> b = nps.array([[2], [3], [4]]) # doctest: +SKIP
>>> nps.vstack((a,b)).get() # doctest: +SKIP
array([[1],
[2],
[3],
[2],
[3],
[4]])
"""
return _instance().row_stack(tup)
[docs]def squeeze(a: BlockArray, axis=None):
"""Remove single-dimensional entries from the shape of an array.
This docstring was copied from numpy.squeeze.
Some inconsistencies with the NumS version may exist.
Parameters
----------
a : BlockArray
Input data.
Returns
-------
squeezed : BlockArray
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 : The inverse operation, adding singleton dimensions
reshape : Insert, remove, and combine dimensions, and resize existing ones
Notes
-----
axis not supported.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> x = nps.array([[[0], [1], [2]]]) # doctest: +SKIP
>>> x.shape # doctest: +SKIP
(1, 3, 1)
>>> nps.squeeze(x).shape # doctest: +SKIP
(3,)
>>> x = nps.array([[1234]]) # doctest: +SKIP
>>> x.shape # doctest: +SKIP
(1, 1)
>>> nps.squeeze(x).get() # doctest: +SKIP
array(1234) # 0d array
>>> nps.squeeze(x).shape # doctest: +SKIP
()
>>> nps.squeeze(x)[()].get() # doctest: +SKIP
array(1234)
"""
assert axis is None, "axis not supported."
return a.squeeze()
[docs]def split(ary: BlockArray, indices_or_sections, axis=0):
"""Split an array into multiple sub-arrays as views into `ary`.
This docstring was copied from numpy.split.
Some inconsistencies with the NumS version may exist.
Parameters
----------
ary : BlockArray
Array to be divided into sub-arrays.
indices_or_sections : int or 1-D array
If `indices_or_sections` is an integer, N, the array will be divided
into N equal arrays along `axis`. If such a split is not possible,
an error is raised.
If `indices_or_sections` is a 1-D array of sorted integers, the entries
indicate where along `axis` the array is split. For example,
``[2, 3]`` would, for ``axis=0``, result in
- ary[:2]
- ary[2:3]
- ary[3:]
If an index exceeds the dimension of the array along `axis`,
an empty sub-array is returned correspondingly.
axis : int, optional
The axis along which to split, default is 0.
Returns
-------
sub-arrays : list of BlockArrays
A list of sub-arrays as views into `ary`.
Raises
------
ValueError
If `indices_or_sections` is given as an integer, but
a split does not result in equal division.
See Also
--------
array_split : Split an array into multiple sub-arrays of equal or
near-equal size. Does not raise an exception if
an equal division cannot be made.
hsplit : Split array into multiple sub-arrays horizontally (column-wise).
vsplit : Split array into multiple sub-arrays vertically (row wise).
dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
hstack : Stack arrays in sequence horizontally (column wise).
vstack : Stack arrays in sequence vertically (row wise).
dstack : Stack arrays in sequence depth wise (along third dimension).
Notes
-----
Split currently supports integers only.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> x = nps.arange(9.0) # doctest: +SKIP
>>> [a.get() for a in nps.split(x, 3)] # doctest: +SKIP
[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]
"""
if not isinstance(indices_or_sections, int):
raise NotImplementedError("Split currently supports integers only.")
dim_total = ary.shape[axis]
# Splits into N equal arrays, and raise if this is not possible.
if dim_total % indices_or_sections != 0:
raise ValueError(
"ary axis %s cannot be split into %s equal arrays."
% (axis, indices_or_sections)
)
dim_partial = dim_total // indices_or_sections
results = []
ss_op = [slice(None, None, 1) for _ in ary.shape]
for i in range(0, dim_total, dim_partial):
start = i
stop = i + dim_partial
ss_op[axis] = slice(start, stop, 1)
ary_part = ary[tuple(ss_op)]
results.append(ary_part)
return tuple(results)
[docs]def swapaxes(a: BlockArray, axis1: int, axis2: int):
"""Interchange two axes of an array.
This docstring was copied from numpy.swapaxes.
Some inconsistencies with the NumS version may exist.
Parameters
----------
a : BlockArray
Input array.
axis1 : int
First axis.
axis2 : int
Second axis.
Returns
-------
a_swapped : BlockArray
For NumPy >= 1.10.0, if `a` is an BlockArray, then a view of `a` is
returned; otherwise a new array is created. For earlier NumPy
versions a view of `a` is returned only if the order of the
axes is changed, otherwise the input array is returned.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> x = nps.array([[1,2,3]]) # doctest: +SKIP
>>> nps.swapaxes(x,0,1).get() # doctest: +SKIP
array([[1],
[2],
[3]])
>>> x = nps.array([[[0,1],[2,3]],[[4,5],[6,7]]]) # doctest: +SKIP
>>> x.get() # doctest: +SKIP
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
>>> nps.swapaxes(x,0,2).get() # doctest: +SKIP
array([[[0, 4],
[2, 6]],
[[1, 5],
[3, 7]]])
"""
return a.swapaxes(axis1, axis2)
[docs]def transpose(a: BlockArray, axes=None):
"""Reverse or permute the axes of an array; returns the modified array.
This docstring was copied from numpy.transpose.
Some inconsistencies with the NumS version may exist.
For an array a with two axes, transpose(a) gives the matrix transpose.
Parameters
----------
a : BlockArray
Input array.
Returns
-------
p : BlockArray
`a` with its axes permuted. A view is returned whenever
possible.
Notes
-----
Transposing a 1-D array returns an unchanged view of the original array.
axes not supported.
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> x = nps.arange(4).reshape((2,2)) # doctest: +SKIP
>>> x.get() # doctest: +SKIP
array([[0, 1],
[2, 3]])
>>> nps.transpose(x).get() # doctest: +SKIP
array([[0, 2],
[1, 3]])
"""
assert axes is None, "axes not supported."
return a.T
[docs]def vstack(tup):
"""Stack arrays in sequence vertically (row wise).
This docstring was copied from numpy.vstack.
Some inconsistencies with the NumS version may exist.
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 BlockArrays
The arrays must have the same shape along all but the first axis.
1-D arrays must have the same length.
Returns
-------
stacked : BlockArray
The array formed by stacking the given arrays, will be at least 2-D.
See Also
--------
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
block : Assemble an nd-array from nested lists of blocks.
hstack : Stack arrays in sequence horizontally (column wise).
dstack : Stack arrays in sequence depth wise (along third axis).
column_stack : Stack 1-D arrays as columns into a 2-D array.
vsplit : Split an array into multiple sub-arrays vertically (row-wise).
Examples
--------
The doctests shown below are copied from NumPy.
They won’t show the correct result until you operate ``get()``.
>>> a = nps.array([1, 2, 3]) # doctest: +SKIP
>>> b = nps.array([2, 3, 4]) # doctest: +SKIP
>>> nps.vstack((a,b)).get() # doctest: +SKIP
array([[1, 2, 3],
[2, 3, 4]])
>>> a = nps.array([[1], [2], [3]]) # doctest: +SKIP
>>> b = nps.array([[2], [3], [4]]) # doctest: +SKIP
>>> nps.vstack((a,b)).get() # doctest: +SKIP
array([[1],
[2],
[3],
[2],
[3],
[4]])
"""
return _instance().vstack(tup)