Returns element-wise sum of the input arrays with broadcasting.

    Equivalent to ``lhs + rhs``, ``mx.nd.broadcast_add(lhs, rhs)`` and
    ``mx.nd.broadcast_plus(lhs, rhs)`` when shapes of lhs and rhs do not
    match. If lhs.shape == rhs.shape, this is equivalent to
    ``mx.nd.elemwise_add(lhs, rhs)``

    .. note::

        If the corresponding dimensions of two arrays have the same size or one of them has size 1,
        then the arrays are broadcastable to a common shape.abs

    Parameters
    ----------
    lhs : scalar or mxnet.ndarray.sparse.array
        First array to be added.
    rhs : scalar or mxnet.ndarray.sparse.array
         Second array to be added.
        If ``lhs.shape != rhs.shape``, they must be
        broadcastable to a common shape.

    Returns
    -------
    NDArray
        The element-wise sum of the input arrays.

    Examples
    --------
    >>> a = mx.nd.ones((2,3)).tostype('csr')
    >>> b = mx.nd.ones((2,3)).tostype('csr')
    >>> a.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> b.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> (a+b).asnumpy()
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.]], dtype=float32)
    >>> c = mx.nd.ones((2,3)).tostype('row_sparse')
    >>> d = mx.nd.ones((2,3)).tostype('row_sparse')
    >>> c.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> d.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> (c+d).asnumpy()
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.]], dtype=float32)

def add(lhs, rhs):
    """Returns element-wise sum of the input arrays with broadcasting.

    Equivalent to ``lhs + rhs``, ``mx.nd.broadcast_add(lhs, rhs)`` and
    ``mx.nd.broadcast_plus(lhs, rhs)`` when shapes of lhs and rhs do not
    match. If lhs.shape == rhs.shape, this is equivalent to
    ``mx.nd.elemwise_add(lhs, rhs)``

    .. note::

        If the corresponding dimensions of two arrays have the same size or one of them has size 1,
        then the arrays are broadcastable to a common shape.abs

    Parameters
    ----------
    lhs : scalar or mxnet.ndarray.sparse.array
        First array to be added.
    rhs : scalar or mxnet.ndarray.sparse.array
         Second array to be added.
        If ``lhs.shape != rhs.shape``, they must be
        broadcastable to a common shape.

    Returns
    -------
    NDArray
        The element-wise sum of the input arrays.

    Examples
    --------
    >>> a = mx.nd.ones((2,3)).tostype('csr')
    >>> b = mx.nd.ones((2,3)).tostype('csr')
    >>> a.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> b.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> (a+b).asnumpy()
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.]], dtype=float32)
    >>> c = mx.nd.ones((2,3)).tostype('row_sparse')
    >>> d = mx.nd.ones((2,3)).tostype('row_sparse')
    >>> c.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> d.asnumpy()
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]], dtype=float32)
    >>> (c+d).asnumpy()
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.]], dtype=float32)
    """
    # pylint: disable= no-member, protected-access
    if isinstance(lhs, NDArray) and isinstance(rhs, NDArray) and lhs.shape == rhs.shape:
        return _ufunc_helper(
            lhs,
            rhs,
            op.elemwise_add,
            operator.add,
            _internal._plus_scalar,
            None)

    return _ufunc_helper(
        lhs,
        rhs,
        op.broadcast_add,
        operator.add,
        _internal._plus_scalar,
        None)