o
    Qe                     @   s  d dl Z ddlmZmZ ddlmZ ddlmZ ddlm	Z	 e	r(e j
jjjjZnddlmZ dd	lmZmZ dd
lmZ ddlmZ d dl mZmZ d dlmZ g Zd<ddZd=ddZd=ddZd=ddZe d=ddZd>ddZd>ddZe d?d d!Z e d>d"d#Z!e d>d$d%Z"e d>d&d'Z#e d>d(d)Z$e d>d*d+Z%e d>d,d-Z&d.d/ Z'd<d0d1Z(e d=d2d3Z)e d=d4d5Z*e d=d6d7Z+e d=d8d9Z,e d?d:d;Z-dS )@    N   )
check_typecheck_variable_and_dtype   )templatedoc)Variable)_in_eager_mode_)VarBase)in_dygraph_mode_non_static_mode)LayerHelper)_in_legacy_dygraph)_C_ops_legacy_C_ops)fullTc                 C   s  t  rtt| }|r|||S ||S t r&tt| }|r"|||S ||S t|dg d|  |d ur<t|dg d|  |d urGt|dt|  t| fi t	 }|rc|j
|j
krctd| |j
|j
f |d u rn|j|j
d}|r|j| ||dd|id	 |S |j| d
|id|id	 |S )Nx)boolint8int16int32int64float32float64youtz^(InvalidArgument) The DataType of %s Op's Variable must be consistent, but received %s and %s.dtypeXYOuttypeinputsoutputsr   )r
   getattrr   r   r   r   r   r   r   localsr   
ValueError"create_variable_for_type_inference	append_opop_namer   r   r   name	binary_opophelper r0   CD:\Projects\ConvertPro\env\Lib\site-packages\paddle/tensor/logic.py_logical_op'   sR   



