# Elementwise and Reductions

> NumKong for Rust

Elementwise kernels live on tensors and views.
They are not a promise that every arbitrary strided view gets the same SIMD path on every backend.

```rust
use numkong::Tensor;

let a = Tensor::<f32>::from_slice(&[1.0, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
let b = Tensor::<f32>::full(&[2, 2], 2.0).unwrap();

let blended = a.view().blend_tensor(&b.view(), 0.25, 0.75).unwrap();
let sines = blended.sin().unwrap();

assert_eq!(sines.shape(), &[2, 2]);
```

The `_inplace` methods update a tensor in its own storage and report a kernel failure:

```rust
use numkong::Tensor;

let mut t = Tensor::<f32>::full(&[4], 1.0).unwrap();
t.add_scalar_inplace(10.0).unwrap();
t.sub_scalar_inplace(0.5).unwrap();
t.mul_scalar_inplace(2.0).unwrap();
```

### Trigonometry

The trigonometric kernels share the tensor and view surface.
They are useful both directly and as a sanity check that the container path is not just about matrix kernels.

```rust
use numkong::Tensor;

let a = Tensor::<f32>::from_slice(&[0.0, 1.0, 2.0, 3.0], &[2, 2]).unwrap();
let c = a.cos().unwrap();
let s = a.sin().unwrap();

assert_eq!(c.shape(), &[2, 2]);
assert_eq!(s.shape(), &[2, 2]);
```

### Moments Reductions

Moments reductions return both sum and sum-of-squares.
That is the right building block for norms and variance-like workflows.

```rust
use numkong::{ReduceMoments, Tensor};

let narrow = Tensor::<u8>::full(&[1024], 255).unwrap();
let (sum, sumsq) = narrow.moments_all().unwrap();

assert!(sum > 255);      // a naive u8 accumulation would overflow immediately
assert!(sumsq > 255u64); // same for sum-of-squares
```

The important documentation point is not just "wider outputs exist".
It is that the API makes the widened outputs part of the type story.

### Min/Max Reductions

Min/max reductions return a `MinMaxResult` with both the value and its flat index:

```rust
use numkong::Tensor;

let t = Tensor::<f32>::from_slice(&[
    3.0, 0.0, 7.0,
    1.0, 2.0, 5.0,
    4.0, -1.0, 6.0,
], &[3, 3]).unwrap();

let second_column = t.slice((.., 1_usize)).unwrap();  // t[:, 1]
let idx = second_column.argmin_all().unwrap();

assert_eq!(idx, 2);
```

`use numkong::BlendOps;`

`use numkong::EachBlend;`

`use numkong::EachFma;`

`use numkong::EachRmsCast;`

`use numkong::EachRmsNorm;`

`use numkong::EachScale;`

`use numkong::EachSum;`

`use numkong::EachSwiGlu;`

`use numkong::FmaOps;`

`use numkong::ScaleOps;`

`use numkong::SumOps;`

`use numkong::BitwiseReductionsOps;`

`use numkong::MinMaxOps;`

`use numkong::MomentsOps;`

`use numkong::ReduceMinMax;`

`use numkong::ReduceMoments;`

`use numkong::Reductions;`

`use numkong::TrigAtan;`

`use numkong::TrigAtanOps;`

`use numkong::TrigCos;`

`use numkong::TrigCosOps;`

`use numkong::TrigSin;`

`use numkong::TrigSinOps;`

`use numkong::Trigonometry;`

`use numkong::MinMaxResult;`

## BlendOps

Extension trait: element-wise subtraction for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait BlendOps<Scalar: Clone + EachBlend, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
where
    Scalar::Scalar: From<f32> + Copy,
