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` (default `None` = TF32 on capable hardware).
271    /// - `max_num_imprecise_acc`: limit on imprecise accumulations (default `None`).
272    fn dot<D: ty::Num, O: ty::Num>(
273        a: Self::Tensor<D>,
274        b: Self::Tensor<D>,
275        acc: Option<Self::Tensor<O>>,
276        input_precision: Option<InputPrecision>,
277        max_num_imprecise_acc: Option<i32>,
278    ) -> Self::Tensor<O>;
279
280    /// Scaled mixed-precision matrix multiply (FP8 / narrow formats).
281    ///
282    /// - `acc`: optional accumulator (default `None`).
283    /// - `fast_math`: allow reduced precision accumulation (default `false`).
284    fn dot_scaled<D: ty::Num, S: ty::Num, O: ty::Num>(
285        lhs: Self::Tensor<D>,
286        lhs_scale: Self::Tensor<S>,
287        lhs_format: DotFormat,
288        rhs: Self::Tensor<D>,
289        rhs_scale: Self::Tensor<S>,
290        rhs_format: DotFormat,
291        acc: Option<Self::Tensor<O>>,
292        fast_math: bool,
293    ) -> Self::Tensor<O>;
294
295    /*------------------------------ Memory / Pointer Ops ------------------------------*/
296
297    /// Create a block pointer encoding shape, strides, offsets, and tile shape.
298    fn make_block_ptr<D: ty::Dtype>(
299        base: Self::Pointer<D>,
300        shape: &[i32],
301        strides: &[i32],
302        offsets: &[i32],
303        block_shape: &[i32],
304        order: &[i32],
305    ) -> Self::Pointer<D>;
306
307    /// Advance a block pointer by the given per-dimension offsets.
308    fn advance<D: ty::Dtype>(ptr: Self::Pointer<D>, offsets: &[i32]) -> Self::Pointer<D>;
309
310    /// Create a tensor descriptor for TMA (Tensor Memory Accelerator) operations.
311    ///
312    /// - `padding_option`: out-of-bounds padding behaviour (default `PaddingOption::Zero`).
313    fn make_tensor_descriptor<D: ty::Dtype>(
314        base: Self::Pointer<D>,
315        shape: &[i32],
316        strides: &[i32],
317        block_shape: &[i32],
318        padding_option: Option<PaddingOption>,
319    ) -> Self::Pointer<D>;
320
321    /// Load a tile from memory using a tensor descriptor and per-dimension offsets.
322    fn load_tensor_descriptor<D: ty::Dtype>(
323        desc: Self::Pointer<D>,
324        offsets: &[i32],
325    ) -> Self::Tensor<D>;
326
327    /// Store a tile to memory using a tensor descriptor and per-dimension offsets.
328    fn store_tensor_descriptor<D: ty::Dtype>(
329        desc: Self::Pointer<D>,
330        offsets: &[i32],
331        value: Self::Tensor<D>,
332    );
333
334    /// Load a tensor from memory.
335    ///
336    /// - `mask`: when `Some`, lanes where mask is `false` are not loaded (default `None` = unconditional).
337    /// - `other`: fill value for masked-off lanes (default `None` = undefined).
338    /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
339    /// - `padding_option`: fill for out-of-bounds lanes in block-pointer mode (default `None`).
340    /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
341    /// - `eviction_policy`: eviction priority hint (default `None`).
342    /// - `volatile`: always fetch fresh from memory (default `false`).
343    fn load<D: ty::Dtype, const N: usize>(
344        ptr: Self::Tensor<Self::Pointer<D>>,
345        mask: Option<Self::BoolTensor>,
346        other: Option<Self::Tensor<D>>,
347        boundary_check: &[i32; N],
348        padding_option: Option<PaddingOption>,
349        cache_modifier: Option<CacheModifier>,
350        eviction_policy: Option<EvictionPolicy>,
351        volatile: bool,
352    ) -> Self::Tensor<D>;
353
354    /// Store a tensor to memory.
355    ///
356    /// - `mask`: when `Some`, lanes where mask is `false` are not stored (default `None` = unconditional).
357    /// - `boundary_check`: dimensions to check for out-of-bounds (block-pointer mode only, default `&[]`).
358    /// - `cache_modifier`: L1/L2 cache behaviour (default `None`).
359    /// - `eviction_policy`: eviction priority hint (default `None`).
360    fn store<D: ty::Dtype, const N: usize>(
361        dest: Self::Tensor<Self::Pointer<D>>,
362        src: Self::Tensor<D>,
363        mask: Option<Self::BoolTensor>,
364        boundary_check: &[i32; N],
365        cache_modifier: Option<CacheModifier>,
366        eviction_policy: Option<EvictionPolicy>,
367    );
368
369    /*------------------------------ Comparison Ops ------------------------------*/
370
371    /// Element-wise less-than between two tensors.
372    fn lt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
373    /// Element-wise less-than-or-equal between two tensors.
374    fn le<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
375    /// Element-wise greater-than between two tensors.
376    fn gt<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
377    /// Element-wise greater-than-or-equal between two tensors.
378    fn ge<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
379    /// Element-wise equality between two tensors.
380    fn eq<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
381    /// Element-wise inequality between two tensors.
382    fn ne<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::BoolTensor;
383
384    /// Element-wise less-than against a scalar.
385    fn lt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
386    /// Element-wise less-than-or-equal against a scalar.
387    fn le_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
388    /// Element-wise greater-than against a scalar.
389    fn gt_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
390    /// Element-wise greater-than-or-equal against a scalar.
391    fn ge_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
392    /// Element-wise equality against a scalar.
393    fn eq_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
394    /// Element-wise inequality against a scalar.
395    fn ne_scalar<D: ty::Num>(x: Self::Tensor<D>, y: D) -> Self::BoolTensor;
396
397    /*------------------------------ Indexing Ops ------------------------------*/
398
399    /// Conditional element selection — corresponds to `tl.where`.
400    /// Named `where_` to avoid collision with the Rust keyword `where`.
401    fn where_<D: ty::Dtype>(
402        cond: Self::BoolTensor,
403        x: Self::Tensor<D>,
404        y: Self::Tensor<D>,
405    ) -> Self::Tensor<D>;
406
407    /// Reverse a tensor along `dim`. `None` reverses all dimensions.
408    fn flip<D: ty::Dtype>(x: Self::Tensor<D>, dim: Option<i32>) -> Self::Tensor<D>;
409
410    /// Gather elements from `src` along `axis` using `index`.
411    fn gather<D: ty::Dtype>(
412        src: Self::Tensor<D>,
413        index: Self::I32Tensor,
414        axis: i32,
415    ) -> Self::Tensor<D>;
416
417    /*------------------------------ Math Ops — Unary ------------------------------*/
418
419    /// Element-wise absolute value.
420    fn abs<D: ty::Dtype>(x: Self::Tensor<D>) -> Self::Tensor<D>;
421    /// Element-wise ceiling.
422    fn ceil<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
423    /// Element-wise floor.
424    fn floor<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
425    /// Element-wise cosine.
426    fn cos<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
427    /// Element-wise sine.
428    fn sin<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
429    /// Element-wise natural exponential (`e^x`).
430    fn exp<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
431    /// Element-wise base-2 exponential (`2^x`).
432    fn exp2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
433    /// Element-wise natural logarithm.
434    fn log<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
435    /// Element-wise base-2 logarithm.
436    fn log2<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
437    /// Element-wise reciprocal square root (`1/sqrt(x)`).
438    fn rsqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
439    /// Element-wise sigmoid (`1/(1+e^-x)`).
440    fn sigmoid<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
441    /// Element-wise square root.
442    fn sqrt<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
443    /// Element-wise square root, round-to-nearest.
444    fn sqrt_rn<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
445    /// Element-wise error function.
446    fn erf<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
447    /// Element-wise arctangent.
448    fn atan<D: ty::Float>(x: Self::Tensor<D>) -> Self::Tensor<D>;
449
450    /*------------------------------ Math Ops — Float (higher-level) ------------------------------*/
451
452    /// Numerically-stable softmax along `dim`. `dim = None` defaults to the last dimension.
453    ///
454    /// - `keep_dims`: retain the reduced dimension with length 1 (default `false`).
455    /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
456    fn softmax<D: ty::Float>(
457        x: Self::Tensor<D>,
458        dim: Option<i32>,
459        keep_dims: bool,
460        ieee_rounding: bool,
461    ) -> Self::Tensor<D>;
462
463    /*------------------------------ Math Ops — Binary ------------------------------*/
464
465    /// Element-wise maximum of two tensors.
466    fn maximum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
467    /// Element-wise minimum of two tensors.
468    fn minimum<D: ty::Num>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
469
470    /// Element-wise clamp of `x` to `[lo, hi]`.
471    fn clamp<D: ty::Num>(
472        x: Self::Tensor<D>,
473        lo: Self::Tensor<D>,
474        hi: Self::Tensor<D>,
475    ) -> Self::Tensor<D>;
476
477    /// Element-wise fused multiply-add: `x * y + z`.
478    fn fma<D: ty::Float>(
479        x: Self::Tensor<D>,
480        y: Self::Tensor<D>,
481        z: Self::Tensor<D>,
482    ) -> Self::Tensor<D>;
483
484    /// Element-wise floating-point division.
485    ///
486    /// - `ieee_rounding`: use IEEE-754 rounding (default `false`).
487    fn fdiv<D: ty::Float>(
488        x: Self::Tensor<D>,
489        y: Self::Tensor<D>,
490        ieee_rounding: bool,
491    ) -> Self::Tensor<D>;
492
493    /// Element-wise division, round-to-nearest.
494    fn div_rn<D: ty::Float>(x: Self::Tensor<D>, y: Self::Tensor<D>) -> Self::Tensor<D>;
495
496    /// Element-wise high 32 bits of an unsigned 32×32→64-bit multiply.
497    fn umulhi(x: Self::Tensor<u32>, y: Self::Tensor<u32>) -> Self::Tensor<u32>;
498
499    /// Ceiling integer division: `ceil(x / div)`.
500    fn cdiv(x: i32, div: i32) -> i32;
501
502    /// Swizzle 2-D indices for shared-memory bank-conflict avoidance.
503    /// Returns the remapped `(i, j)` indices.
504    fn swizzle2d(i: i32, j: i32, size_i: i32, size_j: i32, size_g: i32) -> (i32, i32);
505
506    /*------------------------------ Reduction Ops ------------------------------*/
507
508    /// Sum all elements along `axis`. `axis = None` reduces all dimensions.
509    fn sum<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
510
511    /// Maximum along `axis`. `axis = None` reduces all dimensions.
512    fn max<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
513
514    /// Maximum along `axis`, also returning the index of the maximum.
515    ///
516    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
517    fn max_with_indices<D: ty::Num>(
518        x: Self::Tensor<D>,
519        axis: i32,
520        tie_break_left: bool,
521        keep_dims: bool,
522    ) -> (Self::Tensor<D>, Self::I32Tensor);
523
524    /// Minimum along `axis`. `axis = None` reduces all dimensions.
525    fn min<D: ty::Num>(x: Self::Tensor<D>, axis: Option<i32>, keep_dims: bool) -> Self::Tensor<D>;
526
527    /// Minimum along `axis`, also returning the index of the minimum.
528    ///
529    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
530    fn min_with_indices<D: ty::Num>(
531        x: Self::Tensor<D>,
532        axis: i32,
533        tie_break_left: bool,
534        keep_dims: bool,
535    ) -> (Self::Tensor<D>, Self::I32Tensor);
536
537    /// Index of the maximum along `axis`.
538    ///
539    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
540    fn argmax<D: ty::Num>(
541        x: Self::Tensor<D>,
542        axis: i32,
543        tie_break_left: bool,
544        keep_dims: bool,
545    ) -> Self::I32Tensor;
546
547    /// Index of the minimum along `axis`.
548    ///
549    /// - `tie_break_left`: when `true`, the leftmost index wins on ties (default `true`).
550    fn argmin<D: ty::Num>(
551        x: Self::Tensor<D>,
552        axis: i32,
553        tie_break_left: bool,
554        keep_dims: bool,
555    ) -> Self::I32Tensor;
556
557    /// XOR-reduction along `axis`. `axis = None` reduces all dimensions.
558    fn xor_sum<D: ty::Int>(
559        x: Self::Tensor<D>,
560        axis: Option<i32>,
561        keep_dims: bool,
562    ) -> Self::Tensor<D>;
563
564    /*------------------------------ Scan / Sort Ops ------------------------------*/
565
566    /// Cumulative sum along `axis`.
567    fn cumsum<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
568
569    /// Cumulative product along `axis`.
570    fn cumprod<D: ty::Num>(x: Self::Tensor<D>, axis: i32, reverse: bool) -> Self::Tensor<D>;
571
572    /// Sort along `dim`. `dim = None` sorts along the last dimension.
573    fn sort<D: ty::Num>(x: Self::Tensor<D>, dim: Option<i32>, descending: bool) -> Self::Tensor<D>;
574
575    /// Compute a histogram with `num_bins` bins (width 1, starting at 0).
576    ///
577    /// - `mask`: when `Some`, masked-off elements are excluded (default `None`).
578    fn histogram(
579        x: Self::I32Tensor,
580        num_bins: i32,
581        mask: Option<Self::BoolTensor>,
582    ) -> Self::I32Tensor;
583
584    /// Generic reduction along `axis` using a user-supplied combine function.
585    ///
586    /// `combine_fn` must be a statically-known function pointer (corresponds to a
587    /// `@triton.jit`-decorated helper in Python Triton).
588    fn reduce<D: ty::Dtype, O: ty::Dtype>(
589        x: Self::Tensor<D>,
590        axis: i32,
591        combine_fn: fn(Self::Tensor<O>, Self::Tensor<O>) -> Self::Tensor<O>,
592        keep_dims: bool,
593    ) -> Self::Tensor<O>;
594
595    /// Generic prefix-scan along `axis` using a user-supplied combine function.
596    ///
597    /// - `reverse`: scan in the reverse direction (default `false`).
598    fn associative_scan<D: ty::Dtype>(
599        x: Self::Tensor<D>,
600        axis: i32,
601        combine_fn: fn(Self::Tensor<D>, Self::Tensor<D>) -> Self::Tensor<D>,
602        reverse: bool,
603    ) -> Self::Tensor<D>;
604
605    /*------------------------------ Atomic Ops ------------------------------*/
606
607    /// Atomic add. Returns the previous value.
608    ///
609    /// - `mask`: when `Some`, only masked lanes perform the operation (default `None`).
610    /// - `sem`: memory ordering semantics (default `None` = AcqRel).
611    /// - `scope`: synchronization scope (default `None` = Gpu).
612    fn atomic_add<D: ty::Num>(
613        ptr: Self::Tensor<Self::Pointer<D>>,
614        val: Self::Tensor<D>,
615        mask: Option<Self::BoolTensor>,
616        sem: Option<MemSem>,
617        scope: Option<MemScope>,
618    ) -> Self::Tensor<D>;
619
620    /// Atomic bitwise AND. Returns the previous value. See [`Triton::atomic_add`] for parameters.
621    fn atomic_and<D: ty::Int>(
622        ptr: Self::Tensor<Self::Pointer<D>>,
623        val: Self::Tensor<D>,
624        mask: Option<Self::BoolTensor>,
625        sem: Option<MemSem>,
626        scope: Option<MemScope>,
627    ) -> Self::Tensor<D>;
628
629    /// Atomic bitwise OR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
630    fn atomic_or<D: ty::Int>(
631        ptr: Self::Tensor<Self::Pointer<D>>,
632        val: Self::Tensor<D>,
633        mask: Option<Self::BoolTensor>,
634        sem: Option<MemSem>,
635        scope: Option<MemScope>,
636    ) -> Self::Tensor<D>;
637
638    /// Atomic bitwise XOR. Returns the previous value. See [`Triton::atomic_add`] for parameters.
639    fn atomic_xor<D: ty::Int>(
640        ptr: Self::Tensor<Self::Pointer<D>>,
641        val: Self::Tensor<D>,
642        mask: Option<Self::BoolTensor>,
643        sem: Option<MemSem>,
644        scope: Option<MemScope>,
645    ) -> Self::Tensor<D>;
646
647    /// Atomic maximum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
648    fn atomic_max<D: ty::Num>(
649        ptr: Self::Tensor<Self::Pointer<D>>,
650        val: Self::Tensor<D>,
651        mask: Option<Self::BoolTensor>,
652        sem: Option<MemSem>,
653        scope: Option<MemScope>,
654    ) -> Self::Tensor<D>;
655
656    /// Atomic minimum. Returns the previous value. See [`Triton::atomic_add`] for parameters.
657    fn atomic_min<D: ty::Num>(
658        ptr: Self::Tensor<Self::Pointer<D>>,
659        val: Self::Tensor<D>,
660        mask: Option<Self::BoolTensor>,
661        sem: Option<MemSem>,
662        scope: Option<MemScope>,
663    ) -> Self::Tensor<D>;
664
665    /// Atomic exchange. Returns the previous value. See [`Triton::atomic_add`] for parameters.
666    fn atomic_xchg<D: ty::Dtype>(
667        ptr: Self::Tensor<Self::Pointer<D>>,
668        val: Self::Tensor<D>,
669        mask: Option<Self::BoolTensor>,
670        sem: Option<MemSem>,
671        scope: Option<MemScope>,
672    ) -> Self::Tensor<D>;
673
674    /// Atomic compare-and-swap. Returns the previous value.
675    fn atomic_cas<D: ty::Dtype>(
676        ptr: Self::Tensor<Self::Pointer<D>>,
677        cmp: Self::Tensor<D>,
678        val: Self::Tensor<D>,
679        sem: Option<MemSem>,
680        scope: Option<MemScope>,
681    ) -> Self::Tensor<D>;
682
683    /*------------------------------ Random Number Generation ------------------------------*/
684
685    /// Uniform random `f32` in `[0, 1)`.
686    ///
687    /// - `n_rounds`: number of Philox rounds (default `10`).
688    fn rand(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
689
690    /// Standard-normal random `f32`.
691    ///
692    /// - `n_rounds`: number of Philox rounds (default `10`).
693    fn randn(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::Tensor<f32>;
694
695    /// Random `i32`.
696    ///
697    /// - `n_rounds`: number of Philox rounds (default `10`).
698    fn randint(seed: u32, offsets: Self::I32Tensor, n_rounds: i32) -> Self::I32Tensor;
699
700    /// Four random `i32` streams (maximally efficient Philox entry point).
701    ///
702    /// - `n_rounds`: number of Philox rounds (default `10`).
703    fn randint4x(
704        seed: u32,
705        offsets: Self::I32Tensor,
706        n_rounds: i32,
707    ) -> (
708        Self::I32Tensor,
709        Self::I32Tensor,
710        Self::I32Tensor,
711        Self::I32Tensor,
712    );
713
714    /*------------------------------ Inline Assembly ------------------------------*/
715
716    /// Emit inline PTX/assembly applied element-wise across a tensor.
717    ///
718    /// - `asm`: the assembly template string.
719    /// - `constraints`: register constraint string.
720    /// - `is_pure`: whether the assembly has no side-effects (may be CSE'd).
721    /// - `pack`: number of elements packed into each register.
722    fn inline_asm_elementwise<D: ty::Dtype>(
723        asm: &str,
724        constraints: &str,
725        is_pure: bool,
726        pack: i32,
727    ) -> Self::Tensor<D>;
728
729    /*------------------------------ Compiler Hint Ops ------------------------------*/
730
731    /// Assert that `cond` is always true, allowing the compiler to assume so.
732    fn assume(cond: Self::BoolTensor);
733
734    /// Hint that values of `x` are always multiples of the given constants.
735    fn multiple_of<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
736
737    /// Hint that `x` has `values[i]` contiguous elements along dimension `i`.
738    fn max_contiguous<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
739
740    /// Hint that `x` has `values[i]` constant elements along dimension `i`.
741    fn max_constancy<D: ty::Dtype>(x: Self::Tensor<D>, values: &[i32]) -> Self::Tensor<D>;
742
743    /*------------------------------ Debug Ops ------------------------------*/
744
745    /// Insert a memory barrier for debugging purposes.
746    fn debug_barrier();
747
748    /// Emit a runtime assertion on the device. No-op when `cond` is `true`.
749    ///
750    /// - `msg`: message shown on assertion failure (default `""`).
751    /// - `mask`: when `Some`, only lanes where mask is `true` check the assertion.
752    fn device_assert(cond: Self::BoolTensor, msg: &str, mask: Option<Self::BoolTensor>);
753
754    /// Print a tensor value from device code for debugging.
755    ///
756    /// - `hex`: print values in hexadecimal (default `false`).
757    fn device_print<D: ty::Dtype>(prefix: &str, val: Self::Tensor<D>, hex: bool);
758
759    /// Compile-time assertion (evaluated before kernel launch).
760    fn static_assert(cond: bool, msg: &str);
761
762    /// Compile-time print (evaluated before kernel launch).
763    fn static_print(msg: &str);
764}