
    #jn                        d dl mZmZ  e            r
ddlZddlmZ ddlmZ d dlmZm	Z	 d dl
mZmZ  ej        e          Zg dZed	             Z G d
 de          Z G d de          Z G d de          Z G d de          Zd Zd Zej        dddej        dedej        fdZej        dddej        dedej        fdZ G d dej                  Zd Z d Z!d Z"d  Z#d! Z$d" Z%d%d#e&e'         dz  fd$Z(dS )&   )is_torch_availablelogging    N)nn)contextmanager)ConversionOps_IdentityOp)get_module_from_nameshould_convert_module)g        g      ?g      ?g      ?g       @g      @g      @g      @g       g      g      g      g       g      g      g      c              #     K   t                      rdd l}t          | |j                  r| j        } n%t          | t
                    r |j        |           } t          | dd           }|dk    r8|j                            |           5  d V  	 d d d            d S # 1 swxY w Y   |dk    rHt          |d          r8|j	                            |           5  d V  	 d d d            d S # 1 swxY w Y   d V  d S )Nr   typecudaxpu)
r   torch
isinstanceTensordevicestrgetattrr   hasattrr   )devr   dev_types      i/lsinfo/ai/hellotax_ai/base_platform/venv/lib/python3.11/site-packages/transformers/integrations/mxfp4.py	on_devicer   1   s      c5<(( 	$*CCS!! 	$%,s##C3--v""3''                  u!6!6!!#&&                  
EEEEEs$   BB"BC))C-0C-c                       e Zd Zd Z	 	 	 d	deeej        f         dej        j	        dz  de
e         dz  dedz  deeej        f         f
dZdS )
Mxfp4Quantizec                     || _         d S Nhf_quantizerselfr    s     r   __init__zMxfp4Quantize.__init__H       (    N
input_dictmodelmissing_keysfull_layer_namereturnc                 J   t          |                                          d         \  }}t          |t                    r|d         n|}t	          ||          \  }}t          j        |j                  5  t          |t                    rt          |	                    dd          t                    \  }	}
t          j        j        t          j        j        t          j        j        }}}t          |	|
t                    \  }	}
d|v rdnd}||j        v r|j        |= t#          |||	           t#          || d ||
 | |                                           |                    |            d	|_        i cd d d            S 	 d d d            d S # 1 swxY w Y   d S )
Nr   gate_up_proj	down_proj_precision_configrhs_dataweight_scaleflex_ctxT)tupleitemsr   listr
   r   r   Mxfp4GptOssExpertsquantize_to_mxfp4	transposetriton_kernels_hub
