//
//  MLCTypes.h
//  MLCompute
//
//  Copyright © 2019 Apple. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <MLCompute/MLCDefines.h>

#ifndef MLComputeTypes_h
#define MLComputeTypes_h

#ifdef __cplusplus
extern "C" {
#endif

@class MLCTensor;

/*! @abstract A callback completion handler you execute when a graph finishes execution.
 */
typedef void (^MLCGraphCompletionHandler)(MLCTensor __autoreleasing * _Nullable resultTensor,
                                          NSError * _Nullable error,
                                          NSTimeInterval executionTime);

#pragma mark - General Types

/*!
 *  @enum      MLCDataType
 *  @abstract  A tensor data type.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCDataType) {
    MLCDataTypeInvalid NS_SWIFT_UNAVAILABLE("") = 0,
    /*! The 32-bit floating-point data type.
     */
    MLCDataTypeFloat32 = 1,
    /*! The 16-bit floating-point data type.
     */
    MLCDataTypeFloat16 MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0)) = 3,
    /*! The Boolean data type.
     */
    MLCDataTypeBoolean = 4,
    /*! The 64-bit integer data type.
     */
    MLCDataTypeInt64   = 5,
    /*! The 32-bit integer data type.
     */
    MLCDataTypeInt32   = 7,

    /*! The 8-bit integer data type.
     */
    MLCDataTypeInt8 MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0)) = 8,
    /*! The 8-bit unsigned integer data type.
     */
    MLCDataTypeUInt8 MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0)) NS_SWIFT_NAME(uint8) = 9,

    // Must be last
    MLCDataTypeCount   NS_SWIFT_UNAVAILABLE(""), // holds the number of MLCDataTypes
};

/*!
 *  @enum      MLCRandomInitializerType
 *  @abstract  An initializer type you use to create a tensor with random data.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCRandomInitializerType) {
    MLCRandomInitializerTypeInvalid       NS_SWIFT_UNAVAILABLE("") = 0,
    /*! The uniform random initializer type.
     */
    MLCRandomInitializerTypeUniform       = 1,
    /*! The glorot uniform random initializer type.
     */
    MLCRandomInitializerTypeGlorotUniform = 2,
    /*! The Xavier random initializer type.
     */
    MLCRandomInitializerTypeXavier        = 3,

    // Must be last
    MLCRandomInitializerTypeCount         NS_SWIFT_UNAVAILABLE(""), // holds the number of MLCRandomInitializerType
};

/*!
 *  @enum       MLCDeviceType
 *  @abstract   A device type for execution of a neural network.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCDeviceType) {
    /*! The CPU device
     */
    MLCDeviceTypeCPU NS_SWIFT_NAME(cpu) = 0,
    /*! The GPU device.
     */
    MLCDeviceTypeGPU NS_SWIFT_NAME(gpu) = 1,
    /*! The any device type.  When selected, the framework will automatically use the appropriate devices to achieve the best
     *  performance.
     */
    MLCDeviceTypeAny = 2,
    /*! The  Apple Neural Engine device.  When selected, the framework will use the  Neural Engine to execute all layers that can be executed on it.
     *  Layers that cannot be executed on the ANE will run on the CPU or GPU.   The Neural Engine device must be explicitly selected.  MLDeviceTypeAny
     *  will not select the Neural Engine device.  In addition, this device can be used with inference graphs only.  This device cannot be used with a
     *  training graph or an inference graph that shares layers with a training graph.
     */
    MLCDeviceTypeANE MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0)) NS_SWIFT_NAME(ane) = 3,

    // Must be last
    MLCDeviceTypeCount  NS_SWIFT_UNAVAILABLE(""), // holds the number of MLCDeviceType
};

