B
     \-                @   s  d dl mZmZmZ d dlZd dlZd dlZd dlm	Z	m
Z
mZmZmZmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZ d dlmZmZ d dl Z d dl!Z!d dl"m#Z# d dl$m%  m&Z' d dl(Z(dZ)d Z*ej+gZ,i Z-d	d
ddgZ.ddgZ/dddddgZ0dddddddgZ1dddddd d!d"gZ2e/e0 e1 e2 d#d$g Z3e#d%d& Z4e#d'd( Z5G d)d* d*e6Z7G d+d, d,e7Z8G d-d. d.e8Z9G d/d0 d0e6Z:e;ej<j=> ej?g Z@ejAj=> ZBejCj=> ZDd1d2 ejED ZFdS )3    )print_functiondivisionabsolute_importN)iranalysistypesconfigcgutilstyping)mk_unique_varreplace_vars_innerfind_topo_orderdprint_func_irget_global_func_typguardrequireget_definitionfind_callnamefind_build_sequence
find_constis_namedtuple_class)compute_cfg_from_blocks)npydecl	signature)	intrinsicemptyZzerosZonesZfullZrandZrandnZranfZrandom_sampleZsampleZrandomZstandard_normalZ	chisquareZweibullZpowerZ	geometricZexponentialZpoissonZrayleighZnormalZuniformZbetaZbinomialfZgammaZ	lognormalZlaplaceZrandintZ
triangularc             C   s(   ||krt ddd }t||||fS )aV  
    Calculate index value "idx" relative to a size "size" value as
    (idx % size), where "size" is known to be positive.
    Note that we use the mod(%) operation here instead of
    (idx < 0 ? idx + size : idx) because we may have situations
    where idx > size due to the way indices are calculated
    during slice/range analysis.
    z(Argument types for wrap_index must matchc          	   S   s   t |dkst|d }|d }|||}tj|jd}|d||}|||}	|d|	|}
|	||	|	|
||	}|S )N   r      <>)
lenAssertionErrorZsremllvmliter   ZConstanttypeZicmp_signedaddZselect)contextbuildersigargsidxsizeZremzeroZis_negativeZwrapped_remZis_oversizemod r/   3lib/python3.7/site-packages/numba/array_analysis.pycodegenI   s    zwrap_index.<locals>.codegen)
ValueErrorr   )	typingctxr+   r,   r1   r/   r/   r0   
wrap_index<   s    
r4   c             G   sj   t |dkrt|f}t |d dks,tttdd |d dd sNtdd }ttjf| |fS )z
    A function that asserts the inputs are of equivalent size,
    and throws runtime error when they are not. The input is
    a vararg that contains an error message, followed by a set
    of objects of either array, tuple or integer.
    r   r   c             S   s0   t | tjp.t | tjp.t | tjp.t | tjS )N)
isinstancer   ArrayCompatible	BaseTuple	SliceTypeInteger)ar/   r/   r0   <lambda>h   s   zassert_equiv.<locals>.<lambda>Nc       	         s   t |dkstt |d }|jd }|jd d j fdd fdd}x@tdt |d D ]*}||| || ||d  ||d   qnW  tj	d }|S )Nr   r   c                sN   t |tjr,| | }t |jS t |tjrDt | S | gS d S )N)r5   r   r6   Z
make_arrayr	   unpack_tupleshaper7   )r:   atyZary)r(   r'   r/   r0   unpack_shapess   s    z4assert_equiv.<locals>.codegen.<locals>.unpack_shapesc                s   | |}||}t |t |ks(txrt||D ]d\}} tj||} |<\}	}
|	 W d Q R X |
 j tf W d Q R X W d Q R X q4W d S )N)	r"   r#   zipZicmplcZICMP_EQZif_elseZ	call_convZreturn_user_exc)r:   r>   bZbtyZashapesZbshapesmnZm_eq_nZthenZorelse)r(   r'   msgr?   r/   r0   pairwise|   s    


z/assert_equiv.<locals>.codegen.<locals>.pairwise)
r"   r#   r	   r<   r*   Zliteral_valuerangeZget_constant_genericr   NoneType)	r'   r(   r)   r*   tupZtup_typerF   irr/   )r(   r'   rE   r?   r0   r1   m   s    
	*zassert_equiv.<locals>.codegen)r"   r   ZTupler#   allmapr   none)r3   valr1   r/   r/   r0   assert_equivX   s    
 rP   c               @   sz   e Zd ZdZdddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS )EquivSetzPEquivSet keeps track of equivalence relations between
    a set of objects.
    Nr   c             C   s&   |r|ni | _ |r|ni | _|| _dS )zdCreate a new EquivSet object. Optional keyword arguments are for
        internal use only.
        N)
obj_to_ind
ind_to_objnext_ind)selfrR   rS   rT   r/   r/   r0   __init__   s    zEquivSet.__init__c             C   s   t  S )z)Return an empty EquivSet object.
        )rQ   )rU   r/   r/   r0   r      s    zEquivSet.emptyc             C   s    t t| jt| j| jdS )zReturn a new copy.
        )rR   rS   next_id)rQ   copydeepcopyrR   rS   rT   )rU   r/   r/   r0   clone   s    
zEquivSet.clonec             C   s   d | jS )NzEquivSet({}))formatrS   )rU   r/   r/   r0   __repr__   s    zEquivSet.__repr__c             C   s
   | j i kS )z=Return true if the set is empty, or false otherwise.
        )rR   )rU   r/   r/   r0   is_empty   s    zEquivSet.is_emptyc             C   s   | j |dS )zkReturn the internal index (greater or equal to 0) of the given
        object, or -1 if not found.
        r   )rR   get)rU   xr/   r/   r0   _get_ind   s    zEquivSet._get_indc             C   s.   || j kr| j | }n| j}|  jd7  _|S )zyReturn the internal index (greater or equal to 0) of the given
        object, or create a new one if not found.
        r   )rR   rT   )rU   r_   rJ   r/   r/   r0   _get_or_add_ind   s
    
zEquivSet._get_or_add_indc                s   t |dkstt fdd|D }t|}| jkrBg  j|< xt||D ]\}}||kr| j| kr j| | | j|< qN| jkrx, j| D ]}| j|<  j| | qW  j|= qN| j|<  j| | qNW dS )zXBase method that inserts a set of equivalent objects by modifying
        self.
        r   c             3   s   | ]}  |V  qd S )N)ra   ).0r_   )rU   r/   r0   	<genexpr>   s    z#EquivSet._insert.<locals>.<genexpr>N)r"   r#   tupleminrS   r@   appendrR   )rU   objsindsindrJ   objr_   r/   )rU   r0   _insert   s"    





zEquivSet._insertc                sR   fddD }t |  dkr8t fdd|D S tfddD S dS )zfTry to derive if given objects are equivalent, return true
        if so, or false otherwise.
        c                s   g | ]}  |qS r/   )r`   )rb   r_   )rU   r/   r0   
<listcomp>   s    z%EquivSet.is_equiv.<locals>.<listcomp>r   c             3   s   | ]}| kV  qd S )Nr/   )rb   rJ   )ri   r/   r0   rc      s    z$EquivSet.is_equiv.<locals>.<genexpr>c                s   g | ]}| d  kqS )r   r/   )rb   r_   )rg   r/   r0   rl      s    N)maxrL   )rU   rg   rh   r/   )ri   rg   rU   r0   is_equiv   s
    zEquivSet.is_equivc             C   s<   |  |}|dkr8| j| }x|D ]}t|tr"|S q"W dS )zvCheck if obj is equivalent to some int constant, and return
        the constant if found, or None otherwise.
        r   N)r`   rS   r5   int)rU   rj   ri   rg   r_   r/   r/   r0   get_equiv_const   s    



