
    Cd                      d dl mZ d dlZd dlZd dl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Zd dlmZmZmZm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 d dlm Z m!Z!  e"ddd          Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d)dZ.d Z/ed             Z0d Z1d Z2d Z3d Z4d Z5d Z6d Z7d  Z8d! Z9d" Z:d# Z;d$ Z<d% Z=d& Z>d' Z?d( Z@dS )*    )annotationsN)product)IntegralNumber)
itemgetter)concatmemoizemergepluck)configcoreutilsgetitem)is_dask_collectiontokenize)HighLevelGraph)cached_cumsumis_arraylikec                >   t          | t                    r)t          |           }|| k    rt          d| z            |S | dS t	          |           r/| j        j        dk    s| j        dk    rt          d|            | S t          dt          |           |           )zSanitize a one-element index.$Bad index.  Must be integer-like: %sNi   z!Bad index. Must be integer-like: Invalid index type)

isinstancer   int
IndexErrorr   dtypekindsize	TypeErrortype)indind2s     2lib/python3.11/site-packages/dask/array/slicing.py_sanitize_index_elementr&      s    #v >3xx3;;CcIJJJK	t	C	 	  >9>S  CHMMFFFGGG
,d3ii===    c                
   ddl m} | dS t          | t                    rGt          t	          | j                  t	          | j                  t	          | j                            S t          | t                    rt	          |           S t          |           r| S  || |           }|j
        t          k    rTt          j        |          }t          |          dk    r|d         }t          |          r|S t          j        |          S t          j        |j
        t          j                  r|S t          j        |j
        t          j                  r|                    t          j                  }t          j        ||          r|S t          j        ||          }|                                t          j        |           d                  }t5          d|z            t7          dt9          |           |           )a  Sanitize the elements for indexing along one axis

    >>> sanitize_index([2, 3, 5])
    array([2, 3, 5])
    >>> sanitize_index([True, False, True, False])
    array([0, 2])
    >>> sanitize_index(np.array([1, 2, 3]))
    array([1, 2, 3])
    >>> sanitize_index(np.array([False, True, True]))
    array([1, 2])
    >>> type(sanitize_index(np.int32(0)))
    <class 'int'>
    >>> sanitize_index(1.0)
    1
    >>> sanitize_index(0.5)
    Traceback (most recent call last):
    ...
    IndexError: Bad index.  Must be integer-like: 0.5
    r   )asanyarray_safeNliker   r   r   )dask.array.utilsr)   r   slicer&   startstopstepr   r   r   boolnpnonzerolenr   
asanyarray
issubdtypeintegerfloatingastypeintpallcloseiscloseravelflatnonzeror   r!   r"   )r#   r)   index_arrayr3   	int_index	check_int	first_errs          r%   sanitize_indexrC   )   s   ( 100000
{t	C		 	#CI..#CH--#CH--
 
 	

 
C	 	  &s+++	C	 	  
!/#C000KD  *[))w<<1ajG   	*N=)))	{("*	5	5 >	{("+	6	6 	>&&rw//	;{I.. 	Q
;	::I#))++BNI:,F,Fq,IJICiOPPP,d3ii===r'   c                    t          t          t           |                    }t          d |D                       r&t          d |D              } fd|D             }||fS t	          d |D                       }t          |          |z
  }|t          ddd          f|z  z  }t           |||          \  }	}
t          t          t           |
                    }
|	|
fS )aW  
    Main function for array slicing

    This function makes a new dask that slices blocks along every
    dimension and aggregates (via cartesian product) each dimension's
    slices so that the resulting block slices give the same results
    as the original slice on the original structure

    Index must be a tuple.  It may contain the following types

        int, slice, list (at most one list), None

    Parameters
    ----------
    in_name - string
      This is the dask variable name that will be used as input
    out_name - string
      This is the dask variable output name
    blockshape - iterable of integers
    index - iterable of integers, slices, lists, or None
    itemsize : int
        The number of bytes required for each element of the array.

    Returns
    -------
    Dict where the keys are tuples of

        (out_name, dim_index[, dim_index[, ...]])

    and the values are

        (function, (in_name, dim_index, dim_index, ...),
                   (slice(...), [slice()[,...]])

    Also new blockdims with shapes of each block

        ((10, 10, 10, 10), (20, 20))

    Examples
    --------
    >>> from pprint import pprint
    >>> dsk, blockdims = slice_array('y', 'x', [(20, 20, 20, 20, 20)],
    ...                              (slice(10, 35),), 8)
    >>> pprint(dsk)  # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
    {('y', 0): (<function getitem at ...>,
                ('x', 0),
                (slice(10, 20, 1),)),
     ('y', 1): (<function getitem at ...>, ('x', 1), (slice(0, 15, 1),))}
    >>> blockdims
    ((10, 15),)

    See Also
    --------
    This function works by successively unwrapping cases and passing down
    through a sequence of functions.

    slice_with_newaxis : handle None/newaxis case
    slice_wrap_lists : handle fancy indexing with lists
    slice_slices_and_integers : handle everything else
    c              3  j   K   | ].}t          |t                    o|t          d d d           k    V  /d S N)r   r-   ).0indexs     r%   	<genexpr>zslice_array.<locals>.<genexpr>   sS        JO
5%  EUeD$.E.E%E     r'   c                F    g | ]}t          t          |                    S  ranger4   rG   bds     r%   
<listcomp>zslice_array.<locals>.<listcomp>   s$    @@@U3r77^^@@@r'   c                &    i | ]}f|z   f|z   S rK   rK   )rG   sin_nameout_names     r%   
<dictcomp>zslice_array.<locals>.<dictcomp>   s'    AAA1{Q
QAAAr'   c              3     K   | ]}|d uV  	d S rF   rK   rG   r   s     r%   rI   zslice_array.<locals>.<genexpr>   s&      661$666666r'   N)tuplemapallr   sumr4   r-   slice_with_newaxes)rT   rS   	blockdimsrH   itemsizesuffixesdsknot_none_countmissingdsk_outbd_outs   ``         r%   slice_arrayre   c   s   z c%++,,I   SX      @@i@@@AAAAAAAAAI~ 6666666N)nn~-G	eD$%%''11E )7IuhWWOGV3uf%%&&FF?r'   c                N    t          d |D                       }d t          |          D             }t          |          }t          |          D ]8\  }}	t          d |d|	         D                       }
|
r||xx         |
z  cc<   9t	           ||||          \  }}|r~t          |          t          |           fd|                                D             }t          | fd|                                D                       } |d          }||fS ||fS )z]
    Handle indexing with Nones

    Strips out Nones then hands off to slice_wrap_lists
    c              3     K   | ]}||V  	d S rF   rK   rG   r#   s     r%   rI   z%slice_with_newaxes.<locals>.<genexpr>   s"      ;;33?3????;;r'   c                    g | ]	\  }}||
S rF   rK   rG   r   r#   s      r%   rP   z&slice_with_newaxes.<locals>.<listcomp>   s    BBB3ck!kkkr'   c              3  @   K   | ]}t          |t                    V  d S rF   r   r   rh   s     r%   rI   z%slice_with_newaxes.<locals>.<genexpr>   s,      ??c
3))??????r'   Nc                    i | ]F\  }}|d          k    f |dd         d           z   |dd          |d         d          fz   GS )r   r   N   rK   )rG   kvexpandexpand_origrT   s      r%   rU   z&slice_with_newaxes.<locals>.<dictcomp>   ss     
 
 
1tx K&&122***QrrUkk!A$6M6M5O-Or'   c                4    i | ]\  }}|d          k    ||S r   rK   )rG   ro   rp   rT   s      r%   rU   z&slice_with_newaxes.<locals>.<dictcomp>   s-    MMMTQAaDH<L<LAq<L<L<Lr'   r   )rX   	enumeratelistr[   slice_wrap_listsexpanderitemsr
   )rT   rS   r]   rH   r^   index2
where_nonewhere_none_origr   xnr`   
blockdims2dsk2dsk3
blockdims3rq   rr   s   `               @@r%   r\   r\      sx    ;;%;;;;;FBB)E"2"2BBBJ:&&O*%%  1??U2A2Y????? 	qMMMQMMM 'x)VXVVOC *%%//
 
 
 
 
 
		
 
 
 TMMMMSYY[[MMMNN VJ--
Z Jr'   c                   t          d |D                       sJ t          |          t          |          k    st          d          d t          |          D             }t          |          dk    rt	          d          |rW||d                  j        sDt          |          }t          ddd          ||                                <   t          |          }|st          | |||          S t          d |D                       }t          d |D                       r-|d         t          | ||||d                  |	          \  }}nd
t          | |||f          z   }	t          |	|||          \  }
}|d         t          fdt          |          D                       z
  }t          | |	||         d|	          \  }}t          |
