
    9jn                        d dl Z d dlZd dlmZmZ d dlmZ d dlmZm	Z	m
Z
mZmZ d dlZd dlZd dlmZ d dlmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZ ddlmZ  ed      Z ed      Z e!ejD                  df   Z#e!e$ejJ                     e$ejD                     f   Z&ejN                  jQ                  e)d      Z*d dlm+Z+m,Z, e
rd dl-m.Z.m/Z/ dejD                  dejD                  dz  fdZ0dejD                  dejD                  dz  fdZ1dejD                  de2ejD                  e3f   dejD                  dz  fdZ4dejD                  de2ejD                  e3f   dejD                  dz  fdZ5dejD                  de6fdZ7 e jp                  d       G d d              Z9e	d!d"d#ejD                  d$ejD                  d%ed   de!e&e&f   dz  f
d&       Z:e		 dBd!d"d#ejD                  d$ejD                  d%ed'   de!e&e&f   f
d(       Z:	 dBd!d"d#ejD                  d$ejD                  d%e6de!e&e&f   dz  f
d)Z: G d* d+      Z;d,e$ejJ                     d-e$ejJ                     d.e$ejJ                     d/e$ejJ                     d0e$e$ejD                        d1e$e$ee$ejD                     gejD                  f         de2ejJ                  ejD                  f   fd2Z<d3ed   de9dz  fd4Z=d5ejD                  de2ejJ                  e3f   d6ee>   de3fd7Z?d8e>de3dz  fd9Z@d:ejD                  e3z  de3fd;ZA e jp                  d       G d< d=             ZB e jp                  d       G d> d?             ZCd@ed   deCdz  fdAZDy)C    N)Counterdefaultdict)Callable)LiteraloverloadTYPE_CHECKINGTypeVarUnion)index_vars_no_squeeze)sympy_product
sympy_subs)
OrderedSet)Identity)	try_solve)symbol_is_typeSymT   VTU.loop_tiling)FloorDivModularIndexingFusedSchedulerNodeSchedulerNodeexprreturnc                    | j                         ryt        | t              ryt        | j                        dk(  sJ t        t        | j                              }t        | t              r;t        t        j                  | j                  d   | j                  d         |      }n t        t        j                  | d      |      }|r|d   j                         sy|d   S )zw
    Given an expr with a single free symbol, solve for a constant relation that would make
    this expression 0.
    Nr   r      )is_constant
isinstancer   lenfree_symbolsnextiterr   r   sympyEqargs)r   free_symbolouts      \/media/conek/DATA/Code/OCR/venv/lib/python3.12/site-packages/torch/_inductor/tiling_utils.pysolve_for_zeror.   $   s    
 	D(	#t  !Q&&&tD--./K$(1tyy|<kJq);7c!f((*q6M    c           	         t        | j                        dk7  ryt        t        | j                              dt        j
                  dt        j
                  dz  ffd}| j                  t              s| j                  t              s ||       S g }g }t        j                  j                  |       D ]x  }t        |t        j                        rKd}|j                  D ]5  }t        |      }||j                         sJ d}|j!                  |       7 |rf y|j!                  |       z |syt#        |      }	 ddt        j
                  d	t        j
                  d
t        j
                  dz  dt        j
                  fd}	|j%                  t        |	      j%                  t        |	      }
 ||
      }|rt'        ||i      dk7  ry|j!                  |       t        t)        |            dk(  r|d   S y)a  
    Giving an expr with a single free symbol, try to find a tiling that would
    make the expression coalesced with respect to that symbol.

    Tiling an expression `x` by `y` means that the expression will now be indexed
    by both the original (x) and by (x * y). So we are looking for a
    multiplicative factor that will make ((x + 1) * y) - (x * y) == 1.

    To simplify things for sympy, we'll try just x * y == 1, check x(1) and x(0).
    r   Nr   r   c                    | j                  t              s| j                  t              rJ t        | j                        dk7  ry t        t        j                  | d            }|r|d   j                         sy |d   S )Nr   )	hasr   r   r$   r%   r   r(   r)   r"   )r   r,   r+   s     r-   _solve_simple_exprz,solve_for_tiling.<locals>._solve_simple_exprJ   sk    88O,TXXh5GGGt  !Q&q);7#a&,,.1vr/   FTxyzc                     | |z  S N )r4   r5   r6   s      r-   indexing_div_repz*solve_for_tiling.<locals>.indexing_div_repw   s    
 1ur/   r   r8   )r$   r%   r&   r'   r(   Exprr2   r   r   Add	make_argsr#   Mulr*   r.   r"   appendsumreplacer   r   )r   r3   required_valueseq_1_expressionsargseenmul_argr,   	eq_1_exprr:   eq_1_expr_simplifiedr+   s              @r-   solve_for_tilingrI   9   s    4"tD--./K 