zEquivSet.get_equiv_constc             C   s&   |  |}|dkr t| j| S t S )z.Return the set of equivalent objects.
        r   )r`   setrS   )rU   rj   ri   r/   r/   r0   get_equiv_set   s    
zEquivSet.get_equiv_setc             G   s   |  | dS )zInsert a set of equivalent objects by modifying self. This
        method can be overloaded to transform object type before insertion.
        N)rk   )rU   rg   r/   r/   r0   insert_equiv  s    zEquivSet.insert_equivc       	         s      } j|_x|j D ]}t fdd|D }i }x@t||D ]2\}}||krf|| | qF|dkrF|g||< qFW x&| D ]}t|dkr|| qW qW |S )z Return the intersection of self and the given equiv_set,
        without modifying either of them. The result will also keep
        old equivalence indices unchanged.
        c             3   s   | ]}  |V  qd S )N)r`   )rb   r_   )rU   r/   r0   rc     s    z%EquivSet.intersect.<locals>.<genexpr>r   r   )	r   rT   rS   valuesrd   r@   rf   r"   rk   )	rU   	equiv_setZnew_setrg   rh   rS   rJ   r_   vr/   )rU   r0   	intersect  s    zEquivSet.intersect)NNr   )__name__
__module____qualname____doc__rV   r   rZ   r\   r]   r`   ra   rk   rn   rp   rr   rs   rw   r/   r/   r/   r0   rQ      s   
rQ   c                   s   e Zd ZdZd( fdd	Zdd Zdd	 Zd
d Zdd Z fddZ	 fddZ
dd Z fddZ fddZ fddZdd Zdd Zdd Zd d! Z fd"d#Zd$d% Zd&d' Z  ZS ))ShapeEquivSetad  Just like EquivSet, except that it accepts only numba IR variables
    and constants as objects, guided by their types. Arrays are considered
    equivalent as long as their shapes are equivalent. Scalars are
    equivalent only when they are equal in value. Tuples are equivalent
    when they are of the same size, and their elements are equivalent.
    Nr   c                s:   || _ |r|ni | _|r|ni | _tt| ||| dS )zCreate a new ShapeEquivSet object, where typemap is a dictionary
        that maps variable names to their types, and it will not be modified.
        Optional keyword arguments are for internal use only.
        N)typemapdefs
ind_to_varsuperr|   rV   )rU   r}   r~   r   rR   rS   rW   )	__class__r/   r0   rV   -  s    zShapeEquivSet.__init__c             C   s   t | ji S )z'Return an empty ShapeEquivSet.
        )r|   r}   )rU   r/   r/   r0   r   ?  s    zShapeEquivSet.emptyc             C   s8   t | jt| jt| jt| jt| j| jdS )zReturn a new copy.
        )r~   r   rR   rS   rW   )	r|   r}   rX   r~   r   rY   rR   rS   rT   )rU   r/   r/   r0   rZ   D  s    



zShapeEquivSet.clonec             C   s   d | j| jS )Nz ShapeEquivSet({}, ind_to_var={}))r[   rS   r   )rU   r/   r/   r0   r\   O  s    zShapeEquivSet.__repr__c                s   t |tjst |trt |tr$|n|j j  }t |tjsLt |tjrt |tjr^|j	nt
|}|dkrrdS t fddt|D S n fS nft |tjrt |jtr|jS |jfS n>t |trtfdd|D S t |tr|fS td|dS )zReturn a set of names for the given obj, where array and tuples
        are broken down to their individual shapes or elements. This is
        safe because both Numba array shapes and Python tuples are immutable.
        r   r/   c             3   s   | ]}d   |V  qdS )z{}#{}N)r[   )rb   rJ   )namer/   r0   rc   b  s    z+ShapeEquivSet._get_names.<locals>.<genexpr>c             3   s   | ]}  |d  V  qdS )r   N)
_get_names)rb   r_   )rU   r/   r0   rc   k  s    z!ShapeEquivSet does not support {}N)r5   r   Varstrr   r}   r   r7   r6   ndimr"   rd   rG   Constvaluero   NotImplementedErrorr[   )rU   rj   typr   r/   )r   rU   r0   r   S  s*    



zShapeEquivSet._get_namesc                s   t |dkstfdd|D }dd |D }t |dkr@dS dd |D }|d tfdd	|D stjdkrtd
| dS x6tD ]*  fdd|D }tt	j
| sdS qW dS )zWOverload EquivSet.is_equiv to handle Numba IR variables and
        constants.
        r   c                s   g | ]}  |qS r/   )r   )rb   r_   )rU   r/   r0   rl   w  s    z*ShapeEquivSet.is_equiv.<locals>.<listcomp>c             S   s   g | ]}|d kr|qS )r/   r/   )rb   r_   r/   r/   r0   rl   x  s    Fc             S   s   g | ]}t |qS r/   )r"   )rb   namesr/   r/   r0   rl   {  s    r   c             3   s   | ]} |kV  qd S )Nr/   )rb   r_   )r   r/   r0   rc   }  s    z)ShapeEquivSet.is_equiv.<locals>.<genexpr>z#is_equiv: Dimension mismatch for {}c                s   g | ]}|  qS r/   r/   )rb   obj_name)rJ   r/   r0   rl     s    T)r"   r#   rL   r   DEBUG_ARRAY_OPTprintr[   rG   r   r|   rn   )rU   rg   	obj_namesndimsr   )r   )rJ   r   rU   r0   rn   r  s     
zShapeEquivSet.is_equivc                s.   |  |}t|dkrdS tt| |d S )ztIf the given object is equivalent to a constant scalar,
        return the scalar value, or None otherwise.
        r   Nr   )r   r"   r   r|   rp   )rU   rj   r   )r   r/   r0   rp     s    
zShapeEquivSet.get_equiv_constc             C   sJ   |  |}t|dkrdS | |d }| j|g }|g krF|d S dS )ztIf the given object is equivalent to some defined variable,
        return the variable, or None otherwise.
        r   Nr   )r   r"   r`   r   r^   )rU   rj   r   ri   vsr/   r/   r0   get_equiv_var  s    
zShapeEquivSet.get_equiv_varc                s.   |  |}t|dkrdS tt| |d S )z.Return the set of equivalent objects.
        r   Nr   )r   r"   r   r|   rr   )rU   rj   r   )r   r/   r0   rr     s    
zShapeEquivSet.get_equiv_setc       	         s   g }x&|D ]}|| j kr
|| j |  q
W g }t }xDt|D ]8}x2| j| D ]$}|j|krP|| ||j qPW q@W tt| 	| | j |d  }xt|D ]}| j|= qW || j|< dS )zCOverload EquivSet._insert to manage ind_to_var dictionary.
        r   N)
rR   rf   rq   sortedr   r   r&   r   r|   rk   )	rU   rg   rh   rj   varlistr   rJ   r_   Znew_ind)r   r/   r0   rk     s     



zShapeEquivSet._insertc       	         s  t |dkstfdd|D }dd |D }t |dkr@dS tdd |D g }dd |D }|d tfd	d
|D std|g }xd|D ]\}t|ts|f}xF|D ]>}t|tjr|j	|kr|j	j
kr|d| q|| qW qW xZ|D ]R}|j	}||kr|jkr|gjj< jj|< |gjj<  jd7  _qW x4tD ](  fdd|D }ttj|  q^W dS )zOverload EquivSet.insert_equiv to handle Numba IR variables and
        constants. Input objs are either variable or constant, and at least
        one of them must be variable.
        r   c                s   g | ]}  |qS r/   )r   )rb   r_   )rU   r/   r0   rl     s    z.ShapeEquivSet.insert_equiv.<locals>.<listcomp>c             S   s   g | ]}|d kr|qS )r/   r/   )rb   r_   r/   r/   r0   rl     s    Nc             S   s   g | ]}t |qS r/   )list)rb   r_   r/   r/   r0   rl     s    c             S   s   g | ]}t |qS r/   )r"   )rb   r_   r/   r/   r0   rl     s    r   c             3   s   | ]} |kV  qd S )Nr/   )rb   r_   )r   r/   r0   rc     s    z-ShapeEquivSet.insert_equiv.<locals>.<genexpr>zDimension mismatch for {}c                s   g | ]}|  qS r/   r/   )rb   r   )rJ   r/   r0   rl     s    )r"   r#   sumrL   r[   r5   rd   r   r   r   r~   insertrf   rR   rS   rT   r   rG   r   r|   rs   )	rU   rg   r   r   r   r   rj   varr   )r   )rJ   r   rU   r0   rs     s:    



