
    `Vg+u                       d Z ddlmZ ddlmZmZ ddlmZmZm	Z	 ddl
ZddlmZmZ ddlmZmZmZmZ ddlmZ dd	lmZ dd
lmZmZmZ ddlmZmZmZ erddl m!Z! d)dZ"d*dZ#d+d,dZ$g dZ%g dZ&d-dZ'd.dZ(	 	 	 	 	 	 	 	 	 d/	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d0dZ)	 	 	 	 	 d1	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d2dZ*d3dZ+	 	 	 	 	 	 	 d4	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d5dZ,	 d6dZ-d7dZ.d8dZ/d9dZ0	 	 	 	 	 	 	 	 	 	 d:dZ1	 	 	 	 d;	 	 	 	 	 	 	 	 	 	 	 d<dZ2	 d=	 	 	 d>dZ3d?dZ4e4	 	 d@	 	 	 	 	 	 	 dAd        Z5e4	 	 d@	 	 	 	 	 	 	 dAd!       Z6e4d@dBd"       Z7e4d@dCd#       Z8e5e6d$Z9dDdEd%Z:dFd&Z;dGd'Z<dHd(Z=y)Iz$
Routines for filling missing data.
    )annotations)partialwraps)TYPE_CHECKINGAnycastN)algoslib)	ArrayLikeAxisFnpt)import_optional_dependency)infer_dtype_from)is_array_likeis_numeric_v_string_likeneeds_i8_conversion)is_valid_na_for_dtypeisnana_value_for_dtype)Indexc                v    t        |       r-t        |       |k7  rt        dt        |        d|       | |   } | S )zJ
    Validate the size of the values passed to ExtensionArray.fillna.
    z'Length of 'value' does not match. Got (z)  expected )r   len
ValueError)valuemasklengths      T/var/www/html/hubwallet-dev/venv/lib/python3.12/site-packages/pandas/core/missing.pycheck_value_sizer   .   sP     Uu:9#e* F#H&  dL    c                   t        |      \  }}t        j                  ||      }t        |      }||    }t        j                  | j
                  t              }|D ]J  }t        | |      r| |k(  }t        |t        j                        s|j                  t        d      }||z  }L |j                         r|t        |       z  }|S )a	  
    Return a masking array of same size/shape as arr
    with entries equaling any member of values_to_mask set to True

    Parameters
    ----------
    arr : ArrayLike
    values_to_mask: list, tuple, or scalar

    Returns
    -------
    np.ndarray[bool]
    )dtypeF)r"   na_value)r   nparrayr   zerosshapeboolr   
isinstancendarrayto_numpyany)arrvalues_to_maskr"   na_masknonnar   xnew_masks           r   mask_missingr3   =   s    " -^<E>
 XXnE:N>"GG8$E 88CIIT*D 	#C+axHh

3#,,4%,HHD	 {{}S	Kr    c                    | dv ry t        | t              r| j                         } | dk(  rd} n| dk(  rd} ddg}d}|r|j                  d       d}| |vrt	        d	| d
|        | S )N)Nasfreqffillpadbfillbackfillzpad (ffill) or backfill (bfill)nearestz(pad (ffill), backfill (bfill) or nearestzInvalid fill method. Expecting z. Got )r)   strlowerappendr   )methodallow_nearestvalid_methods	expectings       r   clean_fill_methodrB   k   s    !!&#WFwFJ'M1IY'>	]":9+VF8TUUMr    )lineartimeindexvalues)r:   zeroslinear	quadraticcubicbarycentrickroghspline
polynomialfrom_derivativespiecewise_polynomialpchipakimacubicsplinec                    |j                  d      }| dv r|t        d      t        t        z   }| |vrt        d| d|  d      | dv r|j                  st        |  d      | S )	Norder)rM   rN   z7You must specify the order of the spline or polynomial.zmethod must be one of z. Got 'z
' instead.)rL   rP   rQ   z4 interpolation requires that the index be monotonic.)getr   
NP_METHODS
SP_METHODSis_monotonic_increasing)r>   rE   kwargsrU   valids        r   clean_interp_methodr\      s    JJwE))emRSS#EU1%xzRSS;;,,(NO  Mr    c                   |dv sJ t        |       dk(  ryt        |        }| j                  dk(  r|j                  d      }|dk(  r|dd j	                         }n*|dk(  r%t        |       dz
  |ddd	   j	                         z
  }|   }|sy|S )
a  
    Retrieves the index of the first valid value.

    Parameters
    ----------
    values : ndarray or ExtensionArray
    how : {'first', 'last'}
        Use this parameter to change between the first or last valid index.

    Returns
    -------
    int or None
    )firstlastr   N      axisr^   r_   )r   r   ndimr,   argmax)rF   howis_valididxpos	chk_notnas        r   find_valid_indexrk      s     ####
6{aV}H{{a<<Q<'
g~"$$&	Vq8DbD>#8#8#:: IMr    c
                    	 t        |      }||t        d      t        | ||||       y|J t        d| |||||||d|
 y# t        $ r d}Y Fw xY w)z
    Wrapper to dispatch to either interpolate_2d or _interpolate_2d_with_fill.

    Notes
    -----
    Alters 'data' in-place.
    Nz&Cannot pass both fill_value and method)r>   rc   limit
limit_area)datarE   rc   r>   rm   limit_directionrn   
fill_value )rB   r   interpolate_2d_interpolate_2d_with_fill)ro   r>   rc   rE   rm   rp   rn   rq   coercedowncastrZ   ms               r   interpolate_array_2drx      s    (f% 	}!EFF!	
*     ! 
	
+!!
	
 
	
 ;  s   A AAc                   t        |fi  t        | j                        rt        | j                  d      dk(  r"t	        |j                        st        d      dg d}	j                         |	vrt        d|	 d d	      *ddg}
j                         |
vrt        d|
 d d      t        j                  d
      t        |      dfd}t        j                  |||        y
)z
    Column-wise application of _interpolate_1d.

    Notes
    -----
    Alters 'data' in-place.

    The signature does differ from _interpolate_1d because it only
    includes what is needed for Block.interpolate.
    F)compatrD   zStime-weighted interpolation only works on Series or DataFrames with a DatetimeIndexrF   )forwardbackwardbothz*Invalid limit_direction: expecting one of z, got 'z'.Ninsideoutsidez%Invalid limit_area: expecting one of z, got .)nobsrm   c                .    t        d| dd y )NF)indicesyvaluesr>   rm   rp   rn   rq   bounds_errorrr   )_interpolate_1d)r   rq   r   rZ   rm   rn   rp   r>   s    r   funcz'_interpolate_2d_with_fill.<locals>.funcA  s4     	 
	
+!!
	
 
	
r    )r   
np.ndarrayreturnNone)r\   r   r"   r   r   r   r<   r	   validate_limit_index_to_interp_indicesr$   apply_along_axis)ro   rE   rc   r>   rm   rp   rn   rq   rZ   valid_limit_directionsvalid_limit_areasr   r   s      ``````   @r   rt   rt     s0   , 00Z4'

5A
"5;;/  
 <%++-O448%&go->bB
 	

 %y1%%'
..78I7J&,a!    d%8E&uf5G
 
* dD)
r    c                F   | j                   }t        |j                        r|j                  d      }|dk(  r|}t	        t
        j                  |      }|S t        j                  |      }|dv r2|j                  t
        j                  k(  rt        j                  |      }|S )zE
    Convert Index to ndarray of indices to pass to NumPy/SciPy.
    i8rC   )rF   rE   )_valuesr   r"   viewr   r$   r*   asarrayobject_r
   maybe_convert_objects)rE   r>   xarrindss       r   r   r   Z  s     ==D4::&yyBJJ% K zz$((zzRZZ'006Kr    c	                V   t        |      }
|
 }|j                         sy|j                         ryt        t	        j
                  |
            }t        |d      }|d}t        t        |            }t        |d      }|t        |      }t        t        d|z   t        |                  }|dk(  r|t        t        |
|d            z  }n5|dk(  r|t        t        |
d|            z  }nt        t        |
||            }|d	k(  r	|||z  z  }n|d
k(  r||z
  |z
  }||z  }t        |      }|t        v rBt	        j                  | |         }t	        j                  | |
   | |   |   ||   |         ||
<   nt        | |   ||   | |
   f||||d|	||
<   t        j                  ||<   y)a  
    Logic for the 1-d interpolation.  The input
    indices and yvalues will each be 1-d arrays of the same length.

    Bounds_error is currently hardcoded to False since non-scipy ones don't
    take it as an argument.

    Notes
    -----
    Fills 'yvalues' in-place.
    Nr^   rg   r   r_   ra   r{   r|   r~   r   )r>   rq   r   rU   )r   r,   allsetr$   flatnonzerork   ranger   _interp_limitsortedrW   argsortinterp_interpolate_scipy_wrappernan)r   r   r>   rm   rp   rn   rq   r   rU   rZ   invalidr[   all_nansfirst_valid_index
start_nanslast_valid_indexend_nanspreserve_nansmid_nansindexers                       r   r   r   p  s   0 7mGHE99;yy{ 2>>'*+H(g> U,-.J'V<w<5--s5z:;H )#"Swq)I%JJ	J	& 3}Wa'G#HH M'5%@A Xh..	y	 j(83! =)M **WU^,99GgenW5wu~g7N
 6ENENG	
 !%	
 	
  VVGM
r    c                d   | d}t        d|       ddlm}	 t        j                  |      }|	j
                  |	j                  t        t        d}
t        | dd      r,| j                  j                  d	      |j                  d	      }} |d
k(  r|	j                  |
d
<   n|dk(  r
t        |
d<   n|dk(  r	t        |
d<   g d}||v r'|dk(  r|}|	j                  | ||||      } ||      }|S |dk(  r>t        |      s|dk  rt!        d|        |	j"                  | |fd|i|} ||      }|S | j$                  j&                  s| j)                         } |j$                  j&                  s|j)                         }|j$                  j&                  s|j)                         }|
|   } || ||fi |}|S )z
    Passed off to scipy.interpolate.interp1d. method is scipy's kind.
    Returns an array interpolated at new_x.  Add any new methods to
    the list in _clean_interp_method.
    z interpolation requires SciPy.scipy)extrar   interpolate)rK   rL   rO   rP   _is_all_datesFr   rQ   rR   rS   )r:   rG   rH   rI   rJ   rN   rN   )kindrq   r   rM   z;order needs to be specified and greater than 0; got order: k)r   r   r   r$   r   barycentric_interpolatekrogh_interpolate_from_derivativesgetattrr   astypepchip_interpolate_akima_interpolate_cubicspline_interpolateinterp1dr   r   UnivariateSplineflags	writeablecopy)r1   ynew_xr>   rq   r   rU   rZ   r   r   alt_methodsinterp1d_methodsterpnew_ys                 r   r   r     s    h45Ewe4!JJuE #::..- 1	K q/5)99##D)5<<+=5*<<G	7	1G	=	 %=M" !!\!F##qv*< $ 
 U( L' 
8	;5A:MeWU  ,{++AqDEDVDU L ww  Aww  A{{$$JJLEV$q!U-f-Lr    c                    ddl m} |j                  j                  } || |j	                  dd      ||      } ||      S )a  
    Convenience function for interpolate.BPoly.from_derivatives.

    Construct a piecewise polynomial in the Bernstein basis, compatible
    with the specified values and derivatives at breakpoints.

    Parameters
    ----------
    xi : array-like
        sorted 1D array of x-coordinates
    yi : array-like or list of array-likes
        yi[i][j] is the j-th derivative known at xi[i]
    order: None or int or array-like of ints. Default: None.
        Specifies the degree of local polynomials. If not None, some
        derivatives are ignored.
    der : int or list
        How many derivatives to extract; None for all potentially nonzero
        derivatives (that is a number equal to the number of points), or a
        list of derivatives to extract. This number includes the function
        value as 0th derivative.
     extrapolate : bool, optional
        Whether to extrapolate to ouf-of-bounds points based on first and last
        intervals, or to return NaNs. Default: True.

    See Also
    --------
    scipy.interpolate.BPoly.from_derivatives

    Returns
    -------
    y : scalar or array-like
        The result, of length R or length M or M by R.
    r   r   rd   ra   )ordersextrapolate)r   r   BPolyrO   reshape)	xiyir1   rU   derr   r   r>   rw   s	            r   r   r     s?    D " //Fr2::b!$ULAQ4Kr    c                J    ddl m} |j                  | ||      } |||      S )a[  
    Convenience function for akima interpolation.
    xi and yi are arrays of values used to approximate some function f,
    with ``yi = f(xi)``.

    See `Akima1DInterpolator` for details.

    Parameters
    ----------
    xi : array-like
        A sorted list of x-coordinates, of length N.
    yi : array-like
        A 1-D array of real values.  `yi`'s length along the interpolation
        axis must be equal to the length of `xi`. If N-D array, use axis
        parameter to select correct axis.
    x : scalar or array-like
        Of length M.
    der : int, optional
        How many derivatives to extract; None for all potentially
        nonzero derivatives (that is a number equal to the number
        of points), or a list of derivatives to extract. This number
        includes the function value as 0th derivative.
    axis : int, optional
        Axis in the yi array corresponding to the x-coordinate values.

    See Also
    --------
    scipy.interpolate.Akima1DInterpolator

    Returns
    -------
    y : scalar or array-like
        The result, of length R or length M or M by R,

    r   r   rb   )nu)r   r   Akima1DInterpolator)r   r   r1   r   rc   r   Ps          r   r   r   E  s+    H "''BT':AQ3<r    c                J    ddl m} |j                  | ||||      } ||      S )aq  
    Convenience function for cubic spline data interpolator.

    See `scipy.interpolate.CubicSpline` for details.

    Parameters
    ----------
    xi : array-like, shape (n,)
        1-d array containing values of the independent variable.
        Values must be real, finite and in strictly increasing order.
    yi : array-like
        Array containing values of the dependent variable. It can have
        arbitrary number of dimensions, but the length along ``axis``
        (see below) must match the length of ``x``. Values must be finite.
    x : scalar or array-like, shape (m,)
    axis : int, optional
        Axis along which `y` is assumed to be varying. Meaning that for
        ``x[i]`` the corresponding values are ``np.take(y, i, axis=axis)``.
        Default is 0.
    bc_type : string or 2-tuple, optional
        Boundary condition type. Two additional equations, given by the
        boundary conditions, are required to determine all coefficients of
        polynomials on each segment [2]_.
        If `bc_type` is a string, then the specified condition will be applied
        at both ends of a spline. Available conditions are:
        * 'not-a-knot' (default): The first and second segment at a curve end
          are the same polynomial. It is a good default when there is no
          information on boundary conditions.
        * 'periodic': The interpolated functions is assumed to be periodic
          of period ``x[-1] - x[0]``. The first and last value of `y` must be
          identical: ``y[0] == y[-1]``. This boundary condition will result in
          ``y'[0] == y'[-1]`` and ``y''[0] == y''[-1]``.
        * 'clamped': The first derivative at curves ends are zero. Assuming
          a 1D `y`, ``bc_type=((1, 0.0), (1, 0.0))`` is the same condition.
        * 'natural': The second derivative at curve ends are zero. Assuming
          a 1D `y`, ``bc_type=((2, 0.0), (2, 0.0))`` is the same condition.
        If `bc_type` is a 2-tuple, the first and the second value will be
        applied at the curve start and end respectively. The tuple values can
        be one of the previously mentioned strings (except 'periodic') or a
        tuple `(order, deriv_values)` allowing to specify arbitrary
        derivatives at curve ends:
        * `order`: the derivative order, 1 or 2.
        * `deriv_value`: array-like containing derivative values, shape must
          be the same as `y`, excluding ``axis`` dimension. For example, if
          `y` is 1D, then `deriv_value` must be a scalar. If `y` is 3D with
          the shape (n0, n1, n2) and axis=2, then `deriv_value` must be 2D
          and have the shape (n0, n1).
    extrapolate : {bool, 'periodic', None}, optional
        If bool, determines whether to extrapolate to out-of-bounds points
        based on first and last intervals, or to return NaNs. If 'periodic',
        periodic extrapolation is used. If None (default), ``extrapolate`` is
        set to 'periodic' for ``bc_type='periodic'`` and to True otherwise.

    See Also
    --------
    scipy.interpolate.CubicHermiteSpline

    Returns
    -------
    y : scalar or array-like
        The result, of shape (m,)

    References
    ----------
    .. [1] `Cubic Spline Interpolation
            <https://en.wikiversity.org/wiki/Cubic_Spline_Interpolation>`_
            on Wikiversity.
    .. [2] Carl de Boor, "A Practical Guide to Splines", Springer-Verlag, 1978.
    r   r   )rc   bc_typer   )r   r   CubicSpline)r   r   r1   rc   r   r   r   r   s           r   r   r   p  s3    L "
