
    bioU                       d dl mZ d dl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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 d dlmZ dZddZd Zd Zd Zd Zd Z ddZ!d Z"	 d	 	 	 	 	 	 	 ddZ#d Z$	 	 	 	 	 	 ddZ%y)    )annotationsN)reduce)product)mul)TaskTaskRef)Array)meta_from_array)tokenize)flatten)HighLevelGraph)Ma  
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           
     l    t        d D              sJ t               dz
  }t        |      dz
  }t        t                     D cg c]  }d  }}t        t        |            D cg c]  }d  }}i g }
}	|dk\  s|dk\  r |   ||   k(  r |   ||<   |   ||<   ||	|<   |dz  }|dz  }6 |   }||   }|dk(  rd||<   |dz  }n|dk(  rd||<   |
j                  |       |dz  }n||k  rw|dz
  }||	|<   |dk\  rBt	        t
         ||dz          |k  r)||	|<   |dz  }|dk\  rt	        t
         ||dz          |k  r)||	|<   t	        t
         ||dz          |k7  rt        t              t         fdt        |      D              rKt        |dz         D ]
  }|   ||<    |   t        j                  t        t        ||             z  ||<   nt        |dz   |dz         D ]  } |   f||<    t	        t
        t        t        |dz   |dz                }t        |   |      ||<   t        ||      }t        ||||      }t        |||      ||<   |dz  }|dz
  }n||kD  r|rt        d      |dz
  }|dk\  r=t	        t
        |||dz          |k  r$|dz  }|dk\  rt	        t
        |||dz          |k  r$t	        t
        |||dz          |k7  rt        t              t	        t
        ||dz   |dz          t        |         ||<   t        |dz   |dz         D ]  }||   f||<    t!        fd||   D              ||<   t        ||      }t        ||||      }t        |||      ||<   |dz
  }|dz  }|dk\  r|dk\  rt!        |      t!        |      |	|
fS c c}w c c}w )Nc              3  <   K   | ]  }t        |t                y wN)
isinstancetuple.0cs     M/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/dask/array/reshape.py	<genexpr>z"reshape_rechunk.<locals>.<genexpr>"   s     6z!U#6s      r   )r   c              3  F   K   | ]  }t        |         |   k(    y wr   )len)r   iinchunksinshapes     r   r   z"reshape_rechunk.<locals>.<genexpr>I   s#     Ea3x{#wqz1Es   !zWreshape_blockwise not implemented for expanding dimensions without passing chunk hints.c              3  (   K   | ]	  }|z    y wr    )r   r   css     r   r   z"reshape_rechunk.<locals>.<genexpr>s   s     +QAG+Qs   )allr   rangeappendr   r   NotImplementedError_not_implemented_messagemathprodmapexpand_tuple_cal_max_chunk_size_smooth_chunks_calc_lower_dimension_chunkscontract_tupler   )r   outshaper   disallow_dimension_expansioniioir   result_inchunksresult_outchunks	mapper_inone_dimensionsdindoutileftchunk_reductionmax_in_chunkoleftr!   s   ` `              @r   reshape_rechunkr=   !   sv   6X6666	W	B	X	B%*3w<%89t9O9&+CM&:;;; "B~I
'R1W2;(2,&"*2,OB#+B<R IbM!GB!GBbk|!8"&OB!GBQY#'R !!"%!GB4ZFEIbM
vc7526+BCdJ#%	% 
 
vc7526+BCdJ
  "Iec752623t;)*BCC E59EErAv 5A)1!OA&5'/|diiXeB/07 ( $ uqy"q&1 7A*1!*OA&7 #)c#x	BQRF7S.T"U)5huo)W&28UBG"02|_# (D#UB( $ !GBB4Z+)m  FE1*Xeb1f-E!F!L
 1*Xeb1f-E!F!Lc8EBF34;)*BCCXeai"q&9:B"0"r"BOB519b1f- 5'/{n #5 ',+Q_R=P+Q&QU#.xR@L-eRGWX"> %#OB B!GBg 'R1Wj !5)9#:I~UUs :;s   
	N,+	N1c                F    t        t        d t        | ||dz                 S )Nc                "    t        t        |       S r   r   r   xs    r   <lambda>z._calc_lower_dimension_chunks.<locals>.<lambda>   s    fS!n     r   )r   r)   r   )chunksstartstops      r   r-   r-      s/     $VED1H-.	
 rD   c                   | }t        || |      }||k(  r|S t        d ||    D              r| dz  } t        d ||    D              r| |dz   k  rtt        j                  ||z        }||    }t	        |      dk(  r|d   }t        ||      }t        j                  ||z        }	|	g|z  }
t        |	|z  |z
        D ]  }|