zShapeEquivSet.insert_equivc             C   s   |  |dkS )zEReturn true if the shape of the given variable is available.
        N)	get_shape)rU   r   r/   r/   r0   	has_shape  s    zShapeEquivSet.has_shapec             C   s   t | j|S )ztReturn a tuple of variables that corresponds to the shape
        of the given array, or None if not found.
        )r   
_get_shape)rU   r   r/   r/   r0   r     s    zShapeEquivSet.get_shapec             C   sb   |  |}t|dk g }x>|D ]6}t|| jk | j| }t|g k ||d  q W t|S )zReturn a tuple of variables that corresponds to the shape
        of the given array, or raise GuardException if not found.
        r/   r   )get_shape_classesr   r   rf   rd   )rU   r   rh   r=   rJ   r   r/   r/   r0   r     s    


zShapeEquivSet._get_shapec                sv   t |tjr|j}| jkr& j| nd}t |tjsRt |tjsRt |tjsRg S  	|}t
 fdd|D }|S )zInstead of the shape tuple, return tuple of int, where
        each int is the corresponding class index of the size object.
        Unknown shapes are given class index -1. Return empty tuple
        if the input name is a scalar variable.
        Nc             3   s   | ]}  |V  qd S )N)r`   )rb   r   )rU   r/   r0   rc     s    z2ShapeEquivSet.get_shape_classes.<locals>.<genexpr>)r5   r   r   r   r}   r   r7   r8   r6   r   rd   )rU   r   r   r   rh   r/   )rU   r0   r     s    
zShapeEquivSet.get_shape_classesc                s   t t| |}i }x|j D ]\}}t|dks8t|d }|| jksNt||jks\t| j| }|j| }|| jks~t||jkstg }	dd |j| D }
x&| j| D ]}|j	|
kr|	
| qW |	||< q W ||_|S )z<Overload the intersect method to handle ind_to_var.
        r   c             S   s   g | ]
}|j qS r/   )r   )rb   r_   r/   r/   r0   rl     s    z+ShapeEquivSet.intersect.<locals>.<listcomp>)r   r|   rw   rS   itemsr"   r#   rR   r   r   rf   )rU   ru   newsetr   rJ   rg   rj   jkr   r   r_   )r   r/   r0   rw     s&    


zShapeEquivSet.intersectc             C   s  t |tjr|j}|| jkr| j|  d7  < || jkr| j| }| j|= | j| | | j| g krp| j|= || jks~t	dd | j| D }||kr|
|}| j| |= | j| g kr| j|= || jkrx| j| D ]}| j|= qW | j|= n
d| j|< dS )a  Increment the internal count of how many times a variable is being
        defined. Most variables in Numba IR are SSA, i.e., defined only once,
        but not all of them. When a variable is being re-defined, it must
        be removed from the equivalence relation.
        r   c             S   s   g | ]
}|j qS r/   )r   )rb   r_   r/   r/   r0   rl   2  s    z(ShapeEquivSet.define.<locals>.<listcomp>N)r5   r   r   r   r~   rR   rS   remover   r#   index)rU   r   rJ   r   r   rj   r/   r/   r0   define  s,    





zShapeEquivSet.definec             C   s,   x&|  D ]\}}|dkr
| | q
W dS )zUnion with the given defs dictionary. This is meant to handle
        branch join-point, where a variable may have been defined in more
        than one branches.
        r   N)r   r   )rU   r~   r   rv   r/   r/   r0   
union_defs@  s    zShapeEquivSet.union_defs)NNNNr   )rx   ry   rz   r{   rV   r   rZ   r\   r   rn   rp   r   rr   rk   rs   r   r   r   r   rw   r   r   __classcell__r/   r/   )r   r0   r|   $  s(    	&"r|   c                   s   e Zd ZdZd fdd	Zdd Zdd	 Zd
d Zdd Zd fdd	Z	d fdd	Z
 fddZ fddZ fddZ  ZS )SymbolicEquivSeta/  Just like ShapeEquivSet, except that it also reasons about variable
    equivalence symbolically by using their arithmetic definitions.
    The goal is to automatically derive the equivalence of array ranges
    (slicing). For instance, a[1:m] and a[0:m-1] shall be considered
    size-equivalence.
    Nr   c
       
         sH   |r|ni | _ |r|ni | _|r$|ni | _tt| ||||||	 dS )zCreate a new SymbolicEquivSet object, where typemap is a dictionary
        that maps variable names to their types, and it will not be modified.
        Optional keyword arguments are for internal use only.
        N)def_byref_by
ext_shapesr   r   rV   )
rU   r}   r   r   r   r~   r   rR   rS   rW   )r   r/   r0   rV   R  s
    

zSymbolicEquivSet.__init__c             C   s
   t | jS )z*Return an empty SymbolicEquivSet.
        )r   r}   )rU   r/   r/   r0   r   i  s    zSymbolicEquivSet.emptyc             C   s   d | j| j| j| j| jS )NzHSymbolicEquivSet({}, ind_to_var={}, def_by={}, ref_by={}, ext_shapes={}))r[   rS   r   r   r   r   )rU   r/   r/   r0   r\   n  s    zSymbolicEquivSet.__repr__c             C   sV   t | jt| jt| jt| jt| jt| jt| j	t| j
| jd	S )zReturn a new copy.
        )r   r   r   r~   r   rR   rS   rW   )r   r}   rX   r   r   r   r~   r   rY   rR   rS   rT   )rU   r/   r/   r0   rZ   s  s    






zSymbolicEquivSet.clonec             C   s   t | j|S )zjRetrieve a definition pair for the given variable,
        or return None if it is not available.
        )r   _get_or_set_rel)rU   r   r/   r/   r0   get_rel  s    zSymbolicEquivSet.get_relc                s  t |tjr|j}tj|ddk |jkr<j| S t|dk dd  fdd t||}|df}t |tj	rn|j
dkrt||jd	\}}|d
krl|dkrltfdd|jD }d|krdS j|g }|| t|dkr| |j|< nZ|j
dkr|j|}	|j|}
|jtjkrT|	|
}n|jtjkr |	|
}n"t |tjrt |jtr|j}t|dk |j|< t |tst |tr|d |ks|d dkrt |tr|\}|jkrg j|< j| | f |}|dkrj| }g }x6|D ].}|jkrB|fddj| D 7 }qBW t|dkrt t!| |S dS )zRetrieve a definition pair for the given variable,
        and if it is not already available, try to look it up
        in the given func_ir, and remember it for future use.
        r   r   Nc             S   sZ   t | t}t |t}|r:|r$| | S |\}}|| | fS n| \}}|rR||| fS d S d S )N)r5   ro   )r_   yZ
x_is_constZ
y_is_constr   offsetr/   r/   r0   plus  s    

z.SymbolicEquivSet._get_or_set_rel.<locals>.plusc                sT   t |tr| | S t | trLt |trL| d |d krL | d |d S d S d S )Nr   r   )r5   ro   rd   )r_   r   )minusr   r/   r0   r     s    
z/SymbolicEquivSet._get_or_set_rel.<locals>.minuscall)r}   r4   znumba.array_analysisc             3   s   | ]} j |jd V  qdS )r   N)rR   r^   r   )rb   r_   )rU   r/   r0   rc     s   z3SymbolicEquivSet._get_or_set_rel.<locals>.<genexpr>r   binopc                s   g | ]\}}|  kr|qS r/   r/   )rb   r_   rJ   )r   r/   r0   rl     s    z4SymbolicEquivSet._get_or_set_rel.<locals>.<listcomp>)"r5   r   r   r   r   r~   r^   r   r   Expropr   r}   rd   r*   r   rf   r"   rk   r   lhsrhsfnoperatorr&   subr   r   ro   r   r`   rS   r   r   )rU   r   func_irexprr   fnamemod_namer   r   r   r   r   ri   rg   rj   )r   )r   r   r   rU   r0   r     sh    










