o
    <&i|                     @   s  U d 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mZm	Z	m
Z
 ddlmZmZmZmZmZmZmZmZmZmZm
ZmZmZmZmZmZ g dZedZedZedZed	Z d
Z!dZ"eZ#eZ$ee$geee e#f f Z%eee e#ge$f Z&eZ'ee#ge'f Z(ee'ge#f Z)edee* ge*f Z+ee*geeee#e*f  f Z,G dd deZ-e. Z/i Z0eee e-f e1d< G dd deZ2i Z3eee e2f e1d< i Z4ee*ee f e1d< dddddee de%de&dee* dee( dee) ddfddZ5		ddddddee de%de&dee+ dee, dee* dee( dee) ddfd d!Z6dddddee de%de&dee* dee( dee) ddfd"d#Z7d$eeef deee e#f fd%d&Z8d'ee d(e#deeef fd)d*Z9d$ee deee e#f fd+d,Z:d'ee d(e#dee fd-d.Z;d$eed/f deee e#f fd0d1Z<d'ee d(e#deed/f fd2d3Z=d$edeee e#f fd4d5Z>d'ee d(e#defd6d7Z?d(e#de'fd8d9Z@d:e'de#fd;d<ZAd$eeef deee e#f fd=d>ZBd'ee d(e#deeef fd?d@ZCeBZDeCZEd$eeef deee e#f fdAdBZFd'ee d(e#deeef fdCdDZGd(e#de'fdEdFZHd:e'de#fdGdHZIdIee deee e#f fdJdKZJd'ee d(e#dee fdLdMZKe7eLe<e=dNdO e7eMe:e;dPdO e7eNe8e9dQdO e7e	e>e?e@eAdRdS e7e
eBeCdTdO e7eeFeGdUeHeId e7eeJeKdVdO dWedeOfdXdYZPdWedefdZd[ZQdWe$deOfd\d]ZRejSG d^d dZTG d_d` d`eTZUeU ZVdWe$daee deTfdbdcZWdWe$deee eTf fdddeZXdaee dfeTde$fdgdhZYdWe$daee ddfdidjZZdWe$dee fdkdlZ[dWe$deTfdmdnZ\doed/ef dWe$de$fdpdqZ]doed/ef dWe$de$fdrdsZ^eee ee f Z_eee ee ee f Z`eee eee d/f f Zaeeeef ge f Zbeeeeef ge f Zceege f Zdeege f Zeeegeegef f Zfedte_eef defebeeef  fdudvZgedte`eeef defeceeeef  fdwdvZgedtee defedeef  fdxdvZgedteadefeee  fdydvZgdteadefeee  fdzdvZgedtee doedeef dWe$de$fd{d|Zhedte_eef doebeeef dWe$de$fd}d|Zhedte`eeef doeceeeef dWe$de$fd~d|Zhdteadoeee dWe$de$fdd|Zhedtee doedeef dWe$de$fddZiedte_eef doebeeef dWe$de$fddZiedte`eeef doeceeeef dWe$de$fddZidteadoeee dWe$de$fddZideegeOf dWe$deOfddZjdeegeOf dWe$deOfddZkedtee dedeeOf dWe$deOfddZledte_eef debeeeOf dWe$deOfddZledte`eeef deceeeeOf dWe$deOfddZldteadeeeO dWe$deOfddZledtee dedeeOf dWe$deOfddZmedte_eef debeeeOf dWe$deOfddZmedte`eeef deceeeeOf dWe$deOfddZmdteadeeeO dWe$deOfddZmdWe$dfeTdeee  fddZnejSG dd dZoG dd deZpi Zqeerepf e1d< dfeTdeofddZsde'deTfddZtepeseteqd
< ddfeTdeer de*fddZude*deTfddZvG dd dZwdfeTde*fddZxdfeTde*fddZyde*deTfddZzde$de$dee fddZ{dS )a  
Contains utility functions for working with nested python data structures.

A *pytree* is Python nested data structure. It is a tree in the sense that
nodes are Python collections (e.g., list, tuple, dict) and the leaves are
Python values. Furthermore, a pytree should not contain reference cycles.

pytrees are useful for working with nested collections of Tensors. For example,
one can use `tree_map` to map a function over all Tensors inside some nested
collection of Tensors and `tree_leaves` to get a flat list of all Tensors
inside some nested collection. pytrees are helpful for implementing nested
collection support for PyTorch APIs.