```

Implementors: - `impl<Scalar: Clone + [EachBlend](#EachBlend), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [BlendOps](#BlendOps)<Scalar, R> for C where Scalar::Scalar: From<f32> + Copy`

## sub_tensor

Element-wise difference of two tensors into a new tensor.

```rust
fn sub_tensor(
    &self,
    other: &impl TensorRef<Scalar, MAX_RANK> + ?Sized,
) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## blend_tensor_into

Writes α × aᵢ + β × otherᵢ into the output tensor.

```rust
fn blend_tensor_into<OtherTensor, OutputTensor>(
    &self,
    other: &OtherTensor,
    alpha: Scalar::Scalar,
    beta: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
where
    OtherTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized,
```

## sub_tensor_into

Element-wise difference of two tensors into the output tensor.

```rust
fn sub_tensor_into<OtherTensor, OutputTensor>(
    &self,
    other: &OtherTensor,
    out: &mut OutputTensor,
) -> Result<(), Error>
where
    OtherTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized,
```

## EachBlend

Blends two vectors with an __element-wise weighted sum__.

```rust
pub trait EachBlend: Sized + StorageElement
```

rᵢ = α × aᵢ + β × bᵢ

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implemented for: `f64`, `f32`, [`f16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16), [`bf16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16), `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`,
`u64`, [`e4m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3), [`e5m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2), [`e2m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3), and [`e3m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2).

Implementors: - `impl [EachBlend](#EachBlend) for f64`
- `impl [EachBlend](#EachBlend) for f32`
- `impl [EachBlend](#EachBlend) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [EachBlend](#EachBlend) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachBlend](#EachBlend) for i8`
- `impl [EachBlend](#EachBlend) for u8`
- `impl [EachBlend](#EachBlend) for i16`
- `impl [EachBlend](#EachBlend) for u16`
- `impl [EachBlend](#EachBlend) for i32`
- `impl [EachBlend](#EachBlend) for u32`
- `impl [EachBlend](#EachBlend) for i64`
- `impl [EachBlend](#EachBlend) for u64`
- `impl [EachBlend](#EachBlend) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [EachBlend](#EachBlend) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [EachBlend](#EachBlend) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [EachBlend](#EachBlend) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [EachBlend](#EachBlend) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`
- `impl [EachBlend](#EachBlend) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [EachBlend](#EachBlend) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [EachBlend](#EachBlend) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`

## Scalar

Type of the blend coefficients.

```rust
type Scalar;
```

## each_blend

Writes resultᵢ = α × aᵢ + β × bᵢ into the pre-sized output slice.

```rust
fn each_blend(
    a: &[Self],
    b: &[Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
    result: &mut [Self],
) -> Result<(), Error>
```

## each_blend_inplace

In-place blend: dataᵢ = α × dataᵢ + β × otherᵢ.

```rust
fn each_blend_inplace(
    data: &mut [Self],
    other: &[Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
) -> Result<(), Error>
```

`data` is both the `a` operand and the result; its source and destination pointers come from
the single `&mut`, while `other` is disjoint storage — no aliased `&[Self]` + `&mut [Self]`
over the same buffer is formed.

## EachFma

Applies __fused multiply-add__ element-wise across three vectors.

```rust
pub trait EachFma: Sized + StorageElement
```

rᵢ = α × aᵢ × bᵢ + β × cᵢ

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implemented for: `f64`, `f32`, [`f16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16), [`bf16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16), `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`,
`u64`, [`e4m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3), [`e5m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2), [`e2m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3), and [`e3m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2).

Implementors: - `impl [EachFma](#EachFma) for f64`
- `impl [EachFma](#EachFma) for f32`
- `impl [EachFma](#EachFma) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [EachFma](#EachFma) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachFma](#EachFma) for i8`
- `impl [EachFma](#EachFma) for u8`
- `impl [EachFma](#EachFma) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [EachFma](#EachFma) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [EachFma](#EachFma) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [EachFma](#EachFma) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [EachFma](#EachFma) for i16`
- `impl [EachFma](#EachFma) for u16`
- `impl [EachFma](#EachFma) for i32`
- `impl [EachFma](#EachFma) for u32`
- `impl [EachFma](#EachFma) for i64`
- `impl [EachFma](#EachFma) for u64`
- `impl [EachFma](#EachFma) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`
- `impl [EachFma](#EachFma) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [EachFma](#EachFma) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [EachFma](#EachFma) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`

## Scalar

Type of the fused multiply-add coefficients.

```rust
type Scalar;
```

## each_fma

Writes resultᵢ = α × aᵢ × bᵢ + β × cᵢ into the pre-sized output slice.

```rust
fn each_fma(
    a: &[Self],
    b: &[Self],
    c: &[Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
    result: &mut [Self],
) -> Result<(), Error>
```

## each_fma_inplace

In-place fused multiply-add with the `c` operand bound to `a`: dataᵢ = α × dataᵢ × bᵢ + β × dataᵢ.

```rust
fn each_fma_inplace(
    data: &mut [Self],
    b: &[Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
) -> Result<(), Error>
```

`data` is the `a` operand, the `c` operand, and the result — all derived from the single
`&mut`, while `b` is disjoint storage. This matches out-of-place [`mul_tensor`](#mul_tensor), which wires
`c = self` and is the only in-place FMA caller. No aliased `&[Self]` + `&mut [Self]` over
the same buffer is formed.

## EachRmsCast

Grouped RMSNorm of the values a dot product of `Self` writes back into `Self`, rounding like the cast into `Self`, so a GEMM output becomes the next GEMM's input in one pass.

```rust
pub trait EachRmsCast: Sized + StorageElement
```

Integer outputs
round to nearest even and saturate, with `gamma` carrying the quantization scale, and `u8` suits
only non-negative activations.

Implementors: - `impl [EachRmsCast](#EachRmsCast) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachRmsCast](#EachRmsCast) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [EachRmsCast](#EachRmsCast) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [EachRmsCast](#EachRmsCast) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [EachRmsCast](#EachRmsCast) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [EachRmsCast](#EachRmsCast) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [EachRmsCast](#EachRmsCast) for f32`
- `impl [EachRmsCast](#EachRmsCast) for i8`
- `impl [EachRmsCast](#EachRmsCast) for u8`

## Input

What dot products of `Self` write: `f32` for the narrow floats, `f64` for `f32`, and `i32` or `u32` for `i8` or `u8`.

```rust
type Input: StorageElement;
```

## rmscast_into

Grouped RMSNorm of a 2D __[rows,groups×columns]__ tensor of [`Self::Input`](#Input) into `y`, a tensor of `Self` of the same shape, with ε added to the mean square of the raw input.

```rust
fn rmscast_into<XIn, YOut, const RX: usize, const RY: usize>(
    x: &XIn,
    gamma: Option<&[f32]>,
    y: &mut YOut,
    groups: usize,
    epsilon: f32,
) -> Result<(), Error>
where
    XIn: TensorRef<Self::Input, RX> + ?Sized,
    YOut: TensorMut<Self, RY> + ?Sized,
```

Returns `Err`
on a shape mismatch.

## EachRmsNorm

Grouped RMSNorm over a row-major __[rows,groups×columns]__ slice, y = x / √(mean(x²) + ε) × γ, where each row holds `groups` independent `columns`-vectors, normalized separately, with `columns` equal to `x.len() / rows / groups`.

```rust
pub trait EachRmsNorm: Sized + StorageElement
```

`gamma` is an optional per-column gain of length
`columns`, which defaults to unit scale when `None`.

Implementors: - `impl [EachRmsNorm](#EachRmsNorm) for f32`
- `impl [EachRmsNorm](#EachRmsNorm) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachRmsNorm](#EachRmsNorm) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`

## rmsnorm_into

Grouped RMSNorm of a 2D __[rows,groups×columns]__ tensor into `y` of the same shape.

```rust
fn rmsnorm_into<XIn, YOut, const RX: usize, const RY: usize>(
    x: &XIn,
    gamma: Option<&[f32]>,
    y: &mut YOut,
    groups: usize,
    epsilon: f32,
) -> Result<(), Error>
where
    XIn: TensorRef<Self, RX> + ?Sized,
    YOut: TensorMut<Self, RY> + ?Sized,
```

Row strides are read from the tensors, so `x` and `y` may be non-contiguous sub-spans, for
example a strided section of a fused activation buffer. `gamma` is an optional per-column
gain of length `columns` (`None` = unit scale). Returns `Err` on a shape mismatch.

## EachScale

Applies an __element-wise affine transform__ — scale and shift.

```rust
pub trait EachScale: Sized + StorageElement
```

rᵢ = α × aᵢ + β

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if `a` and `result` lengths differ, or
[`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed) carrying the kernel's status.

Implemented for: `f64`, `f32`, [`f16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16), [`bf16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16), `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`,
`u64`, [`e4m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3), [`e5m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2), [`e2m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3), and [`e3m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2).

Implementors: - `impl [EachScale](#EachScale) for f64`
- `impl [EachScale](#EachScale) for f32`
- `impl [EachScale](#EachScale) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [EachScale](#EachScale) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachScale](#EachScale) for i8`
- `impl [EachScale](#EachScale) for u8`
- `impl [EachScale](#EachScale) for i16`
- `impl [EachScale](#EachScale) for u16`
- `impl [EachScale](#EachScale) for i32`
- `impl [EachScale](#EachScale) for u32`
- `impl [EachScale](#EachScale) for i64`
- `impl [EachScale](#EachScale) for u64`
- `impl [EachScale](#EachScale) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [EachScale](#EachScale) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [EachScale](#EachScale) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [EachScale](#EachScale) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [EachScale](#EachScale) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`
- `impl [EachScale](#EachScale) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [EachScale](#EachScale) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [EachScale](#EachScale) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`

## Scalar

Type of the scale and shift coefficients.

```rust
type Scalar;
```

## each_scale

Writes resultᵢ = α × aᵢ + β into the pre-sized output slice.

```rust
fn each_scale(
    a: &[Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
    result: &mut [Self],
) -> Result<(), Error>
```

Both slices, `a` and `result`, must have identical length — the kernel does not allocate.

Examples: ```
use numkong::EachScale;
let input = [1.0_f32, 2.0, 3.0];
let mut output = [0.0_f32; 3];
// Rescale to [-1, 1]: alpha = 2/(max-min) = 1.0, beta = -1 - 1*min = -2.0
f32::each_scale(&#x26;input, 1.0, -2.0, &#x26;mut output).unwrap();
assert_eq!(output, [-1.0, 0.0, 1.0]);
```

## each_scale_inplace

In-place affine: dataᵢ = α × dataᵢ + β.

```rust
fn each_scale_inplace(
    data: &mut [Self],
    alpha: Self::Scalar,
    beta: Self::Scalar,
) -> Result<(), Error>
```

Both source and destination pointers are derived from the single `&mut`, so no aliased
`&[Self]` + `&mut [Self]` over the same storage is formed.

## EachSum

Applies __element-wise addition__ of two vectors.

```rust
pub trait EachSum: Sized + StorageElement
```

rᵢ = aᵢ + bᵢ

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implemented for: `f64`, `f32`, [`f16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16), [`bf16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16), `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`,
`u64`, [`e4m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3), [`e5m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2), [`e2m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3), and [`e3m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2).

Implementors: - `impl [EachSum](#EachSum) for f64`
- `impl [EachSum](#EachSum) for f32`
- `impl [EachSum](#EachSum) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [EachSum](#EachSum) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachSum](#EachSum) for i8`
- `impl [EachSum](#EachSum) for u8`
- `impl [EachSum](#EachSum) for i16`
- `impl [EachSum](#EachSum) for u16`
- `impl [EachSum](#EachSum) for i32`
- `impl [EachSum](#EachSum) for u32`
- `impl [EachSum](#EachSum) for i64`
- `impl [EachSum](#EachSum) for u64`
- `impl [EachSum](#EachSum) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [EachSum](#EachSum) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [EachSum](#EachSum) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [EachSum](#EachSum) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [EachSum](#EachSum) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`
- `impl [EachSum](#EachSum) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [EachSum](#EachSum) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [EachSum](#EachSum) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`

## each_sum

Writes resultᵢ = aᵢ + bᵢ into the pre-sized output slice.

```rust
fn each_sum(a: &[Self], b: &[Self], result: &mut [Self]) -> Result<(), Error>
```

## each_sum_inplace

In-place sum: dataᵢ = dataᵢ + otherᵢ.

```rust
fn each_sum_inplace(data: &mut [Self], other: &[Self]) -> Result<(), Error>
```

`data` is both the `a` operand and the result; its source and destination pointers come from
the single `&mut`, while `other` is disjoint storage — no aliased `&[Self]` + `&mut [Self]`
over the same buffer is formed.

## EachSwiGlu

Fused SwiGLU of a row-major __[rows,columns]__ slice, where `up = None` reduces it to plain SiLU over `gate.len() / rows` columns: y = silu(gate_scale × gate) × up × output_scale.

```rust
pub trait EachSwiGlu: Sized + StorageElement
```

Implementors: - `impl [EachSwiGlu](#EachSwiGlu) for f32`
- `impl [EachSwiGlu](#EachSwiGlu) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [EachSwiGlu](#EachSwiGlu) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`

## swiglu_into

Fused SwiGLU of 2D tensors: y = silu(gate_scale × gate) × up × output_scale.

```rust
fn swiglu_into<GIn, UIn, YOut, const RG: usize, const RU: usize, const RY: usize>(
    gate: &GIn,
    up: Option<&UIn>,
    y: &mut YOut,
    gate_scale: f32,
    output_scale: f32,
) -> Result<(), Error>
where
    GIn: TensorRef<Self, RG> + ?Sized,
    UIn: TensorRef<Self, RU> + ?Sized,
    YOut: TensorMut<Self, RY> + ?Sized,
```

Strides are read from the tensors, so `gate`, `up`, and `y` may be independent strided
sub-spans, for example the two column halves of a __[rows,2×columns]__ gate|up buffer, while
`up = None` reduces to plain SiLU. Returns `Err` on a shape mismatch.

## FmaOps

Extension trait: element-wise multiplication for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait FmaOps<Scalar: Clone + EachFma, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
where
    Scalar::Scalar: From<f32> + Copy,
```

Implementors: - `impl<Scalar: Clone + [EachFma](#EachFma), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [FmaOps](#FmaOps)<Scalar, R> for C where Scalar::Scalar: From<f32> + Copy`

## mul_tensor

Element-wise product of two tensors into a new tensor.

```rust
fn mul_tensor(
    &self,
    other: &impl TensorRef<Scalar, MAX_RANK> + ?Sized,
) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## fma_tensors_into

Writes α × aᵢ × bᵢ + β × cᵢ into the output tensor.

```rust
fn fma_tensors_into<BTensor, CTensor, OutputTensor>(
    &self,
    b: &BTensor,
    c: &CTensor,
    alpha: Scalar::Scalar,
    beta: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
where
    BTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    CTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized,
```

## mul_tensor_into

Element-wise product of two tensors into the output tensor.

```rust
fn mul_tensor_into<OtherTensor, OutputTensor>(
    &self,
    other: &OtherTensor,
    out: &mut OutputTensor,
) -> Result<(), Error>
where
    OtherTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized,
```

## ScaleOps

Extension trait: scalar arithmetic for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait ScaleOps<Scalar: Clone + EachScale, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
where
    Scalar::Scalar: From<f32> + Mul<Output = Scalar::Scalar> + Copy,
```

Implementors: - `impl<Scalar: Clone + [EachScale](#EachScale), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [ScaleOps](#ScaleOps)<Scalar, R> for C where Scalar::Scalar: From<f32> + Mul<Output = Scalar::Scalar> + Copy`

## add_scalar

Element-wise add scalar into a new tensor.

```rust
fn add_scalar(&self, scalar: Scalar::Scalar) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## sub_scalar

Element-wise subtract scalar into a new tensor.

```rust
fn sub_scalar(&self, scalar: Scalar::Scalar) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## mul_scalar

Element-wise multiply scalar into a new tensor.

```rust
fn mul_scalar(&self, scalar: Scalar::Scalar) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## scale_tensor_into

Writes α × aᵢ + β into the output tensor.

```rust
fn scale_tensor_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    alpha: Scalar::Scalar,
    beta: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## add_scalar_into

Element-wise add scalar into the output tensor.

```rust
fn add_scalar_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    scalar: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## sub_scalar_into

Element-wise subtract scalar into the output tensor.

```rust
fn sub_scalar_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    scalar: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## mul_scalar_into

Element-wise multiply scalar into the output tensor.

```rust
fn mul_scalar_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    scalar: Scalar::Scalar,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## SumOps

Extension trait: element-wise addition for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait SumOps<Scalar: Clone + EachSum, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
```

Implementors: - `impl<Scalar: Clone + [EachSum](#EachSum), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [SumOps](#SumOps)<Scalar, R> for C`

## add_tensor

Element-wise sum of two tensors into a new tensor.

```rust
fn add_tensor(
    &self,
    other: &impl TensorRef<Scalar, MAX_RANK> + ?Sized,
) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## add_tensor_into

Element-wise sum of two tensors into the output tensor.

```rust
fn add_tensor_into<OtherTensor, OutputTensor>(
    &self,
    other: &OtherTensor,
    out: &mut OutputTensor,
) -> Result<(), Error>
where
    OtherTensor: TensorRef<Scalar, MAX_RANK> + ?Sized,
    OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized,
```

## BitwiseReductionsOps

Population count, any/none/all reductions over packed-bit ([`u1x8`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8)) tensors.

```rust
pub trait BitwiseReductionsOps<const MAX_RANK: usize>: TensorRef<u1x8, MAX_RANK>
```

Blanket-impl'd on every [`TensorRef<u1x8, R>`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef), so `Tensor<u1x8>`, `TensorView<u1x8>`, and
`TensorSpan<u1x8>` all expose `.popcount()` / `.any_set()` / `.none_set()` / `.all_set()` with
identical spellings. Mirrors `numkong::popcount(tensor_view)` in `cpp/numkong/reduce.hpp`.

Method names use the `_set` suffix to leave room for a future generic `any` / `none` / `all`
over arbitrary scalar predicates and to avoid colliding with the `all` slice marker exported
from `crate::vector`.

Implementors: - `impl<Container, const MAX_RANK: usize> [BitwiseReductionsOps](#BitwiseReductionsOps)<MAX_RANK> for Container where Container: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<[u1x8](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8), MAX_RANK> + ?Sized`

## popcount

Number of set bits across the entire tensor.

```rust
fn popcount(&self) -> Result<u64, Error>
```

## any_set

`true` if at least one bit in the tensor is set.

```rust
fn any_set(&self) -> Result<bool, Error>
```

## none_set

`true` if no bit in the tensor is set.

```rust
fn none_set(&self) -> Result<bool, Error>
```

## all_set

`true` if every bit in the tensor is set.

```rust
fn all_set(&self) -> Result<bool, Error>
```

## MinMaxOps

Extension trait: min/max reductions for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait MinMaxOps<Scalar: Clone + ReduceMinMax, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
where
    Scalar::Output: Clone + Default + PartialOrd,
```

Implementors: - `impl<Scalar: Clone + [ReduceMinMax](#ReduceMinMax), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R>> [MinMaxOps](#MinMaxOps)<Scalar, R> for C where Scalar::Output: Clone + Default + PartialOrd`

## minmax_all

Minimum and maximum with their indices over all elements.

```rust
fn minmax_all(&self) -> Result<MinMaxResult<Scalar::Output>, Error>
```

## minmax_axis

Minimum and maximum with their indices along one axis, into new tensors.

```rust
fn minmax_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<MinMaxResult<Tensor<<Scalar as ReduceMinMax>::Output, Self::Alloc, MAX_RANK>, Tensor<usize, Self::Alloc, MAX_RANK>>, Error>
where
    Self::Alloc: Clone,
```

## minmax_axis_into

Minimum and maximum with their indices along one axis, into the output tensors.

```rust
fn minmax_axis_into<AnyIndex, ValueTensor, IndexTensor>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
    min_out: &mut ValueTensor,
    argmin_out: &mut IndexTensor,
    max_out: &mut ValueTensor,
    argmax_out: &mut IndexTensor,
) -> Result<(), Error>
where
    AnyIndex: VectorIndex,
    ValueTensor: TensorMut<Scalar::Output, MAX_RANK> + ?Sized,
    IndexTensor: TensorMut<usize, MAX_RANK> + ?Sized,
```

## min_all

Minimum over all elements.

```rust
fn min_all(&self) -> Result<Scalar::Output, Error>
```

## argmin_all

Index of the minimum over all elements.

```rust
fn argmin_all(&self) -> Result<usize, Error>
```

## max_all

Maximum over all elements.

```rust
fn max_all(&self) -> Result<Scalar::Output, Error>
```

## argmax_all

Index of the maximum over all elements.

```rust
fn argmax_all(&self) -> Result<usize, Error>
```

## min_axis

Minimum along one axis, into a new tensor.

```rust
fn min_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<Scalar::Output, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## argmin_axis

Index of the minimum along one axis, into a new tensor.

```rust
fn argmin_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<usize, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## max_axis

Maximum along one axis, into a new tensor.

```rust
fn max_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<Scalar::Output, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## argmax_axis

Index of the maximum along one axis, into a new tensor.

```rust
fn argmax_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<usize, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## MomentsOps

Extension trait: statistical reductions for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait MomentsOps<Scalar: Clone + ReduceMoments, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
where
    Scalar::SumOutput: Clone + Default + AddAssign,
    Scalar::SumSqOutput: Clone + Default + AddAssign + SumSqToF64,
```

Implementors: - `impl<Scalar: Clone + [ReduceMoments](#ReduceMoments), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R>> [MomentsOps](#MomentsOps)<Scalar, R> for C where Scalar::SumOutput: Clone + Default + AddAssign, Scalar::SumSqOutput: Clone + Default + AddAssign + SumSqToF64`

## moments_all

Sum and sum of squares over all elements.

```rust
fn moments_all(&self) -> Result<(Scalar::SumOutput, Scalar::SumSqOutput), Error>
```

## moments_axis

Sum and sum of squares along one axis, into new tensors.

```rust
fn moments_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<(Tensor<<Scalar as ReduceMoments>::SumOutput, Self::Alloc, MAX_RANK>, Tensor<<Scalar as ReduceMoments>::SumSqOutput, Self::Alloc, MAX_RANK>), Error>
where
    Self::Alloc: Clone,
```

## moments_axis_into

Sum and sum of squares along one axis, into the output tensors.

```rust
fn moments_axis_into<AnyIndex, SumTensor, SumSqTensor>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
    sum_out: &mut SumTensor,
    sumsq_out: &mut SumSqTensor,
) -> Result<(), Error>
where
    AnyIndex: VectorIndex,
    SumTensor: TensorMut<Scalar::SumOutput, MAX_RANK> + ?Sized,
    SumSqTensor: TensorMut<Scalar::SumSqOutput, MAX_RANK> + ?Sized,
```

## sum_all

Sum over all elements.

```rust
fn sum_all(&self) -> Result<Scalar::SumOutput, Error>
```

## sum_axis

Sum along one axis, into a new tensor.

```rust
fn sum_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<Scalar::SumOutput, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## sum_axis_into

Sum along one axis, into the output tensor.

```rust
fn sum_axis_into<AnyIndex, SumTensor>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
    out: &mut SumTensor,
) -> Result<(), Error>
where
    AnyIndex: VectorIndex,
    SumTensor: TensorMut<Scalar::SumOutput, MAX_RANK> + ?Sized,
```

## norm_all

Euclidean norm over all elements.

```rust
fn norm_all(&self) -> Result<f64, Error>
```

## norm_axis

Euclidean norm along one axis, into a new tensor.

```rust
fn norm_axis<AnyIndex: VectorIndex>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
) -> Result<Tensor<f64, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## norm_axis_into

Euclidean norm along one axis, into the output tensor.

```rust
fn norm_axis_into<AnyIndex, NormTensor>(
    &self,
    axis: AnyIndex,
    keep_dims: bool,
    out: &mut NormTensor,
) -> Result<(), Error>
where
    AnyIndex: VectorIndex,
    NormTensor: TensorMut<f64, MAX_RANK> + ?Sized,
```

## ReduceMinMax

Find minimum and maximum values with their indices, with stride support.

```rust
pub trait ReduceMinMax: StorageElement
```

Returns `Ok(Some(MinMaxResult))` for all elements in a slice, or `Ok(None)` if all elements are
NaN, for NaN-masking formats. The output value type matches the logical reduced scalar type. A
refusing kernel fails with [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed).

Implementors: - `impl [ReduceMinMax](#ReduceMinMax) for f64`
- `impl [ReduceMinMax](#ReduceMinMax) for f32`
- `impl [ReduceMinMax](#ReduceMinMax) for i8`
- `impl [ReduceMinMax](#ReduceMinMax) for u8`
- `impl [ReduceMinMax](#ReduceMinMax) for i16`
- `impl [ReduceMinMax](#ReduceMinMax) for u16`
- `impl [ReduceMinMax](#ReduceMinMax) for i32`
- `impl [ReduceMinMax](#ReduceMinMax) for u32`
- `impl [ReduceMinMax](#ReduceMinMax) for i64`
- `impl [ReduceMinMax](#ReduceMinMax) for u64`
- `impl [ReduceMinMax](#ReduceMinMax) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [ReduceMinMax](#ReduceMinMax) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [ReduceMinMax](#ReduceMinMax) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [ReduceMinMax](#ReduceMinMax) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [ReduceMinMax](#ReduceMinMax) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [ReduceMinMax](#ReduceMinMax) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [ReduceMinMax](#ReduceMinMax) for [i4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#i4x2)`
- `impl [ReduceMinMax](#ReduceMinMax) for [u4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u4x2)`
- `impl [ReduceMinMax](#ReduceMinMax) for [u1x8](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8)`

## Output

Output type for the min/max values — matches the C layer's native type.

```rust
type Output: StorageElement;
```

## NONE_ON_SENTINEL

Whether `NUMKONG_SIZE_MAX` indicates that the reduction produced no value.

```rust
const NONE_ON_SENTINEL: bool;
```

## reduce_minmax

Returns `Ok(Some(MinMaxResult))` for the given data with the specified stride, or `Ok(None)` if all elements are NaN.

```rust
fn reduce_minmax(data: &[Self], stride: usize) -> Result<Option<MinMaxResult<Self::Output>>, Error>
```

Reads `data.len()` logical elements starting at `data.as_ptr()`, advancing by `stride`
between each — pass `size_of::<Self>()` for contiguous storage.

## ReduceMoments

Compute first and second moments — sum and sum-of-squares — with stride support.

```rust
pub trait ReduceMoments: StorageElement
```

Returns `(sum, sum_of_squares)` for all elements in a slice, with optional striding.
The output types may be wider than the input to avoid overflow.

Errors: [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed) when no capability of the current
[`Capabilities`](https://www.unum.cloud/docs/numkong/rust/runtime-dispatch.md#Capabilities) has the kernel.

Implementors: - `impl [ReduceMoments](#ReduceMoments) for f64`
- `impl [ReduceMoments](#ReduceMoments) for f32`
- `impl [ReduceMoments](#ReduceMoments) for i8`
- `impl [ReduceMoments](#ReduceMoments) for u8`
- `impl [ReduceMoments](#ReduceMoments) for i16`
- `impl [ReduceMoments](#ReduceMoments) for u16`
- `impl [ReduceMoments](#ReduceMoments) for i32`
- `impl [ReduceMoments](#ReduceMoments) for u32`
- `impl [ReduceMoments](#ReduceMoments) for i64`
- `impl [ReduceMoments](#ReduceMoments) for u64`
- `impl [ReduceMoments](#ReduceMoments) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [ReduceMoments](#ReduceMoments) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [ReduceMoments](#ReduceMoments) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [ReduceMoments](#ReduceMoments) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [ReduceMoments](#ReduceMoments) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [ReduceMoments](#ReduceMoments) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [ReduceMoments](#ReduceMoments) for [i4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#i4x2)`
- `impl [ReduceMoments](#ReduceMoments) for [u4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u4x2)`
- `impl [ReduceMoments](#ReduceMoments) for [u1x8](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8)`

## SumOutput

Type for the sum output.

```rust
type SumOutput: StorageElement;
```

## SumSqOutput

Type for the sum-of-squares output.

```rust
type SumSqOutput: StorageElement;
```

## reduce_moments

Compute `(sum, sum_of_squares)` for `data` with the given stride in bytes.

```rust
fn reduce_moments(
    data: &[Self],
    stride: usize,
) -> Result<(Self::SumOutput, Self::SumSqOutput), Error>
```

Use `stride = size_of::<Self>()` for contiguous data.

Reads `data.len()` logical elements starting at `data.as_ptr()`, advancing by `stride`
between each — pass `size_of::<Self>()` for contiguous storage.

## Reductions

[`Reductions`](#Reductions) bundles reduction operations: ReduceMoments and ReduceMinMax.

```rust
pub trait Reductions: ReduceMoments + ReduceMinMax
```

Implementors: - `impl<Scalar: [ReduceMoments](#ReduceMoments) + [ReduceMinMax](#ReduceMinMax)> [Reductions](#Reductions) for Scalar`

## TrigAtan

Computes __element-wise arctangent__ of a vector.

```rust
pub trait TrigAtan: Sized + StorageElement
```

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implementors: - `impl [TrigAtan](#TrigAtan) for f64`
- `impl [TrigAtan](#TrigAtan) for f32`
- `impl [TrigAtan](#TrigAtan) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`

## atan

Writes the arctangent of every input element, in radians, into the output slice.

```rust
fn atan(inputs: &[Self], outputs: &mut [Self]) -> Result<(), Error>
```

## atan_inplace

In-place arctangent: `data[i] = atan(data[i])`.

```rust
fn atan_inplace(data: &mut [Self]) -> Result<(), Error>
```

Both source and destination pointers are derived from the single `&mut`, so no aliased
`&[Self]` + `&mut [Self]` over the same storage is formed.

## TrigAtanOps

Extension trait: element-wise arctangent for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait TrigAtanOps<Scalar: Clone + TrigAtan, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
```

Implementors: - `impl<Scalar: Clone + [TrigAtan](#TrigAtan), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [TrigAtanOps](#TrigAtanOps)<Scalar, R> for C`

## atan

Element-wise arctangent into a new tensor.

```rust
fn atan(&self) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## atan_into

Element-wise arctangent into the output tensor.

```rust
fn atan_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## TrigCos

Computes __element-wise cosine__ of a vector.

```rust
pub trait TrigCos: Sized + StorageElement
```

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implementors: - `impl [TrigCos](#TrigCos) for f64`
- `impl [TrigCos](#TrigCos) for f32`
- `impl [TrigCos](#TrigCos) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`

## cos

Writes the cosine of every input element, in radians, into the output slice.

```rust
fn cos(inputs: &[Self], outputs: &mut [Self]) -> Result<(), Error>
```

## cos_inplace

In-place cosine: `data[i] = cos(data[i])`.

```rust
fn cos_inplace(data: &mut [Self]) -> Result<(), Error>
```

Both source and destination pointers are derived from the single `&mut`, so no aliased
`&[Self]` + `&mut [Self]` over the same storage is formed.

## TrigCosOps

Extension trait: element-wise cosine for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait TrigCosOps<Scalar: Clone + TrigCos, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
```

Implementors: - `impl<Scalar: Clone + [TrigCos](#TrigCos), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [TrigCosOps](#TrigCosOps)<Scalar, R> for C`

## cos

Element-wise cosine into a new tensor.

```rust
fn cos(&self) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## cos_into

Element-wise cosine into the output tensor.

```rust
fn cos_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## TrigSin

Computes __element-wise sine__ of a vector.

```rust
pub trait TrigSin: Sized + StorageElement
```

Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed)
carrying the kernel's status.

Implementors: - `impl [TrigSin](#TrigSin) for f64`
- `impl [TrigSin](#TrigSin) for f32`
- `impl [TrigSin](#TrigSin) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`

## sin

Writes the sine of every input element, in radians, into the output slice.

```rust
fn sin(inputs: &[Self], outputs: &mut [Self]) -> Result<(), Error>
```

## sin_inplace

In-place sine: `data[i] = sin(data[i])`.

```rust
fn sin_inplace(data: &mut [Self]) -> Result<(), Error>
```

Both source and destination pointers are derived from the single `&mut`, so no aliased
`&[Self]` + `&mut [Self]` over the same storage is formed.

## TrigSinOps

Extension trait: element-wise sine for any [`TensorRef`](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef) implementor.

```rust
pub trait TrigSinOps<Scalar: Clone + TrigSin, const MAX_RANK: usize>: TensorRef<Scalar, MAX_RANK>
```

Implementors: - `impl<Scalar: Clone + [TrigSin](#TrigSin), const R: usize, C: [TensorRef](https://www.unum.cloud/docs/numkong/rust/tensors-and-views.md#TensorRef)<Scalar, R> + ?Sized> [TrigSinOps](#TrigSinOps)<Scalar, R> for C`

## sin

Element-wise sine into a new tensor.

```rust
fn sin(&self) -> Result<Tensor<Scalar, Self::Alloc, MAX_RANK>, Error>
where
    Self::Alloc: Clone,
```

## sin_into

Element-wise sine into the output tensor.

```rust
fn sin_into<OutputTensor: TensorMut<Scalar, MAX_RANK> + ?Sized>(
    &self,
    out: &mut OutputTensor,
) -> Result<(), Error>
```

## Trigonometry

[`Trigonometry`](#Trigonometry) bundles trigonometric functions: TrigSin, TrigCos, and TrigAtan.

```rust
pub trait Trigonometry: TrigSin + TrigCos + TrigAtan
```

Implementors: - `impl<Scalar: [TrigSin](#TrigSin) + [TrigCos](#TrigCos) + [TrigAtan](#TrigAtan)> [Trigonometry](#Trigonometry) for Scalar`

## MinMaxResult

Named result from min/max reduction operations.

```rust
pub struct MinMaxResult<Value, AnyIndex = usize>
```

`AnyIndex` defaults to `usize` and `Value` is the scalar output type for scalar reductions such
as [`minmax_all`](#minmax_all), while for axis reductions such as [`minmax_axis`](#minmax_axis), `Value` and `AnyIndex` are
both tensors.

- `min_value` `Value`: Smallest value.
- `min_index` `AnyIndex`: Index of the smallest value.
- `max_value` `Value`: Largest value.
- `max_index` `AnyIndex`: Index of the largest value.

Implements: `Debug`, `Clone`, `StructuralPartialEq`, `PartialEq`, `Eq`

