o
    ?eA                     @   s   d 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 g dZ	e
dejZe
d	ejZe
d
ejZe
dejZd!ddZdd Zd"ddZdd Zd#ddZdd Zdd Zd$ddZdd Zd%d dZdS )&zSpecial Math Ops.    N)constant_op)ops)	array_ops)math_ops)erfinvndtrndtrilog_ndtrlog_cdf_laplaceii      r   c                 C   l   t j|| gd$ t j| dd} | jjtjtjfvr!td| j t	| W  d   S 1 s/w   Y  dS )aG  Normal distribution function.

  Returns the area under the Gaussian probability density function, integrated
  from minus infinity to x:

  ```
                    1       / x
     ndtr(x)  = ----------  |    exp(-0.5 t**2) dt
                sqrt(2 pi)  /-inf

              = 0.5 (1 + erf(x / sqrt(2)))
              = 0.5 erfc(x / sqrt(2))
  ```

  Args:
    x: `Tensor` of type `float32`, `float64`.
    name: Python string. A name for the operation (default="ndtr").

  Returns:
    ndtr: `Tensor` with `dtype=x.dtype`.

  Raises:
    TypeError: if `x` is not floating-type.
  valuesxname=x.dtype=%s is not handled, see docstring for supported types.N)
r   
name_scopeconvert_to_tensordtypeas_numpy_dtypenpfloat32float64	TypeError_ndtrr   r    r   q/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/distributions/special_math.pyr   k   s   $c                 C   sx   t jdtd | jdd}| | }t|}tt	||dt
| tt|ddt| t|}d| S )zImplements ndtr core logic.      ?       @half_sqrt_2)r   r         ?        )r   constantr   sqrtr   r   absr   where_v2lesserfgreatererfc)r   r"   wzyr   r   r   r      s   
r   r   c                 C   r   )a  The inverse of the CDF of the Normal distribution function.

  Returns x such that the area under the pdf from minus infinity to x is equal
  to p.

  A piece-wise rational approximation is done for the function.
  This is a port of the implementation in netlib.

  Args:
    p: `Tensor` of type `float32`, `float64`.
    name: Python string. A name for the operation (default="ndtri").

  Returns:
    x: `Tensor` with `dtype=p.dtype`.

  Raises:
    TypeError: if `p` is not floating-type.
  r   pr   z=p.dtype=%s is not handled, see docstring for supported types.N)
r   r   r   r   r   r   r   r   r   _ndtri)r0   r   r   r   r   r      s   $c              
      s  g d}g d}g d}g d}g d}g d} fdd t | td	 kd
|  | }t |dkt t | td| jj|}|d }	|	d }
|	|	|
  |
| |
|   }|t	dtj
  9 }t	d	t| }|t||  } d
| | d
| | | } d
| | d
| | | }|| }|| }t |td	k|t |dk||}t | d
td	 k|| }tjtj| jd}t t | |}t | dk| t | d
k||}|S )zImplements ndtri core logic.)g~g;+@gVLgX@g-^OM)	gͿgcu/@gٷaTgSi@g_6V.lgԁ5U@g@gt ҕE?r#   )	glLgAcgwDglz9~@g>F^-@gN
F@gBהL@gyՒm?@gێ<8@)	g}yNgmENg23¿g <	@gE؇.@gF"D@go)F@g;Z/@r#   )	gX0:>g4"L)L>g3?gM5iPV?gQ&^E?gT?g+@gx'1@gtՓ	@)	g=kv)=>gC>g)e+5?gǶ'|?g<_?g b*G?g8ҪMp@g(V@r#   c                    s>   t || jj}|jst| S |d  | |dd |   S )z2Compute n_th order polynomial via Horner's method.r      N)r   arrayr   r   sizer   
zeros_like)varZcoeffs_create_polynomialr   r   r8      s   
z"_ndtri.<locals>._create_polynomialg       r#   r$   r       r!   g       @)r   )r   r(   r   expm1fillshaper3   r   r   r&   pir   logexpr   r%   inf)r0   p0q0p1q1p2q2Zmaybe_complement_pZsanitized_mcpr-   ZwwZx_for_big_pr.   Z
first_termZsecond_term_small_pZsecond_term_otherwiseZx_for_small_pZx_otherwiser   Zinfinity_scalarinfinityZx_nan_replacedr   r7   r   r1      s\   r1      r	   c                 C   s  t |ts	td|dk rtd|dkrtdtj|| gdV tj| dd} | jjt	j
kr5t}t}n| jjt	jkrAt}t}ntd	| j tt| |t|   tt| |ttt| |tt| ||W  d
   S 1 szw   Y  d