This pytree implementation is not very performant due to Python overhead
To improve the performance we can move parts of the implementation to C++.
    N)defaultdictdeque
namedtupleOrderedDict)AnyCallablecastDefaultDictDequeDictIterableList
NamedTupleOptionalr   overloadTupleTypeTypeVarUnion)PyTreeContextFlattenFuncUnflattenFuncDumpableContextToDumpableContextFnFromDumpableContextFnTreeSpecLeafSpecregister_pytree_nodetree_flattentree_unflattentree_leavestree_structuretree_map	tree_map_tree_map_onlytree_map_only_tree_alltree_anytree_all_onlytree_any_onlytreespec_dumpstreespec_loadstreespec_pprintTSUR   NO_SERIALIZED_TYPE_NAME_FOUNDr   c                   @   s*   e Zd ZU ee ed< eed< eed< dS )NodeDeftype
flatten_fnunflatten_fnN)__name__
__module____qualname__r   r   __annotations__r   r    r<   r<   >C:\wamp64\www\opt\env\Lib\site-packages\torch/utils/_pytree.pyr4   d   s   
 r4   SUPPORTED_NODESc                   @   s:   e Zd ZU ee ed< eed< ee ed< ee	 ed< dS )_SerializeNodeDeftypserialized_type_nameto_dumpable_contextfrom_dumpable_contextN)
r8   r9   r:   r   r   r;   strr   r   r   r<   r<   r<   r=   r?   u   s
   
 r?   SUPPORTED_SERIALIZED_TYPESSERIALIZED_TYPE_TO_PYTHON_TYPErA   rB   rC   clsr6   r7   rA   rB   rC   returnc                C   s   t  | tv rt|  dW d   n1 sw   Y  t| |||||d zddlm} W n
 ty9   Y dS w |j| |||||d dS )az  Register a container-like type as pytree node.

    Args:
        cls: the type to register
        flatten_fn: A callable that takes a pytree and returns a flattened
            representation of the pytree and additional context to represent the
            flattened pytree.
        unflatten_fn: A callable that takes a flattened version of the pytree,
            additional context, and returns an unflattened pytree.
        serialized_type_name: A keyword argument used to specify the fully qualified
            name used when serializing the tree spec.
        to_dumpable_context: An optional keyword argument to custom specify how
            to convert the context of the pytree to a custom json dumpable
            representation. This is used for json serialization, which is being
            used in torch.export right now.
        from_dumpable_context: An optional keyword argument to custom specify how
            to convert the custom json dumpable representation of the context
            back to the original context. This is used for json deserialization,
            which is being used in torch.export right now.
    z& is already registered as pytree node.NrG   r2   )_cxx_pytree)_NODE_REGISTRY_LOCKr>   
ValueError_private_register_pytree_node rJ   ImportError)rH   r6   r7   rA   rB   rC   Zcxxr<   r<   r=   r      s4   	
r   	to_str_fnmaybe_from_str_fnc                C   s@   t jddd |dus|durt d t| |||||d dS )a  Register a container-like type as pytree node for the Python pytree only.

    Args:
        cls: the type to register
        flatten_fn: A callable that takes a pytree and returns a flattened
            representation of the pytree and additional context to represent the
            flattened pytree.
        unflatten_fn: A callable that takes a flattened version of the pytree,
            additional context, and returns an unflattened pytree.
        serialized_type_name: A keyword argument used to specify the fully qualified
            name used when serializing the tree spec.
        to_dumpable_context: An optional keyword argument to custom specify how
            to convert the context of the pytree to a custom json dumpable
            representation. This is used for json serialization, which is being
            used in torch.export right now.
        from_dumpable_context: An optional keyword argument to custom specify how
            to convert the custom json dumpable representation of the context
            back to the original context. This is used for json deserialization,
            which is being used in torch.export right now.
    zutorch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead.   )
