B
     \                @   s  d Z ddlmZmZmZ ddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZmZmZ ddlmZ ddlZddlZddlmZmZmZ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# dd	l$m%Z% dd
l&m'Z'm(Z( ddlm)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZX ddlYmZZZm[Z[m\Z\m]Z] ddl^m_Z_ ddl`maZambZb ddlcmdZd ddlemfZfmgZgmhZhmiZimjZjmkZk ddl,mlZl ddlZddlmZmddlmZndZoe
jpeoddZqdd ZrdZsdd Zteletdd ZuG dd devZwd d! Zxd"d# Zyd$d% Zzd&d' Z{d(d) Z|d*d+ Z}d,d- Z~d.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Zd>d? d@d? exeyexeyeeeeeeeedAZe-dBdC Ze-dDdE Ze-dFdG Ze-dHdI ZedJdKdLgZedGeedIeedEeedCeedEeedCedMZG dNdO dOevZG dPdQ dQejejZdRdS Zeeje< G dTdU dUevZG dVdW dWevZdXdY ZG dZd[ d[evZd\d] Zd^d_ Zd`da Zdbdc Zddde Zdfdg Zdhdi Zdjdk Zdldm Zdndo Zdpdq Zdrds Zdtdu ZddvdwZdxdy Zdzd{ Zd|d} Zd~d Zdd Zeeje< dddZeeje< dd Zee je< dddZdddZdd Zdd Zdd Zdd ZeddddgZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zeeje< dd Zdd Zdd Zeeje< dd ZdddZdddZdd Zeeje< dd Zeeje< dddZdd Zdd Zdd ZdddZeeje< dddZeeje< dddĄZeeje< ddƄ Zeeje< ddȄ Zeeje< ddʄ Zee!je< ddd̄Zeeje< edd΄ Ze'eG ddЄ de(Zdd҄ ZdS )a  
This module transforms data-parallel operations such as Numpy calls into
'Parfor' nodes, which are nested loops that can be parallelized.
It also implements optimizations such as loop fusion, and extends the rest of
compiler analysis and optimizations to support Parfors.
This is similar to ParallelAccelerator package in Julia:
https://github.com/IntelLabs/ParallelAccelerator.jl
'Parallelizing Julia with a Non-invasive DSL', T. Anderson et al., ECOOP'17.
    )print_functiondivisionabsolute_importN)reduce)defaultdictOrderedDict
namedtuple)contextmanager)	irir_utilstypestypingrewritesconfiganalysisprangepndindex)array_analysispostproc	typeinferutilserrors)as_dtype)infer_globalAbstractTemplate)stencilparfor)StencilPass)register_jitable)*mk_unique_var
next_labelmk_allocget_np_ufunc_typmk_range_blockmk_loop_headerget_name_var_tablereplace_varsreplace_vars_inner
visit_varsvisit_vars_innerremove_delsremove_deadcopy_propagateget_block_copiesapply_copy_propagatedprint_func_irfind_topo_orderget_stmt_writesrename_labelsget_call_tablesimplifysimplify_CFGhas_no_side_effectcanonicalize_array_mathadd_offset_to_labelsfind_callnamefind_build_sequenceguardrequireGuardExceptioncompile_to_numba_irget_definitionbuild_definitionsreplace_arg_nodesreplace_returns
is_getitem
is_setitemis_get_setitemindex_var_of_get_setitemset_index_var_of_get_setitemfind_potential_aliases)compute_use_defscompute_live_mapcompute_dead_mapscompute_cfg_from_blocks)CFGraph)npydecl	signature)Function)random_int_argsrandom_1arg_sizerandom_2arg_sizelastrandom_3arg_sizelastrandom_callsassert_equiv)overloadP   F)widthZdrop_whitespacec             C   s*   x$|   D ]}dd t|D  q
W d S )Nc             S   s   g | ]}t |qS  )print).0yrY   rY   +lib/python3.7/site-packages/numba/parfor.py
<listcomp>d   s    z!print_wrapped.<locals>.<listcomp>)
splitlines_txtwrapperZwrap)xlrY   rY   r]   print_wrappedb   s    rc   c               C   s   d S )NrY   rY   rY   rY   r]   init_prangek   s    rd   c              C   s   dd } | S )Nc               S   s   d S )NrY   rY   rY   rY   r]   no_opp   s    z#init_prange_overload.<locals>.no_oprY   )re   rY   rY   r]   init_prange_overloadn   s    rf   c               @   s   e Zd Zdd ZdS )internal_prangec             G   s   t | S )N)range)clsargsrY   rY   r]   __new__v   s    zinternal_prange.__new__N)__name__
__module____qualname__rk   rY   rY   rY   r]   rg   t   s   rg   c             C   s    |j dkrdd }ndd }|S )N   c             S   sR   t j  tt|  t jj| j}x&t j	t| D ]}t
|| | }q8W |S )N)numbaparforrd   min_checkerlentargetsbuiltinsget_type_max_valuedtyperg   min)in_arrvalirY   rY   r]   min_1}   s    
z min_parallel_impl.<locals>.min_1c             S   sN   t j  tt|  t jj| j}x"t 	| j
D ]}t|| | }q4W |S )N)rp   rq   rd   rr   rs   rt   ru   rv   rw   r   shaperx   )ry   rz   r{   rY   rY   r]   r|      s    
)ndim)return_typeargr|   rY   rY   r]   min_parallel_imply   s    

r   c             C   s    |j dkrdd }ndd }|S )Nro   c             S   sR   t j  tt|  t jj| j}x&t j	t| D ]}t
|| | }q8W |S )N)rp   rq   rd   max_checkerrs   rt   ru   get_type_min_valuerw   rg   max)ry   rz   r{   rY   rY   r]   max_1   s    
z max_parallel_impl.<locals>.max_1c             S   sN   t j  tt|  t jj| j}x"t 	| j
D ]}t|| | }q4W |S )N)rp   rq   rd   r   rs   rt   ru   r   rw   r   r}   r   )ry   rz   r{   rY   rY   r]   r      s    
)r~   )r   r   r   rY   rY   r]   max_parallel_impl   s    

r   c             C   s|   t j  tt|  |  }t jj|j	}t j
jd|}x6t jt|D ]"}t j
j||| }t||}qPW |jS )Nr   )rp   rq   rd   argmin_checkerrs   ravelrt   ru   rv   rw   r   
IndexValuerg   rx   index)ry   Ainit_valivalr{   	curr_ivalrY   rY   r]   argmin_parallel_impl   s    
r   c             C   s|   t j  tt|  |  }t jj|j	}t j
jd|}x6t jt|D ]"}t j
j||| }t||}qPW |jS )Nr   )rp   rq   rd   argmax_checkerrs   r   rt   ru   r   rw   r   r   rg   r   r   )ry   r   r   r   r{   r   rY   rY   r]   argmax_parallel_impl   s    
r   c             C   sP   t j  | jd }|jd }d}x(t j|D ]}|| | ||  7 }q0W |S )Nr   )rp   rq   rd   r}   rg   )abrb   msr{   rY   rY   r]   dotvv_parallel_impl   s    


r   c             C   s^   t j  | j}|j\}}t|| j}x0t j|D ] }|| | ||d d f  7 }q6W |S )N)rp   rq   rd   r}   npzerosrw   rg   )r   r   rb   r   ncr{   rY   rY   r]   dotvm_parallel_impl   s    

 r   c       	      C   sx   t j  | j\}}|j}t|| j}xJt j|D ]:}d}x(t|D ]}|| ||f ||  7 }qHW |||< q6W |S )Nr   )	rp   rq   rd   r}   r   emptyrw   rg   rh   )	r   r   r   r   rb   r   r{   r   jrY   rY   r]   dotmv_parallel_impl   s    

r   c             C   sX   t |tjjrTt |tjjrT|j|j  kr4dkr<n ntS |jdkrT|jdkrTtS d S )Nro      )
isinstancer   npytypesArrayr~   r   r   )r   ZatypZbtyprY   rY   r]   dot_parallel_impl   s    r   c                s0   | d |j dkr  fdd}n fdd}|S )Nr   ro   c                s8   t j   }x$t jt| D ]}|| | 7 }q W |S )N)rp   rq   rd   rg   rs   )ry   rz   r{   )zerorY   r]   sum_1   s
    
z sum_parallel_impl.<locals>.sum_1c                s4   t j   }x t | jD ]}|| | 7 }qW |S )N)rp   rq   rd   r   r}   )ry   rz   r{   )r   rY   r]   r      s
    
)r~   )r   r   r   rY   )r   r]   sum_parallel_impl   s
    
r   c                s0   | d |j dkr  fdd}n fdd}|S )Nro   c                s8   t j   }x$t jt| D ]}|| | 9 }q W |S )N)rp   rq   rd   rg   rs   )ry   rz   r{   )onerY   r]   prod_1  s
    
z"prod_parallel_impl.<locals>.prod_1c                s4   t j   }x t | jD ]}|| | 9 }qW |S )N)rp   rq   rd   r   r}   )ry   rz   r{   )r   rY   r]   r     s
    
)r~   )r   r   r   rY   )r   r]   prod_parallel_impl   s
    
r   c                s0   | d |j dkr  fdd}n fdd}|S )Nr   ro   c                s@   t j   }x$t jt| D ]}|| | 7 }q W |t|  S )N)rp   rq   rd   rg   rs   )ry   rz   r{   )r   rY   r]   mean_1  s
    
z"mean_parallel_impl.<locals>.mean_1c                s:   t j   }x t | jD ]}|| | 7 }qW || j S )N)rp   rq   rd   r   r}   size)ry   rz   r{   )r   rY   r]   r      s
    
)r~   )r   r   r   rY   )r   r]   mean_parallel_impl  s
    