BT7 	  	A Q4Kr    c                   t        |       }|j                         slt        | d      }|d}t        | d      }|t        |       }t	        | ||       |dk(  r	d|||d	z    n|d
k(  rdx|d| ||d	z   d t
        j                  | |<   y)a  
    Apply interpolation and limit_area logic to values along a to-be-specified axis.

    Parameters
    ----------
    values: np.ndarray
        Input array.
    method: str
        Interpolation method. Could be "bfill" or "pad"
    limit: int, optional
        Index limit on interpolation.
    limit_area: str
        Limit area for interpolation. Can be "inside" or "outside"

    Notes
    -----
    Modifies values in-place.
    r^   r   Nr   r_   )r>   rm   r~   Fra   r   )r   r   rk   r   rs   r$   r   )rF   r>   rm   rn   r   r^   r_   s          r   _interpolate_with_limit_arear     s    , 6lG;;= W5=EF3<v;D	
 !(-GED1H%9$499GFUOgdQhj1&&w
r    c                b   |)t        j                  t        t        |||      ||        y|dk(  rd nd }| j                  dk(  r7|dk7  rt        d      | j                  t        d| j                  z               } t        |      } ||       }|d	k(  rt        ||
       yt        ||
       y)a  
    Perform an actual interpolation of values, values will be make 2-d if
    needed fills inplace, returns the result.

    Parameters
    ----------
    values: np.ndarray
        Input array.
    method: str, default "pad"
        Interpolation method. Could be "bfill" or "pad"
    axis: 0 or 1
        Interpolation axis
    limit: int, optional
        Index limit on interpolation.
    limit_area: str, optional
        Limit area for interpolation. Can be "inside" or "outside"

    Notes
    -----
    Modifies values in-place.
    N)r>   rm   rn   r   c                    | S Nrr   r1   s    r   <lambda>z interpolate_2d.<locals>.<lambda>"  s     r    c                    | j                   S r   )Tr   s    r   r   z interpolate_2d.<locals>.<lambda>"  s
     r    ra   z0cannot interpolate on a ndim == 1 with axis != 0ra   r7   rm   )r$   r   r   r   re   AssertionErrorr   tupler'   rB   _pad_2d_backfill_2d)rF   r>   rc   rm   rn   transftvaluess          r   rs   rs     s    8 
 ,%	 %	