|          }||fS )a  
    Fancy indexing along blocked array dasks

    Handles index of type list.  Calls slice_slices_and_integers for the rest

    See Also
    --------

    take : handle slicing with lists ("fancy" indexing)
    slice_slices_and_integers : handle slicing with slices and integers
    c              3  x   K   | ]5}t          |t          t          t          f          pt	          |          V  6d S rF   )r   r-   rw   r   r   rW   s     r%   rI   z#slice_wrap_lists.<locals>.<genexpr>   s>      XXQz!eT8455HaXXXXXXr'   Too many indices for arrayc                L    g | ]!\  }}t          |          r|j        d k    |"S rt   )r   ndimrj   s      r%   rP   z$slice_wrap_lists.<locals>.<listcomp>   s:       aL,=,=BE(Q,,,,,r'   r   #Don't yet support nd fancy indexingr   c              3  Z   K   | ]&}t          |          rt          d d d           n|V  'd S rF   r   r-   rW   s     r%   rI   z#slice_wrap_lists.<locals>.<genexpr>  sO        >?<??9dD$     r'   c              3  ^   K   | ](}t          |          p|t          d d d           k    V  )d S rF   r   rW   s     r%   rI   z#slice_wrap_lists.<locals>.<genexpr>  s>      
J
Jq<??:a5tT#:#::
J
J
J
J
J
Jr'   )axiszslice-c              3  X   K   | ]$\  }}|k     t          |t                     d V  %dS r   Nrl   )rG   r   r#   r   s      r%   rI   z#slice_wrap_lists.<locals>.<genexpr>  sB       
 
!SDZX=V=VA
 
r'      )rZ   r4   r   rv   NotImplementedErrorr    rw   r-   poprX   slice_slices_and_integerstaker   r[   r
   )rT   rS   r]   rH   r^   
where_listindex_without_listr   r   tmpr`   axis2r   r   s                @r%   rx   rx      sY    XXRWXXXXXXXXy>>SZZ''5666 !%((  J :!"GHHH  %
1.3 U"'1a..jnne  N(7IuMMM   CH    
 
J
JE
J
J
JJJ  !}gy%
1*>t
 
 

DD 8Wi"GHHH3)%7
 
Z
 !}s 
 
 
 
%e,,
 
 
 
 
 

  #z5;PUVVV
DS$r'   c           
     $   ddl m} t          d |D                       }t          ||          D ]B\  }}t	          j        |          r)|t          ddd          k    rt          d| |           Ct          d |D                       sJ t          |          t          |          k    sJ t          t          t          |||                    }d |D             }	t          t          |ggd |	D             R            }
t          t          | ggd	 t          ||          D             R            }t          t          d
 |	D                        }d t          ||
|          D             }d t          |||          D             }||fS )z`
    Dask array indexing with slices and integers

    See Also
    --------

    _slice_1d
    r   )unknown_chunk_messagec              3  D   K   | ]}t          |d           d         V  dS )Tinitial_zeroNr   )rG   dims     r%   rI   z,slice_slices_and_integers.<locals>.<genexpr>+  s4      QQ-$777;QQQQQQr'   Nz Arrays chunk sizes are unknown: c              3  N   K   | ] }t          |t          t          f          V  !d S rF   )r   r-   r   rh   s     r%   rI   z,slice_slices_and_integers.<locals>.<genexpr>3  s1      CCcz#x011CCCCCCr'   c                P    g | ]#}t          |                                          $S rK   )sortedrz   rW   s     r%   rP   z-slice_slices_and_integers.<locals>.<listcomp>8  s(    CCC6!'')),,CCCr'   c                .    g | ]}t          d |          S rt   r   rG   rR   s     r%   rP   z-slice_slices_and_integers.<locals>.<listcomp>;  s     (R(R(Rq!(R(R(Rr'   c                    g | ]m\  }}t          |t                    |j        r0|j        d k     r%t          t	          |                    ddd         nt          t	          |                    nS )r   Nr   )r   r   r0   rM   r4   )rG   dr   s      r%   rP   z-slice_slices_and_integers.<locals>.<listcomp>A  su       Aq!!X..'(vO!&1**c!ffddd##%A--  r'   c                .    g | ]}t          d |          S ru   r   r   s     r%   rP   z-slice_slices_and_integers.<locals>.<listcomp>I  s     IIIaIIIr'   c                ,    i | ]\  }}}|t           ||fS rK   r   )rG   rT   rS   slicess       r%   rU   z-slice_slices_and_integers.<locals>.<dictcomp>K  s7       %Hgv 	7GV,  r'   c                b    g | ],\  }}}t          |t                    t          |||          -S rK   )r   r   new_blockdim)rG   r   r   dbs       r%   rP   z-slice_slices_and_integers.<locals>.<listcomp>P  sJ       Aq"!X&&QA  r'   )dask.array.corer   rX   zipr2   isnanr-   