r   c             C   s    |j dkrdd }ndd }|S )Nro   c             S   s`   |   }tj  d}x<tjt| D ](}| | | }|t|t| 7 }q(W |t|  S )Nr   )	meanrp   rq   rd   rg   rs   r   realconj)ry   r   ssdr{   rz   rY   rY   r]   var_1+  s    
z var_parallel_impl.<locals>.var_1c             S   sZ   |   }tj  d}x8t| jD ](}| | | }|t|t| 7 }q$W || j	 S )Nr   )
r   rp   rq   rd   r   r}   r   r   r   r   )ry   r   r   r{   rz   rY   rY   r]   r   6  s    
)r~   )r   r   r   rY   rY   r]   var_parallel_impl(  s    


r   c             C   s   dd }|S )Nc             S   s   |   d S )Ng      ?)var)ry   rY   rY   r]   std_1C  s    z std_parallel_impl.<locals>.std_1rY   )r   r   r   rY   rY   r]   std_parallel_implB  s    r   c                s   t | j  fdd} fdd} fdd}tdd |D rJd	d
 }ndd
 }t|dkrb|S t|dkrr|S t|dkr|S t|dkr|S td|d S )Nc                s   t d| d S )Nr   ro   )r   arange)stop)rw   rY   r]   arange_1J  s    z&arange_parallel_impl.<locals>.arange_1c                s   t | |d S )Nro   )r   r   )startr   )rw   rY   r]   arange_2M  s    z&arange_parallel_impl.<locals>.arange_2c                s   t | || S )N)r   r   )r   r   step)rw   rY   r]   arange_3P  s    z&arange_parallel_impl.<locals>.arange_3c             s   s   | ]}t |tjV  qd S )N)r   r   ZComplex)r[   r   rY   rY   r]   	<genexpr>S  s    z'arange_parallel_impl.<locals>.<genexpr>c       
      S   sx   t j  ||  | }t|j}t|j}ttt	||d}t
||}x$t j|D ]}	| |	|  ||	< q\W |S )Nr   )rp   rq   rd   mathceilr   imagintr   rx   r   r   rg   )
r   r   r   rw   Znitems_cnitems_rZnitems_initemsarrr{   rY   rY   r]   arange_4T  s    
z&arange_parallel_impl.<locals>.arange_4c       	      S   sd   t j  t||  | }tt|d}t||}| }x$t j	|D ]}| ||  ||< qHW |S )Nr   )
rp   rq   rd   r   r   r   r   r   r   rg   )	r   r   r   rw   r   r   r   rz   r{   rY   rY   r]   r   _  s    
ro   r         zparallel arange with types {})r   rw   anyrs   
ValueErrorformat)r   rj   r   r   r   r   rY   )rw   r]   arange_parallel_implG  s     


r   c                sP   t | j dd } fdd}t|dkr.|S t|dkr>|S td|d S )Nc             S   s   t | |dS )N2   )r   linspace)r   r   rY   rY   r]   
linspace_2w  s    z*linspace_parallel_impl.<locals>.linspace_2c                s\   t j  t| }|d }||  }| |d< x(t j|D ]}| |||   ||< q<W |S )Nro   r   )rp   rq   rd   r   r   rg   )r   r   Znumr   ZdivZdeltar{   )rw   rY   r]   
linspace_3z  s    
z*linspace_parallel_impl.<locals>.linspace_3r   r   zparallel linspace with types {})r   rw   rs   r   r   )r   rj   r   r   rY   )rw   r]   linspace_parallel_implt  s    

r   c             C   s   t S )N)r   )rr   rY   rY   r]   <lambda>  s    r   c             C   s   t S )N)r   )r   r   rY   rY   r]   r     s    ))argminnumpy)argmaxr   )rx   r   )r   r   )aminr   )amaxr   )sumr   )Zprodr   )r   r   )r   r   )Zstdr   )dotr   )r   r   )r   r   c             C   s   | dkrt dd S )Nr   zDzero-size array to reduction operation maximum which has no identity)r   )arr_sizerY   rY   r]   r     s    r   c             C   s   | dkrt dd S )Nr   zDzero-size array to reduction operation minimum which has no identity)r   )r   rY   rY   r]   rr     s    rr   c             C   s   | dkrt dd S )Nr   z*attempt to get argmin of an empty sequence)r   )r   rY   rY   r]   r     s    r   c             C   s   | dkrt dd S )Nr   z*attempt to get argmax of an empty sequence)r   )r   rY   rY   r]   r     s    r   checker_implnamefunc))r   r   )r   r   )rx   r   )r   r   )r   r   )r   r   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	LoopNestzThe LoopNest class holds information of a single loop including
    the index variable (of a non-negative integer value), and the
    range variable, e.g. range(r) is 0 to r-1 with step size 1.
    c             C   s   || _ || _|| _|| _d S )N)index_variabler   r   r   )selfr   r   r   r   rY   rY   r]   __init__  s    zLoopNest.__init__c             C   s   d | j| j| j| jS )Nz3LoopNest(index_variable = {}, range = ({}, {}, {})))r   r   r   r   r   )r   rY   rY   r]   __repr__  s    zLoopNest.__repr__c             C   sb   g }| | j t| jtjr*| | j t| jtjrD| | j t| jtjr^| | j |S )N)appendr   r   r   r
   Varr   r   )r   all_usesrY   rY   r]   	list_vars  s    zLoopNest.list_varsN)rl   rm   rn   __doc__r   r   r   rY   rY   rY   r]   r     s   r   c                   sL   e Zd ZdZde f fdd	Zdd Zdd Zdd
dZdddZ	  Z
S )Parforr   Fc                s   t t| jd|d t| j| _t|  jd7  _|| _|| _|| _|| _	d | _
|| _t|dksft|g| _|| _|	| _|
| _tjrd}t|| j|| d S )Nrq   )oplocro   z9Parallel for-loop #{} is produced from pattern '{}' at {})superr   r   type
id_counterid
loop_nests
init_block	loop_body	index_varparams	equiv_setrs   AssertionErrorpatternsflagsno_sequential_loweringracesr   DEBUG_ARRAY_OPT_STATSrZ   r   )r   r   r   r   r   r   r   patternr   r   r   fmt)	__class__rY   r]   r     s(    
zParfor.__init__c             C   s,   dt | j t| j t| j t| j S )Nzid=)strr   reprr   r   r   )r   rY   rY   r]   r   	  s    zParfor.__repr__c             C   sv   g }x2| j  D ]$\}}x|jD ]}|| 7 }q W qW x| jD ]}|| 7 }q@W x| jjD ]}|| 7 }q^W |S )zslist variables used (read/written) in this parfor by
        traversing the body and combining block uses.
        )r   itemsbodyr   r   r   )r   r   rb   r   stmtlooprY   rY   r]   r     s    zParfor.list_varsNc             C   s8   |dk	r| j j}|| j _| j |}|dk	r4|| j _|S )zvget the shape classes for a given variable.
        If a typemap is specified then use it for type resolution
        N)r   typemapget_shape_classes)r   r   r  Zsave_typemapZresrY   rY   r]   r    s    
zParfor.get_shape_classesc             C   s   |pt j}td| jdd|d td| j|d x| jD ]}t||d q>W td|d | j	| x6t
| j D ]$\}}td|f |d |	| qzW td| jdd|d d S )	Nzbegin parfor {}   -)filezindex_var = zinit block:z	label %s:zend parfor {})sysstdoutrZ   r   r   centerr   r   r   dumpsortedr   r   )r   r  loopnestoffsetblockrY   rY   r]   r  0  s    
zParfor.dump)N)N)rl   rm   rn   r   setr   r   r   r  r  __classcell__rY   rY   )r   r]   r     s   
r   c             C   sT   |j }t| }|jdd}||| t| | |jd | _|rL||jd< g g fS )z/Recursive array analysis for parfor nodes.
    r   N)func_irwrap_parfor_blocks
equiv_setsgetrununwrap_parfor_blocksr   )rq   r   r  r   r  Zparfor_blocksZbackup_equivsetrY   rY   r]   _analyze_parfor=  s    

r  c               @   s   e Zd ZdZdd Zdd Zedd Zejd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dZdd Zdd  Zd	S )#ParforDiagnosticszHolds parfor diagnostic info, this is accumulated throughout the
    PreParforPass and ParforPass, also in the closure inlining!
    c             C   s>   d | _ t | _d| _tt| _tt| _g | _i | _	d| _
d S )NZ__numba_parfor_gufuncF)r   dictreplaced_fnsinternal_namer   listfusion_infonested_fusion_infofusion_reports
hoist_info	has_setup)r   rY   rY   r]   r   S  s    

zParforDiagnostics.__init__c             C   s\   || _ | j jj| _| j j| _|| _| j| jkr6d| _nd| j| jf | _| 	 | _
d| _d S )NzInternal parallel functionzFunction %s, %sT)r  func_idfunc_qualnamer   r   linefusion_enabledr  purposeget_parforsinitial_parforsr#  )r   r  r'  rY   rY   r]   setup`  s    

zParforDiagnostics.setupc             C   s   | j S )N)
_has_setup)r   rY   rY   r]   r#  o  s    zParforDiagnostics.has_setupc             C   s
   || _ d S )N)r,  )r   staterY   rY   r]   r#  s  s    Nc             C   s   t |  S )N)rs   r)  )r   blocksrY   rY   r]   count_parforsx  s    zParforDiagnostics.count_parforsc             C   s    t |}| || t| d S )N)r  _get_parforsr  )r   rq   parfors_listr.  rY   rY   r]   _get_nested_parfors{  s    z%ParforDiagnostics._get_nested_parforsc             C   sJ   xD|  D ]8\}}x.|jD ]$}t|tr|| | || qW q
W d S )N)r   r  r   r   r   r2  )r   r.  r1  labelblkr  rY   rY   r]   r0    s
    

zParforDiagnostics._get_parforsc             C   s   g }|  | jj| |S )N)r0  r  r.  )r   r1  rY   rY   r]   r)    s    zParforDiagnostics.get_parforsc             C   s  t |}|i krg t fS t }x(| D ]}x|D ]}|| q6W q,W t| }|| }|dkrnt }t }x^ttt| |d D ]<}|	|}	|	dk	r|	||< q|	g kr|| qg ||< qW g }
x"t
| D ]}|
||  qW |
|fS )zf
        compute adjacency list of the fused loops
        and find the roots in of the lists
        Nro   )copydeepcopyr  valuesaddkeysrh   r   unionr  r  r   )r   Z_ar   Zvtxvra   Zpotential_rootsrootsZ	not_rootsrz   rb   rY   rY   r]   compute_graph_info  s.    


$

z$ParforDiagnostics.compute_graph_infoc                s(    fdd  |||dd\}}||fS )z
        Computes the number of fused and serialized loops
        based on a fusion adjacency list `fadj` and a nested
        parfors adjacency list `nadj` for the root, `root`
        c                s`   xV|| D ]J}|d7 }|| g kr4|t | | 7 }q
 | ||||\}}||7 }|}q
W ||fS )Nro   )rs   )fadjnadjrootnfusednserialkZnfns)
count_rootrY   r]   rE    s    z/ParforDiagnostics.get_stats.<locals>.count_rootr   rY   )r   r>  r?  r@  rA  rB  rY   )rE  r]   	get_stats  s    
zParforDiagnostics.get_statsc             C   sF   g }| ||  x.|| D ]"}|| g kr| | || qW |S )zf
        returns a list of nodes reachable in an adjacency list from a
        specified root
        )extendreachable_nodes)r   adjr@  ZfusersrC  rY   rY   r]   rH    s    z!ParforDiagnostics.reachable_nodesc          	   C   s  || d }|j d }td|jjd }| jjj}| | j\}}| | j\}	}
||	g}t	|t
r|d dkr|d d }|j|krtd|jd S g }xJ|D ]B}|rx"|| D ]}|| || qW |rtdt|d S qW xD|j D ]6}x0|jD ]&}|jj|krtd|jjd S qW qW x| jj D ]t}yV|j|}xDt|d ddD ]0}|j| }t	|tsbtd|jjd }P qbW W n tk
r   Y nX q>W |S )zX
        pd_id - the parfors id
        parfors_simple - the simple parfors map
        r   ro   internalr   )r   r   r   r&  r  filenamer=  r   r  r   tupler   sort_pf_by_linerx   r   r7  r  r.  r   rh   r   r   )r   pf_idparfors_simplepfr   r&  rL  r?  nrootsr>  frootsZgraphsZreported_loctmprI  rC  r4  r  idxr{   rY   rY   r]   rN    sD    





z!ParforDiagnostics.sort_pf_by_linero   c       L         s	  j stdjjj}jj}j|kr4d}d}nd||f }d}d}d}d}d}	d}
d}d}d}d}d}|dkr~d}d}ntd	|d
krd}|dkrd}	d}
d}|dkrd}d}d}|dkr|sd S td tt	d  td| 
t	d tt	d  td |rtd
t	d t }xtjdd dD ]}|jd }|jd }|j}t|tr|d dkr|d dkrdtt|d d }|d d }d|df }n2|d dkrd}n|d dkrd}n
dstd }|r t||j||f  |||f||j< q6W  }|r<td!|  tdt	  jjj}ytj|}W n" tk
rx   tj|}Y nX |rPjjj}yt| }W n t k
r   d }Y nX |rHt!d"d# |D }t"t}xH|# D ]<\}}|| d j|kr$||} ||  %t&| qW t!dgd$d# |' D  }!|d|!t(t&|d    }"g }#|#%d% |#%d&|  |#%|"d d'  d(}t!djjj)d }$xt*||$D ]\}%}|+|%d }&|&d k	rd)d*|& }'nd}'|,d%}(t(|(})|&r
|-|"d |"|'}*n|-|"d+ |"|'}*|#%|(|*|)d    qW t.d%|# nt.d, d-/ }+d.d# |+D },t(|,}-|s~|	rt0std/
t	d d0}.t|. nd1}.t|. tt	d  |-d2k	rfd3d4}/|rx6j1D ],}0|0\}1}2}.td5|1|2f  td6|.  qW j2i kr8|	r8td7 |/j2d8d9 |	rj3rLd:}3nd;}3td<-|3|-d*d=d# |,D  tt	d  td |
rڈj4i krtd>
t	d td? d@}4dA}5|/j4|4|5 tt	d  td 5j2\ }65j4\}7t( t(krt( }8}9nt(}8 }9x"t6t(|9|8D ]}:|9%g  q6W t7 };|7r~x&|7D ]}<|< g kr\|;8|< q\W |6|;A }=i }>x(|6D ] }:$|:|}dB|: f|>|< qW i }?x(|;D ] }:$|:|}dC|:f|?|< qW |>9 }@|@:|?  fdDdE}A fdFdG}B|rBt.dH
t	d |A|@ t.t	d  |rlt.dI
t	d |B|@ t.t	d  td tt	d  td |s|rtdJ
dKd |rd}Ct.dL xj;# D ]\}D}E|E+dMg }Fx|FD ]}Gt|Gj<t=j>ry|Gj<j?}H|HdNkrdO}.|Gj}t|.||Df  ytj|j}W n$ tk
rX   tj|j}Y nX t@A|}|r|j)rtdP||j)dk rdn|j)d  ,   tdQ d}CW n tBtCfk
r   Y nX qW qW |CstdR |	rt.d t.dS d}Ij;	rxj;# D ]\}D}E|E+dMd }J|E+dTd }K|J	sJ|K	sJt.dU|D  	qt.dV|D  |J	rvt.dW dXd# |JD  d}I|K	rt.dY dZd# |KD  d}I	qW |I	std[ td\ ntd]-|| d S )^Nzself.setup has not been calledzInternal parallel functions rJ  z Function %s, %s userF)ro   r   r   r   Tz1Report level unknown, should be one of 1, 2, 3, 4)r   r   r   r   r   z
 =z% Parallel Accelerator Optimizing: %s  zLooking for parallel loopsr  c             S   s   | j jS )N)r   r&  )ra   rY   rY   r]   r   H  s    z(ParforDiagnostics.dump.<locals>.<lambda>)keyr   r   ro   .r   z%s %sz(internal parallel version)zuser defined pranger   zinternal pndindexz5Parallel for-loop #%s: is produced from %s:
    %s
 
z
Found %s parallel loops.c             S   s   g | ]}t |qS rY   )rs   )r[   ra   rY   rY   r]   r^   x  s    z*ParforDiagnostics.dump.<locals>.<listcomp>c             S   s   g | ]}t |qS rY   )rs   )r[   ra   rY   rY   r]   r^     s    
zParallel loop listing for %sz	|loop #IDz{0:{1}}| {2}#z,  zNo source availablez+--c             S   s   g | ]
}|j qS rY   )r   )r[   ra   rY   rY   r]   r^     s    z Fusing loops zPAttempting fusion of parallel loops (combines loops with similar properties)...
z+Performing sequential lowering of loops...
rK  c                s8   t   fdd}| \}|| d S )Nc                sJ    fdd x2|D ]*}t d|f   |d t d qW d S )Nc                sP   xJ| | D ]>}t  | d d|f   | | g kr
| ||d  q
W d S )Nr]  z%s%s %sro   )rc   )rI  r@  depthrC  )facnode_msgprint_gswordrY   r]   ra    s    zYParforDiagnostics.dump.<locals>.dump_graph_indented.<locals>.print_graph.<locals>.print_gz%s%s %sro   rX  )rc   )rI  r<  r   )r_  rb   r`  root_msgrb  )ra  r]   print_graph  s
    
