/* automatically generated by rust-bindgen 0.72.1 */
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
storage: Storage,
}
impl<Storage> __BindgenBitfieldUnit<Storage> {
#[inline]
pub const fn new(storage: Storage) -> Self {
Self { storage }
}
}
impl<Storage> __BindgenBitfieldUnit<Storage>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
#[inline]
fn extract_bit(byte: u8, index: usize) -> bool {
let bit_index = if cfg!(target_endian = "big") {
7 - (index % 8)
} else {
index % 8
};
let mask = 1 << bit_index;
byte & mask == mask
}
#[inline]
pub fn get_bit(&self, index: usize) -> bool {
debug_assert!(index / 8 < self.storage.as_ref().len());
let byte_index = index / 8;
let byte = self.storage.as_ref()[byte_index];
Self::extract_bit(byte, index)
}
#[inline]
pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool {
debug_assert!(index / 8 < core::mem::size_of::< Storage > ());
let byte_index = index / 8;
let byte = unsafe {
*(core::ptr::addr_of!((* this).storage) as *const u8)
.offset(byte_index as isize)
};
Self::extract_bit(byte, index)
}
#[inline]
fn change_bit(byte: u8, index: usize, val: bool) -> u8 {
let bit_index = if cfg!(target_endian = "big") {
7 - (index % 8)
} else {
index % 8
};
let mask = 1 << bit_index;
if val { byte | mask } else { byte & !mask }
}
#[inline]
pub fn set_bit(&mut self, index: usize, val: bool) {
debug_assert!(index / 8 < self.storage.as_ref().len());
let byte_index = index / 8;
let byte = &mut self.storage.as_mut()[byte_index];
*byte = Self::change_bit(*byte, index, val);
}
#[inline]
pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) {
debug_assert!(index / 8 < core::mem::size_of::< Storage > ());
let byte_index = index / 8;
let byte = unsafe {
(core::ptr::addr_of_mut!((* this).storage) as *mut u8)
.offset(byte_index as isize)
};
unsafe { *byte = Self::change_bit(*byte, index, val) };
}
#[inline]
pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
debug_assert!(bit_width <= 64);
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
debug_assert!(
(bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()
);
let mut val = 0;
for i in 0..(bit_width as usize) {
if self.get_bit(i + bit_offset) {
let index = if cfg!(target_endian = "big") {
bit_width as usize - 1 - i
} else {
i
};
val |= 1 << index;
}
}
val
}
#[inline]
pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 {
debug_assert!(bit_width <= 64);
debug_assert!(bit_offset / 8 < core::mem::size_of::< Storage > ());
debug_assert!(
(bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::< Storage > ()
);
let mut val = 0;
for i in 0..(bit_width as usize) {
if unsafe { Self::raw_get_bit(this, i + bit_offset) } {
let index = if cfg!(target_endian = "big") {
bit_width as usize - 1 - i
} else {
i
};
val |= 1 << index;
}
}
val
}
#[inline]
pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
debug_assert!(bit_width <= 64);
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
debug_assert!(
(bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()
);
for i in 0..(bit_width as usize) {
let mask = 1 << i;
let val_bit_is_set = val & mask == mask;
let index = if cfg!(target_endian = "big") {
bit_width as usize - 1 - i
} else {
i
};
self.set_bit(index + bit_offset, val_bit_is_set);
}
}
#[inline]
pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) {
debug_assert!(bit_width <= 64);
debug_assert!(bit_offset / 8 < core::mem::size_of::< Storage > ());
debug_assert!(
(bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::< Storage > ()
);
for i in 0..(bit_width as usize) {
let mask = 1 << i;
let val_bit_is_set = val & mask == mask;
let index = if cfg!(target_endian = "big") {
bit_width as usize - 1 - i
} else {
i
};
unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) };
}
}
}
pub const CUTENSOR_MAJOR: u32 = 2;
pub const CUTENSOR_MINOR: u32 = 6;
pub const CUTENSOR_PATCH: u32 = 0;
pub const CUTENSOR_VERSION: u32 = 20600;
pub type __uint64_t = ::core::ffi::c_ulong;
pub type __off_t = ::core::ffi::c_long;
pub type __off64_t = ::core::ffi::c_long;
pub type size_t = ::core::ffi::c_ulong;
pub type FILE = _IO_FILE;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _IO_marker {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _IO_codecvt {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _IO_wide_data {
_unused: [u8; 0],
}
pub type _IO_lock_t = ::core::ffi::c_void;
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct _IO_FILE {
pub _flags: ::core::ffi::c_int,
pub _IO_read_ptr: *mut ::core::ffi::c_char,
pub _IO_read_end: *mut ::core::ffi::c_char,
pub _IO_read_base: *mut ::core::ffi::c_char,
pub _IO_write_base: *mut ::core::ffi::c_char,
pub _IO_write_ptr: *mut ::core::ffi::c_char,
pub _IO_write_end: *mut ::core::ffi::c_char,
pub _IO_buf_base: *mut ::core::ffi::c_char,
pub _IO_buf_end: *mut ::core::ffi::c_char,
pub _IO_save_base: *mut ::core::ffi::c_char,
pub _IO_backup_base: *mut ::core::ffi::c_char,
pub _IO_save_end: *mut ::core::ffi::c_char,
pub _markers: *mut _IO_marker,
pub _chain: *mut _IO_FILE,
pub _fileno: ::core::ffi::c_int,
pub _bitfield_align_1: [u32; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>,
pub _short_backupbuf: [::core::ffi::c_char; 1usize],
pub _old_offset: __off_t,
pub _cur_column: ::core::ffi::c_ushort,
pub _vtable_offset: ::core::ffi::c_schar,
pub _shortbuf: [::core::ffi::c_char; 1usize],
pub _lock: *mut _IO_lock_t,
pub _offset: __off64_t,
pub _codecvt: *mut _IO_codecvt,
pub _wide_data: *mut _IO_wide_data,
pub _freeres_list: *mut _IO_FILE,
pub _freeres_buf: *mut ::core::ffi::c_void,
pub _prevchain: *mut *mut _IO_FILE,
pub _mode: ::core::ffi::c_int,
pub _unused3: ::core::ffi::c_int,
pub _total_written: __uint64_t,
pub _unused2: [::core::ffi::c_char; 8usize],
}
impl Default for _IO_FILE {
fn default() -> Self {
let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
unsafe {
::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
impl _IO_FILE {
#[inline]
pub fn _flags2(&self) -> ::core::ffi::c_int {
unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) }
}
#[inline]
pub fn set__flags2(&mut self, val: ::core::ffi::c_int) {
unsafe {
let val: u32 = ::core::mem::transmute(val);
self._bitfield_1.set(0usize, 24u8, val as u64)
}
}
#[inline]
pub unsafe fn _flags2_raw(this: *const Self) -> ::core::ffi::c_int {
unsafe {
::core::mem::transmute(
<__BindgenBitfieldUnit<
[u8; 3usize],
>>::raw_get(::core::ptr::addr_of!((* this)._bitfield_1), 0usize, 24u8)
as u32,
)
}
}
#[inline]
pub unsafe fn set__flags2_raw(this: *mut Self, val: ::core::ffi::c_int) {
unsafe {
let val: u32 = ::core::mem::transmute(val);
<__BindgenBitfieldUnit<
[u8; 3usize],
>>::raw_set(
::core::ptr::addr_of_mut!((* this)._bitfield_1),
0usize,
24u8,
val as u64,
)
}
}
#[inline]
pub fn new_bitfield_1(
_flags2: ::core::ffi::c_int,
) -> __BindgenBitfieldUnit<[u8; 3usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default();
__bindgen_bitfield_unit
.set(
0usize,
24u8,
{
let _flags2: u32 = unsafe { ::core::mem::transmute(_flags2) };
_flags2 as u64
},
);
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CUstream_st {
_unused: [u8; 0],
}
pub use self::cudaDataType_t as cutensorDataType_t;
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_16F"]
pub static CUTENSOR_R_16F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_16F"]
pub static CUTENSOR_C_16F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL15CUTENSOR_R_16BF"]
pub static CUTENSOR_R_16BF: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL15CUTENSOR_C_16BF"]
pub static CUTENSOR_C_16BF: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_32F"]
pub static CUTENSOR_R_32F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_32F"]
pub static CUTENSOR_C_32F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_64F"]
pub static CUTENSOR_R_64F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_64F"]
pub static CUTENSOR_C_64F: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_R_4I"]
pub static CUTENSOR_R_4I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_C_4I"]
pub static CUTENSOR_C_4I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_R_4U"]
pub static CUTENSOR_R_4U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_C_4U"]
pub static CUTENSOR_C_4U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_R_8I"]
pub static CUTENSOR_R_8I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_C_8I"]
pub static CUTENSOR_C_8I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_R_8U"]
pub static CUTENSOR_R_8U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL13CUTENSOR_C_8U"]
pub static CUTENSOR_C_8U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_16I"]
pub static CUTENSOR_R_16I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_16I"]
pub static CUTENSOR_C_16I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_16U"]
pub static CUTENSOR_R_16U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_16U"]
pub static CUTENSOR_C_16U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_32I"]
pub static CUTENSOR_R_32I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_32I"]
pub static CUTENSOR_C_32I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_32U"]
pub static CUTENSOR_R_32U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_32U"]
pub static CUTENSOR_C_32U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_64I"]
pub static CUTENSOR_R_64I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_64I"]
pub static CUTENSOR_C_64I: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_R_64U"]
pub static CUTENSOR_R_64U: cutensorDataType_t;
}
unsafe extern "C" {
#[link_name = "\u{1}_ZL14CUTENSOR_C_64U"]
pub static CUTENSOR_C_64U: cutensorDataType_t;
}
/// This enum captures all unary and binary element-wise operations supported by the cuTENSOR library.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorOperator_t {
/// Identity operator (i.e., elements are not changed).
CUTENSOR_OP_IDENTITY = 1,
/// Square root.
CUTENSOR_OP_SQRT = 2,
/// Rectified linear unit.
CUTENSOR_OP_RELU = 8,
/// Complex conjugate.
CUTENSOR_OP_CONJ = 9,
/// Reciprocal.
CUTENSOR_OP_RCP = 10,
/// y=1/(1+exp(-x)).
CUTENSOR_OP_SIGMOID = 11,
/// y=tanh(x).
CUTENSOR_OP_TANH = 12,
/// Exponentiation.
CUTENSOR_OP_EXP = 22,
/// Log (base e).
CUTENSOR_OP_LOG = 23,
/// Absolute value.
CUTENSOR_OP_ABS = 24,
/// Negation.
CUTENSOR_OP_NEG = 25,
/// Sine.
CUTENSOR_OP_SIN = 26,
/// Cosine.
CUTENSOR_OP_COS = 27,
/// Tangent.
CUTENSOR_OP_TAN = 28,
/// Hyperbolic sine.
CUTENSOR_OP_SINH = 29,
/// Hyperbolic cosine.
CUTENSOR_OP_COSH = 30,
/// Inverse sine.
CUTENSOR_OP_ASIN = 31,
/// Inverse cosine.
CUTENSOR_OP_ACOS = 32,
/// Inverse tangent.
CUTENSOR_OP_ATAN = 33,
/// Inverse hyperbolic sine.
CUTENSOR_OP_ASINH = 34,
/// Inverse hyperbolic cosine.
CUTENSOR_OP_ACOSH = 35,
/// Inverse hyperbolic tangent.
CUTENSOR_OP_ATANH = 36,
/// Ceiling.
CUTENSOR_OP_CEIL = 37,
/// Floor.
CUTENSOR_OP_FLOOR = 38,
/// Mish y=x\*tanh(softplus(x)).
CUTENSOR_OP_MISH = 39,
/// Swish y=x\*sigmoid(x).
CUTENSOR_OP_SWISH = 40,
/// Softplus y=log(exp(x)+1).
CUTENSOR_OP_SOFT_PLUS = 41,
/// Softsign y=x/(abs(x)+1).
CUTENSOR_OP_SOFT_SIGN = 42,
/// Addition of two elements.
CUTENSOR_OP_ADD = 3,
/// Multiplication of two elements.
CUTENSOR_OP_MUL = 5,
/// Maximum of two elements.
CUTENSOR_OP_MAX = 6,
/// Minimum of two elements.
CUTENSOR_OP_MIN = 7,
/// reserved for internal use only.
CUTENSOR_OP_UNKNOWN = 126,
}
/// cuTENSOR status type returns
///
/// The type is used for function status returns. All cuTENSOR library functions return their status, which can have the following values.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorStatus_t {
/// The operation completed successfully.
CUTENSOR_STATUS_SUCCESS = 0,
/// The opaque data structure was not initialized.
CUTENSOR_STATUS_NOT_INITIALIZED = 1,
/// Resource allocation failed inside the cuTENSOR library.
CUTENSOR_STATUS_ALLOC_FAILED = 3,
/// An unsupported value or parameter was passed to the function (indicates an user error).
CUTENSOR_STATUS_INVALID_VALUE = 7,
/// Indicates that the device is either not ready, or the target architecture is not supported.
CUTENSOR_STATUS_ARCH_MISMATCH = 8,
/// An access to GPU memory space failed, which is usually caused by a failure to bind a texture.
CUTENSOR_STATUS_MAPPING_ERROR = 11,
/// 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.
CUTENSOR_STATUS_EXECUTION_FAILED = 13,
/// An internal cuTENSOR error has occurred.
CUTENSOR_STATUS_INTERNAL_ERROR = 14,
/// The requested operation is not supported.
CUTENSOR_STATUS_NOT_SUPPORTED = 15,
/// The functionality requested requires some license and an error was detected when trying to check the current licensing.
CUTENSOR_STATUS_LICENSE_ERROR = 16,
/// A call to CUBLAS did not succeed.
CUTENSOR_STATUS_CUBLAS_ERROR = 17,
/// Some unknown CUDA error has occurred.
CUTENSOR_STATUS_CUDA_ERROR = 18,
/// The provided workspace was insufficient.
CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE = 19,
/// Indicates that the driver version is insufficient.
CUTENSOR_STATUS_INSUFFICIENT_DRIVER = 20,
/// Indicates an error related to file I/O.
CUTENSOR_STATUS_IO_ERROR = 21,
}
/// Allows users to specify the algorithm to be used for performing the desired tensor operation.
#[repr(i32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorAlgo_t {
/// More time-consuming than CUTENSOR_DEFAULT, but typically provides a more accurate kernel selection.
CUTENSOR_ALGO_DEFAULT_PATIENT = -6,
/// Choose the GETT algorithm (only applicable to contractions).
CUTENSOR_ALGO_GETT = -4,
/// Transpose (A or B) + GETT (only applicable to contractions).
CUTENSOR_ALGO_TGETT = -3,
/// Transpose-Transpose-GEMM-Transpose (requires additional memory) (only applicable to contractions).
CUTENSOR_ALGO_TTGT = -2,
/// A performance model chooses the appropriate algorithm and kernel.
CUTENSOR_ALGO_DEFAULT = -1,
}
/// This enum gives users finer control over the suggested workspace.
///
/// This enum gives users finer control over the amount of workspace that is suggested by [`cutensorEstimateWorkspaceSize`].
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorWorksizePreference_t {
/// Least memory requirement; at least one algorithm will be available.
CUTENSOR_WORKSPACE_MIN = 1,
/// Aims to attain high performance while also reducing the workspace requirement.
CUTENSOR_WORKSPACE_DEFAULT = 2,
/// Highest memory requirement; all algorithms will be available (choose this option if memory footprint is not a concern).
CUTENSOR_WORKSPACE_MAX = 3,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorComputeDescriptor {
_unused: [u8; 0],
}
/// Opaque structure representing a compute descriptor.
pub type cutensorComputeDescriptor_t = *mut cutensorComputeDescriptor;
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_16F: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_16BF: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_TF32: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_3XTF32: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_32F: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_64F: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_9X16BF: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_8XINT8: cutensorComputeDescriptor_t;
}
unsafe extern "C" {
pub static CUTENSOR_COMPUTE_DESC_4X16F: cutensorComputeDescriptor_t;
}
/// This enum lists all attributes of a [`cutensorOperationDescriptor_t`] that can be modified (see [`cutensorOperationDescriptorSetAttribute`] and [`cutensorOperationDescriptorGetAttribute`]).
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorOperationDescriptorAttribute_t {
/// int32_t: enables users to distinguish two identical problems with respect to the sw-managed plan-cache. (default value: 0).
CUTENSOR_OPERATION_DESCRIPTOR_TAG = 0,
/// cudaDataType_t: data type of the scaling factors.
CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE = 1,
/// float: number of floating-point operations necessary to perform this operation (assuming all scalar are not equal to zero, unless otherwise specified).
CUTENSOR_OPERATION_DESCRIPTOR_FLOPS = 2,
/// float: minimal number of bytes transferred from/to global-memory (assuming all scalar are not equal to zero, unless otherwise specified).
CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES = 3,
/// 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.
CUTENSOR_OPERATION_DESCRIPTOR_PADDING_LEFT = 4,
/// 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.
CUTENSOR_OPERATION_DESCRIPTOR_PADDING_RIGHT = 5,
/// host-side pointer to element of the same type as the output tensor: Constant padding value.
CUTENSOR_OPERATION_DESCRIPTOR_PADDING_VALUE = 6,
}
/// This enum lists all attributes of a [`cutensorPlanPreference_t`] object that can be modified.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorPlanPreferenceAttribute_t {
/// 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.
CUTENSOR_PLAN_PREFERENCE_AUTOTUNE_MODE = 0,
/// 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.
CUTENSOR_PLAN_PREFERENCE_CACHE_MODE = 1,
/// int32_t: Only applicable if [`cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_CACHE_MODE`] is set to [`cutensorAutotuneMode_t::CUTENSOR_AUTOTUNE_MODE_INCREMENTAL`].
CUTENSOR_PLAN_PREFERENCE_INCREMENTAL_COUNT = 2,
/// cutensorAlgo_t: Fixes a certain [`cutensorAlgo_t`].
CUTENSOR_PLAN_PREFERENCE_ALGO = 3,
/// 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).
CUTENSOR_PLAN_PREFERENCE_KERNEL_RANK = 4,
/// cutensorJitMode_t: determines if just-in-time compilation is enabled or disabled (default: [`cutensorJitMode_t::CUTENSOR_JIT_MODE_NONE`]).
CUTENSOR_PLAN_PREFERENCE_JIT = 5,
/// 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.
CUTENSOR_PLAN_PREFERENCE_GPU_ARCH = 6,
}
/// This enum determines the mode with respect to cuTENSOR’s auto-tuning capability.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorAutotuneMode_t {
/// 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.
CUTENSOR_AUTOTUNE_MODE_NONE = 0,
/// 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).
CUTENSOR_AUTOTUNE_MODE_INCREMENTAL = 1,
}
/// This enum determines the mode with respect to cuTENSOR’s just-in-time compilation capability.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorJitMode_t {
/// Indicates that no kernel will be just-in-time compiled.
CUTENSOR_JIT_MODE_NONE = 0,
/// 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).
CUTENSOR_JIT_MODE_DEFAULT = 1,
}
/// This enum defines what is considered a cache hit.
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorCacheMode_t {
/// Plan will not be cached.
CUTENSOR_CACHE_MODE_NONE = 0,
/// All parameters of the corresponding descriptor must be identical to the cached plan (default).
CUTENSOR_CACHE_MODE_PEDANTIC = 1,
}
/// This enum lists all attributes of a [`cutensorPlan_t`] object that can be retrieved via [`cutensorPlanGetAttribute`].
#[repr(u32)]
#[derive(
Debug,
Copy,
Clone,
Hash,
PartialOrd,
Ord,
PartialEq,
Eq,
TryFromPrimitive,
IntoPrimitive,
)]
pub enum cutensorPlanAttribute_t {
/// uint64_t: exact required workspace in bytes that is needed to execute the plan.
CUTENSOR_PLAN_REQUIRED_WORKSPACE = 0,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorOperationDescriptor {
_unused: [u8; 0],
}
/// Opaque structure representing any type of problem descriptor (e.g., contraction, reduction, elementwise).
pub type cutensorOperationDescriptor_t = *mut cutensorOperationDescriptor;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorPlan {
_unused: [u8; 0],
}
/// Opaque structure representing a plan (e.g, contraction, reduction, elementwise).
pub type cutensorPlan_t = *mut cutensorPlan;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorPlanPreference {
_unused: [u8; 0],
}
/// Opaque structure that narrows down the space of applicable algorithms/variants/kernels.
pub type cutensorPlanPreference_t = *mut cutensorPlanPreference;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorHandle {
_unused: [u8; 0],
}
/// Opaque structure holding cuTENSOR’s library context.
pub type cutensorHandle_t = *mut cutensorHandle;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorTensorDescriptor {
_unused: [u8; 0],
}
/// Opaque structure representing a tensor descriptor.
pub type cutensorTensorDescriptor_t = *mut cutensorTensorDescriptor;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorBlockSparseTensorDescriptor {
_unused: [u8; 0],
}
/// Opaque structure representing a block-sparse tensor descriptor.
pub type cutensorBlockSparseTensorDescriptor_t = *mut cutensorBlockSparseTensorDescriptor;
/// A function pointer type for logging.
pub type cutensorLoggerCallback_t = ::core::option::Option<
unsafe extern "C" fn(
logLevel: i32,
functionName: *const ::core::ffi::c_char,
message: *const ::core::ffi::c_char,
),
>;
unsafe extern "C" {
/// Initializes the cuTENSOR library and allocates the memory for the library context.
///
/// 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`].
///
/// 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.
///
/// The user is responsible for calling [`cutensorDestroy`] to free the resources associated with the handle.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorCreate(handle: *mut cutensorHandle_t) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided library handle.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroy(handle: cutensorHandle_t) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Resizes the plan cache.
///
/// This function changes the number of plans that can be stored in the plan cache of the handle.
///
/// Resizing invalidates the cache.
///
/// While this function is not thread-safe, the resulting cache can be shared across different threads in a thread-safe manner.
///
/// Remark
///
/// non-blocking, no reentrant, and not thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context. The cache will be attached to the handle.
/// - `numEntries`: Number of entries the cache will support.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorHandleResizePlanCache(
handle: cutensorHandle_t,
numEntries: u32,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Writes the Plan-Cache (that belongs to the provided handle) to file.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `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.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if the no cache has been attached.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be written to.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorHandleWritePlanCacheToFile(
handle: cutensorHandle_t,
filename: *const ::core::ffi::c_char,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Reads a Plan-Cache from file and overwrites the cachelines of the provided handle.
///
/// 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.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `filename`: Specifies the filename (including the absolute path) to the file that holds all the cache information that have previously been written by [`cutensorHandleWritePlanCacheToFile`].
/// - `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.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE`]: if the stored cache requires more cachelines than those that are currently attached to the handle.
/// - [`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.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be read.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorHandleReadPlanCacheFromFile(
handle: cutensorHandle_t,
filename: *const ::core::ffi::c_char,
numCachelinesRead: *mut u32,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Writes the —per library— kernel cache to file.
///
/// Writes the just-in-time compiled kernels to the provided file (those kernels belong to the library—not to the handle).
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `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.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be written to.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the function is not available for the operating system, CUDA Toolkit, or compute capability of the device.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully or there were no kernels in the cache.
pub fn cutensorWriteKernelCacheToFile(
handle: cutensorHandle_t,
filename: *const ::core::ffi::c_char,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Reads a kernel cache from file and adds all non-existing JIT compiled kernels to the kernel cache.
///
/// 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.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `filename`: Specifies the filename (including the absolute path) to the file that holds all the cache information that have previously been written by cutensorWriteKernelCacheToFile.
///
/// # Return value
///
/// - [`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.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_IO_ERROR`]: if the file cannot be read.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the function is not available for the operating system, CUDA Toolkit, or compute capability of the device.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully, or the file pointed to by filename was empty.
pub fn cutensorReadKernelCacheFromFile(
handle: cutensorHandle_t,
filename: *const ::core::ffi::c_char,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Creates a tensor descriptor.
///
/// This allocates a small amount of host-memory.
///
/// The user is responsible for calling [`cutensorDestroyTensorDescriptor`] to free the associated resources once the tensor descriptor is no longer used.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: Pointer to the address where the allocated tensor descriptor object will be stored.
/// - `numModes`: Number of modes.
/// - `extent`: Extent of each mode (must be larger than zero).
/// - `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.
/// - `dataType`: Data type of the stored entries.
/// - `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).
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the requested descriptor is not supported (e.g., due to non-supported data type).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorCreateTensorDescriptor(
handle: cutensorHandle_t,
desc: *mut cutensorTensorDescriptor_t,
numModes: u32,
extent: *const i64,
stride: *const i64,
dataType: cudaDataType_t,
alignmentRequirement: u32,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided tensor descriptor.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroyTensorDescriptor(
desc: cutensorTensorDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function creates an operation descriptor that encodes an elementwise trinary operation.
///
/// Said trinary operation has the following general form:
/// $$
/// 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)}))
/// $$
///
/// Where
///
/// * A,B,C,D are multi-mode tensors (of arbitrary data types).
/// * $\Pi^A, \Pi^B, \Pi^C$ are permutation operators that permute the modes of A, B, and C respectively.
/// * $op_{A},op_{B},op_{C}$ are unary element-wise operators (e.g., IDENTITY, CONJUGATE).
/// * $\Phi_{ABC}, \Phi_{AB}$ are binary element-wise operators (e.g., ADD, MUL, MAX, MIN).
///
/// Notice that the broadcasting (of a mode) can be achieved by simply omitting that mode from the respective tensor.
///
/// Moreover, modes may appear in any order, giving users a greater flexibility. The only **restrictions** are:
///
/// * 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`].
/// * each mode may appear in each tensor at most once.
///
/// Input tensors may be read even if the value of the corresponding scalar is zero.
///
/// Examples:
///
/// * $D_{a,b,c,d} = A_{b,d,a,c}$
/// * $D_{a,b,c,d} = 2.2 \\* A_{b,d,a,c} + 1.3 \\* B_{c,b,d,a}$
/// * $D_{a,b,c,d} = 2.2 \\* A_{b,d,a,c} + 1.3 \\* B_{c,b,d,a} + C_{a,b,c,d}$
/// * $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})$
///
/// Call [`cutensorElementwiseTrinaryExecute`] to perform the actual operation.
///
/// Please use [`cutensorDestroyOperationDescriptor`] to deallocated the descriptor once it is no longer used.
///
/// Supported data-type combinations are:
///
/// | typeA | typeB | typeC | descCompute |
/// | --- | --- | --- | --- |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_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`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested elementwise operation.
/// - `descA`: A descriptor that holds the information about the data type, modes, and strides of A.
/// - `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`].
/// - `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.
/// - `descB`: A descriptor that holds information about the data type, modes, and strides of B.
/// - `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`].
/// - `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.
/// - `descC`: A descriptor that holds information about the data type, modes, and strides of C.
/// - `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`].
/// - `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.
/// - `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.
/// - `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`].
/// - `opAB`: Element-wise binary operator (see $\Phi_{AB}$ above).
/// - `opABC`: Element-wise binary operator (see $\Phi_{ABC}$ above).
/// - `descCompute`: Determines the precision in which this operations is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the device is either not ready, or the target architecture is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorCreateElementwiseTrinary(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descB: cutensorTensorDescriptor_t,
modeB: *const i32,
opB: cutensorOperator_t,
descC: cutensorTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorTensorDescriptor_t,
modeD: *const i32,
opAB: cutensorOperator_t,
opABC: cutensorOperator_t,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Performs an element-wise tensor operation for three input tensors (see [`cutensorCreateElementwiseTrinary`])
///
/// This function performs a element-wise tensor operation of the form:
/// $$
/// 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)}))
/// $$
///
/// See [`cutensorCreateElementwiseTrinary`] for details.
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding all information about the desired elementwise operation (created by [`cutensorCreateElementwiseTrinary`] followed by [`cutensorCreatePlan`]).
/// - `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.
/// - `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.
/// - `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.
/// - `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.
/// - `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.
/// - `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.
/// - `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`).
/// - `stream`: The CUDA stream used to perform the operation.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorElementwiseTrinaryExecute(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
beta: *const ::core::ffi::c_void,
B: *const ::core::ffi::c_void,
gamma: *const ::core::ffi::c_void,
C: *const ::core::ffi::c_void,
D: *mut ::core::ffi::c_void,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function creates an operation descriptor for an elementwise binary operation.
///
/// The binary operation has the following general form:
/// $$
/// 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)}))
/// $$
///
/// Call [`cutensorElementwiseBinaryExecute`] to perform the actual operation.
///
/// Supported data-type combinations are:
///
/// | typeA | typeC | descCompute |
/// | --- | --- | --- |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested elementwise operation.
/// - `descA`: The descriptor that holds the information about the data type, modes, and strides of A.
/// - `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`].
/// - `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.
/// - `descC`: The descriptor that holds information about the data type, modes, and strides of C.
/// - `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`].
/// - `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.
/// - `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.
/// - `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`].
/// - `opAC`: Element-wise binary operator (corresponding to $\Phi_{AC}$ above).
/// - `descCompute`: Determines the precision in which this operations is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorCreateElementwiseBinary(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descC: cutensorTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorTensorDescriptor_t,
modeD: *const i32,
opAC: cutensorOperator_t,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Performs an element-wise tensor operation for two input tensors (see [`cutensorCreateElementwiseBinary`])
///
/// This function performs a element-wise tensor operation of the form:
/// $$
/// 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)}))
/// $$
///
/// See [`cutensorCreateElementwiseBinary`] for details.
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding all information about the desired elementwise operation (created by [`cutensorCreateElementwiseBinary`] followed by [`cutensorCreatePlan`]).
/// - `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.
/// - `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.
/// - `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.
/// - `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.
/// - `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`).
/// - `stream`: The CUDA stream used to perform the operation.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorElementwiseBinaryExecute(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
gamma: *const ::core::ffi::c_void,
C: *const ::core::ffi::c_void,
D: *mut ::core::ffi::c_void,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function creates an operation descriptor for a tensor permutation.
///
/// The tensor permutation has the following general form:
/// $$
/// B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)})
/// $$
///
/// Consequently, this function performs an out-of-place tensor permutation and is a specialization of [`cutensorCreateElementwiseBinary`].
///
/// Where
///
/// * A and B are multi-mode tensors (of arbitrary data types),
/// * $\Pi^A, \Pi^B$ are permutation operators that permute the modes of A, B respectively,
/// * $op_A$ is an unary element-wise operators (e.g., IDENTITY, SQR, CONJUGATE), and
///
/// Broadcasting (of a mode) can be achieved by simply omitting that mode from the respective tensor.
///
/// Modes may appear in any order. The only **restrictions** are:
///
/// * modes that appear in A `must` also appear in the output tensor.
/// * each mode may appear in each tensor at most once.
///
/// Supported data-type combinations are:
///
/// | typeA | typeB | descCompute |
/// | --- | --- | --- |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_16BF`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested permutation.
/// - `descA`: The descriptor that holds information about the data type, modes, and strides of A.
/// - `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’}).
/// - `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.
/// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
/// - `modeB`: Array of size descB->numModes that holds the names of the modes of B.
/// - `descCompute`: Determines the precision in which this operations is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorCreatePermutation(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descB: cutensorTensorDescriptor_t,
modeB: *const i32,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Performs the tensor permutation that is encoded by `plan` (see [`cutensorCreatePermutation`]).
///
/// This function performs an elementwise tensor operation of the form:
/// $$
/// B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)})
/// $$
///
/// Consequently, this function performs an out-of-place tensor permutation.
///
/// Where
///
/// * A and B are multi-mode tensors (of arbitrary data types),
/// * $\Pi^A, \Pi^B$ are permutation operators that permute the modes of A, B respectively,
/// * $op_A$ is an unary element-wise operators (e.g., IDENTITY, SQR, CONJUGATE), and is specified when creating the operation descriptor using [`cutensorCreatePermutation`]
///
/// Remark
///
/// calls asynchronous functions, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding all information about the desired tensor reduction (created by [`cutensorCreatePermutation`] followed by [`cutensorCreatePlan`]).
/// - `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.
/// - `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.
/// - `B`: Multi-mode tensor of type typeB with nmodeB modes. Pointer to the GPU-accessible memory.
/// - `stream`: The CUDA stream.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorPermute(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
B: *mut ::core::ffi::c_void,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function allocates a cutensorOperationDescriptor_t object that encodes a tensor contraction of the form $D = \alpha \mathcal{A} \mathcal{B} + \beta \mathcal{C}$.
///
/// Allocates data for `desc` to be used to perform a tensor contraction of the form:
/// $$
/// \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}}).
/// $$
///
/// 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.
///
/// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
///
/// Supported data-type combinations are:
///
/// | typeA | typeB | typeC | descCompute | typeScalar | Tensor Core |
/// | --- | --- | --- | --- | --- | --- |
/// | [`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+ |
/// | [`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+ |
/// | [`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 |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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 |
/// | [`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 |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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 |
/// | [`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 |
/// | [`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 |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
/// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
/// - `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.
/// - `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.
/// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
/// - `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.
/// - `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.
/// - `descC`: The escriptor that holds information about the data type, modes, and strides of C.
/// - `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.
/// - `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.
/// - `descD`: The descriptor that holds information about the data type, modes, and strides of D (must be identical to `descC` for now).
/// - `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.
/// - `descCompute`: Determines the precision in which this operations is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorCreateContraction(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descB: cutensorTensorDescriptor_t,
modeB: *const i32,
opB: cutensorOperator_t,
descC: cutensorTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorTensorDescriptor_t,
modeD: *const i32,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided descriptor.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroyOperationDescriptor(
desc: cutensorOperationDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Set attribute of a cutensorOperationDescriptor_t object.
///
/// Currently not supported for blocksparse contraction descriptors.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: Operation descriptor that will be modified.
/// - `attr`: Specifies the attribute that will be set.
/// - `buf`: This buffer (of size `sizeInBytes`) determines the value to which `attr` will be set.
/// - `sizeInBytes`: Size of buf (in bytes).
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorOperationDescriptorSetAttribute(
handle: cutensorHandle_t,
desc: cutensorOperationDescriptor_t,
attr: cutensorOperationDescriptorAttribute_t,
buf: *const ::core::ffi::c_void,
sizeInBytes: size_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function retrieves an attribute of the provided cutensorOperationDescriptor_t object (see [`cutensorOperationDescriptorAttribute_t`]).
///
/// Block-sparse contraction descriptors only support the attributes [`cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE`] and [`cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES`].
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: The cutensorOperationDescriptor_t object whos attribute is queried.
/// - `attr`: Specifies the attribute that will be retrieved.
/// - `buf`: This buffer (of size sizeInBytes) will hold the requested attribute of the provided cutensorOperationDescriptor_t object.
/// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorOperationDescriptorAttribute_t`] for the exact size.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorOperationDescriptorGetAttribute(
handle: cutensorHandle_t,
desc: cutensorOperationDescriptor_t,
attr: cutensorOperationDescriptorAttribute_t,
buf: *mut ::core::ffi::c_void,
sizeInBytes: size_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Allocates the cutensorPlanPreference_t, enabling users to limit the applicable kernels for a given plan/operation.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `pref`: Pointer to the structure holding the [`cutensorPlanPreference_t`] allocated by this function. See [`cutensorPlanPreference_t`].
/// - `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.
/// - `jitMode`: Determines if cuTENSOR is allowed to use JIT-compiled kernels (leading to a longer plan-creation phase); see [`cutensorJitMode_t`].
pub fn cutensorCreatePlanPreference(
handle: cutensorHandle_t,
pref: *mut cutensorPlanPreference_t,
algo: cutensorAlgo_t,
jitMode: cutensorJitMode_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided preference.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroyPlanPreference(
pref: cutensorPlanPreference_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Get attribute of a cutensorPlanPreference_t object.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `pref`: This opaque struct restricts the search space of viable candidates.
/// - `attr`: Requested attribute.
/// - `buf`: On successful exit: Holds the information of the requested attribute.
/// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorPlanPreferenceAttribute_t`] for the exact size.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorPlanPreferenceGetAttribute(
handle: cutensorHandle_t,
pref: cutensorPlanPreference_t,
attr: cutensorPlanPreferenceAttribute_t,
buf: *mut ::core::ffi::c_void,
sizeInBytes: size_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Set attribute of a cutensorPlanPreference_t object.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `pref`: This opaque struct restricts the search space of viable candidates.
/// - `attr`: Specifies the attribute that will be set.
/// - `buf`: This buffer (of size sizeInBytes) determines the value to which `attr` will be set.
/// - `sizeInBytes`: Size of buf (in bytes); see [`cutensorPlanPreferenceAttribute_t`] for the exact size.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorPlanPreferenceSetAttribute(
handle: cutensorHandle_t,
pref: cutensorPlanPreference_t,
attr: cutensorPlanPreferenceAttribute_t,
buf: *const ::core::ffi::c_void,
sizeInBytes: size_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Retrieves information about an already-created plan (see [`cutensorPlanAttribute_t`])
///
/// Block-sparse contraction plans only support [`cutensorPlanAttribute_t::CUTENSOR_PLAN_REQUIRED_WORKSPACE`].
///
/// # Parameters
///
/// - `plan`: Denotes an already-created plan (e.g., via [`cutensorCreatePlan`] or cutensorCreatePlanAutotuned).
/// - `attr`: Requested attribute.
/// - `buf`: On successful exit: Holds the information of the requested attribute.
/// - `sizeInBytes`: size of `buf` in bytes.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorPlanGetAttribute(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
attr: cutensorPlanAttribute_t,
buf: *mut ::core::ffi::c_void,
sizeInBytes: size_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Determines the required workspaceSize for the given operation encoded by `desc`.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct encodes the operation.
/// - `planPref`: This opaque struct restricts the space of viable candidates.
/// - `workspacePref`: This parameter influences the size of the workspace; see [`cutensorWorksizePreference_t`] for details.
/// - `workspaceSizeEstimate`: The workspace size (in bytes) that is required for the given operation.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorEstimateWorkspaceSize(
handle: cutensorHandle_t,
desc: cutensorOperationDescriptor_t,
planPref: cutensorPlanPreference_t,
workspacePref: cutensorWorksizePreference_t,
workspaceSizeEstimate: *mut u64,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// 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.
///
/// 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.
///
/// The plan is created for the active CUDA device.
///
/// 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`]).
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Pointer to the data structure created by this function that holds all information (e.g., selected kernel) necessary to perform the desired operation.
/// - `desc`: This opaque struct encodes the given operation (see [`cutensorCreateContraction`], [`cutensorCreateReduction`], [`cutensorCreatePermutation`], [`cutensorCreateElementwiseBinary`], [`cutensorCreateElementwiseTrinary`], or [`cutensorCreateContractionTrinary`]).
/// - `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.
/// - `workspaceSizeLimit`: Denotes the maximal workspace that the corresponding operation is allowed to use (see [`cutensorEstimateWorkspaceSize`]).
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_WORKSPACE`]: if the provided workspace was insufficient.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: If no viable candidate could be found.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: If a viable candidate has been found.
pub fn cutensorCreatePlan(
handle: cutensorHandle_t,
plan: *mut cutensorPlan_t,
desc: cutensorOperationDescriptor_t,
pref: cutensorPlanPreference_t,
workspaceSizeLimit: u64,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided plan.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroyPlan(plan: cutensorPlan_t) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This routine computes the tensor contraction $D = alpha \\* A \\* B + beta \\* C$.
/// $$
/// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha \\* \mathcal{A}_{{modes}_\mathcal{A}} B_{{modes}_\mathcal{B}} + \beta \mathcal{C}_{{modes}_\mathcal{C}}
/// $$
///
/// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
///
/// **\[Example\]**
/// : See [NVIDIA/CUDALibrarySamples](https://github.com/NVIDIA/CUDALibrarySamples/tree/master/cuTENSOR/contraction.cu) for a concrete example.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateContraction`] followed by [`cutensorCreatePlan`]).
/// - `alpha`: Scaling for A\*B. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
/// - `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.
/// - `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.
/// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
/// - `C`: Pointer to the data corresponding to C. Pointer to the GPU-accessible memory.
/// - `D`: Pointer to the data corresponding to D. Pointer to the GPU-accessible memory.
/// - `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).
/// - `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).
/// - `stream`: The CUDA stream in which all the computation is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorContract(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
B: *const ::core::ffi::c_void,
beta: *const ::core::ffi::c_void,
C: *const ::core::ffi::c_void,
D: *mut ::core::ffi::c_void,
workspace: *mut ::core::ffi::c_void,
workspaceSize: u64,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Creates a cutensorOperatorDescriptor_t object that encodes a tensor reduction of the form $D = alpha \\* opReduce(opA(A)) + beta \\* opC(C)$.
///
/// For example this function enables users to reduce an entire tensor to a scalar: C[] = alpha \* A\[i,j,k\];
///
/// 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.
///
/// 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.
///
/// Supported data-type combinations are:
///
/// | typeA | typeB | typeC | typeCompute |
/// | --- | --- | --- | --- |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_16F`] |
/// | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`cudaDataType_t::CUDA_R_16F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`cudaDataType_t::CUDA_R_16BF`] | [`CUTENSOR_COMPUTE_DESC_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`] | [`cudaDataType_t::CUDA_R_32F`] | [`cudaDataType_t::CUDA_R_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`cudaDataType_t::CUDA_R_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
/// | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`cudaDataType_t::CUDA_C_32F`] | [`CUTENSOR_COMPUTE_DESC_32F`] |
/// | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`cudaDataType_t::CUDA_C_64F`] | [`CUTENSOR_COMPUTE_DESC_64F`] |
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the requested tensor reduction operation.
/// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
/// - `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).
/// - `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.
/// - `descC`: The descriptor that holds the information about the data type, modes and strides of C.
/// - `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`].
/// - `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.
/// - `descD`: Must be identical to descC for now.
/// - `modeD`: Must be identical to modeC for now.
/// - `opReduce`: binary operator used to reduce elements of A.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorCreateReduction(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descC: cutensorTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorTensorDescriptor_t,
modeD: *const i32,
opReduce: cutensorOperator_t,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Performs the tensor reduction that is encoded by `plan` (see [`cutensorCreateReduction`]).
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding the reduction execution plan (created by [`cutensorCreateReduction`] followed by [`cutensorCreatePlan`]).
/// - `alpha`: Scaling for A. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
/// - `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.
/// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
/// - `C`: Pointer to the data corresponding to C in device memory. Pointer to the GPU-accessible memory.
/// - `D`: Pointer to the data corresponding to C in device memory. Pointer to the GPU-accessible memory.
/// - `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).
/// - `workspaceSize`: Please use [`cutensorEstimateWorkspaceSize`] to query the required workspace.
/// - `stream`: The CUDA stream in which all the computation is performed.
pub fn cutensorReduce(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
beta: *const ::core::ffi::c_void,
C: *const ::core::ffi::c_void,
D: *mut ::core::ffi::c_void,
workspace: *mut ::core::ffi::c_void,
workspaceSize: u64,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// 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}$.
///
/// Allocates data for `desc` to be used to perform a tensor contraction of the form:
/// $$
/// \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}}).
/// $$
///
/// 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.
///
/// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
///
/// 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.
///
/// Supported data-type combinations are:
///
/// | typeA | typeB | typeC | typeD | descCompute | | typeScalar | Tensor Core | |
/// | --- | --- | --- | --- | --- | --- | --- | --- | --- |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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 | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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 | |
/// | [`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 | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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+ | |
/// | [`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 | |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
/// | [`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+ |
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
/// - `descA`: The descriptor that holds the information about the data type, modes and strides of A.
/// - `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.
/// - `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.
/// - `descB`: The descriptor that holds information about the data type, modes, and strides of B.
/// - `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.
/// - `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.
/// - `descC`: The escriptor that holds information about the data type, modes, and strides of C.
/// - `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.
/// - `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.
/// - `descD`: The escriptor that holds information about the data type, modes, and strides of D.
/// - `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.
/// - `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.
/// - `descE`: The descriptor that holds information about the data type, modes, and strides of E (must be identical to `descD` for now).
/// - `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.
/// - `descCompute`: Determines the precision in which this operations is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorCreateContractionTrinary(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descB: cutensorTensorDescriptor_t,
modeB: *const i32,
opB: cutensorOperator_t,
descC: cutensorTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorTensorDescriptor_t,
modeD: *const i32,
opD: cutensorOperator_t,
descE: cutensorTensorDescriptor_t,
modeE: *const i32,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This routine computes the tensor contraction $E = alpha \\* A \\* B \\* C + beta \\* D$.
/// $$
/// \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}}
/// $$
///
/// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
///
/// **\[Example\]**
/// : See [NVIDIA/CUDALibrarySamples](https://github.com/NVIDIA/CUDALibrarySamples/tree/master/cuTENSOR/contraction_trinary.cu) for a concrete example.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateContractionTrinary`] followed by [`cutensorCreatePlan`]).
/// - `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.
/// - `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.
/// - `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.
/// - `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.
/// - `beta`: Scaling for D. Its data type is determined by ‘descCompute’ (see cutensorOperationDescriptorGetAttribute(desc, CUTENSOR_OPERATION_SCALAR_TYPE)). Pointer to the host memory.
/// - `D`: Pointer to the data corresponding to D. Pointer to the GPU-accessible memory.
/// - `E`: Pointer to the data corresponding to E. Pointer to the GPU-accessible memory.
/// - `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).
/// - `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).
/// - `stream`: The CUDA stream in which all the computation is performed.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorContractTrinary(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const ::core::ffi::c_void,
B: *const ::core::ffi::c_void,
C: *const ::core::ffi::c_void,
beta: *const ::core::ffi::c_void,
D: *const ::core::ffi::c_void,
E: *mut ::core::ffi::c_void,
workspace: *mut ::core::ffi::c_void,
workspaceSize: u64,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Create a block-sparse tensor descriptor.
///
/// A block-sparse tensor descriptor fully specifies the data layout of a block-sparse tensor (currently limited to up to 8 modes).
///
/// 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:
///
/// | | | |
/// | --- | --- | --- |
/// | 4 x 2 | | 4 x 7 |
/// | | 2 x 3 | |
/// | | 3 x 3 | 3 x 7 |
/// | 4 x 2 | | |
/// | | 5 x 3 | 5 x 7 |
///
/// 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.
///
/// Moreover, we only store the non-zero blocks (blocks that are zero are left blank in the above representation).
///
/// To be precise, the above block-sparse tensor could be created via:
///
/// As an example:
///
/// * 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.
/// * 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.
/// * 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.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
///
/// # Parameters
///
/// - `handle`: The library handle.
/// - `desc`: The resulting block-sparse tensor descriptor.
/// - `numModes`: The number of modes. Currently, a maximum of 8 modes is supported.
/// - `numNonZeroBlocks`: The number of non-zero blocks in the block-sparse tensor.
/// - `numSectionsPerMode`: The number of sections of each mode (host array of size `numModes`).
/// - `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.
/// - `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.
/// - `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.
/// - `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`].
pub fn cutensorCreateBlockSparseTensorDescriptor(
handle: cutensorHandle_t,
desc: *mut cutensorBlockSparseTensorDescriptor_t,
numModes: u32,
numNonZeroBlocks: u64,
numSectionsPerMode: *const u32,
extent: *const i64,
nonZeroCoordinates: *const i32,
stride: *const i64,
dataType: cudaDataType_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Frees all resources related to the provided block-sparse tensor descriptor.
///
/// Remark
///
/// blocking, no reentrant, and thread-safe.
pub fn cutensorDestroyBlockSparseTensorDescriptor(
desc: cutensorBlockSparseTensorDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// 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}$.
///
/// Allocates data for `desc` to be used to perform a block-sparse tensor contraction of the form:
/// $$
/// \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}}).
/// $$
///
/// 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.
///
/// 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:
///
/// | typeA | typeB | typeC | typeD | descCompute | typeScalar |
/// | --- | --- | --- | --- | --- | --- |
/// | [`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`] |
/// | [`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`] |
/// | [`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`] |
/// | [`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`] |
///
/// 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.
///
/// For example, let A, B, and C be block matrices and consider the ordinary matrix-matrix product $C_{mn}=A_{mk}B_{kn}$. Then:
///
/// * 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.
/// * Mode ‘n’: C and B need to have the same number of block-columns of matching size
/// * 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.
///
/// 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.
///
/// See [`cutensorCreatePlan`] to create the plan, [`cutensorEstimateWorkspaceSize`] to compute the required workspace, and finally [`cutensorBlockSparseContract`] to perform the actual contraction.
///
/// The user is responsible for calling [`cutensorDestroyOperationDescriptor`] to free the resources associated with the descriptor.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `desc`: This opaque struct gets allocated and filled with the information that encodes the tensor contraction operation.
/// - `descA`: The descriptor that holds the information about the data type, modes, sections, section extents, strides, and non-zero blocks of A.
/// - `modeA`: Array with ‘nmodeA’ entries that represent the modes of A. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
/// - `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.
/// - `descB`: The descriptor that holds information about the data type, modes, sections, section extents, strides, and non-zero blocks of B.
/// - `modeB`: Array with ‘nmodeB’ entries that represent the modes of B. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
/// - `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.
/// - `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.
/// - `modeC`: Array with ‘nmodeC’ entries that represent the modes of C. Sections, i.e., block-sizes, must match among the involved block-sparse tensors.
/// - `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.
/// - `descD`: For now, this must be the same opaque pointer as descC, and the layouts of C and D must be identical.
/// - `modeD`: Array with ‘nmodeD’ entries that represent the modes of D (must be identical to modeC for now).
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if tensor dimensions or modes or section sizes have an illegal value.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if the combination of data types or operations is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully without error.
pub fn cutensorCreateBlockSparseContraction(
handle: cutensorHandle_t,
desc: *mut cutensorOperationDescriptor_t,
descA: cutensorBlockSparseTensorDescriptor_t,
modeA: *const i32,
opA: cutensorOperator_t,
descB: cutensorBlockSparseTensorDescriptor_t,
modeB: *const i32,
opB: cutensorOperator_t,
descC: cutensorBlockSparseTensorDescriptor_t,
modeC: *const i32,
opC: cutensorOperator_t,
descD: cutensorBlockSparseTensorDescriptor_t,
modeD: *const i32,
descCompute: cutensorComputeDescriptor_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This routine computes the block-sparse tensor contraction $D = alpha \\* A \\* B + beta \\* C$.
/// $$
/// \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha \\* \mathcal{A}_{{modes}_\mathcal{A}} B_{{modes}_\mathcal{B}} + \beta \mathcal{C}_{{modes}_\mathcal{C}}
/// $$
///
/// The active CUDA device must match the CUDA device that was active at the time at which the plan was created.
///
/// 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`.
///
/// # Parameters
///
/// - `handle`: Opaque handle holding cuTENSOR’s library context.
/// - `plan`: Opaque handle holding the contraction execution plan (created by [`cutensorCreateBlockSparseContraction`] followed by [`cutensorCreatePlan`]).
/// - `alpha`: Scaling for A\*B. Its data type is determined by ‘descCompute’ (see [`cutensorCreateBlockSparseContraction`]). Pointer to host memory.
/// - `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.
/// - `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.
/// - `beta`: Scaling for C. Its data type is determined by ‘descCompute’ (see [`cutensorCreateBlockSparseContraction`]). Pointer to host memory.
/// - `C`: Host-array of size numNonZeroBlocks(C), containing pointers to GPU-accessible memory, corresponding the blocks of C.
/// - `D`: Host-array of size numNonZeroBlocks(D), containing pointers to GPU-accessible memory, corresponding the blocks of D.
/// - `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).
/// - `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.
/// - `stream`: The CUDA stream to which all of the computation is synchronised.
///
/// # Return value
///
/// - [`cutensorStatus_t::CUTENSOR_STATUS_ARCH_MISMATCH`]: if the plan was created for a different device than the currently active device.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: if some unknown CUDA error has occurred (e.g., out of memory).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INSUFFICIENT_DRIVER`]: if the driver is insufficient.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: if some input data is invalid (this typically indicates an user error).
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_INITIALIZED`]: if the handle is not initialized.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: if operation is not supported.
/// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
pub fn cutensorBlockSparseContract(
handle: cutensorHandle_t,
plan: cutensorPlan_t,
alpha: *const ::core::ffi::c_void,
A: *const *const ::core::ffi::c_void,
B: *const *const ::core::ffi::c_void,
beta: *const ::core::ffi::c_void,
C: *const *const ::core::ffi::c_void,
D: *const *mut ::core::ffi::c_void,
workspace: *mut ::core::ffi::c_void,
workspaceSize: u64,
stream: cudaStream_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// Returns the description string for an error code.
///
/// Remark
///
/// non-blocking, no reentrant, and thread-safe.
pub fn cutensorGetErrorString(error: cutensorStatus_t) -> *const ::core::ffi::c_char;
}
unsafe extern "C" {
/// Returns Version number of the CUTENSOR library.
pub fn cutensorGetVersion() -> size_t;
}
unsafe extern "C" {
/// Returns version number of the CUDA runtime that cuTENSOR was compiled against.
///
/// Can be compared against the CUDA runtime version from cudaRuntimeGetVersion().
pub fn cutensorGetCudartVersion() -> size_t;
}
unsafe extern "C" {
/// This function sets the logging callback routine.
pub fn cutensorLoggerSetCallback(
callback: cutensorLoggerCallback_t,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function sets the logging output file.
pub fn cutensorLoggerSetFile(file: *mut FILE) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function opens a logging output file in the given path.
pub fn cutensorLoggerOpenFile(
logFile: *const ::core::ffi::c_char,
) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function sets the value of the logging level.
pub fn cutensorLoggerSetLevel(level: i32) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function sets the value of the log mask.
pub fn cutensorLoggerSetMask(mask: i32) -> cutensorStatus_t;
}
unsafe extern "C" {
/// This function disables logging for the entire run.
pub fn cutensorLoggerForceDisable() -> cutensorStatus_t;
}