o
    Nrf*                     @  s   d dl mZ d dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlZ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 d dlmZ d dlmZmZ dZdd Zdd Z dd Z!dddZ"dS )    )annotationsN)Counter)reduce)product)mul)config)Arraynormalize_chunks)meta_from_array)tokenize)flatten)HighLevelGraph)Mparse_bytesa  
Dask's reshape only supports operations that merge or split existing dimensions
evenly. For example:

>>> x = da.ones((6, 5, 4), chunks=(3, 2, 2))
>>> x.reshape((3, 2, 5, 4))  # supported, splits 6 into 3 & 2
>>> x.reshape((30, 4))       # supported, merges 6 & 5 into 30
>>> x.reshape((4, 5, 6))     # unsupported, existing dimensions split unevenly

To work around this you may call reshape in multiple passes, or (if your data
is small enough) call ``compute`` first and handle reshaping in ``numpy``
directly.
c                   s  t dd D sJ td }t|d }dd ttD }dd tt|D }|dks6|dkrƈ| || krS| ||< | ||< |d8 }|d8 }q-| }|| }|dkrid||< |d8 }nU|dkrwd||< |d8 }nG||k r8|d }	|	dkrtt|	|d  |k r|	d8 }	|	dkrtt|	|d  |k stt|	|d  |krttt fd	dt|D rt|d D ]}
|
 ||
< qˈ| tt	t|	|  ||< nHt|	d |d D ]	}
|
 f||
< qttt	t|	d |d  }t
|	 |||	< tt|	d |d  tfd
d||	 D ||< |d8 }|	d }n||kr|d }|dkrktt|||d  |k rk|d8 }|dkrktt|||d  |k sTtt|||d  |kr}tttt||d |d   t|  ||< t|d |d D ]
}
||
 f||
< qt fdd|| D ||< |d }|d8 }|dks6|dks6t|t|fS )Nc                 s  s    | ]}t |tV  qd S N)
isinstancetuple.0c r   [/var/www/html/software/conda/envs/catlas/lib/python3.10/site-packages/dask/array/reshape.py	<genexpr>$   s    z"reshape_rechunk.<locals>.<genexpr>   c                 S     g | ]}d qS r   r   r   ir   r   r   
<listcomp>'       z#reshape_rechunk.<locals>.<listcomp>c                 S  r   r   r   r   r   r   r   r   (   r   r   r   c                 3  s$    | ]}t  | | kV  qd S r   )lenr   )inchunksinshaper   r   r   D   s   " c                 3  s    | ]} | V  qd S r   r   r   )prodr   r   r   R   s    
c                 3  s    | ]}|  V  qd S r   r   r   )csr   r   r   f   s    )allr    ranger   r   NotImplementedError_not_implemented_messagemathr#   mapexpand_tupler   contract_tuple)r"   Zoutshaper!   iiZoiZresult_inchunksZresult_outchunksdindoutZileftr   Zchunk_reductionZoleftr   )r$   r!   r"   r#   r   reshape_rechunk#   sv   
""
 

&&Ar0   c                 C  s   |dkr| S g }| D ]+}|}t || d}|d| kr.|t| |t|8 }|d| ks|r5|| q
t| t|ks@J t|S )z

    >>> expand_tuple((2, 4), 2)
    (1, 1, 2, 2)

    >>> expand_tuple((2, 4), 3)
    (1, 1, 1, 1, 2)

    >>> expand_tuple((3, 4), 2)
    (1, 2, 2, 2)

    >>> expand_tuple((7, 4), 3)
    (2, 2, 3, 1, 1, 2)
    r      )maxappendintsumr   )chunksfactoroutr   xpartr   r   r   r+   n   s   
r+   c                 C  s\   t | | dks
J g }d}| D ]}||7 }|| }|| }|| }|r)|| qt|S )zReturn simple chunks tuple such that factor divides all elements

    Examples
    --------

    >>> contract_tuple((2, 2, 8, 4), 4)
    (4, 8, 4)
    r   )r5   r3   r   )r6   r7   r8   ZresidualchunkdivZgoodr   r   r   r,      s   	