|xx   dz  cc<    t        |
      || <   t        d |
D              r| |k  rt        ||||      S |S |t        ||          z  }g }|D ]  }||z  |k  r|j                  |       t        j                  ||z  |z        }t        j                  ||z        }	|	gt        j                  |      z  }t        |	|z  |z
        D ]  }||xx   dz  cc<    |j                  |        t        |      || <   |S )Nc              3  &   K   | ]	  }|d k(    ywr   Nr    r   rB   s     r   r   z!_smooth_chunks.<locals>.<genexpr>   s     5a1f5   r   r   c              3  &   K   | ]	  }|d k(    ywrJ   r    rK   s     r   r   z!_smooth_chunks.<locals>.<genexpr>   s     /a16/rL   )r+   r"   r'   ceilr   minr#   r   r,   maxr$   extend)r9   r1   r;   r3   
ileft_origmax_result_in_chunkfactorresult_in_chunkelem	ceil_elemnew_inchunkr   other_max_chunk	result_inelem_innew_in_chunks                   r   r,   r,      s   4 J-oubI**
5oe45
5
 5oe45
5 rAv~.=>)%01$
 #1%D&F		$-0I$+.K9v-45 $A!#$%*;%7OE"/;//EBJ%j"lOTT, ! 2S9O5PPOI* 
/_,<$$W-7_#<|#KL IIg&67	 ){TYYv->>y61G;< )A Oq(O)  .
/ &+9%5OE"rD   c                    t        t        t        t        ||dz         D cg c]  }t	        | |          c}            S c c}w )Nr   )intr   r   r#   rP   )rE   rF   rG   axiss       r   r+   r+      sB    +0q+AB4SB	
  Cs   Ac                &   |dk(  r| S g }| D ]`  }|}t        ||z  d      }|d|z  k\  r1|j                  t        |             |t        |      z  }|d|z  k\  r1|sP|j                  |       b 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      )rP   r$   r^   sumr   )rE   rT   outr   rB   parts         r   r*   r*      s     {
C 1v:q!1t8mJJs4y!TNA 1t8m JJqM v;#c(""":rD   c                    t        |       |z  dk(  sJ g }d}| D ]*  }||z  }||z  }||z  }||z  }|s|j                  |       , t        |      S )zReturn simple chunks tuple such that factor divides all elements

    Examples
    --------

    >>> contract_tuple((2, 2, 8, 4), 4)
    (4, 8, 4)
    r   )rb   r$   r   )rE   rT   rc   residualchunkdivgoods          r   r.   r.     st     v;1$$$
CH vo6>|JJt :rD   c                   ddl m} t        t        ||            }|D cg c]
  }|dk7  s	| }}t	        |      t	        |      k  r|t	        |      t	        |      z
  dkD  rt        d      t	        |      dk(  r| j                  dk(  r| S  || j                  t        t        |d      z        t        fd|D              }t        | |       | j                  |k(  r| S t        | t	        |            }dt        | |      z   }| j                  dk(  rt        t!        | j#                                     }	|fdt	        |      z  z   }
|
t%        |
t&        j(                  t+        |	      |      i}t        d	 |D              }t-        j.                  ||| g
      }t1        ||||      S t	        | j                        }t	        |      }|s6||kD  r1| j3                  t4        j7                  t9        ||z
        d            } t;        | j                  || j<                        \  }}}}| j3                  |      }t?        tA        |jB                  gg|D cg c]  }t9        t	        |             c}       }t?        tA        |gg|D cg c]  }t9        t	        |             c}       }t?        tA        |       }tE        |||      D ci c],  \  }}}|t%        |t&        j(                  t+        |      |      . }}}}t-        j.                  |||g
      }t1        ||||      S c c}w c c}w c c}w c c}}}w )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   )sanitize_indexr   z&can only specify one unknown dimensionc              3  0   K   | ]  }|d k(  rn|  yw)rl   Nr    )r   smissing_sizes     r   r   zreshape.<locals>.<genexpr>Q  s     Da2gl14Ds   zreshape-)r   c              3  "   K   | ]  }|f 	 y wr   r    )r   ds     r   r   zreshape.<locals>.<genexpr>`  s     +t+s   dependenciesmeta)#dask.array.slicingrk   r   r)   r   
ValueErrorndimsizer   r   _sanity_checksshaper
   r   npartitionsnextr   __dask_keys__r   r   reshaper   r   from_collectionsr	   rechunkdictfromkeysr#   r=   rE   listr   namezip)rB   r{   merge_chunkslimitrk   rn   known_sizesru   r   keynew_keydskrE   graphr7   r8   r   	outchunks_x2r   in_keysout_keysshapesabro   s                             @r   r   r     s   T 2#ne,-E#/qBw1/K/