T0A  88O$TXXh-?!$''O
 yy""4( )c599%D88 ,$W-;(((&&s+, ##C(#)& $%I
  $:::: :: 
	 %,,_>NOWW" 1
2C *Yc(:;q@3
:o&'1,q!!r/   index
var_rangesc                 *   i }| j                   D ]  }||v rd||<   t        |      ||<    t        | |      }|D ]1  }|| j                   vrd||<   	 t        | |      }||k(  r|c S d||<   3 y# t        $ r t        j                  d| |       Y Ww xY w)z
    Try to find the variable that this index is broadcast over.
    A broadcast pattern is one where consecutive values of a variable
    access the same memory location (e.g., x // 10).
    r   r   zero division error %s %sN)r%   get_hintr   ZeroDivisionErrorloop_tiling_loginfo)rJ   rK   	variablesv
zero_indexnew_vals         r-   find_broadcast_varrV      s     *,I '
?IaL#A;IaL	' E9-J E&&&	!	 	2G
 j H	!  ! 	  !<eYO	s   A// BBc                    t         j                  j                  |       }|D ]
  }||v s|c S  i }| j                  D ]  }||v rd||<   t	        |      ||<    t        | |      }|D ]<  }d||<   	 t        | |      }||z
  dk(  rd||<   t        | |      |z
  dk(  r|c S d||<   > y# t        $ r t        j                  d| |       Y bw xY w)z;
    Try to find the symbol which coalesces this index
    r   r   rM   r!   N)	r(   r<   r=   r%   rN   r   rO   rP   rQ   )rJ   rK   top_level_termsrS   rR   rT   rU   s          r-   find_coalesced_varrY      s    ii))%0O H
 *,I '
?IaL#A;IaL	' E9-J 	!	 	2G Z1$IaL 5),w61<	!  ! 	  !<eYO	s   1B(( C
Cmemory_exprc                 :    t        d | j                  D              S )zD
    Check if this memory expression has any indirect indexing.
    c              3   P   K   | ]  }t        |t        j                           y wr8   )r   r   INDIRECT.0ss     r-   	<genexpr>z&has_indirect_access.<locals>.<genexpr>   s     RA~a/Rs   $&)anyr%   )rZ   s    r-   has_indirect_accessrc      s     R9Q9QRRRr/   T)frozenc                       e Zd ZU dZeej                     ed<   eej                     ed<   eej                  ee
   f   ed<   eej                  ee
   f   ed<   eej                  ef   ed<   y)FusedNormalizedReadsWriteszO
    Normalized reads and writes for nodes in the same FusedSchedulerNode.
    
index_varsreduce_varsreadswritesrK   N)__name__
__module____qualname____doc__r   r(   Symbol__annotations__dictr;   strintr9   r/   r-   rf   rf      sk     5<<((ELL))

JsO+,,Z_,--U\\3&''r/   rf   nr   pointwise_numel	red_numelnone_if_not_divisiblec                      y r8   r9   rt   ru   rv   rw   s       r-   get_pw_red_splitsrz      s     25r/   Fc                      y r8   r9   ry   s       r-   rz   rz      s     +.r/   c                 R   | j                         sJt        j                  j                  j	                  t        | j                  j                  d         |      r^| j                  j                  | j                  j                  d   f| j                  j                  | j                  j                  d   ffS t        t        | j                  j                  d               t        ||z        k(  sJ t        | j                  j                  d         dz
  }d}|dk\  r0|| j                  j                  d   |   z  }||k(  rn|dz  }|dk\  r0|dk\  rr| j                  j                  d   d| }| j                  j                  d| }| j                  j                  d   |d  }| j                  j                  |d  }	||f|	|ffS |ry | j                  j                  | j                  j                  d   f| j                  j                  | j                  j                  d   ffS )Nr   r   )is_reductionr   graphsizevarsstatically_known_equalsr   _bodysizes	iter_varsrh   rN   r$   )
