This is an automated email from the ASF dual-hosted git repository.

haoj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/master by this push:
     new cf93bdc  [Numpy] New FFIs for Operator: tile, trace, transpose (#18017)
cf93bdc is described below

commit cf93bdc3efc380180d74385d9e91c5034e0d7273
Author: Huang, Guangtai <guang...@amazon.com>
AuthorDate: Fri Apr 17 14:14:48 2020 +0800

    [Numpy] New FFIs for Operator: tile, trace, transpose (#18017)
    
    * init
    
    * fix typo
    
    * transpose
    
    * add benchmark
    
    * fix lint
---
 benchmark/python/ffi/benchmark_ffi.py              |   3 +
 python/mxnet/_numpy_op_doc.py                      |  90 +----------------
 python/mxnet/ndarray/numpy/_op.py                  | 101 ++++++++++++++++++-
 python/mxnet/numpy/multiarray.py                   | 107 +++++++++++++++++++--
 python/mxnet/symbol/numpy/_symbol.py               |  59 +++++++++++-
 src/api/operator/numpy/np_matrix_op.cc             |  29 +++++-
 .../{tensor/matrix_op.cc => numpy/np_trace_op.cc}  |  49 ++++------
 src/api/operator/tensor/matrix_op.cc               |  25 ++++-
 src/operator/numpy/np_matrix_op-inl.h              |   5 +
 src/operator/numpy/np_matrix_op.cc                 |   6 +-
 src/operator/numpy/np_matrix_op.cu                 |   2 +-
 src/operator/numpy/np_trace_op-inl.h               |  10 ++
 src/operator/numpy/np_trace_op.cc                  |   6 +-
 src/operator/numpy/np_trace_op.cu                  |   4 +-
 src/operator/tensor/matrix_op-inl.h                |   5 +
 15 files changed, 351 insertions(+), 150 deletions(-)

diff --git a/benchmark/python/ffi/benchmark_ffi.py 
b/benchmark/python/ffi/benchmark_ffi.py
index c42e140..818e5a6 100644
--- a/benchmark/python/ffi/benchmark_ffi.py
+++ b/benchmark/python/ffi/benchmark_ffi.py
@@ -83,6 +83,9 @@ def prepare_workloads():
     OpArgMngr.add_workload("linalg.tensorinv", pool['1x1'], ind=2)
     OpArgMngr.add_workload("linalg.norm", pool['3x3'])
     OpArgMngr.add_workload("linalg.tensorsolve", pool['1x1x1'], pool['1x1x1'], 
(2, 0, 1))
+    OpArgMngr.add_workload("tile", pool['2x2'], 1)
+    OpArgMngr.add_workload("trace", pool['2x2'])
+    OpArgMngr.add_workload("transpose", pool['2x2'])
     OpArgMngr.add_workload("split", pool['3x3'], (0, 1, 2), axis=1)
     OpArgMngr.add_workload("argmax", pool['3x2'], axis=-1)
     OpArgMngr.add_workload("argmin", pool['3x2'], axis=-1)
diff --git a/python/mxnet/_numpy_op_doc.py b/python/mxnet/_numpy_op_doc.py
index 857b87a..47d7545 100644
--- a/python/mxnet/_numpy_op_doc.py
+++ b/python/mxnet/_numpy_op_doc.py
@@ -37,7 +37,7 @@ def _npx_nonzero(a):
     """
     Return the indices of the elements that are non-zero.
 
-    Returns a ndarray with ndim is 2. Each row contains the indices 
+    Returns a ndarray with ndim is 2. Each row contains the indices
     of the non-zero elements. The values in `a` are always tested and returned 
in
     row-major, C-style order.
 
@@ -127,48 +127,6 @@ def _np_repeat(a, repeats, axis=None):
     pass
 
 
-def _np_transpose(a, axes=None):
-    """
-    Permute the dimensions of an array.
-
-    Parameters
-    ----------
-    a : ndarray
-        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.
-
-    Notes
-    -----
-    This function differs from the original `numpy.transpose
-    
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
-    the following way(s):
-
-    - only ndarray is accepted as valid input, python iterables are not 
supported
-    - the operator always returns an `ndarray` that does not share the memory 
with the input
-
-    Examples
-    --------
-    >>> x = np.arange(4).reshape((2,2))
-    >>> x
-    array([[0., 1.],
-           [2., 3.]])
-    >>> np.transpose(x)
-    array([[0., 2.],
-           [1., 3.]])
-    >>> x = np.ones((1, 2, 3))
-    >>> np.transpose(x, (1, 0, 2)).shape
-    (2, 1, 3)
-    """
-    pass
-
-
 def _np_dot(a, b, out=None):
     """
     Dot product of two arrays. Specifically,
@@ -339,52 +297,6 @@ def _np_reshape(a, newshape, order='C', out=None):
     """
 
 
-def _np_trace(a, offset=0, axis1=0, axis2=1, out=None):
-    """
-    Return the sum along diagonals of the array.
-    If `a` is 2-D, the sum along its diagonal with the given offset
-    is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
-    If `a` has more than two dimensions, then the axes specified by axis1 and
-    axis2 are used to determine the 2-D sub-arrays whose traces are returned.
-    The shape of the resulting array is the same as that of `a` with `axis1`
-    and `axis2` removed.
-
-    Parameters
-    ----------
-    a : ndarray
-        Input array, from which the diagonals are taken.
-    offset : int, optional
-        Offset of the diagonal from the main diagonal. Can be both positive
-        and negative. Defaults to 0.
-    axis1, axis2 : int, optional
-        Axes to be used as the first and second axis of the 2-D sub-arrays
-        from which the diagonals should be taken. Defaults are the first two
-        axes of `a`.
-    out : ndarray, optional
-        Array into which the output is placed. It must be of the right shape
-        and right type to hold the output.
-
-    Returns
-    -------
-    sum_along_diagonals : ndarray
-        If `a` is 2-D, the sum along the diagonal is returned.  If `a` has
-        larger dimensions, then an array of sums along diagonals is returned.
-
-    Examples
-    --------
-    >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
-    >>> np.trace(a)
-    array(3.)
-    >>> a = np.arange(8).reshape((2, 2, 2))
-    >>> np.trace(a)
-    array([6., 8.])
-    >>> a = np.arange(24).reshape((2, 2, 2, 3))
-    >>> np.trace(a).shape
-    (2, 3)
-    """
-    pass
-
-
 def _np_squeeze(a, axis=None, out=None):
     """
     Remove single-dimensional entries from the shape of an array.
diff --git a/python/mxnet/ndarray/numpy/_op.py 
b/python/mxnet/ndarray/numpy/_op.py
index 1a66abb..06b8d5f 100644
--- a/python/mxnet/ndarray/numpy/_op.py
+++ b/python/mxnet/ndarray/numpy/_op.py
@@ -31,7 +31,7 @@ from ..ndarray import NDArray
 
 __all__ = ['shape', 'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 
'full_like', 'empty_like', 'invert', 'delete',
            'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 
'remainder', 'fmod',
-           'power', 'bitwise_not',
+           'power', 'bitwise_not', 'trace', 'transpose',
            'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 
'sqrt', 'cbrt', 'abs', 'insert', 'fabs',
            'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 
'log', 'degrees', 'log2', 'matmul',
            'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 
'fix', 'ceil', 'floor', 'histogram',
@@ -2095,6 +2095,53 @@ def triu(m, k=0):
     return _api_internal.triu(m, k)
 
 
+@set_module('mxnet.ndarray.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+    """
+    Return the sum along diagonals of the array.
+    If `a` is 2-D, the sum along its diagonal with the given offset
+    is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+    If `a` has more than two dimensions, then the axes specified by axis1 and
+    axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+    The shape of the resulting array is the same as that of `a` with `axis1`
+    and `axis2` removed.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array, from which the diagonals are taken.
+    offset : int, optional
+        Offset of the diagonal from the main diagonal. Can be both positive
+        and negative. Defaults to 0.
+    axis1, axis2 : int, optional
+        Axes to be used as the first and second axis of the 2-D sub-arrays
+        from which the diagonals should be taken. Defaults are the first two
+        axes of `a`.
+    out : ndarray, optional
+        Array into which the output is placed. It must be of the right shape
+        and right type to hold the output.
+
+    Returns
+    -------
+    sum_along_diagonals : ndarray
+        If `a` is 2-D, the sum along the diagonal is returned.  If `a` has
+        larger dimensions, then an array of sums along diagonals is returned.
+
+    Examples
+    --------
+    >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+    >>> np.trace(a)
+    array(3.)
+    >>> a = np.arange(8).reshape((2, 2, 2))
+    >>> np.trace(a)
+    array([6., 8.])
+    >>> a = np.arange(24).reshape((2, 2, 2, 3))
+    >>> np.trace(a).shape
+    (2, 3)
+    """
+    return _api_internal.trace(a, offset, axis1, axis2, out)
+
+
 def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs):
     """Helper function for unary operators with kwargs.
 
@@ -3748,7 +3795,7 @@ def tile(A, reps):
     >>> np.tile(b, 2)
     array([[1., 2., 1., 2.],
            [3., 4., 3., 4.]])
-    >>> np.(b, (2, 1))
+    >>> np.tile(b, (2, 1))
     array([[1., 2.],
            [3., 4.],
            [1., 2.],
@@ -3767,7 +3814,55 @@ def tile(A, reps):
     array([2, 2, 2]) # repeating integer `2`
 
     """
-    return _unary_func_helper(A, _npi.tile, _np.tile, reps=reps)
+    if isinstance(A, numeric_types):
+        return _np.tile(A, reps)
+    elif isinstance(A, NDArray):
+        return _api_internal.tile(A, reps)
+    else:
+        raise TypeError('type {} not supported'.format(str(type(A))))
+
+
+@set_module('mxnet.ndarray.numpy')
+def transpose(a, axes=None):
+    """
+    Permute the dimensions of an array.
+
+    Parameters
+    ----------
+    a : ndarray
+        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.
+
+    Notes
+    -----
+    This function differs from the original `numpy.transpose
+    
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
+    the following way(s):
+
+    - only ndarray is accepted as valid input, python iterables are not 
supported
+    - the operator always returns an `ndarray` that does not share the memory 
with the input
+
+    Examples
+    --------
+    >>> x = np.arange(4).reshape((2,2))
+    >>> x
+    array([[0., 1.],
+           [2., 3.]])
+    >>> np.transpose(x)
+    array([[0., 2.],
+           [1., 3.]])
+    >>> x = np.ones((1, 2, 3))
+    >>> np.transpose(x, (1, 0, 2)).shape
+    (2, 1, 3)
+    """
+    return _api_internal.transpose(a, axes)
 
 
 # pylint: disable=redefined-outer-name
diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py
index 2d6a788..99a6744 100644
--- a/python/mxnet/numpy/multiarray.py
+++ b/python/mxnet/numpy/multiarray.py
@@ -55,7 +55,7 @@ from . import fallback
 __all__ = ['ndarray', 'empty', 'empty_like', 'array', 'shape', 'median',
            'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 
'all', 'any', 'broadcast_to',
            'add', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 
'fmod', 'power', 'bitwise_not',
-           'delete',
+           'delete', 'trace', 'transpose',
            'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 
'invert',
            'sqrt', 'cbrt', 'abs', 'absolute', 'fabs', 'exp', 'expm1', 
'arcsin', 'arccos', 'arctan', 'sign', 'log',
            'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 
'square', 'negative', 'histogram',
@@ -1730,13 +1730,10 @@ class ndarray(NDArray):
         """
         raise AttributeError('mxnet.numpy.ndarray object has no attribute 
expand_dims')
 
-    def tile(self, *args, **kwargs):
-        """Convenience fluent method for :py:func:`tile`.
-
-        The arguments are the same as for :py:func:`tile`, with
-        this array as data.
-        """
-        raise AttributeError('mxnet.numpy.ndarray object has no attribute 
tile')
+    def tile(self, reps):  # pylint: disable=arguments-differ
+        """Construct an array by repeating A the number of times given by reps.
+        Refer to `mxnet.numpy.tile` for full documentation."""
+        return tile(self, reps=reps)
 
     def transpose(self, *axes):  # pylint: disable=arguments-differ
         """Permute the dimensions of an array."""
@@ -1747,7 +1744,7 @@ class ndarray(NDArray):
                 axes = axes[0]
             elif axes[0] is None:
                 axes = None
-        return _mx_np_op.transpose(self, axes=axes)
+        return transpose(self, axes=axes)
 
     def flip(self, *args, **kwargs):
         """Convenience fluent method for :py:func:`flip`.
@@ -5477,7 +5474,7 @@ def tile(A, reps):
     >>> np.tile(b, 2)
     array([[1., 2., 1., 2.],
            [3., 4., 3., 4.]])
-    >>> np.(b, (2, 1))
+    >>> np.tile(b, (2, 1))
     array([[1., 2.],
            [3., 4.],
            [1., 2.],
@@ -5500,6 +5497,96 @@ def tile(A, reps):
 
 
 @set_module('mxnet.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+    """
+    Return the sum along diagonals of the array.
+    If `a` is 2-D, the sum along its diagonal with the given offset
+    is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+    If `a` has more than two dimensions, then the axes specified by axis1 and
+    axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+    The shape of the resulting array is the same as that of `a` with `axis1`
+    and `axis2` removed.
+
+    Parameters
+    ----------
+    a : ndarray
+        Input array, from which the diagonals are taken.
+    offset : int, optional
+        Offset of the diagonal from the main diagonal. Can be both positive
+        and negative. Defaults to 0.
+    axis1, axis2 : int, optional
+        Axes to be used as the first and second axis of the 2-D sub-arrays
+        from which the diagonals should be taken. Defaults are the first two
+        axes of `a`.
+    out : ndarray, optional
+        Array into which the output is placed. It must be of the right shape
+        and right type to hold the output.
+
+    Returns
+    -------
+    sum_along_diagonals : ndarray
+        If `a` is 2-D, the sum along the diagonal is returned.  If `a` has
+        larger dimensions, then an array of sums along diagonals is returned.
+
+    Examples
+    --------
+    >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+    >>> np.trace(a)
+    array(3.)
+    >>> a = np.arange(8).reshape((2, 2, 2))
+    >>> np.trace(a)
+    array([6., 8.])
+    >>> a = np.arange(24).reshape((2, 2, 2, 3))
+    >>> np.trace(a).shape
+    (2, 3)
+    """
+    return _mx_nd_np.trace(a, offset, axis1, axis2, out)
+
+
+@set_module('mxnet.numpy')
+def transpose(a, axes=None):
+    """
+    Permute the dimensions of an array.
+
+    Parameters
+    ----------
+    a : ndarray
+        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.
+
+    Notes
+    -----
+    This function differs from the original `numpy.transpose
+    
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
+    the following way(s):
+
+    - only ndarray is accepted as valid input, python iterables are not 
supported
+    - the operator always returns an `ndarray` that does not share the memory 
with the input
+
+    Examples
+    --------
+    >>> x = np.arange(4).reshape((2,2))
+    >>> x
+    array([[0., 1.],
+           [2., 3.]])
+    >>> np.transpose(x)
+    array([[0., 2.],
+           [1., 3.]])
+    >>> x = np.ones((1, 2, 3))
+    >>> np.transpose(x, (1, 0, 2)).shape
+    (2, 1, 3)
+    """
+    return _mx_nd_np.transpose(a, axes)
+
+
+@set_module('mxnet.numpy')
 def tril(m, k=0):
     r"""
     Lower triangle of an array.
diff --git a/python/mxnet/symbol/numpy/_symbol.py 
b/python/mxnet/symbol/numpy/_symbol.py
index 8b31c8e..5951865 100644
--- a/python/mxnet/symbol/numpy/_symbol.py
+++ b/python/mxnet/symbol/numpy/_symbol.py
@@ -37,7 +37,7 @@ except ImportError:
 
 __all__ = ['zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 
'empty_like', 'bitwise_not', 'invert',
            'delete', 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 
'mod', 'remainder', 'fmod',
-           'power', 'arctan2',
+           'power', 'arctan2', 'trace', 'transpose',
            'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 
'cbrt', 'abs', 'absolute', 'fabs', 'exp',
            'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 
'log2', 'log1p', 'matmul', 'median',
            'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 
'ceil', 'floor', 'histogram', 'insert',
@@ -653,7 +653,7 @@ class _Symbol(Symbol):
                 axes = axes[0]
             elif axes[0] is None:
                 axes = None
-        return _mx_np_op.transpose(self, axes=axes)
+        return transpose(self, axes=axes)
 
     def flip(self, *args, **kwargs):
         """Convenience fluent method for :py:func:`flip`.
@@ -2308,6 +2308,61 @@ def tril_indices(n, k=0, m=None):
     return _npi.tril_indices(n, k, m)
 
 
+@set_module('mxnet.symbol.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+    """
+    Return the sum along diagonals of the array.
+    If `a` is 2-D, the sum along its diagonal with the given offset
+    is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+    If `a` has more than two dimensions, then the axes specified by axis1 and
+    axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+    The shape of the resulting array is the same as that of `a` with `axis1`
+    and `axis2` removed.
+
+    Parameters
+    ----------
+    a : _Symbol
+        Input array, from which the diagonals are taken.
+    offset : int, optional
+        Offset of the diagonal from the main diagonal. Can be both positive
+        and negative. Defaults to 0.
+    axis1, axis2 : int, optional
+        Axes to be used as the first and second axis of the 2-D sub-arrays
+        from which the diagonals should be taken. Defaults are the first two
+        axes of `a`.
+    out : _Symbol
+        Dummy parameter to keep the consistency with the ndarray counterpart.
+
+    Returns
+    -------
+    sum_along_diagonals : _Symbol
+        If `a` is 2-D, the sum along the diagonal is returned.  If `a` has
+        larger dimensions, then an array of sums along diagonals is returned.
+    """
+    return _npi.trace(a, offset=offset, axis1=axis1, axis2=axis2, out=out)
+
+
+@set_module('mxnet.symbol.numpy')
+def transpose(a, axes=None):
+    """
+    Permute the dimensions of an array.
+
+    Parameters
+    ----------
+    a : _Symbol
+        Input array.
+    axes : list of ints, optional
+        By default, reverse the dimensions,
+        otherwise permute the axes according to the values given.
+
+    Returns
+    -------
+    p : _Symbol
+        a with its axes permuted.
+    """
+    return _npi.transpose(a, axes=axes)
+
+
 def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs):
     """Helper function for unary operators.
 
diff --git a/src/api/operator/numpy/np_matrix_op.cc 
b/src/api/operator/numpy/np_matrix_op.cc
index 998823d..58ee563 100644
--- a/src/api/operator/numpy/np_matrix_op.cc
+++ b/src/api/operator/numpy/np_matrix_op.cc
@@ -6,9 +6,9 @@
  * to you 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
@@ -19,7 +19,7 @@
 
 /*!
  * \file np_matrix_op.cc
- * \brief Implementation of the API of functions in 
src/operator/tensor/matrix_op.cc
+ * \brief Implementation of the API of functions in 
src/operator/numpy/np_matrix_op.cc
  */
 #include <mxnet/api_registry.h>
 #include <mxnet/runtime/packed_func.h>
@@ -31,6 +31,29 @@
 
 namespace mxnet {
 
+MXNET_REGISTER_API("_npi.transpose")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+  using namespace runtime;
+  static const nnvm::Op* op = Op::Get("_npi_transpose");
+  nnvm::NodeAttrs attrs;
+  op::NumpyTransposeParam param;
+  if (args[1].type_code() == kNull) {
+    param.axes = TShape(-1, 0);
+  } else if (args[1].type_code() == kDLInt) {
+    param.axes = TShape(1, args[1].operator int64_t());
+  } else {
+    param.axes = TShape(args[1].operator ObjectRef());
+  }
+  attrs.parsed = std::move(param);
+  attrs.op = op;
+  SetAttrDict<op::NumpyTransposeParam>(&attrs);
+  NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+  int num_inputs = 1;
+  int num_outputs = 0;
+  auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, 
nullptr);
+  *ret = ndoutputs[0];
+});
+
 MXNET_REGISTER_API("_npi.expand_dims")
 .set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
   using namespace runtime;
diff --git a/src/api/operator/tensor/matrix_op.cc 
b/src/api/operator/numpy/np_trace_op.cc
similarity index 61%
copy from src/api/operator/tensor/matrix_op.cc
copy to src/api/operator/numpy/np_trace_op.cc
index ed91b09..2979d21 100644
--- a/src/api/operator/tensor/matrix_op.cc
+++ b/src/api/operator/numpy/np_trace_op.cc
@@ -6,9 +6,9 @@
  * to you 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
@@ -18,51 +18,36 @@
  */
 
 /*!
- * \file matrix_op.cc
- * \brief Implementation of the API of functions in 
src/operator/tensor/matrix_op.cc
+ * \file np_trace_op.cc
+ * \brief Implementation of the API of functions in 
src/operator/numpy/np_trace_op.cc
  */
 #include <mxnet/api_registry.h>
 #include <mxnet/runtime/packed_func.h>
 #include "../utils.h"
-#include "../../../operator/tensor/matrix_op-inl.h"
+#include "../../../operator/numpy/np_trace_op-inl.h"
 
 namespace mxnet {
 
-MXNET_REGISTER_API("_npi.clip")
+MXNET_REGISTER_API("_npi.trace")
 .set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
   using namespace runtime;
-  const nnvm::Op* op = Op::Get("_npi_clip");
+  const nnvm::Op* op = Op::Get("_npi_trace");
   nnvm::NodeAttrs attrs;
-  op::ClipParam param;
-  NDArray* inputs[1];
-
-  if (args[0].type_code() != kNull) {
-    inputs[0] = args[0].operator mxnet::NDArray *();
-  }
-
-  if (args[1].type_code() != kNull) {
-    param.a_min = args[1].operator double();
-  } else {
-    param.a_min = -INFINITY;
-  }
-
-  if (args[2].type_code() != kNull) {
-    param.a_max = args[2].operator double();
-  } else {
-    param.a_max = INFINITY;
-  }
-
+  op::NumpyTraceParam param;
+  param.offset = args[1].operator int64_t();
+  param.axis1 = args[2].operator int64_t();
+  param.axis2 = args[3].operator int64_t();
   attrs.parsed = param;
   attrs.op = op;
-  SetAttrDict<op::ClipParam>(&attrs);
-
-  NDArray* out = args[3].operator mxnet::NDArray*();
+  SetAttrDict<op::NumpyTraceParam>(&attrs);
+  NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+  int num_inputs = 1;
+  NDArray* out = args[4].operator mxnet::NDArray*();
   NDArray** outputs = out == nullptr ? nullptr : &out;
-  // set the number of outputs provided by the `out` arugment
   int num_outputs = out != nullptr;
-  auto ndoutputs = Invoke(op, &attrs, 1, inputs, &num_outputs, outputs);
+  auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, 
outputs);
   if (out) {
-    *ret = PythonArg(3);
+    *ret = PythonArg(4);
   } else {
     *ret = ndoutputs[0];
   }
diff --git a/src/api/operator/tensor/matrix_op.cc 
b/src/api/operator/tensor/matrix_op.cc
index ed91b09..6134428 100644
--- a/src/api/operator/tensor/matrix_op.cc
+++ b/src/api/operator/tensor/matrix_op.cc
@@ -6,9 +6,9 @@
  * to you 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
@@ -68,4 +68,25 @@ MXNET_REGISTER_API("_npi.clip")
   }
 });
 
+MXNET_REGISTER_API("_npi.tile")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+  using namespace runtime;
+  const nnvm::Op* op = Op::Get("_npi_tile");
+  nnvm::NodeAttrs attrs;
+  op::TileParam param;
+  if (args[1].type_code() == kDLInt) {
+    param.reps = Tuple<int>(1, args[1].operator int64_t());
+  } else {
+  param.reps = Tuple<int>(args[1].operator ObjectRef());
+  }
+  attrs.parsed = std::move(param);
+  attrs.op = op;
+  SetAttrDict<op::TileParam>(&attrs);
+  int num_outputs = 0;
+  NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+  int num_inputs = 1;
+  auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, 
nullptr);
+  *ret = ndoutputs[0];
+});
+
 }  // namespace mxnet
diff --git a/src/operator/numpy/np_matrix_op-inl.h 
b/src/operator/numpy/np_matrix_op-inl.h
index 09eb10c..4d73fae 100644
--- a/src/operator/numpy/np_matrix_op-inl.h
+++ b/src/operator/numpy/np_matrix_op-inl.h
@@ -47,6 +47,11 @@ struct NumpyTransposeParam : public 
dmlc::Parameter<NumpyTransposeParam> {
     .describe("By default, reverse the dimensions, otherwise permute "
               "the axes according to the values given.");
   }
+  void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+    std::ostringstream axes_s;
+    axes_s << axes;
+    (*dict)["axes"] = axes_s.str();
+  }
 };
 
 struct NumpyVstackParam : public dmlc::Parameter<NumpyVstackParam> {
diff --git a/src/operator/numpy/np_matrix_op.cc 
b/src/operator/numpy/np_matrix_op.cc
index f47a575..902db89 100644
--- a/src/operator/numpy/np_matrix_op.cc
+++ b/src/operator/numpy/np_matrix_op.cc
@@ -105,7 +105,7 @@ bool NumpyTransposeShape(const nnvm::NodeAttrs& attrs,
   return shape_is_known(*in_attrs) && shape_is_known(*out_attrs);
 }
 
-NNVM_REGISTER_OP(_np_transpose)
+NNVM_REGISTER_OP(_npi_transpose)
 .set_num_inputs(1)
 .set_num_outputs(1)
 .set_attr_parser(ParamParser<NumpyTransposeParam>)
@@ -126,9 +126,9 @@ NNVM_REGISTER_OP(_np_transpose)
       }
       std::ostringstream os;
       os << axes;
-      return MakeNonlossGradNode("_np_transpose", n, ograds, {}, {{"axes", 
os.str()}});
+      return MakeNonlossGradNode("_npi_transpose", n, ograds, {}, {{"axes", 
os.str()}});
     } else {
-      return MakeNonlossGradNode("_np_transpose", n, ograds, {},
+      return MakeNonlossGradNode("_npi_transpose", n, ograds, {},
                                  std::unordered_map<std::string, 
std::string>());
     }
   })
diff --git a/src/operator/numpy/np_matrix_op.cu 
b/src/operator/numpy/np_matrix_op.cu
index f919bb5..7b525d1 100644
--- a/src/operator/numpy/np_matrix_op.cu
+++ b/src/operator/numpy/np_matrix_op.cu
@@ -29,7 +29,7 @@
 namespace mxnet {
 namespace op {
 
-NNVM_REGISTER_OP(_np_transpose)
+NNVM_REGISTER_OP(_npi_transpose)
 .set_attr<FCompute>("FCompute<gpu>", NumpyTranspose<gpu>);
 
 NNVM_REGISTER_OP(_np_reshape)
diff --git a/src/operator/numpy/np_trace_op-inl.h 
b/src/operator/numpy/np_trace_op-inl.h
index 741c20b..ede7d37 100644
--- a/src/operator/numpy/np_trace_op-inl.h
+++ b/src/operator/numpy/np_trace_op-inl.h
@@ -28,6 +28,7 @@
 #include <dmlc/parameter.h>
 #include <mxnet/operator_util.h>
 #include <vector>
+#include <string>
 #include <utility>
 #include <algorithm>
 #include "../mxnet_op.h"
@@ -54,6 +55,15 @@ struct NumpyTraceParam: public 
dmlc::Parameter<NumpyTraceParam> {
     .describe("Axes to be used as the second axis of the 2-D sub-arrays "
               "from which the diagonals should be taken. Defaults to 1.");
   }
+  void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+    std::ostringstream offset_s, axis1_s, axis2_s;
+    offset_s << offset;
+    axis1_s << axis1;
+    axis2_s << axis2;
+    (*dict)["offset"] = offset_s.str();
+    (*dict)["axis1"] = axis1_s.str();
+    (*dict)["axis2"] = axis2_s.str();
+  }
 };
 
 template<int ndim, int req, bool back>
diff --git a/src/operator/numpy/np_trace_op.cc 
b/src/operator/numpy/np_trace_op.cc
index d97ac30..e6a1201 100644
--- a/src/operator/numpy/np_trace_op.cc
+++ b/src/operator/numpy/np_trace_op.cc
@@ -54,7 +54,7 @@ inline bool NumpyTraceOpShape(const nnvm::NodeAttrs& attrs,
 
 DMLC_REGISTER_PARAMETER(NumpyTraceParam);
 
-NNVM_REGISTER_OP(_np_trace)
+NNVM_REGISTER_OP(_npi_trace)
 .describe(R"code(Computes the sum of the diagonal elements of a matrix.
 Input is a tensor *A* of dimension *n >= 2*.
 
@@ -83,11 +83,11 @@ Examples::
 .set_attr<mxnet::FInferShape>("FInferShape", NumpyTraceOpShape)
 .set_attr<nnvm::FInferType>("FInferType", ElemwiseType<1, 1>)
 .set_attr<FCompute>("FCompute<cpu>", NumpyTraceOpForward<cpu>)
-.set_attr<nnvm::FGradient>("FGradient", 
ElemwiseGradUseNone{"_backward_np_trace"})
+.set_attr<nnvm::FGradient>("FGradient", 
ElemwiseGradUseNone{"_backward_npi_trace"})
 .add_argument("data", "NDArray-or-Symbol", "Input ndarray")
 .add_arguments(NumpyTraceParam::__FIELDS__());
 
-NNVM_REGISTER_OP(_backward_np_trace)
+NNVM_REGISTER_OP(_backward_npi_trace)
 .set_attr_parser(ParamParser<NumpyTraceParam>)
 .set_num_inputs(1)
 .set_num_outputs(1)
diff --git a/src/operator/numpy/np_trace_op.cu 
b/src/operator/numpy/np_trace_op.cu
index 220e4ae..5ec2913 100644
--- a/src/operator/numpy/np_trace_op.cu
+++ b/src/operator/numpy/np_trace_op.cu
@@ -26,10 +26,10 @@
 namespace mxnet {
 namespace op {
 
-NNVM_REGISTER_OP(_np_trace)
+NNVM_REGISTER_OP(_npi_trace)
 .set_attr<FCompute>("FCompute<gpu>", NumpyTraceOpForward<gpu>);
 
-NNVM_REGISTER_OP(_backward_np_trace)
+NNVM_REGISTER_OP(_backward_npi_trace)
 .set_attr<FCompute>("FCompute<gpu>", NumpyTraceOpBackward<gpu>);
 
 }  // namespace op
diff --git a/src/operator/tensor/matrix_op-inl.h 
b/src/operator/tensor/matrix_op-inl.h
index 821fa85..19d713d 100644
--- a/src/operator/tensor/matrix_op-inl.h
+++ b/src/operator/tensor/matrix_op-inl.h
@@ -1925,6 +1925,11 @@ struct TileParam : public dmlc::Parameter<TileParam> {
                 " If a.ndim < d, a is promoted to be d-dimensional by 
prepending new axes."
                 " If a.ndim > d, reps is promoted to a.ndim by pre-pending 1's 
to it.");
   }
+  void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+    std::ostringstream reps_s;
+    reps_s << reps;
+    (*dict)["reps"] = reps_s.str();
+  }
 };
 
 inline bool TileOpShape(const nnvm::NodeAttrs& attrs,

Reply via email to