r2   c                 C   &   t  r	t| |S td| |||ddS )ak  

    ``logical_and`` operator computes element-wise logical AND on ``x`` and ``y``, and returns ``out``. ``out`` is N-dim boolean ``Tensor``.
    Each element of ``out`` is calculated by

    .. math::

        out = x \&\& y

    Note:
        ``paddle.logical_and`` supports broadcasting. If you want know more about broadcasting, please refer to :ref:`user_guide_broadcasting`.

    Args:
        x (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        y (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        out(Tensor): The ``Tensor`` that specifies the output of the operator, which can be any ``Tensor`` that has been created in the program. The default value is None, and a new ``Tensor`` will be created to save the output.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        N-D Tensor. A location into which the result is stored. It's dimension equals with ``x``.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([True])
            y = paddle.to_tensor([True, False, True, False])
            res = paddle.logical_and(x, y)
            print(res) # [True False True False]
    logical_andTr+   r   r   r,   r   r-   )r
   r   r4   r2   r   r   r   r,   r0   r0   r1   r4   Y   s
    r4   c                 C   r3   )a2  

    ``logical_or`` operator computes element-wise logical OR on ``x`` and ``y``, and returns ``out``. ``out`` is N-dim boolean ``Tensor``.
    Each element of ``out`` is calculated by

    .. math::

        out = x || y

    Note:
        ``paddle.logical_or`` supports broadcasting. If you want know more about broadcasting, please refer to :ref:`user_guide_broadcasting`.

    Args:
        x (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        y (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        out(Tensor): The ``Variable`` that specifies the output of the operator, which can be any ``Tensor`` that has been created in the program. The default value is None, and a new ``Tensor`` will be created to save the output.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        N-D Tensor. A location into which the result is stored. It's dimension equals with ``x``.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([True, False], dtype="bool").reshape([2, 1])
            y = paddle.to_tensor([True, False, True, False], dtype="bool").reshape([2, 2])
            res = paddle.logical_or(x, y)
            print(res)
            # Tensor(shape=[2, 2], dtype=bool, place=Place(cpu), stop_gradient=True,
            #        [[True , True ],
            #         [True , False]])
    
logical_orTr5   )r
   r   r7   r2   r6   r0   r0   r1   r7      s
   #r7   c                 C   r3   )aG  

    ``logical_xor`` operator computes element-wise logical XOR on ``x`` and ``y``, and returns ``out``. ``out`` is N-dim boolean ``Tensor``.
    Each element of ``out`` is calculated by

    .. math::

        out = (x || y) \&\& !(x \&\& y)

    Note:
        ``paddle.logical_xor`` supports broadcasting. If you want know more about broadcasting, please refer to :ref:`user_guide_broadcasting`.

    Args:
        x (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        y (Tensor): the input tensor, it's data type should be one of bool, int8, int16, in32, in64, float32, float64.
        out(Tensor): The ``Tensor`` that specifies the output of the operator, which can be any ``Tensor`` that has been created in the program. The default value is None, and a new ``Tensor`` will be created to save the output.
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        N-D Tensor. A location into which the result is stored. It's dimension equals with ``x``.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([True, False], dtype="bool").reshape([2, 1])
            y = paddle.to_tensor([True, False, True, False], dtype="bool").reshape([2, 2])
            res = paddle.logical_xor(x, y)
            print(res)
            # Tensor(shape=[2, 2], dtype=bool, place=Place(cpu), stop_gradient=True,
            #        [[False, True ],
            #         [True , False]])
    logical_xorTr5   )r
   r   r8   r2   r6   r0   r0   r1   r8      s
   #r8   c                 C   s$   t  rt| S td| d||ddS )a  

    ``logical_not`` operator computes element-wise logical NOT on ``x``, and returns ``out``. ``out`` is N-dim boolean ``Variable``.
    Each element of ``out`` is calculated by

    .. math::

        out = !x

    Args:
        x(Tensor):  Operand of logical_not operator. Must be a Tensor of type bool, int8, int16, in32, in64, float32, or float64.
        out(Tensor): The ``Tensor`` that specifies the output of the operator, which can be any ``Tensor`` that has been created in the program. The default value is None, and a new ``Tensor` will be created to save the output.
        name(str|None): The default value is None. Normally there is no need for users to set this property. For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: ${out_comment}

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([True, False, True, False])
            res = paddle.logical_not(x)
            print(res) # [False  True False  True]
    logical_notNFr5   )r
   r   r9   r2   r   r   r,   r0   r0   r1   r9      s
   
r9   c                 C   s   t  rt| S t rt| S t| dg dd t|dttdfd t	di t
 }|jdd}d|_|jdd	| gid
|gid |S )a=  

    Test whether a Tensor is empty.

    Args:
        x (Tensor): The Tensor to be tested.
        name (str, optional): The default value is ``None`` . Normally users
                            don't have to set this parameter. For more information,
                            please refer to :ref:`api_guide_Name` .

    Returns:
        Tensor: A bool scalar Tensor. True if 'x' is an empty Tensor.

    Examples:
        .. code-block:: python

            import paddle

            input = paddle.rand(shape=[4, 32, 32], dtype='float32')
            res = paddle.is_empty(x=input)
            print("res:", res)
            # ('res:', Tensor: eager_tmp_1
            #    - place: CPUPlace
            #    - shape: [1]
            #    - layout: NCHW
            #    - dtype: bool
            #    - data: [0])

    r   )r   r   r   r   is_emptyr,   Nr   r   Tr   r    r!   )r;   )r
   r   r;   r   r   r   r   strr"   r   r&   r(   stop_gradientr)   )r   r,   r/   Zcondr0   r0   r1   r;      s   

r;   c                 C   sf   t  r	t| |S t rt| |S tdi t }|jdd}|j	d| g|gdd|gid |S )	a  
    Returns the truth value of :math:`x == y`. True if two inputs have the same elements, False otherwise.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): Tensor, data type is bool, float32, float64, int32, int64.
        y(Tensor): Tensor, data type is bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: output Tensor, data type is bool, value is [False] or [True].

    Examples:
        .. code-block:: python

          import paddle

          x = paddle.to_tensor([1, 2, 3])
          y = paddle.to_tensor([1, 2, 3])
          z = paddle.to_tensor([1, 4, 3])
          result1 = paddle.equal_all(x, y)
          print(result1) # result1 = [True ]
          result2 = paddle.equal_all(x, z)
          print(result2) # result2 = [False ]
    	equal_allr   r   r   r    r!   N)r>   )
r
   r   r>   paddleZin_dynamic_moder   r   r&   r(   r)   r   r   r,   r/   r   r0   r0   r1   r>   *  s   r>   h㈵>:0yE>Fc              
   C      t  rdd }t| ||||||S t r't| |dt|dt|d|S t| dddgd	 t|dddgd	 t|dtd	 t|dtd	 t|dt	d	 t
di t }|jd
d}| |d}	d|i}
t|t||d}|jd	|	|
|d |S )a  
    ${comment}

    Args:
        x(Tensor): ${input_comment}.
        y(Tensor): ${other_comment}.
        rtol(rtoltype, optional): The relative tolerance. Default: :math:`1e-5` .
        atol(atoltype, optional): The absolute tolerance. Default: :math:`1e-8` .
        equal_nan(equalnantype, optional): ${equal_nan_comment}.
        name (str, optional): Name for the operation. For more information, please
            refer to :ref:`api_guide_Name`. Default: None.

    Returns:
        Tensor: ${out_comment}.

    Examples:
        .. code-block:: python

          import paddle

          x = paddle.to_tensor([10000., 1e-07])
          y = paddle.to_tensor([10000.1, 1e-08])
          result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08,
                                  equal_nan=False, name="ignore_nan")
          # [False]

          result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08,
                                      equal_nan=True, name="equal_nan")
          # [False]

          x = paddle.to_tensor([1.0, float('nan')])
          y = paddle.to_tensor([1.0, float('nan')])
          result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08,
                                  equal_nan=False, name="ignore_nan")
          # [False]

          result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08,
                                      equal_nan=True, name="equal_nan")
          # [True]
    c                 S      t j| gdddS Nr   cpu)r   Zplacer?   Z	to_tensorr   r0   r0   r1   <lambda>      zallclose.<locals>.<lambda>rtolatol	equal_naninputr   r   allcloser   r   ZInputOtherr    rK   rL   rM   r"   r#   r$   attrsN)rO   )r
   r   rO   r   r   r<   r   r   floatr   r   r&   r(   r)   r   r   rK   rL   rM   r,   Z	as_tensorr/   r   r#   r$   rT   r0   r0   r1   rO   U  s.   +
rO   c                 C   s   t |ttttfstdt|t |ts tdg| j	|d}t
 r,d}t| ||S t r5t| |S t| dg dd t|dg dd tdi t }|jd	d
}d|_|jd| g|gdd|gid |S )a  

    This layer returns the truth value of :math:`x == y` elementwise.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): Tensor, data type is bool, float32, float64, int32, int64.
        y(Tensor): Tensor, data type is bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: output Tensor, it's shape is the same as the input's Tensor,
        and the data type is bool. The result of this op is stop_gradient.

    Examples:
        .. code-block:: python

          import paddle

          x = paddle.to_tensor([1, 2, 3])
          y = paddle.to_tensor([1, 3, 2])
          result1 = paddle.equal(x, y)
          print(result1)  # result1 = [True False False]
    zKType of input args must be float, bool, int or Tensor, but received type {}r   )shaper   Z
fill_valuer   r   r   r   r   r   equalr   r   r   Tr   r    r!   N)rZ   )
isinstanceintr   rU   r   	TypeErrorformatr"   r   r   r
   r   rZ   r   r   r   r   r&   r(   r=   r)   r   r   r,   Zdefault_axisr/   r   r0   r0   r1   rZ     sD   
rZ   c                 C      t  rd}t| ||S t rt| |S t| dg dd t|dg dd tdi t }|jdd}d|_	|j
d| g|gd	d
|gid |S )a  
    Returns the truth value of :math:`x >= y` elementwise, which is equivalent function to the overloaded operator `>=`.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): First input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        y(Tensor): Second input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.
    Returns:
        Tensor: The output shape is same as input :attr:`x`. The output data type is bool.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([1, 2, 3])
            y = paddle.to_tensor([1, 3, 2])
            result1 = paddle.greater_equal(x, y)
            print(result1)  # result1 = [True False True]
    rX   r   rY   greater_equalr   r   r   Tr   r    r!   N)ra   )r
   r   ra   r   r   r   r   r&   r(   r=   r)   r_   r0   r0   r1   ra     s4   ra   c                 C   s   t  r
t| |dS t rt| |S t| dg dd t|dg dd tdi t }|jdd}d|_	|j
d| g|gd	d
|gid |S )a  
    Returns the truth value of :math:`x > y` elementwise, which is equivalent function to the overloaded operator `>`.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): First input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        y(Tensor): Second input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.
    Returns:
        Tensor: The output shape is same as input :attr:`x`. The output data type is bool.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([1, 2, 3])
            y = paddle.to_tensor([1, 3, 2])
            result1 = paddle.greater_than(x, y)
            print(result1)  # result1 = [False False True]
    rX   r   rY   greater_thanr   r   r   Tr   r    r!   N)rb   )r
   r   rb   r   r   r   r   r&   r(   r=   r)   r@   r0   r0   r1   rb     s2   rb   c                 C   r`   )a  
    Returns the truth value of :math:`x <= y` elementwise, which is equivalent function to the overloaded operator `<=`.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): First input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        y(Tensor): Second input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: The output shape is same as input :attr:`x`. The output data type is bool.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([1, 2, 3])
            y = paddle.to_tensor([1, 3, 2])
            result1 = paddle.less_equal(x, y)
            print(result1)  # result1 = [True True False]
    rX   r   rY   
