
    biO[                        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ZddlZddl	Z	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 ddl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Zdd
l m!Z! ddl"m#Z# ddl$m%Z% ddl"m&Z& dd
l"m!Z' ddl(m)Z)m*Z*m+Z+m,Z, 	 ddlm-Z- ddl.Z/ddl.m0Z0  e&jd                  e3      Z4ejj                  Z6d Z7dee8e9f   de8fdZ:d Z;de9de9dee<e9e9f      fdZ=d Z>ed        Z?edIde8fd       Z@d ZAd  ZBd! ZCd" ZDd# ZE G d$ d%e<      ZF G d& d'eG      ZHd( ZI	 	 	 	 	 	 	 	 	 	 	 dJd)eegef   d*ed+eJd,eJd-eJd.eJd/ee8   d0e8d1eJd2ee8   d3eeK   d4eJd5ee9   defd6ZL G d7 d8      ZMdKd9ZNd: ZO ed;      ZPd<ej                  d=ed>eeP   f   d?e<de8fd@ZRdAeej                  j                  ej                  j                  f   deUe8   fdBZVdAeej                  j                  ej                  j                  f   d=ed>eeP   f   dCee<   deeP   fdDZW edE      ZXdFeeX   dGe8deeYeX      fdHZZy# e1$ r
 dxZ/xZ0Z-Y w xY w)Lz'Some python utils function and classes.    N)Iterable)contextmanager)fieldsis_dataclass)Manager)Empty)
disk_usage)AnyCallableOptionalTypeVarUnion)tqdm   )config)parallel_map   )logging)Picklerdumpdumpspklregister)Final)Literalc                 ~    | syg d}t        |       } |D ]  \  }}| |z  }|dk\  s|dd| c S  t        |        dS )a6  Returns a human readable size string.

    If size_in_bytes is None, then returns "Unknown size".

    For example `size_str(1.5 * datasets.units.GiB) == "1.50 GiB"`.

    Args:
        size_in_bytes: `int` or `None`, the size, in bytes, that we want to
            format as a human-readable size string.
    zUnknown size))PiB           )TiB        )GiB   @)MiB   )KiB   g      ?z.2f z bytes)floatint)size_in_bytes
_NAME_LISTname
size_bytesvalues        R/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/datasets/utils/py_utils.pysize_strr/   H   sf     aJ-(M& )j
*C<C[$(() - !((    sizereturnc                    t        | t              r| S | j                         j                  d      rt        | dd       dz  S | j                         j                  d      rt        | dd       dz  S | j                         j                  d      rt        | dd       dz  S | j                         j                  d	      rt        | dd       d
z  S | j                         j                  d      rt        | dd       dz  S | j                         j                  d      r)t        | dd       dz  }| j                  d      r|dz  S |S | j                         j                  d      r)t        | dd       dz  }| j                  d      r|dz  S |S | j                         j                  d      r)t        | dd       dz  }| j                  d      r|dz  S |S | j                         j                  d      r)t        | dd       dz  }| j                  d      r|dz  S |S | j                         j                  d      r)t        | dd       dz  }| j                  d      r|dz  S |S t	        d|  d      )a)  
    Converts a size expressed as a string with digits an unit (like `"50MB"`) to an integer (in bytes).

    Args:
        size (`int` or `str`): The size to convert. Will be directly returned if an `int`.

    Example:

    ```py
    >>> convert_file_size_to_int("1MiB")
    1048576
    ```
    PIBNr   TIBr   GIBr!   MIBr#   KIBr%   PBl     I5 b   TBl    J)GBi ʚ;MBi@B KB  z`size=zM` is not in a valid format. Use an integer followed by the unit, e.g., '5GB'.)