/*!
 *  @enum       MLCGraphCompilationOptions
 *  @abstract   A bitmask that specifies the options you use when compiling a graph.
 *  @discussion This is passed as an argument to the compileWithOptions method avalable on MLCTrainingGraph and MLCInferenceGraph
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_OPTIONS(uint64_t, MLCGraphCompilationOptions) {
    /*! No graph compilation options.
     */
    MLCGraphCompilationOptionsNone                 = 0x00,
    /*! The option to debug layers during graph compilation.
     *
     *  @discussion Include this option to disable various optimizations such as layer fusion, and ensure the framework synchronizes
     *      the resulting forward and gradients tensors host memory with device memory, for layers marked as debuggable.
     */
    MLCGraphCompilationOptionsDebugLayers          = 0x01,
    /*! The option to disable layer fusion during graph compilation.
     *
     *  @discussion Include this option to disable fusion of layers, which is an important optimization that helps performance and
     *      memory footprint.
     *  */
    MLCGraphCompilationOptionsDisableLayerFusion   = 0x02,
    /*! The option to link graphs during graph compilation.
     *
     *  @discussion Include this option when you link together one or more sub-graphs when executing the forward, gradient, and
     *      optimizer update. For example, if the full computation graph includes a layer that the framework doesn’t support, you’ll
     *      need to create multiple sub-graphs and link them together using \p MLCGraphCompilationOptionsLinkGraphs. When doing so,
     *      include this option when you call \p -compileWithOptions: for graphs you want to link together.
     */
    MLCGraphCompilationOptionsLinkGraphs           = 0x04,
    /*! The option to compute all gradients during graph compilation.
     *
     *  @discussion Include this option to compute gradients for layers with or without parameters that only take input tensors.
     *      For example, if the first layer of a graph is a convolution layer, the framework only computes the gradients for weights
     *      and biases associated with the convolution layer, but not the gradients for the input. Include this option if you want to
     *      compute all gradients for the input.
     */
    MLCGraphCompilationOptionsComputeAllGradients  = 0x08,
};

/*!
 *  @enum       MLCExecutionOptions
 *  @abstract   A bitmask that specifies the options you’ll use when executing a graph.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_OPTIONS(uint64_t, MLCExecutionOptions) {
    MLCExecutionOptionsNone = 0x00,
    /*! The option to skip writing input data to device memory.
     *
     *  @discussion this option to prevent writing the input tensors to device memory associated with these tensors when the framework
     *      executes the graph.
     */
    MLCExecutionOptionsSkipWritingInputDataToDevice = 0x01,

    /*! The option to execute the graph synchronously.
     *
     *  @discussion Include this option to wait until execution of the graph on specified device finishes before returning from the
     *      \p execute method.
     */
    MLCExecutionOptionsSynchronous = 0x02,

    /*! The option to return profiling information in the callback before returning from execution.
     *
     *  @discussion Include this option to return profliling information in the graph execute completion handler callback, including
     *      device execution time.
     */
    MLCExecutionOptionsProfiling = 0x04,

    /*! The option to execute the forward pass for inference only.
     *
     *  @discussion If you include this option and execute a training graph using one of the \p execute methods, such as
     *  \p -executeWithInputsData:lossLabelsData:lossLabelWeightsData:batchSize:options:completionHandler: , the framework only
     *      executes the forward pass of the training graph, and it executes that forward pass for inference only.
     *
     *      If you include this option and execute a training graph using one of the executeForward methods, such as
     *      \p -executeForwardWithBatchSize:options:completionHandler:), the framework executes the forward pass for inference only.
     */
    MLCExecutionOptionsForwardForInference = 0x08,

    /*! The option to enable additional per layer profiling information currently emitted using signposts.
     *
     *  @discussion The option to enable per layer profiling information emitted as signposts. The per layer information
     *      can be visualized using the Logging Instrument in Xcode's Instruments. This information may not be available for all MLCDevice.
     */
    MLCExecutionOptionsPerLayerProfiling MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0)) = 0x10,

};

#pragma mark - Layers