less_equalr   r   r   Tr   r    r!   N)rc   )r
   r   rc   r   r   r   r   r&   r(   r=   r)   r   r   r,   Zaxisr/   r   r0   r0   r1   rc   V  4   rc   c                 C   r`   )a  
    Returns the truth value of :math:`x < y` elementwise, which is equivalent function to the overloaded operator `<`.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): First input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        y(Tensor): Second input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: The output shape is same as input :attr:`x`. The output data type is bool.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([1, 2, 3])
            y = paddle.to_tensor([1, 3, 2])
            result1 = paddle.less_than(x, y)
            print(result1)  # result1 = [False True False]
    rX   r   rY   	less_thanr   r   r   Tr   r    r!   N)rf   )r
   r   rf   r   r   r   r   r&   r(   r=   r)   r_   r0   r0   r1   rf     re   rf   c                 C   r`   )a  
    Returns the truth value of :math:`x != y` elementwise, which is equivalent function to the overloaded operator `!=`.

    Note:
        The output has no gradient.

    Args:
        x(Tensor): First input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        y(Tensor): Second input to compare which is N-D tensor. The input data type should be bool, float32, float64, int32, int64.
        name(str, optional): The default value is None.  Normally there is no need for
            user to set this property.  For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Tensor: The output shape is same as input :attr:`x`. The output data type is bool.

    Examples:
        .. code-block:: python

            import paddle

            x = paddle.to_tensor([1, 2, 3])
            y = paddle.to_tensor([1, 3, 2])
            result1 = paddle.not_equal(x, y)
            print(result1)  # result1 = [False True True]
    rX   r   rY   	not_equalr   r   r   Tr   r    r!   N)rg   )r
   r   rg   r   r   r   r   r&   r(   r=   r)   rd   r0   r0   r1   rg     re   rg   c                 C   s   t | ttjjjjfS )a  

    Tests whether input object is a paddle.Tensor.

    Args:
        x (object): Object to test.

    Returns:
        A boolean value. True if ``x`` is a paddle.Tensor, otherwise False.

    Examples:
        .. code-block:: python

            import paddle

            input1 = paddle.rand(shape=[2, 3, 5], dtype='float32')
            check = paddle.is_tensor(input1)
            print(check)  #True

            input3 = [1, 4]
            check = paddle.is_tensor(input3)
            print(check)  #False

    )r[   Tensorr?   fluidcoreeagerrH   r0   r0   r1   	is_tensor  s   rl   c                 C   s  t  rtt| }|r|||S ||S t r&tt| }|r"|||S ||S t|dg d|  |d ur<t|dg d|  |d urGt|dt|  t| fi t	 }|rZ|j
