
    `iUO                         d Z ddlZddlZddlZddlmZ  G d de          Z	 e	ee          Z G d de          Z
d Z e              G d	 d
e          Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )z}
`fallback_mode` for cupy. Whenever a method is not yet implemented in CuPy,
it will fallback to corresponding NumPy method.
    N)notificationc                   ^    e Zd ZdZd
dZd Zd Zd Zed             Ze	d             Z
d	 ZdS )_RecursiveAttrz
    RecursiveAttr class to catch all attributes corresponding to numpy,
    when user calls fallback_mode. numpy is an instance of this class.
    Nc                 0    || _         || _        || _        dS )a  
        _RecursiveAttr initializer.

        Args:
            numpy_object (method): NumPy method.
            cupy_method (method): Corresponding CuPy method.
            array (ndarray): Acts as flag to know if _RecursiveAttr object
                is called from ``ndarray`` class. Also, acts as container for
                modifying args in case it is called from ``ndarray``.
                None otherwise.
        N)_numpy_object_cupy_object_fallback_array)selfnumpy_objectcupy_objectarrays       p/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/cupyx/fallback_mode/fallback.py__init__z_RecursiveAttr.__init__   s"     *'$    c                 d    | j         t          || j                   S t          || j                  S )z
        Enable support for isinstance(instance, _RecursiveAttr instance)
        by redirecting it to appropriate isinstance method.
        )r   
isinstancer   )r
   instances     r   __instancecheck__z _RecursiveAttr.__instancecheck__&   s3     (h(9:::(D$6777r   c                     t          | j        |          }t          | j        |d          }|t          j        u rt          S |t          j        u rt
          S ||u r|S t          ||          S )a5  
        Catches attributes corresponding to numpy.

        Runs recursively till attribute gets called.
        Or numpy ScalarType is retrieved.

        Args:
            attr (str): Attribute of _RecursiveAttr class object.

        Returns:
            (_RecursiveAttr object, NumPy scalar):
                Returns_RecursiveAttr object with new numpy_object,
                cupy_object. OR
                Returns objects in cupy which is an alias
                of numpy object. OR
                Returns wrapper objects, `ndarray`, `vectorize`.
        N)getattrr   r   npndarray	vectorizer   )r
   attrr   r   s       r   __getattr__z_RecursiveAttr.__getattr__1   sp    & t1488d/t<<2:%%N2<'';&&lK888r   c                     t          | j        t          j                  r4d                    | j        j        t          | j        dd                     S d                    | j        | j                  S )Nz%<numpy = module {}, cupy = module {}>__name__z<numpy = {}, cupy = {}>)r   r   types
ModuleTypeformatr   r   r   r
   s    r   __repr__z_RecursiveAttr.__repr__R   sr    d(%*:;; 	>:AA"+):t<<> > > )// 13 3 	3r   c                     | j         j        S N)r   __doc__r!   s    r   r%   z_RecursiveAttr.__doc__\   s    !))r   c                     t           t                    r	 j        sdS t           t          t          f          rt          d  D                       S t           t                    r fd D             }t          |          S dS )a-  
        Returns False if CuPy's functions never accept the arguments as
        parameters due to the following reasons.
        - The inputs include an object of a NumPy's specific class other than
          `np.ndarray`.
        - The inputs include a dtype which is not supported in CuPy.
        Fc              3   J   K   | ]}t                               |          V  d S r$   r   _is_cupy_compatible).0is     r   	<genexpr>z5_RecursiveAttr._is_cupy_compatible.<locals>.<genexpr>o   s0      JJ~99!<<JJJJJJr   c                 P    g | ]"}t                               |                   #S  r(   )r*   r+   args     r   
<listcomp>z6_RecursiveAttr._is_cupy_compatible.<locals>.<listcomp>r   s+    MMMA^77A??MMMr   T)r   r   _supports_cupytuplelistalldict)r/   boolss   ` r   r)   z"_RecursiveAttr._is_cupy_compatible`   s     c7## 	% ucE4=)) 	KJJcJJJJJJc4   	MMMMMMMEu::tr   c                    t          | j                  s9t          d                    t	          | j                  j                            | j        | j        f|z   }| j        Yt          	                    ||f          r=	 t          | j        ||          S # t          $ r t          | j        ||          cY S w xY wt          j        | j                   t          | j        ||          S )aR  
        Gets invoked when last attribute of _RecursiveAttr class gets called.
        Calls _cupy_object if not None else call _numpy_object.

        Args:
            args (tuple): Arguments.
            kwargs (dict): Keyword arguments.

        Returns:
            (res, ndarray): Returns of methods call_cupy or call_numpy
        z'{}' object is not callable)callabler   	TypeErrorr    typer   r	   r   r   r)   
