Skip to main content

singe_cutensor/
types.rs

1use std::fmt::{self, Display, Formatter};
2
3use num_enum::{IntoPrimitive, TryFromPrimitive};
4use singe_cutensor_sys as sys;
5
6use singe_core::impl_enum_conversion;
7
8/// Algorithm used to perform a tensor operation.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
10#[repr(i32)]
11pub enum Algorithm {
12    /// More time-consuming than CUTENSOR_DEFAULT, but typically provides a more accurate kernel selection.
13    DefaultPatient = sys::cutensorAlgo_t::CUTENSOR_ALGO_DEFAULT_PATIENT as _,
14    /// Choose the GETT algorithm (only applicable to contractions).
15    Gett = sys::cutensorAlgo_t::CUTENSOR_ALGO_GETT as _,
16    /// Transpose (A or B) + GETT (only applicable to contractions).
17    Tgett = sys::cutensorAlgo_t::CUTENSOR_ALGO_TGETT as _,
18    /// Transpose-Transpose-GEMM-Transpose (requires additional memory) (only applicable to contractions).
19    Ttgt = sys::cutensorAlgo_t::CUTENSOR_ALGO_TTGT as _,
20    /// A performance model chooses the appropriate algorithm and kernel.
21    Default = sys::cutensorAlgo_t::CUTENSOR_ALGO_DEFAULT as _,
22}
23
24impl_enum_conversion!(i32, sys::cutensorAlgo_t, Algorithm);
25
26impl Display for Algorithm {
27    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
28        match self {
29            Self::DefaultPatient => write!(f, "CUTENSOR_ALGO_DEFAULT_PATIENT"),
30            Self::Gett => write!(f, "CUTENSOR_ALGO_GETT"),
31            Self::Tgett => write!(f, "CUTENSOR_ALGO_TGETT"),
32            Self::Ttgt => write!(f, "CUTENSOR_ALGO_TTGT"),
33            Self::Default => write!(f, "CUTENSOR_ALGO_DEFAULT"),
34        }
35    }
36}
37
38/// Encodes cuTENSOR's legacy compute type.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
40#[repr(u32)]
41pub enum ComputeType {
42    F16 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_16F as _,
43    Bf16 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_16BF as _,
44    Tf32 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_TF32 as _,
45    Tf32x3 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_3XTF32 as _,
46    F32 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_32F as _,
47    F64 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_64F as _,
48    U8 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_8U as _,
49    I8 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_8I as _,
50    U32 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_32U as _,
51    I32 = sys::cutensorComputeType_t::CUTENSOR_COMPUTE_32I as _,
52}
53
54impl_enum_conversion!(sys::cutensorComputeType_t, ComputeType);
55
56impl Display for ComputeType {
57    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
58        match self {
59            Self::F16 => write!(f, "CUTENSOR_COMPUTE_16F"),
60            Self::Bf16 => write!(f, "CUTENSOR_COMPUTE_16BF"),
61            Self::Tf32 => write!(f, "CUTENSOR_COMPUTE_TF32"),
62            Self::Tf32x3 => write!(f, "CUTENSOR_COMPUTE_3XTF32"),
63            Self::F32 => write!(f, "CUTENSOR_COMPUTE_32F"),
64            Self::F64 => write!(f, "CUTENSOR_COMPUTE_64F"),
65            Self::U8 => write!(f, "CUTENSOR_COMPUTE_8U"),
66            Self::I8 => write!(f, "CUTENSOR_COMPUTE_8I"),
67            Self::U32 => write!(f, "CUTENSOR_COMPUTE_32U"),
68            Self::I32 => write!(f, "CUTENSOR_COMPUTE_32I"),
69        }
70    }
71}
72
73/// Unary and binary element-wise operations supported by cuTENSOR.
74#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
75#[repr(u32)]
76pub enum Operator {
77    /// Identity operator; elements are not changed.
78    Identity = sys::cutensorOperator_t::CUTENSOR_OP_IDENTITY as _,
79    /// Square root.
80    Sqrt = sys::cutensorOperator_t::CUTENSOR_OP_SQRT as _,
81    /// Rectified linear unit.
82    Relu = sys::cutensorOperator_t::CUTENSOR_OP_RELU as _,
83    /// Complex conjugate.
84    Conj = sys::cutensorOperator_t::CUTENSOR_OP_CONJ as _,
85    /// Reciprocal.
86    Rcp = sys::cutensorOperator_t::CUTENSOR_OP_RCP as _,
87    /// y=1/(1+exp(-x)).
88    Sigmoid = sys::cutensorOperator_t::CUTENSOR_OP_SIGMOID as _,
89    /// y=tanh(x).
90    Tanh = sys::cutensorOperator_t::CUTENSOR_OP_TANH as _,
91    /// Exponentiation.
92    Exp = sys::cutensorOperator_t::CUTENSOR_OP_EXP as _,
93    /// Log (base e).
94    Log = sys::cutensorOperator_t::CUTENSOR_OP_LOG as _,
95    /// Absolute value.
96    Abs = sys::cutensorOperator_t::CUTENSOR_OP_ABS as _,
97    /// Negation.
98    Neg = sys::cutensorOperator_t::CUTENSOR_OP_NEG as _,
99    /// Sine.
100    Sin = sys::cutensorOperator_t::CUTENSOR_OP_SIN as _,
101    /// Cosine.
102    Cos = sys::cutensorOperator_t::CUTENSOR_OP_COS as _,
103    /// Tangent.
104    Tan = sys::cutensorOperator_t::CUTENSOR_OP_TAN as _,
105    /// Hyperbolic sine.
106    Sinh = sys::cutensorOperator_t::CUTENSOR_OP_SINH as _,
107    /// Hyperbolic cosine.
108    Cosh = sys::cutensorOperator_t::CUTENSOR_OP_COSH as _,
109    /// Inverse sine.
110    Asin = sys::cutensorOperator_t::CUTENSOR_OP_ASIN as _,
111    /// Inverse cosine.
112    Acos = sys::cutensorOperator_t::CUTENSOR_OP_ACOS as _,
113    /// Inverse tangent.
114    Atan = sys::cutensorOperator_t::CUTENSOR_OP_ATAN as _,
115    /// Inverse hyperbolic sine.
116    Asinh = sys::cutensorOperator_t::CUTENSOR_OP_ASINH as _,
117    /// Inverse hyperbolic cosine.
118    Acosh = sys::cutensorOperator_t::CUTENSOR_OP_ACOSH as _,
119    /// Inverse hyperbolic tangent.
120    Atanh = sys::cutensorOperator_t::CUTENSOR_OP_ATANH as _,
121    /// Ceiling.
122    Ceil = sys::cutensorOperator_t::CUTENSOR_OP_CEIL as _,
123    /// Floor.
124    Floor = sys::cutensorOperator_t::CUTENSOR_OP_FLOOR as _,
125    /// Mish y=x\*tanh(softplus(x)).
126    Mish = sys::cutensorOperator_t::CUTENSOR_OP_MISH as _,
127    /// Swish y=x\*sigmoid(x).
128    Swish = sys::cutensorOperator_t::CUTENSOR_OP_SWISH as _,
129    /// Softplus y=log(exp(x)+1).
130    SoftPlus = sys::cutensorOperator_t::CUTENSOR_OP_SOFT_PLUS as _,
131    /// Softsign y=x/(abs(x)+1).
132    SoftSign = sys::cutensorOperator_t::CUTENSOR_OP_SOFT_SIGN as _,
133    /// Addition of two elements.
134    Add = sys::cutensorOperator_t::CUTENSOR_OP_ADD as _,
135    /// Multiplication of two elements.
136    Mul = sys::cutensorOperator_t::CUTENSOR_OP_MUL as _,
137    /// Maximum of two elements.
138    Max = sys::cutensorOperator_t::CUTENSOR_OP_MAX as _,
139    /// Minimum of two elements.
140    Min = sys::cutensorOperator_t::CUTENSOR_OP_MIN as _,
141    /// Reserved for internal use only.
142    Unknown = sys::cutensorOperator_t::CUTENSOR_OP_UNKNOWN as _,
143}
144
145impl_enum_conversion!(sys::cutensorOperator_t, Operator);
146
147impl Display for Operator {
148    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
149        match self {
150            Self::Identity => write!(f, "CUTENSOR_OP_IDENTITY"),
151            Self::Sqrt => write!(f, "CUTENSOR_OP_SQRT"),
152            Self::Relu => write!(f, "CUTENSOR_OP_RELU"),
153            Self::Conj => write!(f, "CUTENSOR_OP_CONJ"),
154            Self::Rcp => write!(f, "CUTENSOR_OP_RCP"),
155            Self::Sigmoid => write!(f, "CUTENSOR_OP_SIGMOID"),
156            Self::Tanh => write!(f, "CUTENSOR_OP_TANH"),
157            Self::Exp => write!(f, "CUTENSOR_OP_EXP"),
158            Self::Log => write!(f, "CUTENSOR_OP_LOG"),
159            Self::Abs => write!(f, "CUTENSOR_OP_ABS"),
160            Self::Neg => write!(f, "CUTENSOR_OP_NEG"),
161            Self::Sin => write!(f, "CUTENSOR_OP_SIN"),
162            Self::Cos => write!(f, "CUTENSOR_OP_COS"),
163            Self::Tan => write!(f, "CUTENSOR_OP_TAN"),
164            Self::Sinh => write!(f, "CUTENSOR_OP_SINH"),
165            Self::Cosh => write!(f, "CUTENSOR_OP_COSH"),
166            Self::Asin => write!(f, "CUTENSOR_OP_ASIN"),
167            Self::Acos => write!(f, "CUTENSOR_OP_ACOS"),
168            Self::Atan => write!(f, "CUTENSOR_OP_ATAN"),
169            Self::Asinh => write!(f, "CUTENSOR_OP_ASINH"),
170            Self::Acosh => write!(f, "CUTENSOR_OP_ACOSH"),
171            Self::Atanh => write!(f, "CUTENSOR_OP_ATANH"),
172            Self::Ceil => write!(f, "CUTENSOR_OP_CEIL"),
173            Self::Floor => write!(f, "CUTENSOR_OP_FLOOR"),
174            Self::Mish => write!(f, "CUTENSOR_OP_MISH"),
175            Self::Swish => write!(f, "CUTENSOR_OP_SWISH"),
176            Self::SoftPlus => write!(f, "CUTENSOR_OP_SOFT_PLUS"),
177            Self::SoftSign => write!(f, "CUTENSOR_OP_SOFT_SIGN"),
178            Self::Add => write!(f, "CUTENSOR_OP_ADD"),
179            Self::Mul => write!(f, "CUTENSOR_OP_MUL"),
180            Self::Max => write!(f, "CUTENSOR_OP_MAX"),
181            Self::Min => write!(f, "CUTENSOR_OP_MIN"),
182            Self::Unknown => write!(f, "CUTENSOR_OP_UNKNOWN"),
183        }
184    }
185}
186
187/// Controls the workspace amount suggested by [`Plan::estimate_workspace_size`](crate::plan::Plan::estimate_workspace_size).
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
189#[repr(u32)]
190pub enum WorkspacePreference {
191    /// Least memory requirement; at least one algorithm is available.
192    Min = sys::cutensorWorksizePreference_t::CUTENSOR_WORKSPACE_MIN as _,
193    /// Aims to attain high performance while also reducing the workspace requirement.
194    Default = sys::cutensorWorksizePreference_t::CUTENSOR_WORKSPACE_DEFAULT as _,
195    /// Highest memory requirement; all algorithms are available.
196    Max = sys::cutensorWorksizePreference_t::CUTENSOR_WORKSPACE_MAX as _,
197}
198
199impl_enum_conversion!(sys::cutensorWorksizePreference_t, WorkspacePreference);
200
201impl Display for WorkspacePreference {
202    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
203        match self {
204            Self::Min => write!(f, "CUTENSOR_WORKSPACE_MIN"),
205            Self::Default => write!(f, "CUTENSOR_WORKSPACE_DEFAULT"),
206            Self::Max => write!(f, "CUTENSOR_WORKSPACE_MAX"),
207        }
208    }
209}
210
211/// Controls what is considered a cache hit.
212#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
213#[repr(u32)]
214pub enum CacheMode {
215    /// Plans are not cached.
216    None = sys::cutensorCacheMode_t::CUTENSOR_CACHE_MODE_NONE as _,
217    /// All descriptor parameters must match the cached plan.
218    Pedantic = sys::cutensorCacheMode_t::CUTENSOR_CACHE_MODE_PEDANTIC as _,
219}
220
221impl_enum_conversion!(sys::cutensorCacheMode_t, CacheMode);
222
223impl Display for CacheMode {
224    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
225        match self {
226            Self::None => write!(f, "CUTENSOR_CACHE_MODE_NONE"),
227            Self::Pedantic => write!(f, "CUTENSOR_CACHE_MODE_PEDANTIC"),
228        }
229    }
230}
231
232/// Attributes of a cuTENSOR operation descriptor that can be read or modified.
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
234#[repr(u32)]
235pub enum OperationDescriptorAttribute {
236    /// `i32` tag that distinguishes otherwise identical problems in the software-managed plan cache.
237    /// (default value: 0).
238    Tag = sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_TAG as _,
239    /// [`DataType`](singe_cuda::data_type::DataType): data type of the scaling factors.
240    ScalarType =
241        sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE as _,
242    /// `f32`: number of floating-point operations necessary to perform this operation, assuming all scalars are nonzero unless otherwise specified.
243    Flops = sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_FLOPS as _,
244    /// `f32`: minimal number of bytes transferred from or to global memory, assuming all scalars are nonzero unless otherwise specified.
245    MovedBytes =
246        sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES as _,
247    /// `u32` array of length `desc_out.num_modes`; entry `i` is the number of padded values to the left of dimension `i`.
248    PaddingLeft =
249        sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_PADDING_LEFT
250            as _,
251    /// `u32` array of length `desc_out.num_modes`; entry `i` is the number of padded values to the right of dimension `i`.
252    PaddingRight =
253        sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_PADDING_RIGHT
254            as _,
255    /// Host-side pointer to an element of the same type as the output tensor: constant padding value.
256    PaddingValue =
257        sys::cutensorOperationDescriptorAttribute_t::CUTENSOR_OPERATION_DESCRIPTOR_PADDING_VALUE
258            as _,
259}
260
261impl_enum_conversion!(
262    sys::cutensorOperationDescriptorAttribute_t,
263    OperationDescriptorAttribute
264);
265
266impl Display for OperationDescriptorAttribute {
267    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
268        match self {
269            Self::Tag => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_TAG"),
270            Self::ScalarType => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_SCALAR_TYPE"),
271            Self::Flops => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_FLOPS"),
272            Self::MovedBytes => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_MOVED_BYTES"),
273            Self::PaddingLeft => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_PADDING_LEFT"),
274            Self::PaddingRight => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_PADDING_RIGHT"),
275            Self::PaddingValue => write!(f, "CUTENSOR_OPERATION_DESCRIPTOR_PADDING_VALUE"),
276        }
277    }
278}
279
280/// Attributes of a [`PlanPreference`](crate::plan::PlanPreference) that can be read or modified.
281#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
282#[repr(u32)]
283pub enum PlanPreferenceAttribute {
284    /// [`AutotuneMode`]: determines whether recurrent executions of the plan autotune.
285    AutotuneMode =
286        sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_AUTOTUNE_MODE as _,
287    /// [`CacheMode`]: determines whether the algorithm or kernel for this plan is cached and controls what is considered a cache hit.
288    CacheMode = sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_CACHE_MODE as _,
289    /// `i32`: only applicable when [`PlanPreferenceAttribute::CacheMode`] is set to [`AutotuneMode::Incremental`].
290    IncrementalCount =
291        sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_INCREMENTAL_COUNT as _,
292    /// [`Algorithm`]: fixes the algorithm.
293    Algorithm = sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_ALGO as _,
294    /// `i32`: fixes a kernel subvariant of an algorithm; for example, `kernel_rank == 1` with [`Algorithm::Tgett`] selects the second-best GETT kernel variant according to cuTENSOR's performance model, while `kernel_rank == 2` selects the third-best.
295    KernelRank = sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_KERNEL_RANK as _,
296    /// [`JitMode`]: determines whether just-in-time compilation is enabled (default: [`JitMode::None`]).
297    JitMode = sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_JIT as _,
298    /// `i32`: plan for a specific GPU architecture instead of the architecture associated with the context.
299    /// The value encodes the SM version as `10 * SM.major + SM.minor`.
300    /// Currently only SM versions 80, 90 and 100 are supported.
301    GpuArch = sys::cutensorPlanPreferenceAttribute_t::CUTENSOR_PLAN_PREFERENCE_GPU_ARCH as _,
302}
303
304impl_enum_conversion!(
305    sys::cutensorPlanPreferenceAttribute_t,
306    PlanPreferenceAttribute
307);
308
309impl Display for PlanPreferenceAttribute {
310    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
311        match self {
312            Self::AutotuneMode => write!(f, "CUTENSOR_PLAN_PREFERENCE_AUTOTUNE_MODE"),
313            Self::CacheMode => write!(f, "CUTENSOR_PLAN_PREFERENCE_CACHE_MODE"),
314            Self::IncrementalCount => write!(f, "CUTENSOR_PLAN_PREFERENCE_INCREMENTAL_COUNT"),
315            Self::Algorithm => write!(f, "CUTENSOR_PLAN_PREFERENCE_ALGO"),
316            Self::KernelRank => write!(f, "CUTENSOR_PLAN_PREFERENCE_KERNEL_RANK"),
317            Self::JitMode => write!(f, "CUTENSOR_PLAN_PREFERENCE_JIT"),
318            Self::GpuArch => write!(f, "CUTENSOR_PLAN_PREFERENCE_GPU_ARCH"),
319        }
320    }
321}
322
323/// Controls cuTENSOR autotuning behavior.
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
325#[repr(u32)]
326pub enum AutotuneMode {
327    /// Indicates no autotuning (default); the cache reduces plan-creation overhead.
328    /// On a cache hit, the cached plan is reused; otherwise the plan cache is ignored.
329    None = sys::cutensorAutotuneMode_t::CUTENSOR_AUTOTUNE_MODE_NONE as _,
330    /// Indicates incremental autotuning.
331    /// Each corresponding [`sys::cutensorCreatePlan`] invocation creates a plan based on a different algorithm or kernel.
332    /// [`PlanPreferenceAttribute::IncrementalCount`] defines the maximum number of kernels tested.
333    /// May choose different algorithms across plan creations, so it does not
334    /// guarantee bitwise-identical results.
335    Incremental = sys::cutensorAutotuneMode_t::CUTENSOR_AUTOTUNE_MODE_INCREMENTAL as _,
336}
337
338impl_enum_conversion!(sys::cutensorAutotuneMode_t, AutotuneMode);
339
340impl Display for AutotuneMode {
341    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
342        match self {
343            Self::None => write!(f, "CUTENSOR_AUTOTUNE_MODE_NONE"),
344            Self::Incremental => write!(f, "CUTENSOR_AUTOTUNE_MODE_INCREMENTAL"),
345        }
346    }
347}
348
349/// Controls cuTENSOR just-in-time compilation behavior.
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
351#[repr(u32)]
352pub enum JitMode {
353    /// Indicates that no kernel is just-in-time compiled.
354    None = sys::cutensorJitMode_t::CUTENSOR_JIT_MODE_NONE as _,
355    /// Indicates that the corresponding plan tries to compile a dedicated kernel for the given operation.
356    /// Only supported for GPUs with compute capability &gt;= 8.0 (Ampere or newer).
357    Default = sys::cutensorJitMode_t::CUTENSOR_JIT_MODE_DEFAULT as _,
358}
359
360impl_enum_conversion!(sys::cutensorJitMode_t, JitMode);
361
362impl Display for JitMode {
363    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
364        match self {
365            Self::None => write!(f, "CUTENSOR_JIT_MODE_NONE"),
366            Self::Default => write!(f, "CUTENSOR_JIT_MODE_DEFAULT"),
367        }
368    }
369}
370
371/// Attributes of a cuTENSOR plan that can be retrieved via [`sys::cutensorPlanGetAttribute`].
372#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
373#[repr(u32)]
374pub enum PlanAttribute {
375    /// Exact required workspace in bytes needed to execute the plan.
376    RequiredWorkspace = sys::cutensorPlanAttribute_t::CUTENSOR_PLAN_REQUIRED_WORKSPACE as _,
377}
378
379impl_enum_conversion!(sys::cutensorPlanAttribute_t, PlanAttribute);
380
381impl Display for PlanAttribute {
382    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
383        match self {
384            Self::RequiredWorkspace => write!(f, "CUTENSOR_PLAN_REQUIRED_WORKSPACE"),
385        }
386    }
387}
388
389#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
390#[repr(i32)]
391pub enum LoggerLevel {
392    Off = 0,
393    Error = 1,
394    PerformanceTrace = 2,
395    PerformanceHints = 3,
396    HeuristicsTrace = 4,
397    ApiTrace = 5,
398}
399
400impl LoggerLevel {
401    pub const fn as_raw(self) -> i32 {
402        self as i32
403    }
404}
405
406bitflags::bitflags! {
407    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
408    pub struct LoggerMask: i32 {
409        const OFF = 0;
410        const ERROR = 1;
411        const PERFORMANCE_TRACE = 2;
412        const PERFORMANCE_HINTS = 4;
413        const HEURISTICS_TRACE = 8;
414        const API_TRACE = 16;
415    }
416}
417
418#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
419#[repr(transparent)]
420pub struct Mode(i32);
421
422impl Mode {
423    pub const fn new(raw: i32) -> Self {
424        Self(raw)
425    }
426
427    pub const fn from_char(mode: char) -> Self {
428        Self(mode as i32)
429    }
430
431    pub const fn as_raw(self) -> i32 {
432        self.0
433    }
434}
435
436impl From<char> for Mode {
437    fn from(value: char) -> Self {
438        Self::from_char(value)
439    }
440}
441
442impl From<i32> for Mode {
443    fn from(value: i32) -> Self {
444        Self::new(value)
445    }
446}
447
448impl From<Mode> for i32 {
449    fn from(value: Mode) -> Self {
450        value.as_raw()
451    }
452}
453
454impl Display for Mode {
455    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
456        if let Some(ch) = char::from_u32(self.0 as u32)
457            && !ch.is_control()
458        {
459            return write!(f, "{ch}");
460        }
461
462        write!(f, "{}", self.0)
463    }
464}