rt   ru   rv   rw   iprod	pw_splitsr   
red_splitsred_varss
             r-   rz   rz     s    	~~177++CCaggmmA&'
 WWa 01WW  !''--"23
 	

 M!''--"234)#9    	AGGMM!!AD
q&a ##9	Q	 q& 	AvGGMM!$Qq)	GG%%a*	WW]]1%ab)
77$$QR(9%*'=== WWa 01WW  !''--"23
 	
r/   c                   \    e Zd ZdZded   fdZdeeef   fdZdededeeef   d	z  fd
Z	y	)NodeSplitGetterz_
    Finds a Pointwise, Reduction Split that compatible with all nodes in a SchedulerNode.
    noder   c                 n   || _         |j                  d   d   | _        |j                  d   d   | _        t	        t
              | _        t	        t
              | _        d| _        t               | _	        |j                  d   }t        |j                               D ]  }t        |t        j                  j                  j                         s3t#        || j                  | j                  d      }|0| j                  j%                  |j&                  j(                         |\  \  }}\  }}t        j                  j*                  j,                  j.                  j1                  |||f| j                        \  }}| j                  t3        |         j%                  t5        |             | j                  t3        |         j%                  t5        |             |dk7  rt7        |      f| _        t5        |      t5        |      f}| j                  j%                  |        t               | _        y )Nr   r   r9   T)rw   )r   groupru   rv   r   r   pw_split_optionsred_split_optionsreduction_splitall_node_sizesreversed	get_nodesr#   torch	_inductor	schedulerr   rz   addr   r   codegensimd
SIMDKernelprepare_split_iteration_lengthsr$   tupler   seen_pw_splits)	selfr   fused_grouprt   maybe_splits_n_pw_splitsn_red_splitsn_sizes	            r-   __init__zNodeSplitGetter.__init__6  s    	+/::a=+;%)ZZ]1%5>I*>U?J:?V&(?I|jjm$..*+ 	,Aa!:!:!H!HI
 -4''tL ###''62>/Q/q, '',,77WW+|!<dnn &K !!#k"2377k8JK""3|#4599%:MNr!(5l(C'E$K(%*=>F##F+=	,@ 2<r/   r   c                 2   t        | j                        dk(  rt        t        | j                              S t        | j                        dk(  r| j
                  f| j                  ffS t        | j                  j                               }t        | j                  j                               }dt        t        t        t           f   dt        ddfd}||z   }t        t        |dd            D ]  \  }}t        |dd      D ]K  }| j                  |   D ]7  }| j                  ||z
     D ]   }	| j!                  ||	      x}
s|
c c c c S  9 M  || j                  ||z
          || j                  ||z
          | j
                  f| j                  ffS )	zI
        Get a compatible pointwise, reduction split of the node
        r   r   split_optionscurr_lengthr   Nc                     | |   D ]e  }t        t        |      dz
        D ]I  }t        |d| t        |||dz          fz   ||dz   d  z         }| t        |         j	                  |       K g y )Nr   r   r!   )ranger$   r   r   r   )r   r   splitr   	new_splits        r-   add_combined_split_optionszCNodeSplitGetter.get_node_splits.<locals>.add_combined_split_optionsu  s     '{3 As5zA~. AA %a
mE!a!e4D&E%GG%PQTUPUPW.X!I "#i.155i@	AAr/   )r$   r   r&   r'   r   ru   rv   maxkeysr   rq   rs   r   Split	enumerater   	try_split)r   max_pw_splitmax_red_splitr   max_total_splits	curr_itertotal_splitspw_split_lenpw_split	red_splitr,   s              r-   get_node_splitszNodeSplitGetter.get_node_splitsg  s   
 t""#q(T00122t$$%*))+dnn->??4005578D22779:	AZ%6 67	AFI	A	A (-7'07GB1O'P 	#I| %lAr : ' $ 5 5l C 'H%)%;%;$|3& '	 #'..9"EE3E#&JJ	''' 't'<'<lY>VW&&&	(A	 %%'$..):;;r/   pwredNc                    ddl m}m} || j                  v ry| j                  j	                  |       | j
                  D ]  \  }}	 ||z   }||f}|j                  ||      \  }	}