/*!
 *  @enum       MLCArithmeticOperation
 *  @abstract   The list of supported arithmetic operations.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCArithmeticOperation) {
    /*! An operation that calculates the elementwise sum of its two inputs.
     */
    MLCArithmeticOperationAdd      = 0,
    /*! An operation that calculates the elementwise difference of its two inputs.
     */
    MLCArithmeticOperationSubtract = 1,
    /*! An operation that calculates the elementwise product of its two inputs.
     */
    MLCArithmeticOperationMultiply = 2,
    /*! An operation that calculates the elementwise division of its two inputs.
     */
    MLCArithmeticOperationDivide   = 3,
    /*! An operation that calculates the elementwise floor of its two inputs.
     */
    MLCArithmeticOperationFloor    = 4,
    /*! An operation that calculates the elementwise round of its inputs.
     */
    MLCArithmeticOperationRound    = 5,
    /*! An operation that calculates the elementwise ceiling of its inputs.
     */
    MLCArithmeticOperationCeil     = 6,
    /*! An operation that calculates the elementwise square root of its inputs.
     */
    MLCArithmeticOperationSqrt     = 7,
    /*! An operation that calculates the elementwise reciprocal of the square root of its inputs.
     */
    MLCArithmeticOperationRsqrt    = 8,
    /*! An operation that calculates the elementwise sine of its inputs.
     */
    MLCArithmeticOperationSin      = 9,
    /*! An operation that calculates the elementwise cosine of its inputs.
     */
    MLCArithmeticOperationCos      = 10,
    /*! An operation that calculates the elementwise tangent of its inputs.
     */
    MLCArithmeticOperationTan      = 11,
    /*! An operation that calculates the elementwise inverse sine of its inputs.
     */
    MLCArithmeticOperationAsin     = 12,
    /*! An operation that calculates the elementwise inverse cosine of its inputs.
     */
    MLCArithmeticOperationAcos     = 13,
    /*! An operation that calculates the elementwise inverse tangent of its inputs.
     */
    MLCArithmeticOperationAtan     = 14,
    /*! An operation that calculates the elementwise hyperbolic sine of its inputs.
     */
    MLCArithmeticOperationSinh     = 15,
    /*! An operation that calculates the elementwise hyperbolic cosine of its inputs.
     */
    MLCArithmeticOperationCosh     = 16,
    /*! An operation that calculates the elementwise hyperbolic tangent of its inputs.
     */
    MLCArithmeticOperationTanh     = 17,
    /*! An operation that calculates the elementwise inverse hyperbolic sine of its inputs.
     */
    MLCArithmeticOperationAsinh    = 18,
    /*! An operation that calculates the elementwise inverse hyperbolic cosine of its inputs.
     */
    MLCArithmeticOperationAcosh    = 19,
    /*! An operation that calculates the elementwise inverse hyperbolic tangent of its inputs.
     */
    MLCArithmeticOperationAtanh    = 20,
    /*! An operation that calculates the elementwise first input raised to the power of its second input.
     */
    MLCArithmeticOperationPow      = 21,
    /*! An operation that calculates the elementwise result of e raised to the power of its input.
     */
    MLCArithmeticOperationExp      = 22,
    /*! An operation that calculates the elementwise result of 2 raised to the power of its input.
     */
    MLCArithmeticOperationExp2     = 23,
    /*! An operation that calculates the elementwise natural logarithm of its input.
     */
    MLCArithmeticOperationLog      = 24,
    /*! An operation that calculates the elementwise base 2 logarithm of its input.
     */
    MLCArithmeticOperationLog2     = 25,
    /*! An operation that calculates the elementwise product of its two inputs.  Returns 0 if y in x * y is zero, even if x is NaN or INF
     */
    MLCArithmeticOperationMultiplyNoNaN     MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 26,
    /*! An operations that calculates the elementwise division of its two inputs.  Returns 0 if the denominator is 0.
     */
    MLCArithmeticOperationDivideNoNaN       MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 27,
    /*! An operation that calculates the elementwise min of two inputs.
     */
    MLCArithmeticOperationMin               MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 28,
    /*! An operations that calculates the elementwise max of two inputs.
     */
    MLCArithmeticOperationMax               MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 29,

    // Must be last
    MLCArithmeticOperationCount    NS_SWIFT_UNAVAILABLE(""),
};