"z SymbolicEquivSet._get_or_set_relc                s   t |tjr|j}n|}tt| | |r| j|ddkrt |t	j
rt| j||}t |trp| ||g t |tjr| |}|| jkr|g| j|< || j|< || jkr| j| | n|g| j|< dS )af  Besides incrementing the definition count of the given variable
        name, it will also retrieve and simplify its definition from func_ir,
        and remember the result for later equivalence comparison. Supported
        operations are:
          1. arithmetic plus and minus with constants
          2. wrap_index (relative to some given size)
        r   r   N)r5   r   r   r   r   r   r   r~   r^   r   Numberr   r   ro   rk   ra   rS   rR   r   rf   )rU   r   r   r   r   r   ri   )r   r/   r0   r     s"    




zSymbolicEquivSet.definec                sv  t  }t  }xF|D ]>}| |}|dkr4|| q||kr|| || qW t|dkrddS t|}tt| | | j| |d  }i }dd }x|D ]}|| j	kr| j	| }t
|tr|\}	}
|||
 |	 |	| jkrx,| j|	 D ]\}}|||
|  | qW || jkrx(| j| D ]\}	}
|||
|	 q2W qW x| D ]}| | q^W dS )zXOverload _insert method to handle ind changes between relative
        objects.
        r   r   Nr   c             S   s"   || kr| | }ng }|| |< |S )Nr/   )dr   rv   r/   r/   r0   
get_or_set  s
    
z,SymbolicEquivSet._insert.<locals>.get_or_set)rq   r`   r&   r"   r   r   r   rk   rS   r   r5   rd   rf   r   rt   )rU   rg   ZindsetZuniqsrj   ri   Zoffset_dictr   r   r   r   rv   rJ   r   )r   r/   r0   rk     s<    





zSymbolicEquivSet._insertc                sV   t |tjst |tjr$|| j|< n.t |tjs4t| j|j }t	t
| || dS )zCOverload set_shape to remember shapes of SetItem IR nodes.
        N)r5   r   StaticSetItemSetItemr   r   r#   r}   r   r   r   	set_shape)rU   rj   r=   r   )r   r/   r0   r   #  s
    zSymbolicEquivSet.set_shapec                sr   t |tjst |tjr0t|| jk | j| S t |tjs@t| j|j	 }t |t
jr^|fS tt| |S dS )zGOverload _get_shape to retrieve the shape of SetItem IR nodes.
        N)r5   r   r   r   r   r   r   r#   r}   r   r   r8   r   r   r   )rU   rj   r   )r   r/   r0   r   -  s    
zSymbolicEquivSet._get_shape)NNNNNNNr   )N)NN)rx   ry   rz   r{   rV   r   r\   rZ   r   r   r   rk   r   r   r   r/   r/   )r   r0   r   I  s     T+
r   c               @   s  e Zd ZdZdd Zdd ZdddZd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Z d=d> Z!d?d@ Z"dAdB Z#dCdD Z$dEdF Z%dGdH Z&dIdJ Z'dKdL Z(dMdN Z)dOdP Z*dQdR Z+dSdT Z,dUdV Z-dWdX Z.dYdZ Z/d[d\ Z0d]d^ Z1d_d` Z2dadb Z3dcdd Z4dedf Z5dgdh Z6didj Z7dkdl Z8dmdn Z9dodp Z:dqdr Z;dsdt Z<dudv Z=dwdx Z>dydz Z?d{d| Z@d}d~ ZAdd ZBdd ZCdd ZDdd ZEdd ZFdd ZGdd ZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNdd ZOdd ZPdd ZQdddZRdddZSdd ZTdd ZUdd ZVdS )ArrayAnalysisa#  Analyzes Numpy array computations for properties such as
    shape/size equivalence, and keeps track of them on a per-block
    basis. The analysis should only be run once because it modifies
    the incoming IR by inserting assertion statements that safeguard
    parfor optimizations.
    c             C   s4   || _ || _|| _|| _i | _i | _i | _i | _d S )N)r'   r   r}   	calltypes
equiv_setsZarray_attr_callsprependspruned_predecessors)rU   r'   r   r}   r   r/   r/   r0   rV   E  s    zArrayAnalysis.__init__c             C   s
   | j | S )zAReturn the equiv_set object of an block given its label.
        )r   )rU   Zblock_labelr/   r/   r0   rr   T  s    zArrayAnalysis.get_equiv_setNc          	   C   s   |dkr| j j}|dkr$t| j}n|}t| j d| tjdkr`tdt| j	  td| j
 t|}t||d}xb|D ]X}|| }|j}g }	d}||}
|| jkr| j| }ng }x|
D ]\}}||krq|| jkr| j|  }||f| jkr*| j||f }x|D ]}| |||| qW |dkr:|}q||}||j qW |dkrb|}|| j|< xb|jD ]X}| ||||\}}x|D ]}|	| qW |	| x|D ]}|	| qW qtW |	|_q|W tjdkr|   t| j d| dS )zrun array shape analysis on the given IR blocks, resulting in
        modified IR and finalized EquivSet for each block.
        Nzbefore array analysisr   zvariable types: zcall types: )cfgzafter array analysis)r   blocksr   r}   r   r   r   r   r   r   r   r   r   scopeZpredecessorsr   r   rZ   r   _analyze_instrw   r   r~   Zbodyrf   dump)rU   r   ru   Zinit_equiv_setr   Z
topo_orderlabelblockr   Znew_bodyZpredsZprunedpqZfrom_setZinstrsinstprepostZinstrr/   r/   r0   runY  s^    












zArrayAnalysis.runc             C   s   t d| j dS )z@dump per-block equivalence sets for debugging purposes.
        zArray Analysis: N)r   r   )rU   r/   r/   r0   r     s    zArrayAnalysis.dumpc             C   s0   || j |j< |g| jj|j< ||| j| d S )N)r}   r   r   Z_definitionsr   )rU   ru   r   r   r   r/   r/   r0   _define  s    zArrayAnalysis._definec       %         s   g }g }t |tjr|j}| j|j }d }	t |tjrH|jdkrHd}	npt |j	tj
r| |||j	}
|
r|
d }	|
d }t|
dkr|
d }||_	n"t |j	tjst |j	tjr|j	}	t |	tjrt |	j	tr|	j t fdd|	j	D }	nt |	j	tr|	f}	nd }	n*t |	tjr8t | j|	j tjr8|	f}	t |tjr|	d ksvt |	tsvt |	tjr||	s| |||j|	\}	}n<t |tjr|	rt |jtjr| ||t||	\}	}|	d krt |tjr|||	 n|||	 ||| j| nt |tjs,t |tjr2t |tjr@|jn|j}t | j!|||j|}
|
shg g fS |
\}}|"|j	}|dkr||| |g fS |d kr&| j|jj }t#t |tj |j}||g}|jj|j	jg}| $|||j||\}	}t|	}||kst%|||	 || g fS |g fS nt |tj&r|j'}t t(| j|}|s2|)|}g }xh|D ]`}t |t*r|| jkrt t(| j|dd}t |tjr|j}|r|+| n
|+| qnW t,t-d	d
 |}t,|.|}t|dkrt/|d }n$t|dkr2t t(| jt/|d }t |tj
r`|j0dkr`d }|j1t2j3krp|j4}|j5}d}n|j1t2j6kr|j5}|j4}d}| j|j7j } | j|j8j }!|d krt | tjrt |!tjst | tj9rt |!tj9r|j |j7|j8f}"| :| ||"}|+tt| |  || j;||f< ttd|  | g| j;||f< nht |tjrt|j	}t |tst |t<r|r|j5n|j4}#|#| j=kr| j=|# +| n|g| j=|#< n.t>|t?krt?t>| }$|$||| j| \}}||fS )Nr   r/   r   r   c             3   s   | ]}t | V  qd S )N)r   r   )rb   r_   )locr/   r0   rc     s    z.ArrayAnalysis._analyze_inst.<locals>.<genexpr>T)Zlhs_onlyc             S   s
   t | tS )N)r5   r   )r_   r/   r/   r0   r;     s    z-ArrayAnalysis._analyze_inst.<locals>.<lambda>r   )@r5   r   Assigntargetr}   r   r   r6   r   r   r   _analyze_exprr"   r   r   rd   r   ro   r9   r   _gen_shape_callUniTupleZdtyper8   r   rs   r   r   r   r   r   	index_varr   _index_to_shaper   r   _broadcast_assert_shapesr#   ZBranchZcondr   rr   r   rf   rq   filter