zHParforDiagnostics.dump.<locals>.dump_graph_indented.<locals>.print_graph)rs   r=  )r   rc  r`  rd  r<  )r   rb  )r_  rb   r`  rc  r]   dump_graph_indented  s    
z3ParforDiagnostics.dump.<locals>.dump_graph_indentedz#  Trying to fuse loops #%s and #%s:z    %sz
 
Fused loop summary:
z&has the following loops fused into it:z(fused)z4Following the attempted fusion of parallel for-loopszWith fusion disabledzL
{} there are {} parallel for-loop(s) (originating from loops labelled: {}).c             S   s   g | ]}d | qS )z#%srY   )r[   ra   rY   rY   r]   r^     s    z Optimising loop nests zNAttempting loop nest rewrites (optimising for the largest parallel loops)...
 zis a parallel loopz--> rewritten as a serial loopfusenestc       
         s   t   fdd} fdd}d}g }xft|  D ]V\}}|\}}}	|dkrr||kr|d||	d|}q>|dkr||||}q>ds>tq>W d S )	Nc                sN    fdd || g krJt d|   | ||d td |d }|S )Nc          	      s   t  | d d|df   x|| D ]}|| g krg }| |d  d d|df   | | g kr|kr| |}x0|D ](}| |d  d d|df   qW | t d| q(| |||d  q(W d S )Nr]  z%s%s %sz
(parallel)ro   r[  )rc   r   rH  join)fadj_nadj_nrootr^  rC  msgfusedr{   )r_  ra  reportedr   rb  rY   r]   ra    s    $
(
zVParforDiagnostics.dump.<locals>.print_unoptimised.<locals>.print_nest.<locals>.print_gzParallel region %s:r   r[  ro   )rc   rZ   )ri  rj  therootrn  	region_id)r_  r   rb  )ra  rn  r]   
print_nest  s    zEParforDiagnostics.dump.<locals>.print_unoptimised.<locals>.print_nestc                s   g }t d|  | | d d|df   || g krzt||}x,|D ]$}| | d d|df   qRW |d }t d| td |S )NzParallel region %s:r]  z%s%s %sz
(parallel)ro   r[  )rc   r   r  rH  rh  rZ   )tyrO  rI  r^  rp  rl  rm  rC  )r_  r   rb  rY   r]   
print_fuse*  s     
$zEParforDiagnostics.dump.<locals>.print_unoptimised.<locals>.print_fuser   rf  frg  )rs   r  r   r   )
linesrq  rs  rp  rn  r&  infoopt_tyrO  rI  )r>  r?  r   rb  )r_  r]   print_unoptimised  s    
z1ParforDiagnostics.dump.<locals>.print_unoptimisedc                s0  t  t  fdd} fdd}d}g }xft|  D ]V\}}|\}}}	|dkr|||kr|d||	d|}qH|dkr||||}qHdsHtqHW r$xt D ]h\}
}d	}|d
 }|d }|d }|dkr|d7 }t||
||||f  q|d7 }t||
||f  qW ntd d S )Nc                st    fdd || g krpt d  t d|df  |ddd<  | ||d td	 d S )
Nc                s   x|| D ]} | d d|df  }|| g krg }| | g kr||kr|t | |}|d7 }|ddd |D 7 }|d7 }| t|  d	  t|7  < nt|d  | |||d
   d  d
7  < q
W d S )Nr]  z%s%s %sz(serialz, fused with loop(s): z, c             S   s   g | ]}t |qS rY   )r   )r[   ra   rY   rY   r]   r^   U  s    zhParforDiagnostics.dump.<locals>.print_optimised.<locals>.print_nest.<locals>.print_g.<locals>.<listcomp>)rm  ro   
serialized)r  rH  rh  r   rc   rs   )ri  rj  rk  r^  rC  rl  rm  )r_  ra  rp  rn  r   summaryrb  rY   r]   ra  M  s    
zTParforDiagnostics.dump.<locals>.print_optimised.<locals>.print_nest.<locals>.print_gzParallel region %s:z%s%s %sz
(parallel)r   )r@  rm  rz  ro   r[  )rc   rZ   )ri  rj  ro  rn  rp  )r_  r   r{  rb  )ra  rp  rn  r]   rq  L  s    zCParforDiagnostics.dump.<locals>.print_optimised.<locals>.print_nestc                s   t d|   | d d|df  }g }|| g krft||}|d7 }|ddd |D 7 }|t|d	d
|< |d7 }t | td |d }|S )NzParallel region %s:r]  z%s%s %sz	(parallelz, fused with loop(s): z, c             S   s   g | ]}t |qS rY   )r   )r[   ra   rY   rY   r]   r^   o  s    zWParforDiagnostics.dump.<locals>.print_optimised.<locals>.print_fuse.<locals>.<listcomp>r   )r@  rm  rz  ry  r[  ro   )rc   r  rH  rh  rs   rZ   )rr  rO  rI  r^  rp  rl  rm  )r_  r   r{  rb  rY   r]   rs  h  s    zCParforDiagnostics.dump.<locals>.print_optimised.<locals>.print_fuser   rf  rt  rg  z5
 
Parallel region %s (loop #%s) had %s loop(s) fusedr@  rm  rz  zE and %s loop(s) serialized as part of the larger parallel loop (#%s).rZ  z&Parallel structure is already optimal.)rs   r  r  r   r   rc   )ru  rq  rs  rp  rn  r&  rv  rw  rO  rI  rC  r;  rl  r@  rm  rz  )r>  r?  r   rb  )r_  r{  r]   print_optimisedD  s4    

z/ParforDiagnostics.dump.<locals>.print_optimisedz Before Optimisation z After Optimisation zLoop invariant code motionrW   zAllocation hoisting:hoistedr   zThe memory allocation derived from the instruction at %s is hoisted out of the parallel loop labelled #%s (it will be performed before the loop is executed and reused inside the loop):z   Allocation:: z0    - numpy.empty() is used for the allocation.
zNo allocation hoisting foundzInstruction hoisting:not_hoistedzloop #%s has nothing to hoist.z	loop #%s:z  Has the following hoisted:c             S   s   g | ]}t d | qS )z    %s)rZ   )r[   r\   rY   rY   r]   r^     s    z   Failed to hoist the following:c             S   s    g | ]\}}t d ||f qS )z
    %s: %s)rZ   )r[   ra   r\   rY   rY   r]   r^     s    zNo instruction hoisting foundzP--------------------------------------------------------------------------------z+Function %s, %s, has no parallel for-loops.)Dr#  RuntimeErrorr  r$  r%  r   r  r   rc   
