pub trait BinaryOps<R>where
R: Runtime,{
// Required methods
fn add(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn sub(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn mul(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn div(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn pow(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn maximum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn minimum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn atan2(&self, y: &Tensor<R>, x: &Tensor<R>) -> Result<Tensor<R>, Error>;
fn fused_mul_add(
&self,
a: &Tensor<R>,
b: &Tensor<R>,
c: &Tensor<R>,
) -> Result<Tensor<R>, Error>;
fn fused_add_mul(
&self,
a: &Tensor<R>,
b: &Tensor<R>,
c: &Tensor<R>,
) -> Result<Tensor<R>, Error>;
}Expand description
Element-wise binary operations on tensors.
This trait defines operations that take two input tensors and produce one output tensor. All binary operations support broadcasting.
§Broadcasting
Binary operations follow NumPy-style broadcasting rules:
- Dimensions are compared element-wise, from the trailing dimensions backward
- Two dimensions are compatible when they are equal, or when one of them is 1
- Dimensions of size 1 are stretched to match the other dimension
- The output has shape equal to the pairwise maximum of the input shapes
§Example
use numr::prelude::*;
let device = CpuDevice::new();
let client = CpuRuntime::default_client(&device);
let a = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 2.0, 3.0, 4.0], &[2, 2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[5.0f32, 6.0, 7.0, 8.0], &[2, 2], &device);
let c = client.add(&a, &b)?; // [6.0, 8.0, 10.0, 12.0]Required Methods§
Sourcefn add(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn add(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise addition: a + b
Adds two tensors element-wise, supporting broadcasting.
§Arguments
a- Left operandb- Right operand (shape must be broadcastable witha)
§Returns
A new tensor with the result of the addition.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 2.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[3.0f32, 4.0], &[2], &device);
let result = client.add(&a, &b)?;Sourcefn sub(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn sub(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise subtraction: a - b
Subtracts two tensors element-wise, supporting broadcasting.
§Arguments
a- Left operand (minuend)b- Right operand (subtrahend, shape must be broadcastable witha)
§Returns
A new tensor with the result of the subtraction.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[5.0f32, 8.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 3.0], &[2], &device);
let result = client.sub(&a, &b)?;Sourcefn mul(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn mul(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise multiplication: a * b
Multiplies two tensors element-wise, supporting broadcasting.
§Arguments
a- Left operandb- Right operand (shape must be broadcastable witha)
§Returns
A new tensor with the result of the multiplication.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 3.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[4.0f32, 5.0], &[2], &device);
let result = client.mul(&a, &b)?;Sourcefn div(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn div(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise division: a / b
Divides two tensors element-wise, supporting broadcasting. Division by zero is undefined behavior (implementation-dependent).
§Arguments
a- Left operand (dividend/numerator)b- Right operand (divisor/denominator, shape must be broadcastable witha)
§Returns
A new tensor with the result of the division.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[10.0f32, 9.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 3.0], &[2], &device);
let result = client.div(&a, &b)?;Sourcefn pow(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn pow(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise power: a^b
Raises the elements of the first tensor to the power of the elements of the second tensor, element-wise, supporting broadcasting.
§Arguments
a- Base tensorb- Exponent tensor (shape must be broadcastable witha)
§Returns
A new tensor with the result of the power operation.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let base = Tensor::<CpuRuntime>::from_slice(&[2.0f32, 3.0], &[2], &device);
let exponent = Tensor::<CpuRuntime>::from_slice(&[3.0f32, 2.0], &[2], &device);
let result = client.pow(&base, &exponent)?;Sourcefn maximum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn maximum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise maximum: max(a, b)
Computes the element-wise maximum of two tensors, supporting broadcasting.
§Arguments
a- First tensorb- Second tensor (shape must be broadcastable witha)
§Returns
A new tensor containing the maximum of corresponding elements.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 5.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[3.0f32, 2.0], &[2], &device);
let result = client.maximum(&a, &b)?;Sourcefn minimum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
fn minimum(&self, a: &Tensor<R>, b: &Tensor<R>) -> Result<Tensor<R>, Error>
Element-wise minimum: min(a, b)
Computes the element-wise minimum of two tensors, supporting broadcasting.
§Arguments
a- First tensorb- Second tensor (shape must be broadcastable witha)
§Returns
A new tensor containing the minimum of corresponding elements.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let a = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 5.0], &[2], &device);
let b = Tensor::<CpuRuntime>::from_slice(&[3.0f32, 2.0], &[2], &device);
let result = client.minimum(&a, &b)?;Sourcefn atan2(&self, y: &Tensor<R>, x: &Tensor<R>) -> Result<Tensor<R>, Error>
fn atan2(&self, y: &Tensor<R>, x: &Tensor<R>) -> Result<Tensor<R>, Error>
Two-argument arctangent: atan2(y, x)
Computes the angle in radians between the positive x-axis and the point (x, y), element-wise, supporting broadcasting.
The result is in the range [-π, π]. This function is essential for converting Cartesian coordinates to polar coordinates and for spatial algorithms.
§Arguments
y- Y-coordinate tensorx- X-coordinate tensor (shape must be broadcastable withy)
§Returns
A new tensor with the angle in radians for each (y, x) pair.
§Errors
Returns an error if shapes are not broadcastable.
§Example
let y = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 0.0], &[2], &device);
let x = Tensor::<CpuRuntime>::from_slice(&[0.0f32, 1.0], &[2], &device);
let angles = client.atan2(&y, &x)?;Sourcefn fused_mul_add(
&self,
a: &Tensor<R>,
b: &Tensor<R>,
c: &Tensor<R>,
) -> Result<Tensor<R>, Error>
fn fused_mul_add( &self, a: &Tensor<R>, b: &Tensor<R>, c: &Tensor<R>, ) -> Result<Tensor<R>, Error>
Fused multiply-add: a * b + c
Computes the element-wise fused multiply-add of three tensors in a single pass, reducing memory bandwidth compared to separate multiply and add operations. Uses hardware FMA instructions where available (AVX2/AVX-512/NEON).
All three tensors must have the same shape (no broadcasting).
§Arguments
a- First multiplicandb- Second multiplicandc- Addend
Sourcefn fused_add_mul(
&self,
a: &Tensor<R>,
b: &Tensor<R>,
c: &Tensor<R>,
) -> Result<Tensor<R>, Error>
fn fused_add_mul( &self, a: &Tensor<R>, b: &Tensor<R>, c: &Tensor<R>, ) -> Result<Tensor<R>, Error>
Fused add-multiply: (a + b) * c
Computes the element-wise fused add-multiply of three tensors in a single pass. Common in residual + scaling patterns.
All three tensors must have the same shape (no broadcasting).
§Arguments
a- First addendb- Second addendc- Multiplicand
Implementors§
impl BinaryOps<CpuRuntime> for CpuClient
BinaryOps implementation for CPU runtime.