isinstancer(   upperendswith
ValueError)r1   int_sizes     r.   convert_file_size_to_intrH   `   s?    $zz|U#49~''zz|U#49~''zz|U#49~''zz|U#49~''zz|U#49~''zz|T"tCRy>V, $c 2x1}@@zz|T"tCRy>V, $c 2x1}@@zz|T"tCRy>U+ $c 2x1}@@zz|T"tCRy>U+ $c 2x1}@@zz|T"tCRy>U+ $c 2x1}@@
vdV#pq
rrr0   c                    | j                  dd      j                  dd      j                  dd      j                  dd      j                  d	d
      j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                  d
      j                  dd      S )N\z\\.z\.*z.*+z\+z///(z\()z\)|z\|^z\^$z\$?)replacerstrip)patterns    r.   glob_pattern_to_regexrX      s     	e$	e		d		e		s		e		e		e		e		e			c	r0   stringrW   c                    t        j                  dd|      }t        j                  dd|      }t        j                  ||       }|yt        |j	                               }t        j
                  d|      }t        t        ||            }|S )a  Un-format a string using a python f-string pattern.
    From https://stackoverflow.com/a/36838374

    Example::

        >>> p = 'hello, my name is {name} and I am a {age} year old {what}'
        >>> s = p.format(name='cody', age=18, what='quarterback')
        >>> s
        'hello, my name is cody and I am a 18 year old quarterback'
        >>> string_to_dict(s, p)
        {'age': '18', 'name': 'cody', 'what': 'quarterback'}

    Args:
        string (str): input string
        pattern (str): pattern formatted like a python f-string
            This can be a regex - so in case of un-formatting paths you should use posix paths.
            Otherwise backslashes for windows paths can cause issues.

    Returns:
        Optional[dict[str, str]]: dictionary of variable -> value, retrieved from the input using the pattern, or
        `None` if the string does not match the pattern.
    z{([^:}]+)(?::[^}]+)?}z{\1}z{(.+?)}z(?P<_\1>.+)N)resubsearchlistgroupsfindalldictzip)rY   rW   regexresultvalueskeys_dicts          r.   string_to_dictrh      sw    . ff-w@GFF:~w7EYYuf%F~&--/"F::j'*DT6"#ELr0   c                 t    d fdt        | t              s |       st        |  d       |       S )zbConvert an object to its dictionary representation recursively.

    <Added version="2.4.0"/>
    c                 >    t        |       xr t        | t               S N)r   rC   type)objs    r.   _is_dataclass_instancez&asdict.<locals>._is_dataclass_instance   s    C >C)>%>>r0   c                     |       rwi }t        |       D ]e  } t        | |j                              }|j                  r,||j                  k7  s|j
                  j                  dd      sW|||j                  <   g |S t        | t              r.t        | d      r" t        |       | D cg c]
  } |       c} S t        | t        t        f      r t        |       fd| D              S t        | t              r0| j                         D ci c]  \  }} |       |       c}}S t        j                  |       S c c}w c c}}w )N$include_in_asdict_even_if_is_defaultF_fieldsc              3   .   K   | ]  } |        y wrk    ).0v_asdict_inners     r.   	<genexpr>z0asdict.<locals>._asdict_inner.<locals>.<genexpr>   s     ;!]1-;s   )r   getattrr+   initdefaultmetadatagetrC   tuplehasattrrl   r^   ra   itemscopydeepcopy)rm   rd   fr-   ru   krv   rn   s         r.   rv   zasdict.<locals>._asdict_inner   s   !#&FC[ +%gc166&:;vv!))!3qzz~~Flns7t%*F166N+ MU#Y(?49=A}Q/=>>dE]+ 49;s;;;T"CF99;O41aM!$mA&66OO==%% > Ps   ,EE	z is not a dict or a dataclass)rC   ra   	TypeError)rm   rv   rn   s    @@r.   asdictr      s?    ?&* c4 )?)D3%<=>>r0   c              #      K   t        | |d      }t        | ||       	 d t        | ||       y# t        | ||       w xY ww)z%Temporarily assign obj.attr to value.N)rx   setattr)rm   attrr-   originals       r.   temporary_assignmentr      sB      sD$'HCu%T8$T8$s   A0 A?Aseedc              #     K   t         j                  j                         }t         j                  j                  |        |rt        j
                  rddl}|j                  j                         }|j                  j                  |        |j                  j                         r5|j                  j                         }|j                  j                  |        |rt        j                  rddl}ddlm} |j                  j#                         }	|j                  j$                  j'                  |       }
|j                  j)                  |
       |j+                         st-        d      |j!                         }|j.                  }t1        |d      }|r|j2                  }|j5                  |        	 d t         j                  j7                  |       |r`t        j
                  rPj                  j9                         |j                  j                         r|j                  j;                         |rJt        j                  r9j                  j)                  	       _        r|_        yt=        |d       yyy# t         j                  j7                  |       |r`t        j
                  rPj                  j9                         |j                  j                         r|j                  j;                         |rJt        j                  r9j                  j)                  	       _        r|_        w t=        |d       w w w xY ww)zUTemporarily set the random seed. This works for python numpy, pytorch and tensorflow.r   N)contextzBSetting random seed for TensorFlow is only available in eager mode_rng)nprandom	get_stater   r   TORCH_AVAILABLEtorchget_rng_statemanual_seedcudais_availableget_rng_state_allmanual_seed_allTF_AVAILABLE