_termwidthr  r  r  r*  r   r   rM  rh  reversedr  r   r   r/  rL  ospathrelpathabspathr   inspectZ	getsourcer_   OSErrorr   r   r   rN  r   r   r7  rs   r&  	enumerater  stripr   rZ   r)  sequential_parfor_loweringr!  r  r'  r   r=  rh   r  r8  r5  updater"  valuer
   Exprattr	linecachegetlinesKeyErrorAttributeError)Lr   levelr   r&  Zpurpose_strr(  Zprint_loop_searchZprint_source_listingZprint_fusion_searchZprint_fusion_summaryZprint_loopnest_rewriteZprint_pre_optimisedZprint_post_optimisedZprint_allocation_hoistZprint_instruction_hoistZprint_internalrP  rQ  Z	r_patternr   r   Zreplfnr   countrL  r  	func_nameru  Z	src_widthZmap_line_to_pfrC  r;  Z
match_lineZmax_pf_per_linerX   newlinesZlstartZnoZpf_idsZpfstrstrippedZsrclenrb   Zparfors
parfor_ids	n_parforsrl  re  reportl1l2after_fusionrc  r`  rS  Z_nrootsZlimrT  ra   rR  r   Z	all_rootsZfroots_linesZnroots_linesZ	all_linesrx  r|  foundrO  datar  instr  Zhoist_info_printedr}  r~  rY   )r>  r?  r   rb  r]   r    s   

















6T


*

zParforDiagnostics.dumpc             C   s   d}|t | j7 }|S )NzParforDiagnostics:
)r   r  )r   r   rY   rY   r]   __str__  s    zParforDiagnostics.__str__c             C   s   d}|S )Nr  rY   )r   r   rY   rY   r]   r     s    zParforDiagnostics.__repr__)N)ro   )rl   rm   rn   r   r   r+  propertyr#  setterr/  r2  r0  r)  r=  rF  rH  rN  r  r  r   rY   rY   rY   r]   r  O  s&   
(:
   Zr  c               @   s,   e Zd ZdZi fddZdd Zdd ZdS )	PreParforPasszwPreprocessing for the Parfor pass. It mostly inlines parallel
    implementations of numpy functions if available.
    c             C   s(   || _ || _|| _|| _|| _|| _d S )N)r  r  	calltypes	typingctxoptionsswapped)r   r  r  r  r  r  r  rY   rY   r]   r     s    zPreParforPass.__init__c             C   s@   t | j| j| j| j | jjr,| | jj t	| jj| j_dS )z(Run pre-parfor processing pass.
        N)
r6   r  r  r  r  r  r   _replace_parallel_functionsr.  r4   )r   rY   rY   r]   r    s
    
zPreParforPass.runc          	      s  j ddlm t| xr \} x~t jD ]n\}t|t	j
rB|j}j|j |jtt	jrjdkr fdd}t|rP qBtt	jrBjdkrBjdkrBjjj }t|tjjrB|j} j}|j}	t	|td|	}
tjtj|
j< t	d	t|	}t	
||
|	}t	|td
|	}tj |j|j< t!|}|dkrxd}t	j"|
||	}t	
|||	}t	|td|	}t#tj}t$j%|}|&j'j|j fi  tj%|j|j< t	j"|
d|	}t	
|||	}t	|td|	}tj(|j|j< t	j)||gd|	}t	
|||	}t*j|j j|j j+|< ||_ j,d|  j,d|  j,d|  j,d| P qBW q"W dS )z
        Replace functions with their parallel implementation in
        replace_functions_map if available.
        The implementation code is inlined to enable more optimization.
        r   )inline_closure_callcallc                 sF  t jj} tj}t|d }t|d k tfddjD }y|f| }W n   d }Y nX t|d k t		jj
jj}t|d< t|d< t|d< t|d }|d k	r|j||j< j| |j|jj
}t|dd}xN|D ]F}	x@|	 D ]4\}
}|d d	kr||j|  j jg|
< P qW qW d
S )Nc             3   s   | ]} j |j V  qd S )N)r  r   )r[   ra   )r   rY   r]   r     s    zRPreParforPass._replace_parallel_functions.<locals>.replace_func.<locals>.<genexpr>rp   r   r   F)Ztopological_orderingr   rg   T)r>   r  r   r8   replace_functions_mapr  r;   rM  rj   r5  r$  __globals__rp   r   r   replace_functions_checkers_mapr   r  r  r  r2   r   rl   r  r   )Zfunc_defcallnameZ	repl_funcZtypsnew_funcgZcheck
new_blocks
call_tabler  rC  r;  )r  exprr{   r  lhs_typr   r  	work_listrY   r]   replace_func  s8    

z?PreParforPass._replace_parallel_functions.<locals>.replace_funcgetattrrw   z	$np_g_varr   z$np_typ_varboolZbool_z$dtype_attr_varz
$dtype_varrY   N)-r  numba.inline_closurecallr  r  r   popr  r  r   r
   Assigntargetr  r   r  r  r   r:   r  r   r   r   rw   scoper   r   r   miscModuler   Global	functionsZNumberClassr   r  find_templaterp   rO   get_call_typer  ZDTyper  rN   r  insert)r   r.  r3  instrlhsr  typrw   r  r   g_np_varg_npg_np_assignZtyp_varZ	dtype_strZnp_typ_getattrZtyp_var_assignZdtype_attr_varZtempZtfuncZdtype_attr_getattrZdtype_attr_assignZ	dtype_varZdtype_getattrZdtype_assignrY   )r  r  r{   r  r  r   r  r  r]   r    sf    
"


z)PreParforPass._replace_parallel_functionsN)rl   rm   rn   r   r   r  r  rY   rY   rY   r]   r    s   
r  c             C   s(   x"t jjjjD ]}|j| kr|S qW d S )N)rp   r   Z	templatesZbuiltin_registryr  rY  )r   ZftrY   rY   r]   r  s  s    
r  c               @   s   e Zd ZdZe fddZdd Zdd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd 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d9d%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d$S ):
ParforPasszParforPass class is responsible for converting Numpy
    calls in Numba intermediate representation to Parfors, which
    will lower into either sequential or parallel loops during lowering
    stage.
    c	       	      C   sn   || _ || _|| _|| _|| _|| _|| _|j| _|j	| _	|j
| _
t||||| _t|j t_|| _d S )N)r  r  r  r  r   r  diagnosticsr  swapped_fnsr  r   r   ArrayAnalysisr   r.  r9  r   
_max_labelr   )	r   r  r  r  r   r  r  r   r  rY   rY   r]   r     s    
zParforPass.__init__c             C   s  t | jj | j| jj | jjrJt| j| j| j	| j| j
| j}|  | jjr`| | jj | jjrv| | jj | jjr| | jj | jjr| | jj | j| j| jj t| jd t| jj t| j| j| j	 t| j| j| j	 | jjrt| jj| j_t | j_| j| jj t| j| jj| jdd t| jd | | j| jj t| j| jj| j t| jd | | j| jj t| jd t| j| j| j	 t | jji i  t| j| j| j	 t| jd t!j"dkrt#d	t$| j%  t#d
| j	 t&'| j}|  | jj(r8t)| jj*| j+| j t,rVt-| j
| j| j| j	 npt.| jj| jj| j/}t!j0r| jj1j2}t3|}|dkr| jjrdnd}t#d4|||| nt#d4| dS )zgrun parfor conversion pass: replace Numpy calls
        with Parfors when possible and optimize the IR.zafter parfor passF)up_directionzafter maximize fusion downzafter maximize fusion upzafter fusionzafter optimizationro   zvariable types: zcall types: r   zAfter fusionzWith fusion disabledz0{}, function {} has {} parallel for-loop(s) #{}.zFunction {} has no Parfor.N)5r)   r  r.  r   r  r  stencilr   r  r  r  r   setitem_convert_setitemr   _convert_numpy	reduction_convert_reducer   _convert_loopr  r+  Zfusionr.   simplify_parfor_body_CFGr3   r?   Z_definitionsr  r  maximize_fusionfuse_parforspush_call_varsr   DEBUG_ARRAY_OPTrZ   r  r   r   PostProcessorZis_generatorfix_generator_typesgenerator_infor   r  lower_parfor_sequentialget_parfor_paramsr   r   r$  r%  rs   r   )r   Zstencil_pass	post_procr  r   r  r  rY   rY   r]   r    sr    




zParforPass.runc             C   s   t |}g }x|D ]}|| }g }| j|}x|jD ]}t|tjr|j}	|j}
| 	|
j
rt| j|	r| ||
|	}t|tr|\}}|| n&t|	tjr|	jdkr| ||
|	|}||
j
 || q6W ||_qW dS )zi
        Convert supported Numpy functions, as well as arrayexpr nodes, to
        parfor nodes.
        	arrayexprN)r/   r   get_equiv_setr  r   r
   r  r  r  _is_C_orderr   r:   _is_supported_npycall_numpy_to_parforrM  rG  r  r   _arrayexpr_to_parforr   )r   r.  
topo_order
avail_varsr3  r  new_bodyr   r  r  r  Z	pre_stmtsrY   rY   r]   r    s,    

zParforPass._convert_numpyc             C   s   t |}x|D ]}|| }g }| j|}xt|jD ]j}d}t|tjr|j}	|j}
|j	}t
t| j|}|dksv|dkrt
| j||
|j|	}|r|}|| q2W ||_qW dS )zB
        Find reduce() calls and convert them to parfors.
        N)r   ru   )r   
_functools)r/   r   r  r  r   r
   r  r   r  r  r:   r8   r  _reduce_to_parforrj   r   )r   r.  r  r3  r  r  r   r  rq   r   r  r  r  rY   rY   r]   r    s*    



