From c13f90746b231a96a5ff749ecdb119144dbe05dc Mon Sep 17 00:00:00 2001 From: Hao Jin Date: Thu, 15 Aug 2019 01:29:24 -0700 Subject: [PATCH] np elemwise unary ops upstream --- python/mxnet/ndarray/numpy/_op.py | 1175 +++++++++++++++- python/mxnet/numpy/multiarray.py | 1193 ++++++++++++++++- python/mxnet/symbol/numpy/_symbol.py | 970 +++++++++++++- .../numpy/np_elemwise_unary_op_basic.cc | 366 +++++ .../numpy/np_elemwise_unary_op_basic.cu | 110 ++ tests/python/unittest/test_numpy_op.py | 149 ++ 6 files changed, 3957 insertions(+), 6 deletions(-) create mode 100644 src/operator/numpy/np_elemwise_unary_op_basic.cc create mode 100644 src/operator/numpy/np_elemwise_unary_op_basic.cu diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index d7f3fd1ace54..401cf73de432 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -16,6 +16,7 @@ # specific language governing permissions and limitations # under the License. +# pylint: disable=unused-argument """Namespace for numpy operators used in Gluon dispatched by F=ndarray.""" from __future__ import absolute_import @@ -26,7 +27,11 @@ from . import _internal as _npi from ..ndarray import NDArray -__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot', +__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'sin', + 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'absolute', + 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p', + 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', + 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'linspace', 'expand_dims', 'tile', 'arange', 'split', 'concatenate'] @@ -567,6 +572,1174 @@ def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs): raise TypeError('type {} not supported'.format(str(type(x)))) +@set_module('mxnet.ndarray.numpy') +def sin(x, out=None, **kwargs): + r"""Trigonometric sine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The sine of each element of x. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sin, _np.sin, out=out, **kwargs) + +@set_module('mxnet.ndarray.numpy') +def cos(x, out=None, **kwargs): + r"""Cosine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding cosine values. This is a scalar if x is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.cos, _np.cos, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def sinh(x, out=None, **kwargs): + """Hyperbolic sine, element-wise. + Equivalent to ``1/2 * (np.exp(x) - np.exp(-x))`` or ``-1j * np.sin(1j*x)``. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding hyperbolic sine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sinh, _np.sinh, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def cosh(x, out=None, **kwargs): + """Hyperbolic cosine, element-wise. + Equivalent to ``1/2 * (np.exp(x) + np.exp(-x))`` and ``np.cos(1j*x)``. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding hyperbolic cosine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.cosh, _np.cosh, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def tanh(x, out=None, **kwargs): + """ + Compute hyperbolic tangent element-wise. + Equivalent to ``np.sinh(x)/np.cosh(x)``. + Parameters + ---------- + x : ndarray or scalar. + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + The corresponding hyperbolic tangent values. + Notes + ----- + If `out` is provided, the function writes the result into it, + and returns a reference to `out`. (See Examples) + - input x does not support complex computation (like imaginary number) + >>> np.tanh(np.pi*1j) + TypeError: type not supported + Examples + -------- + >>> np.tanh(np.array[0, np.pi])) + array([0. , 0.9962721]) + >>> np.tanh(np.pi) + 0.99627207622075 + >>> # Example of providing the optional output parameter illustrating + >>> # that what is returned is a reference to said parameter + >>> out1 = np.array(1) + >>> out2 = np.tanh(np.array(0.1), out1) + >>> out2 is out1 + True + >>> # Example of ValueError due to provision of shape mis-matched `out` + >>> np.tanh(np.zeros((3,3)),np.zeros((2,2))) + mxnet.base.MXNetError: + [07:17:36] ../src/ndarray/./../operator/tensor/../elemwise_op_common.h:135: + Check failed: assign(&dattr, vec.at(i)): Incompatible attr in node + at 0-th output: expected [3,3], got [2,2] + """ + return _unary_func_helper(x, _npi.tanh, _np.tanh, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def log10(x, out=None, **kwargs): + """Return the base 10 logarithm of the input array, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which t'absolute', he result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The logarithm to the base 10 of `x`, element-wise. NaNs are + returned where x is negative. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.log10, _np.log10, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def sqrt(x, out=None, **kwargs): + """ + Return the non-negative square-root of an array, element-wise. + Parameters + ---------- + x : ndarray or scalar + The values whose square-roots are required. + out : ndarray, or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + An array of the same shape as `x`, containing the positive + square-root of each element in `x`. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sqrt, _np.sqrt, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def cbrt(x, out=None, **kwargs): + r""" + Return the cube-root of an array, element-wise. + Parameters + ---------- + x : ndarray + The values whose cube-roots are required. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape that the + inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + y : ndarray + An array of the same shape as x, containing the cube cube-root of each element in x. + If out was provided, y is a reference to it. This is a scalar if x is a scalar. + Examples + ---------- + >>> np.cbrt([1,8,27]) + array([ 1., 2., 3.]) + """ + return _unary_func_helper(x, _npi.cbrt, _np.cbrt, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def abs(x, out=None, **kwargs): + r"""abs(x, out=None, **kwargs) + Calculate the absolute value element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + absolute : ndarray + An ndarray containing the absolute value of + each element in `x`. This is a scalar if `x` is a scalar. + Examples + -------- + >>> x = np.array([-1.2, 1.2]) + >>> np.abs(x) + array([1.2, 1.2]) + """ + return _unary_func_helper(x, _npi.abs, _np.abs, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def absolute(x, out=None, **kwargs): + r""" + Calculate the absolute value element-wise. + np.abs is a shorthand for this function. + Parameters + ---------- + x : ndarray + Input array. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape + that the inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + absolute : ndarray + An ndarray containing the absolute value of each element in x. + Examples + ---------- + >>> x = np.array([-1.2, 1.2]) + >>> np.absolute(x) + array([ 1.2, 1.2]) + """ + return _unary_func_helper(x, _npi.absolute, _np.absolute, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def sign(x, out=None, **kwargs): + r""" + sign(x, out=None) + Returns an element-wise indication of the sign of a number. + The `sign` function returns ``-1 if x < 0, 0 if x==0, 1 if x > 0``. Only supports real number. + Parameters + ---------- + x : ndarray or a scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The sign of `x`. + This is a scalar if `x` is a scalar. + Note + ------- + - Only supports real number as input elements. + - Input type does not support Python native iterables(list, tuple, ...). + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + >>> a = np.array([-5., 4.5]) + >>> np.sign(a) + array([-1., 1.]) + Scalars as input: + >>> np.sign(4.0) + 1.0 + >>> np.sign(0) + 0 + Use ``out`` parameter: + >>> b = np.zeros((2, )) + >>> np.sign(a, out=b) + array([-1., 1.]) + >>> b + array([-1., 1.]) + """ + return _unary_func_helper(x, _npi.sign, _np.sign, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def exp(x, out=None, **kwargs): + r"""exp(x, out=None, **kwargs) + Calculate the exponential of all elements in the input array. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array, element-wise exponential of `x`. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> np.exp(1) + 2.718281828459045 + >>> x = np.array([-1, 1, -2, 2]) + >>> np.exp(x) + array([0.36787945, 2.7182817 , 0.13533528, 7.389056 ]) + """ + return _unary_func_helper(x, _npi.exp, _np.exp, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def expm1(x, out=None, **kwargs): + r"""expm1(x, out=None, **kwargs) + Calculate `exp(x) - 1` of all elements in the input array. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array, element-wise exponential minus one: `out = exp(x) - 1`. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> np.expm1(1) + 1.718281828459045 + >>> x = np.array([-1, 1, -2, 2]) + >>> np.expm1(x) + array([-0.63212056, 1.71828183, -0.86466472, 6.3890561]) + """ + return _unary_func_helper(x, _npi.expm1, _np.expm1, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arcsin(x, out=None, **kwargs): + r""" + arcsin(x, out=None) + Inverse sine, element-wise. + Parameters + ---------- + x : ndarray or scalar + `y`-coordinate on the unit circle. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + angle : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + The inverse sine of each element in `x`, in radians and in the + closed interval ``[-pi/2, pi/2]``. + Examples + -------- + >>> np.arcsin(1) # pi/2 + 1.5707963267948966 + >>> np.arcsin(-1) # -pi/2 + -1.5707963267948966 + >>> np.arcsin(0) + 0.0 + Notes + ----- + `arcsin` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that :math:`sin(z) = x`. The convention is to + return the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, *arcsin* always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + The inverse sine is also known as `asin` or sin^{-1}. + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.arcsin + `_ in + the following aspects: + - Only support ndarray or scalar now. + - `where` argument is not supported. + - Complex input is not supported. + References + ---------- + Abramowitz, M. and Stegun, I. A., *Handbook of Mathematical Functions*, + 10th printing, New York: Dover, 1964, pp. 79ff. + http://www.math.sfu.ca/~cbm/aands/ + """ + return _unary_func_helper(x, _npi.arcsin, _np.arcsin, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arccos(x, out=None, **kwargs): + r""" + Trigonometric inverse cosine, element-wise. + The inverse of cos so that, if y = cos(x), then x = arccos(y). + Parameters + ---------- + x : ndarray + x-coordinate on the unit circle. For real arguments, the domain is [-1, 1]. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape that + the inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + angle : ndarray + The angle of the ray intersecting the unit circle at the given x-coordinate in radians [0, pi]. + This is a scalar if x is a scalar. + See also + ---------- + cos, arctan, arcsin + Notes + ---------- + arccos is a multivalued function: for each x there are infinitely many numbers z such that + cos(z) = x. The convention is to return the angle z whose real part lies in [0, pi]. + For real-valued input data types, arccos always returns real output. + For each value that cannot be expressed as a real number or infinity, it yields nan and sets + the invalid floating point error flag. + The inverse cos is also known as acos or cos^-1. + Examples + ---------- + We expect the arccos of 1 to be 0, and of -1 to be pi: + >>> np.arccos([1, -1]) + array([ 0. , 3.14159265]) + """ + return _unary_func_helper(x, _npi.arccos, _np.arccos, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arctan(x, out=None, **kwargs): + r"""arctan(x, out=None, **kwargs) + Trigonometric inverse tangent, element-wise. + The inverse of tan, so that if ``y = tan(x)`` then ``x = arctan(y)``. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Out has the same shape as `x`. It lies is in + ``[-pi/2, pi/2]`` (``arctan(+/-inf)`` returns ``+/-pi/2``). + This is a scalar if `x` is a scalar. + Notes + ----- + `arctan` is a multi-valued function: for each `x` there are infinitely + many numbers `z` such that tan(`z`) = `x`. The convention is to return + the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, `arctan` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + For complex-valued input, we do not have support for them yet. + The inverse tangent is also known as `atan` or tan^{-1}. + Examples + -------- + We expect the arctan of 0 to be 0, and of 1 to be pi/4: + >>> x = np.array([0, 1]) + >>> np.arctan(x) + array([0. , 0.7853982]) + >>> np.pi/4 + 0.7853981633974483 + """ + return _unary_func_helper(x, _npi.arctan, _np.arctan, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def log(x, out=None, **kwargs): + """ + log(x, out=None) + Natural logarithm, element-wise. + The natural logarithm `log` is the inverse of the exponential function, + so that `log(exp(x)) = x`. The natural logarithm is logarithm in base + `e`. + Parameters + ---------- + x : ndarray + Input value. Elements must be of real value. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The natural logarithm of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + Currently only supports data of real values and ``inf`` as input. Returns data of real value, ``inf``, ``-inf`` and + ``nan`` according to the input. + This function differs from the original `numpy.log + `_ in + the following aspects: + - Does not support complex number for now + - Input type does not support Python native iterables(list, tuple, ...). + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + >>> a = np.array([1, np.exp(1), np.exp(2), 0], dtype=np.float64) + >>> np.log(a) + array([ 0., 1., 2., -inf], dtype=float64) + Due to internal calculation mechanism, using default float32 dtype may cause some special behavior: + >>> a = np.array([1, np.exp(1), np.exp(2), 0], dtype=np.float32) + >>> np.log(a) + array([ 0., 0.99999994, 2., -inf]) + Scalar calculation: + >>> np.log(1) + 0.0 + """ + return _unary_func_helper(x, _npi.log, _np.log, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def degrees(x, out=None, **kwargs): + """ + degrees(x, out=None) + Convert angles from radians to degrees. + Parameters + ---------- + x : ndarray + Input value. Elements must be of real value. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The corresponding degree values; if `out` was supplied this is a + reference to it. + This is a scalar if `x` is a scalar. + Notes + ------- + This function differs from the original `numpy.degrees + `_ in + the following aspects: + - Input type does not support Python native iterables(list, tuple, ...). Only ndarray is supported. + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + Convert a radian array to degrees + >>> rad = np.arange(12.) * np.pi / 6 + >>> np.degrees(rad) + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + Use specified ``out`` ndarray: + >>> out = np.zeros((rad.shape)) + >>> np.degrees(rad, out) + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + >>> out + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + """ + return _unary_func_helper(x, _npi.degrees, _np.degrees, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def rint(x, out=None, **kwargs): + """ + Round elements of the array to the nearest integer. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.rint + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.rint(a) + array([-2., -2., -0., 0., 1., 2., 2.]) + """ + return _unary_func_helper(x, _npi.rint, _np.rint, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def log2(x, out=None, **kwargs): + """ + Base-2 logarithm of x. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The logarithm base two of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original `numpy.log2 + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> x = np.array([0, 1, 2, 2**4]) + >>> np.log2(x) + array([-inf, 0., 1., 4.]) + """ + return _unary_func_helper(x, _npi.log2, _np.log2, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def log1p(x, out=None, **kwargs): + """ + Return the natural logarithm of one plus the input array, element-wise. + Calculates ``log(1 + x)``. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + Natural logarithm of 1 + x, element-wise. This is a scalar + if x is a scalar. + Notes + ----- + For real-valued input, `log1p` is accurate also for `x` so small + that `1 + x == 1` in floating-point accuracy. + Logarithm is a multivalued function: for each `x` there is an infinite + number of `z` such that `exp(z) = 1 + x`. The convention is to return + the `z` whose imaginary part lies in `[-pi, pi]`. + For real-valued input data types, `log1p` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + cannot support complex-valued input. + Examples + -------- + >>> np.log1p(1e-99) + 1e-99 + >>> a = np.array([3, 4, 5]) + >>> np.log1p(a) + array([1.3862944, 1.609438 , 1.7917595]) + """ + return _unary_func_helper(x, _npi.log1p, _np.log1p, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def radians(x, out=None, **kwargs): + """ + Convert angles from degrees to radians. + Parameters + ---------- + x : ndarray or scalar + Input array in degrees. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The corresponding radian values. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.radians + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> deg = np.arange(12.) * 30. + >>> np.radians(deg) + array([0. , 0.5235988, 1.0471976, 1.5707964, 2.0943952, 2.6179938, + 3.1415927, 3.6651914, 4.1887903, 4.712389 , 5.2359877, 5.7595863], + dtype=float32) + """ + return _unary_func_helper(x, _npi.radians, _np.radians, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def reciprocal(x, out=None, **kwargs): + r""" + reciprocal(x, out=None) + Return the reciprocal of the argument, element-wise. + Calculates ``1/x``. + Parameters + ---------- + x : ndarray or scalar + The values whose reciprocals are required. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Examples + -------- + >>> np.reciprocal(2.) + 0.5 + >>> x = np.array([1, 2., 3.33]) + >>> np.reciprocal(x) + array([1. , 0.5 , 0.3003003]) + Notes + ----- + .. note:: + This function is not designed to work with integers. + For integer arguments with absolute value larger than 1 the result is + always zero because of the way Python handles integer division. For + integer zero the result is an overflow. + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.reciprocal + `_ in + the following aspects: + - Only support ndarray and scalar now. + - `where` argument is not supported. + """ + return _unary_func_helper(x, _npi.reciprocal, _np.reciprocal, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def square(x, out=None, **kwargs): + r""" + square(x, out=None) + Return the element-wise square of the input. + Parameters + ---------- + x : ndarray or scalar + The values whose squares are required. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Examples + -------- + >>> np.square(2.) + 4.0 + >>> x = np.array([1, 2., -1]) + >>> np.square(x) + array([1., 4., 1.]) + Notes + ----- + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.square + `_ in + the following aspects: + - Only support ndarray and scalar now. + - `where` argument is not supported. + - Complex input is not supported. + """ + return _unary_func_helper(x, _npi.square, _np.square, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def negative(x, out=None, where=True, **kwargs): + r""" + negative(x, out=None, where=True) + Numerical negative, element-wise. + Parameters: + ------------ + x : ndarray or scalar + Input array. + out : ndarray, None, or tuple of ndarray and None, optional + A location into which the result is stored. + where : ndarray, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + --------- + y : ndarray or scalar + Returned array or scalar: y = -x. This is a scalar if x is a scalar. + Examples: + --------- + >>> np.negative(1) + -1 + """ + return _unary_func_helper(x, _npi.negative, _np.negative, out=out) + + +@set_module('mxnet.ndarray.numpy') +def fix(x, out=None): + r""" + Round an array of floats element-wise to nearest integer towards zero. + The rounded values are returned as floats. + + Parameters: + ---------- + x : ndarray + An array of floats to be rounded + out : ndarray, optional + Output array + Returns: + ------- + y : ndarray of floats + Examples + --------- + >>> np.fix(3.14) + 3 + """ + return _unary_func_helper(x, _npi.fix, _np.fix, out=out) + + +@set_module('mxnet.ndarray.numpy') +def tan(x, out=None, where=True, **kwargs): + r""" + tan(x, out=None, where=True) + Compute tangent element-wise. + Equivalent to np.sin(x)/np.cos(x) element-wise. + + Parameters: + ---------- + x : array_like + Input array. + out : ndarray, None, or tuple of ndarray and None, optional + A location into which the result is stored. If provided, + it must have a shape that the inputs broadcast to. If not provided or None, + a freshly-allocated array is returned. A tuple (possible only as a keyword argument) + must have length equal to the number of outputs. + where : ndarray, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + ------- + y : ndarray + The corresponding tangent values. This is a scalar if x is a scalar. + Examples: + >>> np.tan(0.5) + 0.5463024898437905 + """ + + return _unary_func_helper(x, _npi.tan, _np.tan, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def ceil(x, out=None, **kwargs): + r""" + Return the ceiling of the input, element-wise. + The ceil of the ndarray `x` is the smallest integer `i`, such that + `i >= x`. It is often denoted as :math:`\lceil x \rceil`. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a same shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + The ceiling of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.ceil(a) + array([-1., -1., -0., 1., 2., 2., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.ceil(np.array(3.5), a) + array(4.) + >>> a + array(4.) + """ + return _unary_func_helper(x, _npi.ceil, _np.ceil, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def floor(x, out=None, **kwargs): + r""" + Return the floor of the input, element-wise. + The floor of the ndarray `x` is the largest integer `i`, such that + `i <= x`. It is often denoted as :math:`\lfloor x \rfloor`. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a same shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + The floor of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.floor(a) + array([-2., -2., -1., 0., 1., 1., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.floor(np.array(3.5), a) + array(3.) + >>> a + array(3.) + """ + return _unary_func_helper(x, _npi.floor, _np.floor, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def trunc(x, out=None, **kwargs): + r""" + trunc(x, out=None) + Return the truncated value of the input, element-wise. + The truncated value of the scalar `x` is the nearest integer `i` which + is closer to zero than `x` is. In short, the fractional part of the + signed number `x` is discarded. + + Parameters + ---------- + x : ndarray or scalar + Input data. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + y : ndarray or scalar + The truncated value of each element in `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.trunc in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.trunc(a) + array([-1., -1., -0., 0., 1., 1., 2.]) + """ + return _unary_func_helper(x, _npi.trunc, _np.trunc, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def logical_not(x, out=None, **kwargs): + r""" + logical_not(x, out=None) + Compute the truth value of NOT x element-wise. + Parameters + ---------- + x : ndarray or scalar + Logical NOT is applied to the elements of `x`. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + y : bool or ndarray of bool + Boolean result with the same shape as `x` of the NOT operation + on elements of `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.logical_not in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + Examples + -------- + >>> x= np.array([True, False, 0, 1]) + >>> np.logical_not(x) + array([0., 1., 1., 0.]) + + >>> x = np.arange(5) + >>> np.logical_not(x<3) + array([0., 0., 0., 1., 1.]) + """ + return _unary_func_helper(x, _npi.logical_not, _np.logical_not, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arcsinh(x, out=None, **kwargs): + r""" + arcsinh(x, out=None) + Inverse hyperbolic sine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arcsinh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arcsinh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `sinh(z) = x`. + + For real-valued input data types, `arcsinh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arcsinh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. DType of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + Examples + -------- + >>> a = np.array([3.2, 5.0]) + >>> np.arcsinh(a) + array([1.8309381, 2.2924316]) + >>> np.arcsinh(1) + 0.0 + """ + return _unary_func_helper(x, _npi.arcsinh, _np.arcsinh, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arccosh(x, out=None, **kwargs): + r""" + arccosh(x, out=None) + Inverse hyperbolic cosine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arccosh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arccosh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `cosh(z) = x`. + + For real-valued input data types, `arccosh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arccosh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + Examples + -------- + >>> a = np.array([3.2, 5.0]) + >>> np.arccosh(a) + array([1.8309381, 2.2924316]) + >>> np.arccosh(1) + 0.0 + """ + return _unary_func_helper(x, _npi.arccosh, _np.arccosh, out=out, **kwargs) + + +@set_module('mxnet.ndarray.numpy') +def arctanh(x, out=None, **kwargs): + r""" + arctanh(x, out=None) + Inverse hyperbolic tangent, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arctanh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arctanh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `tanh(z) = x`. + + For real-valued input data types, `arctanh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arctanh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + Examples + -------- + >>> a = np.array([0.0, -0.5]) + >>> np.arctanh(a) + array([0., -0.54930615]) + >>> np.arctanh(0.0) + 0.0 + """ + return _unary_func_helper(x, _npi.arctanh, _np.arctanh, out=out, **kwargs) + + @set_module('mxnet.ndarray.numpy') def tile(A, reps): r""" diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py index 8988b4eb19c9..44babb98f0e5 100644 --- a/python/mxnet/numpy/multiarray.py +++ b/python/mxnet/numpy/multiarray.py @@ -17,7 +17,7 @@ # specific language governing permissions and limitations # under the License. -# pylint: disable=too-many-lines +# pylint: disable=too-many-lines, unused-argument """numpy ndarray and util functions.""" from __future__ import absolute_import @@ -44,8 +44,11 @@ from ..ndarray.numpy import _internal as _npi __all__ = ['ndarray', 'empty', 'array', 'zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', - 'mod', 'power', 'tensordot', 'linspace', 'expand_dims', 'tile', 'arange', 'split', - 'concatenate'] + 'mod', 'power', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', + 'abs', 'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', + 'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', + 'fix', 'ceil', 'floor', 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', + 'tensordot', 'linspace', 'expand_dims', 'tile', 'arange', 'split', 'concatenate'] # This function is copied from ndarray.py since pylint @@ -1550,6 +1553,1190 @@ def power(x1, x2, out=None): return _mx_nd_np.power(x1, x2, out=out) +@set_module('mxnet.numpy') +def sin(x, out=None, **kwargs): + r"""Trigonometric sine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The sine of each element of x. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.sin(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def cos(x, out=None, **kwargs): + r"""Cosine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding cosine values. This is a scalar if x is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.cos(x, out=out, **kwargs) + + +def sinh(x, out=None, **kwargs): + """Hyperbolic sine, element-wise. + Equivalent to ``1/2 * (np.exp(x) - np.exp(-x))`` or ``-1j * np.sin(1j*x)``. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding hyperbolic sine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.sinh(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def cosh(x, out=None, **kwargs): + """Hyperbolic cosine, element-wise. + Equivalent to ``1/2 * (np.exp(x) + np.exp(-x))`` and ``np.cos(1j*x)``. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The corresponding hyperbolic cosine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.cosh(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def tanh(x, out=None, **kwargs): + """ + Compute hyperbolic tangent element-wise. + Equivalent to ``np.sinh(x)/np.cosh(x)``. + Parameters + ---------- + x : ndarray or scalar. + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ---------- + y : ndarray or scalar + The corresponding hyperbolic tangent values. + Notes + ----- + If `out` is provided, the function writes the result into it, + and returns a reference to `out`. (See Examples) + - input x does not support complex computation (like imaginary number) + >>> np.tanh(np.pi*1j) + TypeError: type not supported + Examples + -------- + >>> np.tanh(np.array[0, np.pi])) + array([0. , 0.9962721]) + >>> np.tanh(np.pi) + 0.99627207622075 + >>> # Example of providing the optional output parameter illustrating + >>> # that what is returned is a reference to said parameter + >>> out1 = np.array(1) + >>> out2 = np.tanh(np.array(0.1), out1) + >>> out2 is out1 + True + >>> # Example of ValueError due to provision of shape mis-matched `out` + >>> np.tanh(np.zeros((3,3)),np.zeros((2,2))) + mxnet.base.MXNetError: + [07:17:36] ../src/ndarray/./../operator/tensor/../elemwise_op_common.h:135: + Check failed: assign(&dattr, vec.at(i)): Incompatible attr in node + at 0-th output: expected [3,3], got [2,2] + """ + return _mx_nd_np.tanh(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def log10(x, out=None, **kwargs): + """Return the base 10 logarithm of the input array, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array or scalar. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs broadcast to. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output is the same as that of the input if the input is an ndarray. + Returns + ------- + y : ndarray or scalar + The logarithm to the base 10 of `x`, element-wise. NaNs are + returned where x is negative. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.log10(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def sqrt(x, out=None, **kwargs): + """ + Return the non-negative square-root of an array, element-wise. + Parameters + ---------- + x : ndarray or scalar + The values whose square-roots are required. + out : ndarray, or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + An array of the same shape as `x`, containing the positive + square-root of each element in `x`. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _mx_nd_np.sqrt(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def cbrt(x, out=None, **kwargs): + """ + Return the cube-root of an array, element-wise. + Parameters + ---------- + x : ndarray + The values whose cube-roots are required. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape that the + inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + y : ndarray + An array of the same shape as x, containing the cube cube-root of each element in x. + If out was provided, y is a reference to it. This is a scalar if x is a scalar. + Examples + ---------- + >>> np.cbrt([1,8,27]) + array([ 1., 2., 3.]) + """ + return _mx_nd_np.cbrt(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def abs(x, out=None, **kwargs): + r"""abs(x, out=None, **kwargs) + Calculate the absolute value element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + absolute : ndarray + An ndarray containing the absolute value of + each element in `x`. This is a scalar if `x` is a scalar. + Examples + -------- + >>> x = np.array([-1.2, 1.2]) + >>> np.abs(x) + array([1.2, 1.2]) + """ + return _mx_nd_np.abs(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def absolute(x, out=None, **kwargs): + """ + Calculate the absolute value element-wise. + np.abs is a shorthand for this function. + Parameters + ---------- + x : ndarray + Input array. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape + that the inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + absolute : ndarray + An ndarray containing the absolute value of each element in x. + Examples + ---------- + >>> x = np.array([-1.2, 1.2]) + >>> np.absolute(x) + array([ 1.2, 1.2]) + """ + return _mx_nd_np.absolute(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def exp(x, out=None, **kwargs): + r"""exp(x, out=None, **kwargs) + Calculate the exponential of all elements in the input array. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array, element-wise exponential of `x`. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> np.exp(1) + 2.718281828459045 + >>> x = np.array([-1, 1, -2, 2]) + >>> np.exp(x) + array([0.36787945, 2.7182817 , 0.13533528, 7.389056 ]) + """ + return _mx_nd_np.exp(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def expm1(x, out=None, **kwargs): + r"""expm1(x, out=None, **kwargs) + Calculate `exp(x) - 1` for all elements in the array. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array, element-wise exponential minus one: `out = exp(x) - 1`. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> np.expm1(1) + 1.718281828459045 + >>> x = np.array([-1, 1, -2, 2]) + >>> np.exp(x) + array([-0.63212056, 1.71828183, -0.86466472, 6.3890561]) + """ + return _mx_nd_np.expm1(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arcsin(x, out=None, **kwargs): + r""" + arcsin(x, out=None) + Inverse sine, element-wise. + Parameters + ---------- + x : ndarray or scalar + `y`-coordinate on the unit circle. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + angle : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + The inverse sine of each element in `x`, in radians and in the + closed interval ``[-pi/2, pi/2]``. + Examples + -------- + >>> np.arcsin(1) # pi/2 + 1.5707963267948966 + >>> np.arcsin(-1) # -pi/2 + -1.5707963267948966 + >>> np.arcsin(0) + 0.0 + Notes + ----- + `arcsin` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that :math:`sin(z) = x`. The convention is to + return the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, *arcsin* always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + The inverse sine is also known as `asin` or sin^{-1}. + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.arcsin + `_ in + the following aspects: + - Only support ndarray or scalar now. + - `where` argument is not supported. + - Complex input is not supported. + References + ---------- + Abramowitz, M. and Stegun, I. A., *Handbook of Mathematical Functions*, + 10th printing, New York: Dover, 1964, pp. 79ff. + http://www.math.sfu.ca/~cbm/aands/ + """ + return _mx_nd_np.arcsin(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arccos(x, out=None, **kwargs): + """ + Trigonometric inverse cosine, element-wise. + The inverse of cos so that, if y = cos(x), then x = arccos(y). + Parameters + ---------- + x : ndarray + x-coordinate on the unit circle. For real arguments, the domain is [-1, 1]. + out : ndarray, optional + A location into which the result is stored. If provided, it must have a shape that + the inputs broadcast to. If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length equal to the number of outputs. + Returns + ---------- + angle : ndarray + The angle of the ray intersecting the unit circle at the given x-coordinate in radians [0, pi]. + This is a scalar if x is a scalar. + See also + ---------- + cos, arctan, arcsin + Notes + ---------- + arccos is a multivalued function: for each x there are infinitely many numbers z such that + cos(z) = x. The convention is to return the angle z whose real part lies in [0, pi]. + For real-valued input data types, arccos always returns real output. + For each value that cannot be expressed as a real number or infinity, it yields nan and sets + the invalid floating point error flag. + The inverse cos is also known as acos or cos^-1. + Examples + ---------- + We expect the arccos of 1 to be 0, and of -1 to be pi: + >>> np.arccos([1, -1]) + array([ 0. , 3.14159265]) + """ + return _mx_nd_np.arccos(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arctan(x, out=None, **kwargs): + r"""arctan(x, out=None, **kwargs) + Trigonometric inverse tangent, element-wise. + The inverse of tan, so that if ``y = tan(x)`` then ``x = arctan(y)``. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. If provided, it must have + a shape that the inputs broadcast to. If not provided or `None`, + a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Out has the same shape as `x`. It lies is in + ``[-pi/2, pi/2]`` (``arctan(+/-inf)`` returns ``+/-pi/2``). + This is a scalar if `x` is a scalar. + Notes + ----- + `arctan` is a multi-valued function: for each `x` there are infinitely + many numbers `z` such that tan(`z`) = `x`. The convention is to return + the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, `arctan` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + For complex-valued input, we do not have support for them yet. + The inverse tangent is also known as `atan` or tan^{-1}. + Examples + -------- + We expect the arctan of 0 to be 0, and of 1 to be pi/4: + >>> x = np.array([0, 1]) + >>> np.arctan(x) + array([0. , 0.7853982]) + >>> np.pi/4 + 0.7853981633974483 + """ + return _mx_nd_np.arctan(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def sign(x, out=None): + """ + sign(x, out=None) + Returns an element-wise indication of the sign of a number. + The `sign` function returns ``-1 if x < 0, 0 if x==0, 1 if x > 0``. Only supports real number. + Parameters + ---------- + x : ndarray or a scalar + Input values. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The sign of `x`. + This is a scalar if `x` is a scalar. + Note + ------- + - Only supports real number as input elements. + - Input type does not support Python native iterables(list, tuple, ...). + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + >>> a = np.array([-5., 4.5]) + >>> np.sign(a) + array([-1., 1.]) + Scalars as input: + >>> np.sign(4.0) + 1.0 + >>> np.sign(0) + 0 + Use ``out`` parameter: + >>> b = np.zeros((2, )) + >>> np.sign(a, out=b) + array([-1., 1.]) + >>> b + array([-1., 1.]) + """ + return _mx_nd_np.sign(x, out=out) + + +@set_module('mxnet.numpy') +def log(x, out=None, **kwargs): + """ + log(x, out=None) + Natural logarithm, element-wise. + The natural logarithm `log` is the inverse of the exponential function, + so that `log(exp(x)) = x`. The natural logarithm is logarithm in base + `e`. + Parameters + ---------- + x : ndarray + Input value. Elements must be of real value. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The natural logarithm of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + Currently only supports data of real values and ``inf`` as input. Returns data of real value, ``inf``, ``-inf`` and + ``nan`` according to the input. + This function differs from the original `numpy.log + `_ in + the following aspects: + - Does not support complex number for now + - Input type does not support Python native iterables(list, tuple, ...). + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + >>> a = np.array([1, np.exp(1), np.exp(2), 0], dtype=np.float64) + >>> np.log(a) + array([ 0., 1., 2., -inf], dtype=float64) + Due to internal calculation mechanism, using default float32 dtype may cause some special behavior: + >>> a = np.array([1, np.exp(1), np.exp(2), 0]) + >>> np.log(a) + array([ 0., 0.99999994, 2., -inf]) + Scalar calculation: + >>> np.log(1) + 0.0 + """ + return _mx_nd_np.log(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def rint(x, out=None, **kwargs): + """ + Round elements of the array to the nearest integer. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + out : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.rint + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.rint(a) + array([-2., -2., -0., 0., 1., 2., 2.]) + """ + return _mx_nd_np.rint(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def log2(x, out=None, **kwargs): + """ + Base-2 logarithm of x. + Parameters + ---------- + x : ndarray or scalar + Input values. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The logarithm base two of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original `numpy.log2 + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> x = np.array([0, 1, 2, 2**4]) + >>> np.log2(x) + array([-inf, 0., 1., 4.]) + """ + return _mx_nd_np.log2(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def log1p(x, out=None, **kwargs): + """ + Return the natural logarithm of one plus the input array, element-wise. + Calculates ``log(1 + x)``. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + Natural logarithm of 1 + x, element-wise. This is a scalar + if x is a scalar. + Notes + ----- + For real-valued input, `log1p` is accurate also for `x` so small + that `1 + x == 1` in floating-point accuracy. + Logarithm is a multivalued function: for each `x` there is an infinite + number of `z` such that `exp(z) = 1 + x`. The convention is to return + the `z` whose imaginary part lies in `[-pi, pi]`. + For real-valued input data types, `log1p` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + cannot support complex-valued input. + Examples + -------- + >>> np.log1p(1e-99) + 1e-99 + >>> a = np.array([3, 4, 5]) + >>> np.log1p(a) + array([1.3862944, 1.609438 , 1.7917595]) + """ + return _mx_nd_np.log1p(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def degrees(x, out=None, **kwargs): + """ + degrees(x, out=None) + Convert angles from radians to degrees. + Parameters + ---------- + x : ndarray + Input value. Elements must be of real value. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape and dtype as input ndarray. + If not provided or `None`, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The corresponding degree values; if `out` was supplied this is a + reference to it. + This is a scalar if `x` is a scalar. + Notes + ------- + This function differs from the original `numpy.degrees + `_ in + the following aspects: + - Input type does not support Python native iterables(list, tuple, ...). Only ndarray is supported. + - ``out`` param: cannot perform auto broadcasting. ``out`` ndarray's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` ndarray's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + Examples + -------- + Convert a radian array to degrees + >>> rad = np.arange(12.) * np.pi / 6 + >>> np.degrees(rad) + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + Use specified ``out`` ndarray: + >>> out = np.zeros((rad.shape)) + >>> np.degrees(rad, out) + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + >>> out + array([ 0., 30., 60., 90., 120., 150., 180., 210., 240., 270., 300., 330.]) + """ + return _mx_nd_np.degrees(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def radians(x, out=None, **kwargs): + """ + Convert angles from degrees to radians. + Parameters + ---------- + x : ndarray or scalar + Input array in degrees. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray + The corresponding radian values. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.radians + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> deg = np.arange(12.) * 30. + >>> np.radians(deg) + array([0. , 0.5235988, 1.0471976, 1.5707964, 2.0943952, 2.6179938, + 3.1415927, 3.6651914, 4.1887903, 4.712389 , 5.2359877, 5.7595863], + dtype=float32) + """ + return _mx_nd_np.radians(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def reciprocal(x, out=None, **kwargs): + r""" + reciprocal(x, out=None) + Return the reciprocal of the argument, element-wise. + Calculates ``1/x``. + Parameters + ---------- + x : ndarray or scalar + The values whose reciprocals are required. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Examples + -------- + >>> np.reciprocal(2.) + 0.5 + >>> x = np.array([1, 2., 3.33]) + >>> np.reciprocal(x) + array([1. , 0.5 , 0.3003003]) + Notes + ----- + .. note:: + This function is not designed to work with integers. + For integer arguments with absolute value larger than 1 the result is + always zero because of the way Python handles integer division. For + integer zero the result is an overflow. + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.reciprocal + `_ in + the following aspects: + - Only support ndarray and scalar now. + - `where` argument is not supported. + """ + return _mx_nd_np.reciprocal(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def square(x, out=None, **kwargs): + r""" + square(x, out=None) + Return the element-wise square of the input. + Parameters + ---------- + x : ndarray or scalar + The values whose squares are required. + out : ndarray or None, optional + A location into which the result is stored. + If provided, it must have the same shape as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : ndarray or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Examples + -------- + >>> np.square(2.) + 4.0 + >>> x = np.array([1, 2., -1]) + >>> np.square(x) + array([1., 4., 1.]) + Notes + ----- + The output `ndarray` has the same `ctx` as the input `ndarray`. + This function differs from the original `numpy.square + `_ in + the following aspects: + - Only support ndarray and scalar now. + - `where` argument is not supported. + - Complex input is not supported. + """ + return _mx_nd_np.square(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def negative(x, out=None, where=True, **kwargs): + r""" + negative(x, out=None, where=True) + Numerical negative, element-wise. + Parameters: + ------------ + x : ndarray or scalar + Input array. + out : ndarray, None, or tuple of ndarray and None, optional + A location into which the result is stored. + If provided, it must have a shape that the inputs broadcast to. + If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length + equal to the number of outputs. + where : ndarray, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + ------- + y : ndarray or scalar + Returned array or scalar: y = -x. This is a scalar if x is a scalar. + Examples: + -------- + >>> np.negative(1) + -1 + """ + return _mx_nd_np.negative(x, out=out) + + +@set_module('mxnet.numpy') +def fix(x, out=None): + """ + Round an array of floats element-wise to nearest integer towards zero. + The rounded values are returned as floats. + + Parameters: + ---------- + x : ndarray + An array of floats to be rounded + out : ndarray, optional + Output array + Returns: + ------- + y : ndarray or scalar + Returned array or scalar: y = -x. This is a scalar if x is a scalar.ndarray of floats + Examples: + --------- + >>> np.fix(3.14) + 3 + """ + return _mx_nd_np.fix(x, out=out) + + +@set_module('mxnet.numpy') +def tan(x, out=None, where=True, **kwargs): + r""" + tan(x, out=None, where=True) + Compute tangent element-wise. + Equivalent to np.sin(x)/np.cos(x) element-wise. + + Parameters: + ---------- + x : ndarray + Input array. + out : ndarray or none, optional + A location into which the result is stored. If provided, + it must have a shape that the inputs broadcast to. If not provided or None, + a freshly-allocated array is returned. A tuple (possible only as a keyword argument) + must have length equal to the number of outputs. + where : ndarray, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + ------- + y : ndarray + The corresponding tangent values. This is a scalar if x is a scalar. + Examples: + --------- + >>> np.tan(0.5) + 0.5463024898437905 + """ + + return _mx_nd_np.tan(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def ceil(x, out=None, **kwargs): + r""" + Return the ceiling of the input, element-wise. + The ceil of the ndarray `x` is the smallest integer `i`, such that + `i >= x`. It is often denoted as :math:`\lceil x \rceil`. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + The ceiling of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.ceil(a) + array([-1., -1., -0., 1., 2., 2., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.ceil(np.array(3.5), a) + array(4.) + >>> a + array(4.) + """ + return _mx_nd_np.ceil(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def floor(x, out=None, **kwargs): + r""" + Return the floor of the input, element-wise. + The ceil of the ndarray `x` is the largest integer `i`, such that + `i <= x`. It is often denoted as :math:`\lfloor x \rfloor`. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None + A location into which the result is stored. If provided, it + must have a shape that the inputs fill into. If not provided + or None, a freshly-allocated array is returned. The dtype of the + output and input must be the same. + Returns + ------- + y : ndarray or scalar + The floor of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.floor(a) + array([-2., -2., -1., 0., 1., 1., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.floor(np.array(3.5), a) + array(3.) + >>> a + array(3.) + """ + return _mx_nd_np.floor(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def trunc(x, out=None, **kwargs): + r""" + trunc(x, out=None) + Return the truncated value of the input, element-wise. + The truncated value of the scalar `x` is the nearest integer `i` which + is closer to zero than `x` is. In short, the fractional part of the + signed number `x` is discarded. + + Parameters + ---------- + x : ndarray or scalar + Input data. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + y : ndarray or scalar + The truncated value of each element in `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.trunc in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.trunc(a) + array([-1., -1., -0., 0., 1., 1., 2.]) + """ + return _mx_nd_np.trunc(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def logical_not(x, out=None, **kwargs): + r""" + logical_not(x, out=None) + Compute the truth value of NOT x element-wise. + Parameters + ---------- + x : ndarray or scalar + Logical NOT is applied to the elements of `x`. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + y : bool or ndarray of bool + Boolean result with the same shape as `x` of the NOT operation + on elements of `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.logical_not in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> x= np.array([True, False, 0, 1]) + >>> np.logical_not(x) + array([0., 1., 1., 0.]) + + >>> x = np.arange(5) + >>> np.logical_not(x<3) + array([0., 0., 0., 1., 1.]) + """ + return _mx_nd_np.logical_not(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arcsinh(x, out=None, **kwargs): + r""" + arcsinh(x, out=None) + Inverse hyperbolic cosine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arcsinh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + + Notes + ----- + `arcsinh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `sinh(z) = x`. + + For real-valued input data types, `arcsinh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arcsinh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. DType of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> a = np.array([3.2, 5.0]) + >>> np.arcsinh(a) + array([1.8309381, 2.2924316]) + + >>> np.arcsinh(1) + 0.0 + """ + return _mx_nd_np.arcsinh(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arccosh(x, out=None, **kwargs): + r""" + arccosh(x, out=None) + Inverse hyperbolic cosine, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arccosh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + + Notes + ----- + `arccosh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `cosh(z) = x`. + + For real-valued input data types, `arccosh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arccosh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> a = np.array([3.2, 5.0]) + >>> np.arccosh(a) + array([1.8309381, 2.2924316]) + + >>> np.arccosh(1) + 0.0 + """ + return _mx_nd_np.arccosh(x, out=out, **kwargs) + + +@set_module('mxnet.numpy') +def arctanh(x, out=None, **kwargs): + r""" + arctanh(x, out=None) + Inverse hyperbolic tangent, element-wise. + Parameters + ---------- + x : ndarray or scalar + Input array. + out : ndarray or None, optional + A location into which the result is stored. + + Returns + ------- + arctanh : ndarray + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + + Notes + ----- + `arctanh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `tanh(z) = x`. + + For real-valued input data types, `arctanh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arctanh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + + Examples + -------- + >>> a = np.array([0.0, -0.5]) + >>> np.arctanh(a) + array([0., -0.54930615]) + + >>> np.arctanh(1) + 0.0 + """ + return _mx_nd_np.arctanh(x, out=out, **kwargs) + + @set_module('mxnet.numpy') def tensordot(a, b, axes=2): r""" diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index a6699d60871a..313deba19182 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -# pylint: disable=too-many-lines +# pylint: disable=too-many-lines, unused-argument """numpy namespace for operators used in Gluon APIs dispatched by F=symbol module.""" from __future__ import absolute_import @@ -29,7 +29,11 @@ from .._internal import _set_np_symbol_class from . import _internal as _npi -__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot', +__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'sin', 'cos', + 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'absolute', 'exp', + 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p', + 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', + 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'tensordot', 'linspace', 'expand_dims', 'tile', 'arange', 'split', 'concatenate'] @@ -1185,6 +1189,968 @@ def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs): raise TypeError('type {} not supported'.format(str(type(x)))) +@set_module('mxnet.symbol.numpy') +def sin(x, out=None, **kwargs): + r"""Trigonometric sine, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The sine of each element of x. + This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sin, _np.sin, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def cos(x, out=None, **kwargs): + r"""Cosine, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Angle, in radians (:math:`2 \pi` rad equals 360 degrees). + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The corresponding cosine values. This is a scalar if x is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.cos, _np.cos, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def sinh(x, out=None, **kwargs): + """Hyperbolic sine, element-wise. + Equivalent to ``1/2 * (np.exp(x) - np.exp(-x))`` or ``-1j * np.sin(1j*x)``. + Parameters + ---------- + x : _Symbol or scalar + Input array or scalar. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + The corresponding hyperbolic sine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sinh, _np.sinh, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def cosh(x, out=None, **kwargs): + """Hyperbolic cosine, element-wise. + Equivalent to ``1/2 * (np.exp(x) + np.exp(-x))`` and ``np.cos(1j*x)``. + Parameters + ---------- + x : _Symbol or scalar + Input array or scalar. + out : ndarray or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + The corresponding hyperbolic cosine values. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.cosh, _np.cosh, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def tanh(x, out=None, **kwargs): + """ + Compute hyperbolic tangent element-wise. + Equivalent to ``np.sinh(x)/np.cosh(x)``. + Parameters + ---------- + x : _Symbol + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The corresponding hyperbolic tangent values. + Notes + ----- + If `out` is provided, the function writes the result into it, + and returns a reference to `out`. (See Examples) + - input x does not support complex computation (like imaginary number) + >>> np.tanh(np.pi*1j) + TypeError: type not supported + Examples + -------- + >>> np.tanh(np.array[0, np.pi])) + array([0. , 0.9962721]) + >>> np.tanh(np.pi) + 0.99627207622075 + >>> # Example of providing the optional output parameter illustrating + >>> # that what is returned is a reference to said parameter + >>> out1 = np.array(1) + >>> out2 = np.tanh(np.array(0.1), out1) + >>> out2 is out1 + True + >>> # Example of ValueError due to provision of shape mis-matched `out` + >>> np.tanh(np.zeros((3,3)),np.zeros((2,2))) + mxnet.base.MXNetError: + [07:17:36] ../src/ndarray/./../operator/tensor/../elemwise_op_common.h:135: + Check failed: assign(&dattr, vec.at(i)): Incompatible attr in node + at 0-th output: expected [3,3], got [2,2] + """ + return _unary_func_helper(x, _npi.tanh, _np.tanh, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def log10(x, out=None, **kwargs): + """Return the base 10 logarithm of the input array, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Input array or scalar. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + The logarithm to the base 10 of `x`, element-wise. NaNs are + returned where x is negative. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.log10, _np.log10, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def sqrt(x, out=None, **kwargs): + """ + Return the non-negative square-root of an array, element-wise. + Parameters + ---------- + x : _Symbol or scalar + The values whose square-roots are required. + out : _Symbol, or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + An array of the same shape as `x`, containing the positive + square-root of each element in `x`. This is a scalar if `x` is a scalar. + Notes + ---- + This function only supports input type of float. + """ + return _unary_func_helper(x, _npi.sqrt, _np.sqrt, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def cbrt(x, out=None, **kwargs): + r""" + Return the cube-root of an array, element-wise. + Parameters + ---------- + x : _Symbol + The values whose cube-roots are required. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ---------- + y : _Symbol + An array of the same shape as x, containing the cube cube-root of each element in x. + If out was provided, y is a reference to it. This is a scalar if x is a scalar. + """ + return _unary_func_helper(x, _npi.cbrt, _np.cbrt, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def abs(x, out=None, **kwargs): + r"""abs(x, out=None, **kwargs) + Calculate the absolute value element-wise. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + absolute : _Symbol + An ndarray containing the absolute value of + each element in `x`. This is a scalar if `x` is a scalar. + """ + return _unary_func_helper(x, _npi.abs, _np.abs, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def absolute(x, out=None, **kwargs): + r""" + Calculate the absolute value element-wise. + np.abs is a shorthand for this function. + Parameters + ---------- + x : _Symbol + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ---------- + absolute : _Symbol + An ndarray containing the absolute value of each element in x. + """ + return _unary_func_helper(x, _npi.absolute, _np.absolute, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def sign(x, out=None, **kwargs): + r""" + sign(x, out=None) + Returns an element-wise indication of the sign of a number. + The `sign` function returns ``-1 if x < 0, 0 if x==0, 1 if x > 0``. Only supports real number. + Parameters + ---------- + x : _Symbol or a scalar + Input values. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The sign of `x`. + This is a scalar if `x` is a scalar. + Note + ------- + - Only supports real number as input elements. + - Input type does not support Python native iterables(list, tuple, ...) + - ``out`` param: cannot perform auto broadcasting. ``out`` symbol's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` symbol's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + """ + return _unary_func_helper(x, _npi.sign, _np.sign, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def exp(x, out=None, **kwargs): + r"""exp(x, out=None, **kwargs) + Calculate the exponential of all elements in the input array. + Parameters + ---------- + x : _Symbol or scalar + Input values. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + out : _Symbol + Output array, element-wise exponential of `x`. + This is a scalar if `x` is a scalar. + """ + return _unary_func_helper(x, _npi.exp, _np.exp, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def expm1(x, out=None, **kwargs): + r"""expm1(x, out=None, **kwargs) + Calculate `exp(x) - 1` for all elements in the array. + Parameters + ---------- + x : _Symbol or scalar + Input values. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + out : _Symbol + Output array, . + This is a scalar if `x` is a scalar. + """ + return _unary_func_helper(x, _npi.expm1, _np.expm1, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arcsin(x, out=None, **kwargs): + r""" + arcsin(x, out=None) + Inverse sine, element-wise. + Parameters + ---------- + x : _Symbol or scalar + The values whose reciprocals are required. + out : _Symbol, or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + angle : _Symbol or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + `arcsin` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that :math:`sin(z) = x`. The convention is to + return the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, *arcsin* always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + The inverse sine is also known as `asin` or sin^{-1}. + The output `symbol` has the same `ctx` as the input `symbol`. + This function differs from the original `numpy.arcsin + `_ in + the following aspects: + - Only support _Symbol or scalar now. + - `where` argument is not supported. + - Complex input is not supported. + References + ---------- + Abramowitz, M. and Stegun, I. A., *Handbook of Mathematical Functions*, + 10th printing, New York: Dover, 1964, pp. 79ff. + http://www.math.sfu.ca/~cbm/aands/ + """ + return _unary_func_helper(x, _npi.arcsin, _np.arcsin, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arccos(x, out=None, **kwargs): + r""" + Trigonometric inverse cosine, element-wise. + The inverse of cos so that, if y = cos(x), then x = arccos(y). + Parameters + ---------- + x : _Symbol + x-coordinate on the unit circle. For real arguments, the domain is [-1, 1]. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ---------- + angle : _Symbol + The angle of the ray intersecting the unit circle at the given x-coordinate in radians [0, pi]. + This is a scalar if x is a scalar. + See also + ---------- + cos, arctan, arcsin + Notes + ---------- + arccos is a multivalued function: for each x there are infinitely many numbers z such that + cos(z) = x. The convention is to return the angle z whose real part lies in [0, pi]. + For real-valued input data types, arccos always returns real output. + For each value that cannot be expressed as a real number or infinity, it yields nan and sets + the invalid floating point error flag. + The inverse cos is also known as acos or cos^-1. + """ + return _unary_func_helper(x, _npi.arccos, _np.arccos, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arctan(x, out=None, **kwargs): + r"""arctan(x, out=None, **kwargs) + Trigonometric inverse tangent, element-wise. + The inverse of tan, so that if ``y = tan(x)`` then ``x = arctan(y)``. + Parameters + ---------- + x : _Symbol or scalar + Input values. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + out : _Symbol + Out has the same shape as `x`. It lies is in + ``[-pi/2, pi/2]`` (``arctan(+/-inf)`` returns ``+/-pi/2``). + This is a scalar if `x` is a scalar. + Notes + ----- + `arctan` is a multi-valued function: for each `x` there are infinitely + many numbers `z` such that tan(`z`) = `x`. The convention is to return + the angle `z` whose real part lies in [-pi/2, pi/2]. + For real-valued input data types, `arctan` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + For complex-valued input, we do not have support for them yet. + The inverse tangent is also known as `atan` or tan^{-1}. + """ + return _unary_func_helper(x, _npi.arctan, _np.arctan, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def log(x, out=None, **kwargs): + """ + log(x, out=None) + Natural logarithm, element-wise. + The natural logarithm `log` is the inverse of the exponential function, + so that `log(exp(x)) = x`. The natural logarithm is logarithm in base + `e`. + Parameters + ---------- + x : _Symbol + Input value. Elements must be of real value. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The natural logarithm of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + Currently only supports data of real values and ``inf`` as input. Returns data of real value, ``inf``, ``-inf`` and + ``nan`` according to the input. + This function differs from the original `numpy.log + `_ in + the following aspects: + - Does not support complex number for now + - Input type does not support Python native iterables(list, tuple, ...). Only ndarray is supported. + - ``out`` param: cannot perform auto braodcasting. ``out`` symbol's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` symbol's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + """ + return _unary_func_helper(x, _npi.log, _np.log, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def degrees(x, out=None, **kwargs): + """ + degrees(x, out=None) + Convert angles from radians to degrees. + Parameters + ---------- + x : _Symbol + Input value. Elements must be of real value. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol of floats + The corresponding degree values; if `out` was supplied this is a + reference to it. + This is a scalar if `x` is a scalar. + Notes + ------- + This function differs from the original `numpy.degrees + `_ in + the following aspects: + - Input type does not support Python native iterables(list, tuple, ...). Only ndarray is supported. + - ``out`` param: cannot perform auto broadcasting. ``out`` symbol's shape must be the same as the expected output. + - ``out`` param: cannot perform auto type cast. ``out`` symbol's dtype must be the same as the expected output. + - ``out`` param does not support scalar input case. + """ + return _unary_func_helper(x, _npi.degrees, _np.degrees, out=out, **kwargs) + + +def rint(x, out=None, **kwargs): + """ + Round elements of the array to the nearest integer. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + out : _Symbol or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.rint + `_ in + the following way(s): + - only _Symbol or scalar is accpted as valid input, tuple of _Symbol is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + """ + return _unary_func_helper(x, _npi.rint, _np.rint, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def log2(x, out=None, **kwargs): + """ + Base-2 logarithm of x. + Parameters + ---------- + x : _Symbol + Input values. + out : ndarray or None + A location into which the result is stored. + If provided, it must have the same shape and type as the input. + If not provided or None, a freshly-allocated array is returned. + Returns + ------- + y : _Symbol + The logarithm base two of `x`, element-wise. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original `numpy.log2 + `_ in + the following way(s): + - only ndarray or scalar is accpted as valid input, tuple of ndarray is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + """ + return _unary_func_helper(x, _npi.log2, _np.log2, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def log1p(x, out=None, **kwargs): + """ + Return the natural logarithm of one plus the input array, element-wise. + Calculates ``log(1 + x)``. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + Natural logarithm of 1 + x, element-wise. This is a scalar + if x is a scalar. + Notes + ----- + For real-valued input, `log1p` is accurate also for `x` so small + that `1 + x == 1` in floating-point accuracy. + Logarithm is a multivalued function: for each `x` there is an infinite + number of `z` such that `exp(z) = 1 + x`. The convention is to return + the `z` whose imaginary part lies in `[-pi, pi]`. + For real-valued input data types, `log1p` always returns real output. + For each value that cannot be expressed as a real number or infinity, + it yields ``nan`` and sets the `invalid` floating point error flag. + cannot support complex-valued input. + Examples + -------- + >>> np.log1p(1e-99) + 1e-99 + >>> a = np.array([3, 4, 5]) + >>> np.log1p(a) + array([1.3862944, 1.609438 , 1.7917595]) + """ + return _unary_func_helper(x, _npi.log1p, _np.log1p, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def radians(x, out=None, **kwargs): + """ + Convert angles from degrees to radians. + Parameters + ---------- + x : _Symbol or scalar + Input array in degrees. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol + The corresponding radian values. This is a scalar if x is a scalar. + Notes + ----- + This function differs from the original `numpy.radians + `_ in + the following way(s): + - only _Symbol or scalar is accpted as valid input, tuple of _Symbol is not supported + - broadcasting to `out` of different shape is currently not supported + - when input is plain python numerics, the result will not be stored in the `out` param + Examples + -------- + >>> deg = np.arange(12.) * 30. + >>> np.radians(deg) + array([0. , 0.5235988, 1.0471976, 1.5707964, 2.0943952, 2.6179938, + 3.1415927, 3.6651914, 4.1887903, 4.712389 , 5.2359877, 5.7595863], + dtype=float32) + """ + return _unary_func_helper(x, _npi.radians, _np.radians, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def reciprocal(x, out=None, **kwargs): + r""" + reciprocal(x, out=None) + Return the reciprocal of the argument, element-wise. + Calculates ``1/x``. + Parameters + ---------- + x : _Symbol or scalar + The values whose reciprocals are required. + out : _Symbol, or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + .. note:: + This function is not designed to work with integers. + For integer arguments with absolute value larger than 1 the result is + always zero because of the way Python handles integer division. For + integer zero the result is an overflow. + The output `symbol` has the same `ctx` as the input `symbol`. + This function differs from the original `numpy.reciprocal + `_ in + the following aspects: + - Only support _Symbol and scalar now. + - `where` argument is not supported. + """ + return _unary_func_helper(x, _npi.reciprocal, _np.reciprocal, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def square(x, out=None, **kwargs): + r""" + square(x, out=None) + Return the element-wise square of the input. + Parameters + ---------- + x : _Symbol or scalar + The values whose reciprocals are required. + out : _Symbol, or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : _Symbol or scalar + Output array is same shape and type as x. This is a scalar if x is a scalar. + Notes + ----- + The output `symbol` has the same `ctx` as the input `symbol`. + This function differs from the original `numpy.square + `_ in + the following aspects: + - Only support _Symbol and scalar now. + - `where` argument is not supported. + """ + return _unary_func_helper(x, _npi.square, _np.square, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def negative(x, out=None, where=True, **kwargs): + r""" + negative(x, out=None, where=True) + Numerical negative, element-wise. + Parameters: + ------------ + x : _Symbol or scalar + Input array. + out : _Symbol or None, optional + A location into which the result is stored. + If provided, it must have a shape that the inputs broadcast to. + If not provided or None, a freshly-allocated array is returned. + A tuple (possible only as a keyword argument) must have length + equal to the number of outputs. + where : _Symbol or scalar, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + ------- + y : _Symbol or scalar + Returned array or scalar: y = -x. This is a scalar if x is a scalar. + Examples: + --------- + >>> np.negative(1) + -1 + """ + return _unary_func_helper(x, _npi.negative, _np.negative, out=out) + + +@set_module('mxnet.symbol.numpy') +def fix(x, out=None): + """ + Round to nearest integer towards zero. + + Round an array of floats element-wise to nearest integer towards zero. The rounded values are returned as floats. + + Parameters: + ---------- + x : _Symbol or scalar + An array of floats to be rounded + out : _Symbol or scalar, optional + Output array + Returns: + --------- + y : _Symbol or scalar + Examples: + ---------- + >>> np.fix(3.14) + 3 + """ + return _unary_func_helper(x, _npi.fix, _np.fix, out=out) + + +@set_module('mxnet.symbol.numpy') +def tan(x, out=None, where=True, **kwargs): + r""" + tan(x, out=None, where=True) + Compute tangent element-wise. + Equivalent to np.sin(x)/np.cos(x) element-wise. + + Parameters: + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or scalar or None. + A location into which the result is stored. If provided, + it must have a shape that the inputs broadcast to. If not provided or None, + a freshly-allocated array is returned. A tuple (possible only as a keyword argument) + must have length equal to the number of outputs. + where : array_like, optional + Values of True indicate to calculate the ufunc at that position, + values of False indicate to leave the value in the output alone. + Returns: + ------- + y : _Symbol or scalar + The corresponding tangent values. This is a scalar if x is a scalar. + """ + + return _unary_func_helper(x, _npi.tan, _np.tan, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def ceil(x, out=None, **kwargs): + r""" + Return the ceiling of the input, element-wise. + The ceil of the ndarray `x` is the smallest integer `i`, such that + `i >= x`. It is often denoted as :math:`\lceil x \rceil`. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : + _Symbol or scalar + The ceiling of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.ceil(a) + array([-1., -1., -0., 1., 2., 2., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.ceil(np.array(3.5), a) + array(4.) + >>> a + array(4.) + """ + return _unary_func_helper(x, _npi.ceil, _np.ceil, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def floor(x, out=None, **kwargs): + r""" + Return the floor of the input, element-wise. + The floor of the ndarray `x` is the largest integer `i`, such that + `i <= x`. It is often denoted as :math:`\lfloor x \rfloor`. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None + Dummy parameter to keep the consistency with the ndarray counterpart. + Returns + ------- + y : + _Symbol or scalar + The floor of each element in `x`, with `float` dtype. + This is a scalar if `x` is a scalar. + Examples + -------- + >>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) + >>> np.floor(a) + array([-2., -2., -1., 0., 1., 1., 2.]) + >>> #if you use parameter out, x and out must be ndarray. if not, you will get an error! + >>> a = np.array(1) + >>> np.floor(np.array(3.5), a) + array(3.) + >>> a + array(3.) + """ + return _unary_func_helper(x, _npi.floor, _np.floor, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def trunc(x, out=None, **kwargs): + r""" + trunc(x, out=None) + Return the truncated value of the input, element-wise. + The truncated value of the scalar `x` is the nearest integer `i` which + is closer to zero than `x` is. In short, the fractional part of the + signed number `x` is discarded. + + Parameters + ---------- + x : _Symbol or scalar + Input data. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + + Returns + ------- + y : _Symbol or scalar + The truncated value of each element in `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.trunc in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + """ + return _unary_func_helper(x, _npi.trunc, _np.trunc, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def logical_not(x, out=None, **kwargs): + r""" + logical_not(x, out=None) + Compute the truth value of NOT x element-wise. + Parameters + ---------- + x : _Symbol or scalar + Logical NOT is applied to the elements of `x`. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + + Returns + ------- + y : bool or _Symbol + Boolean result with the same shape as `x` of the NOT operation + on elements of `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + This function differs from the original numpy.logical_not in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + """ + return _unary_func_helper(x, _npi.logical_not, _np.logical_not, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arcsinh(x, out=None, **kwargs): + r""" + arcsinh(x, out=None) + Inverse hyperbolic sine, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + + Returns + ------- + arcsinh : _Symbol + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arcsinh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `sinh(z) = x`. + + For real-valued input data types, `arcsinh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arcsinh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. DType of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + """ + return _unary_func_helper(x, _npi.arcsinh, _np.arcsinh, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arccosh(x, out=None, **kwargs): + r""" + arccosh(x, out=None) + Inverse hyperbolic cosine, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + + Returns + ------- + arccosh : _Symbol + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arccosh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `cosh(z) = x`. + + For real-valued input data types, `arccosh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arccosh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + """ + return _unary_func_helper(x, _npi.arccosh, _np.arccosh, out=out, **kwargs) + + +@set_module('mxnet.symbol.numpy') +def arctanh(x, out=None, **kwargs): + r""" + arctanh(x, out=None) + Inverse hyperbolic tangent, element-wise. + Parameters + ---------- + x : _Symbol or scalar + Input array. + out : _Symbol or None, optional + Dummy parameter to keep the consistency with the ndarray counterpart. + + Returns + ------- + arctanh : _Symbol + Array of the same shape as `x`. + This is a scalar if `x` is a scalar. + Notes + ----- + `arctanh` is a multivalued function: for each `x` there are infinitely + many numbers `z` such that `tanh(z) = x`. + + For real-valued input data types, `arctanh` always returns real output. + For each value that cannot be expressed as a real number or infinity, it + yields ``nan`` and sets the `invalid` floating point error flag. + + This function differs from the original numpy.arctanh in the following aspects: + - Do not support `where`, a parameter in numpy which indicates where to calculate. + - Do not support complex-valued input. + - Cannot cast type automatically. Dtype of `out` must be same as the expected one. + - Cannot broadcast automatically. Shape of `out` must be same as the expected one. + - If `x` is plain python numeric, the result won't be stored in out. + """ + return _unary_func_helper(x, _npi.arctanh, _np.arctanh, out=out, **kwargs) + + @set_module('mxnet.symbol.numpy') def tile(A, reps): r""" diff --git a/src/operator/numpy/np_elemwise_unary_op_basic.cc b/src/operator/numpy/np_elemwise_unary_op_basic.cc new file mode 100644 index 000000000000..b5764a7fbb4b --- /dev/null +++ b/src/operator/numpy/np_elemwise_unary_op_basic.cc @@ -0,0 +1,366 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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 + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * \file np_elemwise_unary_op_basic.cc + * \brief CPU Implementation of numpy elementwise unary function. + */ +#include +#include "../tensor/elemwise_unary_op.h" + +namespace mxnet { +namespace op { + +MXNET_OPERATOR_REGISTER_UNARY(_npx_relu) +.describe(R"code(Computes rectified linear activation. +.. math:: + max(features, 0) +)code" ADD_FILELINE) +.set_attr("FCompute", UnaryOp::Compute) +.set_attr("FGradient", ElemwiseGradUseOut{"_backward_relu"}); + +MXNET_OPERATOR_REGISTER_UNARY(_npx_sigmoid) +.describe(R"code(Computes sigmoid of x element-wise. +.. math:: + y = 1 / (1 + exp(-x)) +)code" ADD_FILELINE) +.set_attr("FCompute", UnaryOp::Compute) +.set_attr("FGradient", ElemwiseGradUseOut{"_backward_sigmoid"}); + +NNVM_REGISTER_OP(_np_copy) +.describe(R"code(Return an array copy of the given object.)code" ADD_FILELINE) +.set_num_inputs(1) +.set_num_outputs(1) +.set_attr("FInferShape", ElemwiseShape<1, 1>) +.set_attr("FInferType", ElemwiseType<1, 1>) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 0}}; + }) +.set_attr("FCompute", UnaryOp::IdentityCompute) +.set_attr("FInplaceIdentity", + [](const NodeAttrs& attrs){ + return std::vector{true}; + }) +.set_attr("FGradient", ElemwiseGradUseNone{"_copy"}) +.set_attr("FListInputNames", + [](const NodeAttrs& attrs) { + return std::vector{"a"}; + }) +.add_argument("a", "NDArray-or-Symbol", "The input"); + +#define MXNET_OPERATOR_REGISTER_NUMPY_UNARY(__name$, __input_name$, __kernel$) \ +NNVM_REGISTER_OP(__name$) \ +.set_num_inputs(1) \ +.set_num_outputs(1) \ +.set_attr("FInferShape", ElemwiseShape<1, 1>) \ +.set_attr("FInferType", ElemwiseType<1, 1>) \ +.set_attr("FInplaceOption", \ + [](const NodeAttrs& attrs){ \ + return std::vector >{{0, 0}}; \ + }) \ +.set_attr("FListInputNames", \ + [](const NodeAttrs& attrs) { \ + return std::vector{__input_name$}; \ + }) \ +.set_attr("FCompute", UnaryOp::Compute) \ +.add_argument(__input_name$, "NDArray-or-Symbol", "The input array.") + +// negative +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_negative, "x", mshadow_op::negation) +.describe(R"code(Numerical negative, element-wise. +Example:: + negative([1., -1.]) = [-1., 1.] +)code") +.set_attr("FGradient", ElemwiseGradUseNone{"negative"}); + +// reciprocal +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_reciprocal, "x", mshadow_op::reciprocal) +.describe(R"code(Return the reciprocal of the argument, element-wise. +Example:: + reciprocal([-2, 1, 3, 1.6, 0.2]) = [-0.5, 1.0, 0.33333334, 0.625, 5.0] +)code") +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_reciprocal"}); + +// abs +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_absolute, "x", mshadow_op::abs) +.add_alias("_npi_abs") +.describe(R"code(Returns element-wise absolute value of the input. +Example:: + absolute([-2, 0, 3]) = [2, 0, 3] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_abs"}); + +// sign +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_sign, "x", mshadow_op::sign) +.describe(R"code(Returns an element-wise indication of the sign of a number. +The sign function returns -1 if x < 0, 0 if x==0, 1 if x > 0. +Example:: + sign([-2, 0, 3]) = [-1, 0, 1] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_sign"}); + +// rint +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_rint, "x", mshadow_op::rint) +.describe(R"code(Round elements of the array to the nearest integer. +Example:: + rint([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) = [-2., -2., -0., 0., 2., 2., 2.] +)code" ADD_FILELINE) +.set_attr("FGradient", MakeZeroGradNodes); + +// ceil +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_ceil, "x", mshadow_op::ceil) +.describe(R"code(Return the ceiling of the input, element-wise. +The ceil of the scalar x is the smallest integer i, such that i >= x. +Example:: + ceil([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) = [-1., -1., -0., 1., 2., 2., 2.] +)code" ADD_FILELINE) +.set_attr("FGradient", MakeZeroGradNodes); + +// floor +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_floor, "x", mshadow_op::floor) +.describe(R"code(Return the floor of the input, element-wise. +The floor of the scalar x is the largest integer i, such that i <= x. +Example:: + floor([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) = [-2., -2., -1., 0., 1., 1., 2.] +)code" ADD_FILELINE) +.set_attr("FGradient", MakeZeroGradNodes); + +// trunc +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_trunc, "x", mshadow_op::trunc) +.describe(R"code(Return the truncated value of the input, element-wise. +The truncated value of the scalar x is the nearest integer i which is closer to +zero than x is. In short, the fractional part of the signed number x is discarded. +Example:: + trunc([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) = [-1., -1., -0., 0., 1., 1., 2.] +)code" ADD_FILELINE) +.set_attr("FGradient", MakeZeroGradNodes); + +// fix +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_fix, "x", mshadow_op::fix) +.describe(R"code(Round to nearest integer towards zero. +Round an array of floats element-wise to nearest integer towards zero. +The rounded values are returned as floats. +Example:: + fix([-2.1, -1.9, 1.9, 2.1]) = [-2., -1., 1., 2.] +)code" ADD_FILELINE) +.set_attr("FGradient", MakeZeroGradNodes); + +// square +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_square, "x", mshadow_op::square) +.describe(R"code(Return the element-wise square of the input. +Example:: + square([2, 3, 4]) = [4, 9, 16] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_square"}); + +// sqrt +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_sqrt, "x", mshadow_op::square_root) +.describe(R"code(Return the non-negative square-root of an array, element-wise. +Example:: + sqrt([4, 9, 16]) = [2, 3, 4] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseOut{"_backward_sqrt"}); + +// cbrt +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_cbrt, "x", mshadow_op::cube_root) +.describe(R"code(Return the cube-root of an array, element-wise. +Example:: + cbrt([1, 8, -125]) = [1, 2, -5] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseOut{"_backward_cbrt"}); + +// exp +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_exp, "x", mshadow_op::exp) +.describe(R"code(Calculate the exponential of all elements in the input array. +Example:: + exp([0, 1, 2]) = [1., 2.71828175, 7.38905621] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseOut{"_mul"}); + +// log +NNVM_REGISTER_OP(_npi_log) +.describe(R"code(Returns element-wise Natural logarithmic value of the input. +The natural logarithm is logarithm in base *e*, so that ``log(exp(x)) = x`` +)code" ADD_FILELINE) +.set_num_inputs(1) +.set_num_outputs(1) +.set_attr("FInferShape", ElemwiseShape<1, 1>) +.set_attr("FInferType", ElemwiseType<1, 1>) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 0}}; + }) +.set_attr("FListInputNames", + [](const NodeAttrs& attrs) { + return std::vector{"x"}; + }) +.set_attr("FCompute", UnaryOp::Compute) +.add_argument("x", "NDArray-or-Symbol", "The input array.") +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_log"}); + +// log10 +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_log10, "x", mshadow_op::log10) +.describe(R"code(Returns element-wise Base-10 logarithmic value of the input. +``10**log10(x) = x`` +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_log10"}); + +// log2 +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_log2, "x", mshadow_op::log2) +.describe(R"code(Returns element-wise Base-2 logarithmic value of the input. +``2**log2(x) = x`` +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_log2"}); + +// log1p +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_log1p, "x", mshadow_op::log1p) +.describe(R"code(Return the natural logarithm of one plus the input array, element-wise. +Calculates ``log(1 + x)``. +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_log1p"}); + +// expm1 +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_expm1, "x", mshadow_op::expm1) +.describe(R"code(Calculate ``exp(x) - 1`` for all elements in the array.)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_expm1"}); + + +// logical_not +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_logical_not, "x", mshadow_op::nt) +.describe(R"code(Compute the truth value of NOT x element-wise. +Example:: + logical_not([-2., 0., 1.]) = [0., 1., 0.] +)code") +.set_attr("FGradient", MakeZeroGradNodes); + +// sin +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_sin, "x", mshadow_op::sin) +.describe(R"code(Trigonometric sine, element-wise. +.. math:: + sin([0, \pi/4, \pi/2]) = [0, 0.707, 1] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_sin" }); + +// cos +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_cos, "x", mshadow_op::cos) +.describe(R"code(Computes the element-wise cosine of the input array. +.. math:: + cos([0, \pi/4, \pi/2]) = [1, 0.707, 0] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_cos"}); + +// tan +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_tan, "x", mshadow_op::tan) +.describe(R"code(Computes the element-wise tangent of the input array. +.. math:: + tan([0, \pi/4, \pi/2]) = [0, 1, -inf] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseOut{ "_backward_tan" }); + +// arcsin +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arcsin, "x", mshadow_op::arcsin) +.describe(R"code(Returns element-wise inverse sine of the input array. +.. math:: + arcsin([-1, -.707, 0, .707, 1]) = [-\pi/2, -\pi/4, 0, \pi/4, \pi/2] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arcsin" }); + +// arccos +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arccos, "x", mshadow_op::arccos) +.describe(R"code(Returns element-wise inverse cosine of the input array. +The input should be in range `[-1, 1]`. +The output is in the closed interval :math:`[0, \pi]` +.. math:: + arccos([-1, -.707, 0, .707, 1]) = [\pi, 3\pi/4, \pi/2, \pi/4, 0] +The storage type of ``arccos`` output is always dense +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arccos" }); + +// arctan +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arctan, "x", mshadow_op::arctan) +.describe(R"code(Returns element-wise inverse tangent of the input array. +.. math:: + arctan([-1, 0, 1]) = [-\pi/4, 0, \pi/4] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arctan" }); + +// degrees +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_degrees, "x", mshadow_op::degrees) +.describe(R"code(Converts each element of the input array from radians to degrees. +.. math:: + degrees([0, \pi/2, \pi, 3\pi/2, 2\pi]) = [0, 90, 180, 270, 360] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_degrees" }); + +// radians +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_radians, "x", mshadow_op::radians) +.describe(R"code(Converts each element of the input array from degrees to radians. +.. math:: + radians([0, 90, 180, 270, 360]) = [0, \pi/2, \pi, 3\pi/2, 2\pi] +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_radians" }); + +// sinh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_sinh, "x", mshadow_op::sinh) +.describe(R"code(Returns the hyperbolic sine of the input array, computed element-wise. +.. math:: + sinh(x) = 0.5\times(exp(x) - exp(-x)) +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_sinh" }); + +// cosh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_cosh, "x", mshadow_op::cosh) +.describe(R"code(Returns the hyperbolic cosine of the input array, computed element-wise. +.. math:: + cosh(x) = 0.5\times(exp(x) + exp(-x)) +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_cosh" }); + +// tanh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_tanh, "x", mshadow_op::tanh) +.describe(R"code(Returns the hyperbolic tangent of the input array, computed element-wise. +.. math:: + tanh(x) = sinh(x) / cosh(x) +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseOut{ "_backward_tanh" }); + +// arcsinh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arcsinh, "x", mshadow_op::arcsinh) +.describe(R"code(Returns the element-wise inverse hyperbolic sine of the input array, \ +computed element-wise. +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arcsinh" }); + +// arccosh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arccosh, "x", mshadow_op::arccosh) +.describe(R"code(Returns the element-wise inverse hyperbolic cosine of the input array, \ +computed element-wise. +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arccosh" }); + +// arctanh +MXNET_OPERATOR_REGISTER_NUMPY_UNARY(_npi_arctanh, "x", mshadow_op::arctanh) +.describe(R"code(Returns the element-wise inverse hyperbolic tangent of the input array, \ +computed element-wise. +)code" ADD_FILELINE) +.set_attr("FGradient", ElemwiseGradUseIn{ "_backward_arctanh" }); + +} // namespace op +} // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_unary_op_basic.cu b/src/operator/numpy/np_elemwise_unary_op_basic.cu new file mode 100644 index 000000000000..cb8bb771b27d --- /dev/null +++ b/src/operator/numpy/np_elemwise_unary_op_basic.cu @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * 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 + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * \file np_elemwise_unary_op_basic.cu + * \brief GPU Implementation of numpy unary functions. + */ +#include "../tensor/elemwise_binary_op.h" + +namespace mxnet { +namespace op { + +NNVM_REGISTER_OP(_npx_relu) +.set_attr("FCompute", UnaryOp::Compute); + +NNVM_REGISTER_OP(_npx_sigmoid) +.set_attr("FCompute", UnaryOp::Compute); + +NNVM_REGISTER_OP(_np_copy) +.set_attr("FCompute", UnaryOp::IdentityCompute); + +#define MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(__name$, __kernel$) \ +NNVM_REGISTER_OP(__name$) \ +.set_attr("FCompute", UnaryOp::Compute) \ + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_negative, mshadow_op::negation); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_reciprocal, mshadow_op::reciprocal); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_absolute, mshadow_op::abs); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_sign, mshadow_op::sign); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_rint, mshadow_op::rint); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_ceil, mshadow_op::ceil); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_floor, mshadow_op::floor); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_trunc, mshadow_op::trunc); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_fix, mshadow_op::fix); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_square, mshadow_op::square); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_sqrt, mshadow_op::square_root); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_cbrt, mshadow_op::cube_root); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_exp, mshadow_op::exp); + +NNVM_REGISTER_OP(_npi_log) +.set_attr("FCompute", UnaryOp::Compute); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_log10, mshadow_op::log10); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_log2, mshadow_op::log2); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_log1p, mshadow_op::log1p); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_expm1, mshadow_op::expm1); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_logical_not, mshadow_op::nt); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_sin, mshadow_op::sin); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_cos, mshadow_op::cos); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_tan, mshadow_op::tan); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arcsin, mshadow_op::arcsin); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arccos, mshadow_op::arccos); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arctan, mshadow_op::arctan); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_degrees, mshadow_op::degrees); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_radians, mshadow_op::radians); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_sinh, mshadow_op::sinh); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_cosh, mshadow_op::cosh); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_tanh, mshadow_op::tanh); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arcsinh, mshadow_op::arcsinh); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arccosh, mshadow_op::arccosh); + +MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(_npi_arctanh, mshadow_op::arctanh); + +} // namespace op +} // namespace mxnet diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index 2291bcdb6d3d..95ac7b3dd93a 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -713,6 +713,155 @@ def hybrid_forward(self, F, x): assert same(ret_mx.asnumpy(), ret_np) +@with_seed() +@use_np +def test_np_unary_funcs(): + def check_unary_func(func, ref_grad, shape, low, high): + class TestUnary(HybridBlock): + def __init__(self, func): + super(TestUnary, self).__init__() + self._func = func + + def hybrid_forward(self, F, a, *args, **kwargs): + print(self._func) + return getattr(F.np, self._func)(a) + + np_func = getattr(_np, func) + mx_func = TestUnary(func) + np_test_data = _np.random.uniform(low, high, shape).astype(_np.float32) + mx_test_data = mx.numpy.array(np_test_data) + for hybridize in [True, False]: + if hybridize: + mx_func.hybridize() + if ref_grad: + mx_test_data.attach_grad() + np_out = np_func(np_test_data) + with mx.autograd.record(): + y = mx_func(mx_test_data) + assert y.shape == np_out.shape + assert_almost_equal(y.asnumpy(), np_out, rtol=1e-3, atol=1e-5) + + if ref_grad: + y.backward() + assert_almost_equal(mx_test_data.grad.asnumpy(), ref_grad(np_test_data), rtol=1e-5, atol=1e-6, equal_nan=True) + + funcs = { + 'absolute' : (lambda x: -1. * (x < 0) + (x > 0), -1.0, 1.0), + 'cbrt' : (lambda x: 1. / (3. * _np.cbrt(x) ** 2), -1.0, 1.0), + 'ceil' : (None, -10.0, 10.0), + 'exp' : (lambda x: _np.exp(x), -1.0, 1.0), + 'expm1' : (lambda x: _np.exp(x), -1.0, 1.0), + 'fix' : (None, -10.0, 10.0), + 'floor' : (None, -10.0, 10.0), + 'log' : (lambda x: 1.0 / x, 0.1, 5.0), + 'log10' : (lambda x: 1.0 / (x * _np.log(10)), 0.1, 10.0), + 'log1p' : (lambda x: 1.0 / (1.0 + x), -0.9, 5.0), + 'log2' : (lambda x: 1.0 / (x * _np.log(2)), 0.1, 2.0), + 'logical_not' : (None, -1.0, 1.0), + 'negative' : (lambda x: -1. * _np.ones(x.shape), -1.0, 1.0), + 'reciprocal' : (lambda x: -1. / (x ** 2), 0.01, 1.0), + 'rint' : (None, -5.0, 5.0), + 'sign' : (None, -1.0, 1.0), + 'sqrt' : (lambda x: 0.5 / _np.sqrt(x), 0.001, 10.0), + 'square' : (lambda x: 2.0 * x, -1.0, 1.0), + 'trunc' : (None, -5.0, 5.0), + 'sin' : (lambda x: _np.cos(x), -1.0, 1.0), + 'cos' : (lambda x: -_np.sin(x), -1.0, 1.0), + 'tan' : (lambda x: _np.tan(x) ** 2 + 1.0, -1.0, 1.0), + 'arcsin' : (lambda x: 1. / (1. - x ** 2) ** (1. / 2.), -1.0, 1.0), + 'arccos' : (lambda x: -1. / (1. - x ** 2.) ** (1. / 2.), -1.0, 1.0), + 'arctan' : (lambda x: 1. / (x ** 2. + 1.), -1.0, 1.0), + 'degrees' : (lambda x: 180. / _np.pi * _np.ones(x.shape), -1.0, 1.0), + 'radians' : (lambda x: _np.pi / 180. * _np.ones(x.shape), -1.0, 1.0), + 'sinh' : (lambda x: _np.cosh(x), -1.0, 1.0), + 'cosh' : (lambda x: _np.sinh(x), -1.0, 1.0), + 'tanh' : (lambda x: 1. - _np.tanh(x) ** 2, -1.0, 1.0), + 'arcsinh' : (lambda x: 1./(x**2 + 1.)**(1./2.), -1.0, 1.0), + 'arccosh' : (lambda x: 1./(x**2 - 1.)**(1./2.), 2.0, 5.0), + 'arctanh' : (lambda x: -1./(x**2 - 1.), -0.99, 0.99) + } + ndim = random.choice([2, 3, 4]) + shape = random.choice([rand_shape_nd(ndim, dim=3), (1, 0, 2)]) + for shape in [rand_shape_nd(ndim, dim=3), (1, 0, 2)]: + for func, func_data in funcs.items(): + ref_grad, low, high = func_data + check_unary_func(func, ref_grad, shape, low, high) + + +@with_seed() +@use_np +def test_npx_relu(): + def np_relu(x): + return _np.maximum(x, 0.0) + def np_relu_grad(x): + return 1.0 * (x > 0.0) + + class TestReLU(HybridBlock): + def __init__(self): + super(TestReLU, self).__init__() + + def hybrid_forward(self, F, a): + return F.npx.relu(a) + + shapes = [(), (2, 3, 4), (2, 0, 3), (1, 0, 0)] + for hybridize in [True, False]: + for shape in shapes: + test_relu = TestReLU() + if hybridize: + test_relu.hybridize() + x = rand_ndarray(shape).as_np_ndarray() + x.attach_grad() + np_out = np_relu(x.asnumpy()) + with mx.autograd.record(): + mx_out = test_relu(x) + assert mx_out.shape == np_out.shape + assert_almost_equal(mx_out.asnumpy(), np_out, rtol=1e-3, atol=1e-5) + mx_out.backward() + np_backward = np_relu_grad(x.asnumpy()) + assert_almost_equal(x.grad.asnumpy(), np_backward, rtol=1e-3, atol=1e-5) + + mx_out = npx.relu(x) + np_out = np_relu(x.asnumpy()) + assert_almost_equal(mx_out.asnumpy(), np_out, rtol=1e-3, atol=1e-5) + + +@with_seed() +@use_np +def test_npx_sigmoid(): + def np_sigmoid(x): + return _np.divide(1.0, (1.0 + _np.exp(-x))) + def np_sigmoid_grad(ya): + return ya * (1 - ya) + + class TestSigmoid(HybridBlock): + def __init__(self): + super(TestSigmoid, self).__init__() + + def hybrid_forward(self, F, a): + return F.npx.sigmoid(a) + + shapes = [(), (2, 3, 4), (2, 0, 3), (1, 0, 0)] + for hybridize in [True, False]: + for shape in shapes: + test_sigmoid = TestSigmoid() + if hybridize: + test_sigmoid.hybridize() + x = rand_ndarray(shape).as_np_ndarray() + x.attach_grad() + np_out = np_sigmoid(x.asnumpy()) + with mx.autograd.record(): + mx_out = test_sigmoid(x) + assert mx_out.shape == np_out.shape + assert_almost_equal(mx_out.asnumpy(), np_out, rtol=1e-3, atol=1e-5) + mx_out.backward() + np_backward = np_sigmoid_grad(np_out) + assert_almost_equal(x.grad.asnumpy(), np_backward, rtol=1e-3, atol=1e-5) + + mx_out = npx.sigmoid(x) + np_out = np_sigmoid(x.asnumpy()) + assert_almost_equal(mx_out.asnumpy(), np_out, rtol=1e-3, atol=1e-5) + + @with_seed() @use_np def test_np_arange():