t        |
      dk(  sJ |	dt        |       }t        t        j                  j                  |            }||k7  sq| j                  ||      x}s|c S  ||fS # |$ r Y  yw xY w)zs
        See if this split is compatible, and potentially returning a longer split
        than the input.
        r   )	CantSplitr   Nr!   )torch._inductor.codegen.simdr   r   r   r   r   _split_iteration_rangesr$   r   	itertoolschainfrom_iterabler   )r   r   r   r   r   n_pwn_redgroupslengthssplitsgetterspw_group_splitsflattened_pw_splitsr,   s                 r-   r   zNodeSplitGetter.try_split  s     	G$$$#.. 	KD%c-","D"DVW"U w<1$$$$Ys2w/O
 #(	(E(Eo(V"W"b(..)<cBB3BJ#	& 3w  s   CCC)
rk   rl   rm   rn   r
   r   r   r   r   r   r9   r/   r-   r   r   1  sY    />9:/>b(<ue|!4 (<TE  %u2E2L r/   r   r   r   norm_pw_varsnorm_red_vars
new_rangesreturn_getters_groupsc           	         t        d |D              }t        j                  d|       }d}t        |       dk(  rt        |      dk(  ri S t        |      t        ||z         k(  sJ g }	|D ]'  }
|	j	                  |
D cg c]
  } ||       c}       ) i }t        t        |	| |fd            D ]f  \  }\  }
}t        |
      t        |      k7  r|dk(  sJ t        |      dk(  sJ 8|j                  t        |
|      D ci c]  \  }}||
 c}}       h d}i }t        |||z   d      D ]l  \  }}g }t        t        |            D ]  }|j	                  ||          |dz  } d}t        t        |      dz
  dd      D ]  }||z  |||   <   ||   |z  } n |j                         D ci c]  \  }}|t        ||       c}}S c c}w c c}}w c c}}w )zBMaps original variables to expressions using normalized variables.c              3   2   K   | ]  }t        |        y wr8   )r$   r^   s     r-   ra   z$apply_var_mapping.<locals>.<genexpr>  s     .a3q6.s   zv_0:r   T)strictr   r   )r@   r(   symbolsr$   r?   r   zipupdater   itemsr   )r   r   r   r   r   r   num_vars	flat_varscountapply_groupsr   giter_vars_to_flat_varsr   	var_grouprS   flat_vars_to_new_vars	new_rangenew_var
range_varsr   r   ks                          r-   apply_var_mappingr     s'   . .:..HXJ/0IE
9~s8}1	z?c,">????L& ;59aQy\9:;  !*L9h/=" 
PE9
 u:Y'6M6y>Q&&&%%E98M&N1q!t&NO