ValueErrorrZ   r4   rw   rY   	_slice_1dr   )rT   rS   r]   rH   r   shaper   r#   block_slicessorted_block_slicesin_names	out_names
all_slicesrc   new_blockdimss                  r%   r   r      s    655555QQyQQQQQEu%%  S8C== 	SE$d$;$;;;Q5Q:OQQ   CCUCCCCCCCCu::Y'''' Iui??@@LCClCCC GWIS(R(R>Q(R(R(RSSSTTH J	
 e44  	
 	
 	
	 	I gII5HIIIJKKJ ),Y*)M)M  G
 E5)44  M M!!r'   c           	        t          |          }t          |t                    rJt          j        ||          }|dk    r|||dz
           z
  }n|}t          |          t          |          iS t          |t                    sJ |t          k    r&d t          t          |                    D             S |j
        pd}|dk    r|j        pd}|j        |j        n| }n4|j        |j        n| dz
  }|| k    r| dz
  n|}|j        | dz    n|j        }|dk     r|| z  }|dk     r|| z  }t                      }	|dk    rt          j        ||          }
t          j        ||          }t          |dz   t          |                    }|
dk    r|||
dz
           z
  }|||
dz
           z
  }t          |
|          D ]K}||         }||k     r1|dk    r+t          |t          ||          |          |	|<   ||z
  |z  }n||z
  }||z  }Ln|}t          j        ||          }
t          j        ||          }t          |
dz   t          |          dz
            }
t!          |dz
  d          }t          |
|d          D ]u}||         }|dk    rd}n||dz
           }||cxk    r|k     rJn .||k    rAt          ||z
  t!          ||z
  dz
  ||z
            |          |	|<   ||dz
  z
  |z  }||z   dz
  }v|	                                D ]4\  }}|t          d||         d          k    rt          ddd          |	|<   5|	st          ddd          |	d<   |	S )a 	  Returns a dict of {blocknum: slice}

    This function figures out where each slice should start in each
    block for a single dimension. If the slice won't return any elements
    in the block, that block will not be in the output.

    Parameters
    ----------

    dim_shape - the number of elements in this dimension.
      This should be a positive, non-zero integer
    blocksize - the number of elements per block in this dimension
      This should be a positive, non-zero integer
    index - a description of the elements in this dimension that we want
      This might be an integer, a slice(), or an Ellipsis

    Returns
    -------

    dictionary where the keys are the integer index of the blocks that
      should be sliced and the values are the slices

    Examples
    --------

    Trivial slicing

    >>> _slice_1d(100, [60, 40], slice(None, None, None))
    {0: slice(None, None, None), 1: slice(None, None, None)}

    100 length array cut into length 20 pieces, slice 0:35

    >>> _slice_1d(100, [20, 20, 20, 20, 20], slice(0, 35))
    {0: slice(None, None, None), 1: slice(0, 15, 1)}

    Support irregular blocks and various slices

    >>> _slice_1d(100, [20, 10, 10, 10, 25, 25], slice(10, 35))
    {0: slice(10, 20, 1), 1: slice(None, None, None), 2: slice(0, 5, 1)}

    Support step sizes

    >>> _slice_1d(100, [15, 14, 13], slice(10, 41, 3))
    {0: slice(10, 15, 3), 1: slice(1, 14, 3), 2: slice(2, 12, 3)}

    >>> _slice_1d(100, [20, 20, 20, 20, 20], slice(0, 100, 40))  # step > blocksize
    {0: slice(0, 20, 40), 2: slice(0, 20, 40), 4: slice(0, 20, 40)}

    Also support indexing single elements

    >>> _slice_1d(100, [20, 20, 20, 20, 20], 25)
    {1: 5}

    And negative slicing

    >>> _slice_1d(100, [20, 20, 20, 20, 20], slice(100, 0, -3)) # doctest: +NORMALIZE_WHITESPACE
    {4: slice(-1, -21, -3),
     3: slice(-2, -21, -3),
     2: slice(-3, -21, -3),
     1: slice(-1, -21, -3),
     0: slice(-2, -20, -3)}

    >>> _slice_1d(100, [20, 20, 20, 20, 20], slice(100, 12, -3)) # doctest: +NORMALIZE_WHITESPACE
    {4: slice(-1, -21, -3),
     3: slice(-2, -21, -3),
     2: slice(-3, -21, -3),
     1: slice(-1, -21, -3),
     0: slice(-2, -8, -3)}

    >>> _slice_1d(100, [20, 20, 20, 20, 20], slice(100, -12, -3))
    {4: slice(-1, -12, -3)}
    r   r   c                    i | ]
}|t           S rK   )colon)rG   ro   s     r%   rU   z_slice_1d.<locals>.<dictcomp>  s    666Q5666r'   Nr   )r   r   r   bisectbisect_rightr   r-   r   rM   r4   r0   r.   r/   dictbisect_leftminmaxrz   )	dim_shapelengthsrH   chunk_boundariesr   r#   r0   r.   r/   r   istartistoplengthrstart
chunk_stopchunk_startoffsetro   rp   s                      r%   r   r   Y  s   R %W--%"" " 0%88q55*1q511CCCAC!!eU#####~~66%G"5"56666:?Daxx q"Z3uzz${6IM!&)!3!3	A#(:#5Q5: qyyaxx	Aaxx$%5u=="#3T:: EAIs7||,, A::,VaZ88E*6A:66Dvu%% 	 	AQZFv~~$((UCf$5$5t<<!4/FNDD	 #$4e<<#$4d;; VaZ%5!6!6!:;;EAIr""vub)) 	2 	2A)!,JAvv.q1u5 v2222
22222$Z'j014dZ6GHH ! !K!O4<$v-1 		 + +1aQ''''tT**AaD Q1~~!Hr'   c                   t                    st          j                  t          j        t	          |           dz   t
                    }d|d<   t          j        | |dd                   }t          j        t	          |           dz   t
                    }d|d<   t          j        |          |dd<   fdt          |dd         |dd         |          D             S )zy

    >>> partition_by_size([10, 20, 10], [1, 5, 9, 12, 29, 35])
    [array([1, 5, 9]), array([ 2, 19]), array([5])]
    r   )r   r   N)outc                2    g | ]\  }}}||         |z
  S rK   rK   )rG   jro   lseqs       r%   rP   z%partition_by_size.<locals>.<listcomp>  s+    SSSwq!QS1X\SSSr'   r   )	r   r2   r5   emptyr4   r   cumsumsearchsortedr   )sizesr   leftright	locationss    `   r%   partition_by_sizer      s      !mC  8CJJN#...DDGIeabb***EUas333IIaLOC//IabbMSSSS#inimT*R*RSSSSr'   c                |    t          |           dk    rdS t          j        | dd         | dd         k              S )zdIs sequence sorted?

    >>> issorted([1, 2, 3])
    True
    >>> issorted([3, 1, 2])
    False
    r   TNr   r   )r4   r2   rZ   )r   s    r%   issortedr     s=     3xx1}}t6#crc(c!""g%&&&r'   c                   ddl m} t          |          st          j        |          }t          |           } |||          }t          j        ||d          }|                                }t          j        t          j	        |                    d         dz   } |dg|          } |t          |          g|          }t          j        |||g          }g }t          t          |          dz
            D ]T}	|||	         ||	dz                     }
|||	                  }|dk    r|
||dz
           z
  }
|                    ||
f           U|S )a  Construct a plan to slice chunks with the given index

    Parameters
    ----------
    chunks : Tuple[int]
        One dimensions worth of chunking information
    index : np.ndarray[int]
        The index passed to slice on that dimension

    Returns
    -------
    out : List[Tuple[int, np.ndarray]]
        A list of chunk/sub-index pairs corresponding to each output chunk
    r   asarray_safer*   r   )sider   )r,   r   r   r2   r5   r   r   tolistwherediffr4   concatenaterM   append)chunksrH   r   
cum_chunkschunk_locationsr   extrac_locr   r   	sub_indexchunks               r%   slicing_planr     sw    .----- %e$$v&&Jju555Joj%gFFFO &,,..OHRW_--..q1A5EL!5)))EL#o../e<<<ENE5%011E
C3u::>"" ' '%(U1q5\12	a)199!Juqy$99I

E9%&&&&Jr'   c                   ddl m} t                   |          }t          |          t                             dz  k    rQt	          j        t          |          t                             z            }t          j        d|z  |d           t          |          st          j
        |          }t          j        t          j        d                    }	fdt          t                              D             }
t	          j        d	 |
D                       }t	          j        |          s|dk    rt          j        x}}nt	          j        |	||z  z            }|d
z  }t          j        dd          }|du}|D ]5\  }}|s.t          |          |k    rd}t          j        ||d           d}6g }g }|D ]\  }}t          |          }|rl||k    rft          j        |t	          j        ||z                      }|                    |           |                    |gt          |          z             t          |          st          j        |          }|                    |           |                    |           d D             }t/          |          }t/          t          t          |                              |<   t/          t1          | gg|R            }t/          |          }||<   d D             }||<   t/          t1          |           }t/          t1          |gg|R            }d t3          ||          D             }t/                    }t5          t7          t          |                    |<   t9          t3          ||                    } t5          |          | fS )a  Index array with an iterable of index

    Handles a single index by a single list

    Mimics ``np.take``

    >>> from pprint import pprint
    >>> chunks, dsk = take('y', 'x', [(20, 20, 20, 20)], [5, 1, 47, 3], 8, axis=0)
    >>> chunks
    ((2, 1, 1),)
    >>> pprint(dsk)   # doctest: +ELLIPSIS
    {('y', 0): (<function getitem at ...>, ('x', 0), (array([5, 1]),)),
     ('y', 1): (<function getitem at ...>, ('x', 2), (array([7]),)),
     ('y', 2): (<function getitem at ...>, ('x', 0), (array([3]),))}

    When list is sorted we retain original block structure

    >>> chunks, dsk = take('y', 'x', [(20, 20, 20, 20)], [1, 3, 5, 47], 8, axis=0)
    >>> chunks
    ((3, 1),)
    >>> pprint(dsk)     # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
    {('y', 0): (<function getitem at ...>,
                ('x', 0),
                (array([1, 3, 5]),)),
     ('y', 1): (<function getitem at ...>, ('x', 2), (array([7]),))}

    When any indexed blocks would otherwise grow larger than
    dask.config.array.chunk-size, we might split them,
    depending on the value of ``dask.config.slicing.split-large-chunks``.

    >>> import dask
    >>> with dask.config.set({"array.slicing.split-large-chunks": True}):
    ...      chunks, dsk = take('y', 'x', [(1, 1, 1), (2000, 2000), (2000, 2000)],
    ...                        [0] + [1] * 6 + [2], axis=0, itemsize=8)
    >>> chunks
    ((1, 3, 3, 1), (2000, 2000), (2000, 2000))
    r   PerformanceWarning
   zESlicing with an out-of-order index is generating %d times more chunks   
stacklevelzarray.chunk-sizec                ,    g | ]}|k    |         S rK   rK   )rG   r   r   r   s     r%   rP   ztake.<locals>.<listcomp>  s"    GGG!Q$YYF1IYYYr'   c              3  4   K   | ]}t          |          V  d S rF   )r   )rG   r~   s     r%   rI   ztake.<locals>.<genexpr>  s(      99qCFF999999r'      z array.slicing.split-large-chunksNai  Slicing 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[indexer]

To avoid creating the large chunks, set the option
    >>> with dask.config.set(**{'array.slicing.split_large_chunks': True}):
    ...     array[indexer]Tc                F    g | ]}t          t          |                    S rK   rL   rN   s     r%   rP   ztake.<locals>.<listcomp>  s$    ,,,rE#b''NN,,,r'   c                >    g | ]}t           gt          |          z  S rK   )r   r4   rN   s     r%   rP   ztake.<locals>.<listcomp>  s%    111BugB111r'   c                (    g | ]\  }}t           ||fS rK   r   )rG   inkeyslcs      r%   rP   ztake.<locals>.<listcomp>  s#    JJJ
