defmodule Nx.Constants do
@moduledoc """
Common constants used in computations.
This module can be used in `defn`.
"""
import Nx.Shared
import Nx.Defn.Kernel, only: [keyword!: 2]
@doc """
Returns NaN in f32.
"""
def nan, do: nan({:f, 32}, [])
@doc """
Returns NaN (Not a Number).
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.nan({:bf, 16})
#Nx.Tensor<
bf16
NaN
>
iex> Nx.Constants.nan({:f, 16})
#Nx.Tensor<
f16
NaN
>
iex> Nx.Constants.nan({:f, 32})
#Nx.Tensor<
f32
NaN
>
iex> Nx.Constants.nan({:f, 64})
#Nx.Tensor<
f64
NaN
>
"""
def nan(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.nan_binary(type), type, opts)
end
@doc """
Returns infinity in f32.
"""
def infinity, do: infinity({:f, 32}, [])
@doc """
Returns infinity.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.infinity({:bf, 16})
#Nx.Tensor<
bf16
Inf
>
iex> Nx.Constants.infinity({:f, 16})
#Nx.Tensor<
f16
Inf
>
iex> Nx.Constants.infinity({:f, 32})
#Nx.Tensor<
f32
Inf
>
iex> Nx.Constants.infinity({:f, 64})
#Nx.Tensor<
f64
Inf
>
"""
def infinity(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.infinity_binary(type), type, opts)
end
@doc """
Returns infinity in f32.
"""
def neg_infinity, do: neg_infinity({:f, 32}, [])
@doc """
Returns negative infinity.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.neg_infinity({:bf, 16})
#Nx.Tensor<
bf16
-Inf
>
iex> Nx.Constants.neg_infinity({:f, 16})
#Nx.Tensor<
f16
-Inf
>
iex> Nx.Constants.neg_infinity({:f, 32})
#Nx.Tensor<
f32
-Inf
>
iex> Nx.Constants.neg_infinity({:f, 64})
#Nx.Tensor<
f64
-Inf
>
"""
def neg_infinity(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.neg_infinity_binary(type), type, opts)
end
@doc """
Returns a scalar tensor with the maximum finite value for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.max_finite({:u, 8})
#Nx.Tensor<
u8
255
>
iex> Nx.Constants.max_finite({:s, 16})
#Nx.Tensor<
s16
32677
>
iex> Nx.Constants.max_finite({:f, 32})
#Nx.Tensor<
f32
3.4028234663852886e38
>
"""
def max_finite(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.max_finite_binary(type), type, opts)
end
@doc """
Returns a scalar tensor with the maximum value for the given type.
It is infinity for floating point tensors.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.max({:u, 8})
#Nx.Tensor<
u8
255
>
iex> Nx.Constants.max({:f, 32})
#Nx.Tensor<
f32
Inf
>
"""
def max(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.max_binary(type), type, opts)
end
@doc """
Returns a scalar tensor with the minimum finite value for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.min_finite({:u, 8})
#Nx.Tensor<
u8
0
>
iex> Nx.Constants.min_finite({:s, 16})
#Nx.Tensor<
s16
-32678
>
iex> Nx.Constants.min_finite({:f, 32})
#Nx.Tensor<
f32
-3.4028234663852886e38
>
"""
def min_finite(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.min_finite_binary(type), type, opts)
end
@doc """
Returns a scalar tensor with the minimum value for the given type.
It is negative infinity for floating point tensors.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.min({:u, 8})
#Nx.Tensor<
u8
0
>
iex> Nx.Constants.min({:f, 32})
#Nx.Tensor<
f32
-Inf
>
"""
def min(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.min_binary(type), type, opts)
end
@doc """
Returns the imaginary constant in c64
"""
def i, do: i(:c64)
@doc """
Returns the imaginary constant.
Accepts the same options as `Nx.tensor/2`
## Examples
iex> Nx.Constants.i()
#Nx.Tensor<
c64
0.0+1.0i
>
iex> Nx.Constants.i(:c128)
#Nx.Tensor<
c128
0.0+1.0i
>
## Error cases
iex> Nx.Constants.i({:f, 32})
** (ArgumentError) invalid type for complex number. Expected {:c, 64} or {:c, 128}, got: {:f, 32}
"""
def i(type, opts \\ []) do
if Keyword.has_key?(opts, :type) do
raise "type must not be passed as an option"
end
Nx.tensor(Complex.new(0, 1), Keyword.put(opts, :type, type))
end
@doc """
Returns a scalar tensor with the maximum finite value for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.smallest_positive_normal({:f, 64})
#Nx.Tensor<
f64
2.2250738585072014e-308
>
iex> Nx.Constants.smallest_positive_normal({:f, 32})
#Nx.Tensor<
f32
1.1754943508222875e-38
>
iex> Nx.Constants.smallest_positive_normal({:f, 16})
#Nx.Tensor<
f16
6.103515625e-5
>
iex> Nx.Constants.smallest_positive_normal(:bf16)
#Nx.Tensor<
bf16
1.1754943508222875e-38
>
iex> Nx.Constants.smallest_positive_normal({:s, 32})
** (ArgumentError) only floating types are supported, got: {:s, 32}
"""
def smallest_positive_normal(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.smallest_positive_normal_binary(type), type, opts)
end
@doc """
Returns a scalar with the machine epsilon for the given type.
The values are compatible with a IEEE 754 floating point standard.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.epsilon({:f, 64})
#Nx.Tensor<
f64
2.220446049250313e-16
>
iex> Nx.Constants.epsilon({:f, 32})
#Nx.Tensor<
f32
1.1920928955078125e-7
>
iex> Nx.Constants.epsilon({:f, 16})
#Nx.Tensor<
f16
9.765625e-4
>
iex> Nx.Constants.epsilon(:bf16)
#Nx.Tensor<
bf16
0.0078125
>
iex> Nx.Constants.epsilon({:s, 32})
** (ArgumentError) only floating types are supported, got: {:s, 32}
"""
def epsilon(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.epsilon_binary(type), type, opts)
end
@doc ~S"""
Returns $\pi$ in f32.
"""
def pi, do: pi({:f, 32}, [])
@doc ~S"""
Returns a scalar tensor with the value of $\pi$ for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.pi({:f, 64})
#Nx.Tensor<
f64
3.141592653589793
>
iex> Nx.Constants.pi({:f, 32})
#Nx.Tensor<
f32
3.1415927410125732
>
iex> Nx.Constants.pi({:f, 16})
#Nx.Tensor<
f16
3.140625
>
iex> Nx.Constants.pi({:bf, 16})
#Nx.Tensor<
bf16
3.140625
>
iex> Nx.Constants.pi({:s, 32})
** (ArgumentError) only floating types are supported, got: {:s, 32}
"""
def pi(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.pi_binary(type), type, opts)
end
@doc """
Returns $e$ in f32.
"""
def e, do: e({:f, 32}, [])
@doc """
Returns a scalar tensor with the value of $e$ for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.e({:f, 64})
#Nx.Tensor<
f64
2.718281828459045
>
iex> Nx.Constants.e({:f, 32})
#Nx.Tensor<
f32
2.7182817459106445
>
iex> Nx.Constants.e({:f, 16})
#Nx.Tensor<
f16
2.71875
>
iex> Nx.Constants.e({:bf, 16})
#Nx.Tensor<
bf16
2.703125
>
iex> Nx.Constants.e({:s, 32})
** (ArgumentError) only floating types are supported, got: {:s, 32}
"""
def e(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.e_binary(type), type, opts)
end
@doc ~S"""
Returns $\gamma$ (Euler-Mascheroni constant) in f32.
"""
def euler_gamma, do: euler_gamma({:f, 32}, [])
@doc ~S"""
Returns a scalar tensor with the value of $\gamma$ (Euler-Mascheroni constant) for the given type.
## Options
* `:backend` - a backend to allocate the tensor on.
## Examples
iex> Nx.Constants.euler_gamma({:f, 64})
#Nx.Tensor<
f64
0.5772156649015329
>
iex> Nx.Constants.euler_gamma({:f, 32})
#Nx.Tensor<
f32
0.5772156715393066
>
iex> Nx.Constants.euler_gamma({:f, 16})
#Nx.Tensor<
f16
0.5771484375
>
iex> Nx.Constants.euler_gamma({:bf, 16})
#Nx.Tensor<
bf16
0.57421875
>
iex> Nx.Constants.euler_gamma({:s, 32})
** (ArgumentError) only floating types are supported, got: {:s, 32}
"""
def euler_gamma(type, opts \\ []) do
type = Nx.Type.normalize!(type)
from_binary(Nx.Type.euler_gamma_binary(type), type, opts)
end
defp from_binary(binary, type, opts) do
opts = keyword!(opts, [:backend])
{backend, backend_options} = backend_from_options!(opts) || Nx.default_backend()
backend.from_binary(%Nx.Tensor{type: type, shape: {}, names: []}, binary, backend_options)
end
end