Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ivy.lgamma #19177

Merged
merged 13 commits into from
Jul 19, 2023
35 changes: 35 additions & 0 deletions ivy/data_classes/array/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,41 @@


class _ArrayWithElementWiseExperimental(abc.ABC):
def lgamma(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array:
"""
ivy.Array instance method variant of ivy.lgamma. This method simply wraps the
function, and so the docstring for ivy.lgamma also applies to this method with
minimal changes.

Parameters
----------
self
input array. Should have a real-valued floating-point data type.
out
optional output array, for writing the result to. It must have a shape that
the inputs broadcast to.

Returns
-------
ret
an array containing the evaluated result for each element in ``self``.
The returned array must have a real-valued floating-point data
type determined by :ref:`type-promotion`.

Examples
--------
>>> x = ivy.array([1 , 2 , 3 ])
>>> y = x.lgamma()
>>> print(y)
ivy.array([0., 0., 0.69314718])

>>> x = ivy.array([4.5, -4, -5.6])
>>> x.lgamma(out = x)
>>> print(x)
ivy.array([2.45373654, inf, -4.6477685 ])
"""
return ivy.lgamma(self._data, out=out)

def sinc(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array:
"""
ivy.Array instance method variant of ivy.sinc. This method simply wraps the
Expand Down
131 changes: 131 additions & 0 deletions ivy/data_classes/container/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,137 @@


class _ContainerWithElementWiseExperimental(ContainerBase):
@staticmethod
def static_lgamma(
x: Union[ivy.Container, ivy.Array, ivy.NativeArray],
/,
*,
key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
to_apply: bool = True,
prune_unapplied: bool = False,
map_sequences: bool = False,
out: Optional[ivy.Container] = None,
) -> ivy.Container:
"""
ivy.Container static method variant of ivy.lgamma. This method simply wraps the
function, and so the docstring for ivy.lgamma also applies to this method with
minimal changes.

Parameters
----------
x
input container. Should have a real-valued floating-point data type.
key_chains
The key-chains to apply or not apply the method to. Default is ``None``.
to_apply
If True, the method will be applied to key_chains, otherwise key_chains
will be skipped. Default is ``True``.
prune_unapplied
Whether to prune key_chains for which the function was not applied.
Default is ``False``.
map_sequences
Whether to also map method to sequences (lists, tuples).
Default is ``False``.
out
optional output container, for writing the result to. It must have a shape
that the inputs broadcast to.

Returns
-------
ret
a container containing the evaluated result for each element in ``x``.
The returned array must have a real-valued floating-point data type
determined by :ref:`type-promotion`.

Examples
--------
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]), b=ivy.array([3., 4., 5.1]))
>>> y = ivy.Container.static_lgamma(x)
>>> print(y)
{
a: ivy.array([inf, 0., 0.]),
b: ivy.array([0.69314718, 1.79175949, 3.32976389])
}


>>> x = ivy.Container(a=ivy.array([0., 2.]), b=ivy.array([ 4., 5.1]))
>>> ivy.Container.static_lgamma(x, out = x)
>>> print(y)
{
a: ivy.array([inf, 0.]),
b: ivy.array([1.79175949, 3.32976389])
}
"""
return ContainerBase.cont_multi_map_in_function(
"lgamma",
x,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)

def lgamma(
self: ivy.Container,
*,
key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
to_apply: bool = True,
prune_unapplied: bool = False,
map_sequences: bool = False,
out: Optional[ivy.Container] = None,
) -> ivy.Container:
"""
ivy.Container instance method variant of ivy.lgamma. This method simply wraps
the function, and so the docstring for ivy.lgamma also applies to this method
with minimal changes.

Parameters
----------
self
input container. Should have a real-valued floating-point data type.
key_chains
The key-chains to apply or not apply the method to. Default is ``None``.
to_apply
If True, the method will be applied to key_chains, otherwise key_chains
will be skipped. Default is ``True``.
prune_unapplied
Whether to prune key_chains for which the function was not applied.
Default is ``False``.
map_sequences
Whether to also map method to sequences (lists, tuples).
Default is ``False``.
out
optional output container, for writing the result to. It must have a shape
that the inputs broadcast to.

Returns
-------
ret
a container containing the evaluated result for each element in ``self``.
The returned array must have a real-valued floating-point data type
determined by :ref:`type-promotion`.

