U
    /eH                  	   @   sF  d dl Z d dlZd dlZd dlZd dlZd dlZ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mZmZ dd Zd7dd	Zd
d Zd8ddZdd Zdd Zdd Zd9ddZd:ddZd;ddZd<ddZejfdd Zd!d" Z d#d$ Z!d%d& Z"d'd( Z#d)d* Z$d+d, Z%d-d. Z&d=d/d0Z'd1d2 Z(d>d3d4Z)d5d6 Z*dS )?    N)concatfrequencies)Array)HighLevelGraph)has_keywordis_arraylikeis_cupy_typec                 C   s   t | r|  S | S d S N)r   getx r   4/tmp/pip-unpacked-wheel-dbjnr7gq/dask/array/utils.pynormalize_to_array   s    r   c              
      s  t | drt| tr| j} |dkr2| dkr2tdt| rFt| } | dkrVtj} n|dkrnt | drn| j	}t| t
r| d|pd |d} t| tst| trdd	 | D }d
d	 t| |D }t| tr|S t| S t | drt | drt| jts| S |dkr| j}z| tdd t| jD  }|j|kr|| jkr|tftdd t||j D   }|tdd t|jD  }n"|dkr| }n|d| }|tjjkrtjjtjd| |p| j	ddd}W n0 tk
r   tjd| |p| j	d}Y nX t|r&t|}|r|j	|krz||}W n` tk
r   z@t fdddD r|j	jdkrtg |}n W 5 d  X Y nX |S )a  Normalize an array to appropriate meta object

    Parameters
    ----------
    x: array-like, callable
        Either an object that looks sufficiently like a Numpy array,
        or a callable that accepts shape and dtype keywords
    ndim: int
        Number of dimensions of the array
    dtype: Numpy dtype
        A valid input for ``np.dtype``

    Returns
    -------
    array-like with zero elements of the correct dtype
    _metaNz/You must specify the meta or dtype of the arraydtyper   r   )shaper   c                 S   s4   g | ],}t |tjrd nt|dr(|jnt|qS )r   ndim)
isinstancenumbersNumberhasattrr   len).0ar   r   r   
<listcomp><   s   
z#meta_from_array.<locals>.<listcomp>c                 S   s&   g | ]\}}|d kr|nt ||qS r   )meta_from_array)r   r   Zndr   r   r   r   D   s     r   c                 s   s   | ]}t d d dV  qdS r   Nslicer   _r   r   r   	<genexpr>R   s     z"meta_from_array.<locals>.<genexpr>c                 s   s   | ]
}d V  qd S r	   r   r!   r   r   r   r#   U   s     c                 s   s   | ]}t d d dV  qdS r   r   r!   r   r   r   r#   V   s     r   T)maskc                 3   s   | ]}|t  kV  qd S r	   strr   ser   r   r#   h   s   )zinvalid literalz!could not convert string to floatZSU)r   r   r   r   
ValueErrornpisscalararrayndarrayr   typelisttuplezipr   r   rangeEllipsissumZreshapemaZmaskedempty	Exceptionastypeanykind)r   r   r   Zndimsr   metar   r*   r   r      sn    




&

* 


r   c                    s  t jdd t  tjdtd dd |D }dd | D }t| t jrb| | }nz t	| drvd	|d< | ||}W n t
k
r   z<t fd
ddD r nW Y W 5 Q R  W 5 Q R  d S W 5 d   X Y n tk
rB   zHt|dkrdt kr|d }nW Y W 5 Q R  W 5 Q R  d S W 5 d   X Y n, tk
rl   Y W 5 Q R  W 5 Q R  d S X |rt|dd |krtt ||}W 5 Q R X t |rt |}|W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )Nignore)all)categoryc                 S   s    g | ]}t |rt|n|qS r   r   r   )r   r   r   r   r   r   |   s     z compute_meta.<locals>.<listcomp>c                 S   s&   i | ]\}}|t |rt|n|qS r   rB   r   kvr   r   r   
<dictcomp>}   s     z compute_meta.<locals>.<dictcomp>Zcomputing_metaTc                 3   s   | ]}|t  kV  qd S r	   r&   r(   r*   r   r   r#      s   zcompute_meta.<locals>.<genexpr>)zunexpected keyword argumentzis an invalid keyword forz'Did not understand the following kwargs   z&zero-size array to reduction operationr   r   )r-   Zerrstatewarningscatch_warningssimplefilterRuntimeWarningitemsr   Z	vectorizer   	TypeErrorr<   r,   r   r'   r:   getattr
contextlibsuppressAttributeErrorr;   r.   r/   )funcZ_dtypeargskwargsZ	args_metaZkwargs_metar>   r   r*   r   compute_metax   sH    
.

.
rU   Fc                 K   s   t | } t |}t| dd dkrft| ds4t|drNtjj| |fddi|S tj| |fd|i|S |r| j|jkotdd t| j	|j	D S | |k S )	Nr   Or%   Zmasked_equalT	equal_nanc                 s   s.   | ]&\}}t |rt |n||kV  qd S r	   )r-   isnan)r   r   br   r   r   r#      s    zallclose.<locals>.<genexpr>)
r   rN   r   r-   r8   allcloser   r@   r4   Zflat)r   rY   rW   rT   r   r   r   rZ      s    rZ   c                 C   s$   dd }t | j|dt |j|dkS )Nc                 S   s   t | tr| dddfS | S d S )N)r   r'   )rD   r   r   r   key   s    
zsame_keys.<locals>.key)r\   )sorteddask)r   rY   r\   r   r   r   	same_keys   s    r_   c                 C   s   | j od| j kS Nr   )r   r   r   r   r   
_not_empty   s    ra   c                 C   sb   t | tsdS |   tdd | jD s.ttt| j }dd |	 D }|r^t|dS )z2Check that graph is well named and non-overlappingNc                 s   s   | ]}t |ttfV  qd S r	   )r   r3   r'   )r   rD   r   r   r   r#      s     z_check_dsk.<locals>.<genexpr>c                 S   s   i | ]\}}|d kr||qS )rG   r   rC   r   r   r   rF      s       z_check_dsk.<locals>.<dictcomp>)
r   r   validater@   ZlayersAssertionErrorr   r   valuesrL   )ZdskZfreqsZnon_oner   r   r   
_check_dsk   s    
re   Tc                 C   sn   |rt | t |kstt| |D ]F\}}t|s>t|r\|rht|t|kshtq"||ks"tq"d S r	   )r   rc   r4   mathrX   )r   rY   
check_ndim	check_nanZaaZbbr   r   r   assert_eq_shape   s    ri   c                 C   s   | j |d} tjdd | jD  D ]}| j| jf|  }t|drJ| }t|dsbtj	|dd}t
dd t| j|D }t||j|d	d
 |j| jks"tdq"| S )N	schedulerc                 s   s   | ]}t t|V  qd S r	   )r5   r   )r   cr   r   r   r#      s     z _check_chunks.<locals>.<genexpr>resultr   rV   r$   c                 s   s   | ]\}}|| V  qd S r	   r   )r   rl   ir   r   r   r#      s     F)rg   rh   z6maybe you forgot to pass the scheduler to `assert_eq`?)Zpersist	itertoolsproductchunksr^   namer   rm   r-   r/   r3   r4   ri   r   r   rc   )r   rg   rk   idxchunkZexpected_shaper   r   r   _check_chunks   s&    

   
ru   c           
      C   s   | }d }d }t | tr| jd k	s$t| j}	|r8t| j t| dd }|rVt| ||d} | j|d} | }t	| drx| 
 } t	| dstj| dd} t| r| j|jkst|rt|j| jdd	 n$t	| dstj| dd} t| dd }	| |	||fS )
Nr   )rg   rk   rj   todenser   rV   r$   F)rh   )r   r   r   rc   re   r^   rN   ru   computer   rv   r-   r/   ra   ri   r   )
r   check_shapecheck_graphcheck_chunksrg   rk   Z
x_originalZx_metaZ
x_computedadtr   r   r   _get_dt_meta_computed   s2    




r|   syncc                 K   sV  | }|}t | tttfr"t| } t |tttfr<t|}t| |||||
d\} }}}t||||||
d\}}}}|rt|t|krtd| d| dzj| j	|j	kstd| j	 d|j	 d|r"| j	r| n| 
 }|j	r|n|
 }t|t|ks"tdt| dt| d|rt| drNt|drNt| j|j t|drd|jj d	| j d}|jj| jkst||d k	rd
t|j d	t| d}t|jt|kst|t|st|sdt| dt| d}t|t|kst|t|drd|jj d	|j d}|jj|jksTt||d k	rdt|j d	t| d}t|jt|kst|t|st|sdt| dt| d}t|t|kst|d}t| |fd|	i|st|W dS  tk
r    Y nX | |k}t |tjrH| sRtn
|sRtdS )N)rx   ry   rz   rg   rk   z#a and b have different dtypes: (a: z, b: )z"a and b have different shapes (a: z!a and b have different types (a: r   z<compute()-ing 'a' changes its number of dimensions (before: z	, after: z,compute()-ing 'a' changes its type (before: zRcompute()-ing 'a' results in a different type than implied by its metadata (meta: z, computed: z<compute()-ing 'b' changes its number of dimensions (before: z,compute()-ing 'b' changes its type (before: zRcompute()-ing 'b' results in a different type than implied by its metadata (meta: zHfound values in 'a' and 'b' which differ by more than the allowed amountrW   T)r   r2   intfloatr-   r/   r|   r'   rc   r   itemr1   r   	assert_eqr   r   r.   rZ   rM   r0   r@   )r   rY   rx   ry   Z
check_metarz   rg   Z
check_typeZcheck_dtyperW   rk   rT   Z
a_originalZ
b_originalr{   Za_metaZ
a_computedZbdtZb_metaZ
b_computedZ_a_bmsgrl   r   r   r   r     s    

	



 
r   c                    s0   t  fdd|D r$tj |dS dd S dS )zkLike functools.wraps, but safe to use even if wrapped is not a function.

    Only needed on Python 2.
    c                 3   s   | ]}t  |V  qd S r	   )r   )r   attrwrappedr   r   r#     s     zsafe_wraps.<locals>.<genexpr>)assignedc                 S   s   | S r	   r   r   r   r   r   <lambda>      zsafe_wraps.<locals>.<lambda>N)r@   	functoolswraps)r   r   r   r   r   
safe_wraps  s    r   c                 C   s.   z| j W S  tk
r(   t| j  Y S X dS )z!Determine dtype of an array-like.N)r   rQ   r-   
asanyarray)r   r   r   r   	_dtype_of  s    r   c                 O   sT   | dkrt j||S zt j|dt| i|W S  tk
rN   t j|| Y S X dS )z
    Use the `like=` from `np.arange` to create a new array dispatching
    to the downstream library. If that fails, falls back to the
    default NumPy behavior, resulting in a `numpy.ndarray`.
    Nlike)r-   Zaranger   rM   )r   rS   rT   r   r   r   arange_safe  s    r   c                 K   s   ||krt |dr|S t|tr,||f|S t|trLt|jrL|jdd}z| |fdt|i|W S  tk
r   | |f| Y S X d S )NZ__array_function__r}   rj   r   )r   r   r   r   r   rw   r   rM   )Znp_funcZda_funcr   r   rT   r   r   r   _array_like_safe  s    


r   c                 K   s    ddl m} ttj|| |f|S )a  
    If `a` is `dask.array`, return `dask.array.asarray(a, **kwargs)`,
    otherwise return `np.asarray(a, like=like, **kwargs)`, dispatching
    the call to the library that implements the like array. Note that
    when `a` is a `dask.Array` backed by `cupy.ndarray` but `like`
    isn't, this function will call `a.compute(scheduler="sync")`
    before `np.array`, as downstream libraries are unlikely to know how
    to convert a `dask.Array` and CuPy doesn't implement `__array__` to
    prevent implicit copies to host.
    r   )r/   )Zdask.array.routinesr/   r   r-   )r   r   rT   r/   r   r   r   
array_safe  s    r   c                 K   s    ddl m} ttj|| |f|S )a  
    If a is dask.array, return dask.array.asarray(a, **kwargs),
    otherwise return np.asarray(a, like=like, **kwargs), dispatching
    the call to the library that implements the like array. Note that
    when a is a dask.Array but like isn't, this function will call
    a.compute(scheduler="sync") before np.asarray, as downstream
    libraries are unlikely to know how to convert a dask.Array.
    r   )asarray)dask.array.corer   r   r-   )r   r   rT   r   r   r   r   asarray_safe  s    	r   c                 K   s    ddl m} ttj|| |f|S )a  
    If a is dask.array, return dask.array.asanyarray(a, **kwargs),
    otherwise return np.asanyarray(a, like=like, **kwargs), dispatching
    the call to the library that implements the like array. Note that
    when a is a dask.Array but like isn't, this function will call
    a.compute(scheduler="sync") before np.asanyarray, as downstream
    libraries are unlikely to know how to convert a dask.Array.
    r   )r   )r   r   r   r-   )r   r   rT   r   r   r   r   asanyarray_safe  s    	r   c                    st   t | ttfr$t fdd| D S t | tjs<td|  |   k sN|  kr`td|  f | dk rp|  7 } | S )z#Validate an input to axis= keywordsc                 3   s   | ]}t | V  qd S r	   )validate_axis)r   Zaxr   r   r   r#     s     z validate_axis.<locals>.<genexpr>z%Axis value must be an integer, got %sz2Axis %d is out of bounds for array of dimension %dr   )r   r3   r2   r   IntegralrM   r-   	AxisError)axisr   r   r   r   r     s    
