Unary operations perform element-wise transformations on a single tensor.
Basic Math
Negate
a = Nx.tensor([1.0, -2.0, 3.0], backend: ExCubecl.Backend)
Nx.negate(a)
# #Nx.Tensor<f32[3] [-1.0, 2.0, -3.0]>Absolute Value
Nx.abs(a)
# #Nx.Tensor<f32[3] [1.0, 2.0, 3.0]>Sign
Nx.sign(Nx.tensor([-5.0, 0.0, 3.0]))
# #Nx.Tensor<f32[3] [-1.0, 0.0, 1.0]>Exponential & Logarithmic
Exp
Nx.exp(Nx.tensor([0.0, 1.0, 2.0]))
# #Nx.Tensor<f32[3] [1.0, 2.7182817459106445, 7.389056205749512]>Log (natural logarithm)
Nx.log(Nx.tensor([1.0, 2.7182818, 7.389056]))
# #Nx.Tensor<f32[3] [0.0, 1.0, 2.0]>Expm1 (e^x - 1, more accurate for small x)
Nx.expm1(Nx.tensor([0.0, 0.001, 1.0]))
# #Nx.Tensor<f32[3] [0.0, 0.0010005003213882446, 1.718281865119934]>Log1p (ln(1 + x), more accurate for small x)
Nx.log1p(Nx.tensor([0.0, 0.001, 1.0]))
# #Nx.Tensor<f32[3] [0.0, 0.0009995003213882446, 0.6931471824645996]>Roots
Square Root
Nx.sqrt(Nx.tensor([4.0, 9.0, 16.0]))
# #Nx.Tensor<f32[3] [2.0, 3.0, 4.0]>Reciprocal Square Root (1/√x)
Nx.rsqrt(Nx.tensor([4.0, 9.0, 16.0]))
# #Nx.Tensor<f32[3] [0.5, 0.3333333432674408, 0.25]>Cube Root
Nx.cbrt(Nx.tensor([8.0, 27.0, 64.0]))
# #Nx.Tensor<f32[3] [2.0, 3.0, 4.0]>Trigonometric Functions
All trigonometric functions work in radians.
Sin / Cos / Tan
x = Nx.tensor([0.0, :math.pi() / 4, :math.pi() / 2], backend: ExCubecl.Backend)
Nx.sin(x) # [0.0, 0.7071067690849304, 1.0]
Nx.cos(x) # [1.0, 0.7071067690849304, 0.0]
Nx.tan(x) # [0.0, 1.0, 1.633123935319537e16]Inverse Trigonometric
Nx.asin(Nx.tensor([0.0, 0.5, 1.0]))
# #Nx.Tensor<f32[3] [0.0, 0.5235987901687622, 1.5707963705062866]>
Nx.acos(Nx.tensor([1.0, 0.5, 0.0]))
# #Nx.Tensor<f32[3] [0.0, 1.0471975803375244, 1.5707963705062866]>
Nx.atan(Nx.tensor([0.0, 1.0, 1.0e10]))
# #Nx.Tensor<f32[3] [0.0, 0.7853981852531433, 1.5707963705062866]>Hyperbolic
x = Nx.tensor([0.0, 1.0, 2.0], backend: ExCubecl.Backend)
Nx.sinh(x) # [0.0, 1.175201177597046, 3.6268603801727295]
Nx.cosh(x) # [1.0, 1.5430806875228882, 3.762195587158203]
Nx.tanh(x) # [0.0, 0.7615941762924194, 0.9640275835990906]Inverse Hyperbolic
Nx.asinh(Nx.tensor([0.0, 1.0, 2.0]))
Nx.acosh(Nx.tensor([1.0, 2.0, 3.0]))
Nx.atanh(Nx.tensor([0.0, 0.5, 0.9]))Rounding Operations
x = Nx.tensor([1.5, -1.5, 2.3, -2.7], backend: ExCubecl.Backend)
Nx.ceil(x) # [2.0, -1.0, 3.0, -2.0]
Nx.floor(x) # [1.0, -2.0, 2.0, -3.0]
Nx.round(x) # [2.0, -2.0, 2.0, -3.0]Activation Functions
Sigmoid
Nx.sigmoid(Nx.tensor([0.0, 2.0, -2.0]))
# #Nx.Tensor<f32[3] [0.5, 0.8807970285415649, 0.11920291930437088]>ReLU
Nx.relu(Nx.tensor([-2.0, -1.0, 0.0, 1.0, 2.0]))
# #Nx.Tensor<f32[5] [0.0, 0.0, 0.0, 1.0, 2.0]>Error Functions
x = Nx.tensor([0.0, 0.5, 1.0, 2.0], backend: ExCubecl.Backend)
Nx.erf(x) # [0.0, 0.5204998850822449, 0.8427007794380188, 0.9953222870826721]
Nx.erfc(x) # [1.0, 0.4795001149177551, 0.1572992205619812, 0.004677712917327881]
Nx.erf_inv(Nx.tensor([0.0, 0.5, 0.9]))
# #Nx.Tensor<f32[3] [0.0, 0.4769362807273865, 1.1630871295928955]>Special Operations
Conjugate (identity for real numbers)
Nx.conjugate(Nx.tensor([1.0, 2.0, 3.0]))
# #Nx.Tensor<f32[3] [1.0, 2.0, 3.0]>Real / Imaginary parts
Nx.real(Nx.tensor([1.0, 2.0, 3.0])) # [1.0, 2.0, 3.0]
Nx.imag(Nx.tensor([1.0, 2.0, 3.0])) # [0.0, 0.0, 0.0]Is NaN / Is Infinity
x = Nx.tensor[:nan, :infinity, :neg_infinity, 1.0]
Nx.is_nan(x) # [1, 0, 0, 0]
Nx.is_infinity(x) # [0, 1, 1, 0]Integer-Specific Operations
Count Leading Zeros
Nx.count_leading_zeros(Nx.tensor([1::32, 0::32, 255::32]))
# [31, 32, 24]Population Count (number of 1-bits)
Nx.population_count(Nx.tensor([0::32, 1::32, 255::32, 7::32]))
# [0, 1, 8, 3]Bitwise Not
Nx.bitwise_not(Nx.tensor([0::32, 1::32, 255::32]))
# [-1, -2, -256]