sws#JJJr'   )r   r   r   r4   mathceilwarningswarnr   r2   asarrayr   parse_bytesr   getrM   prodr   infarray_splitextendarrayr   rw   r   r   rX   rY   r   )!outnameinnamer   rH   r^   r   r   planfactornbytesother_chunksother_numelwarnsizemaxsizesplitwarned_
index_listmsgwhere_indexindex_lists	where_idxindex_lengthindex_sublistdimsindimskeysoutdimsr   inkeysvalueschunks2r`   s!     `  `                           r%   r   r   K  s   L 322222te,,D
4yyCt%%***3t99s6$<'8'8899 "()		
 	
 	
 	
  "
5!! vz*<==>>FGGGGGuS[['9'9GGGL)99L99999Kz+ +"2"2!X%77)FkH&<=>>Q;J94@@E $F  : 	#j//H44-  M#1a@@@@FKK!% * *	:: 
	*\G++NDIlW&<== M }---	{S-?-??@@@@
++ 2Xj11
z***y)))),,V,,,D$ZZFc+..//00F4L	+F+++,,D4jjGGDM11&111FF4L'6"##F'6(-W---..FJJc&&6I6IJJJF6llG#c;//00GDM
s4  
!
!C>>3r'   c                   t          |t                    r#t          t          t          | |                    S t          |t                    r!|dk     rt          j        |           s|| z   S |S t          |t          j        t          f          rEt          j        |           s1t          j
        |          }t          j        |dk     || z   |          S |S )aP  Flip negative indices around to positive ones

    >>> posify_index(10, 3)
    3
    >>> posify_index(10, -3)
    7
    >>> posify_index(10, [3, -3])
    array([3, 7])

    >>> posify_index((10, 20), (3, -3))
    (3, 17)
    >>> posify_index((10, 20), (3, [3, 4, -3]))  # doctest: +NORMALIZE_WHITESPACE
    (3, array([ 3,  4, 17]))
    r   )r   rX   rY   posify_indexr   r   r   r2   ndarrayrw   r5   r   )r   r#   s     r%   r%  r%    s     #u 4Suc22333#x   774:e,,7;J#
D)** 34:e3D3D 3mC  xauc222Jr'   c                   | sd }|S d}g }d}t          t          |           dz             D ]9}|| v r|                    d           |                    d|z             |dz  }:d|z  }d                    |          } |j        di t                      }i }t          t          |d	d
          ||           |d         S )Nc                    | S rF   rK   )r   vals     r%   rq   z_expander.<locals>.expand  s    Jr'   zKdef expand(seq, val):
            return ({left}) + tuple({right})
        r   r   zval, z	seq[%d], zseq[%d:] z	<dynamic>execrq   rK   )rM   r   r   joinformatlocalsr+  compile)r   rq   declr   r   r   r   nss           r%   	_expanderr2    s     	 	 	  s5zzA~&& 	 	AEzzG$$$$K!O,,,QQwwt}}t{&&VXX&&WT;//R888(|r'   c                :    t          t          |                     S )zCreate a function to insert value at many locations in sequence.

    >>> expander([0, 2])(['a', 'b', 'c'], 'z')
    ('z', 'a', 'z', 'b', 'c')
    )r2  rX   )r   s    r%   ry   ry     s     U5\\"""r'   c                   |t          ddd          k    rS t          |t                    rt          |          gS t          |t                    rJ t          t          | |                                          t          d                    }fd|D             }t          |t                     r|j	        r|j	        dk     r|ddd         }d |D             S )a  

    >>> new_blockdim(100, [20, 10, 20, 10, 40], slice(0, 90, 2))
    [10, 5, 10, 5, 15]

    >>> new_blockdim(100, [20, 10, 20, 10, 40], [5, 1, 30, 22])
    [4]

    >>> new_blockdim(100, [20, 10, 20, 10, 40], slice(90, 10, -2))
    [16, 5, 10, 5, 4]
    Nr   )keyc                r    g | ]3\  }}|t          d d d           k    rt          d|         d          n|4S )Nr   r   r-   )rG   r   r   r   s      r%   rP   z new_blockdim.<locals>.<listcomp>  sX       As $'%dD*A*A#A#AaQs  r'   r   c                    g | ];}t          t          j        d |j        z  |j        z
  |j        z                      <S )g      ?)r   r   r   r/   r.   r0   )rG   r   s     r%   rP   z new_blockdim.<locals>.<listcomp>  s>    VVVC	3>CI5ABBCCVVVr'   )
r-   r   rw   r4   r   r   r   rz   r   r0   )r   r   rH   pairsr   s    `   r%   r   r     s     dD$''''% E

|%*****9Y77==??ZPQ]]SSSE     F % EJ 5:>>"VVvVVVVr'   c                   d t          |          D             }|s|S |d         }| t          |          t          d |D                       z
  dz
  z
  }|d|         t          ddd          f|z  z   ||dz   d         z   S )zReplace ... with slices, :, : ,:

    >>> replace_ellipsis(4, (3, Ellipsis, 2))
    (3, slice(None, None, None), slice(None, None, None), 2)

    >>> replace_ellipsis(2, (Ellipsis, None))
    (slice(None, None, None), slice(None, None, None), None)
    c                *    g | ]\  }}|t           u |S rK   )Ellipsisrj   s      r%   rP   z$replace_ellipsis.<locals>.<listcomp>*  s!    FFF3cXoo!ooor'   r   c              3     K   | ]}|d u V  	d S rF   rK   rW   s     r%   rI   z#replace_ellipsis.<locals>.<genexpr>/  s&      ,F,F1Q$Y,F,F,F,F,F,Fr'   r   N)rv   r4   r[   r-   )r   rH   
isellipsislocextra_dimensionss        r%   replace_ellipsisrA     s     GF)E"2"2FFFJ mCJJ,F,F,F,F,F)F)FFJKdsduT4..03CCCeCRSGIIFVVr'   c                8   t          | t                    rt          j        |          r| S |                     |          \  }}}|dk    r%|dk    rd}||k    rd}|dk    rd}|
|||k     r|}n|dk     r||dz
  k    rd}|dk     rd}t          |||          S | S )zNormalize slices to canonical form

    Parameters
    ----------
    idx: slice or other index
    dim: dimension length

    Examples
    --------
    >>> normalize_slice(slice(0, 10, 1), 10)
    slice(None, None, None)
    r   Nr   )r   r-   r   r   indices)idxr   r.   r/   r0   s        r%   normalize_slicerE  5  s     #u (:c?? 	JKK,,tT!88zzs{{qyyE$5$,,AXXaaxxUD$'''Jr'   c                $   ddl m}m} t          | t                    s| f} t          |           dk    r\t          |          dk    rI| d         }t          |          r2t          ||          s"|j        |k    r ||          g| dd         R } t          t          |          |           } d}| D ]0}t          |d          r|j
        dk    r||j
        z  }(|+|dz  }1| t          d          ft          |          |z
  z  z   } t          d | D                       t          |          k    rt          d          g }d}| D ]:}|!|                    ||                    |dz  }%|                    d           ;t          t          | |                    D ]\  }\  }}	|	t!          |||	           t	          t#          t$          |                     } t	          t#          t&          | |                    } t)          ||           } | S )aT  Normalize slicing indexes

    1.  Replaces ellipses with many full slices
    2.  Adds full slices to end of index
    3.  Checks bounding conditions
    4.  Replace multidimensional numpy arrays with dask arrays
    5.  Replaces numpy arrays with lists
    6.  Posify's integers and lists
    7.  Normalizes slices to canonical form

    Examples
    --------
    >>> normalize_index(1, (10,))
    (1,)
    >>> normalize_index(-1, (10,))
    (9,)
    >>> normalize_index([-1], (10,))
    (array([9]),)
    >>> normalize_index(slice(-3, 10, 1), (10,))
    (slice(7, None, None),)
    >>> normalize_index((Ellipsis, None), (10,))
    (slice(None, None, None), None)
    >>> normalize_index(np.array([[True, False], [False, True], [True, True]]), (3, 2))
    (dask.array<array, shape=(3, 2), dtype=bool, chunksize=(3, 2), chunktype=numpy.ndarray>,)
    r   )Array
from_arrayr   Nr   c                    g | ]}||S rF   rK   rW   s     r%   rP   z#normalize_index.<locals>.<listcomp>  s    ,,,!amAmmmr'   r   )r   rG  rH  r   rX   r4   r   r   rA  hasattrr   r-   r   r   rv   r   check_indexrY   rC   rE  r%  )
rD  r   rG  rH  r   n_sliced_dims
none_shaper#   r   r   s
             r%   normalize_indexrN  Y  sE   4 21111111c5!! f 3xx!||E

