Skip to main content

teeny_triton/triton/
mod.rs

1/*
2 * Copyright (c) 2026 Teenygrad.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *   http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use core::ops::{Add, Div, Mul, Neg, Sub};
18pub use core::ops::{BitAnd, BitOr};
19
20use self::types::{self as ty};
21
22/// LLVM-backend-facing DSL types (the compiled counterpart of this module's `Tensor`/`Pointer`).
23pub mod llvm;
24/// Dtype/numeric-kind trait hierarchy (`Dtype`, `Num`, `Int`, `Float`) used to bound the `Triton`
25/// trait's generic methods.
26pub mod types;
27
28pub use types::*;
29
30/*------------------------------ Parameter Enums ------------------------------*/
31
32/// A grid/program-ID axis.
33#[repr(i32)]
34pub enum Axis {
35    /// The first (fastest-varying) grid axis.
36    X = 0,
37    /// The second grid axis.
38    Y = 1,
39    /// The third grid axis.
40    Z = 2,
41}
42
43/// Padding value applied to out-of-bounds lanes when using `boundary_check` in `load`.
44pub enum PaddingOption {
45    /// Pad with zero.
46    Zero,
47    /// Pad with NaN.
48    Nan,
49}
50
51/// L1/L2 cache behaviour for load and store instructions.
52pub enum CacheModifier {
53    /// Cache at all levels (L1 + L2).
54    Ca,
55    /// Cache at global level only (L2, bypass L1).
56    Cg,
57    /// Volatile — don't cache, always fetch from memory.
58    Cv,
59    /// Write-back at all coherent levels.
60    Wb,
61    /// Streaming — likely accessed once.
62    Cs,
63}
64
65/// Cache eviction priority hint for load and store instructions.
66pub enum EvictionPolicy {
67    /// Evict this data first (low reuse expected).
68    EvictFirst,
69    /// Evict this data last (high reuse expected).
70    EvictLast,
71    /// No eviction priority hint.
72    NoEvict,
73}
74
75/// Tensor-core precision mode for `dot` on `f32 × f32` inputs.
76pub enum InputPrecision {
77    /// TF32 precision (default on devices with Tensor Cores).
78    TF32,
79    /// Emulate higher precision using three TF32 dot products.
80    TF32x3,
81    /// Full IEEE-754 precision.
82    IEEE,
83}
84
85/// Rounding mode used when down-casting floating-point types in `cast`.
86pub enum FpDowncastRounding {
87    /// Round to nearest, ties to even.
88    Rtne,
89    /// Round towards zero (truncate).
90    Rtz,
91}
92
93/// Input format for scaled dot-product (`dot_scaled`).
94pub enum DotFormat {
95    /// 8-bit float, 4 exponent + 3 mantissa bits.
96    E4M3,
97    /// 8-bit float, 5 exponent + 2 mantissa bits.
98    E5M2,
99    /// 4-bit float (2 exponent + 1 mantissa bit), packed 2-per-byte.
100    E2M1x2,
101    /// 4-bit float (2 exponent + 1 mantissa bit), packed 4-per-byte.
102    E2M1x4,
103    /// `bfloat16`, packed 2-per-32-bits.
104    BF16x2,
105    /// Signed 8-bit integer.
106    Int8,
107    /// Unsigned 8-bit integer.
108    UInt8,
109}
110
111/// Memory ordering semantics for atomic operations.
112pub enum MemSem {
113    /// No ordering constraint beyond atomicity.
114    Relaxed,
115    /// Acquire ordering: subsequent operations can't be reordered before this one.
116    Acquire,
117    /// Release ordering: prior operations can't be reordered after this one.
118    Release,
119    /// Acquire + Release (default).
120    AcqRel,
121}
122
123/// Synchronization scope for atomic operations.
124pub enum MemScope {
125    /// Cooperative thread array (thread block).
126    Cta,
127    /// All threads on the GPU (default).
128    Gpu,
129    /// All threads in the system.
130    Sys,
131}
132
133/*------------------------------ Triton Trait ------------------------------*/
134
135/// The Triton-like kernel DSL: tensor/pointer types and the operations (creation, shape
136/// manipulation, linear algebra, memory, math, reduction, scan/sort, atomics, RNG) available
137/// inside a `#[kernel]`-annotated function. See the module docs for how this compiles.
138pub trait Triton
139where
140    Self::I32Tensor: Add<i32, Output = Self::I32Tensor>,
141    Self::I32Tensor: Sub<i32, Output = Self::I32Tensor>,
142    Self::I32Tensor: Mul<i32, Output = Self::I32Tensor>,
143    Self::I32Tensor: Div<i32, Output = Self::I32Tensor>,
144    Self::BoolTensor: BitAnd<Output = Self::BoolTensor>,
145    Self::BoolTensor: BitOr<Output = Self::BoolTensor>,
146{
147    /// A tensor of `bool`, produced by comparisons and used as a mask.
148    type BoolTensor: Copy + Clone;
149    /// A tensor of `i32`, e.g. produced by [`Triton::arange`].
150    type I32Tensor: Copy + Clone;
151    /// A tensor of dtype `D`.
152    type Tensor<D: ty::Dtype>: Copy
153        + Clone
154        + Add<Self::Tensor<D>, Output = Self::Tensor<D>>
155        + Sub<Self::Tensor<D>, Output = Self::Tensor<D>>
156        + Mul<Self::Tensor<D>, Output = Self::Tensor<D>>
157        + Div<Self::Tensor<D>, Output = Self::Tensor<D>>
158        + Neg<Output = Self::Tensor<D>>;
159    /// A device pointer to elements of dtype `D`.
160    type Pointer<D: ty::Dtype>: Copy
161        + Clone
162        + ty::Dtype
163        + Add<Self::Pointer<D>, Output = Self::Pointer<D>>;
164
165    /*------------------------------ Programming Model ------------------------------*/
166
167    /// The current program's index along `axis` within the launch grid.
168    fn program_id(axis: Axis) -> i32;
169
170    /// The total number of programs launched along `axis`.
171    fn num_programs(axis: Axis) -> i32;
172
173    /// Scalar gather: load the `f32` at `ptr + offset`, truncate to `i32`,
174    /// and return it as a plain Rust `i32` usable in scalar arithmetic
175    /// (e.g. as an addend to `arange` results via `I32Tensor + i32`).
176    ///
177    /// Used when integer indices are stored as f32 (the graph's default dtype).
178    fn load_scalar_f32_as_i32(ptr: Self::Pointer<f32>, offset: i32) -> i32;
179
180    /*------------------------------ Creation Ops ------------------------------*/
181
182    /// Create a 1-D `i32` tensor with values `[start, start+1, ..., end-1]`.
183    fn arange(start: impl Into<i32>, end: impl Into<i32>) -> Self::I32Tensor;
184
185    /// Create a 1-D `f32` tensor with values `[start as f32, start+1, ..., end-1]`.
186    ///
187    /// Equivalent to casting `arange(start, end)` to f32, but avoids the
188    /// intermediate I32Tensor copy that some backends cannot handle.
189    fn arange_f32(start: impl Into<i32>, end: impl Into<i32>) -> Self::Tensor<f32>;
190
191    /// Create a tensor of the given `shape` filled with zeros.
192    fn zeros<D: ty::Dtype>(shape: &[i32]) -> Self::Tensor<D>;
193
194    /// Create a zero-filled tensor with the same shape/dtype as `x`.
195    fn zeros_like<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
196
197    /// Create a tensor of the given `shape` filled with `value`.
198    fn full<D: ty::Dtype>(shape: &[i32], value: D) -> Self::Tensor<D>;
199
200    /// Cast a tensor to a different dtype.
201    ///
202    /// - `fp_downcast_rounding`: rounding mode when narrowing float types (default `None` = unspecified).
203    /// - `bitcast`: reinterpret bits without conversion (default `false`).
204    fn cast<Src: ty::Dtype, Dst: ty::Dtype>(
205        x: Self::Tensor<Src>,
206        fp_downcast_rounding: Option<FpDowncastRounding>,
207        bitcast: bool,
208    ) -> Self::Tensor<Dst>;
209
210    /// Concatenate two tensors.
211    ///
212    /// - `can_reorder`: allow the compiler to reorder elements (default `false`).
213    fn cat<D: ty::Dtype>(
214        a: Self::Tensor<D>,
215        b: Self::Tensor<D>,
216        can_reorder: bool,
217    ) -> Self::Tensor<D>;
218
219    /*------------------------------ Shape Manipulation Ops ------------------------------*/
220
221    /// Broadcast two tensors to a common compatible shape.
222    fn broadcast<D: ty::Dtype>(
223        a: Self::Tensor<D>,
224        b: Self::Tensor<D>,
225    ) -> (Self::Tensor<D>, Self::Tensor<D>);
226
227    /// Broadcast `x` to `shape`.
228    fn broadcast_to<D: ty::Dtype>(x: Self::Tensor<D>, shape: &[i32]) -> Self::Tensor<D>;
229
230    /// Insert a size-1 dimension at `axis`.
231    fn expand_dims<D: ty::Dtype>(x: Self::Tensor<D>, axis: i32) -> Self::Tensor<D>;
232
233    /// Permute `x`'s dimensions according to `dims`.
234    fn permute<D: ty::Dtype>(x: Self::Tensor<D>, dims: &[i32]) -> Self::Tensor<D>;
235
236    /// Reshape a tensor.
237    ///
238    /// - `can_reorder`: allow element reordering during reshape (default `false`).
239    fn reshape<D: ty::Dtype>(
240        x: Self::Tensor<D>,
241        shape: &[i32],
242        can_reorder: bool,
243    ) -> Self::Tensor<D>;
244
245    /// Permute dimensions. Alias for `permute`.
246    fn trans<D: ty::Dtype>(x: Self::Tensor<D>, dims: &[i32]) -> Self::Tensor<D>;
247
248    /// Flatten to 1-D.
249    ///
250    /// - `can_reorder`: allow element reordering (default `false`).
251    fn ravel<D: ty::Dtype>(x: Self::Tensor<D>, can_reorder: bool) -> Self::Tensor<D>;
252
253    /// View with a new shape (order not preserved).
254    fn view<D: ty::Dtype>(x: Self::Tensor<D>, shape: &[i32]) -> Self::Tensor<D>;
255
256    /// Join two tensors along a new minor dimension.
257    fn join<D: ty::Dtype>(a: Self::Tensor<D>, b: Self::Tensor<D>) -> Self::Tensor<D>;
258
259    /// Interleave two tensors along their last dimension.
260    fn interleave<D: ty::Dtype>(a: Self::Tensor<D>, b: Self::Tensor<D>) -> Self::Tensor<D>;
261
262    /// Split a tensor in two along its last dimension (which must have size 2).
263    fn split<D: ty::Dtype>(x: Self::Tensor<D>) -> (Self::Tensor<D>, Self::Tensor<D>);
264
265    /*------------------------------ Linear Algebra Ops ------------------------------*/
266
267    /// Matrix (or batched matrix) multiply.
268    ///
269    /// - `acc`: optional accumulator tensor added to the result.
270    /// - `input_precision`: Tensor Core precision for `f32 × f32`. No default — every call site must
271    ///   pick one explicitly. `IEEE` matches `tt.dot`'s own default (full-precision, no tensor cores);
272    ///   `TF32` routes through tensor cores at reduced mantissa precision. A silent default here is
273    ///   exactly what caused kernels to unknowingly run at `IEEE` instead of the intended `TF32`.
274    /// - `max_num_imprecise_acc`: limit on imprecise accumulations (default `None`).
275    fn dot<D: ty::Num, O: ty::Num>(
276        a: Self::Tensor<D>,
277        b: Self::Tensor<D>,
278        acc: Option<Self::Tensor<O>>,
279        input_precision: InputPrecision,
280        max_num_imprecise_acc: Option<i32>,
281    ) -> Self::Tensor<O>;
282
283    /// Scaled mixed-precision matrix multiply (FP8 / narrow formats).
284    ///
285    /// - `acc`: optional accumulator (default `None`).
286    /// - `fast_math`: allow reduced precision accumulation (default `false`).
287    fn dot_scaled<D: ty::Num, S: ty::Num, O: ty::Num>(
288        lhs: Self::Tensor<D>,
289        lhs_scale: Self::Tensor<S>,
290        lhs_format: DotFormat,
291        rhs: Self::Tensor<D>,
292        rhs_scale: Self::Tensor<S>,
293        rhs_format: DotFormat,
294        acc: Option<Self::Tensor<O>>,
295        fast_math: bool,
296    ) -> Self::Tensor<O>;
297
298    /*------------------------------ Memory / Pointer Ops ------------------------------*/
299
300    /// Create a block pointer encoding shape, strides, offsets, and tile shape.
301    fn make_block_ptr<D: ty::Dtype>(
302        base: Self::Pointer<D>,
303        shape: &[i32],
304        strides: &[i32],
305        offsets: &[i32],
306        block_shape: &[i32],
307        order: &[i32],
308    ) -> Self::Pointer<D>;
309
310    /// Advance a block pointer by the given per-dimension offsets.
311    fn advance<D: ty::Dtype>(ptr: Self::Pointer<D>, offsets: &[i32]) -> Self::Pointer<D>;
312
313    /// Create a tensor descriptor for TMA (Tensor Memory Accelerator) operations.
314    ///
315    /// - `padding_option`: out-of-bounds padding behaviour (default `PaddingOption::Zero`).
316    fn make_tensor_descriptor<D: ty::Dtype>(
317        base: Self::Pointer<D>,
318        shape: &[i32],
319        strides: &[i32],
320        block_shape: &[i32],
321        padding_option: Option<PaddingOption>,
322    ) -> Self::Pointer<D>;
323
324    /// Load a tile from memory using a tensor descriptor and per-dimension offsets.
325    fn load_tensor_descriptor<D: ty::Dtype>(
326        desc: Self::Pointer<D>,
327        offsets: &[i32],
328    ) -> Self::Tensor<D>;
329
330    /// Store a tile to memory using a tensor descriptor and per-dimension offsets.
331    fn store_tensor_descriptor<D: ty::Dtype>(
332        desc: Self::Pointer<D>,
333        offsets: &[i32],
334        value: Self::Tensor<D>,
335    );
336
337    /// Load a tensor from memory.
338    ///
339    /// - `mask`: when `Some`, lanes where mask is `false` are not loaded (default `None` = unconditional).
340    /// - `other`: fill value for masked-off lanes (default `None` = undefined).
341    /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
342    /// - `padding_option`: fill for out-of-bounds lanes in block-pointer mode (default `None`).
343    /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
344    /// - `eviction_policy`: eviction priority hint (default `None`).
345    /// - `volatile`: always fetch fresh from memory (default `false`).
346    fn load<D: ty::Dtype, const N: usize>(
347        ptr: Self::Tensor<Self::Pointer<D>>,
348        mask: Option<Self::BoolTensor>,
349        other: Option<Self::Tensor<D>>,
350        boundary_check: &[i32; N],
351        padding_option: Option<PaddingOption>,
352        cache_modifier: Option<CacheModifier>,
353        eviction_policy: Option<EvictionPolicy>,
354        volatile: bool,
355    ) -> Self::Tensor<D>;
356
357    /// Store a tensor to memory.
358    ///
359    /// - `mask`: when `Some`, lanes where mask is `false` are not stored (default `None` = unconditional).
360    /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
361    /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
362    /// - `eviction_policy`: eviction priority hint (default `None`).
363    fn store<D: ty::Dtype, const N: usize>(
364        dest: Self::Tensor<Self::Pointer<D>>,
365        src: Self::Tensor<D>,
366        mask: Option<Self::BoolTensor>,
367        boundary_check: &[i32; N],
368        cache_modifier: Option<CacheModifier>,
369        eviction_policy: Option<EvictionPolicy>,
370    );
371
372    /*------------------------------ Comparison Ops ------------------------------*/
373
374    /// Element-wise less-than between two tensors.
375    fn lt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
376    /// Element-wise less-than-or-equal between two tensors.
377    fn le<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
378    /// Element-wise greater-than between two tensors.
379    fn gt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
380    /// Element-wise greater-than-or-equal between two tensors.
381    fn ge<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
382    /// Element-wise equality between two tensors.
383    fn eq<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
384    /// Element-wise inequality between two tensors.
385    fn ne<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
386
387    /// Element-wise less-than against a scalar.
388    fn lt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
389    /// Element-wise less-than-or-equal against a scalar.
390    fn le_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
391    /// Element-wise greater-than against a scalar.
392    fn gt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
393    /// Element-wise greater-than-or-equal against a scalar.
394    fn ge_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
395    /// Element-wise equality against a scalar.
396    fn eq_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
397    /// Element-wise inequality against a scalar.
398    fn ne_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
399
400    /*------------------------------ Indexing Ops ------------------------------*/
401
402    /// Conditional element selection — corresponds to `tl.where`.
403    /// Named `where_` to avoid collision with the Rust keyword `where`.
404    fn where_<D: ty::Dtype>(
405        cond: Self::BoolTensor,
406        x: Self::Tensor<D>,
407        y: Self::Tensor<D>,
408    ) -> Self::Tensor<D>;
409
410    /// Reverse a tensor along `dim`. `None` reverses all dimensions.
411    fn flip<D: ty::Dtype>(x: Self::Tensor<D>, dim: Option<i32>) -> Self::Tensor<D>;
412
413    /// Gather elements from `src` along `axis` using `index`.
414    fn gather<D: ty::Dtype>(
415        src: Self::Tensor<D>,
416        index: Self::I32Tensor,
417        axis: i32,
418    ) -> Self::Tensor<D>;
419
420    /*------------------------------ Math Ops — Unary ------------------------------*/
421
422    /// Element-wise absolute value.
423    fn abs<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
424    /// Element-wise ceiling.
425    fn ceil<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
426    /// Element-wise floor.
427    fn floor<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
428    /// Element-wise cosine.
429    fn cos<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
430    /// Element-wise sine.
431    fn sin<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
432    /// Element-wise natural exponential (`e^x`).
433    fn exp<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
434    /// Element-wise base-2 exponential (`2^x`).
435    fn exp2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
436    /// Element-wise natural logarithm.
437    fn log<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
438    /// Element-wise base-2 logarithm.
439    fn log2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
440    /// Element-wise reciprocal square root (`1/sqrt(x)`).
441    fn rsqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
442    /// Element-wise sigmoid (`1/(1+e^-x)`).
443    fn sigmoid<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
444    /// Element-wise square root.
445    fn sqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
446    /// Element-wise square root, round-to-nearest.
447    fn sqrt_rn<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
448    /// Element-wise error function.
449    fn erf<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
450    /// Element-wise arctangent.
451    fn atan<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
452
453    /*------------------------------ Math Ops — Float (higher-level) ------------------------------*/
454
455    /// Numerically-stable softmax along `dim`. `dim = None` defaults to the last dimension.
456    ///
457    /// - `keep_dims`: retain the reduced dimension with length 1 (default `false`).
458    /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
459    fn softmax<D: ty::Float>(
460        x: Self::Tensor<D>,
461        dim: Option<i32>,
462        keep_dims: bool,
463        ieee_rounding: bool,
464    ) -> Self::Tensor<D>;
465
466    /*------------------------------ Math Ops — Binary ------------------------------*/
467
468    /// Element-wise maximum of two tensors.
469    fn maximum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
470    /// Element-wise minimum of two tensors.
471    fn minimum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
472
473    /// Element-wise clamp of `x` to `[lo, hi]`.
474    fn clamp<D: ty::Num>(
475        x: Self::Tensor<D>,
476        lo: Self::Tensor<D>,
477        hi: Self::Tensor<D>,
478    ) -> Self::Tensor<D>;
479
480    /// Element-wise fused multiply-add: `x * y + z`.
481    fn fma<D: ty::Float>(
482        x: Self::Tensor<D>,
483        y: Self::Tensor<D>,
484        z: Self::Tensor<D>,
485    ) -> Self::Tensor<D>;
486
487    /// Element-wise floating-point division.
488    ///
489    /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
490    fn fdiv<D: ty::Float>(
491        x: Self::Tensor<D>,
492        y: Self::Tensor<D>,
493        ieee_rounding: bool,
494    ) -> Self::Tensor<D>;
495
496    /// Element-wise division, round-to-nearest.
497    fn div_rn<D: ty::Float>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
498
499    /// Element-wise high 32 bits of an unsigned 32×32→64-bit multiply.
500    fn umulhi(x: Self::Tensor<u32>, y: Self::Tensor<u32>) -> Self::Tensor<u32>;
501
502    /// Ceiling integer division: `ceil(x / div)`.
503    fn cdiv(x: i32, div: i32) -> i32;
504
505    /// Swizzle 2-D indices for shared-memory bank-conflict avoidance.
506    /// Returns the remapped `(i, j)` indices.
507    fn swizzle2d(i: i32, j: i32, size_i: i32, size_j: i32, size_g: i32) -> (i32, i32);
508
509    /*------------------------------ Reduction Ops ------------------------------*/
510
511    /// Sum all elements along `axis`. `axis = None` reduces all dimensions.
512    fn sum<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
513
514    /// Maximum along `axis`. `axis = None` reduces all dimensions.
515    fn max<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
516
517    /// Maximum along `axis`, also returning the index of the maximum.
518    ///
519    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
520    fn max_with_indices<D: ty::Num>(
521        x: Self::Tensor<D>,
522        axis: i32,
523        tie_break_left: bool,
524        keep_dims: bool,
525    ) -> (Self::Tensor<D>, Self::I32Tensor);
526
527    /// Minimum along `axis`. `axis = None` reduces all dimensions.
528    fn min<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
529
530    /// Minimum along `axis`, also returning the index of the minimum.
531    ///
532    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
533    fn min_with_indices<D: ty::Num>(
534        x: Self::Tensor<D>,
535        axis: i32,
536        tie_break_left: bool,
537        keep_dims: bool,
538    ) -> (Self::Tensor<D>, Self::I32Tensor);
539
540    /// Index of the maximum along `axis`.
541    ///
542    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
543    fn argmax<D: ty::Num>(
544        x: Self::Tensor<D>,
545        axis: i32,
546        tie_break_left: bool,
547        keep_dims: bool,
548    ) -> Self::I32Tensor;
549
550    /// Index of the minimum along `axis`.
551    ///
552    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
553    fn argmin<D: ty::Num>(
554        x: Self::Tensor<D>,
555        axis: i32,
556        tie_break_left: bool,
557        keep_dims: bool,
558    ) -> Self::I32Tensor;
559
560    /// XOR-reduction along `axis`. `axis = None` reduces all dimensions.
561    fn xor_sum<D: ty::Int>(
562        x: Self::Tensor<D>,
563        axis: Option<i32>,
564        keep_dims: bool,
565    ) -> Self::Tensor<D>;
566
567    /*------------------------------ Scan / Sort Ops ------------------------------*/
568
569    /// Cumulative sum along `axis`.
570    fn cumsum<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
571
572    /// Cumulative product along `axis`.
573    fn cumprod<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
574
575    /// Sort along `dim`. `dim = None` sorts along the last dimension.
576    fn sort<D: ty::Num>(x: Self::Tensor<D>, dim: Option<i32>, descending: bool) -> Self::Tensor<D>;
577
578    /// Compute a histogram with `num_bins` bins (width 1, starting at 0).
579    ///
580    /// - `mask`: when `Some`, masked-off elements are excluded (default `None`).
581    fn histogram(
582        x: Self::I32Tensor,
583        num_bins: i32,
584        mask: Option<Self::BoolTensor>,
585    ) -> Self::I32Tensor;
586
587    /// Generic reduction along `axis` using a user-supplied combine function.
588    ///
589    /// `combine_fn` must be a statically-known function pointer (corresponds to a
590    /// `@triton.jit`-decorated helper in Python Triton).
591    fn reduce<D: ty::Dtype, O: ty::Dtype>(
592        x: Self::Tensor<D>,
593        axis: i32,
594        combine_fn: fn(Self::Tensor<O>, Self::Tensor<O>) -> Self::Tensor<O>,
595        keep_dims: bool,
596    ) -> Self::Tensor<O>;
597
598    /// Generic prefix-scan along `axis` using a user-supplied combine function.
599    ///
600    /// - `reverse`: scan in the reverse direction (default `false`).
601    fn associative_scan<D: ty::Dtype>(
602        x: Self::Tensor<D>,
603        axis: i32,
604        combine_fn: fn(Self::Tensor<D>, Self::Tensor<D>) -> Self::Tensor<D>,
605        reverse: bool,
606    ) -> Self::Tensor<D>;
607
608    /*------------------------------ Atomic Ops ------------------------------*/
609
610    /// Atomic add. Returns the previous value.
611    ///
612    /// - `mask`: when `Some`, only masked lanes perform the operation (default `None`).
613    /// - `sem`: memory ordering semantics (default `None` = AcqRel).
614    /// - `scope`: synchronization scope (default `None` = Gpu).
615    fn atomic_add<D: ty::Num>(
616        ptr: Self::Tensor<Self::Pointer<D>>,
617        val: Self::Tensor<D>,
618        mask: Option<Self::BoolTensor>,
619        sem: Option<MemSem>,
620        scope: Option<MemScope>,
621    ) -> Self::Tensor<D>;
622
623    /// Atomic bitwise AND. Returns the previous value. See [`Triton::atomic_add`] for parameters.
624    fn atomic_and<D: ty::Int>(
625        ptr: Self::Tensor<Self::Pointer<D>>,
626        val: Self::Tensor<D>,
627        mask: Option<Self::BoolTensor>,
628        sem: Option<MemSem>,
629        scope: Option<MemScope>,
630    ) -> Self::Tensor<D>;
631
632    /// Atomic bitwise OR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
633    fn atomic_or<D: ty::Int>(
634        ptr: Self::Tensor<Self::Pointer<D>>,
635        val: Self::Tensor<D>,
636        mask: Option<Self::BoolTensor>,
637        sem: Option<MemSem>,
638        scope: Option<MemScope>,
639    ) -> Self::Tensor<D>;
640
641    /// Atomic bitwise XOR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
642    fn atomic_xor<D: ty::Int>(
643        ptr: Self::Tensor<Self::Pointer<D>>,
644        val: Self::Tensor<D>,
645        mask: Option<Self::BoolTensor>,
646        sem: Option<MemSem>,
647        scope: Option<MemScope>,
648    ) -> Self::Tensor<D>;
649
650    /// Atomic maximum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
651    fn atomic_max<D: ty::Num>(
652        ptr: Self::Tensor<Self::Pointer<D>>,
653        val: Self::Tensor<D>,
654        mask: Option<Self::BoolTensor>,
655        sem: Option<MemSem>,
656        scope: Option<MemScope>,
657    ) -> Self::Tensor<D>;
658
659    /// Atomic minimum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
660    fn atomic_min<D: ty::Num>(
661        ptr: Self::Tensor<Self::Pointer<D>>,
662        val: Self::Tensor<D>,
663        mask: Option<Self::BoolTensor>,
664        sem: Option<MemSem>,
665        scope: Option<MemScope>,
666    ) -> Self::Tensor<D>;
667
668    /// Atomic exchange. Returns the previous value. See [`Triton::atomic_add`] for parameters.
669    fn atomic_xchg<D: ty::Dtype>(
670        ptr: Self::Tensor<Self::Pointer<D>>,
671        val: Self::Tensor<D>,
672        mask: Option<Self::BoolTensor>,
673        sem: Option<MemSem>,
674        scope: Option<MemScope>,
675    ) -> Self::Tensor<D>;
676
677    /// Atomic compare-and-swap. Returns the previous value.
678    fn atomic_cas<D: ty::Dtype>(
679        ptr: Self::Tensor<Self::Pointer<D>>,
680        cmp: Self::Tensor<D>,
681        val: Self::Tensor<D>,
682        sem: Option<MemSem>,
683        scope: Option<MemScope>,
684    ) -> Self::Tensor<D>;
685
686    /*------------------------------ Random Number Generation ------------------------------*/
687
688    /// Uniform random `f32` in `[0, 1)`.
689    ///
690    /// - `n_rounds`: number of Philox rounds (default `10`).
691    fn rand(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
692
693    /// Standard-normal random `f32`.
694    ///
695    /// - `n_rounds`: number of Philox rounds (default `10`).
696    fn randn(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
697
698    /// Random `i32`.
699    ///
700    /// - `n_rounds`: number of Philox rounds (default `10`).
701    fn randint(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::I32Tensor;
702
703    /// Four random `i32` streams (maximally efficient Philox entry point).
704    ///
705    /// - `n_rounds`: number of Philox rounds (default `10`).
706    fn randint4x(
707        seed: u32,
708        offsets: Self::I32Tensor,
709        n_rounds: i32,
710    ) -> (
711        Self::I32Tensor,
712        Self::I32Tensor,
713        Self::I32Tensor,
714        Self::I32Tensor,
715    );
716
717    /*------------------------------ Inline Assembly ------------------------------*/
718
719    /// Emit inline PTX/assembly applied element-wise across a tensor.
720    ///
721    /// - `asm`: the assembly template string.
722    /// - `constraints`: register constraint string.
723    /// - `is_pure`: whether the assembly has no side-effects (may be CSE'd).
724    /// - `pack`: number of elements packed into each register.
725    fn inline_asm_elementwise<D: ty::Dtype>(
726        asm: &str,
727        constraints: &str,
728        is_pure: bool,
729        pack: i32,
730    ) -> Self::Tensor<D>;
731
732    /*------------------------------ Compiler Hint Ops ------------------------------*/
733
734    /// Assert that `cond` is always true, allowing the compiler to assume so.
735    fn assume(cond: Self::BoolTensor);
736
737    /// Hint that values of `x` are always multiples of the given constants.
738    fn multiple_of<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
739
740    /// Hint that `x` has `values[i]` contiguous elements along dimension `i`.
741    fn max_contiguous<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
742
743    /// Hint that `x` has `values[i]` constant elements along dimension `i`.
744    fn max_constancy<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
745
746    /*------------------------------ Debug Ops ------------------------------*/
747
748    /// Insert a memory barrier for debugging purposes.
749    fn debug_barrier();
750
751    /// Emit a runtime assertion on the device. No-op when `cond` is `true`.
752    ///
753    /// - `msg`: message shown on assertion failure (default `""`).
754    /// - `mask`: when `Some`, only lanes where mask is `true` check the assertion.
755    fn device_assert(cond: Self::BoolTensor, msg: &str, mask: Option<Self::BoolTensor>);
756
757    /// Print a tensor value from device code for debugging.
758    ///
759    /// - `hex`: print values in hexadecimal (default `false`).
760    fn device_print<D: ty::Dtype>(prefix: &str, val: Self::Tensor<D>, hex: bool);
761
762    /// Compile-time assertion (evaluated before kernel launch).
763    fn static_assert(cond: bool, msg: &str);
764
765    /// Compile-time print (evaluated before kernel launch).
766    fn static_print(msg: &str);
767}