S )a  Log Normal distribution function.

  For details of the Normal distribution function see `ndtr`.

  This function calculates `(log o ndtr)(x)` by either calling `log(ndtr(x))` or
  using an asymptotic series. Specifically:
  - For `x > upper_segment`, use the approximation `-ndtr(-x)` based on
    `log(1-x) ~= -x, x << 1`.
  - For `lower_segment < x <= upper_segment`, use the existing `ndtr` technique
    and take a log.
  - For `x <= lower_segment`, we use the series approximation of erf to compute
    the log CDF directly.

  The `lower_segment` is set based on the precision of the input:

  ```
  lower_segment = { -20,  x.dtype=float64
                  { -10,  x.dtype=float32
  upper_segment = {   8,  x.dtype=float64
                  {   5,  x.dtype=float32
  ```

  When `x < lower_segment`, the `ndtr` asymptotic series approximation is:

  ```
     ndtr(x) = scale * (1 + sum) + R_N
     scale   = exp(-0.5 x**2) / (-x sqrt(2 pi))
     sum     = Sum{(-1)^n (2n-1)!! / (x**2)^n, n=1:N}
     R_N     = O(exp(-0.5 x**2) (2N+1)!! / |x|^{2N+3})
  ```

  where `(2n-1)!! = (2n-1) (2n-3) (2n-5) ...  (3) (1)` is a
  [double-factorial](https://en.wikipedia.org/wiki/Double_factorial).


  Args:
    x: `Tensor` of type `float32`, `float64`.
    series_order: Positive Python `integer`. Maximum depth to
      evaluate the asymptotic expansion. This is the `N` above.
    name: Python string. A name for the operation (default="log_ndtr").

  Returns:
    log_ndtr: `Tensor` with `dtype=x.dtype`.

  Raises:
    TypeError: if `x.dtype` is not handled.
    TypeError: if `series_order` is a not Python `integer.`
    ValueError:  if `series_order` is not in `[0, 30]`.
  z&series_order must be a Python integer.r   z"series_order must be non-negative.   zseries_order must be <= 30.r   r   r   zx.dtype=%s is not supported.N)
isinstanceintr   
ValueErrorr   r   r   r   r   r   r   LOGNDTR_FLOAT64_LOWERLOGNDTR_FLOAT64_UPPERr   LOGNDTR_FLOAT32_LOWERLOGNDTR_FLOAT32_UPPERr   r(   r   r+   r   r>   maximum_log_ndtr_lowerminimum)r   series_orderr   Zlower_segmentZupper_segmentr   r   r   r	     s2   
2


$c                 C   sF   t | }d| t |   dtdtj   }|t t| | S )zGAsymptotic expansion version of `Log[cdf(x)]`, appropriate for `x<<-1`.      r    r!   )r   squarer>   r   r=   _log_ndtr_asymptotic_series)r   rT   x_2Z	log_scaler   r   r   rR   r  s   
(rR   c           	      C   s   | j j}|dkrtd|S t| }t| }t| }|}td|d D ]!}tt	d| d || }|d r?||7 }n||7 }||9 }q&d| | S )z2Calculates the asymptotic series used in log_ndtr.r   r2   r9   r#   )
r   r   r   r3   r   rV   r   r5   range_double_factorial)	r   rT   r   rX   Zeven_sumZodd_sumZx_2nnr/   r   r   r   rW   z  s   




rW   r   c                 C   s~   t j|| gd- t j| dd} | jjtjtjfvr!td| j t	| d d t
d W  d   S 1 s8w   Y  dS )	a  The inverse function for erf, the error function.

  Args:
    x: `Tensor` of type `float32`, `float64`.
    name: Python string. A name for the operation (default="erfinv").

  Returns:
    x: `Tensor` with `dtype=x.dtype`.

  Raises:
    TypeError: if `x` is not floating-type.
  r   r   r   r   r#   r!   r9   N)r   r   r   r   r   r   r   r   r   r   r&   r   r   r   r   r     s   $c                 C   s   t t | ddS )z;The double factorial function for small Python integer `n`.r2   )r   prodZarange)r[   r   r   r   rZ     s   rZ   r
   c                 C   s   t j|| gd0 t j| dd} td |  }tt|  }td| }t	
| dk ||W  d   S 1 s;w   Y  dS )a  Log Laplace distribution function.

  This function calculates `Log[L(x)]`, where `L(x)` is the cumulative
  distribution function of the Laplace distribution, i.e.

  ```L(x) := 0.5 * int_{-infty}^x e^{-|t|} dt```

  For numerical accuracy, `L(x)` is computed in different ways depending on `x`,

  ```
  x <= 0:
    Log[L(x)] = Log[0.5] + x, which is exact

  0 < x:
    Log[L(x)] = Log[1 - 0.5 * e^{-x}], which is exact
  ```

  Args:
    x: `Tensor` of type `float32`, `float64`.
    name: Python string. A name for the operation (default="log_ndtr").

  Returns:
    `Tensor` with `dtype=x.dtype`.

  Raises:
    TypeError: if `x.dtype` is not handled.
  r   r   r   r!   rU   r$   N)r   r   r   r   r>   r   r?   r'   log1pr   r(   )r   r   Zlower_solutionZsafe_exp_neg_xZupper_solutionr   r   r   r
     s   $)r   )r   )rH   r	   )r   )r
   )__doc__numpyr   Ztensorflow.python.frameworkr   r   Ztensorflow.python.opsr   r   __all__r3   r   rM   r   rO   rN   rP   r   r   r   r1   r	   rR   rW   r   rZ   r
   r   r   r   r   <module>   s*   F
#

^\