/*!
 *  @enum       MLCLossType
 *  @abstract   A loss function.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCLossType) {
    /*! The mean absolute error loss.
     */
    MLCLossTypeMeanAbsoluteError       = 0,
    /*! The mean squared error loss.
     */
    MLCLossTypeMeanSquaredError        = 1,
    /*! The softmax cross entropy loss.
     */
    MLCLossTypeSoftmaxCrossEntropy     = 2,
    /*! The sigmoid cross entropy loss.
     */
    MLCLossTypeSigmoidCrossEntropy     = 3,
    /*! The categorical cross entropy loss.
     */
    MLCLossTypeCategoricalCrossEntropy = 4,
    /*! The hinge loss.
     */
    MLCLossTypeHinge                   = 5,
    /*! The Huber loss.
     */
    MLCLossTypeHuber                   = 6,
    /*! The cosine distance loss.
     */
    MLCLossTypeCosineDistance          = 7,
    /*! The log loss.
     */
    MLCLossTypeLog                     = 8,

    // Must be last
    MLCLossTypeCount                   NS_SWIFT_UNAVAILABLE("")   // Holds the number of MLCLossTypes
};

/*!
 * @enum       MLCActivationType
 * @abstract   An activation type that you specify for an activation descriptor.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCActivationType) {
    /*! The identity activation type.
     */
    MLCActivationTypeNone                                               = 0,
    /*! The ReLU activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x >= 0 ? x : a * x
     *  \endcode
     */
    MLCActivationTypeReLU                 NS_SWIFT_NAME(relu)           = 1,
    /*! The linear activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = a * x + b
     *  \endcode
     */
    MLCActivationTypeLinear                                             = 2,
    /*! The sigmoid activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = 1 / (1 + e⁻ˣ)
     *  \endcode
     */
    MLCActivationTypeSigmoid                                            = 3,
    /*! The hard sigmoid activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = clamp((x * a) + b, 0, 1)
     *  \endcode
     */
    MLCActivationTypeHardSigmoid                                        = 4,
    /*! The hyperbolic tangent (TanH) activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = a * tanh(b * x)
     *  \endcode
     */
    MLCActivationTypeTanh                                               = 5,
    /*! The absolute activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = fabs(x)
     *  \endcode
     */
    MLCActivationTypeAbsolute                                           = 6,
    /*! The parametric soft plus activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = a * log(1 + e^(b * x))
     *  \endcode
     */
    MLCActivationTypeSoftPlus                                           = 7,
    /*! The parametric soft sign activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x / (1 + abs(x))
     *  \endcod
     */
    MLCActivationTypeSoftSign                                           = 8,
    /*! The parametric ELU activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x >= 0 ? x : a * (exp(x) - 1)
     *  \endcode
     */
    MLCActivationTypeELU                  NS_SWIFT_NAME(elu)            = 9,
    /*! The ReLUN activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = min((x >= 0 ? x : a * x), b)
     *  \endcode
     */
    MLCActivationTypeReLUN                NS_SWIFT_NAME(relun)          = 10,
    /*! The log sigmoid activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = log(1 / (1 + exp(-x)))
     *  \endcode
     */
    MLCActivationTypeLogSigmoid                                         = 11,
    /*! The SELU activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = scale * (max(0, x) + min(0, α * (exp(x) − 1)))
     *  \endcode
     *  where:
     *  \code
     *  α = 1.6732632423543772848170429916717
     *  scale = 1.0507009873554804934193349852946
     *  \endcode
     */
    MLCActivationTypeSELU                 NS_SWIFT_NAME(selu)           = 12,
    /*! The CELU activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = max(0, x) + min(0, a * (exp(x / a) − 1))
     *  \endcode
     */
    MLCActivationTypeCELU                 NS_SWIFT_NAME(celu)           = 13,
    /*! The hard shrink activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x, if x > a or x < −a, else 0
     *  \endcode
     */
    MLCActivationTypeHardShrink                                         = 14,
    /*! The soft shrink activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x - a, if x > a, x + a, if x < −a, else 0
     *  \endcode
     */
    MLCActivationTypeSoftShrink                                         = 15,
    /*! The hyperbolic tangent (TanH) shrink activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x - tanh(x)
     *  \endcode
     */
    MLCActivationTypeTanhShrink                                         = 16,
    /*! The threshold activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x, if x > a, else b
     *  \endcode
     */
    MLCActivationTypeThreshold                                          = 17,
    /*! The GELU activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = x * CDF(x)
     *  \endcode
     */
    MLCActivationTypeGELU                 NS_SWIFT_NAME(gelu)           = 18,
    /*! The hardswish activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = 0, if x <= -3
     *  f(x) = x, if x >= +3
     *  f(x) = x * (x + 3)/6, otherwise
     *  \endcode
     */
    MLCActivationTypeHardSwish            NS_SWIFT_NAME(hardSwish) MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5))     = 19,
    /*! The clamp activation type.
     *  @discussion This activation type implements the following function:
     *  \code
     *  f(x) = min(max(x, a), b)
     *  \endcode
     */
    MLCActivationTypeClamp                MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5))     = 20,

    // Must be last
    MLCActivationTypeCount                NS_SWIFT_UNAVAILABLE(""),
};