_call_cupy	Exception_call_numpyr   _dispatch_notificationr
   argskwargss      r   __call__z_RecursiveAttr.__call__w   s    *++ 	49@@T'((13 3 4 4 4 +)+d2D(--tVn== )E!$"3T6BBB E E E"4#5tVDDDDDE 	+D,>???4-tV<<<s   B  B=<B=r$   )r   
__module____qualname__r%   r   r   r   r"   propertystaticmethodr)   rB   r.   r   r   r   r      s         
% % % %"	8 	8 	89 9 9B3 3 3 * * X*   \,= = = = =r   r   c                       e Zd ZdZej        j        Zd Zd Zed             Z	ed             Z
ed             Zd Zd Zd	 Zd
 Zd ZdS )r   z~
    Wrapper around cupy.ndarray
    Supports cupy.ndarray.__init__ as well as,
    gets initialized with a cupy ndarray.
    c                     |                     dd          }|t                              |           S t          j        |i |} | |d          S )z
        If `_initial_array` and `_supports_cupy` are arguments,
        initialize cls(ndarray).
        Else get cupy.ndarray from provided arguments,
        then initialize cls(ndarray).
        _initial_arrayNTrI   r1   )getobject__new__cpr   )clsr@   rA   rI   cupy_ndarray_inits        r   rM   zndarray.__new__   s[      $4d;;%>>#&&&J777s"3DIIIIr   c                 v   |                     dd          }|                     dd          }|dS d| _        d| _        d| _        || _        t          |t          j        t          j        f          sJ |r;t          |          t          j        u r|| _        d| _
        dS || _        d| _
        dS || _        dS )a  
        Args:
            _initial_array (None, cp.ndarray/np.ndarray(including variants)):
                If _initial_array is None, object is not initialized.
                Otherwise, _initial_array (ndarray) would be set to
                _cupy_array and/or _numpy_array depending upon _supports_cupy.
            _supports_cupy (bool): If _supports_cupy is True, _initial_array
                is set as _cupy_array and _numpy_array.
                Otherwise, _initial_array is set as only _numpy_array.

        Attributes:
            _cupy_array (None or cp.ndarray): ndarray fully compatible with
                CuPy. This will be always set to a ndarray in GPU.
            _numpy_array (None or np.ndarray(including variants)): ndarray not
                supported by CuPy. Such as np.ndarray (where dtype is not in
                '?bhilqBHILQefdFD') and it's variants. This will be always set
                to a ndarray in CPU.
            _supports_cupy (bool): If _supports_cupy is True, data of array
                will contain in _cupy_array and _numpy_array.
                Else only _numpy_array will have the data.
        r1   NrI   FT)pop_cupy_array_numpy_arraybaser1   r   rN   r   r   r:   _remember_numpy)r
   r@   rA   r1   rI   s        r   r   zndarray.__init__   s    .  $4d;;$4d;;!F 	,.2:rz*BCCCCC 	/N##rz11 $2 ',$$$ %3!'+$$$ .Dr   c                      | |d          S )NTrJ   r.   rO   r   s     r   _store_array_from_cupyzndarray._store_array_from_cupy   s    s%====r   c                     t          |          t          j        u r|j        j        dv r | |d          S  | |d          S )Nz?bhilqBHILQefdFDTrJ   F)r:   r   r   dtypekindrX   s     r   _store_array_from_numpyzndarray._store_array_from_numpy   sP    ;;"*$$;1113eDAAAAs%>>>>r   c                 N    | j         r| j        s| j        j        S | j        j        S r$   )r1   rV   rS   r[   rT   r!   s    r   r[   zndarray.dtype   s/     	*t'; 	*#)) &&r   c                    | j         r6t          t          j        |d          }t          t          j        |          }nd}t          | j        j        |          }t          |          sL| j         r0| j        r| 	                                 t          | j
        |          S t          | j        |          S t          |||           S )aQ  
        Catches attributes corresponding to ndarray.

        Args:
            attr (str): Attribute of ndarray class.

        Returns:
            (_RecursiveAttr object, self._array.attr):
            Returns_RecursiveAttr object with numpy_object, cupy_object.
            Returns self._array.attr if attr is not callable.
        N)r1   r   rN   r   r   rT   	__class__r8   rV   _update_cupy_arrayrS   r   )r
   r   r   r   s       r   r   zndarray.__getattr__   s      	F!"*dD99K"2:t44LLK"4#4#>EEL%% 	4" 7' .++---t/6664,d333lK>>>r   c                 >    | j         }|d|_        d| _        | j        S )z
        Returns _cupy_array (cupy.ndarray) of ndarray object. And marks
        self(ndarray) and it's base (if exist) as numpy not up-to-date.
        NF)rU   rV   rS   r
   rU   s     r   _get_cupy_arrayzndarray._get_cupy_array  s*    
 y#(D $r   c                 Z    | j         }||j        rd|_        | j        rd| _        | j        S )z
        Returns _numpy_array (ex: np.ndarray, numpy.ma.MaskedArray,
        numpy.chararray etc.) of ndarray object. And marks self(ndarray)
        and it's base (if exist) as numpy up-to-date.
        NT)rU   r1   rV   rT   rc   s     r   _get_numpy_arrayzndarray._get_numpy_array   s=     y 3#'D  	(#'D   r   c                 |   | j         }| j        rt          j        n| j        j        }| j        r|R| j        sI| j         t          j        | j	                  | _        dS | j	        
                    | j                   dS dS |j        s|                                 | j        j|j                            |          | _        | j	        j        | j        _        | j        j        | j	        j        k    r| j	        j        | j        _        dS dS dS dS |&|j        sJ |j        s|                                 dS dS dS )zn
        Updates _numpy_array from _cupy_array.
        To be executed before calling numpy function.
        N)out)r:   )rU   r1   r   r   rT   r`   rV   rN   asnumpyrS   rK   _update_numpy_arrayviewshapestrides)r
   rU   _types      r   rj   zndarray._update_numpy_array-  s   
 y"1 -

", 	  	/|+ D(0,.Jt7G,H,H)))(,,1B,CCCCC	D D + 9,,...(0,0,=,B,B,B,N,N)262B2H)/ -5#'#3#;< < !% 0 8 !-5559 900< < ****+ /,,.....  / /r   c                     | j         }|C| j        r:| j         t          j        | j                  | _        dS | j        | j        dd<   dS dS |j        r|                                 dS dS )zm
        Updates _cupy_array from _numpy_array.
        To be executed before calling cupy function.
        N)rU   rV   rS   rN   r   rT   ra   rc   s     r   ra   zndarray._update_cupy_arrayO  s    
 y<# <#+')x0A'B'BD$$$*.*;D$QQQ'''	< < # *'')))))* *r   N)r   rC   rD   r%   r   r   rM   r   classmethodrY   r]   rE   r[   r   rd   rf   rj   ra   r.   r   r   r   r      s          j GJ J J./ ./ ./` > > [> ? ? [? ' ' X'
? ? ?:	  	  	 ! ! ! /  /  /D* * * * *r   r   c                  T    d } dD ]!}t          t          | | |                     "dS )zK
    Set magic methods of cupy.ndarray as methods of fallback.ndarray.
    c                 Z      fd}t          t          j                   j        |_        |S )Nc                     | j         rt          j        n| j        j        }t          |          }| f|z   }| j         rt          |||          S t          |||          S r$   )r1   rN   r   rT   r`   r   r;   r=   )r
   r@   rA   CLASS_methodnames        r   methodz:_create_magic_methods.<locals>.make_method.<locals>.methodh  sk    "&"5 1BJJ&0 eT**GGdND" 9!'4888wf555r   )r   r   r   r%   )rv   rw   s   ` r   make_methodz*_create_magic_methods.<locals>.make_methodg  s9    	6 	6 	6 	6 	6 !T22:r   )?__eq____ne____lt____gt____le____ge____neg____pos____abs__