differencer   r   r   r   eqZtruebrZfalsebrner   r   r7   _make_assert_equivr   boolr   r%   array_analysis_extensions)%rU   r   r   ru   r   r   r   r   r   r=   resultr   r   Ztarget_shapeZvalue_shapeZ
target_typZtarget_ndimshapesr   assertsrD   Zcond_varZcond_defZequivsr~   r   Zvar_defZdefvarsZ	defconstsbrZotherbrZcond_vallhs_typrhs_typr*   Z	pruned_brr   r/   )r   r0   r     s    






(zArrayAnalysis._analyze_instc             C   s>   d |j}yt| |}W n tk
r.   d S X t||||S )Nz_analyze_op_{})r[   r   getattrAttributeErrorr   )rU   r   ru   r   r   r   r/   r/   r0   r   ;  s    zArrayAnalysis._analyze_exprc             C   sN   |j dkr,| |jjr,| |||jgi S |j dkrJ||j}|g fS d S )NTr=   )attr_isarrayr   r    _analyze_op_call_numpy_transposer   )rU   r   ru   r   r=   r/   r/   r0   _analyze_op_getattrC  s    
z!ArrayAnalysis._analyze_op_getattrc             C   s
   |j g fS )N)r   )rU   r   ru   r   r/   r/   r0   _analyze_op_castL  s    zArrayAnalysis._analyze_op_castc             C   sJ   |j }| j|j }t|tjrFtt||jk t|	| |g fS d S )N)
r   r}   r   r5   r   r7   r   r"   countr   )rU   r   ru   r   r   r   r/   r/   r0   _analyze_op_exhaust_iterO  s    z&ArrayAnalysis._analyze_op_exhaust_iterc                s,  j |j }tt|tj j |j } |} |}t|tjrP|f}	nBtt|tj t	j
|\}
}t|dk tfdd|
D }	tt|t|	  kot|kn   g  fddfddtfddt|	||D }ttd	d |D   td
d |D }|fS )zFor indexing like var[index] (either write or read), see if
        the index corresponds to a range/slice shape. Return the shape
        (and prepending instructions) if so, or raise GuardException
        otherwise.
        build_tuplec             3   s   | ]} j |j V  qd S )N)r}   r   )rb   r_   )rU   r/   r0   rc   i  s    z0ArrayAnalysis._index_to_shape.<locals>.<genexpr>c                s  | j }tj| }tj|jd\}}t|dko8|dk tt|jdk |jd }|jd }j|j }j|j }	j|j }
t	
td|}t|	tjrt	d|}t	j|||d  ||| |}|}	t|
tjr|}|}
 |} |}|dkr@t|tr@ ||d r@|d dkr@|S t	
td	|}t	jjtj|||d
}t||	|
j|<  |||  |}t|tst|tr |d |jrt|tr|n|d }t	||}t	
td	|} ||| t	
td|}t	jdt|d
}tt}j !|||fi } ||| t	
td|}t	j"|||gi |} ||| |j|< t	j|||d t	j|||d t	j|||d |S )a  Reason about the size of a slice represented by the "index"
            variable, and return a variable that has this size data, or
            raise GuardException if it cannot reason about it.

            The computation takes care of negative values used in the slice
            with respect to the given dimensional size ("dsize").

            Extra statments required to produce the result are appended
            to parent function's stmts list.
            )r}   slice)Z__builtin__builtinsr   r   r   r-   )r   r   r   
slice_size)r   Zwrapr4   r   )#r   r   r   r   r}   r   r"   r*   r   r   r   r   r5   r   rH   r   rf   r   r   r   rd   rn   r   r   r   r   r   r   ro   Globalr4   r   r'   resolve_function_typer   )r   dsizer   Z	index_defr   r   r   r   Zsize_typr   r   Zzero_varr-   Zlhs_relZrhs_relsize_varsize_valZsize_relZrelZwrap_varZwrap_deffntyr)   r   r   )ru   r   rU   stmtsr/   r0   r   m  sf    





z1ArrayAnalysis._index_to_shape.<locals>.slice_sizec                s2   t | tjr ||S t | tjr&d S td d S )NF)r5   r   r8   r   r   )r   r   r   )r   r/   r0   to_shape  s
    
z/ArrayAnalysis._index_to_shape.<locals>.to_shapec             3   s    | ]\}}} |||V  qd S )Nr/   )rb   r   r,   r   )r  r/   r0   rc     s   c             s   s   | ]}|d kV  qd S )Nr/   )rb   r_   r/   r/   r0   rc     s    c             s   s   | ]}|d kr|V  qd S )Nr/   )rb   r_   r/   r/   r0   rc     s    )r}   r   r   r5   r   r6   r   r8   r7   r   r   rd   r"   r@   rL   )rU   r   ru   r   Zind_varr   Zind_typZ	ind_shapeZ	var_shapeZseq_typsseqr   r=   r/   )ru   r   rU   r   r   r  r0   r   X  s(    

(I	zArrayAnalysis._index_to_shapec             C   s   |  |||j|jS )N)r   r   r   )rU   r   ru   r   r/   r/   r0   _analyze_op_getitem  s    z!ArrayAnalysis._analyze_op_getitemc             C   sh   |j }| j|j }t|tjs2| |||j |jS ||}t	t|j
toV|j
t|k  ||j
 g fS )N)r   r}   r   r5   r   r7   r   r   r   r   r   ro   r"   )rU   r   ru   r   r   r   r=   r/   r/   r0   _analyze_op_static_getitem  s    
z(ArrayAnalysis._analyze_op_static_getitemc             C   s6   t |jtk | |jjs(|jtjkr2|jg fS d S )N)r   r   UNARY_MAP_OPr   r   r   r   r&   )rU   r   ru   r   r/   r/   r0   _analyze_op_unary  s    
zArrayAnalysis._analyze_op_unaryc             C   s(   t |jtk | |||j|j|jgS )N)r   r   BINARY_MAP_OP_analyze_broadcastr   r   r   )rU   r   ru   r   r/   r/   r0   _analyze_op_binop  s    zArrayAnalysis._analyze_op_binopc             C   s(   t |jtk | |||j|j|jgS )N)r   r   INPLACE_BINARY_MAP_OPr  r   r   r   )rU   r   ru   r   r/   r/   r0   _analyze_op_inplace_binop  s    z'ArrayAnalysis._analyze_op_inplace_binopc             C   s   |  |||j| S )N)r  r   Z	list_vars)rU   r   ru   r   r/   r/   r0   _analyze_op_arrayexpr  s    z#ArrayAnalysis._analyze_op_arrayexprc             C   s   t |jg fS )N)rd   r   )rU   r   ru   r   r/   r/   r0   _analyze_op_build_tuple  s    z%ArrayAnalysis._analyze_op_build_tuplec          	   C   sH  ddl m} |j}t| j|}t|tjtjfrHt	|j
rHt|jg fS t|tjtjfrt|j
|r|j}| |||j
|j|t|jS t| j|| jd\}}	t|	tjrt| j|	j tjr|	g|j }d}	n|j}d|	|dd}|tkr| |||j|S yt| |}
W n tk
r,   d S X t|
|||t|jS d S )Nr   )StencilFunc)r}   numpyz_analyze_op_call_{}_{}._)Znumba.stencilr  funcr   r   r5   r   r   ZFreeVarr   r   rd   r*   _analyze_stencilr   dictkwsr   r}   r   r   r   r6   r[   replaceUFUNC_MAP_OPr  r   r   r   )rU   r   ru   r   r  ZcalleeZ
callee_defr*   r   r   r   r/   r/   r0   _analyze_op_call  s8    