matmul_ogsPrecisionConfigFlexCtx
InFlexDataswizzle_mxfp4_parameterssetattrdiscard_is_hf_initialized)r"   r&   r'   r(   r)   kwargs_valuemoduletriton_weight_tensorr4   r>   r?   r@   projs                  r   convertzMxfp4Quantize.convertK   s%    ))++,,Q/5&ud33>a(@@	\%,'' 	 	&"455 5FuWY[]G^G^`r5s5s2$l&1A&19&1< +5
 6C(,8J6 62$l *8?)J)J~~P[6---*40&:;;;...#OYcYcYeYeHfHfHfggg   $$%9:::,0)9	 	 	 	 	 	 	 		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   6DFFFNNN__name__
__module____qualname__r#   dictr   r   r   r   Moduler8   rL    r%   r   r   r   G   s        ) ) ) )-)-&*) )el*+) x%) 3i$&	)
 t) 
c5<	 ) ) ) ) ) )r%   r   c                       e Zd Zd Z	 	 	 ddeeej        f         dej        j	        dz  dedz  de
e         dz  deeej        f         f
dZedd
            ZdS )Mxfp4Dequantizec                     || _         d S r   r   r!   s     r   r#   zMxfp4Dequantize.__init__x   r$   r%   Nr&   r'   r)   r(   r*   c                    i }d|v rdnd}| d|                                 v rGt          || d         t                    r|| d         d         || d<   n|| d         || d<   | d|                                 v rGt          || d         t                    r|| d         d         || d<   n|| d         || d<   t          || d         || d                   }||iS )Nr.   r/   _blocksr   _scales)keysr   r8   dequantize_convertops)	r"   r&   r'   r)   r(   rF   
param_datarK   dequantizeds	            r   rL   zMxfp4Dequantize.convert{   sg    
!/?!B!B~~z0000*%5%5%56== L/9T:J:J:J/KA/N
d+++,,/9T:J:J:J/K
d+++,z0000*%5%5%56== L/9T:J:J:J/KA/N
d+++,,/9T:J:J:J/K
d+++, ,J$7G7G7G,H*X\UeUeUeJfgg--r%   r   c                     t                      S r   )r	   r"   s    r   
reverse_opzMxfp4Dequantize.reverse_op   s    }}r%   rM   )r*   r   )rO   rP   rQ   r#   rR   r   r   r   r   rS   r8   rL   propertyra   rT   r%   r   rV   rV   w   s        ) ) ) )-&*)-. .el*+. x%. t	.
 3i$&. 
c5<	 . . . .2    X  r%   rV   c                       e Zd Zd Z	 	 	 d
deeej        f         dej        j	        dz  dedz  de
e         dz  deeej        f         f
dZedefd	            ZdS )Mxfp4Deserializec                     || _         d S r   r   r!   s     r   r#   zMxfp4Deserialize.__init__   r$   r%   Nr&   r'   r)   r(   r*   c           	      l   i }d|v rdnd}| d|                                 v rGt          || d         t                    r|| d         d         || d<   n|| d         || d<   | d|                                 v rGt          || d         t                    r|| d         d         || d<   n|| d         || d<   t          ||          \  }}	t	          || d         || d         |||| d         j        t                     |                    |            d|_        i S )Nr.   r/   rY   r   rZ   T)	r[   r   r8   r
   swizzle_mxfp4_convertopsr   r<   rD   rE   )
r"   r&   r'   r)   r(   rF   r]   rK   rI   rG   s
             r   rL   zMxfp4Deserialize.convert   s    
!/?!B!B~~z0000*%5%5%56== L/9T:J:J:J/KA/N
d+++,,/9T:J:J:J/K
d+++,z0000*%5%5%56== L/9T:J:J:J/KA/N
d+++,,/9T:J:J:J/K
d+++, )@@	 $'''($'''($'''(/	
 	
 	
 	1222$(! 	r%   c                 *    t          | j                  S r   )Mxfp4ReverseDeserializer    r`   s    r   ra   zMxfp4Deserialize.reverse_op   s    &t'8999r%   rM   )rO   rP   rQ   r#   rR   r   r   r   r   rS   r8   rL   rb   r   ra   rT   r%   r   rd   rd      s        ) ) ) )-&*)-% %el*+% x%% t	%
 3i$&% 
c5<	 % % % %N :M : : : X: : :r%   rd   c                       e Zd Zd Z	 	 	 d	deeej        f         dej        j	        dz  dedz  de
e         dz  deeej        f         f
dZdS )
ri   c                     || _         d S r   r   r!   s     r   r#   z Mxfp4ReverseDeserialize.__init__   r$   r%   Nr&   r'   r)   r(   r*   c                 R   t          |j        dd          }t          |j        dd          }d|v rdnd}|                    dd          d	         }	t          ||          \  }
}i }t	          |
t
                    rd
|v r.|                    dd          }	t          |
|dz             ||	<   |S d|v r|
j        j        j	        
                    |
j        j        j                                      dd                              |ddd          ||	 d<   |
j        j        j        j	        
                    |
j        j        j        j                                      dd          ||	 d<   n|
j        j        j	        
                    |
j        j        j                                      dd                              ||dd          ||	 d<   |
j        j        j        j	        
                    |
j        j        j        j                                      dd          ||	 d<   |S )Nnum_local_experts    hidden_sizei@  r.   r/   rG      r   biasrY    _biasr,   r-   Z      rZ   )r   configrsplitr
   r   r9   replacer.   storagelayoutunswizzle_datadatar;   reshapegate_up_proj_precision_configr4   r/   down_proj_precision_config)r"   r&   r'   r)   r(   rF   rm   ro   rK   namerI   rG   