( 	"aikmF {{a19 !STTdV\\&9 :;v&FVnG u%  	WE*
r    c                ^    |t        |       }|j                  t        j                        }|S r   )r   r   r$   uint8)rF   r   s     r   _fillna_prepr   6  s)    
 |F|99RXXDKr    c                L     t               d fd	       }t        t        |      S )z>
    Wrapper to handle datetime64 and timedelta64 dtypes.
    c                    t        | j                        rG|t        |       } | j                  d      ||      \  }}|j                  | j                        |fS  | ||      S )Nr   )rm   r   )r   r"   r   r   )rF   rm   r   resultr   s       r   new_funcz&_datetimelike_compat.<locals>.new_funcG  s_    v||,|F|D 1TJLFD;;v||,d22F%d33r    NN)r   r   r   )r   r   s   ` r   _datetimelike_compatr   B  s*    
 4[	4 	4 8r    c                R    t        | |      }t        j                  | ||       | |fS Nr   )r   r	   pad_inplacerF   rm   r   s      r   _pad_1dr   V  s,     %D	fd%04<r    c                R    t        | |      }t        j                  | ||       | |fS r   )r   r	   backfill_inplacer   s      r   _backfill_1dr   a  s,     %D	64u54<r    c                    t        | |      }t        j                  | j                        rt	        j
                  | ||       | |fS 	 | |fS r   )r   r$   r   r'   r	   pad_2d_inplacer   s      r   r   r   l  sK    %D	vvfllVT7 4< 	4<r    c                    t        | |      }t        j                  | j                        rt	        j
                  | ||       | |fS 	 | |fS r   )r   r$   r   r'   r	   backfill_2d_inplacer   s      r   r   r   x  sK    %D	vvfll!!&$e< 4< 	4<r    r7   r9   c                T    t        |       } |dk(  r	t        |    S t        t        d|    S )Nra   r   )rB   _fill_methodsr   r   )r>   re   s     r   get_fill_funcr    s.    v&FqyV$$5f==r    c                    t        | d      S )NT)r?   )rB   )r>   s    r   clean_reindex_fill_methodr    s    V488r    c                R   t        |       t               }t               }fd}|0|dk(  r"t        t        j                  |       d         }n	 || |      }|J|dk(  r|S t	         || ddd   |            }t        dz
  t        j
                  |      z
        }|dk(  r|S ||z  S )ak  
    Get indexers of values that won't be filled
    because they exceed the limits.

    Parameters
    ----------
    invalid : np.ndarray[bool]
    fw_limit : int or None
        forward limit to index
    bw_limit : int or None
        backward limit to index

    Returns
    -------
    set of indexers

    Notes
    -----
    This is equivalent to the more readable, but slower

    .. code-block:: python

        def _interp_limit(invalid, fw_limit, bw_limit):
            for x in np.where(invalid)[0]:
                if invalid[max(0, x - fw_limit):x + bw_limit + 1].all():
                    yield x
    c           	        t        |      }t        | |dz         j                  d      }t        t	        j
                  |      d   |z         t        t	        j
                  | d |dz     j                         dk(        d         z  }|S )Nra   r   )min_rolling_windowr   r   r$   wherecumsum)r   rm   windowedidxNs       r   innerz_interp_limit.<locals>.inner  s    E1"7EAI6::1="((8$Q'%/03HHw{++335:;A>4
 
 
r    Nr   rd   ra   )r   r   r$   r  listr   )r   fw_limitbw_limitf_idxb_idxr  	b_idx_invr  s          @r   r   r     s    > 	GAEEEE q=)!,-E'8,Eq= LU74R4=(;<IA

