o
    oi_5                  
   @   s  d dl Zd dlZd dlZd dlZd dlmZmZmZ d dl	m
Z
 d dlmZmZ d dlmZmZmZmZmZmZmZmZmZmZmZ d dlZd dlmZ d dlmZ d dlm Z  d	e!fd
dZ"ded	e!fddZ#dFde$d	ej%fddZ&d	ej%fddZ'd	ej%fddZ(edede)d	efddZ*ede)d	e)fddZ*dee)ef deded	ee)ef fddZ*	dGdee) dee) d ee) d	efd!d"Z+d#eee  d	eej%ej,f fd$d%Z-d&ed	efd'd(Z.d&ed)e$d*ee/e!f d+ee/e!f d	ef
d,d-Z0d&ed	eeeef fd.d/Z1d&ed	efd0d1Z2d2ed3ed	efd4d5Z3d3ed2ed	eeeef fd6d7Z4d2ed	eeef fd8d9Z5dHd;e!d	e!fd<d=Z6d>ed	efd?d@Z7edAZ8dBee)ef dCee8 d	e8fdDdEZ9dS )I    N)asdictfieldsis_dataclass)wraps)isclass
isfunction)TYPE_CHECKINGAnyCallableDictListOptionalTupleTypeTypeVarUnionoverload)inv_ex)Tensor)torch_version_gereturnc                   C   s   t jddur
dS dS )z6Return whether `torch_xla` is available in the system.	torch_xlaNTF)	importlibutil	find_spec r   r   H/home/ubuntu/.local/lib/python3.10/site-packages/kornia/utils/helpers.pyxla_is_available"   s   r   xc                 C   s   dt | jv S )z'Return whether tensor is on MPS device.mps)strdevice)r   r   r   r   is_mps_tensor_safe)   s   r"   indexc                 C   s$   t j rt d|  S t dS )zTry to get cuda device, if fail, return cpu.

    Args:
        index: cuda device index

    Returns:
        torch.device

    zcuda:cpu)torchcudais_availabler!   )r#   r   r   r   get_cuda_device_if_available.   s   


r(   c                  C   s*   d} t tjdrtjj rd} t| S )zTTry to get mps device, if fail, return cpu.

    Returns:
        torch.device

    r$   r   )hasattrr%   backendsr   r'   r!   )devr   r   r   get_mps_device_if_available>   s
   
r,   c                   C   s"   t jdkrt dkrt S t S )zCheck OS and platform and run get_cuda_device_if_available or get_mps_device_if_available.

    Returns:
        torch.device

    darwinarm64)sysplatformmachiner,   r(   r   r   r   r   #get_cuda_or_mps_device_if_availableL   s   r2   storagelocationc                 C      d S Nr   )r3   r4   r   r   r   map_location_to_cpuY      r7   c                 C   r5   r6   r   )r3   r   r   r   r7   ]   r8   argskwargsc                 O   s   | S )z@Map location of device to CPU, util for loading things from HUB.r   )r3   r9   r:   r   r   r   r7   a   s   replace_withversionextra_reasonc                    s&   dt dtf dtf fdd}|S )zMark methods as deprecated.func.r   c                    s,   t  dtdtdtf fdd}|S )Nr9   r:   r   c                     s   d}d urd dnd}t rjj}trj}tdt d ur;tj| d| d d  tdd	 ntj| d| d
  tdd	 tdt | i |S )N zSince kornia z the always`z` is deprecated in favor of `z`.   )category
stacklevelz;` is deprecated and will be removed in the future versions.default)r   	__class____name__r   warningssimplefilterDeprecationWarningwarn)r9   r:   name	beginning)r=   r>   r;   r<   r   r   wrapperl   s(   z0deprecated.<locals>._deprecated.<locals>.wrapper)r   r	   )r>   rN   r=   r;   r<   )r>   r   _deprecatedk   s   "zdeprecated.<locals>._deprecated)r
   r	   )r;   r<   r=   rP   r   rO   r   
deprecatedf   s   "rQ   tensor_listc                 C   s   d\}}| D ]9}|dur?t |tfsq|j}|j}|du r&|du r&|}|}q||ks.||kr?td| d| d| d| d	q|du rItd}|du rQt }||fS )zCheck if all the input are in the same device (only if when they are Tensor).

    If so, it would return a tuple of (device, dtype). Default: (cpu, ``get_default_dtype()``).

    Returns:
        [torch.device, torch.dtype]

    )NNNz8Passed values are not in the same device and dtype.Got (z, z) and (z).r$   )
isinstancer   r!   dtype
ValueErrorr%   get_default_dtype)rR   r!   rT   tensor_device_dtyper   r   r   _extract_device_dtype   s8   	
rZ   inputc                 C   sT   t | tstdt|  d| j}|tjtjfvrtj}tj	| 
|
| jS )a  Make torch.inverse work with other than fp32/64.

    The function torch.inverse is only implemented for fp32/64 which makes impossible to be used by fp16 or others. What
    this function does, is cast input data type to fp32, apply torch.inverse, and cast back to the input dtype.
    Input must be Tensor. Got: .)rS   r   AssertionErrortyperT   r%   float32float64linalginvto)r[   rT   r   r   r   _torch_inverse_cast   s   
re   binsminmaxc                 C   sX   t | tstdt|  d| j}|tjtjfvrtj}t| 	||||	| jS )a  Make torch.histc work with other than fp32/64.

    The function torch.histc is only implemented for fp32/64 which makes impossible to be used by fp16 or others. What
    this function does, is cast input data type to fp32, apply torch.inverse, and cast back to the input dtype.
    r\   r]   )
rS   r   r^   r_   rT   r%   r`   ra   histcrd   )r[   rf   rg   rh   rT   r   r   r   _torch_histc_cast   s   
rj   c                 C   st   | j }|tjtjfvrtj}tj| |\}}}tddr#|j}n|	dd}|| j || j || j fS )ai  Make torch.svd work with other than fp32/64.

    The function torch.svd is only implemented for fp32/64 which makes
    impossible to be used by fp16 or others. What this function does, is cast
    input data type to fp32, apply torch.svd, and cast back to the input dtype.

    NOTE: in torch 1.8.1 this function is recommended to use as torch.linalg.svd
          )