state_dicts                r   rL   zMxfp4ReverseDeserialize.convert   s0    $EL2ErJJelM4@@!/?!B!B~~%%c1--a0(@@	
f011 	((&..y"==#*64'>#B#B
4 !!00'/6EEfFYFaFfggYr2&&W.B;; d+++, 8EMTcc<IQV iB'' d+++,, $,3BB6CSC[C`aaYr2&&W.RDD d+++, 5BJQ``9FNS iB'' d+++, r%   rM   rN   rT   r%   r   ri   ri      s        ) ) ) )-&*)-, ,el*+, x%, t	,
 3i$&, 
c5<	 , , , , , ,r%   ri   c                     |j         j        j        } ||                     t          j                  t          j        d          \  } }| |fS )Nrp   )axis)numerics_detailsmxfpdowncast_to_mxfp_torchtor   bfloat16uint8)wr<   r   w_scales       r   r:   r:      sG    /@E\''U^(<(<ekPQRRRJAwg:r%   c                    |j         j        |j         j        |j         j        }}}|j        j        }|j        j        j        }|                    d          \  }}	 | || |          |fi |	}  | ||          |          }| |fS )zE
    Changes the layout of the tensors depending on the hardware
    rp   )mx_axisdtype)tensorFP4convert_layoutwrap_torch_tensortensor_detailsrz   StridedLayout"make_default_matmul_mxfp4_w_layout)
r   r   r<   r   r   r   rz   r   value_layoutvalue_layout_optss
             r   rA   rA     s    
 	!%!0!3 +C
  .5F&5<JM&,&O&OXY&O&Z&Z#L#((#666ZZHYZZAn..w77GGGg:r%   i   r   rows_per_chunkr   r   r*   c                P   ddl }|                     t          j                  } |                    t          j                  dz
  }| j        dd         |j        k    s"J d| j        dd         d|j                    t          j        t          || j                  }| j        ^ }}}|	                    |          |z  }	| 
                    |	|          } |
                    |	d          }t          j        |	|d	z  || j                  }
t          d|	|          D ]}t          ||z   |	          }| ||         }|||         }|
||         }|d
z                      t          j                  }||         |ddddd	f<   ~|dz	                      t          j                  }||         |ddddd	f<   ~t          j        |||           ~~~  |
j
        g |||d	z  R  j        g |||z  d	z  R  }
|
                    dd	                                          S )w
    Convert the mxfp4 weights again, dequantizing and makes them compatible with the forward
    pass of GPT_OSS.
    r   N   r,   zblocks.shape[:-1]=z does not match scales.shape=)r   r   rp   r         )out)mathr   r   r   int32shaper   
FP4_VALUESr   prodr}   emptyrangeminintldexpviewr;   
contiguous)blocksscalesr   r   r   lutprefix_shapeGB
rows_totalr   r0r1blkexpsubidx_loidx_his                     r   _convert_moe_packed_tensorsr     sI    KKKYYu{##FYYu{##c)F<,,,.dcrc1B.d.dU[Ua.d.d,,,
,zv}
E
E
EC ,\1a<((1,J^^J**F^^J**F
+j!a%uV]
K
K
KCAz>22  n$j11RUmRUm"R%j *++6{AAAqt!tG (uy))6{AAAqt!tG 	C#&&&&cc
3+#+
.|
.Q
.A
.
.
.
3
M\
M1q519
M
M
MC==A))+++r%   c                    	 t          | |||          S # t          j        $ r@ |                     d          } |                    d          }t          | |||          cY S w xY w)r   r   cpu)r   r   OutOfMemoryErrorr   )r   r   r   r   s       r   convert_moe_packed_tensorsr   M  s    g*66Weffff ! g g g5!!5!!*66Weffffffgs    AA$#A$c                   B     e Zd Z fdZdej        dej        fdZ xZS )r9   c           	      h   t                                                       |j        | _        |j        | _        |j        | _        t          j        t          j	        | j        d| j        z  | j        dz  dt          j
                  d          | _        t          j        t          j	        | j        d| j        z  t          j                  d          | _        t          j        t          j	        | j        | j        | j        dz  dft          j
                  d          | _        t          j        t          j	        | j        | j        t          j                  d          | _        d| _        t#          |dd	          | _        d | _        d | _        t#          |dd	          | _        d S )