|j
ksZJ |d u re|j|j
d}|rv|j| ||dd|id |S |j| d	|id|id |S )
Nr   )r   Zuint8r   r   r   r   r   r   r   r   r    r!   r   )r
   r%   r   r   r   r   r   r   r   r&   r   r(   r)   r*   r0   r0   r1   _bitwise_op   sD   



rm   c                 C   .   t  r|du rt| |S td| |||ddS )a  
    ${comment}

    Args:
        x (Tensor): ${x_comment}
        y (Tensor): ${y_comment}
        out(Tensor): ${out_comment}

    Returns:
        Tensor: ${out_comment}

    Examples:
        .. code-block:: python

            import paddle
            x = paddle.to_tensor([-5, -1, 1])
            y = paddle.to_tensor([4,  2, -3])
            res = paddle.bitwise_and(x, y)
            print(res)  # [0, 2, 1]
    Nbitwise_andTr5   )r
   r   ro   rm   r6   r0   r0   r1   ro   L  
   ro   c                 C   rn   )a  
    ${comment}

    Args:
        x (Tensor): ${x_comment}
        y (Tensor): ${y_comment}
        out(Tensor): ${out_comment}

    Returns:
        Tensor: ${out_comment}

    Examples:
        .. code-block:: python

            import paddle
            x = paddle.to_tensor([-5, -1, 1])
            y = paddle.to_tensor([4,  2, -3])
            res = paddle.bitwise_or(x, y)
            print(res)  # [-1, -1, -3]
    N