tensorflowtensorflow.python.eagerr   get_global_generator	Generator	from_seedset_global_generatorexecuting_eagerlyrF   _seedr~   r   _set_global_seed	set_stateset_rng_stateset_rng_state_alldelattr)r   set_pytorchset_tensorflownp_stater   torch_statetorch_cuda_statestftfpycontexttf_statetemp_gen
tf_contexttf_seedtf_rng_initializedtf_rngs                  r.   	temp_seedr      sg     yy""$HIINN4v--ll002  &::""$ %

 < < >JJ&&t,&--B9911399&&006
		&&x0##%abb ((*
""$Z8__F##D),
		H%611LL&&{3zz&&(

,,->?f11II**84&J!"(

F+ 2> 			H%611LL&&{3zz&&(

,,->?f11II**84&J!"(

F+ 2>s    F0M3J 7CMCMMc              #   b   K   t               }| D ]  }||vs|j                  |       |  yw)z=Iterate over iterable and return only unique values in order.N)setadd)re   seenr-   s      r.   unique_valuesr   )  s4     5D HHUOKs   //c                       fd}|S )z4If the value is None, return None, else call `func`.c                     |  |       S d S rk   rs   )r-   funcs    r.   wrapperz'no_op_if_value_is_null.<locals>.wrapper5  s    #/tE{9T9r0   rs   )r   r   s   ` r.   no_op_if_value_is_nullr   2  s    : Nr0   c                 :    t        |       D ]  \  }}|	||fc S  y)zwReturn the index and the value of the first non-null value in the iterable. If all values are None, return -1 as index.N)	enumerateiterableir-   s      r.   first_non_null_valuer   ;  s.    h' 5e8O r0   c                     t        |       D ]2  \  }}|	t        |t        t        f      rt	        |      dk(  r.||fc S  y)zReturn the index and the value of the first non-null non-empty value in the iterable. If all values are None or empty, return -1 as index.r   r   )r   rC   ra   r^   lenr   s      r.   first_non_null_non_empty_valuer   C  sF    h' 5jt&E#e*XY/e8O r0   c               '   ~   K   t        t        j                  |        D ]  t        fd| D              f  yw)z9Iterate over items of dictionaries grouped by their keys.c              3   (   K   | ]	  }|     y wrk   rs   )rt   dkeys     r.   rw   zzip_dict.<locals>.<genexpr>O  s     /A3/s   N)r   	itertoolschainr}   )dictsr   s    @r.   zip_dictr   K  s:     Y__e45 05/////0s   :=c                   6     e Zd ZdZ fdZ fdZ fdZ xZS )NonMutableDictzDict where keys can only be added but not modified.

    Will raise an error if the user try to overwrite one key. The error message
    can be customized during construction. It will be formatted using {key} for
    the overwritten key.
    c                 l    |j                  dd      | _        |rt        d      t        |   |i | y )N	error_msgz$Try to overwrite existing key: {key}z1NonMutableDict cannot be initialized with kwargs.)pop
_error_msgrF   super__init__)selfargskwargs	__class__s      r.   r   zNonMutableDict.__init__Z  s<     **2
 PQQ$)&)r0   c                 v    || v r%t        | j                  j                  |            t        |   ||      S )Nr   )rF   r   formatr   __setitem__)r   r   r-   r   s      r.   r   zNonMutableDict.__setitem__c  s9    $;T__333<==w"3..r0   c                      t         fd|D              r:t         j                  j                  t	               t	        |      z              t
           |      S )Nc              3   &   K   | ]  }|v  
 y wrk   rs   )rt   r   r   s     r.   rw   z(NonMutableDict.update.<locals>.<genexpr>i  s     (QqDy(s   r   )anyrF   r   r   r   r   update)r   otherr   s   ` r.   r   zNonMutableDict.updateh  sJ    (%((T__33D	CJ8N3OPPw~e$$r0   )__name__
__module____qualname____doc__r   r   r   __classcell__)r   s   @r.   r   r   R  s    */
% %r0   r   c                       e Zd ZdZddZy)classpropertyz5Descriptor to be used as decorator for @classmethods.Nc                 D     | j                   j                  d |             S rk   )fget__get__)r   rm   objtypes      r.   r   zclassproperty.__get__q  s    /tyy  w/11r0   rk   )r   r   r   r   r   rs   r0   r.   r   r   n  s
    ?2r0   r   c                 `   | \  }}}}}}}t        |t              s"t        |      s|r ||g      d   S  ||      S |rYt        |t              sIt        |      r=t        fd|D              r)t        ||      D 	cg c]  } ||      D ]  }	|	  c}	}S |9t	        j
                         t        j                  k  rt	        j                          |0|s.t        d t        j                  D              rt        ddd       t        |t              r|j                         n|}