__invert____add____sub____mul____truediv____floordiv____mod__
__divmod____pow__
__lshift__
__rshift____and____or____xor____iadd____isub____imul____itruediv____ifloordiv____imod____ipow____ilshift____irshift____iand____ior____ixor__
__matmul____radd____rsub____rmul____rtruediv____rfloordiv____rmod____rdivmod____rpow____rlshift____rrshift____rand____ror____rxor____rmatmul____copy____deepcopy__
__reduce____iter____len____getitem____setitem____bool____int__	__float____complex__r"   __str__N)setattrr   )rx   rw   s     r   _create_magic_methodsr   a  sO    
 
 
# $6 $6H 	V!4!45555I$6 $6r   c                   >    e Zd Zej        j        Zd Zd Zd Zd Z	dS )r   c                 z   d| j         d<   d| j         d<   t          |d         t                    r:d| j         d<   |d         j        r
d| j         d<   |d         j        f|dd          z   }t          j        t          j                   t          j        |i || j         d<   | j         d         j	        | j         d<   d S )	NF_is_numpy_pyfunc_cupy_supportr   T   vec_objr%   )
__dict__r   r   r   r   r   r>   r   r   r%   r?   s      r   r   zvectorize.__init__  s    ,1()).o&d1g~.. 	704DM,-Aw# 615o.G)+d122h6D+BL999#%<#@#@#@i #'=#;#Ci   r   c                 8    t          | j        d         |          S )Nr   )r   r   )r
   r   s     r   r   zvectorize.__getattr__  s    t}Y/666r   c                 .    t          | j        ||          S r$   )r   r   )r
   rv   values      r   __setattr__zvectorize.__setattr__  s    t|T5111r   c                     | j         r$t          j        | j        j        | j                   t          | j        ||          S r$   )r   r   r>   r   pyfuncr   r=   r?   s      r   rB   zvectorize.__call__  sC      	9/#T%79 9 94<v666r   N)
