# Copyright 2018 The JAX Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import numpy as np from jax import lax from jax._src.lax.lax import _const as _lax_const from jax._src.numpy.util import promote_args_inexact from jax.numpy import arctan from jax._src.typing import Array, ArrayLike def logpdf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy log probability distribution function. JAX implementation of :obj:`scipy.stats.cauchy` ``logpdf``. The Cauchy probability distribution function is .. math:: f(x) = \frac{1}{\pi(1 + x^2)} Args: x: arraylike, value at which to evaluate the PDF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of logpdf values See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ x, loc, scale = promote_args_inexact("cauchy.logpdf", x, loc, scale) pi = _lax_const(x, np.pi) scaled_x = lax.div(lax.sub(x, loc), scale) normalize_term = lax.log(lax.mul(pi, scale)) return lax.neg(lax.add(normalize_term, lax.log1p(lax.mul(scaled_x, scaled_x)))) def pdf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy probability distribution function. JAX implementation of :obj:`scipy.stats.cauchy` ``pdf``. The Cauchy probability distribution function is .. math:: f(x) = \frac{1}{\pi(1 + x^2)} Args: x: arraylike, value at which to evaluate the PDF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of pdf values See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ return lax.exp(logpdf(x, loc, scale)) def cdf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy cumulative distribution function. JAX implementation of :obj:`scipy.stats.cauchy` ``cdf``. The cdf is defined as .. math:: f_{cdf} = \int_{-\infty}^x f_{pdf}(y) \mathrm{d}y where here :math:`f_{pdf}` is the Cauchy probability distribution function, :func:`jax.scipy.stats.cauchy.pdf`. Args: x: arraylike, value at which to evaluate the CDF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of cdf values. See Also: - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ x, loc, scale = promote_args_inexact("cauchy.cdf", x, loc, scale) pi = _lax_const(x, np.pi) scaled_x = lax.div(lax.sub(x, loc), scale) return lax.add(_lax_const(x, 0.5), lax.mul(lax.div(_lax_const(x, 1.), pi), arctan(scaled_x))) def logcdf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy log cumulative distribution function. JAX implementation of :obj:`scipy.stats.cauchy` ``logcdf`` The cdf is defined as .. math:: f_{cdf} = \int_{-\infty}^x f_{pdf}(y) \mathrm{d}y where here :math:`f_{pdf}` is the Cauchy probability distribution function, :func:`jax.scipy.stats.cauchy.pdf`. Args: x: arraylike, value at which to evaluate the CDF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of logcdf values. See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ return lax.log(cdf(x, loc, scale)) def sf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy distribution log survival function. JAX implementation of :obj:`scipy.stats.cauchy` ``sf``. The survival function is defined as .. math:: f_{sf}(x) = 1 - f_{cdf}(x) where :math:`f_{cdf}(x)` is the cumulative distribution function, :func:`jax.scipy.stats.cauchy.cdf`. Args: x: arraylike, value at which to evaluate the SF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of sf values See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ x, loc, scale = promote_args_inexact("cauchy.sf", x, loc, scale) return cdf(-x, -loc, scale) def logsf(x: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy distribution log survival function. JAX implementation of :obj:`scipy.stats.cauchy` ``logsf`` The survival function is defined as .. math:: f_{sf}(x) = 1 - f_{cdf}(x) where :math:`f_{cdf}(x)` is the cumulative distribution function, :func:`jax.scipy.stats.cauchy.cdf`. Args: x: arraylike, value at which to evaluate the SF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of logsf values. See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.isf` - :func:`jax.scipy.stats.cauchy.ppf` """ x, loc, scale = promote_args_inexact("cauchy.logsf", x, loc, scale) return logcdf(-x, -loc, scale) def isf(q: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy distribution inverse survival function. JAX implementation of :obj:`scipy.stats.cauchy` ``isf``. Returns the inverse of the survival function, :func:`jax.scipy.stats.cauchy.sf`. Args: q: arraylike, value at which to evaluate the ISF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of isf values. See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.ppf` """ q, loc, scale = promote_args_inexact("cauchy.isf", q, loc, scale) pi = _lax_const(q, np.pi) half_pi = _lax_const(q, np.pi / 2) unscaled = lax.tan(lax.sub(half_pi, lax.mul(pi, q))) return lax.add(lax.mul(unscaled, scale), loc) def ppf(q: ArrayLike, loc: ArrayLike = 0, scale: ArrayLike = 1) -> Array: r"""Cauchy distribution percent point function. JAX implementation of :obj:`scipy.stats.cauchy` ``ppf``. The percent point function is defined as the inverse of the cumulative distribution function, :func:`jax.scipy.stats.cauchy.cdf`. Args: q: arraylike, value at which to evaluate the PPF loc: arraylike, distribution offset parameter scale: arraylike, distribution scale parameter Returns: array of ppf values. See Also: - :func:`jax.scipy.stats.cauchy.cdf` - :func:`jax.scipy.stats.cauchy.pdf` - :func:`jax.scipy.stats.cauchy.sf` - :func:`jax.scipy.stats.cauchy.logcdf` - :func:`jax.scipy.stats.cauchy.logpdf` - :func:`jax.scipy.stats.cauchy.logsf` - :func:`jax.scipy.stats.cauchy.isf` """ q, loc, scale = promote_args_inexact("cauchy.ppf", q, loc, scale) pi = _lax_const(q, np.pi) half_pi = _lax_const(q, np.pi / 2) unscaled = lax.tan(lax.sub(lax.mul(pi, q), half_pi)) return lax.add(lax.mul(unscaled, scale), loc)