Examples
--------
>>> x = ivy.Container(a=ivy.array([1.6, 2.6, 3.5]),
... b=ivy.array([4.5, 5.3, 2.3]))
>>> y = x.lgamma()
>>> print(y)
{
a: ivy.array([-0.11259222, 0.3574121, 1.20097375]),
b: ivy.array([2.45373821, 3.63963795, 0.15418935])
}
"""
return self.static_lgamma(
self,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)

@staticmethod
def static_sinc(
x: ivy.Container,
Expand Down
12 changes: 12 additions & 0 deletions ivy/functional/backends/jax/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
default_float_dtype,
is_float_dtype,
)
from ivy.func_wrapper import (
with_supported_dtypes,
)
from ivy.functional.backends.jax import JaxArray
import jax.numpy as jnp
import jax.scipy as js
import jax.lax as jlax
from .. import backend_version

jax_ArrayLike = Union[JaxArray, Number]

Expand All @@ -18,6 +23,13 @@ def sinc(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray:
return jnp.sinc(x)


@with_supported_dtypes(
{"0.4.13 and below": ("float16", "float32", "float64")}, backend_version
)
def lgamma(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray:
return jlax.lgamma(x)


def fmax(
x1: JaxArray,
x2: JaxArray,
Expand Down
15 changes: 15 additions & 0 deletions ivy/functional/backends/mxnet/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@
import mxnet as mx

from ivy.utils.exceptions import IvyNotImplementedException
from ivy.func_wrapper import with_supported_dtypes
from .. import backend_version


@with_supported_dtypes(
{"1.9.1 and below": ("float16", "float32", "float64")},
backend_version,
)
def lgamma(
x: Union[(None, mx.ndarray.NDArray)],
/,
*,
out: Optional[Union[(None, mx.ndarray.NDArray)]] = None,
) -> Union[(None, mx.ndarray.NDArray)]:
return mx.np.log(mx.npx.gamma(x))


def sinc(
Expand Down
5 changes: 5 additions & 0 deletions ivy/functional/backends/numpy/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array
from ivy.func_wrapper import with_unsupported_dtypes
from . import backend_version
from ivy.utils.exceptions import IvyNotImplementedException


def lgamma(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray:
raise IvyNotImplementedException()


@_scalar_output_to_0d_array
Expand Down
10 changes: 10 additions & 0 deletions ivy/functional/backends/paddle/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@
from .. import backend_version


@with_supported_dtypes(
{"2.5.0 and below": ("float32", "float64")},
backend_version,
)
def lgamma(
x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None
) -> paddle.Tensor:
return paddle.lgamma(x)


@with_supported_dtypes(
{"2.5.0 and below": ("float64", "float32", "int32", "int64")},
backend_version,
Expand Down
13 changes: 13 additions & 0 deletions ivy/functional/backends/tensorflow/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@
from .. import backend_version


@with_supported_dtypes(
{"2.13.0 and below": ("float16", "float32", "float64")},
backend_version,
)
def lgamma(
x: Union[tf.Tensor, tf.Variable],
/,
*,
out: Optional[Union[tf.Tensor, tf.Variable]] = None,
) -> Union[tf.Tensor, tf.Variable]:
return tf.math.lgamma(x)


def sinc(
x: Union[tf.Tensor, tf.Variable],
/,
Expand Down
5 changes: 5 additions & 0 deletions ivy/functional/backends/torch/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
from .. import backend_version


@with_supported_dtypes({"2.0.1 and below": ("float32", "float64")}, backend_version)
def lgamma(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor:
return torch.lgamma(x, out=out)


@with_unsupported_dtypes({"2.0.1 and below": ("complex",)}, backend_version)
def fmax(
x1: torch.Tensor,
Expand Down
54 changes: 54 additions & 0 deletions ivy/functional/ivy/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,60 @@
from ivy.utils.exceptions import handle_exceptions


@handle_exceptions
@handle_nestable
@handle_array_like_without_promotion
@handle_out_argument
@to_native_arrays_and_back
@handle_array_function
def lgamma(
x: Union[ivy.Array, ivy.NativeArray],
/,
*,
out: Optional[ivy.Array] = None,
) -> ivy.Array:
"""
Compute the natural logarithm of the absolute value of the gamma function on x.

Parameters
----------
x
input array. Should have a floating-point data type.
out
optional output array, for writing the result to. It must have a shape that the
inputs broadcast to.

Returns
-------
ret
an array containing the natural log of Gamma(x) of each element in x.
The returned array must have a floating-point data type determined
by :ref:`type-promotion`.

Examples
--------
>>> x = ivy.Container(a=ivy.array([1.6, 2.6, 3.5]),
... b=ivy.array([4.5, 5.3, 2.3]))
>>> y = x.lgamma()
>>> print(y)
{
a: ivy.array([-0.11259222, 0.3574121, 1.20097375]),
b: ivy.array([2.45373821, 3.63963795, 0.15418935])
}

>>> x = ivy.array([1 , 2 , 3 ])
>>> y = x.lgamma()
>>> print(y)
ivy.array([0., 0., 0.69314718])

>>> x = ivy.array([4.5, -4, -5.6])
>>> x.lgamma(out = x)
>>> print(x)
ivy.array([2.45373654, inf, -4.6477685 ])
"""
return ivy.current_backend(x).lgamma(x, out=out)


@handle_exceptions
@handle_nestable
@handle_array_like_without_promotion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@

# Helpers #
# ------- #
# lgamma
@handle_test(
fn_tree="functional.ivy.experimental.lgamma",
dtype_and_x=helpers.dtype_and_values(
available_dtypes=helpers.get_dtypes("float"),
safety_factor_scale="log",
),
test_gradients=st.just(False),
)
def test_lgamma(
*,
dtype_and_x,
test_flags,
backend_fw,
fn_name,
on_device,
):
input_dtype, x = dtype_and_x
helpers.test_function(
input_dtypes=input_dtype,
test_flags=test_flags,
on_device=on_device,
fw=backend_fw,
fn_name=fn_name,
x=x[0],
)


# sinc
Expand Down Expand Up @@ -400,7 +426,7 @@ def test_diff(
test_flags,
backend_fw,
fn_name,
on_device
on_device,
):
input_dtype, x, axis = dtype_n_x_n_axis
_, prepend = dtype_prepend
Expand Down