r   c                 C   sf   |r| j }tj| ddd}n|j }tj|dddj}d|dkd | }| | ||j  } }| |fS )a  Sign correction to ensure deterministic output from SVD.

    This function is useful for orienting eigenvectors such that
    they all lie in a shared but arbitrary half-space. This makes
    it possible to ensure that results are equivalent across SVD
    implementations and random number generator states.

    Parameters
    ----------

    u : (M, K) array_like
        Left singular vectors (in columns)
    v : (K, N) array_like
        Right singular vectors (in rows)
    u_based_decision: bool
        Whether or not to choose signs based
        on `u` rather than `v`, by default False

    Returns
    -------

    u : (M, K) array_like
        Left singular vectors with corrected sign
    v:  (K, N) array_like
        Right singular vectors with corrected sign
    r   T)r   ZkeepdimsrG   g       @g      ?)r   r-   r7   Tr;   )urE   Zu_based_decisionr   Zsignsr   r   r   svd_flip  s    r   c                 O   sF   |d }t |r(dd l}t|jj| }ndd l}t|j| }|||S r`   )r   Zcupyx.scipy.linalgrN   scipyZlinalgZscipy.linalg)	func_namerS   rT   r   ZcupyxrR   r   r   r   r   scipy_linalg_safe  s    r   c                 C   s   t d| ||dS )NZsolve_triangular)lower)r   )r   rY   r   r   r   r   solve_triangular_safe.  s    r   c                 C   s6   | dkrt jdtdd tjS tdt d|  d S )Nr   z}AxisError was deprecated after version 2021.10.0 and will be removed in a future release. Please use numpy.AxisError instead.   )rA   
stacklevelzmodule z has no attribute )rH   warnFutureWarningr-   r   rQ   __name__)rr   r   r   r   __getattr__2  s    r   )NN)F)TT)TN)TTTTN)	TTTTTTTTr}   )F)F)+rO   r   ro   rf   r   rH   Znumpyr-   Ztlzr   r   r   r   Zdask.highlevelgraphr   Z
dask.utilsr   r   r   r   r   rU   rZ   r_   ra   re   ri   ru   r|   r   WRAPPER_ASSIGNMENTSr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s^   
a4



     
*         
k

*