r   rC   rD   r   r   r%   r   r   r   rB   r.   r   r   r   r     s]        l"GD D D7 7 72 2 27 7 7 7 7r   r   c                 V    t          |           r |          S t          |t                    rt           fd|D                       S t          |t                    r! fd|                                D             S t          |t                    r fd|D             S |S )a  
    Converts ndarray_instance type object to target object using to_xp.

    Args:
        ndarray_instance (numpy.ndarray, cupy.ndarray or fallback.ndarray):
            Objects of type `ndarray_instance` will be converted using `to_xp`.
        to_xp (FunctionType): Method to convert ndarray_instance type objects.
        arg (object): `ndarray_instance`, `tuple`, `list` and `dict` type
            objects will be returned by either converting the object or it's
            elements, if object is iterable. Objects of other types is
            returned as it is.

    Returns:
        Return data structure will be same as before after converting ndarrays.
    c                 2    g | ]}t          |          S r.   _get_xp_argsr*   xndarray_instanceto_xps     r   r0   z _get_xp_args.<locals>.<listcomp>  s&    LLL1l#3UA>>LLLr   c                 :    i | ]\  }}|t          |          S r.   r   )r*   x_namer   r   r   s      r   
<dictcomp>z _get_xp_args.<locals>.<dictcomp>  s<     . . .FA %5ua@@ . . .r   c                 2    g | ]}t          |          S r.   r   r   s     r   r0   z _get_xp_args.<locals>.<listcomp>  s&    FFFQ-ua88FFFr   )r   r2   r5   itemsr3   )r   r   r/   s   `` r   r   r     s    " #'(( uSzz#u NLLLLLLLLMMM#t .. . . . .!$. . . 	. #t GFFFFF#FFFFJr   c                 L    t          t          j        t          j        |           S r$   )r   r   r   r]   )	numpy_ress    r   _convert_numpy_to_fallbackr     s    
G$CYOOOr   c                 F    t          t          t          j        | |f          S r$   )r   r   rf   r@   rA   s     r   _convert_fallback_to_numpyr     s    !9D&>JJJr   c                 F    t          t          t          j        | |f          S r$   )r   r   rd   r   s     r   _convert_fallback_to_cupyr     s    !84.IIIr   c                 L    t          t          j        t          j        |           S r$   )r   rN   r   rY   )cupy_ress    r   _convert_cupy_to_fallbackr     s    
G$BHMMMr   c                 F    t          t          t          j        | |f          S r$   )r   r   rj   r   s     r   _update_numpy_argsr     s    !<tVnMMMr   c                 F    t          t          t          j        | |f          S r$   )r   r   ra   r   s     r   _update_cupy_argsr     s    !;dF^LLLr   c                 L   t          ||           t          ||          \  }} | |i |}t          |||||          }||S t          |t          j                  rG|j        t          |          }n.t          |j        ||||          }t          |          }||_        |S |S )a8  
    Calls cupy function with *args and **kwargs and
    does necessary data transfers.

    Args:
        func: A cupy function that needs to be called.
        args (tuple): Arguments.
        kwargs (dict): Keyword arguments.

    Returns:
        Result after calling func and performing data transfers.
    )r   r   _get_same_referencer   rN   r   rU   r   )	funcr@   rA   	cupy_argscupy_kwargsr   ext_resfallback_resbase_args	            r   r;   r;     s     dF###6tVDDI{tY.+..H ")[$8 8G(BJ'' 
