U
    e»{jÜ<  ã                   @   st   d Z ddlZddlZddlmZmZmZmZ dddddgZ	G d	d
„ d
e
ƒZeƒ ZejZdd„ Zdd„ Zddd„ZdS )zConverters for Quantity.é    N)ÚUnitConversionErrorÚ
UnitsErrorÚUnitTypeErrorÚdimensionless_unscaledÚcan_have_arbitrary_unitÚconverters_and_unitÚcheck_outputÚUFUNC_HELPERSÚUNSUPPORTED_UFUNCSc                       sD   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Zdd	„ Z‡ fd
d„Z‡  Z	S )ÚUfuncHelpersa  Registry of unit conversion functions to help ufunc evaluation.

    Based on dict for quick access, but with a missing method to load
    helpers for additional modules such as scipy.special and erfa.

    Such modules should be registered using ``register_module``.
    c                    s*   i | _ tƒ | _t ¡ | _tƒ j||Ž d S ©N)ÚmodulesÚsetÚUNSUPPORTEDÚ	threadingÚRLockÚ_lockÚsuperÚ__init__)ÚselfÚargsÚkwargs©Ú	__class__© úg/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/units/quantity_helper/converters.pyr   !   s    
zUfuncHelpers.__init__c              	   C   s&   | j � ||dœ| j|< W 5 Q R X dS )a  Register (but do not import) a set of ufunc helpers.

        Parameters
        ----------
        module : str
            Name of the module with the ufuncs (e.g., 'scipy.special').
        names : iterable of str
            Names of the module ufuncs for which helpers are available.
        importer : callable
            Function that imports the ufuncs and returns a dict of helpers
            keyed by those ufuncs.  If the value is `None`, the ufunc is
            explicitly *not* supported.
        )ÚnamesÚimporterN)r   r   )r   Úmoduler   r   r   r   r   Úregister_module'   s    zUfuncHelpers.register_modulec              	   C   s2   | j �" | j |¡}|  |d ƒ ¡ W 5 Q R X dS )zÐImport the helpers from the given module using its helper function.

        Parameters
        ----------
        module : str
            Name of the module. Has to have been registered beforehand.
        r   N)r   r   ÚpopÚupdate)r   r   Úmodule_infor   r   r   Úimport_module8   s    zUfuncHelpers.import_modulec              
   C   sÂ   | j �  || kr$| | W  5 Q R £ S || jkr@td|j› d�ƒ‚t| j ¡ ƒD ]R\}}|j|d krNz|  |¡ W n tk
r†   Y qNX | |   W  5 Q R £ S qNW 5 Q R X td|j› d�ƒ‚dS )z Called if a ufunc is not found.

        Check if the ufunc is in any of the available modules, and, if so,
        import the helpers for that module.
        zCannot use ufunc 'z' with quantitiesr   zunknown ufunc zm.  If you believe this ufunc should be supported, please raise an issue on https://github.com/astropy/astropyN)	r   r   Ú	TypeErrorÚ__name__Úlistr   Úitemsr#   ÚImportError)r   Zufuncr   r"   r   r   r   Ú__missing__D   s    
	$ÿzUfuncHelpers.__missing__c              	      sZ   | j �J |d kr.|  j|hO  _|  |d ¡ ntƒ  ||¡ |  j|h8  _W 5 Q R X d S r   )r   r   r    r   Ú__setitem__)r   ÚkeyÚvaluer   r   r   r*   i   s    zUfuncHelpers.__setitem__)
r%   Ú
__module__Ú__qualname__Ú__doc__r   r   r#   r)   r*   Ú__classcell__r   r   r   r   r      s   %r   c                 C   s"   t  t  t  | d¡t  | ¡ ¡¡S )aO  Test whether the items in value can have arbitrary units

    Numbers whose value does not change upon a unit change, i.e.,
    zero, infinity, or not-a-number

    Parameters
    ----------
    value : number or array

    Returns
    -------
    bool
        `True` if each member is either zero or not finite, `False` otherwise
    g        )ÚnpÚallÚ
logical_orÚequalÚisfinite)r,   r   r   r   r   {   s    c                 G   s  t |  }|dks&|dk�rš| jdk�ršdd„ |D ƒ}|| f|žŽ \}}tdd„ |D ƒƒrØzHt|ƒD ]:\}}|dk	rtqbt|| ƒrŠd	||< qbtd
| j› d�ƒ‚qbW n6 tk
rÖ   td | jd 	dd„ |D ƒ¡¡ƒ‚Y nX |dk�r|d d	ksü|d t
k�rt
}n”|d d	k�r|d }	n|d  t
¡j}	z|d |	 }W nZ tk
�r” }
 z:z|d  t