zParforPass._convert_reducec          
   C   s  t |}g }x|D ]}|| }g }| j|}xl|jD ]`}t|tjs\t|tjr|j}	|j	}
t|tjrz|j
n|j}|j}| j|
j }| j|j }| j|j }t|tjjrt|tjjrjt|jtjrj|j|jkrjt|tjr
| ||	|
||}n^t|tjjrtt| j|j}t|tjr|jdkr|j
j|jkr| ||	|
||j}n*||}|d kr| j||	|
|||d}|| q<W ||_qW d S )Ngetitem)r}   )r/   r   r  r  r   r
   StaticSetItemSetItemr   r  r   r   r  r  r   r   r   r   rw   Booleanr~   Number_setitem_to_parforr:   r>   r  r  r   	get_shaper   )r   r.  r  r  r3  r  r  r   r  r   r  r   r  Z
target_typ	index_typ	value_typZval_defr}   rY   rY   r]   r  &  sH    

zParforPass._convert_setitemc       6         s2  t  \}}t }t }t| |j|j| 		fdd	 D }g }xt|dd dD ]\}t	j
dksdt	jdkrqdtj
d }	x |	 jD ]|}
t|
tjrt|
jtjr|
jjdkr
|
jjj|r fd	djD }|
jj}
|
jjj|\}}xL j jD ]<}t|tjr(t|jtjr(|jjd
kr(|jjP q(W td j i
j\}}|d }tfdd|D   |	 j}|
j }
j!"j}t#||}
$ |	 |||_|
j|
_ fdd|D t% }t#|||< t }x|D ]}|&|j| }q$W t }xjD ]}|&| }qLW |'|}x>|D ]6}| jd }t|tj(rt|jjkrt||_qtW fddd }d }
fdd}d}|dkrn|)|d st*t+||d } | r| \}!}}"}n|d }!|,|d kr4|!n|}#
-|#||\	}$|rlt.fdd|D t/  }%t#||}&
0||&\}'|&j|%j }(|(|%_|r|$d })n})|d krrt% }*t1|*t/  d  }+t/|+},t2|+}-t#||}&|&|*< t3|t4d|}.|"
j|.j< tj5||)|}/|&j6t|/|.|t7|.|,|-|g nd}0d}1|d }2t	|dkr|d }0|d }2t	|dkr|d }0|d }2y
j89|d }1W n t:k
r   t;dY nX t|1tj<st;d|1j}1|1dkrt;dt3|t4d|t|0t=rL|0dkrLt>j?}'n
t>j@}'d}tA|0|2|1g	|'
jj< fddD }3tB|3 |r
C tD	|||r|)n|d ||f
jE|d!	}4 |	 jd }5tjd |5_ |5j jFd|4  Gj x|D ]} G| qW qW qdW d S )"Nc                s"   g | ]} | t  | jfqS rY   )rs   r  )r[   rC  )loopsrY   r]   r^   W  s    z,ParforPass._convert_loop.<locals>.<listcomp>c             S   s   | d S )Nro   rY   )tuprY   rY   r]   r   Z  s    z*ParforPass._convert_loop.<locals>.<lambda>)rY  ro   r   r  c                s"   g | ]}| kr|j kr|qS rY   )header)r[   rb   )r.  r  rY   r]   r^   d  s    Z
pair_firstc             3   s   | ]\}}| kr|V  qd S )NrY   )r[   tr;  )
loop_indexrY   r]   r   u  s    z+ParforPass._convert_loop.<locals>.<genexpr>c                s   i | ]} | |qS rY   rY   )r[   rb   )r.  rY   r]   
<dictcomp>  s    z,ParforPass._convert_loop.<locals>.<dictcomp>rK  c                 s   t  } xN  D ]B}x<|tjD ],}t|jtjr&|jj| kr&| 	|j
j q&W qW g }g }x  D ]}x|jD ]v}tdd | D }|| @ rx|| rqxtt|tj |j}tt|tjo|jdk ||jj || qxW qlW ||fS )zfind expressions that involve getitem using the
                        index variable. Return both the arrays and expressions.
                        c             s   s   | ]}|j V  qd S )N)r   )r[   ra   rY   rY   r]   r     s    zHParforPass._convert_loop.<locals>.find_indexed_arrays.<locals>.<genexpr>)r  static_getitem)r5  r7  Z
find_instsr
   r  r   r  r   r   r8  r  r  r  r   issubsetr;   r  r   r   )indicesr  r  ZarrsZexprsZlvr  )r   loop_index_varsrY   r]   find_indexed_arrays  s*    

z5ParforPass._convert_loop.<locals>.find_indexed_arraysc       	         s   t j| }t|o0t|tjo0|jdko0|jdk |j}t	j
fddjD  }  \}}t|jgt|k t|j|k t j|j}|}x|D ]}|d |_qW |S )zFind the case where size_var is defined by A[M].shape,
                        where M is a boolean array.
                        r  r}   c                s   g | ]} | qS rY   rY   )r[   rb   )live_maprY   r]   r^     s    zIParforPass._convert_loop.<locals>.find_mask_from_size.<locals>.<listcomp>r   )r>   r  r;   r   r
   r  r   r  r  r  r:  exitsr   r  
_find_mask)	size_varZsize_defZarr_var	live_varsZ
index_arrsZindex_exprsarr_defresultr  )r  r  r  r   rY   r]   find_mask_from_size  s    


z5ParforPass._convert_loop.<locals>.find_mask_from_sizeTr   c             3   s   | ]}|r|n d  V  qdS )r   NrY   )r[   ra   )
index_varsrY   r]   r     s   z	$mask_valr   r   z,Only known step size is supported for prangez/Only constant step size is supported for prangez4Only constant step size of 1 is supported for prangeparfor_indexFc                s   i | ]
} |qS rY   rY   )r[   r;  )r   rY   r]   r     s    r   )r   )Hr2   rK   rH   rI   usemapdefmapr  r9  r  rs   entriesr  r  r  r   r
   r  r  r  r   _is_parallel_loopr   r   rj   _get_loop_kindr  r  r,   r  r  r8  r  r   r   r  Block_get_prange_init_blockr   r:  intersectionJumpZ	has_shaper   r:   r  _mk_parfor_loopsrM  rx   _make_index_varr7   r   r   r   r  rG  Branchr  r>   r  NotImplementedErrorConstr   r   uintpZintpr   r%   _replace_loop_access_indicesr   r   r  r  )6r   r.  r  _cfgusedefsZsized_loopsZmoved_blocksr   entryr  Zbody_labelsrj   Z	loop_kindZloop_replacingr  Zcpsr  r   r   r   	end_labelZbodydefsZblZ
exit_livesr   rb   Z	last_instmask_varmask_indicesr
  Zunsigned_indexr	  ry   mask_typ	size_varsZ
orig_indexfirst_body_block
body_blockindex_var_typr  Zorig_index_var
body_labellabels
true_labelfalse_labelmaskmask_valr   r   r  Zindex_var_maprq   jumprY   )r.  r  r   r  r  r  r   r  r  r  r   r]   r  Q  s   
















zParforPass._convert_loopc          	   C   sj  | |j t| t|}W dQ R X |d }t }x$|D ]}|| }x
|jD  ]}	t|	tjrt|	j	tj
r||kr|	j	j|kr|	jj|kr| |	jj | |	jj n|	jj|krtd|	jjt|	r<t|	}
|
dkrqVtt| j|
dd}|
j|ks"|dk	r,|j|kr,t|	| t| j||| t|	trV| |	j|| qVW q>W ||8 }dS )z
        Replace array access indices in a loop body with a new index.
        index_set has all the variables that are equivalent to loop index.
        Nr   z&Overwrite of parallel loop index at {}T)Zlhs_only)r8  r   dummy_return_in_loop_bodyr/   r  r  r   r
   r  r  r   r  r   r   r   rD   rE   r:   r>   r  rF   _replace_multi_dim_indr   r  r   )r   r   	index_set	new_indexr*  first_labelZadded_indicesrb   r  r  r   Zind_defrY   rY   r]   r  5  sD    






z'ParforPass._replace_loop_access_indicesc                sl   t |dk	 t t| j|j tjtjf t| j|}t t|t	j
oL|jdk  fdd|jD |_dS )zq
        replace individual indices in multi-dimensional access variable, which
        is a build_tuple
        Nbuild_tuplec                s   g | ]}|j  krn|qS rY   )r   )r[   r;  )r2  r3  rY   r]   r^   z  s   z5ParforPass._replace_multi_dim_ind.<locals>.<listcomp>)r;   r   r  r   r   ZTupleUniTupler>   r  r
   r  r   r   )r   Zind_varr2  r3  Zind_def_noderY   )r2  r3  r]   r1  n  s    z!ParforPass._replace_multi_dim_indc             C   s  t t|tjo|jdk |j}|j}| j|j }| j|j }|j	}t t|t
jj t|t
jjrt|jt
jr||j	kr|||jdfS t|t
jrt| j|\}}t |dkot||k d}	g }
d}x|D ]}| j|j }t|t
jjrt|jt
jr|}|j}|
d qt|t
jjrNt|jt
jrN|}|j}|
d qt|t
jr|	d7 }	|
| qW t |o|	|d k ||||
fS tdS )zcheck if an array is of B[...M...], where M is a
        boolean array, and other indices (if available) are ints.
        If found, return B, M, M's type, and a tuple representing mask indices.
        Otherwise, raise GuardException.
        r  Nr5  r   ro   )r;   r   r
   r  r   r  r   r  r   r~   r   r   r   rw   r  	BaseTupler9   r  rs   r   ZIntegerr<   )r   r  r  r   r  r  r~   seqr   Zcount_constsr#  r"  Zindr$  rY   rY   r]   r  }  sF    

zParforPass._find_maskc             C   s\  d}d}g }xt |jD ]\}}t|tjr\t|jtjr\|jjdkr\| |jj	j
|r\|}t|tjrt|jtjr|jjdkr| |jj	j
|r|}qW |dkrX|dkrXdd |D }	g }
x^tt|d |D ]H}|j| }dd | D }|	|@ r|	|O }	|
| q|| qW |  |
  |jd| |
 |j|d d  |_|S )z
        If there is init_prange, find the code between init_prange and prange
        calls. Remove the code from entry_block and return it.
        rK  r  c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   	<setcomp>  s    z4ParforPass._get_prange_init_block.<locals>.<setcomp>ro   c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r9    s    N)r  r  r   r
   r  r  r  r   _is_prange_initr   r   r  r  rh   r   r   reverse)r   Zentry_blockr  Zprange_argsZinit_call_indZprange_call_indZ	init_bodyr{   r  Zarg_related_varsZsaved_nodesZ	inst_varsrY   rY   r]   r    s4    

&z!ParforPass._get_prange_init_blockc             C   s8   ||krdS || }t |dko6|d dkp6|d tkS )NFr   rd   )rs   rd   )r   func_varr  r  rY   rY   r]   r:    s    zParforPass._is_prange_initc             C   sh   ||krdS || }t |dkof|d dkpf|d tkpf|d dkpf|d tkpf|d dkpf|d tkS )NFr   r   rg   r   )rs   r   rg   r   )r   r<  r  r  rY   rY   r]   r    s    $zParforPass._is_parallel_loopc             C   s   ||kst || }t|dks$t d}|d dks@|d tkry$d| j| d | j| d ff}W q tk
r|   d}Y qX n|d dks|d tkrd}|S )	z(see if prange is user prange or internalr   )rV  rX  rg   rJ  rK  )rJ  )rX  rX  r   )r   rX  )r   rs   rg   r  r  r   )r   r<  r  r  ZkindrY   rY   r]   r    s    $zParforPass._get_loop_kindc             C   s,   | j | }t|tjjo*|jdko*|jdkS )NCr   )r  r   r   r   r   layoutr~   )r   Zarr_namer  rY   rY   r]   r    s    
zParforPass._is_C_orderc       	      C   s   t |}|j}|dkrt|td|}tjtj|| j	|j
< tjt||}t|||}|j| |tjtj|fS |dkr|d tjfS tdd S )Nro   z$parfor_index_tuple_varr   z,Parfor does not handle arrays of dimension 0)rs   r   r
   r   r   r   
containersr6  r  r  r   r  r5  r  r  r  r   r  )	r   r  r  r'  ndimsr   	tuple_var
tuple_calltuple_assignrY   rY   r]   r    s    
zParforPass._make_index_varc             C   s\   g }g }xJ|D ]B}t |td|}|| tj| j|j< |t|d|d qW ||fS )zV
        Create loop index variables and build LoopNest objects for a parfor.
        r  r   ro   )	r
   r   r   r   r   r  r  r   r   )r   r%  r  r   	loopnestsr  r  r   rY   rY   r]   r    s    

zParforPass._mk_parfor_loopsc             C   sb  |j }|j}|j}| j|j }|j}	||}
| |
||\}}t	||}t
| j| j|t|
|	|||_t }t	||}t|td|}|	| j|j< | |||\}}|jt| j| j| j| j||||||| dt|jf}t||i ||||d | j}t||||}ttj| j|j ||	| j|< |j| ||i|_t j!dkr^|"  |S )zegenerate parfor from arrayexpr node, which is essentially a
        map with recursive tree.
        z$expr_out_varzarray expression {}r   ro   )#r  r   r  r  r   rw   r  r  r
   r  r    r  rM  r  r   r   r   r  rG  _arrayexpr_tree_to_irr  r  r   repr_arrayexprr   r   r  rN   r   noner   r   r   r  r  )r   r   r  r  r  r  r   r  arr_typel_typr%  r  rD  r   r)  r'  expr_out_varr   r(  Zpatrq   setitem_noderY   rY   r]   r    sN    

zParforPass._arrayexpr_to_parforNc       "   	   C   s  |j }| j|j }|j}	| j|j }
t||}|rt|
tjsPt|
tj	sPt
|}t|td|}tj|||}tj||
j}|| j|j< | ||
f| j|< |t||| |}n t|
tjst
||}|
j}g }g }xJ|D ]B}t|td|}|| tj| j|j< |t|d|d qW t }t||}| |||\}}t||i |||d| j}|r||i|_|}d}nt }t||}t }t||}||||||i|_t|td|}|| j|j< tj|||}|j !t|||t"||||g | j|j }t|tj#j$rt|td|} |j| j| j< tj|||}t%|j||| j|< |j t|| | n|} t&||| |}!t%tj'| j|j ||	| j|!< |j |! |r|j t(|| t)j*dkr|+  |S )	zgenerate parfor from setitem node with a boolean or slice array indices.
        The value can be either a scalar or an array variable, and if a boolean index
        is used for the latter case, the same index must be used for the value too.
        z$subarrr  r   ro   )r  rX  Nz	$mask_varz
$value_var),r  r  r   rw   r
   r  r   r   r7  Z	SliceTyper   r   r   r  r  r   Z	arraydeclZget_array_index_typer	  _type_getitemr  r   r  ZArrayCompatibler  r  r   r   r  r   r   r   r  rG  r  r   r   rN   r  rG  r  r   r  r  )"r   r   r   r  r   r  r}   r  rH  rI  r  r   r%  Z
subarr_vargetitem_callZ
subarr_typZbool_typrD  r  r  r   r)  r'  r(  rq   Z
true_blockr!  r+  	end_blockr"  r.  r  Z	value_varrK  rY   rY   r]   r  J  s    





zParforPass._setitem_to_parforc             C   s   t j}| j|t|i S )N)operatorr  r  resolve_function_typerM  )r   rj   ZfntyrY   rY   r]   rL    s    zParforPass._type_getitemc             C   sX   t | j|\}}t|tr$|ds(dS |dkr4dS |dkr@dS |dkrT|tkrTdS dS )zLcheck if we support parfor translation for
        this Numpy call.
        r   F)r   onesT)r   r   znumpy.random)r8   r  r   r   
startswithrT   )r   r  	call_namemod_namerY   rY   r]   r    s    z ParforPass._is_supported_npycallc             C   s   | j | jS )N)r  r~   )r   r   rY   rY   r]   
_get_ndims  s    zParforPass._get_ndimsc             C   sR   t | j|\}}|j}t|j}|dks0|dkrD| ||||||S td|d S )N)r   rQ  znumpy.randomzparfor translation failed for )r8   r  rj   r  kws_numpy_map_to_parforr  )r   r   r  r  rS  rT  rj   rV  rY   rY   r]   r    s    
zParforPass._numpy_to_parforc          
   C   s  |j }|j}| j|j }	|	j}
||}| |||\}}t||}t	| j| j
|t||
|||_t }t||}t|td|}|
| j|j< | |||\}}|dkrt|
d|}n|dkrt|
d|}nf|tkr2t|| t|| j\}}| j
| | j|jj t ||| j
|< |}ntd| t|||}|j| t||i |||d|df| j}t ||||}t!t"j#| j|j ||
| j
|< |j| ||i|_$t%j&dkrt'd	 |(  |S )
z8generate parfor from Numpy calls that are maps.
        z$expr_out_varr   r   rQ  ro   z,Map of numpy.{} to parfor is not implementedz{} functionzNumPy mappingzgenerated parfor for numpy map:))r  r   r  r   rw   r  r  r
   r  r    r  rM  r  r   r   r   r  r  rT   _remove_size_arg_get_call_arg_typesr  r   r  r   Contextr  r   r  r   r   r   r  rN   r   rG  r   r   r  rZ   r  )r   r   rS  r  rj   rV  r  r  r   rH  rI  r%  r  rD  r   r)  r'  rJ  r   r(  r  new_arg_typsnew_kw_typesZvalue_assignrq   rK  rY   rY   r]   rW    sV    



zParforPass._numpy_map_to_parforc             C   s<  ddl m} t| j|}|| j| | j|j }	|	j}
t||}| 	|||\}}t
|td|}|
| j|j< tj|||}t|
|	|| j|< |t||| t|| jjjj| j|
|
f| j| j}|j}t }t||}|||< t|j }|j| }|j|j |j|_t|||g t||| ||fS )zZ
        Produce the body blocks for a reduction function indicated by call_name.
        r   )check_reduce_funcz$val)r  r]  r>   r  r  r   rw   r
   r  r  r   r   r  r  rN   r  r   r  r=   r$  r   r  r  r.  r   rx   r9  r  rG  r@   rA   )r   rS  r  r   r  ry   acc_varr]  Zreduce_funcrH  Zin_typr'  r   Zindex_var_typeZtmp_varrM  Zreduce_f_irr   r!  rN  Zfirst_reduce_labelZfirst_reduce_blockrY   rY   r]   _mk_reduction_body	  s>    

zParforPass._mk_reduction_bodyc          
      s  |j }|d }|d }t| j|j}d}	d}
t| j|}|rH|\}}	}}
|d }||
dkr`|n|	}| |||\ } }|
rt fdd|
D  |}t	
||}|jt	||| t }| ||| ||\}}|
r|d }|	dkrpt| }t| }t	
||}|||< t	|td|}|| j|j< t	j|	||}|jt	|||t	||||g t||||||d|d	f| j}|S )
zy
        Convert a reduce call to a parfor.
        The call arguments should be (call_name, array, init_value).
        r   ro   Nr   c             3   s   | ]}|r|n d  V  qdS )r   NrY   )r[   ra   )r  rY   r]   r   @	  s    z/ParforPass._reduce_to_parfor.<locals>.<genexpr>z	$mask_valz{} functionr  )r  r>   r  r   r:   r  r  r  rM  r
   r  r  r   r  r   r_  rx   r9  r   r   r   r  r  r  rG  r  r   r   r   )r   r   r  rj   r   r  rS  ry   r  r"  r#  r	  r$  r   r%  rD  Z