QF?? 	,:a#7#7 	,AGu<L<L:a==+3qrr7++C
3u::s
+
+CM  1f 	!&A++QV#MMYQMM
t#e**}"<=
=C
,,s,,,--E

::5666J	A $ $?eAh'''FAAd####!#c:"6"677 $ $fq!=a###
NC((
)
)C
OS*55
6
6C
z3
'
'CJr'   c                H   t          |t                    rt          j        |          }t          j        |          rdS t          |          rdS t          |          r|j        t          k    r*|j	        |k    rt          d|j	         d|  d|           dS ||k                                    s|| k                                     rt          d|  d|           dS t          |t                    rdS |dS ||k    s|| k     rt          d| d|  d|           dS )a  Check validity of index for a given dimension

    Examples
    --------
    >>> check_index(0, 3, 5)
    >>> check_index(0, 5, 5)
    Traceback (most recent call last):
    ...
    IndexError: Index 5 is out of bounds for axis 0 with size 5

    >>> check_index(1, 6, 5)
    Traceback (most recent call last):
    ...
    IndexError: Index 6 is out of bounds for axis 1 with size 5

    >>> check_index(1, -1, 5)
    >>> check_index(1, -6, 5)
    Traceback (most recent call last):
    ...
    IndexError: Index -6 is out of bounds for axis 1 with size 5

    >>> check_index(0, [1, 2], 5)
    >>> check_index(0, [6, 3], 5)
    Traceback (most recent call last):
    ...
    IndexError: Index is out of bounds for axis 0 with size 5

    >>> check_index(1, slice(0, 3), 5)

    >>> check_index(0, [True], 1)
    >>> check_index(0, [True, True], 3)
    Traceback (most recent call last):
    ...
    IndexError: Boolean array with size 2 is not long enough for axis 0 with size 3
    >>> check_index(0, [True, True, True], 1)
    Traceback (most recent call last):
    ...
    IndexError: Boolean array with size 3 is not long enough for axis 0 with size 1
    NzBoolean array with size z is not long enough for axis z with size z Index is out of bounds for axis zIndex z is out of bounds for axis )r   rw   r2   r5   r   r   r   r   r1   r    r   anyr-   )r   r#   	dimensions      r%   rK  rK    s   P #t !mC   
x	 
	C	 	  
	c		 
9x9$$ =sx = = $= =1:= =   %$
 Y##%% 	#
*:)?)?)A)A 	O4OOIOO  	 	 
C		 
					SI:--QSQQTQQiQQ
 
 	
 .-r'   c                   ddl m t          |          | j        k    sJ fd|D             }t	          |          dk    rt          d          g }d}t          |          D ]\  }}||z
  t          |          r|j        j	        dv r|j        dk    r\|t          j                 }t          | |          } | t          fdt          | j                  D                                } |dz  }|j        dk    r4t          | |          } |                    t!          d                     t          d	          |                    |           | t          |          fS )
a*  Slice x with at most one 1D dask arrays of ints.

    This is a helper function of :meth:`Array.__getitem__`.

    Parameters
    ----------
    x: Array
    index: tuple with as many elements as x.ndim, among which there are
           one or more Array's with dtype=int

    Returns
    -------
    tuple of (sliced x, new index)

    where the new index is the same as the input, but with slice(None)
    replaced to the original slicer where a 1D filter has been applied and
    one less element where a zero-dimensional filter has been applied.
    r   )rG  c                    g | ]E}t          |t          t          f          p&t          |t          j        f          o
|j        d k    FS rt   )r   rX   rw   r2   r&  r   )rG   rD  rG  s     r%   rP   z-slice_with_int_dask_array.<locals>.<listcomp>  s^         	3&& 	CsRZ/00ASX\  r'   r   r   iuc              3  F   K   | ]}|k    rd nt          d          V  dS )r   Nr7  )rG   r   out_axiss     r%   rI   z,slice_with_int_dask_array.<locals>.<genexpr>
  s5      WWAhAAE$KKWWWWWWr'   NzZSlicing with dask.array of ints only permitted when the indexer has zero or one dimensions)r   rG  r4   r   r[   r   rv   r   r   r   r2   newaxis!slice_with_int_dask_array_on_axisrX   rM   r   r-   )	r~   rH   fancy_indexes	out_indexdropped_axis_cntin_axisrD  rG  rV  s	          @@r%   slice_with_int_dask_arrayr]    s   & &%%%%%u::      M
 =A!"GHHHI!%(( " "--c5!! 	"cin&<&<x1}}"*o5ahGGeWWWWqvWWWWWX A%  Q5ahGG  t----)=  
 S!!!!eIr'   c                r   ddl m} ddlm}m}m} ddlm} d|cxk    r| j        k     sn J t          j
        | j        |                                                   rt          d          t          j        t          j         || j        |         | j                            d          }d|d<    ||d          } ||j        |j        | j        |         f|j        | j        	          }t)          t+          | j                            }	| j        f}
|f}|	d
|dz            |
z   |	|dz   d
         z   }|	d
|         |
z   |	|dz   d
         z   } ||j        || |	||
||| j        |         || j        | j                  } ||j        |||
||d| j        |         || j        | j                  }|S )zSlice a ND dask array with a 1D dask arrays of ints along the given
    axis.

    This is a helper function of :func:`slice_with_int_dask_array`.
    r   )r   )rG  	blockwiserH  r   zOSlicing an array with unknown chunks with a dask.array of ints is not supportedr*   r   )r   )metaN)x_sizer   r   r`  T)r   x_chunksr   r   r`  )
dask.arrayr   r   rG  r_  rH  r,   r   r   r2   r   r   rP  r   rollr   _metadasknamer   rX   rM   r]  r   #slice_with_int_dask_array_aggregate)r~   rD  r   r   rG  r_  rH  r   r   x_axesidx_axesoffset_axesp_axesy_axespys                   r%   rX  rX    s7    !     <<<<<<<<<<------qv	x##%% 
!4
 
 	
 WRY||AHTNIIIJJANNFF1IZq)))F UV[18D>"3V\  F
 5==!!FyH'KJdQhJ(*VD1HJJ-??FETE]X%taxzz(::F 		'	wt}gW	 	 	A  		1	$gW	 	 	A Hr'   c           
        ddl mm}m} fd|D             }t	          |          dk    rn|d         j        | j        k    rWt          j        | j                  	                                s_t          j        |d         j                  	                                s.| 
                                } t          d |D                       }n!| j        dk    rt          j        dd            |t          | g|R d	| j        i}d
t!          | |          z   fdt#          t%          j        |                                                    D             }t          j        f|j        z  f}t/          j        ||g          } ||| j                  |fS t          fd|D                       rt3          d          fd|D             }	g }
d}|	D ]}t5          |          rB|j        t6          k    r2|t          t9          |||j        z                       f}|| j        z  }nt;          d          df}|dz  }|
                    |           t?          tA          |
                    }
 |tB          t          t9          | j                            | t          t9          | j                            g|
R d	| j        i}g }tE          ||j#                  D ]k\  }}t5          |          rA|j        t6          k    r1|                    t          j        ft	          |          z             V|                    |           lt          |          |_$        |t          |          fS )a  Slice x with one or more dask arrays of bools

    This is a helper function of `Array.__getitem__`.

    Parameters
    ----------
    x: Array
    index: tuple with as many elements as x.ndim, among which there are
           one or more Array's with dtype=bool

    Returns
    -------
    tuple of (sliced x, new index)

    where the new index is the same as the input, but with slice(None)
    replaced to the original slicer when a filter has been applied.

    Note: The sliced x will have nan chunks on the sliced axes.
    r   )rG  r_  elemwisec                r    g | ]3}t          |          r|j        t          k    rt          d           n|4S rF   r   r   r1   r-   rG   r#   rG  s     r%   rP   z.slice_with_bool_dask_array.<locals>.<listcomp>t  sN        "#u--L#)t2C2Cd  r'   r   c              3  >   K   | ]}|                                 V  d S rF   )r=   rW   s     r%   rI   z-slice_with_bool_dask_array.<locals>.<genexpr>|  s*      33!''))333333r'   zWhen slicing a Dask array of unknown chunks with a boolean mask Dask array, the output array may have a different ordering compared to the equivalent NumPy operation. This will raise an error in a future release of Dask.   r   r   zgetitem-c                     i | ]
\  }}|f|S rK   rK   )rG   r   ro   rg  s      r%   rU   z.slice_with_bool_dask_array.<locals>.<dictcomp>  s#    SSS1ay!SSSr'   dependenciesc              3  n   K   | ]/}t          |          o|j        t          k    o
|j        d k    V  0dS r   )r   r   r1   r   rt  s     r%   rI   z-slice_with_bool_dask_array.<locals>.<genexpr>  sU        KN
3F39#4FQ     r'   zSlicing with dask.array of bools only permitted when the indexer has only one dimension or when it has the same dimension as the sliced arrayc                r    g | ]3}t          |          r|j        t          k    r|nt          d           4S rF   rs  rt  s     r%   rP   z.slice_with_bool_dask_array.<locals>.<listcomp>  sN        #u%%L#)t*;*;t  r'   N)%r   rG  r_  rq  r4   r   r2   r   r   rP  r=   rX   r   r  r   r   r   rv   r   flatten__dask_keys__nannpartitionsr   from_collectionsr   r   r1   rM   r-   r   rw   r   getitem_variadicr   r   _chunks)r~   rH   r_  rq  rZ  ro  r`   r   graphindexesargindsr   r#   newr   r   rG  rg  s                   @@r%   slice_with_bool_dask_arrayr  ^  s   ( ;:::::::::     I
 5zzQ58=AF22x  $$&& 
	rxa/G/G/K/K/M/M 
			A33U33333EEVaZZM5     HWa7%777qw77HQ...SSSS	$,q?P?P2Q2Q(R(RSSS6)am+-/cLLLuUD&!'22I==
    RW     
 "
 
 	
     G
 G	A  c5!! 	ci4&7&7eAq38|44556CKAA;;%CFAs6'??##G
)eAFmm	eAFmm	
 
   g C F%,, ! !
Uc5!! 	!ci4&7&7MM26)c%jj01111MM%    --CKi    r'   c                    | |         S rF   rK   )r~   rH   s     r%   r  r    s    U8Or'   c           	        ddl m}  ||          }t          |d                   dk    rd |D             }t          j        t          j        |d                   d          }d|d<   t          j        |           }t          j        |           }t          ||          D ]g\  }}| |         }	t          j        |	          }
|t          j	        |

                    t          j	        |	                              z   }|
||<   |||<   h||fS )a  Generate blockwise-sorted index pairs for shuffling an array.

    Parameters
    ----------
    index : ndarray
        An array of index positions.
    chunks : tuple
        Chunks from the original dask array

    Returns
    -------
    index2 : ndarray
        Same values as `index`, but each block has been sorted
    index3 : ndarray
        The location of the values of `index` in `index2`

    Examples
    --------
    >>> index = np.array([6, 0, 4, 2, 7, 1, 5, 3])
    >>> chunks = ((4, 4),)
    >>> a, b = make_block_sorted_slices(index, chunks)

    Notice that the first set of 4 items are sorted, and the
    second set of 4 items are sorted.

    >>> a
    array([0, 2, 4, 6, 1, 3, 5, 7])
    >>> b
    array([3, 0, 2, 1, 7, 4, 6, 5])
    r   )slices_from_chunksr   c                    g | ]
}|d          S rt   rK   )rG   slice_s     r%   rP   z,make_block_sorted_slices.<locals>.<listcomp>  s    111&)111r'   )r   r  r4   r2   rd  r   
empty_liker   sortargsortr   )rH   r   r  r   offsetsr{   index3r  r   abcs               r%   make_block_sorted_slicesr    s   > 322222''F
6!9~~11&111gbiq	**A..GGAJ]5!!F]5!!Ffg..  &MGAJJRZrz!}} 5 5666vv6>r'   c                4   ddl m} | j        x}}| j        dk    r	|d         f}t	          ||          \  }}t          j                    5  t          j        d|           | |                             |          |         cddd           S # 1 swxY w Y   dS )a!  A relatively efficient way to shuffle `x` according to `index`.

    Parameters
    ----------
    x : Array
    index : ndarray
        This should be an ndarray the same length as `x` containing
        each index position in ``range(0, len(x))``.

    Returns
    -------
    Array
    r   r   r   ignoreN)	r   r   r   r   r  r   catch_warningssimplefilterrechunk)r~   rH   r   chunks1r#  r{   r  s          r%   shuffle_slicer    s     322222 Ggvzz1:--eW==NFF		 	"	" 2 2h(:;;;y  ))&12 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2s   
6BBBc           	        t          | t                    s| f} | D ]S}|du s|du rt          d|          t          |          st	          |          r|j        st          d|          Tg }g }g }t          t          | |                    }d}t          t          ||                    D ]\  }\  }}	t          |t                    }
|
r.|                    |	          \  }}}|dk     r|dk    rd}t          |||          }|dk     ro|                    |	          \  }}}|dz  }t          ||z
  dz
  |          \  }}||z  }||z  }||z   dz   }t          |||          }|                    |           |                    |	          \  }}}t          ||z
  |          \  }}|s|s|                    d           n|dk    r|dz  }|                    |           |                    |           nYt          |t          t          j        f          rt          |          }n't          |t          j                  st	          |          r|dz  }|dk    rt          d	|            |j        dk    rt%          d
|j         d|	           |j        }|j        t,          k    r2t/          j        |          s||	k    rt%          d| d|	 d|           t	          |          r:|j        t,          k    rt          j        }nt          j        |dk     ||	z   |          }|                    |           |                    |           |||<   ||||fS )a  Reformat the indices for assignment.

    The aim of this is to convert the indices to a standardised form
    so that it is easier to ascertain which chunks are touched by the
    indices.

    This function is intended to be called by `setitem_array`.

    A slice object that is decreasing (i.e. with a negative step), is
    recast as an increasing slice (i.e. with a postive step. For
    example ``slice(7,3,-1)`` would be cast as ``slice(4,8,1)``. This
    is to facilitate finding which blocks are touched by the
    index. The dimensions for which this has occured are returned by
    the function.

    Parameters
    ----------
    indices : numpy-style indices
        Indices to array defining the elements to be assigned.
    shape : sequence of `int`
        The shape of the array.

    Returns
    -------
    parsed_indices : `list`
        The reformated indices that are equivalent to the input
        indices.
    implied_shape : `list`
        The shape implied by the parsed indices. For instance, indices
        of ``(slice(0,2), 5, [4,1,-1])`` will have implied shape
        ``[2,3]``.
    reverse : `list`
        The positions of the dimensions whose indices in the
        parsed_indices output are reversed slices.
    implied_shape_positions: `list`
        The positions of the dimensions whose indices contribute to
        the implied_shape. For instance, indices of ``(slice(0,2), 5,
        [4,1,-1])`` will have implied_shape ``[2,3]`` and
        implied_shape_positions ``[0,2]``.

    Examples
    --------
    >>> parse_assignment_indices((slice(1, -1),), (8,))
    ([slice(1, 7, 1)], [6], [], [0])

    >>> parse_assignment_indices(([1, 2, 6, 5],), (8,))
    ([array([1, 2, 6, 5])], [4], [], [0])

    >>> parse_assignment_indices((3, slice(-1, 2, -1)), (7, 8))
    ([3, slice(3, 8, 1)], [5], [1], [1])

    >>> parse_assignment_indices((slice(-1, 2, -1), 3, [1, 2]), (7, 8, 9))
    ([slice(3, 7, 1), 3, array([1, 2])], [4, 2], [0], [0, 2])

    >>> parse_assignment_indices((slice(0, 5), slice(3, None, 2)), (5, 4))
    ([slice(0, 5, 1), slice(3, 4, 2)], [5, 1], [], [0, 1])

    >>> parse_assignment_indices((slice(0, 5), slice(3, 3, 2)), (5, 4))
    ([slice(0, 5, 1), slice(3, 3, 2)], [5, 0], [], [0])

    TFzBdask does not yet implement assignment to a scalar boolean index: zNdask does not yet implement assignment to a scalar numpy or dask array index: r   r   Nr   zvdask is currently limited to at most one dimension's assignment index being a 1-d array of integers or booleans. Got: zIncorrect shape (z-) of integer indices for dimension with size z:boolean index did not match indexed array along dimension z; dimension is z( but corresponding boolean dimension is )r   rX   r   r   r   r   rw   rN  rv   r   r-   rC  divmodr   r   r2   r7   r&  r   r   r    r   r1   r   r   r~  r   )rC  r   rH   implied_shapeimplied_shape_positionsreverseparsed_indicesn_listsr   r    is_slicer.   r/   r0   divmoddiv_step
index_sizes                     r%   parse_assignment_indicesr    sJ   | gu%% *   D==EUNN%,"', ,  
  	#5e#<#< 	ej 	%8.38 8   M G/'599::NG%c.%&@&@AA `" `"=E4eU++ \	. %d 3 3E4axxDBJJ%t,,Eaxx  %*MM$$7$7!tT
!%$,"2D99S:!x'!+eT400q!!! %d 3 3E4 dUlD11HC 	2s 	2 $$Q''''!881HC$$S)))'..q1111RZ011 *	.JJEErz** &	..@.G.G &	.qLG{{)& $& &   zQ > > >7;> >  
 Jt##
:.. $$&& G!"G G37G G:DG G   "%(( E;$&&!#JJHUQYeDDE  ,,,#**1---!q='3JJJr'   c                    ddl m}m} | j        dk    r| S dt	          |           z   }|df||                                 fi}t          j        ||| g          }| j        }|sd} ||||f| j	                  S )zConcatenate the multidimensional chunks of an array.

    Can be used on chunks with unknown sizes.

    Parameters
    ----------
    x : dask array

    Returns
    -------
    dask array
        The concatenated dask array with one chunk.

    r   )rG  concatenate3r   zconcatenate3-rx  ru   )r   r   )