;#e*$u:K((1,EFF u:?qvv{H%affvc;/J&JKDeDD1eww%1c%j)DE**D}}71??,-.'D3u:--WaiiuEF+U++//cLUD&t44 agg,Cu:DC$JIIdmmE#*$5q9: / IHiA	
8	B 7BGG9Ix'H!c!f'HIJGGTFHY%GeCFm%GHIH'9%&F x&9 Aq% 	
4199gaj%00C 
 ++D#RDIEid33_ 0L (I%Gs   
L.L.L3
L81L=c                    t        j                  t        | j                              r!t	        dt        | j                        z        t        t        |d      | j                  k7  rt	        d      y )Nz_Array chunk size or shape is unknown. shape: %s

Possible solution with x.compute_chunk_sizes()r   z)total size of new array must be unchanged)	npisnanrb   r{   rw   strr   r   ry   )rB   r{   s     r   rz   rz   z  sa    	xxAGG=?B177|L
 	

 c5!&DEE 'rD   c                   |dv rt        t        | j                        f}t        |t              s|f}t        | |       t        |      | j                  k(  r<|| j                  k(  r-t        | j                  | j                  | j                  |       S dt        | |      z   }t        t        d t        | j                        D               }t        |      | j                  kD  r|t!        d      t        t        d |D               }t        t        d |D               }t        t        d	 | j                  D               }t        t#        ||            D 	
cg c]8  \  }\  }	}
t%        j&                  |	      t%        j&                  |
      k7  r||	|
f: }}	}}
|r:t)        d
|dd D  cg c]  } | d   	 c}  d|dd D  cg c]  } | dd 	 c}  d      t#        |||      D ci c]S  \  }}}|ft	        |      z   t+        |ft	        |      z   t,        t/        | j                  ft	        |      z         |      U }}}}t1        j2                  ||| g      }t        |||| j4                        S |t)        d      t7        | j                  || j                  d      \  }}}}t        t        d | j                  D               D cg c]  }t9        |||       }}t9        t	        t;        t        | j                              ||      }t        t        d |D               }t#        |||      D ci c]S  \  }}}|ft	        |      z   t+        |ft	        |      z   t,        t/        | j                  ft	        |      z         |      U }}}}g }d}t        t=        |            D ]_  \  }}g }t?        |      D ]+  }|jA                  |||z     t        |      |z
  dz
            - |jA                  t	        |             ||z  }a t1        j2                  ||| g      }t        ||t	        t=        |            | j4                        S c c}
}	}w c c} w c c} w c c}}}w c c}w c c}}}w )a;  Blockwise-reshape into a new shape.

    The regular reshape operation in Dask preserves C-ordering in the array
    which requires a rechunking for most reshaping operations, making the
    computation relatively expensive.

    Blockwise-reshape reshapes every block into the new shape and concatenates
    the results. This is a trivial blockwise computation but will return the
    result in a different order than NumPy. This is a good solution for
    subsequent operations that don't rely on the order.

    Parameters
    ----------
    x: Array
        The input array to reshape.
    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.
    chunks: tuple of ints, default None
        The chunk sizes for every chunk in the output array. Dask will expand
        the chunks per dimension into the cross product of chunks for every
        chunk in the array.

        An error is raised if chunks is given and the number of dimensions
        decreases.

        .. note::
            This information is required if the number of dimensions is increased.
            Dask cannot infer the output chunks in this case. The keyword is ignored
            if the number of dimensions is reduced.

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

    1.  It does not return elements in the same order as NumPy would
    2.  It only allows for reshapings that collapse like
        ``(1, 2, 3, 4) -> (1, 6, 4)``

    Examples
    --------
    >>> import dask.array as da
    >>> import numpy as np
    >>> x = da.from_array(np.arange(0, 27).reshape(3, 3, 3), chunks=(3, 2, (2, 1)))
    >>> result = reshape_blockwise(x, (3, 9))
    >>> result.chunks
    ((3,), (4, 2, 2, 1))

    The resulting chunks are calculated automatically to match the new shape.

    >>> result.compute()
    array([[ 0,  1,  3,  4,  2,  5,  6,  7,  8],
           [ 9, 10, 12, 13, 11, 14, 15, 16, 17],
           [18, 19, 21, 22, 20, 23, 24, 25, 26]])

    >>> result = reshape_blockwise(result, (3, 3, 3), chunks=x.chunks)
    >>> result.chunks
    ((3,), (2, 1), (2, 1))

    The resulting chunks are taken from the input. Chaining the reshape operation
    together like this reverts the previous reshaping operation that reduces the
    number of dimensions.

    >>> result.compute()
    array([[[ 0,  1,  2],
            [ 3,  4,  5],
            [ 6,  7,  8]],
    <BLANKLINE>
           [[ 9, 10, 11],
            [12, 13, 14],
            [15, 16, 17]],
    <BLANKLINE>
           [[18, 19, 20],
            [21, 22, 23],
            [24, 25, 26]]])
    )rl   )rl   rt   zreshape-blockwise-c              3  J   K   | ]  \  }}t        t        |              y wr   r#   r   )r   r   r   s      r   r   z$reshape_blockwise.<locals>.<genexpr>  s     !PDAq%A-!Ps   !#Nz/Need to specify chunks if expanding dimensions.c              3      K   | ]  }|  y wr   r    r   s     r   r   z$reshape_blockwise.<locals>.<genexpr>  s     #6!A#6   c              3  D   K   | ]  }t        t        |              y wr   r   r   s     r   r   z$reshape_blockwise.<locals>.<genexpr>  s     )HA%A-)Hs    c              3      K   | ]  }|  y wr   r    r   s     r   r   z$reshape_blockwise.<locals>.<genexpr>  s     "71"7r   z3Chunk sizes do not match for the following chunks:    r   z%. 
