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

feat: implement real #23669

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions ivy/data_classes/array/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,3 +1064,35 @@ def sparsify_tensor(
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
"""
return ivy.sparsify_tensor(self._data, card, out=out)

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

Parameters
----------
self
Input array.
out
Alternate output array in which to place the result.
The default is None.

Returns
-------
ret
The real part of a complex (or real) tensor.

Examples
--------
>>> x = ivy.array([-2.25 + 4.75j, 3.25 + 5.75j])
>>> y = ivy.real(x)
ivy.array([-2.25, 3.25])
"""
return ivy.real(self._data, out=out)
86 changes: 86 additions & 0 deletions ivy/data_classes/container/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,7 @@ def static_sparsify_tensor(
-------
ret
container including the sparsified tensor computed element-wise

Examples
--------
>>> x = ivy.Container(
Expand Down Expand Up @@ -3068,3 +3069,88 @@ def sparsify_tensor(
map_sequences=map_sequences,
out=out,
)

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

Parameters
----------
x
Input container containing input arrays.
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
Alternate output container in which to place the result.
The default is None.

Returns
-------
ret
The real part of a complex (or real) tensor.

Examples
--------
>>> x = ivy.Container(
a=ivy.array([-2.25 + 4.75j, 3.25 + 5.75j])
)
>>> ivy.Container.static_real(x)
{
a: ivy.array([-2.25, 3.25]),
}
"""
return ContainerBase.cont_multi_map_in_function(
"real",
x,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)

def real(
self: Union[ivy.Container, ivy.Array, ivy.NativeArray],
/,
*,
key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
to_apply: Union[bool, ivy.Container] = True,
prune_unapplied: Union[bool, ivy.Container] = False,
map_sequences: Union[bool, ivy.Container] = False,
out: Optional[ivy.Container] = None,
) -> ivy.Container:
"""
ivy.Container instance method variant of ivy.real.

This method simply wraps the function, and so the docstring for
ivy.real also applies to this method with minimal changes.
"""
return self.static_real(
self,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)
9 changes: 9 additions & 0 deletions ivy/functional/backends/jax/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,3 +464,12 @@ def digamma(
out: Optional[JaxArray] = None,
) -> JaxArray:
return js.special.digamma(x)


def real(
x: JaxArray,
/,
*,
out: Optional[JaxArray] = None,
) -> JaxArray:
return jnp.real(x)
10 changes: 10 additions & 0 deletions ivy/functional/backends/mxnet/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,13 @@ def modf(
out: Optional[Union[(None, mx.ndarray.NDArray)]] = None,
) -> Union[(None, mx.ndarray.NDArray)]:
raise IvyNotImplementedException()


def real(
x: Union[(None, mx.ndarray.NDArray)],
/,
*,
out: Optional[Union[(None, mx.ndarray.NDArray)]] = None,
) -> Union[(None, mx.ndarray.NDArray)]:
# return mx.np.real(x)
raise IvyNotImplementedException()
9 changes: 9 additions & 0 deletions ivy/functional/backends/numpy/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,3 +480,12 @@ def func(x):
# Vectorize 'func' for element-wise operations on 'x', output matching 'x' dtype.
vfunc = np.vectorize(func, otypes=[x.dtype])
return vfunc(x)


def real(
x: np.ndarray,
/,
*,
out: Optional[np.ndarray] = None,
) -> np.ndarray:
return np.real(x)
4 changes: 4 additions & 0 deletions ivy/functional/backends/paddle/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,7 @@ def digamma(
out: Optional[paddle.Tensor] = None,
) -> paddle.Tensor:
return paddle.digamma(x)


def real(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor:
return paddle.real(x)
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,12 @@ def digamma(
out: Optional[Union[tf.Tensor, tf.Variable]] = None,
) -> Union[tf.Tensor, tf.Variable]:
return tf.math.digamma(x)


def real(
x: Union[tf.Tensor, tf.Variable],
/,
*,
out: Optional[Union[tf.Tensor, tf.Variable]] = None,
) -> Union[tf.Tensor, tf.Variable]:
return tf.math.real(x)
9 changes: 9 additions & 0 deletions ivy/functional/backends/torch/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,12 @@ def digamma(


digamma.support_native_out = True


def real(
x: torch.Tensor,
/,
*,
out: Optional[torch.Tensor] = None,
) -> torch.Tensor:
return torch.real(x)
67 changes: 67 additions & 0 deletions ivy/functional/ivy/experimental/elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -1388,3 +1388,70 @@ def sparsify_tensor(
tensor = ivy.concat([ivy.zeros(len(x) - card, dtype=x.dtype), x[-card:]], axis=0)

return ivy.reshape(tensor, _shape, out=out)


@handle_exceptions
@handle_nestable
@inputs_to_ivy_arrays
def real(
x: Union[ivy.Array, ivy.NativeArray],
/,
*,
out: Optional[ivy.Array] = None,
) -> ivy.Array:
"""
Test each element ``x_i`` of the input array ``x`` to take only real part from it.
Returns a float array, where it only contains . If element has complex type with
zero complex part, the return value will be that element, else it only returns real
part.

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

Returns
-------
ret
an array containing test results. An element ``out_i`` is
``real number`` if ``x_i`` contain real number part only
and if it is ``real number with complex part also`` then it
returns the real number part.
The returned array must have a floating-point data type with the
same floating-point precision as ``x`` (e.g., if ``x`` is ``complex64``,
the returned array must have the floating-point precision of ``float32``).

The descriptions above assume an array input for simplicity, but
the method also accepts :class:`ivy.Container` instances
in place of: class:`ivy.Array` or :class:`ivy.NativeArray`
instances, as shown in the type hints and also the examples below.

Examples
--------
With :class:`ivy.Array` inputs:

>>> x = ivy.array([[[1.1], [2], [-6.3]]])
>>> z = ivy.real(x)
>>> print(z)
ivy.array([[[1.1], [2.], [-6.3]]])

>>> x = ivy.array([4.2-0j, 3j, 7+5j])
>>> z = ivy.real(x)
>>> print(z)
ivy.array([4.2, 0., 7.])

With :class:`ivy.Container` input:

>>> x = ivy.Container(a=ivy.array([-6.7-7j, 0.314+0.355j, 1.23]),\
b=ivy.array([5j, 5.32-6.55j, 3.001]))
>>> z = ivy.real(x)
>>> print(z)
{
a: ivy.array([-6.7, 0.314, 1.23]),
b: ivy.array([0., 5.32, 3.001])
}
"""
return ivy.current_backend(x).real(x, out=out)
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,25 @@ def test_nextafter(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device):
)


# real
@handle_test(
fn_tree="functional.ivy.experimental.real",
dtype_and_x=helpers.dtype_and_values(
available_dtypes=helpers.get_dtypes("numeric"),
),
)
def test_real(*, 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,
backend_to_test=backend_fw,
fn_name=fn_name,
on_device=on_device,
x=x[0],
)


# sinc
@handle_test(
fn_tree="functional.ivy.experimental.sinc",
Expand Down