stacklevelNzpto_str_fn and maybe_from_str_fn is deprecated. Please use to_dumpable_context and from_dumpable_context instead.rG   )warningswarnrM   )rH   r6   r7   rP   rQ   rA   rB   rC   r<   r<   r=   _register_pytree_node   s    
rV   c                C   s   t K | tv rt|  d t| ||}|t| < |du |du A r)td|  d|du r6| j d| j }t| |||}|t	| < | t
|< W d   dS 1 sPw   Y  dS )zThis is an internal function that is used to register a pytree node type
    for the Python pytree only. End-users should use :func:`register_pytree_node`
    instead.
    zM is already registered as pytree node. Overwriting the previous registration.Nz7Both to_dumpable_context and from_dumpable_context for z must be None or registered..)rK   r>   rT   rU   r4   rL   r9   r:   r?   rE   rF   )rH   r6   r7   rA   rB   rC   Znode_defserialize_node_defr<   r<   r=   rM      s4   

"rM   dc                 C      t |  t |  fS NlistvalueskeysrY   r<   r<   r=   _dict_flatten     ra   r^   contextc                 C   s   t t|| S r[   )dictzipr^   rc   r<   r<   r=   _dict_unflatten!     rg   c                 C   s   | d fS r[   r<   r`   r<   r<   r=   _list_flatten%     ri   c                 C      t | S r[   r]   rf   r<   r<   r=   _list_unflatten)  rj   rm   .c                 C   s   t | d fS r[   rl   r`   r<   r<   r=   _tuple_flatten-     rn   c                 C   rk   r[   )tuplerf   r<   r<   r=   _tuple_unflatten1  rj   rq   c                 C   s   t | t| fS r[   )r]   r5   r`   r<   r<   r=   _namedtuple_flatten5  s   rr   c                 C   s   t t||  S r[   )r   r   rf   r<   r<   r=   _namedtuple_unflatten9  rh   rs   c                 C   s   | j | jd}|S )N)
class_namefields)r8   _fields)rc   Zjson_namedtupler<   r<   r=   _namedtuple_serialize=  s   rw   dumpable_contextc                 C   s(   | d }t |tsJ t|| d }|S )Nrt   ru   )
isinstancerD   r   )rx   rt   rc   r<   r<   r=   _namedtuple_deserializeE  s   rz   c                 C   rZ   r[   r\   r`   r<   r<   r=   _ordereddict_flattenL  rb   r{   c                 C   s   t dd t|| D S )Nc                 s   s    | ]	\}}||fV  qd S r[   r<   ).0keyvaluer<   r<   r=   	<genexpr>T      z)_ordereddict_unflatten.<locals>.<genexpr>)r   re   rf   r<   r<   r=   _ordereddict_unflattenP  s   r   c                 C   s   t | \}}|| j|gfS r[   )ra   default_factory)rY   r^   dict_contextr<   r<   r=   _defaultdict_flatten[  s   r   c                 C   s   |\}}t |t| |S r[   )r   rg   )r^   rc   r   r   r<   r<   r=   _defaultdict_unflatten`  s   r   c                 C   s   | \}}|j |j|d}|S )N)default_factory_moduledefault_factory_namer   )r9   r:   )rc   r   r   Zjson_defaultdictr<   r<   r=   _defaultdict_serializeh  s   r   c                 C   sr   t | tsJ t| h dksJ | d }| d }t |ts J t |ts'J t|}t||}| d }||gS )N>   r   r   r   r   r   r   )ry   rd   setrD   	importlibimport_modulegetattr)rx   r   r   moduler   r   r<   r<   r=   _defaultdict_deserializer  s   