zArrayAnalysis._analyze_op_callc             C   s   |  ||||S )N)_analyze_op_call_builtins_len)rU   r   ru   r*   r  r/   r/   r0    _analyze_op_call___builtin___len
  s    z.ArrayAnalysis._analyze_op_call___builtin___lenc             C   s^   t t|dk |d }| j|j }t t|tj |jdkrZ||}|d g |d fS d S )Nr   r   )	r   r"   r}   r   r5   r   r6   r   r   )rU   r   ru   r*   r  r   r   r=   r/   r/   r0   r    s    

z+ArrayAnalysis._analyze_op_call_builtins_lenc             C   s   |j |dd    d S )Nr   )rs   )rU   r   ru   r*   r  r/   r/   r0   2_analyze_op_call_numba_array_analysis_assert_equiv  s    z@ArrayAnalysis._analyze_op_call_numba_array_analysis_assert_equivc             C   sB   d }t |dkr|d }nd|kr*|d }|r6|g fS tdd S )Nr   r=   z'Must specify a shape for array creation)r"   r   )rU   r   ru   r*   r  Z	shape_varr/   r/   r0   _analyze_numpy_create_array  s    
z)ArrayAnalysis._analyze_numpy_create_arrayc             C   s   |  ||||S )N)r  )rU   r   ru   r*   r  r/   r/   r0   _analyze_op_call_numpy_empty(  s    z*ArrayAnalysis._analyze_op_call_numpy_emptyc             C   s   |  ||||S )N)r  )rU   r   ru   r*   r  r/   r/   r0   4_analyze_op_call_numba_unsafe_ndarray_empty_inferred+  s    zBArrayAnalysis._analyze_op_call_numba_unsafe_ndarray_empty_inferredc             C   s   |  ||||S )N)r  )rU   r   ru   r*   r  r/   r/   r0   _analyze_op_call_numpy_zeros/  s    z*ArrayAnalysis._analyze_op_call_numpy_zerosc             C   s   |  ||||S )N)r  )rU   r   ru   r*   r  r/   r/   r0   _analyze_op_call_numpy_ones2  s    z)ArrayAnalysis._analyze_op_call_numpy_onesc             C   sR   t |dkr|d }nd|kr(|d }ntdd|krB|d }n|}||fg fS )Nr   Nz,Expect one argument (or 'N') to eye functionM)r"   r   )rU   r   ru   r*   r  r!  r"  r/   r/   r0   _analyze_op_call_numpy_eye5  s    


z(ArrayAnalysis._analyze_op_call_numpy_eyec             C   s$   t |dkst|d }||fg fS )Nr   )r"   r#   )rU   r   ru   r*   r  r!  r/   r/   r0   _analyze_op_call_numpy_identityC  s    z-ArrayAnalysis._analyze_op_call_numpy_identityc       
      C   s   t |dkst|d }t|tjs(t| j|j }t|tjr|j	dkrd|krj|d }|
|dsjd S ||\}}	|
||	r|fg fS n"|j	dkr||\}||fg fS d S )Nr   r   r   r   )r"   r#   r5   r   r   r}   r   r   r6   r   rn   r   )
rU   r   ru   r*   r  r:   Zatypr   rC   rD   r/   r/   r0   _analyze_op_call_numpy_diagH  s"    

z)ArrayAnalysis._analyze_op_call_numpy_diagc             C   sZ   t |dkst|d }| j|j }t|tjr8dg fS t|tjrV||rV|g fS d S )Nr   )r   )	r"   r#   r}   r   r5   r   r9   r6   r   )rU   r   ru   r*   r  r   r   r/   r/   r0   _analyze_numpy_array_like]  s    
z'ArrayAnalysis._analyze_numpy_array_likec             C   sh   t |dkst|d }| j|j }t|tjs4t|jdkrd||rd|j	dkr\|g |fS |g fS d S )Nr   r   C)
r"   r#   r}   r   r5   r   r6   r   r   Zlayout)rU   r   ru   r*   r  r   r   r/   r/   r0   _analyze_op_call_numpy_ravelh  s    

z*ArrayAnalysis._analyze_op_call_numpy_ravelc             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0   _analyze_op_call_numpy_copyx  s    z)ArrayAnalysis._analyze_op_call_numpy_copyc             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0   !_analyze_op_call_numpy_empty_like{  s    z/ArrayAnalysis._analyze_op_call_numpy_empty_likec             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0   !_analyze_op_call_numpy_zeros_like~  s    z/ArrayAnalysis._analyze_op_call_numpy_zeros_likec             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0    _analyze_op_call_numpy_ones_like  s    z.ArrayAnalysis._analyze_op_call_numpy_ones_likec             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0    _analyze_op_call_numpy_full_like  s    z.ArrayAnalysis._analyze_op_call_numpy_full_likec             G   s
   | j | S )N)r&  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_asfortranarray  s    z3ArrayAnalysis._analyze_op_call_numpy_asfortranarrayc             C   sX   t |}|dkst|dkrD| j|d j }t|tjrD|d g fS t|dd  g fS )Nr   r   )r"   r#   r}   r   r5   r   r7   rd   )rU   r   ru   r*   r  rD   r   r/   r/   r0   _analyze_op_call_numpy_reshape  s    z,ArrayAnalysis._analyze_op_call_numpy_reshapec       	         s   |d } j |j }t|tjs(td||t|dkrNtt	g fS  fdd|dd  D }t|d trt
|d }d |krd S fdd|D }t|g fS )Nr   zInvalid np.transpose argumentr   c                s   g | ]}t t j|qS r/   )r   r   r   )rb   r:   )rU   r/   r0   rl     s    zBArrayAnalysis._analyze_op_call_numpy_transpose.<locals>.<listcomp>c                s   g | ]} | qS r/   r/   )rb   rJ   )r=   r/   r0   rl     s    )r}   r   r5   r   r6   r#   r   r"   rd   reversedr   )	rU   r   ru   r*   r  Zin_arrr   Zaxesretr/   )rU   r=   r0   r     s    
z.ArrayAnalysis._analyze_op_call_numpy_transposec             C   s   t |dkrt|g fS d S )Nr   )r"   rd   )rU   r   ru   r*   r  r/   r/   r0   "_analyze_op_call_numpy_random_rand  s    z0ArrayAnalysis._analyze_op_call_numpy_random_randc             G   s
   | j | S )N)r2  )rU   r*   r/   r/   r0   #_analyze_op_call_numpy_random_randn  s    z1ArrayAnalysis._analyze_op_call_numpy_random_randnc             C   s0   d|kr|d g fS t ||kr,|| g fS d S )Nr,   )r"   )rU   posr   ru   r*   r  r/   r/   r0   "_analyze_op_numpy_random_with_size  s
    z0ArrayAnalysis._analyze_op_numpy_random_with_sizec             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   "_analyze_op_call_numpy_random_ranf  s    z0ArrayAnalysis._analyze_op_call_numpy_random_ranfc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   +_analyze_op_call_numpy_random_random_sample  s    z9ArrayAnalysis._analyze_op_call_numpy_random_random_samplec             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   $_analyze_op_call_numpy_random_sample  s    z2ArrayAnalysis._analyze_op_call_numpy_random_samplec             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   $_analyze_op_call_numpy_random_random  s    z2ArrayAnalysis._analyze_op_call_numpy_random_randomc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   -_analyze_op_call_numpy_random_standard_normal  s    z;ArrayAnalysis._analyze_op_call_numpy_random_standard_normalc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   '_analyze_op_call_numpy_random_chisquare  s    z5ArrayAnalysis._analyze_op_call_numpy_random_chisquarec             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_random_weibull  s    z3ArrayAnalysis._analyze_op_call_numpy_random_weibullc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   #_analyze_op_call_numpy_random_power  s    z1ArrayAnalysis._analyze_op_call_numpy_random_powerc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   '_analyze_op_call_numpy_random_geometric  s    z5ArrayAnalysis._analyze_op_call_numpy_random_geometricc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   )_analyze_op_call_numpy_random_exponential  s    z7ArrayAnalysis._analyze_op_call_numpy_random_exponentialc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_random_poisson  s    z3ArrayAnalysis._analyze_op_call_numpy_random_poissonc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   &_analyze_op_call_numpy_random_rayleigh  s    z4ArrayAnalysis._analyze_op_call_numpy_random_rayleighc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   $_analyze_op_call_numpy_random_normal  s    z2ArrayAnalysis._analyze_op_call_numpy_random_normalc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_random_uniform  s    z3ArrayAnalysis._analyze_op_call_numpy_random_uniformc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   "_analyze_op_call_numpy_random_beta  s    z0ArrayAnalysis._analyze_op_call_numpy_random_betac             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   &_analyze_op_call_numpy_random_binomial  s    z4ArrayAnalysis._analyze_op_call_numpy_random_binomialc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   _analyze_op_call_numpy_random_f  s    z-ArrayAnalysis._analyze_op_call_numpy_random_fc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   #_analyze_op_call_numpy_random_gamma  s    z1ArrayAnalysis._analyze_op_call_numpy_random_gammac             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   '_analyze_op_call_numpy_random_lognormal  s    z5ArrayAnalysis._analyze_op_call_numpy_random_lognormalc             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_random_laplace  s    z3ArrayAnalysis._analyze_op_call_numpy_random_laplacec             G   s   | j d| S )Nr   )r   )r5  )rU   r*   r/   r/   r0   %_analyze_op_call_numpy_random_randint  s    z3ArrayAnalysis._analyze_op_call_numpy_random_randintc             G   s   | j d| S )N   )rK  )r5  )rU   r*   r/   r/   r0   (_analyze_op_call_numpy_random_triangular  s    z6ArrayAnalysis._analyze_op_call_numpy_random_triangularc          	      s"  t |dkst|d j}t| j|d \}}t |}t|dk d}	d|krxt|d trf|d }	qt| j|d }	nt |dkrt| j|d }	tt|	t t|dk  fdd|D }