¡|d< W n tk
�r~   |
‚Y nX t
}W 5 d	}
~
X Y nX �nj| j}t|d dd	ƒ}|dk�r
|dk�r
|dk�rÖ|g}n|t|d dd	ƒg}|| f|žŽ \}}| dd	¡ nx|dk�rP|dk�rP|| ||ƒ\}}|d	d… }|dk�r‚|d	g7 }n2|dk�rr|dk�rrt|› d�ƒ‚td|› d�ƒ‚|d	k	�r®|d	k�r®td|› d| j› d�ƒ‚|d d	k	�sì|d	k	�r||k	�r| |¡�rì| |¡dk�rtd|› d| j› d�ƒ‚||fS )a>  Determine the required converters and the unit of the ufunc result.

    Converters are functions required to convert to a ufunc's expected unit,
    e.g., radian for np.sin; or to ensure units of two inputs are consistent,
    e.g., for np.add.  In these examples, the unit of the result would be
    dimensionless_unscaled for np.sin, and the same consistent unit for np.add.

    Parameters
    ----------
    function : `~numpy.ufunc`
        Numpy universal function
    method : str
        Method with which the function is evaluated, e.g.,
        '__call__', 'reduce', etc.
    *args :  `~astropy.units.Quantity` or ndarray subclass
        Input arguments to the function

    Raises
    ------
    TypeError : when the specified function cannot be used with Quantities
        (e.g., np.logical_or), or when the routine does not know how to handle
        the specified function (in which case an issue should be raised on
        https://github.com/astropy/astropy).
    UnitTypeError : when the conversion to the required (or consistent) units
        is not possible.
    Ú__call__Úouteré   c                 S   s   g | ]}t |d dƒ‘qS )ÚunitN)Úgetattr©Ú.0Úargr   r   r   Ú
<listcomp>³   s     z'converters_and_unit.<locals>.<listcomp>c                 s   s   | ]}|d kV  qdS )FNr   )r<   Ú	converterr   r   r   Ú	<genexpr>¸   s     z&converters_and_unit.<locals>.<genexpr>FNzCan only apply 'zz' function to dimensionless quantities when other argument is not a quantity (unless the latter is all zero/infinity/nan).z.Unsupported operand type(s) for ufunc {}: '{}'ú,c                 S   s   g | ]}|j j‘qS r   )r   r%   r;   r   r   r   r>   Ó   s     r   é   r9   Úat>   ÚreduceatÚ
accumulateÚreducerD   >   r7   rD   rE   rF   z$ only supported for binary functionszUnexpected ufunc method zS.  If this should work, please raise an issue on https://github.com/astropy/astropyzCannot use 'z' method on ufunc z: with a Quantity instance as the result is not a Quantity.g      ð?z6 with a Quantity instance as it would change the unit.)r	   ÚninÚanyÚ	enumerater   r   r%   r$   ÚformatÚjoinr   Útor,   Ú
ValueErrorZ_get_converterr:   ÚinsertZis_equivalentr   )ÚfunctionÚmethodr   Zufunc_helperZunitsÚ
convertersZresult_unitÚir?   ÚpÚexcrG   r9   r   r   r   r   �   sŒ     
ÿ
þÿ






ÿÿÿþýýÿc                    sJ  t | tƒr(t‡ ‡fdd„t| |ƒD ƒƒS | dkr4dS t| dƒ�r|dkrrtd ˆ dk	rddˆ j› d�ndt| ƒ¡ƒ‚|  |¡\}}|s¾|t| ƒks¾t	d	 |ˆ dk	r®dˆ j› d�ndt| ƒ|¡ƒ‚ˆrü| j
jsütjˆŽ }|jsütj|| j
d
d�sütd| j
› �ƒ‚|  tj¡S |dk�sB|tk�sBt	d ˆ dk	�r:dˆ j› d�nd¡ƒ‚| S dS )a¨  Check that function output can be stored in the output array given.

    Parameters
    ----------
    output : array or `~astropy.units.Quantity` or tuple
        Array that should hold the function output (or tuple of such arrays).
    unit : `~astropy.units.Unit` or None, or tuple
        Unit that the output will have, or `None` for pure numbers (should be
        tuple of same if output is a tuple of outputs).
    inputs : tuple
        Any input arguments.  These should be castable to the output.
    function : callable
        The function that will be producing the output.  If given, used to
        give a more informative error message.

    Returns
    -------
    arrays : ndarray view or tuple thereof
        The view(s) is of ``output``.

    Raises
    ------
    UnitTypeError : If ``unit`` is inconsistent with the class of ``output``

    TypeError : If the ``inputs`` cannot be cast safely to ``output``.
    c                 3   s    | ]\}}t ||ˆˆ ƒV  qd S r   )r   )r<   Zoutput_Zunit_©rO   Úinputsr   r   r@   A  s   ÿzcheck_output.<locals>.<genexpr>NÚ__quantity_subclass__z1Cannot store non-quantity output{} in {} instancez from z	 functionÚ zNCannot store output with unit '{}'{} in {} instance.  Use {} instance instead.Z	same_kind)Zcastingz=Arguments cannot be cast safely to inplace output with dtype=zBCannot store quantity with dimension {}in a non-Quantity instance.zresulting from z
 function )Ú
isinstanceÚtupleÚzipÚhasattrr$   rJ   r%   ÚtyperW   r   Zdtyper   r1   Úresult_typeZcan_castÚviewZndarrayr   )Úoutputr9   rV   rO   Zq_clsZsubokr^   r   rU   r   r   %  s^    
þÿúÿÿ÷ÿ
ÿþ
ÿÿüÿ	)N)r/   r   Únumpyr1   Zastropy.units.corer   r   r   r   Ú__all__Údictr   r	   r   r
   r   r   r   r   r   r   r   Ú<module>   s    û	_ 