r   rG  r  r  r   r}  r   r  r   r   )r~   rG  r  rg  r   r  r   s          r%   concatenate_array_chunksr    s     43333333}Xa[[(D
\1??#4#456A+D!1#FFFEWF 5fYag>>>>r'   c           	       6789 t           j        678fd            }t           j        8fd            }t           j        8fd            }t           j        8fd            }ddlm7 |j        }|j        }	t          |	          }
t          ||          \  }}}}d|v r7|	r5t          |	          dk    r"t          d|	 d	t          |                     t          |          |
z
  99dk    r|9d
         }|	}d}9fd|D             }nD9 }|}|	|d
         }d9|	d
|         d|z  k    r"t          d|	 dt          |                     g }g }t          t          |||                    D ]P\  }\  }}}||         8t          8          ru8j        t          k    ret          j        |          s|8j        k    r+|                    d
           |                    |           nt          d| d8j                   |dk    r#|                    t'          d
                     ||k    r+|                    d
           |                    |           t          j        |          r,|                    d
           |                    |           0t          d|	 d	t          |                     |j        }d |D             }d t          ||          D             }t+          | }t-           7|                                                    }i 6| f} t          ||          D ]R\  }}g }g }g }9} d}!d
}"t          t          ||                    D ]\  }#\  8\  }$}%t1          8t2                    }&t1          8t&                    r|%|$z
  }'8j        |%k     r|'|%8j        z
  z  }'8j        |$z
  }(|(dk     r
|(8j        z  }(|(|'k    rd}! n58j        })t'          |(|'|)          }*t;          |'|(z
  |)          \  }+},|,r|+dz  }+8                    |$          }-t;          |-d         |-d         z
  |)          \  }.},|,r|.dz  }.n~|&r| dz  } |$8cxk    r|%k     sn d}! n8|$z
  }*n^8j        t          k    }/ ||#|$|%|/          }*|/r ||#|$|%          }+ ||#|$          }.n