rT   r%   r`   ra   rb   svdrd   r   mH	transpose)r[   rT   out1out2out3Hout3r   r   r   _torch_svd_cast   s   
"rv   c                 C   s   t | tstdt|  d| j}|tjtjfvrtj}tr nt	ddr/tj
| |}ntj
| |\}}}|| jS )at  Make torch.linalg.svdvals work with other than fp32/64.

    The function torch.svd is only implemented for fp32/64 which makes
    impossible to be used by fp16 or others. What this function does, is cast
    input data type to fp32, apply torch.svd, and cast back to the input dtype.

    NOTE: in torch 1.8.1 this function is recommended to use as torch.linalg.svd
    r\   r]   rk   
   )rS   r   r^   r_   rT   r%   r`   ra   r   r   rb   svdvalsrd   ro   )r[   rT   out_r   r   r   _torch_linalg_svdvals   s   
	
r{   ABc                 C   s<   t | rtj}ntj}tj| |||}|| jS )zMake torch.solve work with other than fp32/64.

    For stable operation, the input matrices should be cast to fp64, and the output will
    be cast back to the input dtype. However, fp64 is not yet supported on MPS.
    )r"   r%   r`   ra   rb   solverd   rT   )r|   r}   rT   ry   r   r   r   _torch_solve_cast   s
   r   c                 C   sJ  t dds!t|| }tjdtdd ||tjt|tj|j	dfS t
| ts0tdt|  d| j}|tjtjfvr>tj}trAn t ddrStj||\}}}ntj||d	d	d
\}}}|dk}t| j}t|j}	|	| dkrz| d} tr}nt ddrtj||| |}
n
t| |||}
|
| j||j|fS )zSolves the system of equations.

    Avoids crashing because of singular matrix input and outputs the mask of valid solution.
    rk   rw   z>PyTorch version < 1.10, solve validness mask maybe not correct)rD   )rT   r!   zB must be Tensor. Got: r]      T)	get_infosr   rm   )r   r   rH   rK   RuntimeWarningr%   oneslenboolr!   rS   r   r^   r_   rT   r`   ra   r   rb   lu_factor_exrd   lushape	unsqueezelu_solve)r}   r|   solrT   A_LUpivotsinfo
valid_maskn_dim_Bn_dim_AXr   r   r   safe_solve_with_mask	  s.   







r   c                 C   sh   t | tstdt|  d| j}|tjtjfvrtj}n|}t| 	|\}}|dk}|	||fS )zyPerform inverse.

    Avoids crashing because of non-invertable matrix input and outputs the mask of valid solution.
    zA must be Tensor. Got: r]   r   )
rS   r   r^   r_   rT   r%   r`   ra   r   rd   )r|   dtype_originalrT   inverser   maskr   r   r   safe_inverse_with_mask6  s   
r   Tbothc                 C   sP   t rdS tdddsdS | r$tddrt ptdS t p#t S t S )a  Check if torch autocast is enabled.

    Args:
        both: if True will consider autocast region for both types of devices

    Returns:
        Return a Bool,
        will always return False for a torch without support, otherwise will be: if both is True
        `torch.is_autocast_enabled() or torch.is_autocast_enabled('cpu')`. If both is False will return just
        `torch.is_autocast_enabled()`.

    Frk   rw   rB      r$   )r   r   r%   is_autocast_enabledis_autocast_cpu_enabled)r   r   r   r   r   I  s   
r   objc                 C   sl   t | rt| tsdd t|  D S t| ttfr&t| dd | D S t| tr4dd |  D S | S )z8Recursively convert dataclass instances to dictionaries.c                 S      i | ]	\}}|t |qS r   dataclass_to_dict.0keyvaluer   r   r   
<dictcomp>i      z%dataclass_to_dict.<locals>.<dictcomp>c                 s   s    | ]}t |V  qd S r6   r   )r   itemr   r   r   	<genexpr>k  s    z$dataclass_to_dict.<locals>.<genexpr>c                 S   r   r   r   r   r   r   r   r   m  r   )r   rS   r_   r   itemslisttupledict)r   r   r   r   r   f  s   
r   Tdict_objdataclass_typec                 C   s   t | ts	tdt|stddd t|D }i }|  D ]\}}||v r8t|| r8t||| ||< q |||< q |di |S )z8Recursively convert dictionaries to dataclass instances.zInput conf must be dictz"dataclass_type must be a dataclassc                 S   s   i | ]}|j |jqS r   )rL   r_   )r   fr   r   r   r   {  s    z%dict_to_dataclass.<locals>.<dictcomp>Nr   )rS   r   	TypeErrorr   r   r   dict_to_dataclass)r   r   field_typesconstructor_argsr   r   r   r   r   r   u  s   

r   )r   )NNN)T):importlib.utilr   r0   r/   rH   dataclassesr   r   r   	functoolsr   inspectr   r   typingr   r	   r
   r   r   r   r   r   r   r   r   r%   torch.linalgr   kornia.corer   kornia.utils._compatr   r   r   r"   intr!   r(   r,   r2   r    r7   rQ   rT   rZ   re   floatrj   rv   r{   r   r   r   r   r   r   r   r   r   r   r   <module>   sX   4*
&$ . -&