r   deqc                 C   s   t | | jfS r[   )r]   maxlen)r   r<   r<   r=   _deque_flatten  rh   r   c                 C   s   t | |dS )Nr   )r   rf   r<   r<   r=   _deque_unflatten  ro   r   zbuiltins.tuple)rA   zbuiltins.listzbuiltins.dictzcollections.namedtuple)rB   rC   rA   zcollections.OrderedDictzcollections.defaultdictzcollections.dequetreec                 C   sV   t | }|j}t|dks|d tkrdS t|dd }t|ts"dS tdd |D S )Nr2   r   Frv   c                 s   s    | ]	}t |tkV  qd S r[   )r5   rD   )r|   entryr<   r<   r=   r     r   z*_is_namedtuple_instance.<locals>.<genexpr>)r5   	__bases__lenrp   r   ry   all)r   r@   basesru   r<   r<   r=   _is_namedtuple_instance  s   
r   c                 C   s   t | rtS t| S r[   )r   r   r5   r   r<   r<   r=   _get_node_type  s   r   c                 C   s   t | tvS r[   )r   r>   r   r<   r<   r=   _is_leaf  ro   r   c                   @   sV   e Zd ZU eed< eed< ed  ed< dddZdd	ede	fd
dZ
defddZdS )r   r5   rc   children_specsrI   Nc                 C   s   t dd | jD | _d S )Nc                 S   s   g | ]}|j qS r<   )
num_leaves)r|   specr<   r<   r=   
<listcomp>      z*TreeSpec.__post_init__.<locals>.<listcomp>)sumr   r   selfr<   r<   r=   __post_init__  s   zTreeSpec.__post_init__r   indentc                    s   d| j j d| j d}d}t| jrA d7  || jd  7 }|t| jdkr+dnd7 }|d fd	d
| jdd  D 7 }| d}|| S )Nz	TreeSpec(z, z, [rN   rR   r   r2   ,c                    s"   g | ]}d d   |   qS )
 )__repr__r|   childr   r<   r=   r     s    z%TreeSpec.__repr__.<locals>.<listcomp>z]))r5   r8   rc   r   r   r   join)r   r   Zrepr_prefixZchildren_specs_strZrepr_suffixr<   r   r=   r     s   


zTreeSpec.__repr__c                 C   s
   t | tS r[   )ry   r   r   r<   r<   r=   is_leaf  s   
zTreeSpec.is_leafrI   Nr   )r8   r9   r:   r   r;   r   r   r   intrD   r   boolr   r<   r<   r<   r=   r     s   
 
c                       s2   e Zd Zd	 fddZd
dedefddZ  ZS )r   rI   Nc                    s   t  d d g  d| _d S )Nr2   )super__init__r   r   	__class__r<   r=   r     s   
zLeafSpec.__init__r   r   c                 C      dS N*r<   )r   r   r<   r<   r=   r        zLeafSpec.__repr__r   r   )r8   r9   r:   r   r   rD   r   __classcell__r<   r<   r   r=   r     s    r   leavesc                    sR   t | r |  tS t| }t| j}|| \}} fdd|D }t|||S )Nc                    s   g | ]}t | qS r<   _tree_flatten_helperr   r   r<   r=   r     s    z(_tree_flatten_helper.<locals>.<listcomp>)r   append
_LEAF_SPECr   r>   r6   r   )r   r   	node_typer6   child_pytreesrc   r   r<   r   r=   r     s   

r   c                 C   s   g }t | |}||fS )zkFlattens a pytree into a list of values and a TreeSpec that can be used
    to reconstruct the pytree.
    r   )r   r   r   r<   r<   r=   r     s   
r   treespecc                 C   s   t |tstdt| dt | ttfst| } t| |jkr2tdt|  d|j d| dt |t	r;| d S t
|j j}d}d}g }|jD ]}||j7 }|t| || | |}qJ|||jS )zqGiven a list of values and a TreeSpec, builds a pytree.
    This is the inverse operation of `tree_flatten`.
    zftree_unflatten(leaves, treespec): Expected `treespec` to be instance of TreeSpec but got item of type rW   z6tree_unflatten(leaves, treespec): `leaves` has length z, but the spec refers to a pytree that holds z items (z).r   )ry   r   	TypeErrorr5   r]   rp   r   r   rL   r   r>   r7   r   r   r    rc   )r   r   r7   startendr   
child_specr<   r<   r=   r      s6   



r    c                 C   sL   t | r||  d S t| }t| j}|| \}}|D ]}t|| qd S r[   )r   r   r   r>   r6   _tree_leaves_helper)r   r   r   r6   r   _r   r<   r<   r=   r   >  s   

