Skip to main content

singe_cutensor_sys/
sys_20600.rs

1/* automatically generated by rust-bindgen 0.72.1 */
2
3#[repr(C)]
4#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
5pub struct __BindgenBitfieldUnit<Storage> {
6    storage: Storage,
7}
8impl<Storage> __BindgenBitfieldUnit<Storage> {
9    #[inline]
10    pub const fn new(storage: Storage) -> Self {
11        Self { storage }
12    }
13}
14impl<Storage> __BindgenBitfieldUnit<Storage>
15where
16    Storage: AsRef<[u8]> + AsMut<[u8]>,
17{
18    #[inline]
19    fn extract_bit(byte: u8, index: usize) -> bool {
20        let bit_index = if cfg!(target_endian = "big") {
21            7 - (index % 8)
22        } else {
23            index % 8
24        };
25        let mask = 1 << bit_index;
26        byte & mask == mask
27    }
28    #[inline]
29    pub fn get_bit(&self, index: usize) -> bool {
30        debug_assert!(index / 8 < self.storage.as_ref().len());
31        let byte_index = index / 8;
32        let byte = self.storage.as_ref()[byte_index];
33        Self::extract_bit(byte, index)
34    }
35    #[inline]
36    pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool {
37        debug_assert!(index / 8 < core::mem::size_of::< Storage > ());
38        let byte_index = index / 8;
39        let byte = unsafe {
40            *(core::ptr::addr_of!((* this).storage) as *const u8)
41                .offset(byte_index as isize)
42        };
43        Self::extract_bit(byte, index)
44    }
45    #[inline]
46    fn change_bit(byte: u8, index: usize, val: bool) -> u8 {
47        let bit_index = if cfg!(target_endian = "big") {
48            7 - (index % 8)
49        } else {
50            index % 8
51        };
52        let mask = 1 << bit_index;
53        if val { byte | mask } else { byte & !mask }
54    }
55    #[inline]
56    pub fn set_bit(&mut self, index: usize, val: bool) {
57        debug_assert!(index / 8 < self.storage.as_ref().len());
58        let byte_index = index / 8;
59        let byte = &mut self.storage.as_mut()[byte_index];
60        *byte = Self::change_bit(*byte, index, val);
61    }
62    #[inline]
63    pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) {
64        debug_assert!(index / 8 < core::mem::size_of::< Storage > ());
65        let byte_index = index / 8;
66        let byte = unsafe {
67            (core::ptr::addr_of_mut!((* this).storage) as *mut u8)
68                .offset(byte_index as isize)
69        };
70        unsafe { *byte = Self::change_bit(*byte, index, val) };
71    }
72    #[inline]
73    pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
74        debug_assert!(bit_width <= 64);
75        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
76        debug_assert!(
77            (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()
78        );
79        let mut val = 0;
80        for i in 0..(bit_width as usize) {
81            if self.get_bit(i + bit_offset) {
82                let index = if cfg!(target_endian = "big") {
83                    bit_width as usize - 1 - i
84                } else {
85                    i
86                };
87                val |= 1 << index;
88            }
89        }
90        val
91    }
92    #[inline]
93    pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 {
94        debug_assert!(bit_width <= 64);
95        debug_assert!(bit_offset / 8 < core::mem::size_of::< Storage > ());
96        debug_assert!(
97            (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::< Storage > ()
98        );
99        let mut val = 0;
100        for i in 0..(bit_width as usize) {
101            if unsafe { Self::raw_get_bit(this, i + bit_offset) } {
102                let index = if cfg!(target_endian = "big") {
103                    bit_width as usize - 1 - i
104                } else {
105                    i
106                };
107                val |= 1 << index;
108            }
109        }
110        val
111    }
112    #[inline]
113    pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
114        debug_assert!(bit_width <= 64);
115        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
116        debug_assert!(
117            (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()
118        );
119        for i in 0..(bit_width as usize) {
120            let mask = 1 << i;
121            let val_bit_is_set = val & mask == mask;
122            let index = if cfg!(target_endian = "big") {
123                bit_width as usize - 1 - i
124            } else {
125                i
126            };
127            self.set_bit(index + bit_offset, val_bit_is_set);
128        }
129    }
130    #[inline]
131    pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) {
132        debug_assert!(bit_width <= 64);
133        debug_assert!(bit_offset / 8 < core::mem::size_of::< Storage > ());
134        debug_assert!(
135            (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::< Storage > ()
136        );
137        for i in 0..(bit_width as usize) {
138            let mask = 1 << i;
139            let val_bit_is_set = val & mask == mask;
140            let index = if cfg!(target_endian = "big") {
141                bit_width as usize - 1 - i
142            } else {
143                i
144            };
145            unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) };
146        }
147    }
148}
149pub const CUTENSOR_MAJOR: u32 = 2;
150pub const CUTENSOR_MINOR: u32 = 6;
151pub const CUTENSOR_PATCH: u32 = 0;
152pub const CUTENSOR_VERSION: u32 = 20600;
153pub type __uint64_t = ::core::ffi::c_ulong;
154pub type __off_t = ::core::ffi::c_long;
155pub type __off64_t = ::core::ffi::c_long;
156pub type size_t = ::core::ffi::c_ulong;
157pub type FILE = _IO_FILE;
158#[repr(C)]
159#[derive(Debug, Copy, Clone)]
160pub struct _IO_marker {
161    _unused: [u8; 0],
162}
163#[repr(C)]
164#[derive(Debug, Copy, Clone)]
165pub struct _IO_codecvt {
166    _unused: [u8; 0],
167}
168#[repr(C)]
169#[derive(Debug, Copy, Clone)]
170pub struct _IO_wide_data {
171    _unused: [u8; 0],
172}
173pub type _IO_lock_t = ::core::ffi::c_void;
174#[repr(C)]
175#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
176pub struct _IO_FILE {
177    pub _flags: ::core::ffi::c_int,
178    pub _IO_read_ptr: *mut ::core::ffi::c_char,
179    pub _IO_read_end: *mut ::core::ffi::c_char,
180    pub _IO_read_base: *mut ::core::ffi::c_char,
181    pub _IO_write_base: *mut ::core::ffi::c_char,
182    pub _IO_write_ptr: *mut ::core::ffi::c_char,
183    pub _IO_write_end: *mut ::core::ffi::c_char,
184    pub _IO_buf_base: *mut ::core::ffi::c_char,
185    pub _IO_buf_end: *mut ::core::ffi::c_char,
186    pub _IO_save_base: *mut ::core::ffi::c_char,
187    pub _IO_backup_base: *mut ::core::ffi::c_char,
188    pub _IO_save_end: *mut ::core::ffi::c_char,
189    pub _markers: *mut _IO_marker,
190    pub _chain: *mut _IO_FILE,
191    pub _fileno: ::core::ffi::c_int,
192    pub _bitfield_align_1: [u32; 0],
193    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>,
194    pub _short_backupbuf: [::core::ffi::c_char; 1usize],
195    pub _old_offset: __off_t,
196    pub _cur_column: ::core::ffi::c_ushort,
197    pub _vtable_offset: ::core::ffi::c_schar,
198    pub _shortbuf: [::core::ffi::c_char; 1usize],
199    pub _lock: *mut _IO_lock_t,
200    pub _offset: __off64_t,
201    pub _codecvt: *mut _IO_codecvt,
202    pub _wide_data: *mut _IO_wide_data,
203    pub _freeres_list: *mut _IO_FILE,
204    pub _freeres_buf: *mut ::core::ffi::c_void,
205    pub _prevchain: *mut *mut _IO_FILE,
206    pub _mode: ::core::ffi::c_int,
207    pub _unused3: ::core::ffi::c_int,
208    pub _total_written: __uint64_t,
209    pub _unused2: [::core::ffi::c_char; 8usize],
210}
211impl Default for _IO_FILE {
212    fn default() -> Self {
213        let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
214        unsafe {
215            ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
216            s.assume_init()
217        }
218    }
219}
220impl _IO_FILE {
221    #[inline]
222    pub fn _flags2(&self) -> ::core::ffi::c_int {
223        unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) }
224    }
225    #[inline]
226    pub fn set__flags2(&mut self, val: ::core::ffi::c_int) {
227        unsafe {
228            let val: u32 = ::core::mem::transmute(val);
229            self._bitfield_1.set(0usize, 24u8, val as u64)
230        }
231    }
232    #[inline]
233    pub unsafe fn _flags2_raw(this: *const Self) -> ::core::ffi::c_int {
234        unsafe {
235            ::core::mem::transmute(
236                <__BindgenBitfieldUnit<
237                    [u8; 3usize],
238                >>::raw_get(::core::ptr::addr_of!((* this)._bitfield_1), 0usize, 24u8)
239                    as u32,
240            )
241        }
242    }
243    #[inline]
244    pub unsafe fn set__flags2_raw(this: *mut Self, val: ::core::ffi::c_int) {
245        unsafe {
246            let val: u32 = ::core::mem::transmute(val);
247            <__BindgenBitfieldUnit<
248                [u8; 3usize],
249            >>::raw_set(
250                ::core::ptr::addr_of_mut!((* this)._bitfield_1),
251                0usize,
252                24u8,
253                val as u64,
254            )
255        }
256    }
257    #[inline]
258    pub fn new_bitfield_1(
259        _flags2: ::core::ffi::c_int,
260    ) -> __BindgenBitfieldUnit<[u8; 3usize]> {
261        let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default();
262        __bindgen_bitfield_unit
263            .set(
264                0usize,
265                24u8,
266                {
267                    let _flags2: u32 = unsafe { ::core::mem::transmute(_flags2) };
268                    _flags2 as u64
269                },
270            );
271        __bindgen_bitfield_unit
272    }
273}
274#[repr(C)]
275#[derive(Debug, Copy, Clone)]
276pub struct CUstream_st {
277    _unused: [u8; 0],
278}
279pub use self::cudaDataType_t as cutensorDataType_t;
280unsafe extern "C" {
281    #[link_name = "\u{1}_ZL14CUTENSOR_R_16F"]
282    pub static CUTENSOR_R_16F: cutensorDataType_t;
283}
284unsafe extern "C" {
285    #[link_name = "\u{1}_ZL14CUTENSOR_C_16F"]
286    pub static CUTENSOR_C_16F: cutensorDataType_t;
287}
288unsafe extern "C" {
289    #[link_name = "\u{1}_ZL15CUTENSOR_R_16BF"]
290    pub static CUTENSOR_R_16BF: cutensorDataType_t;
291}
292unsafe extern "C" {
293    #[link_name = "\u{1}_ZL15CUTENSOR_C_16BF"]
294    pub static CUTENSOR_C_16BF: cutensorDataType_t;
295}
296unsafe extern "C" {
297    #[link_name = "\u{1}_ZL14CUTENSOR_R_32F"]
298    pub static CUTENSOR_R_32F: cutensorDataType_t;
299}
300unsafe extern "C" {
301    #[link_name = "\u{1}_ZL14CUTENSOR_C_32F"]
302    pub static CUTENSOR_C_32F: cutensorDataType_t;
303}
304unsafe extern "C" {
305    #[link_name = "\u{1}_ZL14CUTENSOR_R_64F"]
306    pub static CUTENSOR_R_64F: cutensorDataType_t;
307}
308unsafe extern "C" {
309    #[link_name = "\u{1}_ZL14CUTENSOR_C_64F"]
310    pub static CUTENSOR_C_64F: cutensorDataType_t;
311}
312unsafe extern "C" {
313    #[link_name = "\u{1}_ZL13CUTENSOR_R_4I"]
314    pub static CUTENSOR_R_4I: cutensorDataType_t;
315}
316unsafe extern "C" {
317    #[link_name = "\u{1}_ZL13CUTENSOR_C_4I"]
318    pub static CUTENSOR_C_4I: cutensorDataType_t;
319}
320unsafe extern "C" {
321    #[link_name = "\u{1}_ZL13CUTENSOR_R_4U"]
322    pub static CUTENSOR_R_4U: cutensorDataType_t;
323}
324unsafe extern "C" {
325    #[link_name = "\u{1}_ZL13CUTENSOR_C_4U"]
326    pub static CUTENSOR_C_4U: cutensorDataType_t;
327}
328unsafe extern "C" {
329    #[link_name = "\u{1}_ZL13CUTENSOR_R_8I"]
330    pub static CUTENSOR_R_8I: cutensorDataType_t;
331}
332unsafe extern "C" {
333    #[link_name = "\u{1}_ZL13CUTENSOR_C_8I"]
334    pub static CUTENSOR_C_8I: cutensorDataType_t;
335}
336unsafe extern "C" {
337    #[link_name = "\u{1}_ZL13CUTENSOR_R_8U"]
338    pub static CUTENSOR_R_8U: cutensorDataType_t;
339}
340unsafe extern "C" {
341    #[link_name = "\u{1}_ZL13CUTENSOR_C_8U"]
342    pub static CUTENSOR_C_8U: cutensorDataType_t;
343}
344unsafe extern "C" {
345    #[link_name = "\u{1}_ZL14CUTENSOR_R_16I"]
346    pub static CUTENSOR_R_16I: cutensorDataType_t;
347}
348unsafe extern "C" {
349    #[link_name = "\u{1}_ZL14CUTENSOR_C_16I"]
350    pub static CUTENSOR_C_16I: cutensorDataType_t;
351}
352unsafe extern "C" {
353    #[link_name = "\u{1}_ZL14CUTENSOR_R_16U"]
354    pub static CUTENSOR_R_16U: cutensorDataType_t;
355}
356unsafe extern "C" {
357    #[link_name = "\u{1}_ZL14CUTENSOR_C_16U"]
358    pub static CUTENSOR_C_16U: cutensorDataType_t;
359}
360unsafe extern "C" {
361    #[link_name = "\u{1}_ZL14CUTENSOR_R_32I"]
362    pub static CUTENSOR_R_32I: cutensorDataType_t;
363}
364unsafe extern "C" {
365    #[link_name = "\u{1}_ZL14CUTENSOR_C_32I"]
366    pub static CUTENSOR_C_32I: cutensorDataType_t;
367}
368unsafe extern "C" {
369    #[link_name = "\u{1}_ZL14CUTENSOR_R_32U"]
370    pub static CUTENSOR_R_32U: cutensorDataType_t;
371}
372unsafe extern "C" {
373    #[link_name = "\u{1}_ZL14CUTENSOR_C_32U"]
374    pub static CUTENSOR_C_32U: cutensorDataType_t;
375}
376unsafe extern "C" {
377    #[link_name = "\u{1}_ZL14CUTENSOR_R_64I"]
378    pub static CUTENSOR_R_64I: cutensorDataType_t;
379}
380unsafe extern "C" {
381    #[link_name = "\u{1}_ZL14CUTENSOR_C_64I"]
382    pub static CUTENSOR_C_64I: cutensorDataType_t;
383}
384unsafe extern "C" {
385    #[link_name = "\u{1}_ZL14CUTENSOR_R_64U"]
386    pub static CUTENSOR_R_64U: cutensorDataType_t;
387}
388unsafe extern "C" {
389    #[link_name = "\u{1}_ZL14CUTENSOR_C_64U"]
390    pub static CUTENSOR_C_64U: cutensorDataType_t;
391}
392/// This enum captures all unary and binary element-wise operations supported by the cuTENSOR library.
393#[repr(u32)]
394#[derive(
395    Debug,
396    Copy,
397    Clone,
398    Hash,
399    PartialOrd,
400    Ord,
401    PartialEq,
402    Eq,
403    TryFromPrimitive,
404    IntoPrimitive,
405)]
406pub enum cutensorOperator_t {
407    /// Identity operator (i.e., elements are not changed).
408    CUTENSOR_OP_IDENTITY = 1,
409    /// Square root.
410    CUTENSOR_OP_SQRT = 2,
411    /// Rectified linear unit.
412    CUTENSOR_OP_RELU = 8,
413    /// Complex conjugate.
414    CUTENSOR_OP_CONJ = 9,
415    /// Reciprocal.
416    CUTENSOR_OP_RCP = 10,
417    /// y=1/(1+exp(-x)).
418    CUTENSOR_OP_SIGMOID = 11,
419    /// y=tanh(x).
420    CUTENSOR_OP_TANH = 12,
421    /// Exponentiation.
422    CUTENSOR_OP_EXP = 22,
423    /// Log (base e).
424    CUTENSOR_OP_LOG = 23,
425    /// Absolute value.
426    CUTENSOR_OP_ABS = 24,
427    /// Negation.
428    CUTENSOR_OP_NEG = 25,
429    /// Sine.
430    CUTENSOR_OP_SIN = 26,
431    /// Cosine.
432    CUTENSOR_OP_COS = 27,
433    /// Tangent.
434    CUTENSOR_OP_TAN = 28,
435    /// Hyperbolic sine.
436    CUTENSOR_OP_SINH = 29,
437    /// Hyperbolic cosine.
438    CUTENSOR_OP_COSH = 30,
439    /// Inverse sine.
440    CUTENSOR_OP_ASIN = 31,
441    /// Inverse cosine.
442    CUTENSOR_OP_ACOS = 32,
443    /// Inverse tangent.
444    CUTENSOR_OP_ATAN = 33,
445    /// Inverse hyperbolic sine.
446    CUTENSOR_OP_ASINH = 34,
447    /// Inverse hyperbolic cosine.
448    CUTENSOR_OP_ACOSH = 35,
449    /// Inverse hyperbolic tangent.
450    CUTENSOR_OP_ATANH = 36,
451    /// Ceiling.
452    CUTENSOR_OP_CEIL = 37,
453    /// Floor.
454    CUTENSOR_OP_FLOOR = 38,
455    /// Mish y=x\*tanh(softplus(x)).
456    CUTENSOR_OP_MISH = 39,
457    /// Swish y=x\*sigmoid(x).
458    CUTENSOR_OP_SWISH = 40,
459    /// Softplus y=log(exp(x)+1).
460    CUTENSOR_OP_SOFT_PLUS = 41,
461    /// Softsign y=x/(abs(x)+1).
462    CUTENSOR_OP_SOFT_SIGN = 42,
463    /// Addition of two elements.
464    CUTENSOR_OP_ADD = 3,
465    /// Multiplication of two elements.
466    CUTENSOR_OP_MUL = 5,
467    /// Maximum of two elements.
468    CUTENSOR_OP_MAX = 6,
469    /// Minimum of two elements.
470    CUTENSOR_OP_MIN = 7,
471    /// reserved for internal use only.
472    CUTENSOR_OP_UNKNOWN = 126,
473}
474/// cuTENSOR status type returns
475///
476/// The type is used for function status returns. All cuTENSOR library functions return their status, which can have the following values.
477#[repr(u32)]
478#[derive(
479    Debug,
480    Copy,
481    Clone,
482    Hash,
483    PartialOrd,
484    Ord,
485    PartialEq,
486    Eq,
487    TryFromPrimitive,
488    IntoPrimitive,
489)]
490pub enum cutensorStatus_t {
491    /// The operation completed successfully.
492    CUTENSOR_STATUS_SUCCESS = 0,
493    /// The opaque data structure was not initialized.
494    CUTENSOR_STATUS_NOT_INITIALIZED = 1,
495    /// Resource allocation failed inside the cuTENSOR library.
496    CUTENSOR_STATUS_ALLOC_FAILED = 3,
497    /// An unsupported value or parameter was passed to the function (indicates an user error).
498    CUTENSOR_STATUS_INVALID_VALUE = 7,
499    /// Indicates that the device is either not ready, or the target architecture is not supported.
500    CUTENSOR_STATUS_ARCH_MISMATCH = 8,
501    /// An access to GPU memory space failed, which is usually caused by a failure to bind a texture.
502    CUTENSOR_STATUS_MAPPING_ERROR = 11,
503    /// The GPU program failed to execute. This is often caused by a launch failure of the kernel on the GPU, which can be caused by multiple reasons.
504    CUTENSOR_STATUS_EXECUTION_FAILED = 13,
505    /// An internal cuTENSOR error has occurred.
506    CUTENSOR_STATUS_INTERNAL_ERROR = 14,
507    /// The requested operation is not supported.
508    CUTENSOR_STATUS_NOT_SUPPORTED = 15,
509    /// The functionality requested requires some license and an error was detected when trying to check the current licensing.
510    CUTENSOR_STATUS_LICENSE_ERROR = 16,
511    /// A call to CUBLAS did not succeed.
512    CUTENSOR_STATUS_CUBLAS_ERROR = 17,
513    /// Some unknown CUDA error has occurred.
514    CUTENSOR_STATUS_CUDA_ERROR = 18,
515    /// The provided workspace was insufficient.
516    CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE = 19,
517    /// Indicates that the driver version is insufficient.
518    CUTENSOR_STATUS_INSUFFICIENT_DRIVER = 20,
519    /// Indicates an error related to file I/O.
520    CUTENSOR_STATUS_IO_ERROR = 21,
521}
522/// Allows users to specify the algorithm to be used for performing the desired tensor operation.
523#[repr(i32)]
524#[derive(
525    Debug,
526    Copy,
527    Clone,
528    Hash,
529    PartialOrd,
530    Ord,
531    PartialEq,
532    Eq,
533    TryFromPrimitive,
534    IntoPrimitive,
535)]
536pub enum cutensorAlgo_t {
537    /// More time-consuming than CUTENSOR_DEFAULT, but typically provides a more accurate kernel selection.
538    CUTENSOR_ALGO_DEFAULT_PATIENT = -6,
539    /// Choose the GETT algorithm (only applicable to contractions).
540    CUTENSOR_ALGO_GETT = -4,
541    /// Transpose (A or B) + GETT (only applicable to contractions).
542    CUTENSOR_ALGO_TGETT = -3,
543    /// Transpose-Transpose-GEMM-Transpose (requires additional memory) (only applicable to contractions).
544    CUTENSOR_ALGO_TTGT = -2,
545    /// A performance model chooses the appropriate algorithm and kernel.
546    CUTENSOR_ALGO_DEFAULT = -1,
547}
548/// This enum gives users finer control over the suggested workspace.
549///
550/// This enum gives users finer control over the amount of workspace that is suggested by [`cutensorEstimateWorkspaceSize`].
551#[repr(u32)]
552#[derive(
553    Debug,
554    Copy,
555    Clone,
556    Hash,
557    PartialOrd,
558    Ord,
559    PartialEq,
560    Eq,
561    TryFromPrimitive,
562    IntoPrimitive,
563)]
564pub enum cutensorWorksizePreference_t {
565    /// Least memory requirement; at least one algorithm will be available.
566    CUTENSOR_WORKSPACE_MIN = 1,
567    /// Aims to attain high performance while also reducing the workspace requirement.
568    CUTENSOR_WORKSPACE_DEFAULT = 2,
569    /// Highest memory requirement; all algorithms will be available (choose this option if memory footprint is not a concern).
570    CUTENSOR_WORKSPACE_MAX = 3,
571}
572#[repr(C)]
573#[derive(Debug, Copy, Clone)]
574pub struct cutensorComputeDescriptor {
575    _unused: [u8; 0],
576}
577/// Opaque structure representing a compute descriptor.
578pub type cutensorComputeDescriptor_t = *mut cutensorComputeDescriptor;
579unsafe extern "C" {
580    pub static CUTENSOR_COMPUTE_DESC_16F: cutensorComputeDescriptor_t;
581}
582unsafe extern "C" {
583    pub static CUTENSOR_COMPUTE_DESC_16BF: cutensorComputeDescriptor_t;
584}
585unsafe extern "C" {
586    pub static CUTENSOR_COMPUTE_DESC_TF32: cutensorComputeDescriptor_t;
587}
588unsafe extern "C" {
589    pub static CUTENSOR_COMPUTE_DESC_3XTF32: cutensorComputeDescriptor_t;
590}
591unsafe extern "C" {
592    pub static CUTENSOR_COMPUTE_DESC_32F: cutensorComputeDescriptor_t;
593}
594unsafe extern "C" {
595    pub static CUTENSOR_COMPUTE_DESC_64F: cutensorComputeDescriptor_t;
596}
597unsafe extern "C" {
598    pub static CUTENSOR_COMPUTE_DESC_9X16BF: cutensorComputeDescriptor_t;
599}
600unsafe extern "C" {
601    pub static CUTENSOR_COMPUTE_DESC_8XINT8: cutensorComputeDescriptor_t;
602}
603unsafe extern "C" {
604    pub static CUTENSOR_COMPUTE_DESC_4X16F: cutensorComputeDescriptor_t;
605}
606/// This enum lists all attributes of a [`cutensorOperationDescriptor_t`] that can be modified (see [`cutensorOperationDescriptorSetAttribute`] and [`cutensorOperationDescriptorGetAttribute`]).
607#[repr(u32)]
608#[derive(
609    Debug,
610    Copy,
611    Clone,
612    Hash,
613    PartialOrd,
614    Ord,
615    PartialEq,
616    Eq,
617    TryFromPrimitive,
618    IntoPrimitive,
619)]
620pub enum cutensorOperationDescriptorAttribute_t {
621    /// int32_t: enables users to distinguish two identical problems with respect to the sw-managed plan-cache. (default value: 0).
622    CUTENSOR_OPERATION_DESCRIPTOR_TAG = 0,
623    /// cudaDataType_t: data type of the scaling factors.
624    CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE = 1,
625    /// float: number of floating-point operations necessary to perform this operation (assuming all scalar are not equal to zero, unless otherwise specified).
626    CUTENSOR_OPERATION_DESCRIPTOR_FLOPS = 2,
627    /// float: minimal number of bytes transferred from/to global-memory (assuming all scalar are not equal to zero, unless otherwise specified).
628    CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES = 3,
629    /// uint32_t[] (of size descOut->numModes): Each entry i holds the number of padded values that should be padded to the left of the ith dimension.
630    CUTENSOR_OPERATION_DESCRIPTOR_PADDING_LEFT = 4,
631    /// uint32_t[] (of size descOut->numModes): Each entry i holds the number of padded values that should be padded to the right of the ith dimension.
632    CUTENSOR_OPERATION_DESCRIPTOR_PADDING_RIGHT = 5,
633    /// host-side pointer to element of the same type as the output tensor: Constant padding value.
634    CUTENSOR_OPERATION_DESCRIPTOR_PADDING_VALUE = 6,
635}
636/// This enum lists all attributes of a [`cutensorPlanPreference_t`] object that can be modified.
637#[repr(u32)]
638#[derive(
639    Debug,
640    Copy,
641    Clone,
642    Hash,
643    PartialOrd,
644    Ord,
645    PartialEq,
646    Eq,
647    TryFromPrimitive,
648    IntoPrimitive,
649)]
650pub enum cutensorPlanPreferenceAttribute_t {
651    /// cutensorAutotuneMode_t: Determines if recurrent executions of the plan (e.g., via cutensorContract, cutensorPermute) should autotune (i.e., try different kernels); see section “Plan Cache” for details.
652    CUTENSOR_PLAN_PREFERENCE_AUTOTUNE_MODE = 0,
653    /// cutensorCacheMode_t: Determines if the corresponding algorithm/kernel for this plan should be cached and it gives fine control over what is considered a cachehit.
654    CUTENSOR_PLAN_PREFERENCE_CACHE_MODE = 1,
655    /// int32_t: Only applicable if [`cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_CACHE_MODE`] is set to [`cutensorAutotuneMode_t::CUTENSOR_AUTOTUNE_MODE_INCREMENTAL`].
656    CUTENSOR_PLAN_PREFERENCE_INCREMENTAL_COUNT = 2,
657    /// cutensorAlgo_t: Fixes a certain [`cutensorAlgo_t`].
658    CUTENSOR_PLAN_PREFERENCE_ALGO = 3,
659    /// int32_t: Fixes a kernel (a sub variant of an algo; e.g., kernel_rank==1 while algo == [`cutensorAlgo_t::CUTENSOR_ALGO_TGETT`] would select the second-best GETT kernel/variant according to cuTENSOR’s performance model; kernel_rank==2 would select the third-best).
660    CUTENSOR_PLAN_PREFERENCE_KERNEL_RANK = 4,
661    /// cutensorJitMode_t: determines if just-in-time compilation is enabled or disabled (default: [`cutensorJitMode_t::CUTENSOR_JIT_MODE_NONE`]).
662    CUTENSOR_PLAN_PREFERENCE_JIT = 5,
663    /// int32_t: Plan for a specific GPU architecture and not one associated with the context. Value should encode SM version via `10 * SM.major + SM.minor`. Currently only SM versions 80, 90 and 100 are supported.
664    CUTENSOR_PLAN_PREFERENCE_GPU_ARCH = 6,
665}
666/// This enum determines the mode with respect to cuTENSOR’s auto-tuning capability.
667#[repr(u32)]
668#[derive(
669    Debug,
670    Copy,
671    Clone,
672    Hash,
673    PartialOrd,
674    Ord,
675    PartialEq,
676    Eq,
677    TryFromPrimitive,
678    IntoPrimitive,
679)]
680pub enum cutensorAutotuneMode_t {
681    /// Indicates no autotuning (default); in this case the cache will help to reduce the plan-creation overhead. In the case of a cachehit: the cached plan will be reused, otherwise the plancache will be neglected.
682    CUTENSOR_AUTOTUNE_MODE_NONE = 0,
683    /// Indicates an incremental autotuning (i.e., each invocation of corresponding [`cutensorCreatePlan`] will create a plan based on a different algorithm/kernel; the maximum number of kernels that will be tested is defined by the [`cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_INCREMENTAL_COUNT`] of [`cutensorPlanPreferenceAttribute_t`]). WARNING: If this autotuning mode is selected, then we cannot guarantee bit-wise identical results (since different algorithms could be executed).
684    CUTENSOR_AUTOTUNE_MODE_INCREMENTAL = 1,
685}
686/// This enum determines the mode with respect to cuTENSOR’s just-in-time compilation capability.
687#[repr(u32)]
688#[derive(
689    Debug,
690    Copy,
691    Clone,
692    Hash,
693    PartialOrd,
694    Ord,
695    PartialEq,
696    Eq,
697    TryFromPrimitive,
698    IntoPrimitive,
699)]
700pub enum cutensorJitMode_t {
701    /// Indicates that no kernel will be just-in-time compiled.
702    CUTENSOR_JIT_MODE_NONE = 0,
703    /// Indicates that the corresponding plan will try to compile a dedicated kernel for the given operation. Only supported for GPUs with compute capability >= 8.0 (Ampere or newer).
704    CUTENSOR_JIT_MODE_DEFAULT = 1,
705}
706/// This enum defines what is considered a cache hit.
707#[repr(u32)]
708#[derive(
709    Debug,
710    Copy,
711    Clone,
712    Hash,
713    PartialOrd,
714    Ord,
715    PartialEq,
716    Eq,
717    TryFromPrimitive,
718    IntoPrimitive,
719)]
720pub enum cutensorCacheMode_t {
721    /// Plan will not be cached.
722    CUTENSOR_CACHE_MODE_NONE = 0,
723    /// All parameters of the corresponding descriptor must be identical to the cached plan (default).
724    CUTENSOR_CACHE_MODE_PEDANTIC = 1,
725}
726/// This enum lists all attributes of a [`cutensorPlan_t`] object that can be retrieved via [`cutensorPlanGetAttribute`].
727#[repr(u32)]
728#[derive(
729    Debug,
730    Copy,
731    Clone,
732    Hash,
733    PartialOrd,
734    Ord,
735    PartialEq,
736    Eq,
737    TryFromPrimitive,
738    IntoPrimitive,
739)]
740pub enum cutensorPlanAttribute_t {
741    /// uint64_t: exact required workspace in bytes that is needed to execute the plan.
742    CUTENSOR_PLAN_REQUIRED_WORKSPACE = 0,
743}
744#[repr(C)]
745#[derive(Debug, Copy, Clone)]
746pub struct cutensorOperationDescriptor {
747    _unused: [u8; 0],
748}
749/// Opaque structure representing any type of problem descriptor (e.g., contraction, reduction, elementwise).
750pub type cutensorOperationDescriptor_t = *mut cutensorOperationDescriptor;
751#[repr(C)]
752#[derive(Debug, Copy, Clone)]
753pub struct cutensorPlan {
754    _unused: [u8; 0],
755}
756/// Opaque structure representing a plan (e.g, contraction, reduction, elementwise).
757pub type cutensorPlan_t = *mut cutensorPlan;
758#[repr(C)]
759#[derive(Debug, Copy, Clone)]
760pub struct cutensorPlanPreference {
761    _unused: [u8; 0],
762}
763/// Opaque structure that narrows down the space of applicable algorithms/variants/kernels.
764pub type cutensorPlanPreference_t = *mut cutensorPlanPreference;
765#[repr(C)]
766#[derive(Debug, Copy, Clone)]
767pub struct cutensorHandle {
768    _unused: [u8; 0],
769}
770/// Opaque structure holding cuTENSOR’s library context.
771pub type cutensorHandle_t = *mut cutensorHandle;
772#[repr(C)]
773#[derive(Debug, Copy, Clone)]
774pub struct cutensorTensorDescriptor {
775    _unused: [u8; 0],
776}
777/// Opaque structure representing a tensor descriptor.
778pub type cutensorTensorDescriptor_t = *mut cutensorTensorDescriptor;
779#[repr(C)]
780#[derive(Debug, Copy, Clone)]
781pub struct cutensorBlockSparseTensorDescriptor {
782    _unused: [u8; 0],
783}
784/// Opaque structure representing a block-sparse tensor descriptor.
785pub type cutensorBlockSparseTensorDescriptor_t = *mut cutensorBlockSparseTensorDescriptor;
786/// A function pointer type for logging.
787pub type cutensorLoggerCallback_t = ::core::option::Option<
788    unsafe extern "C" fn(
789        logLevel: i32,
790        functionName: *const ::core::ffi::c_char,
791        message: *const ::core::ffi::c_char,
792    ),
793>;
794unsafe extern "C" {
795    /// Initializes the cuTENSOR library and allocates the memory for the library context.
796    ///
797    /// The device associated with a particular cuTENSOR handle is assumed to remain unchanged after the [`cutensorCreate`] call. In order for the cuTENSOR library to use a different device, the application must set the new device to be used by calling cudaSetDevice and then create another cuTENSOR handle, which will be associated with the new device, by calling [`cutensorCreate`].
798    ///
799    /// Moreover, each handle by default has a plan cache that can store the least recently used [`cutensorPlan_t`]; its default capacity is 64, but it can be changed via [`cutensorHandleResizePlanCache`] if this is too little storage space. See the [Plan Cache Guide](https://docs.nvidia.com/cuda/cutensor/2.6.0/plan_cache.html) for more information.
800    ///
801    /// The user is responsible for calling [`cutensorDestroy`] to free the resources associated with the handle.
802    ///
803    /// Remark
804    ///
805    /// blocking, no reentrant, and thread-safe.
806    pub fn cutensorCreate(handle: *mut cutensorHandle_t) -> cutensorStatus_t;
807}
808unsafe extern "C" {
809    /// Frees all resources related to the provided library handle.
810    ///
811    /// Remark
812    ///
813    /// blocking, no reentrant, and thread-safe.
814    pub fn cutensorDestroy(handle: cutensorHandle_t) -> cutensorStatus_t;
815}
816unsafe extern "C" {
817    /// Resizes the plan cache.
818    ///
819    /// This function changes the number of plans that can be stored in the plan cache of the handle.
820    ///
821    /// Resizing invalidates the cache.
822    ///
823    /// While this function is not thread-safe, the resulting cache can be shared across different threads in a thread-safe manner.
824    ///
825    /// Remark
826    ///
827    /// non-blocking, no reentrant, and not thread-safe.
828    ///
829    /// # Parameters
830    ///
831    /// - `handle`: Opaque handle holding cuTENSOR’s library context. The cache will be attached to the handle.
832    /// - `numEntries`: Number of entries the cache will support.
833    ///
834    /// # Return value
835    ///
836    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
837    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
838    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
839    pub fn cutensorHandleResizePlanCache(
840        handle: cutensorHandle_t,
841        numEntries: u32,
842    ) -> cutensorStatus_t;
843}
844unsafe extern "C" {
845    /// Writes the Plan-Cache (that belongs to the provided handle) to file.
846    ///
847    /// Remark
848    ///
849    /// non-blocking, no reentrant, and thread-safe.
850    ///
851    /// # Parameters
852    ///
853    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
854    /// - `filename`: Specifies the filename (including the absolute path) to the file that should hold all the cache information. Warning: an existing file will be overwritten.
855    ///
856    /// # Return value
857    ///
858    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if the no cache has been attached.
859    /// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be written to.
860    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
861    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
862    pub fn cutensorHandleWritePlanCacheToFile(
863        handle: cutensorHandle_t,
864        filename: *const ::core::ffi::c_char,
865    ) -> cutensorStatus_t;
866}
867unsafe extern "C" {
868    /// Reads a Plan-Cache from file and overwrites the cachelines of the provided handle.
869    ///
870    /// A cache is only valid for the same cuTENSOR version and CUDA version; moreover, the GPU architecture (incl. multiprocessor count) must match, otherwise [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`] will be returned.
871    ///
872    /// Remark
873    ///
874    /// non-blocking, no reentrant, and thread-safe.
875    ///
876    /// # Parameters
877    ///
878    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
879    /// - `filename`: Specifies the filename (including the absolute path) to the file that holds all the cache information that have previously been written by [`cutensorHandleWritePlanCacheToFile`].
880    /// - `numCachelinesRead`: On exit, this variable will hold the number of successfully-read cachelines, if [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`] is returned. Otherwise, this variable will hold the number of cachelines that are required to read all cachelines associated to the cache pointed to by `filename`; in that case [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE`] is returned.
881    ///
882    /// # Return value
883    ///
884    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE`]: if the stored cache requires more cachelines than those that are currently attached to the handle.
885    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if the stored cache was created by a different cuTENSOR- or CUDA-version or if the GPU architecture (incl. multiprocessor count) doesn’t match.
886    /// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be read.
887    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
888    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
889    pub fn cutensorHandleReadPlanCacheFromFile(
890        handle: cutensorHandle_t,
891        filename: *const ::core::ffi::c_char,
892        numCachelinesRead: *mut u32,
893    ) -> cutensorStatus_t;
894}
895unsafe extern "C" {
896    /// Writes the —per library— kernel cache to file.
897    ///
898    /// Writes the just-in-time compiled kernels to the provided file (those kernels belong to the library—not to the handle).
899    ///
900    /// Remark
901    ///
902    /// non-blocking, no reentrant, and thread-safe.
903    ///
904    /// # Parameters
905    ///
906    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
907    /// - `filename`: Specifies the filename (including the absolute path) to the file that should hold all the cache information. Warning: an existing file will be overwritten.
908    ///
909    /// # Return value
910    ///
911    /// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be written to.
912    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
913    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the function is not available for the operating system, CUDA Toolkit, or compute capability of the device.
914    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully or there were no kernels in the cache.
915    pub fn cutensorWriteKernelCacheToFile(
916        handle: cutensorHandle_t,
917        filename: *const ::core::ffi::c_char,
918    ) -> cutensorStatus_t;
919}
920unsafe extern "C" {
921    /// Reads a kernel cache from file and adds all non-existing JIT compiled kernels to the kernel cache.
922    ///
923    /// A cache is only valid for the same cuTENSOR version and CUDA version; moreover, the GPU architecture (incl. multiprocessor count) must match, otherwise [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`] will be returned.
924    ///
925    /// Remark
926    ///
927    /// non-blocking, no reentrant, and thread-safe.
928    ///
929    /// # Parameters
930    ///
931    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
932    /// - `filename`: Specifies the filename (including the absolute path) to the file that holds all the cache information that have previously been written by cutensorWriteKernelCacheToFile.
933    ///
934    /// # Return value
935    ///
936    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if the stored cache was created by a different cuTENSOR- or CUDA-version or if the GPU architecture (incl. multiprocessor count) doesn’t match.
937    /// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be read.
938    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
939    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the function is not available for the operating system, CUDA Toolkit, or compute capability of the device.
940    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully, or the file pointed to by filename was empty.
941    pub fn cutensorReadKernelCacheFromFile(
942        handle: cutensorHandle_t,
943        filename: *const ::core::ffi::c_char,
944    ) -> cutensorStatus_t;
945}
946unsafe extern "C" {
947    /// Creates a tensor descriptor.
948    ///
949    /// This allocates a small amount of host-memory.
950    ///
951    /// The user is responsible for calling [`cutensorDestroyTensorDescriptor`] to free the associated resources once the tensor descriptor is no longer used.
952    ///
953    /// Remark
954    ///
955    /// non-blocking, no reentrant, and thread-safe.
956    ///
957    /// # Parameters
958    ///
959    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
960    /// - `desc`: Pointer to the address where the allocated tensor descriptor object will be stored.
961    /// - `numModes`: Number of modes.
962    /// - `extent`: Extent of each mode (must be larger than zero).
963    /// - `stride`: stride\[i\] denotes the displacement (a.k.a. stride)—in elements of the base type—between two consecutive elements in the ith-mode. If stride is NULL, a packed generalized column-major memory layout is assumed (i.e., the strides increase monotonically from left to right). Each stride must be larger than zero; to be precise, a stride of zero can be achieved by omitting this mode entirely; for instance instead of writing C\[a,b\] = A\[b,a\] with strideA(a) = 0, you can write C\[a,b\] = A\[b\] directly; cuTENSOR will then automatically infer that the a-mode in A should be broadcasted.
964    /// - `dataType`: Data type of the stored entries.
965    /// - `alignmentRequirement`: Alignment (in bytes) to the base pointer that will be used in conjunction with this tensor descriptor (e.g., `cudaMalloc` has a default alignment of 256 bytes).
966    ///
967    /// # Return value
968    ///
969    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
970    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
971    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the requested descriptor is not supported (e.g., due to non-supported data type).
972    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
973    pub fn cutensorCreateTensorDescriptor(
974        handle: cutensorHandle_t,
975        desc: *mut cutensorTensorDescriptor_t,
976        numModes: u32,
977        extent: *const i64,
978        stride: *const i64,
979        dataType: cudaDataType_t,
980        alignmentRequirement: u32,
981    ) -> cutensorStatus_t;
982}
983unsafe extern "C" {
984    /// Frees all resources related to the provided tensor descriptor.
985    ///
986    /// Remark
987    ///
988    /// blocking, no reentrant, and thread-safe.
989    pub fn cutensorDestroyTensorDescriptor(
990        desc: cutensorTensorDescriptor_t,
991    ) -> cutensorStatus_t;
992}
993unsafe extern "C" {
994    /// This function creates an operation descriptor that encodes an elementwise trinary operation.
995    ///
996    /// Said trinary operation has the following general form:
997    /// $$
998    /// D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{ABC}(\Phi_{AB}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \beta op_B(B_{\Pi^B(i_0,i_1,...,i_n)})), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)}))
999    /// $$
1000    ///
1001    /// Where
1002    ///
1003    /// * A,B,C,D are multi-mode tensors (of arbitrary data types).
1004    /// * $\Pi^A, \Pi^B, \Pi^C$ are permutation operators that permute the modes of A, B, and C respectively.
1005    /// * $op_{A},op_{B},op_{C}$ are unary element-wise operators (e.g., IDENTITY, CONJUGATE).
1006    /// * $\Phi_{ABC}, \Phi_{AB}$ are binary element-wise operators (e.g., ADD, MUL, MAX, MIN).
1007    ///
1008    /// Notice that the broadcasting (of a mode) can be achieved by simply omitting that mode from the respective tensor.
1009    ///
1010    /// Moreover, modes may appear in any order, giving users a greater flexibility. The only **restrictions** are:
1011    ///
1012    /// * modes that appear in A or B `must` also appear in the output tensor; a mode that only appears in the input would be contracted and such an operation would be covered by either [`cutensorContract`] or [`cutensorReduce`].
1013    /// * each mode may appear in each tensor at most once.
1014    ///
1015    /// Input tensors may be read even if the value of the corresponding scalar is zero.
1016    ///
1017    /// Examples:
1018    ///
1019    /// * $D_{a,b,c,d} = A_{b,d,a,c}$
1020    /// * $D_{a,b,c,d} = 2.2 \\* A_{b,d,a,c} + 1.3 \\* B_{c,b,d,a}$
1021    /// * $D_{a,b,c,d} = 2.2 \\* A_{b,d,a,c} + 1.3 \\* B_{c,b,d,a} + C_{a,b,c,d}$
1022    /// * $D_{a,b,c,d} = min((2.2 \\* A_{b,d,a,c} + 1.3 \\* B_{c,b,d,a}), C_{a,b,c,d})$
1023    ///
1024    /// Call [`cutensorElementwiseTrinaryExecute`] to perform the actual operation.
1025    ///
1026    /// Please use [`cutensorDestroyOperationDescriptor`] to deallocated the descriptor once it is no longer used.
1027    ///
1028    /// Supported data-type combinations are:
1029    ///
1030    /// | typeA | typeB | typeC | descCompute |
1031    /// | --- | --- | --- | --- |
1032    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
1033    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1034    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
1035    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1036    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1037    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1038    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1039    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1040    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1041    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1042    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1043    ///
1044    /// Remark
1045    ///
1046    /// calls asynchronous functions, no reentrant, and thread-safe.
1047    ///
1048    /// # Parameters
1049    ///
1050    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1051    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested elementwise operation.
1052    /// - `descA`: A descriptor that holds the information about the data type, modes, and strides of A.
1053    /// - `modeA`: Array (in host memory) of size descA->numModes that holds the names of the modes of A (e.g., if $A_{a,b,c}$ then modeA = {‘a’,’b’,’c’}). The modeA\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to [`cutensorCreateTensorDescriptor`].
1054    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1055    /// - `descB`: A descriptor that holds information about the data type, modes, and strides of B.
1056    /// - `modeB`: Array (in host memory) of size descB->numModes that holds the names of the modes of B. modeB\[i\] corresponds to extent\[i\] and stride\[i\] of the [`cutensorCreateTensorDescriptor`].
1057    /// - `opB`: Unary operator that will be applied to each element of B before it is further processed. The original data of this tensor remains unchanged.
1058    /// - `descC`: A descriptor that holds information about the data type, modes, and strides of C.
1059    /// - `modeC`: Array (in host memory) of size descC->numModes that holds the names of the modes of C. The modeC\[i\] corresponds to extent\[i\] and stride\[i\] of the [`cutensorCreateTensorDescriptor`].
1060    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged.
1061    /// - `descD`: A descriptor that holds information about the data type, modes, and strides of D. Notice that we currently request descD and descC to be identical.
1062    /// - `modeD`: Array (in host memory) of size descD->numModes that holds the names of the modes of D. The modeD\[i\] corresponds to extent\[i\] and stride\[i\] of the [`cutensorCreateTensorDescriptor`].
1063    /// - `opAB`: Element-wise binary operator (see $\Phi_{AB}$ above).
1064    /// - `opABC`: Element-wise binary operator (see $\Phi_{ABC}$ above).
1065    /// - `descCompute`: Determines the precision in which this operations is performed.
1066    ///
1067    /// # Return value
1068    ///
1069    /// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the device is either not ready, or the target architecture is not supported.
1070    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1071    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1072    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1073    pub fn cutensorCreateElementwiseTrinary(
1074        handle: cutensorHandle_t,
1075        desc: *mut cutensorOperationDescriptor_t,
1076        descA: cutensorTensorDescriptor_t,
1077        modeA: *const i32,
1078        opA: cutensorOperator_t,
1079        descB: cutensorTensorDescriptor_t,
1080        modeB: *const i32,
1081        opB: cutensorOperator_t,
1082        descC: cutensorTensorDescriptor_t,
1083        modeC: *const i32,
1084        opC: cutensorOperator_t,
1085        descD: cutensorTensorDescriptor_t,
1086        modeD: *const i32,
1087        opAB: cutensorOperator_t,
1088        opABC: cutensorOperator_t,
1089        descCompute: cutensorComputeDescriptor_t,
1090    ) -> cutensorStatus_t;
1091}
1092unsafe extern "C" {
1093    /// Performs an element-wise tensor operation for three input tensors (see [`cutensorCreateElementwiseTrinary`])
1094    ///
1095    /// This function performs a element-wise tensor operation of the form:
1096    /// $$
1097    /// D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{ABC}(\Phi_{AB}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \beta op_B(B_{\Pi^B(i_0,i_1,...,i_n)})), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)}))
1098    /// $$
1099    ///
1100    /// See [`cutensorCreateElementwiseTrinary`] for details.
1101    ///
1102    /// Remark
1103    ///
1104    /// calls asynchronous functions, no reentrant, and thread-safe.
1105    ///
1106    /// # Parameters
1107    ///
1108    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1109    /// - `plan`: Opaque handle holding all information about the desired elementwise operation (created by [`cutensorCreateElementwiseTrinary`] followed by [`cutensorCreatePlan`]).
1110    /// - `alpha`: Scaling factor for A (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE) to query the expected data type). Pointer to the host memory. If alpha is zero, A is not read and the corresponding unary operator is not applied.
1111    /// - `A`: Multi-mode tensor (described by `descA` as part of [`cutensorCreateElementwiseTrinary`]). Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1112    /// - `beta`: Scaling factor for B (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE) to query the expected data type). Pointer to the host memory. If beta is zero, B is not read and the corresponding unary operator is not applied.
1113    /// - `B`: Multi-mode tensor (described by `descB` as part of [`cutensorCreateElementwiseTrinary`]). Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1114    /// - `gamma`: Scaling factor for C (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE) to query the expected data type). Pointer to the host memory. If gamma is zero, C is not read and the corresponding unary operator is not applied.
1115    /// - `C`: Multi-mode tensor (described by `descC` as part of [`cutensorCreateElementwiseTrinary`]). Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1116    /// - `D`: Multi-mode tensor (described by `descD` as part of [`cutensorCreateElementwiseTrinary`]). Pointer to the GPU-accessible memory (`C` and `D` may be identical, if and only if `descC == descD`).
1117    /// - `stream`: The CUDA stream used to perform the operation.
1118    ///
1119    /// # Return value
1120    ///
1121    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1122    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1123    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1124    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1125    pub fn cutensorElementwiseTrinaryExecute(
1126        handle: cutensorHandle_t,
1127        plan: cutensorPlan_t,
1128        alpha: *const ::core::ffi::c_void,
1129        A: *const ::core::ffi::c_void,
1130        beta: *const ::core::ffi::c_void,
1131        B: *const ::core::ffi::c_void,
1132        gamma: *const ::core::ffi::c_void,
1133        C: *const ::core::ffi::c_void,
1134        D: *mut ::core::ffi::c_void,
1135        stream: cudaStream_t,
1136    ) -> cutensorStatus_t;
1137}
1138unsafe extern "C" {
1139    /// This function creates an operation descriptor for an elementwise binary operation.
1140    ///
1141    /// The binary operation has the following general form:
1142    /// $$
1143    /// D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{AC}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)}))
1144    /// $$
1145    ///
1146    /// Call [`cutensorElementwiseBinaryExecute`] to perform the actual operation.
1147    ///
1148    /// Supported data-type combinations are:
1149    ///
1150    /// | typeA | typeC | descCompute |
1151    /// | --- | --- | --- |
1152    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
1153    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1154    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
1155    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1156    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1157    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1158    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1159    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1160    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1161    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1162    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1163    ///
1164    /// Remark
1165    ///
1166    /// calls asynchronous functions, no reentrant, and thread-safe.
1167    ///
1168    /// # Parameters
1169    ///
1170    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1171    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested elementwise operation.
1172    /// - `descA`: The descriptor that holds the information about the data type, modes, and strides of A.
1173    /// - `modeA`: Array (in host memory) of size descA->numModes that holds the names of the modes of A (e.g., if A_{a,b,c} => modeA = {‘a’,’b’,’c’}). The modeA\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to [`cutensorCreateTensorDescriptor`].
1174    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1175    /// - `descC`: The descriptor that holds information about the data type, modes, and strides of C.
1176    /// - `modeC`: Array (in host memory) of size descC->numModes that holds the names of the modes of C. The modeC\[i\] corresponds to extent\[i\] and stride\[i\] of the [`cutensorCreateTensorDescriptor`].
1177    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged.
1178    /// - `descD`: The descriptor that holds information about the data type, modes, and strides of D. Notice that we currently request descD and descC to be identical.
1179    /// - `modeD`: Array (in host memory) of size descD->numModes that holds the names of the modes of D. The modeD\[i\] corresponds to extent\[i\] and stride\[i\] of the [`cutensorCreateTensorDescriptor`].
1180    /// - `opAC`: Element-wise binary operator (corresponding to $\Phi_{AC}$ above).
1181    /// - `descCompute`: Determines the precision in which this operations is performed.
1182    ///
1183    /// # Return value
1184    ///
1185    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1186    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1187    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1188    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1189    pub fn cutensorCreateElementwiseBinary(
1190        handle: cutensorHandle_t,
1191        desc: *mut cutensorOperationDescriptor_t,
1192        descA: cutensorTensorDescriptor_t,
1193        modeA: *const i32,
1194        opA: cutensorOperator_t,
1195        descC: cutensorTensorDescriptor_t,
1196        modeC: *const i32,
1197        opC: cutensorOperator_t,
1198        descD: cutensorTensorDescriptor_t,
1199        modeD: *const i32,
1200        opAC: cutensorOperator_t,
1201        descCompute: cutensorComputeDescriptor_t,
1202    ) -> cutensorStatus_t;
1203}
1204unsafe extern "C" {
1205    /// Performs an element-wise tensor operation for two input tensors (see [`cutensorCreateElementwiseBinary`])
1206    ///
1207    /// This function performs a element-wise tensor operation of the form:
1208    /// $$
1209    /// D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{AC}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)}))
1210    /// $$
1211    ///
1212    /// See [`cutensorCreateElementwiseBinary`] for details.
1213    ///
1214    /// Remark
1215    ///
1216    /// calls asynchronous functions, no reentrant, and thread-safe.
1217    ///
1218    /// # Parameters
1219    ///
1220    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1221    /// - `plan`: Opaque handle holding all information about the desired elementwise operation (created by [`cutensorCreateElementwiseBinary`] followed by [`cutensorCreatePlan`]).
1222    /// - `alpha`: Scaling factor for A (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE) to query the expected data type). Pointer to the host memory. If alpha is zero, A is not read and the corresponding unary operator is not applied.
1223    /// - `A`: Multi-mode tensor (described by `descA` as part of [`cutensorCreateElementwiseBinary`]). Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1224    /// - `gamma`: Scaling factor for C (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE) to query the expected data type). Pointer to the host memory. If gamma is zero, C is not read and the corresponding unary operator is not applied.
1225    /// - `C`: Multi-mode tensor (described by `descC` as part of [`cutensorCreateElementwiseBinary`]). Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1226    /// - `D`: Multi-mode tensor (described by `descD` as part of [`cutensorCreateElementwiseBinary`]). Pointer to the GPU-accessible memory (`C` and `D` may be identical, if and only if `descC == descD`).
1227    /// - `stream`: The CUDA stream used to perform the operation.
1228    ///
1229    /// # Return value
1230    ///
1231    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1232    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1233    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1234    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1235    pub fn cutensorElementwiseBinaryExecute(
1236        handle: cutensorHandle_t,
1237        plan: cutensorPlan_t,
1238        alpha: *const ::core::ffi::c_void,
1239        A: *const ::core::ffi::c_void,
1240        gamma: *const ::core::ffi::c_void,
1241        C: *const ::core::ffi::c_void,
1242        D: *mut ::core::ffi::c_void,
1243        stream: cudaStream_t,
1244    ) -> cutensorStatus_t;
1245}
1246unsafe extern "C" {
1247    /// This function creates an operation descriptor for a tensor permutation.
1248    ///
1249    /// The tensor permutation has the following general form:
1250    /// $$
1251    /// B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)})
1252    /// $$
1253    ///
1254    /// Consequently, this function performs an out-of-place tensor permutation and is a specialization of [`cutensorCreateElementwiseBinary`].
1255    ///
1256    /// Where
1257    ///
1258    /// * A and B are multi-mode tensors (of arbitrary data types),
1259    /// * $\Pi^A, \Pi^B$ are permutation operators that permute the modes of A, B respectively,
1260    /// * $op_A$ is an unary element-wise operators (e.g., IDENTITY, SQR, CONJUGATE), and
1261    ///
1262    /// Broadcasting (of a mode) can be achieved by simply omitting that mode from the respective tensor.
1263    ///
1264    /// Modes may appear in any order. The only **restrictions** are:
1265    ///
1266    /// * modes that appear in A `must` also appear in the output tensor.
1267    /// * each mode may appear in each tensor at most once.
1268    ///
1269    /// Supported data-type combinations are:
1270    ///
1271    /// | typeA | typeB | descCompute |
1272    /// | --- | --- | --- |
1273    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
1274    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1275    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1276    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1277    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
1278    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1279    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1280    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1281    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1282    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1283    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1284    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1285    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1286    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1287    ///
1288    /// Remark
1289    ///
1290    /// calls asynchronous functions, no reentrant, and thread-safe.
1291    ///
1292    /// # Parameters
1293    ///
1294    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1295    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested permutation.
1296    /// - `descA`: The descriptor that holds information about the data type, modes, and strides of A.
1297    /// - `modeA`: Array of size descA->numModes that holds the names of the modes of A (e.g., if A_{a,b,c} => modeA = {‘a’,’b’,’c’}).
1298    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1299    /// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
1300    /// - `modeB`: Array of size descB->numModes that holds the names of the modes of B.
1301    /// - `descCompute`: Determines the precision in which this operations is performed.
1302    ///
1303    /// # Return value
1304    ///
1305    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1306    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1307    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1308    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1309    pub fn cutensorCreatePermutation(
1310        handle: cutensorHandle_t,
1311        desc: *mut cutensorOperationDescriptor_t,
1312        descA: cutensorTensorDescriptor_t,
1313        modeA: *const i32,
1314        opA: cutensorOperator_t,
1315        descB: cutensorTensorDescriptor_t,
1316        modeB: *const i32,
1317        descCompute: cutensorComputeDescriptor_t,
1318    ) -> cutensorStatus_t;
1319}
1320unsafe extern "C" {
1321    /// Performs the tensor permutation that is encoded by `plan` (see [`cutensorCreatePermutation`]).
1322    ///
1323    /// This function performs an elementwise tensor operation of the form:
1324    /// $$
1325    /// B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)})
1326    /// $$
1327    ///
1328    /// Consequently, this function performs an out-of-place tensor permutation.
1329    ///
1330    /// Where
1331    ///
1332    /// * A and B are multi-mode tensors (of arbitrary data types),
1333    /// * $\Pi^A, \Pi^B$ are permutation operators that permute the modes of A, B respectively,
1334    /// * $op_A$ is an unary element-wise operators (e.g., IDENTITY, SQR, CONJUGATE), and is specified when creating the operation descriptor using [`cutensorCreatePermutation`]
1335    ///
1336    /// Remark
1337    ///
1338    /// calls asynchronous functions, no reentrant, and thread-safe.
1339    ///
1340    /// # Parameters
1341    ///
1342    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1343    /// - `plan`: Opaque handle holding all information about the desired tensor reduction (created by [`cutensorCreatePermutation`] followed by [`cutensorCreatePlan`]).
1344    /// - `alpha`: Scaling factor for A (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory. If alpha is zero, A is not read and the corresponding unary operator is not applied.
1345    /// - `A`: Multi-mode tensor of type typeA with nmodeA modes. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1346    /// - `B`: Multi-mode tensor of type typeB with nmodeB modes. Pointer to the GPU-accessible memory.
1347    /// - `stream`: The CUDA stream.
1348    ///
1349    /// # Return value
1350    ///
1351    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1352    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1353    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1354    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1355    pub fn cutensorPermute(
1356        handle: cutensorHandle_t,
1357        plan: cutensorPlan_t,
1358        alpha: *const ::core::ffi::c_void,
1359        A: *const ::core::ffi::c_void,
1360        B: *mut ::core::ffi::c_void,
1361        stream: cudaStream_t,
1362    ) -> cutensorStatus_t;
1363}
1364unsafe extern "C" {
1365    /// This function allocates a cutensorOperationDescriptor_t object that encodes a tensor contraction of the form $D = \alpha \mathcal{A} \mathcal{B} + \beta \mathcal{C}$.
1366    ///
1367    /// Allocates data for `desc` to be used to perform a tensor contraction of the form:
1368    /// $$
1369    /// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha op_\mathcal{A}(\mathcal{A}_{{modes}_\mathcal{A}}) op_\mathcal{B}(B_{{modes}_\mathcal{B}}) + \beta op_\mathcal{C}(\mathcal{C}_{{modes}_\mathcal{C}}).
1370    /// $$
1371    ///
1372    /// See [`cutensorCreatePlan`] (or cutensorCreatePlanAutotuned) to create the plan (i.e., to select the kernel) followed by a call to [`cutensorContract`] to perform the actual contraction.
1373    ///
1374    /// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
1375    ///
1376    /// Supported data-type combinations are:
1377    ///
1378    /// | typeA | typeB | typeC | descCompute | typeScalar | Tensor Core |
1379    /// | --- | --- | --- | --- | --- | --- |
1380    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_R_32F`] | Volta+ |
1381    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |
1382    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_R_32F`] | No |
1383    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_TF32`] | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |
1384    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_3XTF32`] | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |
1385    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_16BF`] | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |
1386    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_16F`] | [`cudaDataType_t::CUDA_R_32F`] | Volta+ |
1387    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_R_64F`] | Ampere+ |
1388    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_R_64F`] | No |
1389    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_C_32F`] | No |
1390    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_TF32`] | [`cudaDataType_t::CUDA_C_32F`] | Ampere+ |
1391    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_3XTF32`] | [`cudaDataType_t::CUDA_C_32F`] | Ampere+ |
1392    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_C_64F`] | Ampere+ |
1393    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_C_64F`] | No |
1394    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_C_64F`] | No |
1395    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_C_64F`] | No |
1396    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_8XINT8`] | [`cudaDataType_t::CUDA_R_64F`] | Hopper+ |
1397    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_8XINT8`] | [`cudaDataType_t::CUDA_C_64F`] | Hopper+ |
1398    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_9X16BF`] | [`cudaDataType_t::CUDA_R_32F`] | Hopper+ |
1399    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_9X16BF`] | [`cudaDataType_t::CUDA_C_32F`] | Hopper+ |
1400    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_4X16F`] | [`cudaDataType_t::CUDA_R_32F`] | Blackwell+ |
1401    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_4X16F`] | [`cudaDataType_t::CUDA_C_32F`] | Blackwell+ |
1402    ///
1403    /// # Parameters
1404    ///
1405    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1406    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
1407    /// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
1408    /// - `modeA`: Array with ‘nmodeA’ entries that represent the modes of A. The modeA\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1409    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1410    /// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
1411    /// - `modeB`: Array with ‘nmodeB’ entries that represent the modes of B. The modeB\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1412    /// - `opB`: Unary operator that will be applied to each element of B before it is further processed. The original data of this tensor remains unchanged.
1413    /// - `descC`: The escriptor that holds information about the data type, modes, and strides of C.
1414    /// - `modeC`: Array with ‘nmodeC’ entries that represent the modes of C. The modeC\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1415    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged.
1416    /// - `descD`: The descriptor that holds information about the data type, modes, and strides of D (must be identical to `descC` for now).
1417    /// - `modeD`: Array with ‘nmodeD’ entries that represent the modes of D (must be identical to modeC for now). The modeD\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1418    /// - `descCompute`: Determines the precision in which this operations is performed.
1419    ///
1420    /// # Return value
1421    ///
1422    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1423    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1424    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1425    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1426    pub fn cutensorCreateContraction(
1427        handle: cutensorHandle_t,
1428        desc: *mut cutensorOperationDescriptor_t,
1429        descA: cutensorTensorDescriptor_t,
1430        modeA: *const i32,
1431        opA: cutensorOperator_t,
1432        descB: cutensorTensorDescriptor_t,
1433        modeB: *const i32,
1434        opB: cutensorOperator_t,
1435        descC: cutensorTensorDescriptor_t,
1436        modeC: *const i32,
1437        opC: cutensorOperator_t,
1438        descD: cutensorTensorDescriptor_t,
1439        modeD: *const i32,
1440        descCompute: cutensorComputeDescriptor_t,
1441    ) -> cutensorStatus_t;
1442}
1443unsafe extern "C" {
1444    /// Frees all resources related to the provided descriptor.
1445    ///
1446    /// Remark
1447    ///
1448    /// blocking, no reentrant, and thread-safe.
1449    pub fn cutensorDestroyOperationDescriptor(
1450        desc: cutensorOperationDescriptor_t,
1451    ) -> cutensorStatus_t;
1452}
1453unsafe extern "C" {
1454    /// Set attribute of a cutensorOperationDescriptor_t object.
1455    ///
1456    /// Currently not supported for blocksparse contraction descriptors.
1457    ///
1458    /// # Parameters
1459    ///
1460    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1461    /// - `desc`: Operation descriptor that will be modified.
1462    /// - `attr`: Specifies the attribute that will be set.
1463    /// - `buf`: This buffer (of size `sizeInBytes`) determines the value to which `attr` will be set.
1464    /// - `sizeInBytes`: Size of buf (in bytes).
1465    ///
1466    /// # Return value
1467    ///
1468    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1469    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1470    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1471    pub fn cutensorOperationDescriptorSetAttribute(
1472        handle: cutensorHandle_t,
1473        desc: cutensorOperationDescriptor_t,
1474        attr: cutensorOperationDescriptorAttribute_t,
1475        buf: *const ::core::ffi::c_void,
1476        sizeInBytes: size_t,
1477    ) -> cutensorStatus_t;
1478}
1479unsafe extern "C" {
1480    /// This function retrieves an attribute of the provided cutensorOperationDescriptor_t object (see [`cutensorOperationDescriptorAttribute_t`]).
1481    ///
1482    /// Block-sparse contraction descriptors only support the attributes [`cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE`] and [`cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES`].
1483    ///
1484    /// # Parameters
1485    ///
1486    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1487    /// - `desc`: The cutensorOperationDescriptor_t object whos attribute is queried.
1488    /// - `attr`: Specifies the attribute that will be retrieved.
1489    /// - `buf`: This buffer (of size sizeInBytes) will hold the requested attribute of the provided cutensorOperationDescriptor_t object.
1490    /// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorOperationDescriptorAttribute_t`] for the exact size.
1491    ///
1492    /// # Return value
1493    ///
1494    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1495    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1496    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1497    pub fn cutensorOperationDescriptorGetAttribute(
1498        handle: cutensorHandle_t,
1499        desc: cutensorOperationDescriptor_t,
1500        attr: cutensorOperationDescriptorAttribute_t,
1501        buf: *mut ::core::ffi::c_void,
1502        sizeInBytes: size_t,
1503    ) -> cutensorStatus_t;
1504}
1505unsafe extern "C" {
1506    /// Allocates the cutensorPlanPreference_t, enabling users to limit the applicable kernels for a given plan/operation.
1507    ///
1508    /// # Parameters
1509    ///
1510    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1511    /// - `pref`: Pointer to the structure holding the [`cutensorPlanPreference_t`] allocated by this function. See [`cutensorPlanPreference_t`].
1512    /// - `algo`: Allows users to select a specific algorithm. [`cutensorAlgo_t::CUTENSOR_ALGO_DEFAULT`] lets the heuristic choose the algorithm. Any value >= 0 selects a specific GEMM-like algorithm and deactivates the heuristic. If a specified algorithm is not supported [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`] is returned. See [`cutensorAlgo_t`] for additional choices.
1513    /// - `jitMode`: Determines if cuTENSOR is allowed to use JIT-compiled kernels (leading to a longer plan-creation phase); see [`cutensorJitMode_t`].
1514    pub fn cutensorCreatePlanPreference(
1515        handle: cutensorHandle_t,
1516        pref: *mut cutensorPlanPreference_t,
1517        algo: cutensorAlgo_t,
1518        jitMode: cutensorJitMode_t,
1519    ) -> cutensorStatus_t;
1520}
1521unsafe extern "C" {
1522    /// Frees all resources related to the provided preference.
1523    ///
1524    /// Remark
1525    ///
1526    /// blocking, no reentrant, and thread-safe.
1527    pub fn cutensorDestroyPlanPreference(
1528        pref: cutensorPlanPreference_t,
1529    ) -> cutensorStatus_t;
1530}
1531unsafe extern "C" {
1532    /// Get attribute of a cutensorPlanPreference_t object.
1533    ///
1534    /// # Parameters
1535    ///
1536    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1537    /// - `pref`: This opaque struct restricts the search space of viable candidates.
1538    /// - `attr`: Requested attribute.
1539    /// - `buf`: On successful exit: Holds the information of the requested attribute.
1540    /// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorPlanPreferenceAttribute_t`] for the exact size.
1541    ///
1542    /// # Return value
1543    ///
1544    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1545    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1546    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1547    pub fn cutensorPlanPreferenceGetAttribute(
1548        handle: cutensorHandle_t,
1549        pref: cutensorPlanPreference_t,
1550        attr: cutensorPlanPreferenceAttribute_t,
1551        buf: *mut ::core::ffi::c_void,
1552        sizeInBytes: size_t,
1553    ) -> cutensorStatus_t;
1554}
1555unsafe extern "C" {
1556    /// Set attribute of a cutensorPlanPreference_t object.
1557    ///
1558    /// # Parameters
1559    ///
1560    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1561    /// - `pref`: This opaque struct restricts the search space of viable candidates.
1562    /// - `attr`: Specifies the attribute that will be set.
1563    /// - `buf`: This buffer (of size sizeInBytes) determines the value to which `attr` will be set.
1564    /// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorPlanPreferenceAttribute_t`] for the exact size.
1565    ///
1566    /// # Return value
1567    ///
1568    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1569    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1570    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1571    pub fn cutensorPlanPreferenceSetAttribute(
1572        handle: cutensorHandle_t,
1573        pref: cutensorPlanPreference_t,
1574        attr: cutensorPlanPreferenceAttribute_t,
1575        buf: *const ::core::ffi::c_void,
1576        sizeInBytes: size_t,
1577    ) -> cutensorStatus_t;
1578}
1579unsafe extern "C" {
1580    /// Retrieves information about an already-created plan (see [`cutensorPlanAttribute_t`])
1581    ///
1582    /// Block-sparse contraction plans only support [`cutensorPlanAttribute_t::CUTENSOR_PLAN_REQUIRED_WORKSPACE`].
1583    ///
1584    /// # Parameters
1585    ///
1586    /// - `plan`: Denotes an already-created plan (e.g., via [`cutensorCreatePlan`] or cutensorCreatePlanAutotuned).
1587    /// - `attr`: Requested attribute.
1588    /// - `buf`: On successful exit: Holds the information of the requested attribute.
1589    /// - `sizeInBytes`: size of `buf` in bytes.
1590    ///
1591    /// # Return value
1592    ///
1593    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1594    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1595    pub fn cutensorPlanGetAttribute(
1596        handle: cutensorHandle_t,
1597        plan: cutensorPlan_t,
1598        attr: cutensorPlanAttribute_t,
1599        buf: *mut ::core::ffi::c_void,
1600        sizeInBytes: size_t,
1601    ) -> cutensorStatus_t;
1602}
1603unsafe extern "C" {
1604    /// Determines the required workspaceSize for the given operation encoded by `desc`.
1605    ///
1606    /// # Parameters
1607    ///
1608    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1609    /// - `desc`: This opaque struct encodes the operation.
1610    /// - `planPref`: This opaque struct restricts the space of viable candidates.
1611    /// - `workspacePref`: This parameter influences the size of the workspace; see [`cutensorWorksizePreference_t`] for details.
1612    /// - `workspaceSizeEstimate`: The workspace size (in bytes) that is required for the given operation.
1613    ///
1614    /// # Return value
1615    ///
1616    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1617    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1618    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1619    pub fn cutensorEstimateWorkspaceSize(
1620        handle: cutensorHandle_t,
1621        desc: cutensorOperationDescriptor_t,
1622        planPref: cutensorPlanPreference_t,
1623        workspacePref: cutensorWorksizePreference_t,
1624        workspaceSizeEstimate: *mut u64,
1625    ) -> cutensorStatus_t;
1626}
1627unsafe extern "C" {
1628    /// This function allocates a cutensorPlan_t object, selects an appropriate kernel for a given operation (encoded by `desc`) and prepares a plan that encodes the execution.
1629    ///
1630    /// This function applies cuTENSOR’s heuristic to select a candidate/kernel for a given operation (created by either [`cutensorCreateContraction`], [`cutensorCreateReduction`], [`cutensorCreatePermutation`], [`cutensorCreateElementwiseBinary`], [`cutensorCreateElementwiseTrinary`], [`cutensorCreateContractionTrinary`], or [`cutensorCreateBlockSparseContraction`]). The created plan can then be passed to either [`cutensorContract`], [`cutensorReduce`], [`cutensorPermute`], [`cutensorElementwiseBinaryExecute`], [`cutensorElementwiseTrinaryExecute`], or [`cutensorContractTrinary`] to perform the actual operation.
1631    ///
1632    /// The plan is created for the active CUDA device.
1633    ///
1634    /// Note: [`cutensorCreatePlan`] must not be captured via CUDA graphs if Just-In-Time compilation is enabled (i.e., [`cutensorJitMode_t`] is not [`cutensorJitMode_t::CUTENSOR_JIT_MODE_NONE`]).
1635    ///
1636    /// # Parameters
1637    ///
1638    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1639    /// - `plan`: Pointer to the data structure created by this function that holds all information (e.g., selected kernel) necessary to perform the desired operation.
1640    /// - `desc`: This opaque struct encodes the given operation (see [`cutensorCreateContraction`], [`cutensorCreateReduction`], [`cutensorCreatePermutation`], [`cutensorCreateElementwiseBinary`], [`cutensorCreateElementwiseTrinary`], or [`cutensorCreateContractionTrinary`]).
1641    /// - `pref`: This opaque struct is used to restrict the space of applicable candidates/kernels (see [`cutensorCreatePlanPreference`] or [`cutensorPlanPreferenceAttribute_t`]). May be `nullptr`, in that case default choices are assumed. Block-sparse contractions currently only support these default settings and ignore other supplied preferences.
1642    /// - `workspaceSizeLimit`: Denotes the maximal workspace that the corresponding operation is allowed to use (see [`cutensorEstimateWorkspaceSize`]).
1643    ///
1644    /// # Return value
1645    ///
1646    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE`]: if the provided workspace was insufficient.
1647    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1648    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1649    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: If no viable candidate could be found.
1650    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: If a viable candidate has been found.
1651    pub fn cutensorCreatePlan(
1652        handle: cutensorHandle_t,
1653        plan: *mut cutensorPlan_t,
1654        desc: cutensorOperationDescriptor_t,
1655        pref: cutensorPlanPreference_t,
1656        workspaceSizeLimit: u64,
1657    ) -> cutensorStatus_t;
1658}
1659unsafe extern "C" {
1660    /// Frees all resources related to the provided plan.
1661    ///
1662    /// Remark
1663    ///
1664    /// blocking, no reentrant, and thread-safe.
1665    pub fn cutensorDestroyPlan(plan: cutensorPlan_t) -> cutensorStatus_t;
1666}
1667unsafe extern "C" {
1668    /// This routine computes the tensor contraction $D = alpha \\* A \\* B + beta \\* C$.
1669    /// $$
1670    /// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha \\* \mathcal{A}_{{modes}_\mathcal{A}} B_{{modes}_\mathcal{B}} + \beta \mathcal{C}_{{modes}_\mathcal{C}}
1671    /// $$
1672    ///
1673    /// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
1674    ///
1675    /// **\[Example\]**
1676    /// :   See [NVIDIA/CUDALibrarySamples](https://github.com/NVIDIA/CUDALibrarySamples/tree/master/cuTENSOR/contraction.cu) for a concrete example.
1677    ///
1678    /// # Parameters
1679    ///
1680    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1681    /// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateContraction`] followed by [`cutensorCreatePlan`]).
1682    /// - `alpha`: Scaling for A\*B. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1683    /// - `A`: Pointer to the data corresponding to A. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1684    /// - `B`: Pointer to the data corresponding to B. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1685    /// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1686    /// - `C`: Pointer to the data corresponding to C. Pointer to the GPU-accessible memory.
1687    /// - `D`: Pointer to the data corresponding to D. Pointer to the GPU-accessible memory.
1688    /// - `workspace`: Optional parameter that may be NULL. This pointer provides additional workspace, in device memory, to the library for additional optimizations; the workspace must be aligned to 256 bytes (i.e., the default alignment of cudaMalloc).
1689    /// - `workspaceSize`: Size of the workspace array in bytes; please refer to [`cutensorEstimateWorkspaceSize`] to query the required workspace. While [`cutensorContract`] does not strictly require a workspace for the contraction, it is still recommended to provide some small workspace (e.g., 128 MB).
1690    /// - `stream`: The CUDA stream in which all the computation is performed.
1691    ///
1692    /// # Return value
1693    ///
1694    /// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
1695    /// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
1696    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
1697    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1698    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1699    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
1700    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1701    pub fn cutensorContract(
1702        handle: cutensorHandle_t,
1703        plan: cutensorPlan_t,
1704        alpha: *const ::core::ffi::c_void,
1705        A: *const ::core::ffi::c_void,
1706        B: *const ::core::ffi::c_void,
1707        beta: *const ::core::ffi::c_void,
1708        C: *const ::core::ffi::c_void,
1709        D: *mut ::core::ffi::c_void,
1710        workspace: *mut ::core::ffi::c_void,
1711        workspaceSize: u64,
1712        stream: cudaStream_t,
1713    ) -> cutensorStatus_t;
1714}
1715unsafe extern "C" {
1716    /// Creates a cutensorOperatorDescriptor_t object that encodes a tensor reduction of the form $D = alpha \\* opReduce(opA(A)) + beta \\* opC(C)$.
1717    ///
1718    /// For example this function enables users to reduce an entire tensor to a scalar: C[] = alpha \* A\[i,j,k\];
1719    ///
1720    /// This function is also able to perform partial reductions; for instance: C\[i,j\] = alpha \* A\[k,j,i\]; in this case only elements along the k-mode are contracted.
1721    ///
1722    /// The binary opReduce operator provides extra control over what kind of a reduction ought to be performed. For instance, setting opReduce to [`cutensorOperator_t::CUTENSOR_OP_ADD`] reduces element of A via a summation while [`cutensorOperator_t::CUTENSOR_OP_MAX`] would find the largest element in A.
1723    ///
1724    /// Supported data-type combinations are:
1725    ///
1726    /// | typeA | typeB | typeC | typeCompute |
1727    /// | --- | --- | --- | --- |
1728    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
1729    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1730    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
1731    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1732    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1733    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1734    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
1735    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
1736    ///
1737    /// # Parameters
1738    ///
1739    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1740    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested tensor reduction operation.
1741    /// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
1742    /// - `modeA`: Array with ‘nmodeA’ entries that represent the modes of A. modeA\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to [`cutensorCreateTensorDescriptor`]. Modes that only appear in modeA but not in modeC are reduced (contracted).
1743    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1744    /// - `descC`: The descriptor that holds the information about the data type, modes and strides of C.
1745    /// - `modeC`: Array with ‘nmodeC’ entries that represent the modes of C. modeC\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to [`cutensorCreateTensorDescriptor`].
1746    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged.
1747    /// - `descD`: Must be identical to descC for now.
1748    /// - `modeD`: Must be identical to modeC for now.
1749    /// - `opReduce`: binary operator used to reduce elements of A.
1750    ///
1751    /// # Return value
1752    ///
1753    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1754    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1755    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
1756    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1757    pub fn cutensorCreateReduction(
1758        handle: cutensorHandle_t,
1759        desc: *mut cutensorOperationDescriptor_t,
1760        descA: cutensorTensorDescriptor_t,
1761        modeA: *const i32,
1762        opA: cutensorOperator_t,
1763        descC: cutensorTensorDescriptor_t,
1764        modeC: *const i32,
1765        opC: cutensorOperator_t,
1766        descD: cutensorTensorDescriptor_t,
1767        modeD: *const i32,
1768        opReduce: cutensorOperator_t,
1769        descCompute: cutensorComputeDescriptor_t,
1770    ) -> cutensorStatus_t;
1771}
1772unsafe extern "C" {
1773    /// Performs the tensor reduction that is encoded by `plan` (see [`cutensorCreateReduction`]).
1774    ///
1775    /// # Parameters
1776    ///
1777    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1778    /// - `plan`: Opaque handle holding the reduction execution plan (created by [`cutensorCreateReduction`] followed by [`cutensorCreatePlan`]).
1779    /// - `alpha`: Scaling for A. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1780    /// - `A`: Pointer to the data corresponding to A in device memory. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to D.
1781    /// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1782    /// - `C`: Pointer to the data corresponding to C in device memory. Pointer to the GPU-accessible memory.
1783    /// - `D`: Pointer to the data corresponding to C in device memory. Pointer to the GPU-accessible memory.
1784    /// - `workspace`: Scratchpad (device) memory of size —at least— `workspaceSize` bytes; the workspace must be aligned to 256 bytes (i.e., the default alignment of cudaMalloc).
1785    /// - `workspaceSize`: Please use [`cutensorEstimateWorkspaceSize`] to query the required workspace.
1786    /// - `stream`: The CUDA stream in which all the computation is performed.
1787    pub fn cutensorReduce(
1788        handle: cutensorHandle_t,
1789        plan: cutensorPlan_t,
1790        alpha: *const ::core::ffi::c_void,
1791        A: *const ::core::ffi::c_void,
1792        beta: *const ::core::ffi::c_void,
1793        C: *const ::core::ffi::c_void,
1794        D: *mut ::core::ffi::c_void,
1795        workspace: *mut ::core::ffi::c_void,
1796        workspaceSize: u64,
1797        stream: cudaStream_t,
1798    ) -> cutensorStatus_t;
1799}
1800unsafe extern "C" {
1801    /// This function allocates a cutensorOperationDescriptor_t object that encodes a tensor contraction of the form $\mathcal{E} = \alpha \mathcal{A} \mathcal{B} \mathcal{C} + \beta \mathcal{D}$.
1802    ///
1803    /// Allocates data for `desc` to be used to perform a tensor contraction of the form:
1804    /// $$
1805    /// \mathcal{E}_{{modes}_\mathcal{E}} \gets \alpha op_\mathcal{A}(\mathcal{A}_{{modes}_\mathcal{A}}) op_\mathcal{B}(\mathcal{B}_{{modes}_\mathcal{B}}) op_\mathcal{C}(\mathcal{C}_{{modes}_\mathcal{C}}) + \beta op_\mathcal{D}(\mathcal{D}_{{modes}_\mathcal{D}}).
1806    /// $$
1807    ///
1808    /// See [`cutensorCreatePlan`] (or cutensorCreatePlanAutotuned) to create the plan (i.e., to select the kernel) followed by a call to [`cutensorContractTrinary`] to perform the actual contraction.
1809    ///
1810    /// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
1811    ///
1812    /// The performance improvements due to this API are currently especially high if your data resides on the host (i.e. out-of-core), targeting Grace-based systems.
1813    ///
1814    /// Supported data-type combinations are:
1815    ///
1816    /// | typeA | typeB | typeC | typeD | descCompute |  | typeScalar | Tensor Core |  |
1817    /// | --- | --- | --- | --- | --- | --- | --- | --- | --- |
1818    /// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_R_32F`] | Volta+ |  |
1819    /// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |  |
1820    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_R_32F`] | No |  |
1821    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_TF32`] |  | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |  |
1822    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_3XTF32`] |  | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |  |
1823    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |  | [`cudaDataType_t::CUDA_R_32F`] | Ampere+ |  |
1824    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |  | [`cudaDataType_t::CUDA_R_32F`] | Volta+ |  |
1825    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |  | [`cudaDataType_t::CUDA_R_64F`] | Ampere+ |  |
1826    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_R_64F`] | No |  |
1827    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_C_32F`] | No |  |
1828    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_TF32`] |  | [`cudaDataType_t::CUDA_C_32F`] | Ampere+ |  |
1829    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_3XTF32`] |  | [`cudaDataType_t::CUDA_C_32F`] | Ampere+ |  |
1830    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |  | [`cudaDataType_t::CUDA_C_64F`] | Ampere+ |  |
1831    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |  | [`cudaDataType_t::CUDA_C_64F`] | No |  |
1832    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_8XINT8`] |  |  | [`cudaDataType_t::CUDA_R_64F`] | Hopper+ |
1833    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_8XINT8`] |  |  | [`cudaDataType_t::CUDA_C_64F`] | Hopper+ |
1834    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_9X16BF`] |  |  | [`cudaDataType_t::CUDA_R_32F`] | Hopper+ |
1835    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_9X16BF`] |  |  | [`cudaDataType_t::CUDA_C_32F`] | Hopper+ |
1836    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_4X16F`] |  |  | [`cudaDataType_t::CUDA_R_32F`] | Blackwell+ |
1837    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_4X16F`] |  |  | [`cudaDataType_t::CUDA_C_32F`] | Blackwell+ |
1838    ///
1839    /// # Parameters
1840    ///
1841    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1842    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
1843    /// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
1844    /// - `modeA`: Array with ‘nmodeA’ entries that represent the modes of A. The modeA\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1845    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged.
1846    /// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
1847    /// - `modeB`: Array with ‘nmodeB’ entries that represent the modes of B. The modeB\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1848    /// - `opB`: Unary operator that will be applied to each element of B before it is further processed. The original data of this tensor remains unchanged.
1849    /// - `descC`: The escriptor that holds information about the data type, modes, and strides of C.
1850    /// - `modeC`: Array with ‘nmodeC’ entries that represent the modes of C. The modeC\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1851    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged.
1852    /// - `descD`: The escriptor that holds information about the data type, modes, and strides of D.
1853    /// - `modeD`: Array with ‘nmodeD’ entries that represent the modes of D. The modeD\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1854    /// - `opD`: Unary operator that will be applied to each element of D before it is further processed. The original data of this tensor remains unchanged.
1855    /// - `descE`: The descriptor that holds information about the data type, modes, and strides of E (must be identical to `descD` for now).
1856    /// - `modeE`: Array with ‘nmodeE’ entries that represent the modes of E (must be identical to modeD for now). The modeE\[i\] corresponds to extent\[i\] and stride\[i\] with respect to the arguments provided to cutensorInitTensorDescriptor.
1857    /// - `descCompute`: Determines the precision in which this operations is performed.
1858    ///
1859    /// # Return value
1860    ///
1861    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
1862    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1863    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
1864    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
1865    pub fn cutensorCreateContractionTrinary(
1866        handle: cutensorHandle_t,
1867        desc: *mut cutensorOperationDescriptor_t,
1868        descA: cutensorTensorDescriptor_t,
1869        modeA: *const i32,
1870        opA: cutensorOperator_t,
1871        descB: cutensorTensorDescriptor_t,
1872        modeB: *const i32,
1873        opB: cutensorOperator_t,
1874        descC: cutensorTensorDescriptor_t,
1875        modeC: *const i32,
1876        opC: cutensorOperator_t,
1877        descD: cutensorTensorDescriptor_t,
1878        modeD: *const i32,
1879        opD: cutensorOperator_t,
1880        descE: cutensorTensorDescriptor_t,
1881        modeE: *const i32,
1882        descCompute: cutensorComputeDescriptor_t,
1883    ) -> cutensorStatus_t;
1884}
1885unsafe extern "C" {
1886    /// This routine computes the tensor contraction $E = alpha \\* A \\* B \\* C + beta \\* D$.
1887    /// $$
1888    /// \mathcal{E}_{{modes}_\mathcal{E}} \gets \alpha \\* \mathcal{A}_{{modes}_\mathcal{A}} \mathcal{B}_{{modes}_\mathcal{B}} \mathcal{C}_{{modes}_\mathcal{C}} + \beta \mathcal{D}_{{modes}_\mathcal{D}}
1889    /// $$
1890    ///
1891    /// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
1892    ///
1893    /// **\[Example\]**
1894    /// :   See [NVIDIA/CUDALibrarySamples](https://github.com/NVIDIA/CUDALibrarySamples/tree/master/cuTENSOR/contraction_trinary.cu) for a concrete example.
1895    ///
1896    /// # Parameters
1897    ///
1898    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
1899    /// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateContractionTrinary`] followed by [`cutensorCreatePlan`]).
1900    /// - `alpha`: Scaling for A\*B\*C. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1901    /// - `A`: Pointer to the data corresponding to A. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to E.
1902    /// - `B`: Pointer to the data corresponding to B. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to E.
1903    /// - `C`: Pointer to the data corresponding to C. Pointer to the GPU-accessible memory. The data accessed via this pointer must not overlap with the elements written to E.
1904    /// - `beta`: Scaling for D. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
1905    /// - `D`: Pointer to the data corresponding to D. Pointer to the GPU-accessible memory.
1906    /// - `E`: Pointer to the data corresponding to E. Pointer to the GPU-accessible memory.
1907    /// - `workspace`: Optional parameter that may be NULL. This pointer provides additional workspace, in device memory, to the library for additional optimizations; the workspace must be aligned to 256 bytes (i.e., the default alignment of cudaMalloc).
1908    /// - `workspaceSize`: Size of the workspace array in bytes; please refer to [`cutensorEstimateWorkspaceSize`] to query the required workspace. While [`cutensorContract`] does not strictly require a workspace for the contraction, it is still recommended to provide some small workspace (e.g., 128 MB).
1909    /// - `stream`: The CUDA stream in which all the computation is performed.
1910    ///
1911    /// # Return value
1912    ///
1913    /// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
1914    /// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
1915    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
1916    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
1917    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
1918    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
1919    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
1920    pub fn cutensorContractTrinary(
1921        handle: cutensorHandle_t,
1922        plan: cutensorPlan_t,
1923        alpha: *const ::core::ffi::c_void,
1924        A: *const ::core::ffi::c_void,
1925        B: *const ::core::ffi::c_void,
1926        C: *const ::core::ffi::c_void,
1927        beta: *const ::core::ffi::c_void,
1928        D: *const ::core::ffi::c_void,
1929        E: *mut ::core::ffi::c_void,
1930        workspace: *mut ::core::ffi::c_void,
1931        workspaceSize: u64,
1932        stream: cudaStream_t,
1933    ) -> cutensorStatus_t;
1934}
1935unsafe extern "C" {
1936    /// Create a block-sparse tensor descriptor.
1937    ///
1938    /// A block-sparse tensor descriptor fully specifies the data layout of a block-sparse tensor (currently limited to up to 8 modes).
1939    ///
1940    /// Let us consider an example for a block-sparse tensor of order 2, i.e., a block-sparse matrix `A`. Its first mode (`rows`) is subdivided into 5 sections (with extents 4, 2, 3, 4, 5, respectively), and its second mode (`columns`) is subdivided into 3 sections (with extents 2, 3, 7). The matrix has 8 non-zero blocks:
1941    ///
1942    /// |  |  |  |
1943    /// | --- | --- | --- |
1944    /// | 4 x 2 |  | 4 x 7 |
1945    /// |  | 2 x 3 |  |
1946    /// |  | 3 x 3 | 3 x 7 |
1947    /// | 4 x 2 |  |  |
1948    /// |  | 5 x 3 | 5 x 7 |
1949    ///
1950    /// Notice that we require the same extent of each sub section across the entire mode, i.e., every block within the same section of a mode has the same extent. For example, in the above picture every block on the right has 7 colums, and all blocks on the bottom have 5 rows.
1951    ///
1952    /// Moreover, we only store the non-zero blocks (blocks that are zero are left blank in the above representation).
1953    ///
1954    /// To be precise, the above block-sparse tensor could be created via:
1955    ///
1956    /// As an example:
1957    ///
1958    /// * strides of block #0: 5, 1, 10, 20. Sorted strides would be: 1, 5, 10, 20. The permutation to sort the strides in this case is to swap the first two elements.
1959    /// * strides of block #1: 10, 1, 30, 60. Applying the permutation would result in: 1, 10, 30, 60. The result is sorted in ascending order, this is allowed.
1960    /// * strides of block #2: 1, 5, 50, 100. Applying permuation would result in: 5, 1, 50, 100. The result is `not` sorted in ascending order, this is `not` allowed.
1961    ///
1962    ///   Remark
1963    ///
1964    ///   non-blocking, no reentrant, and thread-safe.
1965    ///
1966    /// # Parameters
1967    ///
1968    /// - `handle`: The library handle.
1969    /// - `desc`: The resulting block-sparse tensor descriptor.
1970    /// - `numModes`: The number of modes. Currently, a maximum of 8 modes is supported.
1971    /// - `numNonZeroBlocks`: The number of non-zero blocks in the block-sparse tensor.
1972    /// - `numSectionsPerMode`: The number of sections of each mode (host array of size `numModes`).
1973    /// - `extent`: The extents of the sections of each mode (host array of size `\sum_i^numModes(numSectionsPerMode\[i\])`). First come the extents of the sections of the first mode, then the extents of the sections of the second mode, and so forth.
1974    /// - `nonZeroCoordinates`: Block-coordinates of each non-zero block (host array of size `numModes` x `numNonZeroBlocks` Blocks can be specified in any order, however, that order must be consistent with stride and alignmentRequirement arrays.
1975    /// - `stride`: The strides of each dense block (either nullptr or a host array of size `numModes` x `numNonZeroBlocks`). First the strides of the first block, then the strides of the second block, with the blocks in the same order as in nonZeroCoordinates. Passing nullptr means contiguous column-major order for each block. Moreover, the strides need to be compatible in the following sense: Suppose you sort the strides of the first block, such that they are ascending; this sorting results in a permutation. If you apply this permutation to the strides of any other block, the result needs to be sorted as well.
1976    /// - `dataType`: Data type of the stored entries. We assume the same datatype for each block. Currently, the only supported values are [`cudaDataType_t::CUDA_C_64F`], [`cudaDataType_t::CUDA_C_32F`], [`cudaDataType_t::CUDA_R_64F`], and [`cudaDataType_t::CUDA_R_32F`].
1977    pub fn cutensorCreateBlockSparseTensorDescriptor(
1978        handle: cutensorHandle_t,
1979        desc: *mut cutensorBlockSparseTensorDescriptor_t,
1980        numModes: u32,
1981        numNonZeroBlocks: u64,
1982        numSectionsPerMode: *const u32,
1983        extent: *const i64,
1984        nonZeroCoordinates: *const i32,
1985        stride: *const i64,
1986        dataType: cudaDataType_t,
1987    ) -> cutensorStatus_t;
1988}
1989unsafe extern "C" {
1990    /// Frees all resources related to the provided block-sparse tensor descriptor.
1991    ///
1992    /// Remark
1993    ///
1994    /// blocking, no reentrant, and thread-safe.
1995    pub fn cutensorDestroyBlockSparseTensorDescriptor(
1996        desc: cutensorBlockSparseTensorDescriptor_t,
1997    ) -> cutensorStatus_t;
1998}
1999unsafe extern "C" {
2000    /// This function allocates a cutensorOperationDescriptor_t object that encodes a block-sparse tensor contraction of the form $D = \alpha \mathcal{A} \mathcal{B} + \beta \mathcal{C}$.
2001    ///
2002    /// Allocates data for `desc` to be used to perform a block-sparse tensor contraction of the form:
2003    /// $$
2004    /// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha op_\mathcal{A}(\mathcal{A}_{{modes}_\mathcal{A}}) op_\mathcal{B}(B_{{modes}_\mathcal{B}}) + \beta op_\mathcal{C}(\mathcal{C}_{{modes}_\mathcal{C}}).
2005    /// $$
2006    ///
2007    /// Only the predefined non-zero blocks of $\mathcal{D}$ that were specified in [`cutensorCreateBlockSparseTensorDescriptor`] are actually computed. The other blocks are omitted, even if the true result of the contraction would be non-zero. Conversely, if a predefined non-zero block of $\mathcal{D}$ is present, but the result of the contraction is zero for this block, explicit zeros will be stored.
2008    ///
2009    /// Currently, the data-types for the tensors `A`, `B`, `C`, and `D`, as well as the scalars $\alpha$ and $\beta$ must all be identical, and the only supported types are [`cudaDataType_t::CUDA_C_64F`], [`cudaDataType_t::CUDA_C_32F`], [`cudaDataType_t::CUDA_R_64F`], and [`cudaDataType_t::CUDA_R_32F`]. The compute-type needs to match as well, that is, we currently only support:
2010    ///
2011    /// | typeA | typeB | typeC | typeD | descCompute | typeScalar |
2012    /// | --- | --- | --- | --- | --- | --- |
2013    /// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_R_32F`] |
2014    /// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_R_64F`] |
2015    /// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] | [`cudaDataType_t::CUDA_C_32F`] |
2016    /// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] | [`cudaDataType_t::CUDA_C_64F`] |
2017    ///
2018    /// For every mode, the segmentation of that mode must be identical in all tensors that it occurs in. For example, if modeA\[i\] = modeB\[j\] for some i and j, then numSectionsPerMode\[i\] of tensor A must have the same value as numSectionsPerMode\[j\] of tensor B, and the corresponding section extents must be identical.
2019    ///
2020    /// For example, let A, B, and C be block matrices and consider the ordinary matrix-matrix product $C_{mn}=A_{mk}B_{kn}$. Then:
2021    ///
2022    /// * Mode ‘m’: C and A need to have the same number of block-rows, and each block-row of C needs to contain the same number of rows as the corresponding block-row of A.
2023    /// * Mode ‘n’: C and B need to have the same number of block-columns of matching size
2024    /// * Mode ‘k’: A needs to have the same number of block-columns as B has block-rows, and each block-column of A needs to consist of the same number of columns as the number of rows in the corresponding block-row of B.
2025    ///
2026    /// At the moment, descC and descD must be identical, i.e., the same opaque pointer needs to be passed and the layouts of the C and the D tensors need to be identical.
2027    ///
2028    /// See [`cutensorCreatePlan`] to create the plan, [`cutensorEstimateWorkspaceSize`] to compute the required workspace, and finally [`cutensorBlockSparseContract`] to perform the actual contraction.
2029    ///
2030    /// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
2031    ///
2032    /// # Parameters
2033    ///
2034    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
2035    /// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
2036    /// - `descA`: The descriptor that holds the information about the data type, modes, sections, section extents, strides, and non-zero blocks of A.
2037    /// - `modeA`: Array with ‘nmodeA’ entries that represent the modes of A. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
2038    /// - `opA`: Unary operator that will be applied to each element of A before it is further processed. The original data of this tensor remains unchanged. Currently, only [`cutensorOperator_t::CUTENSOR_OP_IDENTITY`] is supported.
2039    /// - `descB`: The descriptor that holds information about the data type, modes, sections, section extents, strides, and non-zero blocks of B.
2040    /// - `modeB`: Array with ‘nmodeB’ entries that represent the modes of B. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
2041    /// - `opB`: Unary operator that will be applied to each element of B before it is further processed. The original data of this tensor remains unchanged. Currently, only [`cutensorOperator_t::CUTENSOR_OP_IDENTITY`] is supported.
2042    /// - `descC`: The descriptor that holds information about the data type, modes, sections, section extents, strides, and non-zero blocks of C. Note that the block-sparsity pattern of C (the nonZeroCoordinates[] array used to create the decriptor) of C must be identical to that of D; and it is this block-sparsity pattern that determines which parts of the results are computed; no fill-in is allocated or computed.
2043    /// - `modeC`: Array with ‘nmodeC’ entries that represent the modes of C. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
2044    /// - `opC`: Unary operator that will be applied to each element of C before it is further processed. The original data of this tensor remains unchanged. Currently, only [`cutensorOperator_t::CUTENSOR_OP_IDENTITY`] is supported.
2045    /// - `descD`: For now, this must be the same opaque pointer as descC, and the layouts of C and D must be identical.
2046    /// - `modeD`: Array with ‘nmodeD’ entries that represent the modes of D (must be identical to modeC for now).
2047    ///
2048    /// # Return value
2049    ///
2050    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes or section sizes have an illegal value.
2051    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
2052    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
2053    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
2054    pub fn cutensorCreateBlockSparseContraction(
2055        handle: cutensorHandle_t,
2056        desc: *mut cutensorOperationDescriptor_t,
2057        descA: cutensorBlockSparseTensorDescriptor_t,
2058        modeA: *const i32,
2059        opA: cutensorOperator_t,
2060        descB: cutensorBlockSparseTensorDescriptor_t,
2061        modeB: *const i32,
2062        opB: cutensorOperator_t,
2063        descC: cutensorBlockSparseTensorDescriptor_t,
2064        modeC: *const i32,
2065        opC: cutensorOperator_t,
2066        descD: cutensorBlockSparseTensorDescriptor_t,
2067        modeD: *const i32,
2068        descCompute: cutensorComputeDescriptor_t,
2069    ) -> cutensorStatus_t;
2070}
2071unsafe extern "C" {
2072    /// This routine computes the block-sparse tensor contraction $D = alpha \\* A \\* B + beta \\* C$.
2073    /// $$
2074    /// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha \\* \mathcal{A}_{{modes}_\mathcal{A}} B_{{modes}_\mathcal{B}} + \beta \mathcal{C}_{{modes}_\mathcal{C}}
2075    /// $$
2076    ///
2077    /// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
2078    ///
2079    /// The array-parameters `A`, `B`, `C`, and `D` are host-arrays containing pointers to GPU-accessible memory. For example, `A` is a host-array whose size equals the number of non-zero blocks in tensor $\mathcal{A}$. `A\[i\]` is a pointer to the GPU-accessible memory location of block number `i` of $\mathcal{A}$. The blocks are numbered in the same way as in the construction of $\mathcal{A}$’s block-sparse tensor descriptor. The same analogously holds for the other array-parameters `B`, `C`, and `D`.
2080    ///
2081    /// # Parameters
2082    ///
2083    /// - `handle`: Opaque handle holding cuTENSOR’s library context.
2084    /// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateBlockSparseContraction`] followed by [`cutensorCreatePlan`]).
2085    /// - `alpha`: Scaling for A\*B. Its data type is determined by ‘descCompute’ (see [`cutensorCreateBlockSparseContraction`]). Pointer to host memory.
2086    /// - `A`: Host-array of size numNonZeroBlocks(A), containing pointers to GPU-accessible memory, corresponding the blocks of A. The data accessed via these pointers must not overlap with the elements written to D.
2087    /// - `B`: Host-array of size numNonZeroBlocks(B), containing pointers to GPU-accessible memory, corresponding the blocks of B. The data accessed via these pointers must not overlap with the elements written to D.
2088    /// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see [`cutensorCreateBlockSparseContraction`]). Pointer to host memory.
2089    /// - `C`: Host-array of size numNonZeroBlocks(C), containing pointers to GPU-accessible memory, corresponding the blocks of C.
2090    /// - `D`: Host-array of size numNonZeroBlocks(D), containing pointers to GPU-accessible memory, corresponding the blocks of D.
2091    /// - `workspace`: This pointer provides the required workspace in device memory. The workspace must be aligned to 256 bytes (i.e., the default alignment of cudaMalloc).
2092    /// - `workspaceSize`: Size of the workspace array in bytes; please refer to [`cutensorEstimateWorkspaceSize`] to query the required workspace. For block-sparse contractions, this estimate is exact.
2093    /// - `stream`: The CUDA stream to which all of the computation is synchronised.
2094    ///
2095    /// # Return value
2096    ///
2097    /// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
2098    /// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
2099    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
2100    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
2101    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
2102    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
2103    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
2104    pub fn cutensorBlockSparseContract(
2105        handle: cutensorHandle_t,
2106        plan: cutensorPlan_t,
2107        alpha: *const ::core::ffi::c_void,
2108        A: *const *const ::core::ffi::c_void,
2109        B: *const *const ::core::ffi::c_void,
2110        beta: *const ::core::ffi::c_void,
2111        C: *const *const ::core::ffi::c_void,
2112        D: *const *mut ::core::ffi::c_void,
2113        workspace: *mut ::core::ffi::c_void,
2114        workspaceSize: u64,
2115        stream: cudaStream_t,
2116    ) -> cutensorStatus_t;
2117}
2118unsafe extern "C" {
2119    /// Returns the description string for an error code.
2120    ///
2121    /// Remark
2122    ///
2123    /// non-blocking, no reentrant, and thread-safe.
2124    pub fn cutensorGetErrorString(error: cutensorStatus_t) -> *const ::core::ffi::c_char;
2125}
2126unsafe extern "C" {
2127    /// Returns Version number of the CUTENSOR library.
2128    pub fn cutensorGetVersion() -> size_t;
2129}
2130unsafe extern "C" {
2131    /// Returns version number of the CUDA runtime that cuTENSOR was compiled against.
2132    ///
2133    /// Can be compared against the CUDA runtime version from cudaRuntimeGetVersion().
2134    pub fn cutensorGetCudartVersion() -> size_t;
2135}
2136unsafe extern "C" {
2137    /// This function sets the logging callback routine.
2138    pub fn cutensorLoggerSetCallback(
2139        callback: cutensorLoggerCallback_t,
2140    ) -> cutensorStatus_t;
2141}
2142unsafe extern "C" {
2143    /// This function sets the logging output file.
2144    pub fn cutensorLoggerSetFile(file: *mut FILE) -> cutensorStatus_t;
2145}
2146unsafe extern "C" {
2147    /// This function opens a logging output file in the given path.
2148    pub fn cutensorLoggerOpenFile(
2149        logFile: *const ::core::ffi::c_char,
2150    ) -> cutensorStatus_t;
2151}
2152unsafe extern "C" {
2153    /// This function sets the value of the logging level.
2154    pub fn cutensorLoggerSetLevel(level: i32) -> cutensorStatus_t;
2155}
2156unsafe extern "C" {
2157    /// This function sets the value of the log mask.
2158    pub fn cutensorLoggerSetMask(mask: i32) -> cutensorStatus_t;
2159}
2160unsafe extern "C" {
2161    /// This function disables logging for the entire run.
2162    pub fn cutensorLoggerForceDisable() -> cutensorStatus_t;
2163}