|||dz   ndd	z   t        |      z   n|}t        |
||d
|      5 }t        |t              r0|D ci c]  \  }}|t        ||||dddf       c}}cddd       S |D cg c]  }t        ||||dddf       }}t        |t               r|cddd       S t        |t"              rt#        |      cddd       S t%        j&                  |      cddd       S c c}	}w c c}}w c c}w # 1 sw Y   yxY w)zEApply a function recursively to each element of a nested data struct.r   c              3   D   K   | ]  }t        |t        f         y wrk   )rC   ra   )rt   ru   typess     r.   rw   z%_single_map_nested.<locals>.<genexpr>  s     FQJq4-00Fs    Nc              3   8   K   | ]  }d |j                   v   yw)notebookN)r   )rt   tqdm_clss     r.   rw   z%_single_map_nested.<locals>.<genexpr>  s     4rYaZ8CTCT5T4rs   r&    T)endflush#rm   )disablepositionunitdesc)rC   ra   alliter_batchedr   get_verbosityWARNINGset_verbosity_warningr   r   __mro__printr   strhf_tqdm_single_map_nestedr^   r}   r   array)r   functiondata_structbatched
batch_sizerankdisable_tqdmr   batchmapped_itempbar_iterable	pbar_descpbarr   ru   mappedr   s                   @r.   r
  r
  u  s1   RVOHk7Jt\4 k4(K1O[M*1--K((;-{E*F+FF)5k:)NrbjkpbqrS^rrr G113gooE%%' 4reieqeq4r1rcr& ,6k4+HK%%'kMNRN^t/R3>TJdhI	t%V_	` (dhk4(osgkghjk%xGZPTVZ\`&abb( ( pttjk((Aw
ESWY]_c)detFt+t,( ( K/V}( ( xx'( ( s u( (sB    HH$+H	H$H$H4H$H$5H$H$$H-r  r  	dict_onlymap_list	map_tuple	map_numpynum_procparallel_min_lengthr  r  r   r  r   c                   
 
ag 
|sR|r 
j                   t               |r 
j                   t               |r  
j                   t        j                         t        
      
t        |t              s"t        |
      s|r|g} | |      }|r|d   }|S t        |t              rt        |j                               n||d}t        
fdD              r!D cg c]  }t        | |||||	
       }}na|dk7  r|dk  st              |k  r|rO|	|	dk  r3t        t              |z  t        t              |z  dkD        z   d      }	t        t        |	            t        ||      D cg c]  }t        | |||	
dddf       }}|r|D cg c]  }|D ]  }|  }}}nt!        j"                         5  t!        j$                  d	d
t&               |rE|	|	dk  r)t              |z  t        t              |z  dkD        z   }	t        t        |	            t)        | |||	
||t        	      }|r|D cg c]  }|D ]  }|  }}}ddd       t        |t              r#t        t+        |j-                                     S t        |t              rS t        |t              rt              S t        j.                        S c c}w c c}w c c}}w c c}}w # 1 sw Y   xY w)a4	  Apply a function recursively to each element of a nested data struct.

    Use multiprocessing if num_proc > 1 and the length of data_struct is greater than or equal to
    `parallel_min_length`.

    <Changed version="2.5.0">

    Before version 2.5.0, multiprocessing was not used if `num_proc` was greater than or equal to ``len(iterable)``.

    Now, if `num_proc` is greater than or equal to ``len(iterable)``, `num_proc` is set to ``len(iterable)`` and
    multiprocessing is used.

    </Changed>

    Args:
        function (`Callable`): Function to be applied to `data_struct`.
        data_struct (`Any`): Data structure to apply `function` to.
        dict_only (`bool`, default `False`): Whether only apply `function` recursively to `dict` values in
            `data_struct`.
        map_list (`bool`, default `True`): Whether also apply `function` recursively to `list` elements (besides `dict`
            values).
        map_tuple (`bool`, default `False`): Whether also apply `function` recursively to `tuple` elements (besides
            `dict` values).
        map_numpy (`bool, default `False`): Whether also apply `function` recursively to `numpy.array` elements (besides
            `dict` values).
        num_proc (`int`, *optional*): Number of processes.
            The level in the data struct used for multiprocessing is the first level that has smaller sub-structs,
            starting from the root.
        parallel_min_length (`int`, default `2`): Minimum length of `data_struct` required for parallel
            processing.
            <Added version="2.5.0"/>
        batched (`bool`, defaults to `False`):
            Provide batch of items to `function`.
            <Added version="2.19.0"/>
        batch_size (`int`, *optional*, defaults to `1000`):
            Number of items per batch provided to `function` if `batched=True`.
            If `batch_size <= 0` or `batch_size == None`, provide the full iterable as a single batch to `function`.
            <Added version="2.19.0"/>
        types (`tuple`, *optional*): Additional types (besides `dict` values) to apply `function` recursively to their
            elements.
        disable_tqdm (`bool`, default `True`): Whether to disable the tqdm progressbar.
        desc (`str`, *optional*): Prefix for the tqdm progressbar.

    Returns:
        `Any`
    Nr   r   c              3   h   K   | ])  }t        |      xr t        |      t              kD   + y wrk   )rC   r   )rt   ru   r   r   s     r.   rw   zmap_nested.<locals>.<genexpr>  s-     