r   c                 C   s   g }t | | |S )z!Get a list of leaves of a pytree.)r   )r   r   r<   r<   r=   r!   L  s   
r!   c                 C   s   t | d S )zGet the TreeSpec for a pytree.r2   )r   r   r<   r<   r=   r"   S  s   r"   funcc                    s$   t |\}}t fdd|D |S )Nc                    s   g | ]} |qS r<   r<   )r|   ir   r<   r=   r   Z      ztree_map.<locals>.<listcomp>)r   r    )r   r   	flat_argsr   r<   r   r=   r#   X  s   r#   c                 C   s   t |}tt| |dd |S )Nr   r   )r!   r   map)r   r   r   r<   r<   r=   r$   ]  s   r$   __type_or_typesc                 C      d S r[   r<   r   r<   r<   r=   map_onlyq     r   c                 C   r   r[   r<   r   r<   r<   r=   r   v  r   c                 C   r   r[   r<   r   r<   r<   r=   r   {  r   c                 C   r   r[   r<   r   r<   r<   r=   r     r   c                    s.   dt tgtf dt tgtf f fdd}|S )a  
    Suppose you are writing a tree_map over tensors, leaving everything
    else unchanged.  Ordinarily you would have to write:

        def go(t):
            if isinstance(t, Tensor):
                return ...
            else:
                return t

    With this function, you only need to write:

        @map_only(Tensor)
        def go(t):
            return ...

    You can also directly use 'tree_map_only'
    r   rI   c                    s   dt dtf fdd}|S )NxrI   c                    s   t |  r	| S | S r[   ry   )r   )r   r   r<   r=   wrapped  s   
z*map_only.<locals>.wrapper.<locals>.wrapped)r.   r   )r   r   r   r   r=   wrapper  s   zmap_only.<locals>.wrapper)r   r.   r   )r   r   r<   r   r=   r     s   *	c                 C   r   r[   r<   r   r   r   r<   r<   r=   r%        r%   c                 C   r   r[   r<   r   r<   r<   r=   r%     r   c                 C   r   r[   r<   r   r<   r<   r=   r%     r   c                 C      t t| ||S r[   )r#   r   r   r<   r<   r=   r%        c                 C   r   r[   r<   r   r<   r<   r=   r&     r   r&   c                 C   r   r[   r<   r   r<   r<   r=   r&     r   c                 C   r   r[   r<   r   r<   r<   r=   r&     r   c                 C   r   r[   )r$   r   r   r<   r<   r=   r&     r   predc                 C      t |}tt| |S r[   )r!   r   r   r   r   r   r<   r<   r=   r'        r'   c                 C   r   r[   )r!   anyr   r   r<   r<   r=   r(     r   r(   c                 C   r   r[   r<   r   r   r   r<   r<   r=   r)     r   r)   c                 C   r   r[   r<   r   r<   r<   r=   r)     r   c                 C   r   r[   r<   r   r<   r<   r=   r)     r   c                        t |}t fdd|D S )Nc                 3   "    | ]}t | r|V  qd S r[   r   r|   r   r   r   r<   r=   r          z tree_all_only.<locals>.<genexpr>)r!   r   r   r   r   r   r<   r   r=   r)        c                 C   r   r[   r<   r   r<   r<   r=   r*     r   r*   c                 C   r   r[   r<   r   r<   r<   r=   r*   #  r   c                 C   r   r[   r<   r   r<   r<   r=   r*   ,  r   c                    r   )Nc                 3   r   r[   r   r   r   r<   r=   r   ;  r   z tree_any_only.<locals>.<genexpr>)r!   r   r   r<   r   r=   r*   5  r   c           
      C   s   t |tsJ t| r| g|j S t |trd S t| }||jkr#d S t| j}|| \}}t	|t	|j
ks<||jkr>d S g }t||j
D ]\}}t||}	|	d urX||	7 }qF d S |S r[   )ry   r   r   r   r   r   r5   r>   r6   r   r   rc   re   _broadcast_to_and_flatten)
r   r   r   r6   r   ctxresultr   r   Zflatr<   r<   r=   r   F  s&   




r   c                   @   s2   e Zd ZU dZee ed< eed< ed  ed< dS )_TreeSpecSchemaa  
    _TreeSpecSchema is the schema used to serialize the TreeSpec
    It contains the following fields:
    - type: A string name of the type. null for the case of a LeafSpec.
    - context: Any format which is json dumpable
    - children_spec: A list of children serialized specs.
    r5   rc   children_specN)	r8   r9   r:   __doc__r   rD   r;   r   r   r<   r<   r<   r=   r   d  s
   
 r   c                   @   s2   e Zd ZU eegef ed< eegef ed< dS )_ProtocolFntreespec_to_jsonjson_to_treespecN)r8   r9   r:   r   r   r   r;   r<   r<   r<   r=   r   s  s   
 r   _SUPPORTED_PROTOCOLSc              
   C   s   t | trtd d g S | jtvrtd| j dt| j }|j}|tkr.td| j d|jd u rMzt	