The corresponding chunksizes are: r   z". (restricted to first 5 entries).rr   zESetting chunks is not allowed when reducing the number of dimensions.T)r0   c              3      K   | ]  }|  y wr   r    r   s     r   r   z$reshape_blockwise.<locals>.<genexpr>  s     4a4r   c              3  2   K   | ]  }t        |        y wr   )r#   r   s     r   r   z$reshape_blockwise.<locals>.<genexpr>  s     %F1eAh%Fs   )!r   r   r{   r   r   rz   r   rx   r	   daskr   rE   r   r   r   	enumerate	TypeErrorr   r'   r(   rw   r   _reshape_blockwiser   r   r   _metar=   _convert_to_shaper)   reversedr#   r$   )rB   r{   rE   outnamechunk_tuples
out_shapesout_chunk_tuples	in_shapesr   in_cout_cnon_matching_chunkschunk_in	chunk_outr   r   r   r5   r6   r   nr_out_chunksoutput_chunksctrnr_chunks_dimdimension_chunksrV   s                             r   reshape_blockwiser     s   h QWW%'eU#1e
5zQVV 0QVVQVVQXXA66"Xa%77G!PIahh<O!PQRL
5zAFF>MNN'#6v#678
)H)H IJ"7ahh"789	 %.c)Z.H$I
 
 =D%yy$))E"22 e
 

 E"5bq"9:QAaD:; <5EXY[Z[E\5]ae5]4^ _34  /2.
/
 
 +)U JI $
U9--"	E(O34	!
 
 //A3OUGV!''::S
 	
 '6	t'#Aq)^ g4188456 	!Y7J 
 &c#qxx !9nM G%F%FGH +.*J+
  'Hi 


	
	 Jy))QVVIh/0	
	
C   M
C%h}&=> =-( 	XD##Jtcz$:3};MPQ;QTU;U$VW	XU#345} ++GSsKEx'>!?aggNNY
 ;5]
4s&   =Q.Q!
Q&,AQ+Q2 AQ7c                $    | j                  |      S r   )r   )arrr{   s     r   r   r   <  s    ;;urD   c                6   g gt        t        |j                                     t        |      z   z  }t        t	        d |            }|D ]  }dg||<   
 |j                         D ]  \  }}||   j                  | |           t        t	        d |            S )Nc                "    | j                         S r   )copyrA   s    r   rC   z#_convert_to_shape.<locals>.<lambda>I  s    affh rD   r   c                "    t        t        |       S r   r@   rA   s    r   rC   z#_convert_to_shape.<locals>.<lambda>P  s    vc1~ rD   )r   setvaluesr   r)   itemsr$   r   )r{   r5   one_dimsoutput_shaper   kvs          r   r   r   @  s     &(DC	  "#$s8}4%L .=>L #Q ! )1QuQx() -|<==rD   )F)TNr   )rB   r	   r{   zint | tuple[int, ...]rE   z"tuple[tuple[int, ...], ...] | Nonereturnr	   )r{   ztuple[int, ...]r5   zdict[int, int]r   z	list[int])&
__future__r   r'   	functoolsr   	itertoolsr   operatorr   numpyr   dask._task_specr   r   dask.array.corer	   dask.array.utilsr
   	dask.baser   	dask.corer   dask.highlevelgraphr   
dask.utilsr   r&   r=   r-   r,   r+   r*   r.   r   rz   r   r   r   r    rD   r   <module>r      s    "      ) ! ,   .  ]V@M`>.\4~F 26tOtO tO /tO 	tOn>>'5>AJ>rD   