Skip to content

Commit

Permalink
Merge f9e9195 into 3100df1
Browse files Browse the repository at this point in the history
  • Loading branch information
okuta committed Jul 31, 2017
2 parents 3100df1 + f9e9195 commit dfb8588
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 30 deletions.
35 changes: 22 additions & 13 deletions cupy/core/core.pyx
Expand Up @@ -269,9 +269,9 @@ cdef class ndarray:
dtype: Type specifier.
order ({'C', 'F', 'A', 'K'}): Row-major (C-style) or column-major
(Fortran-style) order.
When `order` is 'A', it uses 'F' if `a` is column-major and
uses `C` otherwise.
And when `order` is 'K', it keeps strides as closely as
When ``order`` is 'A', it uses 'F' if ``a`` is column-major and
uses 'C' otherwise.
And when ``order`` is 'K', it keeps strides as closely as
possible.
copy (bool): If it is False and no cast happens, then this method
returns the array itself. Otherwise, a copy is returned.
Expand Down Expand Up @@ -349,8 +349,8 @@ cdef class ndarray:
Args:
order ({'C', 'F', 'A', 'K'}): Row-major (C-style) or column-major
(Fortran-style) order.
When `order` is 'A', it uses 'F' if `a` is column-major and
uses `C` otherwise.
When ``order`` is 'A', it uses 'F' if ``a`` is column-major and
uses 'C' otherwise.
And when `order` is 'K', it keeps strides as closely as
possible.
Expand Down Expand Up @@ -1551,10 +1551,13 @@ cdef class ndarray:
arr.dtype, self.dtype))
if self.shape != arr.shape:
raise ValueError('Shape mismatch')
if not self._c_contiguous:
if self._c_contiguous:
arr = numpy.ascontiguousarray(arr)
elif self._f_contiguous:
arr = numpy.asfortranarray(arr)
else:
raise RuntimeError('Cannot set to non-contiguous array')