|	dk rt |
d |	 }	td|	  kot |
d k n   g }g }|dkr|
d } 	|
d }|
d xXtt |D ]H|	krr 	| }|rl|rl|| nd }n|  |
d }q<W || n|xztt |
d D ]f|	kr|  fdd|
D }n0fdd|
D }|| || | |d }|| qW t|t|g fS )	Nr   axisr   r   c                s   g | ]}  |qS r/   )r   )rb   r_   )ru   r/   r0   rl     s    zDArrayAnalysis._analyze_op_call_numpy_concatenate.<locals>.<listcomp>c                s   g | ]}|  qS r/   r/   )rb   r=   )rJ   r/   r0   rl     s    c                s   g | ]}|  qS r/   r/   )rb   r=   )rJ   r/   r0   rl     s    )r"   r#   r   r   r   r   r5   ro   r   rp   poprG   	_sum_sizerf   _call_assert_equivrd   r   )rU   r   ru   r*   r  r   r  r   rD   rM  r   r   	new_shaper=   rC   r,   sizesr/   )ru   rJ   r0   "_analyze_op_call_numpy_concatenate  sP    

$



z0ArrayAnalysis._analyze_op_call_numpy_concatenatec                sD  t |dkst|d j}t| j|d \}}t |}t|dk d}	d|krxt|d trf|d }	qt| j|d }	nt |dkrt| j|d }	tt|	t t|dk  fdd|D }
| 	|| |}|
d }|	dk rt ||	 d }	td|	  ko
t |kn   t
|d|	 |g t
||	d   }t||fS )Nr   rM  r   r   c                s   g | ]}  |qS r/   )r   )rb   r_   )ru   r/   r0   rl   4  s    z>ArrayAnalysis._analyze_op_call_numpy_stack.<locals>.<listcomp>)r"   r#   r   r   r   r   r5   ro   r   rP  r   rd   )rU   r   ru   r*   r  r   r  r   rD   rM  r   r   r=   rQ  r/   )ru   r0   _analyze_op_call_numpy_stack#  s,    

"&z*ArrayAnalysis._analyze_op_call_numpy_stackc       	      C   s   t |dkstt| j|d \}}t |}t|dk | j|d j }tt|tj	 |j
dk rr| ||||S d|d< | ||||S d S )Nr   r   r   rM  )r"   r#   r   r   r   r}   r   r5   r   r6   r   rT  rS  )	rU   r   ru   r*   r  r  r   rD   r   r/   r/   r0   _analyze_op_call_numpy_vstack=  s    
z+ArrayAnalysis._analyze_op_call_numpy_vstackc       	      C   s   t |dkstt| j|d \}}t |}t|dk | j|d j }tt|tj	 |j
dk rld|d< nd|d< | ||||S )Nr   r   r   rM  )r"   r#   r   r   r   r}   r   r5   r   r6   r   rS  )	rU   r   ru   r*   r  r  r   rD   r   r/   r/   r0   _analyze_op_call_numpy_hstackJ  s    

z+ArrayAnalysis._analyze_op_call_numpy_hstackc             C   s   t |dkstt| j|d \}}t |}t|dk | j|d j }tt|tj	 |j
dkrd|d< | ||||}	t|	 |	\}
}tdgt|
 }
|
|fS |j
dkrd|d< | ||||S d|d< | ||||S d S )Nr   r   rM  r   )r"   r#   r   r   r   r}   r   r5   r   r6   r   rT  rd   r   rS  )rU   r   ru   r*   r  r  r   rD   r   r   r=   r   r/   r/   r0   _analyze_op_call_numpy_dstackW  s&    

z+ArrayAnalysis._analyze_op_call_numpy_dstackc             C   s   d S )Nr/   )rU   r   ru   r*   r  r/   r/   r0   _analyze_op_call_numpy_cumsumm  s    z+ArrayAnalysis._analyze_op_call_numpy_cumsumc             C   s   d S )Nr/   )rU   r   ru   r*   r  r/   r/   r0   _analyze_op_call_numpy_cumprodq  s    z,ArrayAnalysis._analyze_op_call_numpy_cumprodc             C   s8   t |}d}|dkr|d }nd|kr.|d }|fg fS )N2   r   num)r"   )rU   r   ru   r*   r  rD   r[  r/   r/   r0   _analyze_op_call_numpy_linspaceu  s    
z-ArrayAnalysis._analyze_op_call_numpy_linspacec                s  t |}|dkst|d j}ttfdd|D  fdd|D }dd |D }ttdd |D  |d d	kr|d	 d	krd S  fd
d|D }	|d d	kr|| |	d d |	d	 d g}
t|	d	 dd |	d	 dd   |
fS |d	 d	kr>|| |	d d |	d	 d g}
t|	d dd |
fS |d dkr|d	 dkr|| |	d d	 |	d	 d g}
|	d d |	d	 d	 f|
fS |d dkrd S )Nr   r   c                s   g | ]}  |jqS r/   )r   r   )rb   r_   )rU   r/   r0   rl     s    z<ArrayAnalysis._analyze_op_call_numpy_dot.<locals>.<listcomp>c                s   g | ]} j |j qS r/   )r}   r   )rb   r_   )rU   r/   r0   rl     s    c             S   s   g | ]
}|j qS r/   )r   )rb   Ztyr/   r/   r0   rl     s    c             s   s   | ]}|d kV  qdS )r   Nr/   )rb   r_   r/   r/   r0   rc     s    z;ArrayAnalysis._analyze_op_call_numpy_dot.<locals>.<genexpr>r   c                s   g | ]}  |qS r/   )r   )rb   r_   )ru   r/   r0   rl     s    r   )r"   r#   r   r   rL   rP  rd   )rU   r   ru   r*   r  rD   r   Ztypsdimsr   r   r/   )ru   rU   r0   _analyze_op_call_numpy_dot~  s0    
 (  z(ArrayAnalysis._analyze_op_call_numpy_dotc             C   s   |j dd}|jj}t|tr&|f}g }	t|dkrFt|t|ksJtx@t||D ]2\}
}| j	|j
 }t|tjrV|