Nr   rn   ru   r   Frequires_gradgZd;?swiglu_limitg      @)superr#   rm   num_expertsintermediate_sizero   r   	Parameterr   zerosr   r.   float32gate_up_proj_biasr/   down_proj_biasalphar   limitr~   r   )r"   rv   	__class__s     r   r#   zMxfp4GptOssExperts.__init__g  s   !3!'!9!-LK(!d.D*DdFVZ\F\^`hmhsttt
 
 

 "$K(!d.D*DEMZZZjo"
 "
 "
 K)4+;T=SWY=Y[]^fkfqrrr
 
 

 !lK($*:%-PPP`e
 
 
 
V^S99
-1**.'V^S99


r%   hidden_statesr*   c                 2   t           j        j        t           j        j        t           j        j        }}}t           j        j        }t          |j                  5   | |d|d          | j        | j	        fd          }	 ||| j
        | j                            t          j                  ||| j        d |	          }
 ||
| j        | j                            t          j                  ||| j        |j                  }d d d            n# 1 swxY w Y   |S )Nswiglu)r   r   r   )gather_indxprecision_configgammasfused_activation)scatter_indxr   r   )r<   r=   FnSpecsFusedActivationr   	swiglu_fnr   r   r   r   r.   r   r   r   r   r~   r/   r   r   	gate_scal)r"   r   routing_data
gather_idxscatter_idxr   r   r=   r   actintermediate_cache1intermediate_cache3s               r   forwardzMxfp4GptOssExperts.forward  sb   )1)9)4 #-
 '-7	}+,, 	 	!/''(I?Q"R"RUYU_aeakTlnoppC",*!&))%-88&!%!C!$	# 	# 	# #-*##&&u}55(!%!@#-# # #	 	 	 	 	 	 	 	 	 	 	 	 	 	 	. #"s   B'DDD)rO   rP   rQ   r#   r   r   r   __classcell__)r   s   @r   r9   r9   f  s`        : : : : :<#U\ #]b]i # # # # # # # #r%   r9   c                 T   dd l }t          j        j        t          j        j        t          j        j        t          j        j        f\  }}}}t          | j                  5  t          j
                                        }t          |j                            dd                    }d}	| j        d         }
| j        d         }||z  }||z  }|dz   |z  }|
|z  }d } || |          \  }}t          j        |d          }t          j        |d          \  }}t          j        |d|          }|                    d          }t          j        |||dz
            ||         }|                    d                              t          j                  }d	}t          j        ||k     ||          }t          j        |d
                              t          j                  }t          j        |                              t          j                  }t          j        ||k     ||	          }t          j        ||k    ||	          }t          j        ||	k    |	|          }||         }t          j        ||         |	k    |	|          } ||                                |                                          } ||                                |                                          } ||||          }|}d d d            n# 1 swxY w Y    ||||||          ||fS )Nr   