mask_indexr^  r   r)  r   r   r+  r,  r'  r-  r.  rq   rY   )r  r]   r  +	  sL    

zParforPass._reduce_to_parforc             C   sD  x<|  D ].\}}||}d}x|r:d}g }d}x|t|jd k r |j| }	|j|d  }
t|	trt|
tr||}||	_||
_t||	|
\}}| jj	
| |d k	rd}| jj|	j |
jg |
| | || |d7 }q<|
|	 t|	tr| |	| |d7 }q<W |
|jd  ||_q(W qW d S )NTFr   ro   r   rK  )r   r  rs   r  r   r   r   try_fuser  r!  r   r  r   rG  fuse_recursive_parfor)r   r   r.  r3  r  r   Zfusion_happenedr  r{   r  	next_stmtZ
fused_nodeZfuse_reportrY   rY   r]   r  a	  s<    





zParforPass.fuse_parforsc             C   sT   t |}t| j|| j t| j| j| j| j}||| | 	|| t
| d S )N)r  r  r  r  r   r  r  r  r  r  r  )r   rq   r   r.  Zarr_analysisrY   rY   r]   ra  	  s    z ParforPass.fuse_recursive_parfor)N) rl   rm   rn   r   r  r   r  r  r  r  r  r  r1  r  r  r:  r  r  r  r  r  r  r  rL  r  rU  r  rW  r_  r  r  ra  rY   rY   rY   r]   r  x  s:   Z+ e9,'	5
]	;(6#r  c             C   s   t |j}|dd t| |_| tt kr6g |_| tkrVt	|jdkrV|j  | t
krvt	|jdkrv|j  | dkrt	|jdkr|j  t	|jdkr|j }|j  |j| | dkrt	|jdkr|j  dS )	z%remove size argument from args or kwsr   rX  r   r   Zrandintr   Z
triangularN)r  rV  r  rM  r   rQ   rP   rj   rS   rs   rR   r   )rS  r  rV  Zdt_argrY   rY   r]   rX  	  s,    






rX  c             C   sV   g }x| j D ]}|||j  qW i }x | jD ]\}}||j ||< q0W t||fS )N)rj   r   r   rV  rM  )r  r  r[  r   r\  r   rY   rY   r]   rY  	  s    rY  c       !      C   sj  ||j  }|j}|j}g }t|tr|\}}g }xR|D ]J}t|td|}|||j < |t| |||||||||	|
7 }|	| q8W |t
jkrV||d j  }t|dkr||d j  }||||fi }tj||d |d |}|tjkr4t|d |d ||\}}n$|||fi }tj||d |}|||< |j}|	t||| xtjD ]2}t||r`t|||
}t|t||}|| ||j < | |}t|tjr(|jdkr(|jdkr(t|td|}tjt||j < t dt|}t|||}tj!|d|}|	| tj"||d	|}||j  #t$% |gt| i }|||< |j}|	t||| |	t||| q`W nt|tjr ||j  } t| tj&r| j'}t(||||	||||||
}n| }|}|	t||| n2t|tj)r2t$% *|j+}|	t||| t|dkrNt,d
|f |-|j d |||j < |S )zgenerate IR from array_expr's expr tree recursively. Assign output to
    expr_out_var and returns the whole IR as a list of Assign nodes.
    z$arg_out_varr   r   ro   r  Zsqrtz$math_g_varr   rY   z1Don't know how to translate array expression '%r'N).r   r  r   r   rM  r
   r   r   rE  r   rM   Zsupported_array_operatorsrs   rP  r  binoprO  truediv_gen_np_divideZunaryr   r  r   Z	MAP_TYPES_find_func_varr>   r   r  r   r  r  r   r  r  r  r  r   rZ  r   rw   _gen_arrayexpr_getitemr  Zresolve_value_typer  r  r  )!r  r  r  r  r   r   rJ  r  parfor_index_tuple_varall_parfor_indicesr  rI  r  r   out_irr   Zarr_expr_argsZarg_varsr   Zarg_out_varZel_typ1Zel_typ2func_typir_exprTZfunc_var_namer<  Zfunc_var_defZ
g_math_varZg_mathZg_math_assignZcall_typvar_typrY   rY   r]   rE  	  s    



&



rE  c             C   s   | j }| j}t|td|}tjt||j	< t
dt|}t|||}tj|d|}	t|td|}
ttj}|||
j	< t|	|
|}tj|
| |gd|}|t || j	 ||j	 gi }|||g ||fS )zgenerate np.divide() instead of / for array_expr to get numpy error model
    like inf for division by zero (test_division_by_zero).
    z	$np_g_varr   dividez	$div_attrrY   )r  r   r
   r   r   r   r  r  r   r   r  r  r  r  r!   ro  r  r  r   rZ  rG  )Zarg1Zarg2rj  r  r  r   r  r  r  Zdiv_attr_callZattr_varZfunc_var_typZattr_assignZdiv_callrk  rY   rY   r]   re  /
  s     

re  c
           	      sV  |j }
|}||j }||j j}t|} |p4g } fdd|D }|dkrt|jtd|
}t	j
j|jddd}|||j< tdtj||g|||}|j| |}td|j }t|jtd	|
}t	j||j< t|||
}|	| |}n,|dkr|d
 }ntdd |D r&|| }t|jtd|
}t	jt	j|||j< td|j }t|jtd	|
}t	j||j< t|||
}|	| g }xNtt|D ]>}|| }|| }|dkr|| n||||   qW tt|}tj||
}t|||
}|	| |}tj|||
}t |||j ||j ||< |S )a  if there is implicit dimension broadcast, generate proper access variable
    for getitem. For example, if indices are (i1,i2,i3) but shape is (c1,0,c3),
    generate a tuple with (i1,0,i3) for access.  Another example: for (i1,i2,i3)
    and (c1,c2) generate (i2,i3).
    c                s   g | ]}  |qS rY   )Zget_equiv_const)r[   ra   )r   rY   r]   r^   ^
  s    z*_gen_arrayexpr_getitem.<locals>.<listcomp>r   z$ravelro   r=  )rw   r~   r>  r   z$const_ind_0rK  c             S   s   g | ]}|d kqS )NrY   )r[   ra   rY   rY   r]   r^   q
  s    z$parfor_index_tuple_var_bcast)!r   r   r~   rs   r  r
   r   r  r   r   r   r   rw   r   Zgen_np_callr   r   r  rG  r  r  r  r   r   r?  r6  r  rh   r  r  r5  r  rN   ) r   r   rh  ri  rI  r  r  r  r   rj  r   r   rn  r@  Znum_indicesr%  Zsize_constsZ	ravel_varZ	ravel_typZstmtsZ
const_nodeZ	const_varZconst_assignZ
ind_offsetrA  r  r{   r  Z
size_constrB  rC  rl  rY   )r   r]   rg  H
  s`    








rg  c             C   s:   x,|D ]$}| | }t |tr|j|kr|S qW tddS )zAfind variable in typemap which represents the function func.
    zufunc call variable not foundN)r   rO   Z
typing_keyr  )r  r   r  r;  r  rY   rY   r]   rf  
  s
    
rf  c       	      C   s   t tjt|jt_d}i }x4|j D ]&\}}t||||||\}}|||< q*W ||_|rjt|j|_t|d t	||| t|d t
|}|  d S )NFz after parfor sequential loweringz after parfor sequential simplify)r   r   r  find_max_labelr.  r   _lower_parfor_sequential_blockr1   r.   r3   r   r  r  )	r  r  r  r  parfor_foundr  block_labelr  r  rY   rY   r]   r  
  s"    


r  c          	   C   s  |j }t|j}x|dkrd}|j| }|jj}	t||	}
|jd | |
_|j|d d  |_t }|
jt	||	 |j||< |
|| < t } t
|j}xt|D ]}|j| }t }t }t||j|j|j|||	}||jd _|jd j}|||< t|||||	}|j|jd _|||< |dkrR|jjt	||	 | |jd _n||| jd _||jd _|}qW t|j }|j| jt	||	 t|j }||jd _x6|j D ](\}}t||||||\}}|||< qW t|j}qW | |fS )NrK  Tro   r   )r  _find_first_parforr  r   r   r
   r  r   r   r  rs   r   rh   r"   r   r   r   r  r#   r   ZfalsebrZtruebrr   r   r9  rx   r   rq  )rs  r  r  r  r  rr  r  r{   r  r   Z
prev_blockZ
init_labelr@  r  Zrange_labelZheader_labelZrange_blockZphi_varZheader_blockZprev_header_labelZbody_last_labelZbody_first_labelrb   r   rY   rY   r]   rq  
  sf    





rq  c             C   s.   x(t | D ]\}}t|tr
|js
|S q
W dS )NrK  )r  r   r   r   )r  r{   r  rY   rY   r]   ru  
  s    ru  c             C   s   t  }t  }t| \}}t| }x|D ]}| | }	xrt|	jD ]d\}
}t|	j|	j}|	jd|
 |_td|ij	d }||O }t
|||||jB |_||j q>W ||| O }q&W |S )zfind variables used in body of parfors from outside and save them.
    computed as live variables at entry of first block.
    Nr   )r  rH   r/   _find_parforsr  r
   r  r  r   r  get_parfor_params_innerr   r   r8  r   )r.  options_fusionr  r  pre_defsr  Zall_defsr  r3  r  r{   rq   Zdummy_blockbefore_defsrY   rY   r]   r    s    	
r  c             C   s   t | }t|}t|}t|||j|j}t|||}t|}	|	dkr|tj	rn|rTdnd}
t
d|
| j|	| t||| j< t|  t| }|d }|d }|j| |B }|| |@ }|S )Nr   zAfter fusionzWith fusion disabledz2{}, parallel for-loop {} has nested Parfor(s) #{}.ro   )r  rK   rH   rI   r  r  r  rs   r   r   rZ   r   r   r  r  r  r9  )rq   ry  rx  r  r.  r  r  r  r  r  r  Zkeylistr   Zfirst_non_init_blockrz  r   rY   rY   r]   rw    s(    rw  c             c   s.   x(t | D ]\}}t|tr
||fV  q
W d S )N)r  r   r   )r  r{   r  rY   rY   r]   rv  8  s    
rv  c             C   s|   t | j }g }xL| j D ]>}x8|jD ].}t|tjr*|jj	| j
j	kr*||jj	 q*W qW tt|t|@ }t|S )zhget arrays that are written to inside the parfor and need to be passed
    as parameters to gufunc.
    )r   r   r9  r7  r  r   r
   r  r   r   r   r   r  r  r  r  )rq   parfor_params
last_labelZoutputsr4  r  rY   rY   r]   get_parfor_outputs>  s    r}  c             C   s
  |dkri }|dkrg }|dkr(t t}|dkr8t t}|dkrDi }t| }t|}	|	dd }	t|  x0t|	D ]"}
xt| j|
 jD ]}t|t	j
rt|jj|ks|jj|krt|jj}|j}||kr|n|| }g }t|t	jr|jg}n"t|t	jrdd |j D }|| | x|D ]}|||< q.W t|}|j|krf||j ||j< || | t|trt|||||||| qW qtW xd| D ]X\}}||kr||kr|| ||   t||| }tt|}||f||< qW ||fS )zfind variables that are updated using their previous values and an array
    item accessed with parfor index, e.g. s = s+A[i]
    Nro   c             S   s   g | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r^   t  s    z)get_parfor_reductions.<locals>.<listcomp>)r   r  r  r/   r  r  r   r  r   r
   r  r  r   r  r   r  r   rG  r5  r6  r   r   get_parfor_reductionsr   r;  get_reduce_nodesr:   get_reduction_init)rq   r{  r  Z
reductionsZreduce_varnamesZ
param_usesZparam_nodesZvar_to_paramr.  r  r3  r  r  rhsZ	cur_paramZ	used_varsr;  Zstmt_cpZparamreduce_nodesr   rY   rY   r]   r~  O  sZ    





r~  c             C   s   t t| dk t t| d jtj t | d jj| d jjk | d j}t t|tjob|j	dk |j
tjkrvdS |j
tjkrdS dS )z
    Get initial value for known reductions.
    Currently, only += and *= are supported. We assume the inplace_binop node
    is followed by an assignment.
    r   rK  rt  inplace_binopr   ro   N)r;   rs   r   r  r
   r   r  r   r  r   fnrO  iaddimul)nodesZacc_exprrY   rY   r]   r    s    
r  c                s&  d}i  d fdd	xt |D ]\}}|j}|j}| |j< t|tjr^|j kr^|}t|tjr"tfdd|	 D }|kr"fddt
|D }fd	d|D }	t|	d
kstdd |D }t|}
t|jd |j|
|	d < t||
 ||d }P q"W |s"td|S )z
    Get nodes that combine the reduction variable with a sentinel variable.
    Recognizes the first node that combines the reduction variable with another
    variable.
    NTc                s:     | jd }t|tjr"|S |s.|d kr2| S |S d S )N)r  r   r   r
   r   )r   Zvaronlyrz   )defslookuprY   r]   r    s    z get_reduce_nodes.<locals>.lookupc             3   s   | ]} |d j V  qdS )TN)r   )r[   r;  )r  rY   r]   r     s    z#get_reduce_nodes.<locals>.<genexpr>c                s   g | ]}|j  |d fqS )T)r   )r[   ra   )r  rY   r]   r^     s    z$get_reduce_nodes.<locals>.<listcomp>c                s   g | ]\}}|j  kr|qS rY   )r   )r[   ra   r\   )r   rY   r]   r^     s    ro   c             S   s"   g | ]\}}||j kr||fqS rY   )r   )r[   ra   r\   rY   rY   r]   r^     s    z#initr   zInvalid reduction format)T)r  r  r  r   r   r
   r   r  r  r   get_expr_argsrs   r   r  r  r   r&   )r   r  r  r{   r  r  r  Zin_varsrj   Znon_red_argsZreplace_dictrY   )r  r  r   r]   r    s.    

r  c             C   sB   | j dkr| j| jgS | j dkr0dd | jD S td| dS )z-
    Get arguments of an expression node
    )rc  r  r  c             S   s   g | ]}|qS rY   rY   )r[   r;  rY   rY   r]   r^     s    z!get_expr_args.<locals>.<listcomp>zget arguments for expression {}N)r   r  r  rj   r  r   )r  rY   rY   r]   r    s
    

r  c             C   s   x| j D ]}|d dkr|d d }x8tt|D ](}t|| tjr2t|| ||||< q2W |d d }x8tt|D ](}t|| tjrxt|| ||||< qxW qW d S )Nr   r  ro   )r   rh   rs   r   r
   r   r(   )rq   callbackcbdatar   left_lengthsr{   right_lengthsrY   rY   r]   visit_parfor_pattern_vars  s    r  c             C   s   t jdkr&td|  tdt|  xx| jD ]n}t|j|||_t|j	t
jr`t|j	|||_	t|jt
jr~t|j|||_t|jt
jr.t|j|||_q.W td| ji|| t| || t| j|| d S )Nro   zvisiting parfor vars for:zcbdata: rK  )r   r  rZ   r  r   r   r(   r   r   r   r
   r   r   r   r'   r   r  r   )rq   r  r  rb   rY   rY   r]   visit_vars_parfor  s    

r  c             C   s&  |dkrt  }|dkrt  }t| }t|\}}t|}t| }t|  | }| | }	x|	 
 D ]}