/*!
 * @enum       MLCConvolutionType
 * @abstract   A convolution type that you specify for a convolution descriptor.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCConvolutionType) {
    /*! The standard convolution type.
     */
    MLCConvolutionTypeStandard   = 0,
    /*! The transposed convolution type.
     */
    MLCConvolutionTypeTransposed = 1,
    /*! The depthwise convolution type.
     */
    MLCConvolutionTypeDepthwise  = 2,
};

/*!
 * @enum       MLCPaddingPolicy
 * @abstract   A padding policy that you specify for a convolution or pooling layer.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCPaddingPolicy) {
    /*! The "same" padding policy.
     */
    MLCPaddingPolicySame           = 0,
    /*! The "valid" padding policy.
     */
    MLCPaddingPolicyValid          = 1,
    /*! The choice to use explicitly specified padding sizes.
     */
    MLCPaddingPolicyUsePaddingSize = 2,
} NS_REFINED_FOR_SWIFT;

/*!
 *  @enum       MLCPaddingType
 *  @abstract   A padding type that you specify for a padding layer.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCPaddingType) {
    /*! The zero padding type.
     */
    MLCPaddingTypeZero      = 0,
    /*! The reflect padding type.
     */
    MLCPaddingTypeReflect   = 1,
    /*! The symmetric padding type.
     */
    MLCPaddingTypeSymmetric = 2,
    /*! The constant padding type.
     */
    MLCPaddingTypeConstant  = 3,
};

/*!
 *  @enum       MLCPoolingType
 *  @abstract   A pooling function type for a pooling layer.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCPoolingType) {
    /*! The max pooling type.
     */
    MLCPoolingTypeMax     = 1,
    /*! The average pooling type.
     */
    MLCPoolingTypeAverage = 2,
    /*! The L2-norm pooling type.
     */
    MLCPoolingTypeL2Norm  = 3,

    // Must be last
    MLCPoolingTypeCount   NS_SWIFT_UNAVAILABLE(""),
} NS_REFINED_FOR_SWIFT;