Mq:a:CFS]$::
Ms   /2)r  r  r  r  r  r  r   r   )r   r   TignorezL.* is experimental and might be subject to breaking changes in the future\.$)messagecategory)appendr^   r}   r   ndarrayrC   ra   re   r   
map_nestedr   maxr(   r  r	  r
  warningscatch_warningsfilterwarningsUserWarningr   rb   rf   r  )r  r  r  r  r  r  r  r  r  r  r   r  r   r  rm   mapped_batchr  r   s             `      @r.   r%  r%    s
   z }T"U#RZZ(e k4(K1O&-K+&AYF-7T-JtK&&()P[H

MH
MM  
  !!$7%
 
 
RHMS]=P-P!Z1_ X(!:SXQYAY\]A]=^!^`ab
L:>?H xDI
 #w
E4QUW[\]
 
 6<]lP\]k]k]F]$$& 	b##g$
 %q!$X(!:SXQYAY\]A]=^!^JXz BC!(Hgz5,X\^pF :@a,T`a[+a+aa	b  +t$C((*F344k4(MU+= 88F##a
"

 ^  b	b 	bs1    K6KKBK)K#K)#K))K2c                       e Zd ZddZddZy)NestedDataStructureNc                 &    ||| _         y g | _         y rk   )data)r   r/  s     r.   r   zNestedDataStructure.__init__+  s     ,D	"	r0   c                     ||n| j                   }t        |t              r(| j                  t	        |j                                     S t        |t        t        f      r(|D cg c]  }| j                  |      D ]  }|  c}}S |gS c c}}w rk   )r/  rC   ra   flattenr^   re   r}   )r   r/  item	flatteneds       r.   r1  zNestedDataStructure.flatten.  sw    'tTYYdD!<<T[[] 344tUm,*.S$T@RS9ISISS6M Ts   $B
rk   )r   r   r   r   r1  rs   r0   r.   r-  r-  *  s    5r0   r-  c                     	 t        t        j                  j                  |            j                  }| |k  S # t
        $ r Y yw xY w)NT)r	   ospathabspathfreeOSError)needed_bytes	directory
free_bytess      r.   has_sufficient_disk_spacer=  8  sE    	 :;@@
 *$$  s   29 	AAc                     t        j                  | j                  | j                  | j                  | j
                  | j                        }| j                  |_        |S rk   )r   FunctionType__code____globals__r   __defaults____closure____kwdefaults__)r   rd   s     r.   copyfuncrE  @  sI    t/?/?PTPaPacgcscstF //FMr0   Yqueuer   .r   c                 \    t         |di |      D ]  \  }} | j                  |        S )Nrs   )r   put)rG  r   r   r   rd   s        r.   _write_generator_to_queuerJ  I  s3    t~f~. 	6		&Hr0   poolc                 T    | j                   D ch c]  }|j                   c}S c c}w rk   )_poolpid)rK  r   s     r.   _get_pool_pidrO  O  s    ::&aAEE&&&s   %kwargs_iterablec          
   #     K   t        |       }d}t        | t        j                  j                        rt
        nt        j
                  } |       5 }|j                         }|D cg c]  }| j                  t        |||f       }	}	 	 	  |j                  d       t        |       |k7  rd}t        d      2c c}w # t        $ r( t        d |	D              r |j                         rY nY Qw xY w	 |sU|	D 
cg c]  }
|
j                  d       nc c}
w c}
 n.# |s'|	D 
cg c]  }
|
j                  d       nc c}
w c}
 w w xY wd d d        y # 1 sw Y   y xY ww)NFTg?)timeoutc              3   <   K   | ]  }|j                           y wrk   )ready)rt   async_results     r.   rw   z%iflatmap_unordered.<locals>.<genexpr>f  s     RL<--/Rs   zkOne of the subprocesses has abruptly died during map operation.To debug the error, disable multiprocessing.)rO  rC   multiprocessingrK  Poolr   multiprocessQueueapply_asyncrJ  r|   r   r  emptyRuntimeError)rK  r   rP  initial_pool_pidpool_changedmanager_clsmanagerrG  r   async_resultsrU  s              r.   iflatmap_unorderedrb  S  sh     %T*L'o.B.B.G.GH'lNbNbK	 S']l
SYD6f8MN
 
	S#%))D11 !&*::#'L&G  	
  RMRRWbW\WbWbWd  DQRL!!$!/RR  DQRL!!$!/RR  )S S Ss   AE"E& B<E	DC D<E,C2-D1C22D6E<D
EE
&E 
?E

E	E"EE"Tr   nc              #      K   |dk  rt        d|       g }| D ](  }|j                  |       t        |      |k(  s#| g }* |r| y y w)Nr   zInvalid batch size )rF   r#  r   )r   rd  r  r2  s       r.   r  r  x  sd     1u.qc233E Tu:?KE	
  s
   :AA)FF)FTFFNr   FrB   NTN)rK   )[r   r   	functoolsr   multiprocessing.poolrV  r5  rG  r[   r   r'  collections.abcr   
contextlibr   dataclassesr   r   r   r   shutilr	   typingr
   r   r   r   r   rX  multiprocess.poolnumpyr   	tqdm.autor   r   r   parallelr   r   r	  _dillr   r   r   r   r   typing_extensions_typing_extensionsr   ImportError
get_loggerr   logger	lru_cachememoizer/   r(   r  rH   rX   ra   rh   r   r   r   r   r   r   r   r   r   propertyr   r
  boolr}   r%  r-  r=  rE  rF  rY  rJ  rK  rW  r   rO  rb  rc  r^   r  rs   r0   r.   <module>r{     sr    .     	  	   $ % , #   : :      #   02)
 
		H	% 

)0)s5c? )ss )sX&3  $sCx.1I D$N % % 2,C 2, 2,j0%T %82H 2)(^ "  $!F$ucz"F$F$ F$ 	F$
 F$ F$ smF$ F$ F$ F$ E?F$ F$ 3-F$ 	F$R % CLU[[ hqkAQ8R \` eh 'o22779J9J9O9OOP 'UXY\U] 'S
$$))<+<+<+A+AA
BS
3#
$S d^	S
 a[SD CL
8A; 
3 
8DG3D 
  0+///50s   H4 4II