bitwise_orTr5   )r
   r   rq   rm   r6   r0   r0   r1   rq   i  s
   rq   c                 C   rn   )a  
    ${comment}

    Args:
        x (Tensor): ${x_comment}
        y (Tensor): ${y_comment}
        out(Tensor): ${out_comment}

    Returns:
        Tensor: ${out_comment}

    Examples:
        .. code-block:: python

            import paddle
            x = paddle.to_tensor([-5, -1, 1])
            y = paddle.to_tensor([4,  2, -3])
            res = paddle.bitwise_xor(x, y)
            print(res) # [-1, -3, -4]
    Nbitwise_xorTr5   )r
   r   rr   rm   r6   r0   r0   r1   rr     rp   rr   c                 C   s,   t  r|du rt| S td| d||ddS )aT  
    ${comment}

    Args:
        x(Tensor):  ${x_comment}
        out(Tensor): ${out_comment}

    Returns:
        Tensor: ${out_comment}

    Examples:
        .. code-block:: python

            import paddle
            x = paddle.to_tensor([-5, -1, 1])
            res = paddle.bitwise_not(x)
            print(res) # [4, 0, -2]
    Nbitwise_notFr5   )r
   r   rs   rm   r:   r0   r0   r1   rs     s
   
rs   c              
   C   rC   )a  
    ${comment}

    Args:
        x(Tensor): ${input_comment}.
        y(Tensor): ${other_comment}.
        rtol(rtoltype, optional): The relative tolerance. Default: :math:`1e-5` .
        atol(atoltype, optional): The absolute tolerance. Default: :math:`1e-8` .
        equal_nan(equalnantype, optional): ${equal_nan_comment}.
        name (str, optional): Name for the operation. For more information, please
            refer to :ref:`api_guide_Name`. Default: None.

    Returns:
        Tensor: ${out_comment}.

    Examples:
        .. code-block:: python

          import paddle

          x = paddle.to_tensor([10000., 1e-07])
          y = paddle.to_tensor([10000.1, 1e-08])
          result1 = paddle.isclose(x, y, rtol=1e-05, atol=1e-08,
                                  equal_nan=False, name="ignore_nan")
          # [True, False]
          result2 = paddle.isclose(x, y, rtol=1e-05, atol=1e-08,
                                      equal_nan=True, name="equal_nan")
          # [True, False]

          x = paddle.to_tensor([1.0, float('nan')])
          y = paddle.to_tensor([1.0, float('nan')])
          result1 = paddle.isclose(x, y, rtol=1e-05, atol=1e-08,
                                  equal_nan=False, name="ignore_nan")
          # [True, False]
          result2 = paddle.isclose(x, y, rtol=1e-05, atol=1e-08,
                                      equal_nan=True, name="equal_nan")
          # [True, True]
    c                 S   rD   rE   rG   rH   r0   r0   r1   rI     rJ   zisclose.<locals>.<lambda>rK   rL   rM   rN   r   r   iscloser   r   rP   r    rR   rS   N)rt   )r
   r   rt   r   r   r<   r   r   rU   r   r   r&   r(   r)   rV   r0   r0   r1   rt     s*   )
rt   )NNT)NN)N)rA   rB   FN).r?   Zfluid.data_feederr   r   Zlayer_function_generatorr   Zstaticr   Zfluid.frameworkr   ri   Z	frameworkrj   rk   rh   r	   r
   r   r   r   r   r   Zpaddle.tensor.creationr   __all__r2   r4   r7   r8   r9   r;   r>   rO   rZ   ra   rb   rc   rf   rg   rl   rm   ro   rq   rr   rs   rt   r0   r0   r0   r1   <module>   s`   

2
(
*+
"
1+JD87999
,