|krV|	| qVW t|	}t|dk | ||||	}||	d }||fS )NZstandard_indexingr/   r   )Zoptionsr^   Z	kernel_ir	arg_namesr5   r   r"   r#   r@   r}   r   r   r6   rf   r   rP  r   )rU   r   ru   Zstencil_funcr   r*   r  Zstd_idx_arrsZkernel_arg_namesZrel_idx_arrsargr   r   rD   r   r=   r/   r/   r0   r    s     
 zArrayAnalysis._analyze_stencilc             C   s"   t t|dk ||d g fS )Nr   r   )r   r"   r   )rU   r   ru   r*   r  r/   r/   r0   !_analyze_op_call_numpy_linalg_inv  s    z/ArrayAnalysis._analyze_op_call_numpy_linalg_invc       
   
      s   t tfdd|}tt|dk dd |D }fdd|D }t|}t|dk y fdd|D }	W n( tk
r   |d || |fS X | ||	|S )zInfer shape equivalence of arguments based on Numpy broadcast rules
        and return shape of output
        https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
        c                s     | jS )N)r   r   )r:   )rU   r/   r0   r;     s    z2ArrayAnalysis._analyze_broadcast.<locals>.<lambda>r   c             S   s   g | ]
}|j qS r/   )r   )rb   r_   r/   r/   r0   rl     s    z4ArrayAnalysis._analyze_broadcast.<locals>.<listcomp>c                s   g | ]} j |j jqS r/   )r}   r   r   )rb   r_   )rU   r/   r0   rl     s    c                s   g | ]}  |qS r/   )r   )rb   r_   )ru   r/   r0   rl     s    )r   r   r   r"   rm   ZGuardExceptionrP  r   )
rU   r   ru   r   r*   Zarrsr   r^  max_dimr   r/   )ru   rU   r0   r    s    z ArrayAnalysis._analyze_broadcastc          
   C   s  g }g }t dd |D }d}	xt|D ]}
g }g }xbt||D ]T\}}|
t|k r@|t|d |
  }||}|dkr|}	q@|| || q@W |g kr|	dkst||	 |d || j|||||d ||d  q(W tt	|t
|g fS )zProduce assert_equiv for sizes in each dimension, taking into account
        of dimension coercion and constant size of 1.
        c             S   s   g | ]}t |qS r/   )r"   )rb   r=   r/   r/   r0   rl     s    z:ArrayAnalysis._broadcast_assert_shapes.<locals>.<listcomp>Nr   1)r   r   )rm   rG   r@   r"   rp   rf   r#   rP  rd   r0  r   )rU   r   ru   r   r   r   r   rQ  rc  Zconst_size_onerJ   rR  Z
size_namesr   r=   r,   Z
const_sizer/   r/   r0   r     s.    



z&ArrayAnalysis._broadcast_assert_shapesc             C   s.   | j |||||d}t|dkr*|j|  |S )N)r   r   )r   r"   rs   )rU   r   r   ru   r*   r   Zinstsr/   r/   r0   rP    s
    
z ArrayAnalysis._call_assert_equivc                s  |d krdd |D }g }g }xRt ||D ]D\}}	d}
x|D ]}||	|r<d}
P q<W |
s*||	 || q*W t|dk rg S dd||}t||}t	|}t
|td|}| j|j< t|g fd	d|D  }tj|}t
|td
|}tjdt|d}tt} j||fi } |||| t
|td|}tjj||g| i |d} ||tj| | j|< tj|||dtj|||dtj|||dgS )Nc             S   s   g | ]
}|j qS r/   )r   )rb   r_   r/   r/   r0   rl     s    z4ArrayAnalysis._make_assert_equiv.<locals>.<listcomp>FTr   zSizes of {} do not match on {}z, rE   c                s   g | ]} j |j qS r/   )r}   r   )rb   r_   )rU   r/   r0   rl     s    assertrP   )r   r1  )r   r   r   )r@   rn   rf   r"   r[   joinr   r   r   ZStringLiteralr   r   r}   r   rd   r7   Z
from_typesr   rP   r   r'   r   r   r   r   rN   r   r   )rU   r   r   ru   Z_argsr   r*   r`  r   r_   seenr   rE   Zmsg_valZmsg_typZmsg_varZargtypsZtup_typZ
assert_varZ
assert_defr   r)   r   r   r/   )rU   r0   r     sD    



z ArrayAnalysis._make_assert_equivc          	   C   sZ  g }t |tjr||}t |tjr4|}d }d }n@tj|d|j}t|jtd	|j
|j}tjtj|}g }	d}
|rt|}||k r||| d  }xvt|D ]h}d}|r|| rt || tjr| j|| j
 }t |tjst |tjr|| }d}nt || tr6t|| |j}n|| }t |tjsPtt|jtd	|j
||j}|t|||j | ||tj| d}|st|jtd	|j
||j}tj||d |j}d}
d | j|< |t|||j | ||tj| |	| qW |
rN|rN|dt|||j | |||| t|	|fS )Nr=   z{}_shapeFTz	{}_size{}r   )r5   r   r   r   r   r   r   r   r   r[   r   r   Z
containersr   Zintpr"   rG   r}   r   r8   ro   r   r#   rf   r   r   Zstatic_getitemr   r   rd   )rU   ru   r   r   r=   outZattr_varZshape_attr_callZshape_attr_typZ	size_varsZuse_attr_varZnshapesrJ   skipr   r   r   getitemr/   r/   r0   r     s`    




zArrayAnalysis._gen_shape_callc             C   s2   | j | }t|tjjo0t|tjj o0|jdkS )Nr   )r}   r5   r   ZnpytypesZArrayZSmartArrayTyper   )rU   Zvarnamer   r/   r/   r0   r   P  s    
zArrayAnalysis._isarrayc             C   s4   d}x*|D ]"}| |}|dkr$dS ||7 }q
W |S )zzReturn the sum of the given list of sizes if they are all equivalent
        to some constant, or None otherwise.
        r   N)rp   )rU   ru   rR  sr,   rD   r/   r/   r0   rO  W  s    

zArrayAnalysis._sum_size)NN)N)N)Wrx   ry   rz   r{   rV   rr   r   r   r   r   r   r   r   r   r   r  r  r  r	  r  r  r  r  r  r  r  r  r  r  r  r   r#  r$  r%  r&  r(  r)  r*  r+  r,  r-  r.  r/  r   r2  r3  r5  r6  r7  r8  r9  r:  r;  r<  r=  r>  r?  r@  rA  rB  rC  rD  rE  rF  rG  rH  rI  rJ  rL  rS  rT  rU  rV  rW  rX  rY  r\  r_  r  rb  r  r   rP  r   r   r   rO  r/   r/   r/   r0   r   <  s   
H 		m	#
	/	

0:r   c             C   s   g | ]
}|j qS r/   )rx   )rb   r   r/   r/   r0   rl   h  s    rl   )GZ
__future__r   r   r   r   Zpytypesr  r   Znumbar   r   r   r	   r
   Znumba.ir_utilsr   r   r   r   r   r   r   r   r   r   r   r   Znumba.analysisr   Znumba.typingr   r   collectionsrX   Znumba.extendingr   Zllvmlite.llvmpy.coreZllvmpyZcorerA   r$   ZUNKNOWN_CLASSZCONST_CLASSZufuncZ	MAP_TYPESr   Zarray_creationZrandom_int_argsZrandom_1arg_sizeZrandom_2arg_sizelastZrandom_3arg_sizelastZrandom_callsr4   rP   objectrQ   r|   r   r   r   ZNumpyRulesUnaryArrayOperatorZ_op_mapkeysr4  r  ZNumpyRulesArrayOperatorr  ZNumpyRulesInplaceArrayOperatorr
  Zsupported_ufuncsr  r/   r/   r/   r0   <module>   sf    8
8   ' t        0