= 4X>>LL +y+tVE EH4X>>L (LOr   c                 L   t          ||           t          ||          \  }} | |i |}t          |||||          }||S t          |t          j                  rG|j        t          |          }n.t          |j        ||||          }t          |          }||_        |S |S )a:  
    Calls numpy function with *args and **kwargs and
    does necessary data transfers.

    Args:
        func: A numpy function that needs to be called.
        args (tuple): Arguments.
        kwargs (dict): Keyword arguments.

    Returns:
        Result after calling func and performing data transfers.
    )r   r   r   r   r   r   rU   r   )	r   r@   rA   
numpy_argsnumpy_kwargsr   r   r   r   s	            r   r=   r=   $  s     tV$$$9$GGJj1L11I ":|T6; ;G)RZ(( 
>!5i@@LL +
L$H HH5i@@L (Lr   c                     t          t          |                    D ]}| ||         u r
||         c S |D ]}| ||         u r
||         c S dS )z_
    Returns object corresponding to res in (args, kwargs)
    from (ret_args, ret_kwargs)
    N)rangelen)resr@   rA   ret_args
ret_kwargsr+   keys          r   r   r   J  s    
 3t99  $q'>>A;   # #&+c?"""  Fr   )r%   r   numpyr   cupyrN   cupyx.fallback_moder   rL   r   r   r   r   r   r   r   r   r   r   r   r;   r=   r   r.   r   r   <module>r      s             - , , , , ,E= E= E= E= E=V E= E= E=P 	r2* * * * *f * * *D66 66 66r     7 7 7 7 7 7 7 7F  BP P PK K KJ J JN N NN N NM M M# # #L# # #L    r   