r,   Tc                   s>  ddl m} ddlm} tt||}dd |D }t|t|k rSt|t| dkr0tdt|dkr=| jdkr=| S || j	t
t|d  t fdd	|D }tt| jrdtd
t| j t
t|d| j	krqtd| j|krx| S t| t|}dt| | }| jdkrtt|  }	|fdt|  tj|	|fi}
tdd	 |D }tj||
| gd}t||||dS t| j}t|}|s||kr| dd t|| D } t| j|| j\}}t
tdd |D | j j! }|du rt"t#$d}t#$dd}nt"|}d}||krW|du rd}t%j&||dd n8|rWt'|t'|@ }g }|D ]}|| dkrF|(| ||  d8  < q.|(d q.t)|||| j |d}| |}t*t+|j,ggdd |D R  }t*t+|ggdd |D R  }t*t+| }dd t-|||D }
tj||
|gd}t||||dS ) ab  Reshape array to new shape

    Parameters
    ----------
    shape : int or tuple of ints
        The new shape should be compatible with the original shape. If
        an integer, then the result will be a 1-D array of that length.
        One shape dimension can be -1. In this case, the value is
        inferred from the length of the array and remaining dimensions.
    merge_chunks : bool, default True
        Whether to merge chunks using the logic in :meth:`dask.array.rechunk`
        when communication is necessary given the input array chunking and
        the output shape. With ``merge_chunks==False``, the input array will
        be rechunked to a chunksize of 1, which can create very many tasks.
    limit: int (optional)
        The maximum block size to target in bytes. If no limit is provided,
        it defaults to using the ``array.chunk-size`` Dask config value.

    Notes
    -----
    This is a parallelized version of the ``np.reshape`` function with the
    following limitations:

    1.  It assumes that the array is stored in `row-major order`_
    2.  It only allows for reshapings that collapse or merge dimensions like
        ``(1, 2, 3, 4) -> (1, 6, 4)`` or ``(64,) -> (4, 4, 4)``

    .. _`row-major order`: https://en.wikipedia.org/wiki/Row-_and_column-major_order

    When communication is necessary this algorithm depends on the logic within
    rechunk.  It endeavors to keep chunk sizes roughly the same when possible.

    See :ref:`array-chunks.reshaping` for a discussion the tradeoffs of
    ``merge_chunks``.

    See Also
    --------
    dask.array.rechunk
    numpy.reshape
    r   )PerformanceWarning)sanitize_indexc                 S  s   g | ]}|d kr|qS )r   r   sr   r   r   r          zreshape.<locals>.<listcomp>r   z&can only specify one unknown dimensionc                 3  s     | ]}|d kr
 n|V  qdS )r?   Nr   r@   Zmissing_sizer   r   r      s    zreshape.<locals>.<genexpr>z_Array chunk size or shape is unknown. shape: %s

Possible solution with x.compute_chunk_sizes()z)total size of new array must be unchangedzreshape-)r   c                 s  s    | ]}|fV  qd S r   r   )r   dr   r   r   r      s    )dependencies)metac                 S  s   i | ]}|d qS r   r   r   r   r   r   
<dictcomp>   s    zreshape.<locals>.<dictcomp>c                 S  s   g | ]}t |qS r   )r2   r   r   r   r   r      s    Nzarray.chunk-sizez array.slicing.split-large-chunksTa  Reshaping is producing a large chunk. To accept the large
chunk and silence this warning, set the option
    >>> with dask.config.set(**{'array.slicing.split_large_chunks': False}):
    ...     array.reshape(shape)

To avoid creating the large chunks, set the option
    >>> with dask.config.set(**{'array.slicing.split_large_chunks': True}):
    ...     array.reshape(shape)Explicitly passing ``limit`` to ``reshape`` will also silence this warning
    >>> array.reshape(shape, limit='128 MiB')   )
stacklevelauto)shapelimitdtypeZprevious_chunksc                 S     g | ]}t t|qS r   r&   r    r   r   r   r   r   (  rB   c                 S  rN   r   rO   r   r   r   r   r   )  rB   c                 S  s    i | ]\}}}|t j||fqS r   )r   reshape)r   abrK   r   r   r   rG   +  s     ).dask.array.corer=   Zdask.array.slicingr>   r   r*   r    
ValueErrorndimsizer   r   npisnanr5   rK   strr
   r   Znpartitionsnextr   Z__dask_keys__r   rP   r   Zfrom_collectionsr   Zrechunkr&   r0   r6   rM   itemsizer   r   getwarningswarnr   r3   r	   listr   namezip)r9   rK   Zmerge_chunksrL   r=   r>   Zknown_sizesrF   r`   keyZdskr6   graphr.   r/   r!   Z	outchunksZmax_chunksize_in_bytessplitmsgZmatching_chunksZ
chunk_planr8   Zx2Zin_keysZout_keysZshapesr   rC   r   rP      s   *







" rP   )TN)#
__future__r   r)   r]   collectionsr   	functoolsr   	itertoolsr   operatorr   numpyrW   Zdaskr   rS   r   r	   Zdask.array.utilsr
   Z	dask.baser   Z	dask.corer   Zdask.highlevelgraphr   Z
dask.utilsr   r   r(   r0   r+   r,   rP   r   r   r   r   <module>   s(    K