|	|
j8 }	qnW xH|D ]@}||	kr||| |  |||  q||| |  qW dd | jD }|dd | jD O }|dd | jD O }|| |t| O }tj||dS )zzlist variables written in this parfor by recursively
    calling compute_use_defs() on body and combining block defs.
    Nc             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9    s   zparfor_defs.<locals>.<setcomp>c             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9    s   c             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9    s   )r  r  )r  r  rH   rK   r   r9  r  r  Z
dominatorsr  r7  r  r  r   get_parfor_pattern_varsr   Z_use_defs_result)rq   Zuse_setZdef_setr.  usesr  r  r|  r  Zdefinitely_executedr  r3  	loop_varsrY   rY   r]   parfor_defs  s6    


r  c             C   s@  t | }t|}t|}t|||j|j}t||||j}dd | jD }|dd | jD O }|dd | jD O }|dd | jD O }t }xt|	 D ]h}	|j
|	  |M  < |j
|	  |8  < ||j
|	 O }|j|	  |M  < |j|	  |8  < ||j|	 O }qW G dd dt}
t|
|}||j
|j t|  ||B S )z~insert dels in parfor. input: dead variable set right after parfor.
    returns the variables for which del was inserted.
    c             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9  4  s   z%parfor_insert_dels.<locals>.<setcomp>c             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9  7  s   c             S   s"   h | ]}t |jtjr|jjqS rY   )r   r   r
   r   r   )r[   rb   rY   rY   r]   r9  :  s   c             S   s   h | ]}|j jqS rY   )r   r   )r[   rb   rY   rY   r]   r9  =  s    c               @   s   e Zd Zdd ZdS )z'parfor_insert_dels.<locals>.DummyFuncIRc             S   s
   || _ d S )N)r.  )r   r.  rY   rY   r]   r   N  s    z0parfor_insert_dels.<locals>.DummyFuncIR.__init__N)rl   rm   rn   r   rY   rY   rY   r]   DummyFuncIRL  s   r  )r  rK   rH   rI   r  r  rJ   r   r  r9  rJ  Zescapingobjectr   r  Z_patch_var_delsr  )rq   Zcurr_dead_setr.  r  r  r  Zdead_mapr  Zdead_setr3  r  r  rY   rY   r]   parfor_insert_dels)  s2    
r  Tc       
      C   sT   t |\}}t|| j|| \}}x.| D ]"}d}	x|	rJt| ||||}	q4W q*W dS )zm
    Reorder statements to maximize parfor fusion. Push all parfors up or down
    so they are adjacent.
    TN)r2   rG   Z	arg_namesr7  maximize_fusion_inner)
r  r.  r  r  r  r  	alias_maparg_aliasesr  order_changedrY   rY   r]   r  Z  s    r  c       
      C   s   d}d}xz|t |jd k r|j| }|j|d  }|rHt||| ||nt||| ||}	|	rx||j|< ||j|d < d}|d7 }q
W |S )NFr   r   ro   T)rs   r  _can_reorder_stmts)
r  r  r  r  r  r  r{   r  rb  Zcan_reorderrY   rY   r]   r  g  s    


r  c             C   s:   t  }x.| D ]&}||kr(||| }q|| qW |S )N)r  r:  r8  )Zthe_setr  Zretr{   rY   rY   r]   expand_aliasesy  s    
r  c       	      C   s   t | trt |tst |tjst |tjrJt|jt |sJtt	||jrt
dd |  D |}t
t| |}t
dd | D |}t
t||}t||@ ||@ B dkrdS dS )zw
    Check dependencies to determine if a parfor can be reordered in the IR block
    with a non-parfor statement.
    c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r9    s    z%_can_reorder_stmts.<locals>.<setcomp>c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r9    s    r   TF)r   r   r
   ZPrintr  r5   r  r  r:   is_assert_equivr  r   get_parfor_writesr0   rs   )	r  rb  r  r  r  Zstmt_accessesZstmt_writesZnext_accessesZnext_writesrY   rY   r]   r    s     	


r  c             C   s   t | |\}}|dkS )NrU   )r8   )r  r  r  rT  rY   rY   r]   r    s    r  c             C   st   t | tstt }| j }| j|d< xF| D ]:}x4|jD ]*}|	t
| t |tr>|	t| q>W q2W |S )NrK  )r   r   r   r  r   r5  r   r7  r  r  r0   r  )rq   Zwritesr.  r  r  rY   rY   r]   r    s    


r  FusionReportfirstsecondmessagec                s2  t d|d| d}t|jt|jkr~t d d}d}||jt|jf }||jt|jf }t|j|j|||f }d|fS t|j} fdd}	xt|D ]}
|j|
 }|j|
 }|	|j|jr|	|j|jr|	|j|jst d	|
 d
}|d|j|j|jf 7 }|d|j|j|jf 7 }t|j|j||
 }d|fS qW t	|sRt	|rt d d}t|j|j||j|jf }d|fS t
|j}t }x|j D ]}||O }qW t
|j}t
d|jijd }x|j D ]}||O }qW ||s(t d d}t|j|j||j|jf }d|fS t||S )zItry to fuse parfors and return a fused parfor, otherwise return None
    ztry_fuse: trying to fuse 
r[  Nz/try_fuse: parfors number of dimensions mismatchz4- fusion failed: number of loops mismatched, %s, %s.z(parallel loop #%s has a nest of %s loopsc                s   | |kp  | |S )N)is_equiv)ra   r\   )r   rY   r]   r    s    ztry_fuse.<locals>.is_equivz/try_fuse: parfor dimension correlation mismatchz7- fusion failed: loop dimension mismatched in axis %s. zslice(%s, %s, %s) != zslice(%s, %s, %s)z1try_fuse: parfor cross iteration dependency foundzK- fusion failed: cross iteration dependency found between loops #%s and #%sr   z)try_fuse: parfor2 depends on parfor1 bodyzT- fusion failed: parallel loop %s has a dependency on the body of parallel loop %s. )dprintrs   r   r   r  rh   r   r   r   has_cross_iter_deprH   r   r  r  r7  r   r  
isdisjointfuse_parfors_inner)r   parfor1parfor2r  rl  r   r  r  r@  r  r{   Znest1Znest2Zp1_body_usedefsZp1_body_defsr  Z
p2_usedefsZp2_usesr  rY   )r   r]   r`    sZ    







r`  c             C   sZ  | j j|j j t|j }|j| j}t| j }t| j }| j| j| | j|j | j| t	| j
}|jj| ji}x*t|D ]}| j
| j||j
| jj< qW t| j| t| |d}	t|	}	t| |	 tdd | D }
t| j|
 | j|j tjr.td|j| j d}||j| j}t| j|j|}| |fS )N)entry_labelc             s   s   | ]}|j V  qd S )N)r   )r[   ra   rY   rY   r]   r     s    z%fuse_parfors_inner.<locals>.<genexpr>z1Parallel for-loop #{} is fused into for-loop #{}.zE- fusion succeeded: parallel for-loop #{} is fused into for-loop #{}.)r   r  rG  rx   r   r9  r   r  r  rs   r   r   r   rh   r   r%   r  r1   r  r  r7  remove_duplicate_definitionsr   r   r   rZ   r   r   r  )r  r  Zparfor2_first_labelZparfor2_first_blockZparfor1_first_labelZparfor1_last_labelr@  Z
index_dictr{   r.  namesetrl  r  rY   rY   r]   r    s6    

r  c       	      C   sx   xr|   D ]f\}}|j}g }t }xF|D ]>}t|tjr\|jj}||kr\||krRq(|| |	| q(W ||_q
W dS )zsRemove duplicated definition for variables in the given nameset, which
    is often a result of parfor fusion.
    N)
r   r  r  r   r
   r  r  r   r8  r   )	r.  r  r3  r  r  r  Zdefinedr  r   rY   rY   r]   r  !  s    


r  c             C   s   dd | j D }x| j D ]r}xl|jD ]b}t|tjtjfr@q(t|tjrlt|j	tj
rl|j	j}|dkrlq(|| s(td|| dS q(W qW dS )Nc             S   s   h | ]
}|j qS rY   )r   )r[   rb   rY   rY   r]   r9  :  s    z%has_cross_iter_dep.<locals>.<setcomp>)r5  r  r  zhas_cross_iter_dep foundTF)r   r   r7  r  r   r
   r  r  r  r  r  r   r  r   r  )rq   r   r   r  r   rY   rY   r]   r  5  s    r  c              G   s   t jdkrt|   d S )Nro   )r   r  rZ   )r   rY   rY   r]   r  M  s    
r  c             C   sh   t  }x\| jD ]R}|d dkr|d d }|d d }x(|| D ]}t|tjr@||j q@W qW |S )z: get the variables used in parfor pattern information
    r   r  ro   )r  r   r   r
   r   r8  r   )rq   outr   r  r  r;  rY   rY   r]   r  Q  s    r  c       "   	   C   s  t | j t| j}W dQ R X |d }i }t| j| j| j||| t| }	x|D ]}
|
|krfqXx| j|
 jD ]v}t|t	j
rt|jt	jr|jjdkr|jjj| jjkrqttdd | D }||	@ }x|D ]}||d qW qtW qXW x>|D ]6}
|
|krq| j|
 }| }t|j| j||| qW | j }t| }t|||\}}t	|t	dd}|| j| t|}t|}t|||j|j}t| }x| D ]\}}g }dd	 |j D }x$||D ]\}}||| O }qW xt |jD ]}||@ }x|D ]} |||  O }qW t|t	j!rn|jj| jjkrn|j"j|krn|j"j|krnq|d