9 556E1}5=r    c                    | j                   dd | j                   d   |z
  dz   |fz   }| j                  | j                  d   fz   }t        j                  j                  j                  | ||      S )z
    [True, True, False, True, False], 2 ->

    [
        [True,  True],
        [True, False],
        [False, True],
        [True, False],
    ]
    Nrd   ra   )r'   strides)r'   r  r$   r
   stride_tricks
as_strided)awindowr'   r  s       r   r  r    sj     GGCRLAGGBK&014f==Eii199R=**G66**1E7*KKr    )r   npt.NDArray[np.bool_]r   int)r-   r   r   r  )F)r>   
str | Noner?   r(   )r>   r;   rE   r   r   r;   )rg   r;   r   
int | None)	r7   r   NNr{   NNFN)ro   r   r>   r;   rc   r  rE   zIndex | Nonerm   r  rp   r;   rn   r  rq   
Any | Noneru   r(   rv   r  r   r   )rC   Nr{   NN)ro   r   rE   r   rc   r  r>   r;   rm   r  rp   r;   rn   r  rq   r  r   r   )rE   r   r>   r;   r   r   )rC   Nr{   NNFN)r   r   r   r   r>   r  rm   r  rp   r;   rn   r  rq   r  r   r(   rU   r  )NFN)Nr   F)r   r   )r   z
not-a-knotN)
rF   r   r>   r;   rm   r  rn   r  r   r   )r7   r   NN)rF   r   r>   r;   rc   r   rm   r  rn   r  r   r   r   )r   npt.NDArray[np.bool_] | Noner   r  )r   r   r   r   r   )rF   r   rm   r  r   r  r   z(tuple[np.ndarray, npt.NDArray[np.bool_]])rF   r   r   r  )r   r  r   )re   r  )r   r  )r   r  )r  r  r  r  r   r  )>__doc__
__future__r   	functoolsr   r   typingr   r   r   numpyr$   pandas._libsr	   r
   pandas._typingr   r   r   r   pandas.compat._optionalr   pandas.core.dtypes.castr   pandas.core.dtypes.commonr   r   r   pandas.core.dtypes.missingr   r   r   pandasr   r   r3   rB   rW   rX   r\   rk   rx   rt   r   r   r   r   r   r   r   rs   r   r   r   r   r   r   r   r  r  r   r  rr   r    r   <module>r,     s   #    ? 4 
  +\0 3

$&"N $!!3
33 3 	3
 3 3 3 3 3 3 
3t $!!P
PP P 	P
 P P P P 
Pf2 "$!!aaa a 	a
 a a a a aJ EICL(V(VL^-- #-,6-DN-	-d !DDD D 	D
 D 
DP 26	.		(  )- ' .	   )- ' .	       \:>9>BLr    