P E!L=0 '	7 
s9~& 	Ai./QJE	 s9~)2r2 	'A3:T>!*Q-0Q<$&D	'' +002Aq 	
:a.// = : 'O"s   =G
G0Gr   c           
      ^	  ) t        t              }t        t              }| j                         }| j                         }t               }t               )|D ]O  }t        j
                  j                  j                  ||      r)j                  |       ?|j                  |       Q t        )fd| j                  j                  D              }| j                  d   d   }| j                  d   d   }	t        |       j                         \  }
}t        |
|d      \  \  }}}t        | j!                               D ]G  }t#        |t$        j&                  j                  j(                        s3|j*                  }t        t              }t        t              }|D ],  }|j-                  |      D ]  }||   j                  |        . |D ],  }|j/                  |      D ]  }||   j                  |        . |s|st1        |||	      \  \  }}\  }}|
|z   }||f}t$        j&                  j2                  j4                  j6                  j9                  |||	      }	 t$        j&                  j2                  j4                  j6                  j;                  ||      \  }}tA        ||||||      }dtB        jD                  dtB        jD                  fd	}|jG                         D  !ci c]  \  } }!tI         ||       |      |! }"} }!|jG                         D #!ci c]  \  }#}!tI         ||#      |      |! }$}#}!|"jG                         D ]  \  }}%||xx   |%z  cc<    |$jG                         D ]  \  }}%||xx   |%z  cc<    J |jG                         D &!ci c]0  \  }&}!t        j
                  jJ                  jM                  |&|      |!2 }}&}!|jG                         D '!ci c]0  \  }'}!t        j
                  jJ                  jM                  |'|      |!2 }}'}!tO        |||||      }(tP        jS                  d
|(       |(S # t$        j&                  j2                  j4                  j<                  $ r |j>                  s|	j>                  sJ Y  yw xY wc c}!} w c c}!}#w c c}!}&w c c}!}'w )zjExtracts index variables, reduce variables, read/write expressions, and variable ranges from a fused node.c              3   T   K   | ]  }|j                   vs|j                    ! y wr8   )name)r_   depremoved_bufferss     r-   ra   z1extract_normalized_read_writes.<locals>.<genexpr>	  s%      chho6Us   ((r   r   rt   )prefixNr   r   c                 0    | j                  t        d       S )Nc                     | S r8   r9   )r4   s    r-   <lambda>zIextract_normalized_read_writes.<locals>.remove_identity.<locals>.<lambda>P  s    A r/   )rA   r   )r   s    r-   remove_identityz7extract_normalized_read_writes.<locals>.remove_identityO  s    <<+66r/   zNormalized Fused reads: %s)*r   r   get_buffer_namesget_operation_namesr   r~   r   $can_buffer_be_removed_through_fusionr   read_writesri   r   r   r   r   listr   r#   r   r   r   r   get_all_read_exprget_all_write_exprrz   r   r   r   r   r   r   r%   r   r(   r;   r   r   r   simplify_with_rangesrf   rP   rQ   )*r   ri   rj   all_output_namesop_namesoutputsbuf_nameinputsru   rv   r   r   r   r   rangesrt   bodyn_readsn_writesinpr   r,   r   r   r   r   r   r   r   r   var_mapr   readrS   n_reads_newwriten_writes_new	buf_namesrw	fused_outr   s*                                            @r-   extract_normalized_read_writesr    s    0;:/FE0;J0GF,,.'')H)|G'1|O$ "77AA(HU)KK!	"   ,,22 F #'**Q-"2O JJqM!,I+D1AACIz -B:c-)!\=6 $.."# G&!U__66DDEww5@5L6A*6M  	'C..s3 '!!#&'	'  	(C//4 (""3'(	( x=N	>
: K":8\ Z'/OO##((33SS 	

	'',,77OOG .J- $!
	7%** 	7 	7 JQ
>EdAJt,g69
 

 %NN,
q u-w7:
 

  +002 	%OD)$K9$K	%  ,113 	&OD)4LI%L	&MG&T IN@D1--a8!;E  IO@D1--a8!;F  +I 5yAc &&++55 	 #//93I3III		(

s,    AQ(RR5R#&5R)ARRaddrr  c                    g }| j                   D ]B  }|j                  |      }t        |t        j                        r/|2|j                  |       D ddlm} |j                  j                  j                  t        |            S )z7
    Score addr according to its approximate size.
    r   r   )r%   getr   r   r]   r?   virtualizedr   r~   r   optimization_hintr   )r  rK   r  	var_sizesrS   v_sizer   s          r-   	get_scorer  r  sr     I %"a/F4FV$	%
 77--mI.FGGr/   r   c                     t         j                  j                  |       }|sy t         j                  j                  j	                  t        |j                                     S r8   )r   r~   try_get_bufferr   r  r   get_size)r   bufs     r-   try_get_buf_sizer    sB    
''
 
 
*C77--mCLLN.KLLr/   rS   c                 x    t        | t              r| S t        j                  j                  j                  |       S r8   )r#   rs   r   r~   r   r  )rS   s    r-   rN   rN     s,    !Sww11!44r/   c                   D    e Zd ZU dZej
                  ed<   eed<   eed<   y)	VarTilingzm
    Tiling of a var by `tiling_factor` that yields additional coalesced mem accesses by `benefit_score`
    vartiling_factorscoreN)rk   rl   rm   rn   r(   ro   rp   rs   r9   r/   r-   r  r    s     
Jr/   r  c                   |    e Zd ZU eej
                  ef   ed<   eej
                  ef   ed<   eed<   dZ	e
dz  ed<   y)CoalesceVarAnalysiscoalesced_by_varuncoalesced_addrsnorm_read_writesNsuggested_split)rk   rl   rm   rq   r(   r;   rs   rp   rf   r$  r  r9   r/   r-   r   r     s?    
 5::s?++EJJO,,00(,OY%,r/   r   
fused_nodec           
      l   t        |       }|y|j                  }|j                  }|j                  }t	               }t	               }t        j                  d |j                         D        d |j                         D              D ]  \  }\  }}	t        |||	      }