d
}+d
}.|#}"|$|%f}0t          8          s|*j        sd}! nC|                    |*           |&s*|                    |+           |                    |.           | |dd
         z   }1|!s|6|1<   |d
d
         }2|D ]P}|9z   }||"k    r||         8 ||"|	||z            g|0R  |2|<   ,||         }(t'          |(|(||         z             |2|<   Q|D ]T}||         }3|2|                             |3          \  }(}'})|3dz  }3|3|(z
  }(|3|'z
  }'|'dk     rd
}'t'          |(|'d          |2|<   U|
t          |          k    r|2                    dt@                     |t          |2                   }4tC          |4          }4tE           7|4                                                    }5tG          tI          |4j%                  6          6tL          ||5|f6|1<   T|'                                 |'                                 |'                                 |'                                 6S )a  Master function for array assignment.

    This function, that is intended to be called by
    `Array.__setitem__`, creates a new dask that assigns values to
    each block that is touched by the indices, leaving other blocks
    unchanged.

    Each block that overlaps the indices is assigned from the
    approriate part of the assignment value. The dasks of these value
    parts are included in the output dask dictionary, as are the dasks
    of any 1-d dask array indices. This ensures that the dask array
    assignment value and any dask array indices are not computed until
    the `Array.__setitem__` operation is computed.

    The part of the assignment value applies to block is created as a
    "getitem" slice of the full asignment value.

    Parameters
    ----------
    out_name : `str`
        The dask variable output name.
    array : dask array
        The dask array that is being assigned to.
    indices : numpy-style indices
        Indices to array defining the elements to be assigned.
    value : dask array
        The assignment value, i.e. the values which will be assigned
        to elements of array.

    Returns
    -------
    dsk : `dict`
        A dictionary where the keys are new unique tokens for each
        block of the form

            (out_name, dim_index[, dim_index[, ...]])

       and the values are either

            (key,)

        or

            (setitem, key, v_key, block_indices)

        where key is an existing top-level dask key of array.

        The first case occurs when the block represented by key does
        not overlap the indices.

        The second case occurs when the block represented by key does
        overlap the indices. setitem is the chunk assignment function;
        v_key is the dask key of the the part of the assignment value
        that corresponds to the block; and block_indices are the
        assigment indices that apply to the block.

        The dictionary also includes any additional key/value pairs
        needed to define v_key, as well as any any additional
        key/value pairs needed to define dask keys contained in the
        block_indices list as references to dask array indices.

    c                   |r||         }nft                    r't          j        |k    |k     z  |          }||z  }n0t          j        |k    |k     z            d         }|         |z
  }t          |          r`t          |          }                    t          |j                             t           |                                                    }|S )a  The positions of index elements in the range values loc0 and loc1.

        The index is the input assignment index that is defined in the
        namespace of the caller. It is assumed that negative elements
        of an integer array have already been posified.

        The non-hashable dsk is the output dask dictionary that is
        defined in the namespace of the caller.

        Parameters
        ----------
        dim : `int`
           The dimension position of the index that is used as a proxy
           for the non-hashable index to define the LRU cache key.
        loc0 : `int`
            The start index of the block along the dimension.
        loc1 : `int`
            The stop index of the block along the dimension.
        is_bool : `bool`
            Whether or not the index is of boolean data type.

        Returns
        -------
        numpy array or `str`
            If index is a numpy array then a numpy array is
            returned.

            If index is a dask array then the dask of the block index
            is inserted into the output dask dictionary, and its
            unique top-layer key is returned.

        r   )	r   r2   r   r  updater   rf  nextr}  )r   loc0loc1is_boolr   r`   r|  rH   s        r%   block_index_from_1d_indexz0setitem_array.<locals>.block_index_from_1d_index+  s    D  	 d4i AA&& 	  $%-EDL95$GGAIAA
 $%-EDL9::1=Aa4Aa   	1(++AJJtAF||$$$WWQ__..//00Ar'   c                <    t          j        ||                   S )a  Number of True index elements between positions loc0 and loc1.

        The index is the input assignment index that is defined in the
        namespace of the caller.

        Parameters
        ----------
        dim : `int`
           The dimension position of the index that is used as a proxy
           for the non-hashable index to define the LRU cache key.
        loc0 : `int`
            The start index of the block along the dimension.
        loc1 : `int`
            The stop index of the block along the dimension.

        Returns
        -------
        numpy array or dask array
            If index is a numpy array then a numpy array is
            returned.

            If index is dask array then a dask array is returned.

        r2   r[   )r   r  r  rH   s      r%   $block_index_shape_from_1d_bool_indexz;setitem_array.<locals>.block_index_shape_from_1d_bool_indexl  s    4 veDI&'''r'   c                <    t          j        d|                   S )a  Number of True index elements preceeding position loc0.

        The index is the input assignment index that is defined in the
        namespace of the caller.

        Parameters
        ----------
        dim : `int`
           The dimension position of the index that is used as a proxy
           for the non-hashable index to define the LRU cache key.
        loc0 : `int`
            The start index of the block along the dimension.

        Returns
        -------
        numpy array or dask array
            If index is a numpy array then a numpy array is
            returned.

            If index is dask array then a dask array is returned.

        Nr  )r   r  rH   s     r%   n_preceeding_from_1d_bool_indexz6setitem_array.<locals>.n_preceeding_from_1d_bool_index  s    0 veETEl###r'   c                   t                    rt          j        j                  r:t          j        |k    |k     z  dd          }t          |          }|ff|_        nZt          j        |k    |k     z            d         }t          |          }n%t          j        |k    |k     z            d         }|S )a  Value indices for index elements between loc0 and loc1.

        The index is the input assignment index that is defined in the
        namespace of the caller. It is assumed that negative elements
        have already been posified.

        Parameters
        ----------
        dim : `int`
           The dimension position of the index that is used as a proxy
           for the non-hashable index to define the LRU cache key.
        vsize : `int`
            The full size of the dimension of the assignment value.
        loc0 : `int`
            The start index of the block along the dimension.
        loc1 : `int`
            The stop index of the block along the dimension.

        Returns
        -------
        numpy array or dask array
            If index is a numpy array then a numpy array is
            returned.

            If index is dask array then a dask array is returned.

        TFr   )r   r2   r   r    r   r  r  )r   vsizer  r  r   rH   s        r%   value_indices_from_1d_int_indexz6setitem_array.<locals>.value_indices_from_1d_int_index  s    < e$$ 	>x
## 0 Hdem=tUKK,Q//#XK		 Hdem=>>qA,Q// $%-EDL9::1=Ar'   r   )r|  r   z%shape mismatch: value array of shape z4 could not be broadcast to indexing result of shape Nc                &    g | ]}|k    |z
  S rK   rK   )rG   r   r   s     r%   rP   z!setitem_array.<locals>.<listcomp>"  s"    >>>!!v++1v:+++r'   ru   z*could not broadcast input array from shapez into shape z.shape mismatch: value array dimension size of z5 is greater then corresponding boolean index size of c                0    g | ]}t          |d           S )Tr   r   )rG   bdss     r%   rP   z!setitem_array.<locals>.<listcomp>W  s%    GGG}St444GGGr'   c                H    g | ]\  }}d  t          ||          D              S )c                "    g | ]\  }}|||z   fS rK   rK   )rG   rR   r   s      r%   rP   z,setitem_array.<locals>.<listcomp>.<listcomp>Y  s$    888&!S!QW888r'   )r   )rG   startsshapess      r%   rP   z!setitem_array.<locals>.<listcomp>X  sD       FF 	98C$7$7888  r'   TFr   )(	functools	lru_cache	dask.corer|  r   r4   r  r   r   rX   rv   r   r   r   r1   r   r   r    r   r-   r   r   rw   r}  r   r   r/   r.   r0   r  rC  insertr<  r  r  r
   r   rf  setitemcache_clear):rT   r	  rC  valuer  r  r  r  array_shapevalue_shape
value_ndimr  r  r  array_common_shapevalue_common_shapevalue_offsetbase_value_indicesnon_broadcast_dimensionsr   r  r  r   r   cumdimsarray_locationsin_keysin_keyr   block_indicesblock_indices_shapeblock_preceeding_sizeslocal_offsetoverlapsdim_1d_int_indexr   r  r  integer_indexr/   r.   r0   block_indexblock_index_sizerempren_preceedingr  	loc0_loc1out_keyvalue_indicesr    rp   v_keyr`   r|  rH   r   s:                                                         @@@@r%   setitem_arrayr    sF	   @ > > > > > > >@ ( ( ( ( (6 $ $ $ $ $2 3 3 3 3 3j "!!!!!+K+K[!!J @X@ @<G]G%<
 	Mkc+.>.>.B.B/K / /m,,/ /
 
 	
l *,F{{ +6773(>>>>w>>> w*(7 }}%)<<<CC C,1-,@,@C C  
 !! 24KLL   9Aq! 
e$$ 	)<)<z!}} UZ"))$///(//2222 $Q $ $z$ $   66%%eDkk2222!VV%%d+++$++A....Z]] 	%%d+++$++A....* * *''* *   \FGGGGGG !'622  O /O 775..001122G C{H /:: n? n?	&  !#   *3C4K4K*L*L J	< J	<&C&%$&uc22M%'' 8d{:$$D5:--Dd*199UZ'ED==$HEz#E466(.te|T(B(B% # *$)$mmD))$*3q6CF?D$A$A!c & A%L !u++++t++++$HE#dl  +-77T4QQ 	+'K'KT4( ($ $C#B3#M#MLL'+$#'L'*$ $d
I)%00 9I   %HE   ---  <#**+;<<<&--l;;; VABBZ' 	 "CL +111-) 	P 	PAF
A$$$
  
#B#B$k!l2B&C$FO$ $ $a  
 /q1#(8KA8N0N#O#Oa  
  		6 		6A%a(D -a 0 8 8 > >E4AID5LE$;Daxx$UD"55M!G$$   H--- %&&'$Q''WWQ__..//00
 DLL#&&  >G))+++(44666#//111#//111Jr'   c                l   |j         s| S t          t          || j                            D ][\  }\  }}t	          |t
          j                  r9|j        t          k    r)|t          j	        ||k               d                  }|||<   \t
          j
                            |           sCt
          j
                            |          r$|                     t
          j
        j                  } |                                 } 	 || t          |          <   n"# t           $ r}t!          d          |d}~ww xY w| S )a  Chunk function of `setitem_array`.

    Assign v to indices of x.

    Parameters
    ----------
    x : numpy array
        The array to be assigned to.
    v : numpy array
        The values which will be assigned.
    indices : list of `slice`, `int`, or numpy array
        The indices describing the elements of x to be assigned from
        v. One index per axis.

        Note that an individual index can not be a `list`, use a 1-d
        numpy array instead.

        If a 1-d numpy array index contains the non-valid value of the
        size of the corresponding dimension of x, then those index
        elements will be removed prior to the assignment (see
        `block_index_from_1d_index` function).

    Returns
    -------
    numpy array
        A new independent array with assigned elements, unless v is
        empty (i.e. has zero size) in which case then the input array
        is returned and the indices are ignored.

    Examples
    --------
    >>> x = np.arange(8).reshape(2, 4)
    >>> setitem(x, np.array(-99), [np.array([False, True])])
    array([[  0,   1,   2,   3],
           [-99, -99, -99, -99]])
    >>> x
    array([[0, 1, 2, 3],
           [4, 5, 6, 7]])
    >>> setitem(x, np.array([-88, -99]), [slice(None), np.array([1, 3])])
    array([[  0, -88,   2, -99],
           [  4, -88,   6, -99]])
    >>> setitem(x, -x, [slice(None)])
    array([[ 0, -1, -2, -3],
           [-4, -5, -6, -7]])
    >>> x
    array([[0, 1, 2, 3],
           [4, 5, 6, 7]])
    >>> setitem(x, np.array([-88, -99]), [slice(None), np.array([4, 4, 3, 4, 1, 4])])
    array([[  0, -99,   2, -88],
           [  4, -99,   6, -88]])
    >>> value = np.where(x < 0)[0]
    >>> value.size
    0
    >>> y = setitem(x, value, [Ellipsis])
    >>> y is x
    True
    r   zEshape mismatch: value array could not be broadcast to indexing resultN)r    rv   r   r   r   r2   r&  r   r1   r   maisMAviewMaskedArraycopyrX   r   )r~   rp   rC  r   rH   
block_sizees          r%   r  r    s/   t 6  #,C,A,A"B"B  E:eRZ(( 	U[D-@-@"(5:#566q9:EGAJ 5::a== &RUZZ]] &FF25$%% 	
A%..   V
 
	
 Hs   ?D 
D1D,,D1rt   )A
__future__r   r   r  r   r   	itertoolsr   numbersr   r   operatorr   numpyr2   tlzr   r	   r
   r   rf  r   r   r   dask.array.chunkr   	dask.baser   r   dask.highlevelgraphr   
dask.utilsr   r   r-   r   r&   rC   re   r\   rx   r   r   r   r   r   r   r%  r2  ry   r   rA  rE  rN  rK  r]  rX  r  r  r  r  r  r  r  r  rK   r'   r%   <module>r     s8   " " " " " "              $ $ $ $ $ $ $ $           - - - - - - - - - - - - $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 2 2 2 2 2 2 2 2 . . . . . . 2 2 2 2 2 2 2 2dD$> > >$7> 7> 7>tP P Pf& & &R> > >B6" 6" 6"rd d dNT T T$
' 
' 
') ) )Xv v v vr  8 	  	6# # #W W W6  *! ! !HB B BJC
 C
 C
L2 2 2jB B BJY! Y! Y!x  3 3 3l2 2 22}K }K }K@? ? ?<o o odT T T T Tr'   