LOCAL_RANK0r,   rp   c                     t          j        |  dd          d d d |f         }|                                }t          j        | |d          }||                                fS )Nrp   T)dimstabler   )r   argsortlongtake_along_dimr   )valsktk_indxtk_vals       r   topkz routing_torch_dist.<locals>.topk  sb    mTEq>>>qqq"1"uEGllnnG)$Q???F7;;==((r%   r   )binsmaxi  T)r   )src_indxdst_indx)osr<   routing
GatherIndxRoutingDataScatterIndxcompute_expt_data_torchr   r   r   distributedget_world_sizer   environgetr   softmaxsortgatherr}   histcr   r   r   wherer   )logitsn_expts_actr   r   r   r   r   
world_sizerankreplace_valuen_tokensn_expts_totn_local_expertslocal_expert_startlocal_expert_endn_gates_padr   	expt_scal	expt_indxsort_indiceshistvar	topk_indx	gate_indxr   r   r   	expt_datahit_expertss                                r   routing_torch_distr    sF    III 	"-".".":	EAJ[*A 
6=	!	! 3" 3"&5577
2:>>,4455<?l1o%3!O3 1H7,	) 	) 	)  $tFK88	9M)444	"'*YA">">">	<LA|<<	 %%b))	{9;K!OLLLM_`pMpqNN2&&))%+66	 K	,> >YOO	M)D999<<U[II	M),,//<<	K	,< <iWW	K 2i ?MZZ	K	] :M9UU	i(	K	) 4 E}V_``	 !j)--//IMMOOTTT"{IMMOOimmooVVV++D/;OO	!g3" 3" 3" 3" 3" 3" 3" 3" 3" 3" 3" 3" 3" 3" 3"h ;y$iPPR]_kkks    J!LLLc                 |   dd l m} |                                r,|                                rt	          | d          rt
          }nt          j        j        }|j        d         }|	                    d| j
        j                  }t          j                            || j
        j        | j
        j                  }t#          |j                  5   ||| j
        j                  \  }}}d d d            n# 1 swxY w Y   |                     ||||          }	|		                    |d| j
        j                  }	|	|fS )Nr   
_is_hookedr,   )r   )torch.distributedr   is_availableis_initializedr   r  r<   r   r   r}   router
hidden_dimr   
functionallinearweightrq   r   r   top_kexperts)
r"   r   distr   
batch_sizerouter_logitsr   r   r   
routed_outs
             r   mlp_forwardr+    s   $$$$$$ 5t2244 5|9T9T 5$$,4$Q'J!))"dk.DEEMM((8JDKL\]]M	='	(	( Z Z07t{GX0Y0Y-j+Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z m\:S^__J##JDK4JKKJ}$$s   C55C9<C9c                    ddl m} |                    d          }|                    d          }|                    d          }	|                    d          }
|                    d          }|                    d          }d	D ]}||v r| ||||||	|
||          }| d
}| d}t          | |                    dd          d         |           t          | |          rt          | |          rt          t          | |          t          | |                    }t          | |t          j	        
                    |                    |                               t          | |           t          | |           d S )Nr   shard_and_distribute_moduler'   empty_paramcasting_dtypeto_contiguousr	  device_mesh)r.   r/   rY   rZ   .rp   )integrations.tensor_parallelr.  r   rC   rw   r   r   r   r   r   r   r   delattr)rI   
param_nameparam_valuetarget_devicedq_param_namerF   r.  r'   r/  r0  r1  r	  r2  rK   blocks_attrscales_attrr^   s                    r   
dequantizer<    s   JJJJJJJJwE**]++KJJ//MJJ//M::fD**]++K- - -:&99!!!	 	 "***K!***KFJ--c155a8+FFFv{++ -0L0L -89U9UW^_egrWsWstteh&8&89V9V&W&WXXX,,,,,,)- -r%   c                 `    t          | |          }t          j                            |          S r   )r   r   r   r   )r   r   r^   s      r   r\   r\   "  s'    ,VV<<K8k***r%   c                    |j         j        |j         j        |j         j        }}}ddlm}	 |                    d          }
|                    d          }|                    d          }|                    d          }|                    d          }|                    d          }d	|v r4|                    d
          d                             d          d         }d|v r4|                    d
          d                             d          d         }| |	|
|||||||           nJt          | |	                    d
d          d         t          j                            |d                     | d}| d}t          | |          }t          | |          }|j        j        dk    rB|j        j        dk    r3|                    d          }|dk    r |                    || j        dz  d          }n|                    |d| j        dz            }t          |d|          dk    rVt'          t          d          rAt          j                                        #t          j                                        j        }|                    |                                          }|                    |                                          }t1          |          5  t3          |                    dd          |                    dd          |          \  }}ddd           n# 1 swxY w Y   |dk    r*t          j        || j        | j        dz  g          |_        n&t          j        || j        | j        g          |_        t          | ||           t          | | d || | |                                           t=          | |           t=          | |           ~dS dS dS )q
    This transforms the weights obtained using `convert_gpt_oss.py` to load them into `Mxfp4GptOssExperts`.
    r   r-  r'   r/  r0  r1  r	  r2  r   r3  r,   rY   r   r   rZ   Nrp   Fr   metar.   r   r   acceleratorr-   r0   r1   r3   )r=   r>   r?   r@   r4  r.  r   splitrC   rw   r   r   r   r   r   r   sizer}   r   r   rA  current_acceleratorr   r   r   rA   r;   Sizero   r   r5  )rI   r6  r7  r8  r<   rF   r>   r?   r@   r.  r'   r/  r0  r1  r	  r2  rK   r:  r;  r   r   local_expertsrJ   r4   s                           r   load_and_swizzle_mxfp4rG  '  sQ   
 	%5%-%0 )WO
 KJJJJJJJwE**]++KJJ//MJJ//M::fD**]++K:$$R(..y99!<:$$R(..y99!<##;ZW[]h	
 	
 	
 	
 	
))#q11!4eh6H6Hdi6H6j6jkkk"""K"""KV[))FV[))F}V##(:f(D(DA>!!^^M63Ka3OQSTTFF^^M2v7OST7TUUFM6=99UBB}-- C!5577C!-AACCHM=))4466=))4466}%% 	 	1>  R((&*:*:2r*B*BDV2 2. ,	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 >!!).]FDVX^XpstXt4u)v)v &&).]FD\^d^p4q)r)r & 	2333&&&OQ[Q[Q]Q]@^@^@^___	
 	
 	
 	$$$$$$FFI $#(D(Ds   &=L//L36L3c                    |j         j        |j         j        |j         j        }}}|                     d          }	t          |d|          dk    rVt          t          d          rAt          j        	                                #t          j        	                                j
        }|                     |                                          } |                    |                                          }|dk    r |                     |	|j        dz  d          } n|                     |	d|j        dz            } t          |          5  t!          |                     d	d          |                    d	d          |          \  }
}ddd           n# 1 swxY w Y   |dk    r*t          j        |	|j        |j        dz  g          |
_        n&t          j        |	|j        |j        g          |
_        ||j        v r|j        |= t-          |||
           t-          || d
 || | |                                           dS )r?  r   r   r   rA  Nr.   r   r,   r-   r0   r1   r3   )r=   r>   r?   r@   rC  r   r   r   rA  rD  r   r   r   r}   r   r   rA   r;   rE  ro   r   rB   rC   )r   r   rI   rK   r8  r<   r>   r?   r@   rF  rJ   r4   s               r   rg   rg   n  s   
 	%5%-%0 )WO KKNNMv}55>>E=)) 	?1133?)==??DYY}%%0022FYY}%%0022F~v/G!/KRPPr63Kq3PQQ	=	!	! 
 