/*!
 *  @enum       MLCReductionType
 *  @abstract   A reduction operation type.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCReductionType) {
    /*! No reduction.
     */
    MLCReductionTypeNone                 = 0,
    /*! The sum reduction.
     */
    MLCReductionTypeSum                  = 1,
    /*! The mean reduction.
     */
    MLCReductionTypeMean                 = 2,
    /*! The max reduction.
     */
    MLCReductionTypeMax                  = 3,
    /*! The min reduction.
     */
    MLCReductionTypeMin                  = 4,
    /*! The argmax reduction.
     */
    MLCReductionTypeArgMax               = 5,
    /*! The argmin reduction.
     */
    MLCReductionTypeArgMin               = 6,
    /*! The L1norm reduction.
     */
    MLCReductionTypeL1Norm    MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 7,
    /*! Any(X) = X_0 || X_1 || ... X_n
     */
    MLCReductionTypeAny       MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 8,
    /*! Alf(X) = X_0 && X_1 && ... X_n
     */
    MLCReductionTypeAll       MLCOMPUTE_ENUM_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5)) = 9,
    
    MLCReductionTypeCount                NS_SWIFT_UNAVAILABLE(""),
};

/*!
 *  @enum       MLCRegularizationType
 *  @abstract
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCRegularizationType) {
    /*! No regularization.
     */
    MLCRegularizationTypeNone                   = 0,
    /*! The L1 regularization.
     */
    MLCRegularizationTypeL1   NS_SWIFT_NAME(l1) = 1,
    /*! The L2 regularization.
     */
    MLCRegularizationTypeL2   NS_SWIFT_NAME(l2) = 2,
};

/*!
 *  @enum       MLCSampleMode
 *  @abstract   A sampling mode for an upsample layer.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCSampleMode) {
    /*! The nearest sample mode.
     */
    MLCSampleModeNearest = 0,
    /*! The linear sample mode.
     */
    MLCSampleModeLinear  = 1,
};

/*!
 *  @enum       MLCSoftmaxOperation
 *  @abstract   A softmax operation.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(int32_t, MLCSoftmaxOperation) {
    /*! The standard softmax operation.
     */
    MLCSoftmaxOperationSoftmax    = 0,
    /*! The log softmax operation.
     */
    MLCSoftmaxOperationLogSoftmax = 1,
};

/*!
 * @enum       MLCLSTMResultMode
 * @abstract   A result mode for an LSTM layer.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.0, 14.0, 14.0)
typedef NS_ENUM(uint64_t, MLCLSTMResultMode) {
    /*! The output result mode. When selected for an LSTM layer, the layer will produce a single result tensor representing the final output of the LSTM.
     */
    MLCLSTMResultModeOutput = 0,
    /*! The output and states result mode. When selected for an LSTM layer, the layer will produce three result tensors representing the final output of
     *  the LSTM, the last hidden state, and the cell state, respectively.
     */
    MLCLSTMResultModeOutputAndStates = 1,
};

/*!
 *  @enum       MLCComparisonOperation
 *  @abstract   A comparison operation.
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(11.3, 14.5, 14.5)
typedef NS_ENUM(int32_t, MLCComparisonOperation) {
    MLCComparisonOperationEqual          = 0,
    MLCComparisonOperationNotEqual       = 1,
    MLCComparisonOperationLess           = 2,
    MLCComparisonOperationGreater        = 3,
    MLCComparisonOperationLessOrEqual    = 4,
    MLCComparisonOperationGreaterOrEqual = 5,
    MLCComparisonOperationLogicalAND     = 6,
    MLCComparisonOperationLogicalOR      = 7,
    MLCComparisonOperationLogicalNOT     = 8,
    MLCComparisonOperationLogicalNAND    = 9,
    MLCComparisonOperationLogicalNOR     = 10,
    MLCComparisonOperationLogicalXOR     = 11,

    // Must be last
    MLCComparisonOperationCount          NS_SWIFT_UNAVAILABLE(""),
};

/*!
 *  @enum       MLCGradientClippingType
 *  @abstract   The type of clipping applied to gradient
 */
MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14(12.0, 15.0, 15.0)
typedef NS_ENUM(int32_t, MLCGradientClippingType) {
    MLCGradientClippingTypeByValue      = 0,
    MLCGradientClippingTypeByNorm       = 1,
    MLCGradientClippingTypeByGlobalNorm = 2
};

NS_ASSUME_NONNULL_BEGIN
/*! @abstract Returns a textual description of the activation type, suitable for debugging.
 */
NSString *MLCActivationTypeDebugDescription(MLCActivationType activationType) NS_SWIFT_NAME(getter:MLCActivationType.debugDescription(self:));
/*! @abstract Returns a textual description of the arithmetic operation, suitable for debugging.
 */
NSString *MLCArithmeticOperationDebugDescription(MLCArithmeticOperation operation) NS_SWIFT_NAME(getter:MLCArithmeticOperation.debugDescription(self:));
/*! @abstract Returns a textual description of the padding policy, suitable for debugging.
 */
NSString *MLCPaddingPolicyDebugDescription(MLCPaddingPolicy paddingPolicy) NS_REFINED_FOR_SWIFT;
/*! @abstract Returns a textual description of the loss type, suitable for debugging.
 */
NSString *MLCLossTypeDebugDescription(MLCLossType lossType) NS_SWIFT_NAME(getter:MLCLossType.debugDescription(self:));
/*! @abstract Returns a textual description of the reduction type, suitable for debugging.
 */
NSString *MLCReductionTypeDebugDescription(MLCReductionType reductionType) NS_SWIFT_NAME(getter:MLCReductionType.debugDescription(self:));
/*! @abstract Returns a textual description of the padding type, suitable for debugging.
 */
NSString *MLCPaddingTypeDebugDescription(MLCPaddingType paddingType) NS_SWIFT_NAME(getter:MLCPaddingType.debugDescription(self:));
/*! @abstract Returns a textual description of the convolution type, suitable for debugging.
 */
NSString *MLCConvolutionTypeDebugDescription(MLCConvolutionType convolutionType) NS_SWIFT_NAME(getter:MLCConvolutionType.debugDescription(self:));
/*! @abstract Returns a textual description of the pooling type, suitable for debugging.
 */
NSString *MLCPoolingTypeDebugDescription(MLCPoolingType poolingType) NS_REFINED_FOR_SWIFT;
/*! @abstract Returns a textual description of the softmax operation, suitable for debugging.
 */
NSString *MLCSoftmaxOperationDebugDescription(MLCSoftmaxOperation operation) NS_SWIFT_NAME(getter:MLCSoftmaxOperation.debugDescription(self:));
/*! @abstract Returns a textual description of the sample mode, suitable for debugging.
 */
NSString *MLCSampleModeDebugDescription(MLCSampleMode mode) NS_SWIFT_NAME(getter:MLCSampleMode.debugDescription(self:));
/*! @abstract Returns a textual description of the LSTM result mode, suitable for debugging.
 */
NSString *MLCLSTMResultModeDebugDescription(MLCLSTMResultMode mode)
    NS_SWIFT_NAME(getter:MLCLSTMResultMode.debugDescription(self:));
/*! @abstract Returns a textual description of the comparison operation, suitable for debugging.
 */
NSString *MLCComparisonOperationDebugDescription(MLCComparisonOperation operation)
    NS_SWIFT_NAME(getter:MLCComparisonOperation.debugDescription(self:)) MLCOMPUTE_AVAILABLE_STARTING(macos(11.3), ios(14.5), tvos(14.5));
/*! @abstract Returns a textual description of the gradient clipping type, suitable for debugging.
 */
NSString *MLCGradientClippingTypeDebugDescription(MLCGradientClippingType gradientClippingType)
    NS_SWIFT_NAME(getter:MLCGradientClippingType.debugDescription(self:)) MLCOMPUTE_AVAILABLE_STARTING(macos(12.0), ios(15.0), tvos(15.0));

NS_ASSUME_NONNULL_END

#ifdef __cplusplus
}
#endif

#endif /* MLComputeTypes_h */