d	 | D O }|| qW |#  ||_qW ||j || j  t$| ||||| t%| j&jdk}!x&| j' D ]}|!t%|jdkM }!qW |!rdS | S )z7 remove dead code inside parfor including get/sets
    Nr   r  c             s   s   | ]}|j V  qd S )N)r   )r[   r;  rY   rY   r]   r   }  s    z%remove_dead_parfor.<locals>.<genexpr>parfors_dummyrK  c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r9    s    z%remove_dead_parfor.<locals>.<setcomp>c             S   s   h | ]
}|j qS rY   )r   )r[   r;  rY   rY   r]   r9    s    )(r0  r   r/   _update_parfor_get_setitemsr  r   r  r9  r   r
   r  r  r  r   r   r   r   r  r5  r   _add_liveness_return_blockr  Locr   rK   rH   rI   r  r  r   
terminatorZ
successorsr  r  r  r;  remove_dead_parfor_recursivers   r   r7  )"rq   livesr  r  r  r  r*  r4  Zfirst_block_saved_valuesZ
saved_arrsrb   r  ZvarnamesZrm_arrsr   r  saved_valuesr.  r|  return_labelrA  r/  r  r  r  Z	alias_setr3  r  Zin_livesZout_blk_dataZalias_livesr;  Zis_emptyrY   rY   r]   remove_dead_parfor_  s    







r  c       	      C   s  x| D ]}t |tjrh|jj|jkrh|jj|krhx$||jjg D ]}||d qDW |j||jj< qt |tj	rt |jtj
r|j}|jdkrt |jtjr|jj|jkr||jj||_qxB| D ]6}||jd x"||jg D ]}||d qW qW qW dS )zS
    replace getitems of a previously set array in a block of parfor loop body
    Nr  )r   r
   r  r   r   r  r  r  r  r  r  r   r   r   )	Z
block_bodyr   r  r  r  r  wr  r;  rY   rY   r]   r    s$    r  c          	   C   s   | j  }t| }|dks"tt| }t|||\}	}
td||	t	dd}|| j
| | j|d< |d j
t|t	dd t|||||| ||
j |d j
  || j
  dS )zIcreate a dummy function from parfor and call remove dead recursively
    r   r  rK  N)r   r5  rx   r9  r   r   r  r
   r  r  r  r   r   r  r*   r  r   )rq   r  r  r  r  r  r.  r&  r|  r  rA  branchrY   rY   r]   r    s    

 r  c                s   t |  }|d }| | j | | jt | |< ttd }tj	
tjd||j<  fdd|D }tj| }| | jt||  | | jt|  ||fS )Nro   z
$tuple_varr   c                s   g | ]}t | qS rY   )r
   r   )r[   r;  )r   r  rY   r]   r^     s    z._add_liveness_return_block.<locals>.<listcomp>)r   r9  r   r  r
   r  r   r   r   r?  r6  r  r   r  r5  r  r   r  Return)r.  r  r  r|  r  rA  r  rB  rY   )r   r  r]   r    s    

r  c             C   s(   t | }t|||||| t|  d S )N)r  r   rG   r  )rq   rj   r  r  r  r  r.  rY   rY   r]   find_potential_aliases_parfor  s
    r  c             C   s   x|   D ]}x|jD ]v}t|tr|}|jt|j  }|jt	dt
dd t|j|_|jt|j  }|j  t|j qW q
W dS )z%simplify CFG of body loops in parforsr   r  rK  N)r7  r  r   r   r   r   r9  r   r
   r  r  r4   r  r  )r.  r  r  rq   Z
last_blockrY   rY   r]   r    s    

r  c             C   s   | j  }|dkrt| }|dks*t| j|d< |d jt	||d j
 x@| D ]4}t|jdksz|jd js\|jt	||j
 q\W |S )z5wrap parfor blocks for analysis/optimization like CFGNr   rK  )r   r5  rx   r9  r   r   r  r   r
   r  r   r7  rs   Zis_terminator)rq   r  r.  r  rY   rY   r]   r  )  s    

r  c             C   s   |dk	r$t | }|| || _t | j }t| jjd tjsJt	| jj  x>| j
 D ]0}t|jd tjrb|jd j|krb|j  qbW dS )zb
    unwrap parfor blocks after analysis/optimization.
    Allows changes to the parfor loop.
    NrK  )rx   r9  r  r   r   r   r  r
   r  r   r7  r  )rq   r.  Zinit_block_labelZfirst_body_labelr  rY   rY   r]   r  9  s    
r  c             C   s   t | }t||\}}t||\}}t|  |d }x4| j D ]&}|dd || D O }||| O }q@W t| j }	||	 |d @ }
tjdkrt	d|
d| |
|fS )z&find copies generated/killed by parforr   c             S   s   h | ]\}}|qS rY   rY   )r[   rb   r   rY   rY   r]   r9  b  s    z$get_copies_parfor.<locals>.<setcomp>ro   zcopy propagate parfor gens:kill_set)
r  r+   r,   r  r   r9  r   r   r  rZ   )rq   r  r.  in_copies_parforout_copies_parforZin_gen_copiesZin_extra_killr  r3  r|  ZgensrY   rY   r]   get_copies_parforU  s    
r  c             C   s  x:t | jD ],\}}|d dkrdt|d |f| j|< qW x8| jD ].}t|j||_t|j||_t|j||_qDW t| }	g }
x4| D ](\}}|
	t
||| t
dd qW |
|	d j |	d _t|	|\}}t|	||||| t|  |	d jt|
d |	d _dS )z*apply copy propagate recursively in parforr   r  ro   ZdummyrK  N)r  r   r&   r   r   r   r   r  r   r   r
   r  r  r  r+   r-   r  rs   )rq   Zvar_dictZname_var_tabler  r  Zsave_copiesr{   r   rb   r.  Zassign_listZlhs_namer  r  r  rY   rY   r]   apply_copies_parforq  s(    
r  c          	      s   x|   D ]}g }t  x|jD ]} fdd}|st|trx|jjD ]}|| qLW |j }	t|	dd |	| q n|| x$|
 D ]}
|t|
j 7 }qW |	| q W ||_q
W dS )zpush call variables to right before their call site.
    assuming one global/getattr is created for each call site and control flow
    doesn't change it.
    c                s   t | tjr| j}| j}t |tjr<| |j<  |j nDt |tjr|j	dkr|jjksj|jjkr| |j<  |j d S )Nr  )
r   r
   r  r  r  r  r   r8  r  r   )r  r  r  )
block_defssaved_getattrssaved_globalsrY   r]   process_assign  s    

z&push_call_vars.<locals>.process_assignT)nestedN)r7  r  r  r   r   r   r   r5  r  r   r   _get_saved_call_nodesr   )r.  r  r  r  r  r  r  r  r   Zpblocksr;  rY   )r  r  r  r]   r    s&    



r  c             C   s   g }x| |kr| |ks| |kr| |krL| ||   |||  jj d} q| |kr||  jjj}| ||   |||  jj |} qW |  |S )NZ_PA_DONE)r   r8  r  r   r  r;  )fnamer  r  r  r  Zup_namerY   rY   r]   r    s    r  c             C   s   t | tr| d }t |ts2t|dr.|j}nd}| d }t|dkrZd|t|d S d| d }d|dd	 |D S nHt | t	j
jr| j}|d
rd| S |S nt | t	j
jrt| jS dS dS )zMExtract operators from arrayexpr to represent it abstractly as a string.
    r   rl   r  ro   z({}({}))r]  z({})c             S   s   g | ]}t |qS rY   )rF  )r[   ra   rY   rY   r]   r^     s    z"repr_arrayexpr.<locals>.<listcomp>$z'%s' (temporary variable)N)r   rM  r   hasattrrl   rs   r   rF  rh  rp   r
   r   r   rR  r  r   r  )r  Zoprrj   r   rY   rY   r]   rF    s&    




rF  c             C   s0   g }x| j D ]}|||  qW t||_dS )zpostproc updates generator_info with live variables after transformations
    but generator variables have types in return_type that are updated here.
    N)Z
state_varsr   rM  Zstate_types)r  r   r  Znew_state_typesr;  rY   rY   r]   r    s
    
r  c             C   s@   |d kri }|d kri }t | }t|||\}}t|  ||fS )N)r  r2   r  )rq   r  Zreverse_call_tabler.  rY   rY   r]   get_parfor_call_table  s    
r  c             C   s,   |d kri }t | }t||}t|  |S )N)r  r   Zget_tuple_tabler  )rq   Ztuple_tabler.  rY   rY   r]   get_parfor_tuple_table  s    r  c             C   s.   |d krt  }t| }t||}t|  |S )N)r  r  r   Zget_array_accessesr  )rq   Zaccessesr.  rY   rY   r]   get_parfor_array_accesses  s    r  c             C   s6   t | }t||}|| |d< || t| | d S )Nr   )r  r7   r  r  )rq   r  r.  rY   rY   r]   parfor_add_offset_to_labels  s    


r  c             C   s   t | }t|}t|  |S )N)r  r   rp  r  )rq   r.  Z	max_labelrY   rY   r]   parfor_find_max_label(  s    
r  c                s   |j }t| }dd | jD }t| }|| j  fdd|D }|| j}||| j || _||_ |  ||_ ||| _t|  d S )Nc             S   s   g | ]
}|j qS rY   )r   )r[   rb   rY   rY   r]   r^   4  s    z$parfor_typeinfer.<locals>.<listcomp>c          	      s&   g | ]}t t jd  dd| qS )ro   F)r   Zuse_literal_type)r
   r  r  )r[   r;  )r   rY   r]   r^   :  s    )	r.  r  r   rx   r9  r   r  Zbuild_constraintr  )rq   ZtypeinfererZsave_blocksr.  r  Zfirst_blockZindex_assignsZsave_first_block_bodyrY   )r   r]   parfor_typeinfer1  s    


r  c             C   s0   |dkrt t}t| j| td| ji| |S )z)get variable definition table for parforsNr   )r   r  r?   r   r   )rq   ZdefinitionsrY   rY   r]   build_parfor_definitionsF  s
    r  c          	   c   sD   t |  }| | jtdtdd dV  | | j  dS )zLadds dummy return to last block of parfor loop body for CFG computation
    r   r  rK  N)r   r9  r  r   r
   r  r  r  )r   r|  rY   rY   r]   r0  S  s
    
r0  c               @   s   e Zd Zdd ZdS )ReduceInferc             C   s@   |rt t|dkst t|d tjs,t t|d jf| S )Nr   ro   )r   rs   r   r   r   rN   rw   )r   rj   rV  rY   rY   r]   generica  s    zReduceInfer.genericN)rl   rm   rn   r  rY   rY   rY   r]   r  _  s   r  c              C   s:   t j} tj }t j}| o|}|}|s(|r6d}t|dS )zKCheck if the platform supports parallel=True and raise if it does not.
    z{The 'parallel' target is not currently supported on Windows operating systems when using Python 2.7, or on 32 bit hardware.N)r   ZIS_WIN32r   ZIS_PY3Z	IS_32BITSr   ZUnsupportedParforsError)Zis_win32Zis_py2Zis_32bitZuns1Zuns2rl  rY   rY   r]   ensure_parallel_supporth  s    r  )NNNNN)NN)T)T)N)N)F)NN)N)N)N)r   Z
__future__r   r   r   r   Zpytypesr	  r   r  textwrapr5  r  	functoolsr   collectionsr   r   r   
contextlibr	   rO  rp   r
   r   r   r   r   r   r   r   r   r   r   r   r   Znumba.numpy_supportr   Znumba.typing.templatesr   r   r   Znumba.stencilparforr   Znumba.extendingr   Znumba.ir_utilsr   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   Znumba.analysisrH   rI   rJ   rK   Znumba.controlflowrL   Znumba.typingrM   rN   Znumba.types.functionsrO   Znumba.array_analysisrP   rQ   rR   rS   rT   rU   rV   r   r   r  ZTextWrapperr`   rc   r  rd   rf   r  rg   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   rr   r   r   r   r  r   r  ZStmtr   r  Zarray_analysis_extensionsr  r  r  r  rX  rY  rE  re  rg  rf  r  rq  ru  r  rw  rv  r}  r~  r  r  r  r  r  Zvisit_vars_extensionsr  Zir_extension_usedefsr  Zir_extension_insert_delsr  r  r  r  r  r  r  r`  r  r  r  r  r  r  r  Zremove_dead_extensionsr  r  r  Zalias_analysis_extensionsr  r  r  r  Zcopy_propagate_extensionsr  Zapply_copy_propagate_extensionsr  r  rF  r  r  Zcall_table_extensionsr  Ztuple_table_extensionsr  Zarray_accesses_extensionsr  Zadd_offset_to_labels_extensionsr  Zfind_max_label_extensionsr  Ztypeinfer_extensionsr  Zbuild_defs_extensionsr0  r  r  rY   rY   rY   r]   <module>   sZ  ,, -b
     $         (nJF  
<%


4
.


	G+_ 






*


	



	