arr = numpy.ascontiguousarray(arr)
ptr = arr.ctypes.get_as_parameter()
if stream is None:
self.data.copy_from_host(ptr, self.nbytes)
Expand Down Expand Up @@ -1893,19 +1896,22 @@ cdef _argmax = create_reduction_func(
# Array creation routines
# -----------------------------------------------------------------------------

cpdef ndarray array(obj, dtype=None, bint copy=True, Py_ssize_t ndmin=0):
# TODO(beam2d): Support order and subok options
cpdef ndarray array(obj, dtype=None, bint copy=True, str order='K',
bint subok=False, Py_ssize_t ndmin=0):
# TODO(beam2d): Support subok options
cdef Py_ssize_t nvidem
cdef ndarray a, src
if subok:
raise NotImplementedError
if isinstance(obj, ndarray):
src = obj
if dtype is None:
dtype = src.dtype
dev = src.data.device
if dev is None or dev.id == device.get_device_id():
a = src.astype(dtype, copy=copy)
a = src.astype(dtype, order=order, copy=copy)
else:
a = src.copy().astype(dtype, copy=False)
a = src.copy(order=order).astype(dtype, copy=False)

ndim = a._shape.size()
if ndmin > ndim:
Expand All @@ -1914,12 +1920,15 @@ cpdef ndarray array(obj, dtype=None, bint copy=True, Py_ssize_t ndmin=0):
a = a.view()
a.shape = (1,) * (ndmin - ndim) + a.shape
else:
a_cpu = numpy.array(obj, dtype=dtype, copy=False, order='C',
if order == 'K':
order = 'A'
a_cpu = numpy.array(obj, dtype=dtype, copy=False, order=order,
ndmin=ndmin)
order = 'C' if a_cpu.flags.c_contiguous else 'F'
a_dtype = a_cpu.dtype
if a_dtype.char not in '?bhilqBHILQefd':
raise ValueError('Unsupported dtype %s' % a_dtype)
a = ndarray(a_cpu.shape, dtype=a_dtype)
a = ndarray(a_cpu.shape, dtype=a_dtype, order=order)
if a_cpu.ndim == 0:
a.fill(a_cpu[()])
return a
Expand Down
22 changes: 19 additions & 3 deletions cupy/creation/from_data.py
@@ -1,7 +1,7 @@
from cupy import core


def array(obj, dtype=None, copy=True, ndmin=0):
def array(obj, dtype=None, copy=True, order='K', subok=False, ndmin=0):
"""Creates an array on the current device.
This function currently does not support the ``order`` and ``subok``
Expand All @@ -13,17 +13,33 @@ def array(obj, dtype=None, copy=True, ndmin=0):
dtype: Data type specifier.
copy (bool): If ``False``, this function returns ``obj`` if possible.
Otherwise this function always returns a new array.
order ({'C', 'F', 'A', 'K'}): Row-major (C-style) or column-major
(Fortran-style) order.
When ``order`` is 'A', it uses 'F' if ``a`` is column-major and
uses 'C' otherwise.
And when ``order`` is 'K', it keeps strides as closely as
possible.
If ``obj`` is ``numpy.ndarray``, thi function returns 'C' or 'F'
order array.
subok (bool): If True, then sub-classes will be passed-through,
otherwise the returned array will be forced to be a base-class
array (default).
ndmin (int): Minimum number of dimensions. Ones are inserted to the
head of the shape if needed.
Returns:
cupy.ndarray: An array on the current device.
.. note::
This method currently does not support ``subok``
arguments.
.. seealso:: :func:`numpy.array`
"""
# TODO(beam2d): Support order and subok options
return core.array(obj, dtype, copy, ndmin)
return core.array(obj, dtype, copy, order, subok, ndmin)


def asarray(a, dtype=None):
Expand Down
12 changes: 12 additions & 0 deletions cupy/testing/array.py
Expand Up @@ -89,6 +89,18 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
numpy.testing.assert_array_equal(
cupy.asnumpy(x), cupy.asnumpy(y), err_msg=err_msg,
verbose=verbose)
if (isinstance(x, (numpy.ndarray, cupy.ndarray)) and
isinstance(y, (numpy.ndarray, cupy.ndarray))):
if x.flags.c_contiguous != x.flags.c_contiguous:
raise AssertionError(
'The state of c_contiguous flag is different. '
'(x:{} y:{})'.format(x.flags.c_contiguous,
y.flags.c_contiguous))
if x.flags.c_contiguous != x.flags.c_contiguous:
raise AssertionError(
'The state of f_contiguous flag is different. '
'(x:{} y:{})'.format(x.flags.f_contiguous,
y.flags.f_contiguous))


def assert_array_list_equal(xlist, ylist, err_msg='', verbose=True):
Expand Down
52 changes: 38 additions & 14 deletions tests/cupy_tests/creation_tests/test_from_data.py
Expand Up @@ -11,51 +11,75 @@ class TestFromData(unittest.TestCase):

_multiprocess_can_split_ = True

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array(self, xp, dtype):
return xp.array([[1, 2, 3], [2, 3, 4]], dtype=dtype)
def test_array(self, xp, dtype, order):
return xp.array([[1, 2, 3], [2, 3, 4]], dtype=dtype, order=order)

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_from_numpy(self, xp, dtype):
def test_array_from_numpy(self, xp, dtype, order):
a = testing.shaped_arange((2, 3, 4), numpy, dtype)
return xp.array(a)
return xp.array(a, order=order)

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_copy(self, xp, dtype):
def test_array_copy(self, xp, dtype, order):
a = testing.shaped_arange((2, 3, 4), xp, dtype)
return xp.array(a)
return xp.array(a, order=order)

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_copy_is_copied(self, xp, dtype):
def test_array_copy_is_copied(self, xp, dtype, order):
a = testing.shaped_arange((2, 3, 4), xp, dtype)
b = xp.array(a)
b = xp.array(a, order=order)
a.fill(0)
return b

@testing.for_orders('CFAK')
@testing.for_all_dtypes(name='dtype1')
@testing.for_all_dtypes(name='dtype2')
@testing.numpy_cupy_array_equal()
def test_array_copy_with_dtype(self, xp, dtype1, dtype2):
def test_array_copy_with_dtype(self, xp, dtype1, dtype2, order):
a = testing.shaped_arange((2, 3, 4), xp, dtype1)
return xp.array(a, dtype=dtype2)
return xp.array(a, dtype=dtype2, order=order)

@testing.for_orders('CFAK')
@testing.numpy_cupy_array_equal()
def test_array_copy_with_dtype_being_none(self, xp):
def test_array_copy_with_dtype_being_none(self, xp, order):
a = testing.shaped_arange((2, 3, 4), xp)
return xp.array(a, dtype=None)
return xp.array(a, dtype=None, order=order)

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_no_copy(self, xp, dtype):
def test_array_no_copy(self, xp, dtype, order):
a = testing.shaped_arange((2, 3, 4), xp, dtype)
b = xp.array(a, copy=False)
b = xp.array(a, copy=False, order=order)
a.fill(0)
return b

@testing.for_orders('CFAK')
@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_f_contiguous_input(self, xp, dtype, order):
a = testing.shaped_arange((2, 3, 4), xp, dtype)
a = xp.asfortranarray(a)
b = xp.array(a, copy=False, order=order)
return b

@testing.for_all_dtypes()
@testing.numpy_cupy_array_equal()
def test_array_f_contiguous_output(self, xp, dtype):
a = testing.shaped_arange((2, 3, 4), xp, dtype)
b = xp.array(a, copy=False, order='F')
self.assertTrue(b.flags.f_contiguous)
return b

@testing.multi_gpu(2)
def test_array_multi_device(self):
with cuda.Device(0):
Expand Down

0 comments on commit dfb8588

Please sign in to comment.