| j}W n tyL } ztd|d }~ww || j}dd | jD }t|||S )NzSerializing  in pytree is not registered.z%No registered serialization name for zZ found. Please update your _register_pytree_node call with a `serialized_type_name` kwarg.zUnable to serialize context. Please make the context json dump-able, or register a custom serializer using _register_pytree_node.c                 S   s   g | ]}t |qS r<   )_treespec_to_jsonr   r<   r<   r=   r     r   z%_treespec_to_json.<locals>.<listcomp>)ry   r   r   r5   rE   NotImplementedErrorrA   r3   rB   jsondumpsrc   r   r   )r   rX   rA   Zserialized_contexteZchild_schemasr<   r<   r=   r   {  s4   



r   json_schemac              
   C   s   | d d u r| d d u rt | d dkrt S | d tvr'td| d  dt| d  }t| }|jd u rQz	t| d }W n tyP } ztd|d }~ww || d }g }| d D ]	}|	t
| q^t|||S )Nr5   rc   r   r   zDeserializing r   zUnable to deserialize context. Please make the context json load-able, or register a custom serializer using _register_pytree_node.)r   r   rF   r   rE   rC   r   loadsr   r   _json_to_treespecr   )r   r@   rX   rc   exr   Zchild_stringr<   r<   r=   r     s4   
r   protocolc                 C   sv   t | tstdt|  d|d u rt}|tv r!t| | }ntd| dtt	  t
|t|f}|S )Nzhtreespec_dumps(treespec, protocol): Expected `treespec` to be instance of TreeSpec but got item of type rW   Unknown protocol . Available protocols: )ry   r   r   r5   'DEFAULT_TREESPEC_SERIALIZATION_PROTOCOLr   r   rL   r]   r_   r   r   dataclassesasdict)r   r  Z	json_specZstr_specr<   r<   r=   r+     s"   

r+   
serializedc                 C   s@   t | \}}|tv rt| |S td| dtt  )Nr  r  )r   r   r   r   rL   r]   r_   )r  r  r   r<   r<   r=   r,     s   
r,   c                   @   s   e Zd ZdefddZdS )
_DummyLeafrI   c                 C   r   r   r<   r   r<   r<   r=   r     r   z_DummyLeaf.__repr__N)r8   r9   r:   rD   r   r<   r<   r<   r=   r    s    r  c                 C   s"   t dd t| jD | }t|S )Nc                 S   s   g | ]}t  qS r<   )r  )r|   r   r<   r<   r=   r     r   z#treespec_pprint.<locals>.<listcomp>)r    ranger   repr)r   Z
dummy_treer<   r<   r=   r-     s
   r-   c                 C      t d t| S )Nz6pytree_to_str is deprecated. Please use treespec_dumps)rT   rU   r+   )r   r<   r<   r=   pytree_to_str     
r  r   c                 C   r  )Nz6str_to_pytree is deprecated. Please use treespec_loads)rT   rU   r,   )r   r<   r<   r=   str_to_pytree  r  r  argskwargsc                  O   s4   g }| D ]}t || q| D ]}t || q|S )zpGet a flat list of arguments to this function

    A slightly faster version of tree_leaves((args, kwargs))
    )r   r^   )r  r  r   ar<   r<   r=   arg_tree_leaves  s   r  )NNr[   )|r   r  r   r   	threadingrT   collectionsr   r   r   r   typingr   r   r   r	   r
   r   r   r   r   r   ZGenericOrderedDictr   r   r   r   r   __all__r.   r/   r0   r1   r  r3   r   r   r   r   r   r   r   rD   Z	ToStrFuncZMaybeFromStrFuncr4   LockrK   r>   r;   r?   rE   rF   r   rV   rM   ra   rg   ri   rm   rn   rq   rr   rs   rw   rz   r{   r   Z_odict_flattenZ_odict_unflattenr   r   r   r   r   r   rp   r]   rd   r   r   r   r   	dataclassr   r   r   r   r   r    r   r!   r"   r#   r$   ZType2ZType3ZTypeAnyZFn2ZFn3ZFnZFnAnyZ	MapOnlyFnr   r%   r&   r'   r(   r)   r*   r   r   r   r   r   r   r   r+   r,   r  r-   r  r  r  r<   r<   r<   r=   <module>   s   H


=	

:
&/""&"&

&


"			"*.$ 





  


	


$#	