|
dk(  rt        |      }|rd}nt        ||      }|t        ||      }d}|	D ]X  }t        j                  j                  |      x}s%t        |      x}s3|t!        ||
      |j"                  j$                  z  z  }Z ||rdndz  }|r||xx   |z  cc<   ||xx   |z  cc<    |st'        |||      S t)        t              }|j                         D ]"  \  }}t        |      rt*        j-                  |j/                         d      }|j0                  |j/                         z  D ]  }||vr|dk(  r||= t3        ||      }d||<   t5        |j0                        dk7  r;t7        |      }||j9                         r|j:                  set=        |      }t        j                  j>                  jA                  |||         sdtC        fd	|||   |z  fD              s||   |xx   |z  cc<    % t5        |      dk(  rt'        |||      S d}d}|j                         D ])  \  }}|j                         D ]  \  }}||kD  s||f}|} + |t'        |||      S t'        |||tE        |d   |d   |      
      S )a[  
    Find variables that coalesce the reads and writes and score the total size.

    If uncoalesced memory expressions are found, look for additionally tiling of variables
    which will coalesce memory accesses.

    For instance - for the following expression:

    (32*p0) // 2048

    Tiling p0 by 64 will make this expression coalesced.
    Nc              3   $   K   | ]  }d |f 
 yw)TNr9   r_   items     r-   ra   z,analyze_memory_coalescing.<locals>.<genexpr>  s     0$$0   c              3   $   K   | ]  }d |f 
 yw)FNr9   r(  s     r-   ra   z,analyze_memory_coalescing.<locals>.<genexpr>  s     24%2r*  r   r   r!   )r!  r"  r#     c              3   r   K   | ].  }t         j                  j                  j                  |       0 y wr8   )r   r~   r   statically_known_lt)r_   blockMIN_TILING_BLOCKs     r-   ra   z,analyze_memory_coalescing.<locals>.<genexpr>  s1         445EuMs   47)r!  r"  r#  r$  )#r  ri   rj   rK   r   r   r   r   r  rc   rY   rV   r   r~   r  r  mindtypeitemsizer   r   rq   fromkeysr   r%   r   r$   rI   r"   
is_integerrs   r   r.  allr  )r%  r#  ri   rj   rK   r!  r"  is_readrZ   r  sizeindirect_exprmaybe_coalesced_vartotal_scorer   r  buf_sizetiling_scoresuncoalesced_expr
addr_score	expr_subsrS   single_var_exprr  best_tilingbest_tiling_scorer  tiling_countertile
tile_scorer0  s                                 @r-   analyze_memory_coalescingrG    s     6jA""E$$F!,,J07	/6y-6__0%++-026<<>2. %:))+y
 j)<19 ,K8"&"4[*"M #*&8j&Q#! 	HHww--h777,X666 s8T2SYY5G5GGG	H 	Gq*01[@1k*k9*K%:N "-/-
 	
 7B'6JM(9(?(?(A +:$*/0MM*//"3Q7	!..1BB &	:A
"Q!()99EOIaL?//0A5,_=M %$002$//.M77##77zRS}U
  ! +Z]m-KL  !]+z9+M&	:+:Z =Q"-/-
 	
 26K,224 /^ . 4 4 6 	/D*--"Dk$.!	// "-/-
 	
 )+)!+a.+a.BST	 r/   )F)Edataclassesr   collectionsr   r   collections.abcr   typingr   r   r   r	   r
   r(   r   torch._inductor.dependenciesr   torch._inductor.utilsr   r   torch.utils._ordered_setr   torch.utils._sympy.functionsr   torch.utils._sympy.solver   torch.utils._sympy.symbolr   r   r  r   r   r   r   r;   r   r   ro   VarsAndRanges_logginggetArtifactLoggerrk   rP   r   r   torch._inductor.schedulerr   r   r.   rI   rq   rs   rV   rY   boolrc   	dataclassrf   rz   r   r   r  rr   r  r  rN   r  r   rG  r9   r/   r-   <module>rX     sk     , $ C C   > ; / 1 . :  CLCL 	ejj#od5<<($uzz*::; ..228]K B K 

T(9 *W5:: W%**t*; Wt :: #'

C#8 
ZZ$ F#::##'

C#8#
ZZ$#LSUZZ SD S d#	( 	( $	( 
55ZZ5 zz5 #4=	5
 =-'(4/5 
5 

 -2	..ZZ. zz. #5>	.
 =-'(. 
. #(	,
,
ZZ,
 zz,
  	,

 =-'(4/,
^ DBELL!B5<< B u||$B %	B
 T%**%&B  XtEJJ/?.@%**.L%M NOB 
%,,


"#BJw
5
6w$&wtH
**H"&u||S'8"9HFPQToHH$Ms MsTz M5

S  5S 5 d#  $ d#
- 
- $
-Z;<Z4Zr/   