-:R$$f&6&6r2&>&>@R.
 .
*l
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 ~%*Z@RTZTlopTp0q%r%r""%*Z@XZ`Zl0m%n%n" v!!!t$FD.///"""\GGZZ\\<Z<Z<Z[[[    s   =FFFmodules_to_not_convertc                    |j         r| S ddlm}  |d          ad}|                                 D ]\  }}t          ||          s|j        j        dk    r]|j         sVt          j	        d          5  | 
                    |t          | j                             d}ddd           n# 1 swxY w Y   |j        j        d	k    r#|j         sd
dlm}  |t          |          |_        |st"                              d           | S )aD  
    Public method that replaces the expert layers of the given model with mxfp4 quantized layers.

    Args:
        model (`torch.nn.Module`):
            The model to convert, can be any `torch.nn.Module` instance.
        quantization_config (`Mxfp4Config`, defaults to `None`):
            The quantization config object that contains the quantization parameters.
        modules_to_not_convert (`list`, *optional*, defaults to `None`):
            A list of modules to not convert. If a module name is in the list (e.g. `lm_head`), it will not be
            converted.
    rp   )
get_kernelz(kernels-community/gpt-oss-triton-kernelsFGptOssExpertsr@  TN	GptOssMLPr   )
MethodTypezYou are loading your model using mixed-precision FP4 quantization but no linear modules were found in your model. Please double check your model architecture, or submit an issue on github if you think this is a bug.)r<  hub_kernelsrK  r<   named_modulesr   r   rO   r   r   set_submoduler9   rv   typesrN  r+  r   loggerwarning)r'   quantization_configrI  rK  has_been_replacedmodule_namerI   rN  s           r   replace_with_mxfp4_linearrX    s    % '''''' $$NOO$2244 
= 
=V$[2HII 	$77@S@^7f%% ) )##K1CEL1Q1QRRR$(!) ) ) ) ) ) ) ) ) ) ) ) ) ) ) $33<O<Z3(((((('ZV<<FN 
	
 	
 	
 Ls   2+B))B-	0B-	)NN))utilsr   r   r   r   
contextlibr   core_model_loadingr   r	   quantizers.quantizers_utilsr
   r   
get_loggerrO   rS  r   r   r   rV   rd   ri   r:   rA   r   r   r   r   r   r   rS   r9   r  r+  r<  r\   rG  rg   r8   r   rX  rT   r%   r   <module>r^     s   0 / / / / / / /  LLL % % % % % % ; ; ; ; ; ; ; ; U U U U U U U U 
	H	%	%  
( 
 
 
*- - - - -M - - -`    m   D-: -: -: -: -:} -: -: -:`0 0 0 0 0m 0 0 0h    0 &3, 3, 3, ;	3,
 3, \3, 3, 3, 3,t &g g g ;	g
 g \g g g g2># ># ># ># ># ># ># >#FAl Al AlH% % %(- - -B+ + +
D D DN. . .b) )W[\_W`cgWg ) ) ) ) ) )r%   