// Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier:  MIT

#ifndef MIOPEN_GUARD_MIOPEN_H_
#define MIOPEN_GUARD_MIOPEN_H_

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wextern-c-compat"
#endif

#include <stddef.h>
#include <stdbool.h>
#include <miopen/config.h>
#include <miopen/export.h>

#if MIOPEN_BACKEND_OPENCL
#define CL_TARGET_OPENCL_VERSION 120
#if defined(__APPLE__) || defined(__MACOSX)
#include <OpenCL/cl.h>
#else
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
#include <CL/cl.h>
#endif

#elif MIOPEN_BACKEND_HIP
#include <hip/hip_runtime_api.h>
#endif

/*
 * @defgroup convolutions
 * @defgroup pooling
 * @defgroup handle
 * @defgroup layernorm
 * @defgroup LRN
 * @defgroup batchnorm
 * @defgroup activation
 * @defgroup tensor
 * @defgroup softmax
 * @defgroup RNN
 * @defgroup fusion
 * @defgroup LossFunction
 * @defgroup TensorReduce
 * @defgroup find2
 * @defgroup ReduceExtreme
 * @defgroup groupnorm
 * @defgroup cat
 * @defgroup SGD
 * @defgroup getitem
 * @defgroup ReduceCalculation
 * @defgroup RotaryPositionalEmbeddings
 * @defgroup ReLU
 *
 */

/*! Constructs type name from a struct */
#define MIOPEN_DECLARE_OBJECT(name) \
    struct name                     \
    {                               \
    };                              \
    typedef struct name* name##_t;

#ifdef __cplusplus
extern "C" {
#endif

#if MIOPEN_BACKEND_OPENCL
typedef cl_command_queue miopenAcceleratorQueue_t;
#elif MIOPEN_BACKEND_HIP
typedef hipStream_t miopenAcceleratorQueue_t;
#endif

/*! @ingroup handle
 * @brief Creates the miopenHandle_t type
 */
MIOPEN_DECLARE_OBJECT(miopenHandle);

/** @addtogroup handle
 *
 *  @{
 */

/*! @enum miopenStatus_t
 * Error codes that are returned by all MIOpen API calls.
 */
typedef enum
{
    miopenStatusSuccess              = 0, /*!< No errors */
    miopenStatusNotInitialized       = 1, /*!< Data not initialized. */
    miopenStatusInvalidValue         = 2, /*!< Incorrect variable value. */
    miopenStatusBadParm              = 3, /*!< Incorrect parameter detected. */
    miopenStatusAllocFailed          = 4, /*!< Memory allocation error. */
    miopenStatusInternalError        = 5, /*!< MIOpen failure. */
    miopenStatusNotImplemented       = 6, /*!< Use of unimplemented feature. */
    miopenStatusUnknownError         = 7, /*!< Unknown error occurred. */
    miopenStatusUnsupportedOp        = 8, /*!< Unsupported operator for fusion. */
    miopenStatusGpuOperationsSkipped = 9, /*!< This is not an error. */
    miopenStatusVersionMismatch = 10, /*!< Version mismatch of the supplied binary data argment. */
} miopenStatus_t;

typedef enum
{
    // TODO:(LYM) temporary use Pedantic as default until TF32 is fully supported
    miopenMathDefault = 0, /*!< Use TF32 if possible */
    miopenMathPedantic =
        1, /*!< Default MathType. Strict IEEE compliance. Don't allow datatype down conversion. */
} miopenMathType_t;

#ifdef MIOPEN_BETA_API
typedef enum
{
    miopenF8RoundingModeStandard   = 0,
    miopenF8RoundingModeStochastic = 1,
} miopenF8RoundingMode_t;
#endif

/*! @brief Get character string for an error code.
 *
 * A function which returns a NULL terminated character string of the error code.
 *
 * @param error  miopenStatus_t type error status (input)
 * @return       errorString
 */
MIOPEN_EXPORT const char* miopenGetErrorString(miopenStatus_t error);

/*! @brief Custom allocator function
 *
 * This function allow for user-defined custom allocator
 *
 * @param context     A pointer a context (input)
 * @param sizeBytes   Number of bytes to allocate (input)
 *
 */
typedef void* (*miopenAllocatorFunction)(void* context, size_t sizeBytes);

/*! @brief Custom deallocator function
 *
 * This function allow for user-defined custom deallocation function
 *
 * @param context     A pointer context (input)
 * @param memory      A pointer allocated memory (input)
 *
 */
typedef void (*miopenDeallocatorFunction)(void* context, void* memory);

/*! @brief Method to return version of MIOpen
 *
 * The output values of this call follow from the versioning
 * format major.minor.patch
 *
 * Pointers that are NULL will be ignored.
 *
 * @param major     Major version number (output)
 * @param minor     Minor version number (output)
 * @param patch     Patch version number (output)
 *
 * @return          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetVersion(size_t* major, size_t* minor, size_t* patch);

/*! @brief Method to create the MIOpen handle object.
 *
 * This function creates a MIOpen handle. This is called at the very start to initialize the MIOpen
 * environment.
 * @param handle     A pointer to a MIOpen handle type (output)
 *
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreate(miopenHandle_t* handle);

/*! @brief Create a MIOpen handle with an accelerator stream.
 *
 * The HIP side uses a hipStream_t type for the stream, while OpenCL will use a
 * cl_command_queue.
 *
 * Create a handle with a previously created accelerator command queue.
 * @param handle     A pointer to a MIOpen handle type (output)
 * @param stream      An accelerator queue type (input)
 *
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateWithStream(miopenHandle_t* handle,
                                                    miopenAcceleratorQueue_t stream);

/*! @brief Destroys the MIOpen handle.
 *
 * This is called when breaking down the MIOpen environment.
 * @param handle     MIOpen handle (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroy(miopenHandle_t handle);

/*! @brief Set accelerator command queue previously created
 *
 * Set a command queue for an accelerator device
 * @param handle     MIOpen handle (input)
 * @param streamID   An accelerator queue type (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetStream(miopenHandle_t handle,
                                             miopenAcceleratorQueue_t streamID);

/*! @brief Get the previously created accelerator command queue
 *
 * Creates a command queue for an accelerator device
 * @param handle     MIOpen handle (input)
 * @param streamID   Pointer to a accelerator queue type (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetStream(miopenHandle_t handle,
                                             miopenAcceleratorQueue_t* streamID);

/*! @brief Set allocator for previously created miopenHandle
 *
 * Set a command queue for an accelerator device
 * @param handle     MIOpen handle
 * @param allocator  A callback function MIOpen will use for internal memory allocations.
 *      The provided callback function should allocate device memory with requested size
 *      and return a pointer to this memory.
 *      Passing 0 will restore the default MIOpen allocator and deallocator.
 * @param deallocator  A callback function MIOpen will use to for internal memory deallocation.
 *      The provided callback function should free the specified memory pointer
 * @param allocatorContext  User-specified pointer which is passed to \p allocator and \p
 * deallocator
 *      This allows the callback function to access state set by the caller to this function,
 *      for example a stateful heap allocator or a c++ class.
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetAllocator(miopenHandle_t handle,
                                                miopenAllocatorFunction allocator,
                                                miopenDeallocatorFunction deallocator,
                                                void* allocatorContext);

/*! @brief Get time for last kernel launched
 *
 * This function is used only when profiling mode has been enabled.
 * Kernel timings are based on the MIOpen handle and is not thread-safe.
 * In order to use multi-threaded profiling, create an MIOpen handle for each
 * concurrent thread.
 *
 * @param handle     MIOpen handle (input)
 * @param time       Pointer to a float type to contain kernel time in milliseconds (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetKernelTime(miopenHandle_t handle, float* time);

/*! @brief Enable profiling to retrieve kernel time
 *
 * Enable or disable kernel profiling. This profiling is only for kernel time.
 * @param handle     MIOpen handle (input)
 * @param enable     Boolean to toggle profiling (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenEnableProfiling(miopenHandle_t handle, bool enable);
/** @} */
// CLOSEOUT HANDLE DOXYGEN GROUP

/*! @ingroup fusion
 * @brief Creates the miopenFusionOpDescriptor_t type
 *
 * Fusion Operator Descriptor contains the meta-data associated with an operator
 * to be fused in a compute graph
 *
 */
MIOPEN_DECLARE_OBJECT(miopenFusionOpDescriptor);

/*! @ingroup tensor
 * @brief Creates the miopenTensorDescriptor_t type
 *
 * Tensor descriptor is an object that allows the user to specify a layer's size for each
 * dimension and dimension strides.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenTensorDescriptor);

/*! @ingroup tensor
 * @brief Creates the miopenSeqTensorDescriptor_t type
 *
 * SeqTensor descriptor is an object that allows the user to specify tensor with sequence dimension.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenSeqTensorDescriptor);

/*! @ingroup convolutions
 * @brief Creates the miopenConvolutionDescriptor_t type
 *
 * Convolution descriptor is an object that allows the user to specify a layer's padding, stride,
 * and dilation of the convolutional filter. Parameters must all be non-negative.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenConvolutionDescriptor);

/*! @ingroup pooling
 * @brief Creates the miopenPoolingDescriptor_t type
 *
 * Pooling descriptor is an object that allows the user to specify the dimension sizes of the
 * pooling windows, paddings, strides, and pooling mode.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenPoolingDescriptor);

/*! @ingroup LRN
 *  @brief Creates the miopenLRNDescriptor_t type
 *
 * LRN descriptor is an object that allows the user to specify the LRN mode, the number of elements
 * in the normalization window, and the LRN k-parameter.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenLRNDescriptor);

/*! @ingroup activation
 * @brief Creates the miopenActivationDescriptor_t type
 *
 * Activation descriptor is an object that allows the user to specify the activation mode.
 *
 */
MIOPEN_DECLARE_OBJECT(miopenActivationDescriptor);

/*! @ingroup RNN
 * @brief Creates the miopenRNNDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenRNNDescriptor);

/*! @ingroup LossFunction
 * @brief Creates the miopenCTCLossDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenCTCLossDescriptor);

/*! @ingroup Dropout
 * @brief Creates the miopenDropoutDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenDropoutDescriptor);

/*! @ingroup TensorReduce
 * @brief Creates the miopenReduceTensorDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenReduceTensorDescriptor);

/*! @ingroup mha
 * @brief Creates the miopenMhaDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenMhaDescriptor);

/*! @ingroup softmax
 * @brief Creates the miopenSoftmaxDescriptor_t type
 */
MIOPEN_DECLARE_OBJECT(miopenSoftmaxDescriptor);

/*! @ingroup tensor
 * @enum miopenDataType_t
 * MIOpen floating point datatypes. Both 32-bit and 16-bit floats are supported in MIOpen.
 */
typedef enum
{
    miopenHalf  = 0, /*!< 16-bit floating point (Fully supported) */
    miopenFloat = 1, /*!< 32-bit floating point (Fully supported) */
    miopenInt32 = 2, /*!< 32-bit integer (Partially supported) */
    miopenInt8  = 3, /*!< 8-bit integer (Partially supported) */
    // miopenInt8x4   = 4, /*!< Pack of 4x Int8 in NCHW_VECT_C format (Support discontinued) */
    miopenBFloat16 = 5,     /*!< 16-bit binary floating point (8-bit exponent, 7-bit fraction)
                               (Partially supported) */
    miopenDouble       = 6, /*!< 64-bit floating point (Partially supported) */
    miopenFloat8_fnuz  = 7,
    miopenBFloat8_fnuz = 8,
    miopenInt64        = 9,
} miopenDataType_t;

/*! @ingroup tensor
 * @enum miopenTensorLayout_t
 * Tensor layouts supported by MIOpen.
 * miopenTensorCHWNc4 and miopenTensorCHWNc8 layout only support weight tensor.
 */
typedef enum
{
    miopenTensorNCHW   = 0, /*!< NCHW memory layout (Fully supported) */
    miopenTensorNHWC   = 1, /*!< NHWC memory layout (Fully supported) */
    miopenTensorCHWN   = 2, /*!< CHWN memory layout (Not supported) */
    miopenTensorNCHWc4 = 3, /*!< NCHWc4 memory layout (Partially supported) */
    miopenTensorNCHWc8 = 4, /*!< NCHWc8 memory layout (Partially supported) */
    miopenTensorCHWNc4 = 5, /*!< CHWNc4 memory layout (Partially supported) */
    miopenTensorCHWNc8 = 6, /*!< CHWNc8 memory layout (Partially supported) */
    miopenTensorNCDHW  = 7, /*!< NCDHW memory layout (Fully supported) */
    miopenTensorNDHWC  = 8, /*!< NCDHW memory layout (Fully supported) */
} miopenTensorLayout_t;

/*! @ingroup pooling
 * @enum miopenIndexType_t
 * MIOpen index datatypes.
 */
typedef enum
{
    miopenIndexUint8  = 0, /*!<  8-bit unsigned */
    miopenIndexUint16 = 1, /*!< 16-bit unsigned */
    miopenIndexUint32 = 2, /*!< 32-bit unsigned */
    miopenIndexUint64 = 3, /*!< 64-bit unsigned */
} miopenIndexType_t;

/*! @ingroup tensor
 * @enum miopenTensorOp_t
 * Element-wise tensor operation modes
 */
typedef enum
{
    miopenTensorOpAdd = 0, /*!< Add tensors element-wise */
    miopenTensorOpMul = 1, /*!< Multiply two tensors element-wise */
    miopenTensorOpMin = 2, /*!< Minimum of tensor element pairs */
    miopenTensorOpMax = 3, /*!< Maximum of tensor element pairs */
} miopenTensorOp_t;

/*! @ingroup convolutions
 *  @enum miopenConvolutionMode_t
 * Convolution mode selection for convolution layer preference.
 */
typedef enum
{
    miopenConvolution = 0, /*!< Cross-Correlation convolution */
    miopenTranspose   = 1, /*!< Transpose convolutions -- deconvolution */
    miopenGroupConv   = 2, /*!< Deprecated Group convolution legacy, ToBe Removed */
    miopenDepthwise   = 3, /*!< Deprecated Depthwise convolution legacy, ToBe Removed */
} miopenConvolutionMode_t;

/*! @ingroup padding
 *  @enum miopenPaddingMode_t
 * Padding mode selection for convolution/Pooling layer preference
 */
typedef enum
{
    miopenPaddingDefault = 0, /*!< MIOPEN Default Padding */
    miopenPaddingSame    = 1, /*!< Tensorflow SAME Padding */
    miopenPaddingValid   = 2, /*!< Tensorflow VALID Padding */
} miopenPaddingMode_t;

/*! @ingroup pooling
 * @enum miopenPoolingMode_t
 * Pooling layer mode
 */
typedef enum
{
    miopenPoolingMax              = 0, /*!< Maximum pooling */
    miopenPoolingAverage          = 1, /*!< Average pooling */
    miopenPoolingAverageInclusive = 2, /*!< Inclusive Average pooling */
} miopenPoolingMode_t;

/*! @ingroup pooling
 * @enum miopenPoolingWorkspaceIndexMode_t
 * Pooling layer workspace index mode. miopenPoolingWorkspaceIndexMask mode records indices
 * indicating the max values' positions in the filter/mask. miopenPoolingWorkspaceIndexImage mode
 * records indices indicating the max values' positions in the image.
 */
typedef enum
{
    miopenPoolingWorkspaceIndexMask  = 0, /*!< Use mask indices, 2D pooling only */
    miopenPoolingWorkspaceIndexImage = 1, /*!< Use image indices */
} miopenPoolingWorkspaceIndexMode_t;

/*! @ingroup LRN
 * @enum miopenLRNMode_t
 * Local Response Normalization layer mode
 */
typedef enum
{
    miopenLRNWithinChannel = 0, /*!< Channel independent */
    miopenLRNCrossChannel  = 1, /*!< Cross Channel */
} miopenLRNMode_t;
#ifdef MIOPEN_BETA_API
/*! @ingroup layernorm
 * @enum miopenNormMode_t
 * LayerNorm mode
 */
typedef enum
{
    MIOPEN_ELEMENTWISE_AFFINE = 0, /*!< initialized to ones for weights and zeros for biases */
    MIOPEN_WEIGHT_BIAS =
        1, /*!< learnable weights and biases of the module of shape normalized_shape */
    MIOPEN_ELEMENTWISE_AFFINE_FUSED_ADD =
        2, /*!< initialized to ones for weights and zeros for biases in addlayernorm */
    MIOPEN_WEIGHT_BIAS_FUSED_ADD = 3, /*!< learnable weights and biases of the module of shape
                                         normalized_shape in addlayernorm */
    MIOPEN_ELEMENTWISE_AFFINE_T5 =
        4, /*!< initialized to ones for weights and zeros for biases in t5layernorm */
    MIOPEN_WEIGHT_BIAS_T5 = 5, /*!< learnable weights and biases of the module of shape
                                  normalized_shape in t5layernorm */
} miopenNormMode_t;
#endif
/*! @ingroup batchnorm
 * @enum miopenBatchNormMode_t
 * Batch Normalization layer mode
 */
typedef enum
{
    miopenBNPerActivation = 0, /*!< Element-wise normalization for fully connected layer */
    miopenBNSpatial       = 1, /*!< Mini-batch spatial normalization for convolutional layers */
} miopenBatchNormMode_t;

/*! @ingroup activation
 * @enum miopenActivationMode_t
 * Activation layer modes
 */
typedef enum
{
    miopenActivationPASTHRU  = 0, /*!< No activation, pass through the data */
    miopenActivationLOGISTIC = 1, /*!< Sigmoid function: \f$1 / (1 + e^{-x})\f$ */
    miopenActivationTANH     = 2, /*!< Tanh activation \f$ \beta * tanh( \alpha * x) \f$ */
    miopenActivationRELU     = 3, /*!< Rectified Linear Unit \f$ max(0, x) \f$ */
    miopenActivationSOFTRELU = 4, /*!< \f$log(1 + e^x)\f$ */
    miopenActivationABS      = 5, /*!< Absolute value \f$abs(x)\f$ */
    miopenActivationPOWER = 6, /*!< Scaled and shifted power \f$(\alpha + \beta * x)^{gamma}\f$ */
    miopenActivationCLIPPEDRELU =
        7, /*!< Clipped Rectified Linear Unit \f$ max(0, min(\alpha, x)) \f$ */
    miopenActivationLEAKYRELU =
        8, /*!< Leaky Rectified Linear Unit \f$ \alpha * x | x <= 0; x | x > 0 \f$ */
    miopenActivationELU =
        9, /*!< Exponential Rectified Linear Unit \f$ \alpha * (e^{x} - 1) | x <= 0; x | x > 0 \f$
            */
    miopenActivationCLAMP = 10, /*!< Clamp \f$ max(\alpha, min(\beta, x)) \f$ */
} miopenActivationMode_t;

/*! @ingroup softmax
 * @enum miopenSoftmaxAlgorithm_t
 * Softmax implementation algorithms
 */
typedef enum
{
    MIOPEN_SOFTMAX_FAST     = 0, /*!< straightforward softmax */
    MIOPEN_SOFTMAX_ACCURATE = 1, /*!< scaled softmax by maximum value in input domain */
    MIOPEN_SOFTMAX_LOG      = 2, /*!< log softmax */
} miopenSoftmaxAlgorithm_t;

/*! @ingroup softmax
 * @enum miopenSoftmaxMode_t
 * Softmax modes
 */
typedef enum
{
    MIOPEN_SOFTMAX_MODE_INSTANCE = 0, /*!< compute per image (N) across C, H, W */
    MIOPEN_SOFTMAX_MODE_CHANNEL =
        1, /*!< compute per spatial location (H, W) per image (N) across C */
} miopenSoftmaxMode_t;

/*! @ingroup TensorReduce
 * @brief Version of TensorReduce API. Applications may use it to ensure
 * backward compatibility with older library versions.
 *
 * - 0 or undefined - Initial API. Supported operations: ADD, MIN, MIN, MAX.
 * - 1 - Added AMAX, AVG, NORM1, NORM2 ops.
 */
#define MIOPEN_API_VERSION_REDUCE_TENSOR 1

/*! @ingroup TensorReduce
 * @enum miopenReduceTensorOp_t
 * Tensor Reduction operation types
 */
typedef enum
{
    MIOPEN_REDUCE_TENSOR_ADD = 0, /*!< the operation is adding the values of the reduced elements */
    MIOPEN_REDUCE_TENSOR_MUL =
        1, /*!< the operation is multiplying the values of the reduced elements */
    MIOPEN_REDUCE_TENSOR_MIN =
        2, /*!< the operation is getting the minimum value of the reduced elements */
    MIOPEN_REDUCE_TENSOR_MAX =
        3, /*!< the operation is getting the maximum value of the reduced elements */
    MIOPEN_REDUCE_TENSOR_AMAX =
        4, /*!< the operation is getting the maximum absolute value of the reduced elements */
    MIOPEN_REDUCE_TENSOR_AVG =
        5, /*!< the operation is getting the averaged value of the reduced elements */
    MIOPEN_REDUCE_TENSOR_NORM1 =
        6, /*!< the operation is adding the absolute values of the reduced elements */
    MIOPEN_REDUCE_TENSOR_NORM2 = 7, /*!< the operation is getting the square root of the sum of
                                     squares of the reduced elements */
    // MIOPEN_REDUCE_TENSOR_MUL_NO_ZEROS =
    //    8, /*!< the operation is same as MUL, but does not have the zero values considered */
} miopenReduceTensorOp_t;

/*! @ingroup TensorReduce
 * @enum miopenReduceTensorOp_t
 * Nan numbers propagation modes
 */
typedef enum
{
    MIOPEN_NOT_PROPAGATE_NAN = 0, /*!< does not propagate NaN number */
    MIOPEN_PROPAGATE_NAN     = 1, /*!< propagate the NaN number by the Reduction operation */
} miopenNanPropagation_t;

/*! @ingroup TensorReduce
 * @enum miopenReduceTensorIndices_t
 * Reduction Indices computation modes
 */
typedef enum
{
    MIOPEN_REDUCE_TENSOR_NO_INDICES        = 0, /*!< Does not compuate indices */
    MIOPEN_REDUCE_TENSOR_FLATTENED_INDICES = 1, /*!< Compute the relative, flatted indices */
} miopenReduceTensorIndices_t;

/*! @ingroup TensorReduce
 * @enum miopenIndicesType_t
 * Reduction Indices types
 */
typedef enum
{
    MIOPEN_32BIT_INDICES = 0, /*!< 32-bit unsigned integer indices */
    MIOPEN_64BIT_INDICES = 1, /*!< 64-bit unsigned integer indices */
    MIOPEN_16BIT_INDICES = 2, /*!< 16-bit unsigned integer indices */
    MIOPEN_8BIT_INDICES  = 3, /*!< 8-bit unsigned integer indices */
} miopenIndicesType_t;

/*! @ingroup convolutions
 *  @enum miopenConvolutionAttrib_t
 * Attribute for convolution descriptor, used for alternating the convolution behavior
 */
typedef enum
{
    MIOPEN_CONVOLUTION_ATTRIB_FP16_ALT_IMPL =
        0, /*!< Use alternative fp16 implementation.
            Only supported for gfx90a; has no effect for other targets.
            0 - disabled, 1 - enabled, -1 or unset - default (F0B1W1) >*/
    MIOPEN_CONVOLUTION_ATTRIB_DETERMINISTIC =
        1, /*!< Restrict MIOpen convolutions to kernels which produce numerically deterministic
              results. 0 - disabled (default), 1 - enabled >*/
#ifdef MIOPEN_BETA_API
    MIOPEN_CONVOLUTION_ATTRIB_FP8_ROUNDING_MODE =
        2, /*!<Specifies the rounding mode for the 8-bit floating data types. Currently, two
              rounding modes are supported miopenF8RoundingModeStandard and
              miopenF8RoundingModeStochastic. These are listed as part of the miopenF8RoundingMode_t
              enum.>*/
#else
// miopenReserved1 = 2,
#endif
    // TODO:(LYM) temporarily use Pedantic as default until TF32 is fully supported
    MIOPEN_CONVOLUTION_ATTRIB_MATH_TYPE =
        3, /*!< refer to miopenMathType_t,default is miopenMathPedantic >*/
} miopenConvolutionAttrib_t;

/*! @ingroup convolutions
 *  @enum miopenConvolutionFindMode_t
 * Findmode for convolution descriptor, used for changing the find behavior when calling
 * miopenFindConvolutionForwardAlgorithm(), miopenFindConvolutionBackwardDataAlgorithm(), or
 * miopenFindConvolutionBackwardWeightsAlgorithm().
 */
typedef enum
{
    miopenConvolutionFindModeNormal =
        1, /*!< Full Find mode call, which will benchmark all the solvers and return a list. >*/
    miopenConvolutionFindModeFast =
        2, /*!< Checks the Find-db for an entry. If there is a hit, use that entry. If there is a
              miss, utilize the Immediate mode fallback. Start-up times are expected to be faster,
              but with worse GPU performance. >*/
    miopenConvolutionFindModeHybrid =
        3, /*!< Checks the Find-db for an entry. If there is a hit, use that entry. If there is a
              miss, use the existing Find machinery. Slower start-up times than Fast Find, but
              better GPU performance. >*/
    // miopenConvolutionFindModeReserved_4 = 4, /*!< Reserved - do not use */
    miopenConvolutionFindModeDynamicHybrid =
        5, /*!< Checks the Find-db for an entry. If there is a hit, uses that entry. If there is a
              miss, uses the existing Find machinery with skipping non-dynamic kernels, thus saving
              compilation time. Faster start-up times than Hybrid Find, but GPU performance might be
              a bit worse. >*/
    miopenConvolutionFindModeTrustVerify     = 6,
    miopenConvolutionFindModeTrustVerifyFull = 7,
    miopenConvolutionFindModeDefault =
        miopenConvolutionFindModeDynamicHybrid /*!< Default FindMode >*/
} miopenConvolutionFindMode_t;

/** @addtogroup tensor
 *
 *  @{
 */

/*! @brief Create a Tensor Descriptor
 *
 * API for creating an uninitialized tensor descriptor.
 * @param tensorDesc Pointer to a tensor descriptor type (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateTensorDescriptor(miopenTensorDescriptor_t* tensorDesc);

/*! @brief Set shape of 4D tensor
 *
 * Interface for setting 4-D tensor shape. MIOpen currently implements NCHW and NHWC layout.
 *
 * @param tensorDesc Tensor descriptor (input/output)
 * @param dataType   MIOpen datatype (input)
 * @param n          Mini-batch size (input)
 * @param c          Number of channels (input)
 * @param h          Data height dimension size (input)
 * @param w          Data width dimension size (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSet4dTensorDescriptor(
    miopenTensorDescriptor_t tensorDesc, miopenDataType_t dataType, int n, int c, int h, int w);

/*! @brief Set shape of ND tensor with specific layout
 *
 * Interface for setting N-D packed tensor shape. This interface support NHWC, NCHW, NCHWc*, CHWNc*
 * @param tensorDesc   Tensor descriptor (input/output)
 * @param dataType     MIOpen datatype (input)
 * @param tensorLayout Tensor layout (input)
 * @param lens         Tensor dimensions (input)
 * @param num_lens     Tensor dimension size (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetNdTensorDescriptorWithLayout(miopenTensorDescriptor_t tensorDesc,
                                      miopenDataType_t dataType,
                                      miopenTensorLayout_t tensorLayout,
                                      const int* lens,
                                      int num_lens);
/*! @brief Set shape and stride of 4D tensor
 *
 * Interface for setting 4-D tensor shape and stride. It allows to create the non-packed tensor.
 * A non-packed tensor refers to the tensor where the elements are not compressed or packed in any
 * specific way. Each element in the tensor is stored individually, and there is no special
 * compression applied to the storage.
 *
 * @param tensorDesc Tensor descriptor (input/output)
 * @param dataType   MIOpen datatype (input)
 * @param n          Mini-batch size (input)
 * @param c          Number of channels (input)
 * @param h          Data height dimension size (input)
 * @param w          Data width dimension size (input)
 * @param nStride    Mini-batch dimension stride (input)
 * @param cStride    Channel dimension stride (input)
 * @param hStride    Height dimension stride (input)
 * @param wStride    Width dimension stride (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSet4dTensorDescriptorEx(miopenTensorDescriptor_t tensorDesc,
                                                           miopenDataType_t dataType,
                                                           int n,
                                                           int c,
                                                           int h,
                                                           int w,
                                                           int nStride,
                                                           int cStride,
                                                           int hStride,
                                                           int wStride);

/*! @brief Get the details of the tensor descriptor
 *
 * Interface to query the 4-D tensor shape.
 *
 * @param tensorDesc Tensor descriptor (input)
 * @param dataType   MIOpen datatype (output)
 * @param n          Mini-batch size (output)
 * @param c          Number of channels (output)
 * @param h          Data height dimension size (output)
 * @param w          Data width dimension size (output)
 * @param nStride    Mini-batch dimension stride (output)
 * @param cStride    Channel dimension stride (output)
 * @param hStride    Height dimension stride (output)
 * @param wStride    Width dimension stride (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGet4dTensorDescriptor(miopenTensorDescriptor_t tensorDesc,
                                                         miopenDataType_t* dataType,
                                                         int* n,
                                                         int* c,
                                                         int* h,
                                                         int* w,
                                                         int* nStride,
                                                         int* cStride,
                                                         int* hStride,
                                                         int* wStride);

/*! @brief Set shape of N-dimensional tensor
 *
 * Interface for setting non-packed tensor shape.
 * @param tensorDesc   Tensor descriptor (input/output)
 * @param dataType     MIOpen datatype (input)
 * @param nbDims       Number of dimensions in the dimsA array (input)
 * @param dimsA        Array containing the size of dimensions (input)
 * @param stridesA     Array containing the size of stride (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTensorDescriptor(miopenTensorDescriptor_t tensorDesc,
                                                       miopenDataType_t dataType,
                                                       int nbDims,
                                                       const int* dimsA,
                                                       const int* stridesA);

#ifdef MIOPEN_BETA_API
/*! @copydoc miopenSetTensorDescriptor()
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTensorDescriptorV2(miopenTensorDescriptor_t tensorDesc,
                                                         miopenDataType_t dataType,
                                                         int nbDims,
                                                         const size_t* dimsA,
                                                         const size_t* stridesA);
#endif

#ifdef MIOPEN_BETA_API
/*! @brief Set the tensor cast type
 *
 *  For tensors where the cast_type attribute is set, the tensor elements would be converted to the
 * target type before the target operation is applied. Currently, only supported for convolution
 * operations targeting the FP8 datatype
 *
 *  @param tensorDesc Tensor descriptor type (input)
 *  @param cast_type  MIOpen datatype (input)
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTensorCastType(miopenTensorDescriptor_t tensorDesc,
                                                     miopenDataType_t cast_type);
#endif

/*! @brief Set shape of N-dimensional tensor
 *
 * Interface for querying tensor size. MIOpen has support for 1, 2, 3, 4, 5 dimensional tensor of
 * layout.
 * @param tensorDesc   Tensor descriptor (input)
 * @param size         number of elements in tensor described by the descriptor (output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetTensorDescriptorSize(miopenTensorDescriptor_t tensorDesc,
                                                           int* size);

/*! @brief Get the details of the N-dimensional tensor descriptor.
 *
 * @param tensorDesc Tensor descriptor (input)
 * @param dataType   MIOpen datatype (output)
 * @param dimsA      Array containing the size of dimensions (output)
 * @param stridesA   Array containing the size of stride (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetTensorDescriptor(miopenTensorDescriptor_t tensorDesc,
                                                       miopenDataType_t* dataType,
                                                       int* dimsA,
                                                       int* stridesA);

/*! @brief Destroys the tensor descriptor
 *
 * @param tensorDesc Tensor descriptor (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyTensorDescriptor(miopenTensorDescriptor_t tensorDesc);

/*! @brief Create a Tensor Descriptor for sequence data
 *
 * API for creating an uninitialized sequence data tensor descriptor.
 * @param tensorDesc Pointer to a sequence data tensor descriptor type (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateSeqTensorDescriptor(miopenSeqTensorDescriptor_t* tensorDesc);

/*! @brief Destroys the sequence data tensor descriptor
 *
 * @param tensorDesc Tensor descriptor (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenDestroySeqTensorDescriptor(miopenSeqTensorDescriptor_t tensorDesc);

/*! @brief Execute element-wise tensor operations
 *
 * This function implements: \f$ C = op ( alpha1[0] * A, alpha2[0] * B ) + beta[0] * C \f$
 *
 * For Forward Bias one can also use, miopenConvolutionForwardBias()
 *
 * @param handle     MIOpen handle (input)
 * @param tensorOp   Operation from miopenTensorOp_t (input)
 * @param alpha1     Tensor A's floating point scaling factor, allocated on the host (input)
 * @param aDesc      Tensor descriptor for tensor A (input)
 * @param A          Tensor A (input)
 * @param alpha2     Tensor B's floating point scaling factor, allocated on the host (input)
 * @param bDesc      Tensor descriptor for tensor B (input)
 * @param B          Tensor B (input)
 * @param beta       Tensor C's floating point scaling factor, allocated on the host (input)
 * @param cDesc      Tensor descriptor for tensor C (input)
 * @param C          Tensor C (input and output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenOpTensor(miopenHandle_t handle,
                                            miopenTensorOp_t tensorOp,
                                            const void* alpha1,
                                            const miopenTensorDescriptor_t aDesc,
                                            const void* A,
                                            const void* alpha2,
                                            const miopenTensorDescriptor_t bDesc,
                                            const void* B,
                                            const void* beta,
                                            const miopenTensorDescriptor_t cDesc,
                                            void* C);

/*! @brief Fills a tensor with a single value.
 *
 * Supported datatypes are fp32, fp16, and bfp16
 *
 * @param handle     MIOpen handle (input)
 * @param yDesc      Tensor descriptor for tensor y (input)
 * @param y          Tensor y (input)
 * @param alpha      Pointer to fill value (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTensor(miopenHandle_t handle,
                                             const miopenTensorDescriptor_t yDesc,
                                             void* y,
                                             const void* alpha);

/*! @brief Scales all elements in a tensor by a single value.
 *
 * Supported datatypes are fp32 and fp16
 *
 * @param handle     MIOpen handle (input)
 * @param yDesc      Tensor descriptor for tensor y (input)
 * @param y          Tensor y (input and output)
 * @param alpha      Floating point scaling factor, allocated on the host (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenScaleTensor(miopenHandle_t handle,
                                               const miopenTensorDescriptor_t yDesc,
                                               void* y,
                                               const void* alpha);

/*! @brief Returns number of bytes associated with tensor descriptor
 *
 * @param tensorDesc Tensor descriptor (input)
 * @param numBytes   Number of bytes associated with tensor descriptor (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetTensorNumBytes(miopenTensorDescriptor_t tensorDesc,
                                                     size_t* numBytes);

/*! @brief Copies one tensor to another tensor with a different layout/scale.
 *
 * This function implements:
 * 1. \f$ Y = alpha * X + beta * Y \f$ for fp32 and fp16 datatype
 * 2. Vectorize/de-vectorize along channel dimension C for int8 datatype
 *
 * Currently this is used for transforming from int8 to int8x4 vector datatypes
 *
 * @param handle     MIOpen handle (input)
 * @param alpha      Floating point scaling factor, allocated on the host (input)
 * @param xDesc      Source Tensor descriptor for tensor x (input)
 * @param x          Source Tensor x (input)
 * @param beta       Floating point scaling factor, allocated on the host (input)
 * @param yDesc      Destination Tensor descriptor for tensor y (input)
 * @param y          Destination Tensor y (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenTransformTensor(miopenHandle_t handle,
                                                   const void* alpha,
                                                   const miopenTensorDescriptor_t xDesc,
                                                   const void* x,
                                                   const void* beta,
                                                   const miopenTensorDescriptor_t yDesc,
                                                   void* y);

/** @} */
// CLOSEOUT TENSOR DOXYGEN GROUP

/** @addtogroup convolutions
 *
 *  @{
 */

/*! @brief Creates a convolution layer descriptor
 *
 * @param convDesc   Convolution layer descriptor
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateConvolutionDescriptor(miopenConvolutionDescriptor_t* convDesc);

/*! @brief Creates a 2-D convolution layer descriptor
 *
 * For group/depthwise convolution dilation height and width, only a dilation value of 1 is
 * supported.
 *
 * @param convDesc   Convolution layer descriptor (output)
 * @param c_mode     Convolutional mode (input)
 * @param pad_h      Height input data padding (input)
 * @param pad_w      Width input data padding (input)
 * @param stride_h   Stride for the height of input data (input)
 * @param stride_w   Stride for the width of input data (input)
 * @param dilation_h Dilation height (input)
 * @param dilation_w Dilation width (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenInitConvolutionDescriptor(miopenConvolutionDescriptor_t convDesc,
                                                             miopenConvolutionMode_t c_mode,
                                                             int pad_h,
                                                             int pad_w,
                                                             int stride_h,
                                                             int stride_w,
                                                             int dilation_h,
                                                             int dilation_w);

/*! @brief Creates a N-dimensional convolution layer descriptor
 *
 * @param convDesc      Convolution layer descriptor (output)
 * @param spatialDim    Convolutional spatial dimension (input)
 * @param padA          Array of input data padding (input)
 * @param strideA       Array of convolution stride (input)
 * @param dilationA     Array of convolution dilation (input)
 * @param c_mode        Convolutional mode (input)
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenInitConvolutionNdDescriptor(miopenConvolutionDescriptor_t convDesc,
                                  int spatialDim,
                                  const int* padA,
                                  const int* strideA,
                                  const int* dilationA,
                                  miopenConvolutionMode_t c_mode);

/*! @brief Retrieves the spatial dimension of a convolution layer descriptor
 *
 * @param convDesc              Convolution layer descriptor (input)
 * @param spatialDim            Spatial dimension of convolution descriptor (output)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetConvolutionSpatialDim(miopenConvolutionDescriptor_t convDesc,
                                                            int* spatialDim);

/*! @brief Retrieves a 2-D convolution layer descriptor's details
 *
 * For group/depthwise convolution dilation height and width, only a dilation value of 1 is
 * supported.
 *
 * @param convDesc   Convolution layer descriptor (input)
 * @param c_mode     Convolutional mode (output)
 * @param pad_h      Height input data padding (output)
 * @param pad_w      Width input data padding (output)
 * @param stride_h   Stride for the height of input data (output)
 * @param stride_w   Stride for the width of input data (output)
 * @param dilation_h Dilation height (output)
 * @param dilation_w Dilation width (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetConvolutionDescriptor(miopenConvolutionDescriptor_t convDesc,
                                                            miopenConvolutionMode_t* c_mode,
                                                            int* pad_h,
                                                            int* pad_w,
                                                            int* stride_h,
                                                            int* stride_w,
                                                            int* dilation_h,
                                                            int* dilation_w);

/*! @brief Retrieves a N-dimensional convolution layer descriptor's details
 *
 * @param convDesc               Convolution layer descriptor (input)
 * @param requestedSpatialDim    Expected convolution spatial dimension (intput)
 * @param spatialDim             Convolutional spatial dimension (output)
 * @param padA                   Array of input data padding (output)
 * @param strideA                Array of convolution stride (output)
 * @param dilationA              Array of convolution dilation (output)
 * @param c_mode                 Convolutional mode (output)
 * @return                       miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetConvolutionNdDescriptor(miopenConvolutionDescriptor_t convDesc,
                                 int requestedSpatialDim,
                                 int* spatialDim,
                                 int* padA,
                                 int* strideA,
                                 int* dilationA,
                                 miopenConvolutionMode_t* c_mode);

/*! @brief Get the number of groups to be used in Group/Depthwise convolution
 *
 * @param convDesc   Convolution layer descriptor (input)
 * @param groupCount Pointer to number of groups in group/depthwise convolution (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetConvolutionGroupCount(miopenConvolutionDescriptor_t convDesc,
                                                            int* groupCount);

/*! @brief Set the number of groups to be used in Group/Depthwise convolution
 *
 * Must be called before all computational APIs of group/depthwise convolution, it is preferable to
 * call miopenInitConvolutionDescriptor() first, then miopenSetConvolutionGroupCount() to fully
 * initialize group convolutions. Both Convolution Mode and Transpose Convolution Mode support
 * group/depthwise convolution. To run depthwise convolution, set groupCount value equal to number
 * of channels.
 *
 * @param convDesc   Convolution layer descriptor (output)
 * @param groupCount      number of groups, in depthwise conv using filter_number/channel_multiplier
 * (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetConvolutionGroupCount(miopenConvolutionDescriptor_t convDesc,
                                                            int groupCount);

/*! @brief Set the output padding to be used in 2-D Transpose convolution
 *
 * This function is optional for initialization of Transpose convolution. If applicable, it must be
 * called before all computational APIs of Transpose convolution. It is preferable to call
 * miopenInitConvolutionDescriptor() first, then miopenSetTransposeConvOutputPadding() to fully
 * initialize transpose convolutions.
 *
 * @param convDesc   Convolution layer descriptor (output)
 * @param adj_h      output padding for the height of output data (input)
 * @param adj_w      output padding for the width of output data (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetTransposeConvOutputPadding(miopenConvolutionDescriptor_t convDesc, int adj_h, int adj_w);

/*! @brief Set the output padding to be used in N-dimensional Transpose convolution
 *
 * This function is optional for initialization of Transpose convolution. If applicable, it must be
 * called before all computational APIs of Transpose convolution. It is preferable to call
 * miopenInitConvolutionNdDescriptor() first, then miopenSetTransposeConvNdOutputPadding() to fully
 * initialize transpose convolutions. Currently, 2-D and 3-D convolutions are supported.
 *
 * @param convDesc      Convolution layer descriptor (output)
 * @param spatialDim    Convolutional spatial dimension (input)
 * @param adjA          array of output padding for output data (input)
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTransposeConvNdOutputPadding(
    miopenConvolutionDescriptor_t convDesc, int spatialDim, const int* adjA);

/*! @brief Get the shape of a resulting 4-D tensor from a 2-D convolution
 *
 * This function returns the dimensions of the resulting 4D tensor of a 2D
 * convolution, given the convolution descriptor, the input tensor descriptor
 * and the filter descriptor. This function can help to setup the output tensor
 * and allocate the proper amount of memory prior to launch the actual
 * convolution.
 *
 * @param convDesc          Convolution layer descriptor (input)
 * @param inputTensorDesc   Input data tensor descriptor (input)
 * @param filterDesc        Weight descriptor (input)
 * @param n                 Mini-batch size (output)
 * @param c                 Number of channels (output)
 * @param h                 Data height dimension size (output)
 * @param w                 Data width dimension size (output)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetConvolutionForwardOutputDim(miopenConvolutionDescriptor_t convDesc,
                                     const miopenTensorDescriptor_t inputTensorDesc,
                                     const miopenTensorDescriptor_t filterDesc,
                                     int* n,
                                     int* c,
                                     int* h,
                                     int* w);

/*! @brief Get the shape of a resulting N-dimensional tensor from a (N-2)-dimensional convolution
 *
 * This function returns the dimensions of the resulting N-dimensional tensor of a (N-2)-dimensional
 * convolution, given the convolution descriptor, the input tensor descriptor
 * and the filter descriptor. It is used to setup the output tensor descriptor prior to executing
 * the convolution layer.
 *
 * @param convDesc          Convolution layer descriptor (input)
 * @param inputTensorDesc   Input data tensor descriptor (input)
 * @param filterDesc        Weight descriptor (input)
 * @param nDim              Pointer to Output data tensor dimension (output)
 * @param outputTensorDimA  Array of Output data tensor length (output)
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetConvolutionNdForwardOutputDim(miopenConvolutionDescriptor_t convDesc,
                                       const miopenTensorDescriptor_t inputTensorDesc,
                                       const miopenTensorDescriptor_t filterDesc,
                                       int* nDim,
                                       int* outputTensorDimA);

/*! @brief Destroys the tensor descriptor object
 *
 * @param convDesc Convolution tensor descriptor type (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenDestroyConvolutionDescriptor(miopenConvolutionDescriptor_t convDesc);

/*! @brief Set the attribute of the convolution descriptor
 *
 * @param convDesc          Convolution layer descriptor (input)
 * @param attr              Attribute of this convolution to set (input)
 * @param value             Value of this attribute (input)
 */
MIOPEN_EXPORT miopenStatus_t miopenSetConvolutionAttribute(miopenConvolutionDescriptor_t convDesc,
                                                           const miopenConvolutionAttrib_t attr,
                                                           int value);

/*! @brief Get the attribute of the convolution descriptor
 *
 * @param convDesc          Convolution layer descriptor (input)
 * @param attr              Attribute of this convolution to get (input)
 * @param value             Value of this attribute (output)
 */
MIOPEN_EXPORT miopenStatus_t miopenGetConvolutionAttribute(miopenConvolutionDescriptor_t convDesc,
                                                           const miopenConvolutionAttrib_t attr,
                                                           int* value);

/*! @brief Sets the Find Mode attribute in the convolution descriptor.
 *
 * The subsequent calls of miopenFindConvolutionForwardAlgorithm(),
 * miopenFindConvolutionBackwardDataAlgorithm(), or miopenFindConvolutionBackwardWeightsAlgorithm()
 * invoked with convDesc, will follow the findMode set by this call.
 *
 * Note that the default Find Mode is overriden by the MIOPEN_FIND_MODE environment variable,
 * if it is set. If unset, the default is as specified by miopenConvolutionFindModeDefault.
 *
 * @param convDesc   Convolution layer descriptor (input)
 * @param findMode   Find Mode of convDesc (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetConvolutionFindMode(miopenConvolutionDescriptor_t convDesc,
                                                          miopenConvolutionFindMode_t findMode);

/*! @brief Reads the Find Mode attribute from the convolution descriptor.
 *
 * @param convDesc   Convolution layer descriptor (input)
 * @param findMode   Find Mode of convDesc (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetConvolutionFindMode(
    const miopenConvolutionDescriptor_t convDesc, miopenConvolutionFindMode_t* findMode);

/*! @enum miopenConvFwdAlgorithm_t
 * Convolutional algorithm mode for forward propagation. MIOpen use cross-correlation for its
 * convolution implementation.
 */
typedef enum
{
    miopenConvolutionFwdAlgoGEMM         = 0, /*!< GEMM variant */
    miopenConvolutionFwdAlgoDirect       = 1, /*!< Direct convolutions */
    miopenConvolutionFwdAlgoFFT          = 2, /*!< Fast Fourier Transform indirect convolutions */
    miopenConvolutionFwdAlgoWinograd     = 3, /*!< Winograd indirect convolutions */
    miopenConvolutionFwdAlgoImplicitGEMM = 5, /*!< Implicit GEMM convolutions */
} miopenConvFwdAlgorithm_t;

/*! @enum miopenConvBwdWeightsAlgorithm_t
 * Convolutional algorithm mode for back propagation on weights.
 */
typedef enum
{
    miopenConvolutionBwdWeightsAlgoGEMM         = 0, /*!< GEMM variant */
    miopenConvolutionBwdWeightsAlgoDirect       = 1, /*!< Direct convolution algorithm */
    miopenConvolutionBwdWeightsAlgoWinograd     = 3, /*!< Winograd convolutions */
    miopenConvolutionBwdWeightsAlgoImplicitGEMM = 5, /*!< Implicit GEMM convolutions */
} miopenConvBwdWeightsAlgorithm_t;

/*! @enum miopenConvBwdDataAlgorithm_t
 * Convolutional algorithm mode for back propagation on data.
 */
typedef enum
{
    miopenConvolutionBwdDataAlgoGEMM     = 0, /*!< GEMM variant */
    miopenConvolutionBwdDataAlgoDirect   = 1, /*!< Direct convolutions */
    miopenConvolutionBwdDataAlgoFFT      = 2, /*!< Fast Fourier Transform indirect convolutions */
    miopenConvolutionBwdDataAlgoWinograd = 3, /*!< Winograd indirect convolutions */
    miopenTransposeBwdDataAlgoGEMM =
        4, /*!< Deprecated Transpose GEMM variant legacy, ToBe Removed */
    miopenConvolutionBwdDataAlgoImplicitGEMM = 5, /*!< Implicit GEMM convolutions */
} miopenConvBwdDataAlgorithm_t;

/*! @enum miopenConvAlgorithm_t
 * Top-level convolutional algorithm mode
 */
typedef enum
{
    miopenConvolutionAlgoGEMM         = 0, /*!< GEMM variant */
    miopenConvolutionAlgoDirect       = 1, /*!< Direct convolutions */
    miopenConvolutionAlgoFFT          = 2, /*!< Fast Fourier Transform indirect convolutions */
    miopenConvolutionAlgoWinograd     = 3, /*!< Winograd indirect convolutions */
    miopenConvolutionAlgoImplicitGEMM = 5, /*!< Implicit GEMM convolutions */
} miopenConvAlgorithm_t;

/*! @brief Perf struct for forward, backward filter, or backward data algorithms
 *
 * Contains the union to hold the selected convolution algorithm for forward, or backwards layers,
 * and also contains the time it took to run the algorithm and the workspace required to run the
 * algorithm. The workspace in this structure can be used when executing the convolution layer.
 */
typedef struct
{
    union
    {
        miopenConvFwdAlgorithm_t fwd_algo; /*!< Forward convolution algorithm enum selection */
        miopenConvBwdWeightsAlgorithm_t bwd_weights_algo; /*!< Back propagation on weights
                                                             convolution algorithm enum selection */
        miopenConvBwdDataAlgorithm_t
            bwd_data_algo; /*!< Back propagation on data convolution algorithm enum selection */
    };

    float time;    /*!< Time to exectued the selected algorithm represented in the union */
    size_t memory; /*!< Workspace required to run the selected algorithm represented in the union */

} miopenConvAlgoPerf_t;

/*! @brief Performance struct for forward, backward filter, or backward data algorithms in
 * immediate mode
 *
 * Contains a 64-bit integer identifying the solution and the algorithm for the solution,
 * as well as the runtime, workspace size and a boolean flag indicating whether the returned
 * solution is a heuristic or resulting from an actual run
 *
 */
typedef struct
{
    float time; /*!< Represents the approximate time required to execute this solution on the GPU,
                     in milliseconds. This value may either be based on an acutal kernel run or an
                     estimate based on a heuristic.*/
    size_t workspace_size; /*!< Workspace required to run the selected algorithm represented in the
                              union */
    uint64_t solution_id;  /*!< Identifier for the returned solution */
    miopenConvAlgorithm_t algorithm; /*!< The algorithm used to compute the solution */

} miopenConvSolution_t;

/*! @brief Query the maximum number of solutions applicable for the given input/output and weights
 *  tensor descriptor for Convolution in the Forward direction.
 *
 * This call returns the maximum number of applicable solutions for a forward convolution problem.
 * The \c solutionCount returned may be used to allocate the memory required for the
 * \c miopenConvAlgoPerf_t which is required by miopenConvolutionGetSolution API calls.
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param solutionCount  Pointer to memory to return number of applicable solutions (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardGetSolutionCount(miopenHandle_t handle,
                                         const miopenTensorDescriptor_t wDesc,
                                         const miopenTensorDescriptor_t xDesc,
                                         const miopenConvolutionDescriptor_t convDesc,
                                         const miopenTensorDescriptor_t yDesc,
                                         size_t* solutionCount);

/*! @brief Query the applicable solutions for a convolution configuration described by
 *  input, output and convolution descriptors.
 *
 *  The returned solutions array is sorted in the order of decreasing performance. The returned
 * solutions
 * might be based
 *  on heuristics and for more consistent performance results the user the advised to run the Find
 * step.
 *  The maximum length of the solutions array may be queried using
 * miopenConvolutionForwardGetSolutionCount
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param maxSolutionCount The size of the solutions array passed in below (input)
 * @param solutionCount The size of the solutions array returned (output)
 * @param solutions      A pointer to an array of type miopenConvSolution_t allocated by the user,
 *                      filled in by MIOpen with applicable solutions. (output)
 * @return               miopenStatus_t
 *
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardGetSolution(miopenHandle_t handle,
                                    const miopenTensorDescriptor_t wDesc,
                                    const miopenTensorDescriptor_t xDesc,
                                    const miopenConvolutionDescriptor_t convDesc,
                                    const miopenTensorDescriptor_t yDesc,
                                    const size_t maxSolutionCount,
                                    size_t* solutionCount,
                                    miopenConvSolution_t* solutions);

/*! @brief Returns the workspace size required for a particular solution id.
 *
 * This is an optional call for users who may have serialized the solution id and just need the
 * workspace
 * size for it. The same information is returned by the miopenConvolutionForwardGetSolution as part
 * of the
 * miopenConvSolution_t struct.
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param solution_id      ID of the solution for which workspace size is required (input)
 * @param workSpaceSize  The size of the workspace (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardGetSolutionWorkspaceSize(miopenHandle_t handle,
                                                 const miopenTensorDescriptor_t wDesc,
                                                 const miopenTensorDescriptor_t xDesc,
                                                 const miopenConvolutionDescriptor_t convDesc,
                                                 const miopenTensorDescriptor_t yDesc,
                                                 const uint64_t solution_id,
                                                 size_t* workSpaceSize);

/*! @brief Compiles the solution provided by the user, this solution may be acquired by the
 * miopenConvolutionForwardGetSolution API call above.
 *   Compiling the solution ensures that the first API call to miopenConvolutionForwardImmediate
 * does
 * not cause a compile.
 *
 *   This is an optional step and may be skipped if a slow first miopenConvolutionForwardImmediate
 * invocation is acceptable.
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardCompileSolution(miopenHandle_t handle,
                                        const miopenTensorDescriptor_t wDesc,
                                        const miopenTensorDescriptor_t xDesc,
                                        const miopenConvolutionDescriptor_t convDesc,
                                        const miopenTensorDescriptor_t yDesc,
                                        const uint64_t solution_id);

/*! @brief Executes the Forward convolution operation based on the provided solution ID.
 *
 * Supported datatypes are fp32, fp16, bfp16, and int8
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param w              Weights tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param x              Data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param workSpace      Workspace tensor (input)
 * @param workSpaceSize  Size of the memory in bytes pointed to by workSpace above
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardImmediate(miopenHandle_t handle,
                                  const miopenTensorDescriptor_t wDesc,
                                  const void* w,
                                  const miopenTensorDescriptor_t xDesc,
                                  const void* x,
                                  const miopenConvolutionDescriptor_t convDesc,
                                  const miopenTensorDescriptor_t yDesc,
                                  void* y,
                                  void* workSpace,
                                  size_t workSpaceSize,
                                  const uint64_t solution_id);

/*! @brief Query the maximum number of solutions applicable for the given input/output and weights
 *  tensor descriptor for backward Convolution w-r-t Data.
 *
 *  This call returns the maximum number of applicable solutions for a the convolution problem, the
 * number
 *  returned may be used to allocate the memory required for the miopenConvAlgoPert2_t which is
 * required
 *  by miopenConvolutionBackwardDataGetSolution API calls.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx (input)
 * @param solutionCount  Pointer to memory to return number of applicable solutions (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataGetSolutionCount(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const miopenTensorDescriptor_t wDesc,
                                              const miopenConvolutionDescriptor_t convDesc,
                                              const miopenTensorDescriptor_t dxDesc,
                                              size_t* solutionCount);

/*! @brief Query the applicable solutions for a backward convolution w-r-t data as described by
 *  input, output and convolution descriptors.
 *
 *  The returned solutions array is sorted in the order of decreasing performance. The returned
 * solutions
 *  ns
 * might be based
 *  on heuristics and for more consistent performance results the user the advised to run the Find
 * step.
 *  The maximum length of the solutions array may be queried using
 * miopenConvolutionBackwardDataGetSolutionCount
 *
 * @param handle           MIOpen handle (input)
 * @param dyDesc           Tensor descriptor for data input tensor dy (input)
 * @param wDesc            Tensor descriptor for weight tensor w (input)
 * @param convDesc         Convolution layer descriptor (input)
 * @param dxDesc           Tensor descriptor for output data tensor dx (input)
 * @param maxSolutionCount The size of the solutions array passed in below (input)
 * @param solutionCount    The size of the solutions array returned (output)
 * @param solutions        A pointer to an array of type miopenConvSolution_t allocated by the user,
 *                         filled in by MIOpen with applicable solutions. (output)
 * @return                 miopenStatus_t
 *
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataGetSolution(miopenHandle_t handle,
                                         const miopenTensorDescriptor_t dyDesc,
                                         const miopenTensorDescriptor_t wDesc,
                                         const miopenConvolutionDescriptor_t convDesc,
                                         const miopenTensorDescriptor_t dxDesc,
                                         const size_t maxSolutionCount,
                                         size_t* solutionCount,
                                         miopenConvSolution_t* solutions);

/*! @brief Returns the workspace size required for a particular solution id.
 *
 * This is an optional call for users who may have serialized the solution id and just need the
 * workspace
 * size for it. The same information is returned by the miopenConvolutionBackwardDataGetSolution as
 * part of the
 * miopenConvSolution_t struct.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc           Tensor descriptor for data input tensor dy (input)
 * @param wDesc            Tensor descriptor for weight tensor w (input)
 * @param convDesc         Convolution layer descriptor (input)
 * @param dxDesc           Tensor descriptor for output data tensor dx (input)
 * @param solution_id      ID of the solution for which workspace size is required (input)
 * @param workSpaceSize  The size of the workspace (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataGetSolutionWorkspaceSize(miopenHandle_t handle,
                                                      const miopenTensorDescriptor_t dyDesc,
                                                      const miopenTensorDescriptor_t wDesc,
                                                      const miopenConvolutionDescriptor_t convDesc,
                                                      const miopenTensorDescriptor_t dxDesc,
                                                      const uint64_t solution_id,
                                                      size_t* workSpaceSize);

/*! @brief Compiles the solution provided by the user, this solution may be acquired by the
 * miopenConvolutionBackwardDataGetSolution API call above.
 *   Compiling the solution ensures that the first API call to
 * miopenConvolutionBackwardDataImmediate
 * does not cause a compile.
 *
 *   This is an optional step and may be skipped if a slow first
 * miopenConvolutionBackwardDataImmediate
 * invocation is acceptable.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx (input)
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataCompileSolution(miopenHandle_t handle,
                                             const miopenTensorDescriptor_t dyDesc,
                                             const miopenTensorDescriptor_t wDesc,
                                             const miopenConvolutionDescriptor_t convDesc,
                                             const miopenTensorDescriptor_t dxDesc,
                                             const uint64_t solution_id);

/*! @brief Executes the Backward convolution w-r-t data  operation based on the provided solution
 * ID.
 *
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param w              Weights tensor w (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx (input)
 * @param dx             Data delta tensor dx (output)
 * @param workSpace      Workspace tensor (input)
 * @param workSpaceSize  Size in bytes of the workspace memory pointed to by workSpace
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataImmediate(miopenHandle_t handle,
                                       const miopenTensorDescriptor_t dyDesc,
                                       const void* dy,
                                       const miopenTensorDescriptor_t wDesc,
                                       const void* w,
                                       const miopenConvolutionDescriptor_t convDesc,
                                       const miopenTensorDescriptor_t dxDesc,
                                       void* dx,
                                       void* workSpace,
                                       size_t workSpaceSize,
                                       const uint64_t solution_id);

/*! @brief Query the maximum number of solutions applicable for the given input/output and weights
 *  tensor descriptor for backward Convolution w-r-t Weights.
 *
 *  This call returns the maximum number of applicable solutions for a the convolution problem, the
 * number
 *  returned may be used to allocate the memory required for the miopenConvAlgoPert2_t which is
 * required
 *  by miopenConvolutionBackwardWeightsGetSolution API calls.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dwDesc         Tensor descriptor for weight tensor dw (input)
 * @param solutionCount  Pointer to memory to return number of applicable solutions (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeightsGetSolutionCount(miopenHandle_t handle,
                                                 const miopenTensorDescriptor_t dyDesc,
                                                 const miopenTensorDescriptor_t xDesc,
                                                 const miopenConvolutionDescriptor_t convDesc,
                                                 const miopenTensorDescriptor_t dwDesc,
                                                 size_t* solutionCount);

/*! @brief Query the applicable solutions for a backward convolution w-r-t weights as described by
 *  input, output and convolution descriptors.
 *
 *  The returned solutions array is sorted in the order of decreasing performance. The returned
 * solutions
 * might be based
 *  on heuristics and for more consistent performance results the user the advised to run the Find
 * step.
 *  The maximum length of the solutions array may be queried using
 * miopenConvolutionBackwardWeightsGetSolutionCount
 *
 * @param handle           MIOpen handle (input)
 * @param dyDesc           Tensor descriptor for data tensor dy (input)
 * @param xDesc            Tensor descriptor for data tensor x (input)
 * @param convDesc         Convolution layer descriptor (input)
 * @param dwDesc           Tensor descriptor for weight tensor dw (input)
 * @param maxSolutionCount The size of the solutions array passed in below (input)
 * @param solutionCount    The size of the solutions array returned (output)
 * @param solutions        A pointer to an array of type miopenConvSolution_t allocated by the user,
 *                         filled in by MIOpen with applicable solutions. (output)
 * @return                 miopenStatus_t
 *
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeightsGetSolution(miopenHandle_t handle,
                                            const miopenTensorDescriptor_t dyDesc,
                                            const miopenTensorDescriptor_t xDesc,
                                            const miopenConvolutionDescriptor_t convDesc,
                                            const miopenTensorDescriptor_t dwDesc,
                                            const size_t maxSolutionCount,
                                            size_t* solutionCount,
                                            miopenConvSolution_t* solutions);

/*! @brief Returns the workspace size required for a particular solution id.
 *
 * This is an optional call for users who may have serialized the solution id and just need the
 * workspace
 * size for it. The same information is returned by the miopenConvolutionBackwardWeightsGetSolution
 * as part of the
 * miopenConvSolution_t struct.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dwDesc         Tensor descriptor for weight tensor dw (input)
 * @param solution_id      ID of the solution for which workspace size is required (input)
 * @param workSpaceSize  The size of the workspace (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenConvolutionBackwardWeightsGetSolutionWorkspaceSize(
    miopenHandle_t handle,
    const miopenTensorDescriptor_t dyDesc,
    const miopenTensorDescriptor_t xDesc,
    const miopenConvolutionDescriptor_t convDesc,
    const miopenTensorDescriptor_t dwDesc,
    const uint64_t solution_id,
    size_t* workSpaceSize);

/*! @brief Compiles the solution provided by the user, this solution may be acquired by the
 * miopenConvolutionBackwardWeightsGetSolution API call above.
 *   Compiling the solution ensures that the first API call to
 * miopenConvolutionBackwardWeightsImmediate
 * does not cause a compile.
 *
 *   This is an optional step and may be skipped if a slow first
 * miopenConvolutionBackwardWeightsImmediate invocation is acceptable.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dwDesc         Tensor descriptor for weight tensor dw (input)
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeightsCompileSolution(miopenHandle_t handle,
                                                const miopenTensorDescriptor_t dyDesc,
                                                const miopenTensorDescriptor_t xDesc,
                                                const miopenConvolutionDescriptor_t convDesc,
                                                const miopenTensorDescriptor_t dwDesc,
                                                const uint64_t solution_id);

/*! @brief Executes the Backward convolution w-r-t weights  operation based on the provided solution
 * ID.
 *
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param x              Data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dwDesc         Tensor descriptor for weight tensor dw (input)
 * @param dw             Weights delta tensor dw (output)
 * @param workSpace      Workspace tensor (input)
 * @param workSpaceSize  Size in bytes of the memory passed in, pointed to by workSpace pointer
 * above
 * @param solution_id      ID of the solution to be compiled, as chosen by the user
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeightsImmediate(miopenHandle_t handle,
                                          const miopenTensorDescriptor_t dyDesc,
                                          const void* dy,
                                          const miopenTensorDescriptor_t xDesc,
                                          const void* x,
                                          const miopenConvolutionDescriptor_t convDesc,
                                          const miopenTensorDescriptor_t dwDesc,
                                          void* dw,
                                          void* workSpace,
                                          size_t workSpaceSize,
                                          const uint64_t solution_id);

/*! @brief Query the workspace size required for a forward convolution algorithm.
 *
 * For given tensor and convolution descriptors, this function calculates and returns the minimum
 * size of the workspace that must be provided to miopenFindConvolutionForwardAlgorithm() in order
 * for the latter to find the best candidate from the available forward data convolution algorithms.
 *
 * WARNING: Providing smaller workspace may result in the selection of a slow convolution
 * algorithm, and therefore affect library performance.
 *
 * It should be assumed that the required workspace size is different for each convolution
 * configuration. Therefore, typically this function should be called at least once for each
 * convolution configuration used.
 *
 * Since the convolution configuration is determined by tensor and convolution descriptors, the user
 * should ensure that all descriptors contain complete information. For example, if Group/Depthwise
 * convolution mode is used, then miopenSetConvolutionGroupCount() should be called before running
 * this, and so on.
 *
 * @param handle         MIOpen handle (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param workSpaceSize  Pointer to memory to return size in bytes (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionForwardGetWorkSpaceSize(miopenHandle_t handle,
                                         const miopenTensorDescriptor_t wDesc,
                                         const miopenTensorDescriptor_t xDesc,
                                         const miopenConvolutionDescriptor_t convDesc,
                                         const miopenTensorDescriptor_t yDesc,
                                         size_t* workSpaceSize);

/*! @brief Search and run the forward convolutional algorithms and return a list of kernel times.
 *
 * This function attempts all MIOpen forward convolution algorithms based on
 * the input configuration, and outputs performance metrics to a
 * user-allocated array of type miopenConvAlgoPerf_t. These metrics are written
 * in a sorted fashion where the first element has the lowest compute time.
 * Users can chose the top-most algorithm if they only care about the fastest
 * algorithm.
 *
 * This function is mandatory before using miopenConvolutionForward(). In order
 * to execute this function, miopenConvolutionForwardGetWorkSpaceSize() must be
 * run to determine the required memory for this search.
 *
 * * If exhaustiveSearch == 0, MIOpen will look for the first kernel with a configuration match. If
 * a configuration match is not found, a default configuration will be returned.
 *
 * * If exhaustiveSearch == 1, MIOpen will look for the best kernel for the provided configuration.
 * If a match is not found, an exhaustive search is performed by running individual algorithms.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle             MIOpen handle (input)
 * @param xDesc              Tensor descriptor for data input tensor x (input)
 * @param x                  Data tensor x (input)
 * @param wDesc              Tensor descriptor for weight tensor w (input)
 * @param w                  Weights tensor w (input)
 * @param convDesc           Convolution layer descriptor (input)
 * @param yDesc              Tensor descriptor for output data tensor y (input)
 * @param y                  Data tensor y (output)
 * @param requestAlgoCount   Number of algorithms to return kernel times (input)
 * @param returnedAlgoCount  Pointer to number of algorithms returned (output)
 * @param perfResults        Pointer to union of best algorithm for forward and backwards (input)
 * @param workSpace          Pointer to workspace buffer (input).
 * @param workSpaceSize      Size in bytes of the workspace buffer (input).
 *                           The buffer must be allocated on the device by the caller.
 *                           The size of the buffer should be determined by calling
 *                           miopenConvolutionForwardGetWorkSpaceSize(), see its
 *                           documentation for details.
 * @param exhaustiveSearch   A boolean to toggle a full search of all algorithms
 *                           and configurations (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFindConvolutionForwardAlgorithm(miopenHandle_t handle,
                                      const miopenTensorDescriptor_t xDesc,
                                      const void* x,
                                      const miopenTensorDescriptor_t wDesc,
                                      const void* w,
                                      const miopenConvolutionDescriptor_t convDesc,
                                      const miopenTensorDescriptor_t yDesc,
                                      void* y,
                                      const int requestAlgoCount,
                                      int* returnedAlgoCount,
                                      miopenConvAlgoPerf_t* perfResults,
                                      void* workSpace,
                                      size_t workSpaceSize,
                                      bool exhaustiveSearch);

/*! @brief Execute a forward convolution layer
 *
 * Runs the forward convolution layer based on the selected algorithm. The function
 * miopenFindConvolutionForwardAlgorithm() must have been executed previously to
 * determine the required memory needed for the workspace and the best convolutional algorithm.
 * The scaling parameter alpha (float) and shift parameter beta (float) are only supported for
 * alpha = 1 and beta = 0 in 2D. In 3D, these parameters can take other values.
 *
 * The forward convolution is designed to accommodate both packed and non-packed tensor strides for
 * multiple data types and dimensions across various platforms. This flexibility ensures optimal
 * performance in handling diverse computational scenarios. To configure tensor parameters,
 * including strides, users can utilize the APIs miopenSetTensorDescriptor() and
 * miopenGetTensorDescriptor(). These APIs empower developers to seamlessly set and retrieve tensor
 * information, facilitating a more intuitive and efficient workflow. The tensor strides are
 * non-packed by default.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param w              Weights tensor w (inputs)
 * @param convDesc       Convolution layer descriptor (inputs)
 * @param algo           Algorithm selected (inputs)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param workSpace      Pointer to workspace required (input)
 * @param workSpaceSize  Size in bytes of the memory determined by the find step (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenConvolutionForward(miopenHandle_t handle,
                                                      const void* alpha,
                                                      const miopenTensorDescriptor_t xDesc,
                                                      const void* x,
                                                      const miopenTensorDescriptor_t wDesc,
                                                      const void* w,
                                                      const miopenConvolutionDescriptor_t convDesc,
                                                      miopenConvFwdAlgorithm_t algo,
                                                      const void* beta,
                                                      const miopenTensorDescriptor_t yDesc,
                                                      void* y,
                                                      void* workSpace,
                                                      size_t workSpaceSize);

/*! @brief Calculate element-wise scale and shift of a tensor via a bias tensor
 *
 *  This function applies an element-wise bias to a data tensor from an input bias tensor.
 *  The scaling parameter alpha (float) and shift parameter beta (float) are only supported for
 *  alpha = 1 and beta = 0.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param bDesc          Tensor descriptor for bias tensor b (input)
 * @param b              Bias tensor b (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for data tensor y (input)
 * @param y              Data tensor y (input and output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenConvolutionForwardBias(miopenHandle_t handle,
                                                          const void* alpha,
                                                          const miopenTensorDescriptor_t bDesc,
                                                          const void* b,
                                                          const void* beta,
                                                          const miopenTensorDescriptor_t yDesc,
                                                          void* y);

/*! @brief Query the workspace size required for a backward data convolution algorithm.
 *
 * For given tensor and convolution descriptors, this function calculates and returns the minimum
 * size of the workspace that must be provided to miopenFindConvolutionBackwardDataAlgorithm() in
 * order for the latter to find the best candidate from the available backward data convolution
 * algorithms.
 *
 * WARNING: Providing smaller workspace may result in the selection of a slow convolution
 * algorithm, and therefore affect library performance.
 *
 * It should be assumed that the required workspace size is different for each convolution
 * configuration. Therefore, typically this function should be called at least once for each
 * convolution configuration used.
 *
 * Since the convolution configuration is determined by tensor and convolution descriptors, the user
 * should ensure that all descriptors contain complete information. For example, if Group/Depthwise
 * convolution mode is used, then miopenSetConvolutionGroupCount() should be called before running
 * this, and so on.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx (input)
 * @param workSpaceSize  Size in bytes of the memory required (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardDataGetWorkSpaceSize(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const miopenTensorDescriptor_t wDesc,
                                              const miopenConvolutionDescriptor_t convDesc,
                                              const miopenTensorDescriptor_t dxDesc,
                                              size_t* workSpaceSize);

/*! @brief Search and run the backwards data convolution algorithms and return a list of kernel
 * times.
 *
 * This function attempts all MIOpen backward data convolution algorithms, and outputs the
 * performance metrics to a user-allocated array of type miopenConvAlgoPerf_t.
 * These metrics are written in sorted fashion where the first element has the lowest compute time.
 * This function is mandatory before using backwards convolutions. Users can chose the top-most
 * algorithm if they only care about the fastest algorithm.
 *
 * This function is mandatory before using miopenConvolutionBackwardData(). In order to
 * execute this function, miopenConvolutionBackwardsDataGetWorkSpaceSize() must be run to determine
 * the required memory for this search.
 *
 * * If exhaustiveSearch == 0, MIOpen will look for the first kernel with a configuration match. If
 * a configuration match is not found, a default configuration will be returned.
 *
 * * If exhaustiveSearch == 1, MIOpen will look for the best kernel for the provided configuration.
 * If a match is not found, an exhaustive search is performed by running individual algorithms.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle             MIOpen handle (input)
 * @param dyDesc             Tensor descriptor for data input tensor dy (input)
 * @param dy                 Data delta tensor dy (input)
 * @param wDesc              Tensor descriptor for weight tensor w (input)
 * @param w                  Weights tensor w (input)
 * @param convDesc           Convolution layer descriptor (input)
 * @param dxDesc             Tensor descriptor for output data tensor dx (input)
 * @param dx                 Data delta tensor dx (input)
 * @param requestAlgoCount   Number of algorithms to return kernel times (input)
 * @param returnedAlgoCount  Pointer to number of algorithms returned (output)
 * @param perfResults        Pointer to union of best algorithm for forward and backwards (output)
 * @param workSpace          Pointer to workspace buffer (input).
 * @param workSpaceSize      Size in bytes of the workspace buffer (input).
 *                           The buffer must be allocated on the device by the caller.
 *                           The size of the buffer should be determined by calling
 *                           miopenConvolutionBackwardDataGetWorkSpaceSize(), see its
 *                           documentation for details.
 * @param exhaustiveSearch   A boolean to toggle a full search of all algorithms
 *                           and configurations (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFindConvolutionBackwardDataAlgorithm(miopenHandle_t handle,
                                           const miopenTensorDescriptor_t dyDesc,
                                           const void* dy,
                                           const miopenTensorDescriptor_t wDesc,
                                           const void* w,
                                           const miopenConvolutionDescriptor_t convDesc,
                                           const miopenTensorDescriptor_t dxDesc,
                                           void* dx,
                                           const int requestAlgoCount,
                                           int* returnedAlgoCount,
                                           miopenConvAlgoPerf_t* perfResults,
                                           void* workSpace,
                                           size_t workSpaceSize,
                                           bool exhaustiveSearch);

/*! @brief Execute a backward data convolution layer
 *
 * Runs the backward data convolution layer based on the selected algorithm. The function
 * miopenFindConvolutionBackwardDataAlgorithm() must have been executed previously to
 * determine the required memory needed for the workspace and the best convolutional
 * algorithm.
 *
 * The backward data convolution is designed to accommodate both packed and non-packed tensor
 * strides for multiple data types and dimensions across various platforms. This flexibility ensures
 * optimal performance in handling diverse computational scenarios. To configure tensor parameters,
 * including strides, users can utilize the APIs miopenSetTensorDescriptor() and
 * miopenGetTensorDescriptor(). These APIs empower developers to seamlessly set and retrieve tensor
 * information, facilitating a more intuitive and efficient workflow. The tensor strides are
 * non-packed by default.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param wDesc          Tensor descriptor for weight tensor w (input)
 * @param w              Weights tensor w (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param algo           Algorithm selected (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx (input)
 * @param dx             Data delta tensor dx (output)
 * @param workSpace      Pointer to workspace required for the search (input)
 * @param workSpaceSize  Size in bytes of the memory needed for find (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardData(miopenHandle_t handle,
                              const void* alpha,
                              const miopenTensorDescriptor_t dyDesc,
                              const void* dy,
                              const miopenTensorDescriptor_t wDesc,
                              const void* w,
                              const miopenConvolutionDescriptor_t convDesc,
                              miopenConvBwdDataAlgorithm_t algo,
                              const void* beta,
                              const miopenTensorDescriptor_t dxDesc,
                              void* dx,
                              void* workSpace,
                              size_t workSpaceSize);

/*! @brief Get the GPU memory required for the backward weights convolution algorithm.
 *
 * For given tensor and convolution descriptors, this function calculates and returns the minimum
 * size of the workspace that must be provided to miopenFindConvolutionBackwardWeightsAlgorithm() in
 * order for the latter to find the best candidate from the available backward weights convolution
 * algorithms.
 *
 * WARNING: Providing smaller workspace may result in the selection of a slow convolution
 * algorithm, and therefore affect library performance.
 *
 * It should be assumed that the required workspace size is different for each convolution
 * configuration. Therefore, typically this function should be called at least once for each
 * convolution configuration used.
 *
 * Since the convolution configuration is determined by tensor and convolution descriptors, the user
 * should ensure that all descriptors contain complete information. For example, if Group/Depthwise
 * convolution mode is used, then miopenSetConvolutionGroupCount() should be called before running
 * this, and so on.
 *
 * @param handle         MIOpen handle (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param dwDesc         Tensor descriptor for output weights tensor dw (input)
 * @param workSpaceSize  Size in bytes of the memory required (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeightsGetWorkSpaceSize(miopenHandle_t handle,
                                                 const miopenTensorDescriptor_t dyDesc,
                                                 const miopenTensorDescriptor_t xDesc,
                                                 const miopenConvolutionDescriptor_t convDesc,
                                                 const miopenTensorDescriptor_t dwDesc,
                                                 size_t* workSpaceSize);

/*! @brief Search and run the backwards weights convolutional algorithms and return a list of kernel
 * times.
 *
 * This function attempts all MIOpen backward weights convolution algorithms, and outputs
 * the performance metrics to a user-allocated array of type miopenConvAlgoPerf_t. These metrics are
 * written in sorted fashion where the first element has the lowest compute time.
 * This function is mandatory before using backwards weight convolutions. Users can chose the
 * top-most algorithm if they only care about the fastest algorithm.
 *
 * This function is mandatory before using miopenConvolutionBackwardWeights(). In order to
 * execute this function, miopenConvolutionBackwardsWeightsGetWorkSpaceSize() must be run to
 * determine the required memory for this search.
 *
 * * If exhaustiveSearch == 0, MIOpen will look for the first kernel with a configuration match. If
 * a configuration match is not found, a default configuration will be returned.
 *
 * * If exhaustiveSearch == 1, MIOpen will look for the best kernel for the provided configuration.
 * If a match is not found, an exhaustive search is performed by running individual algorithms.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle             MIOpen handle (input)
 * @param dyDesc             Tensor descriptor for data input tensor dy (input)
 * @param dy                 Data delta tensor dy (input)
 * @param xDesc              Tensor descriptor for output data tensor x (input)
 * @param x                  Data delta tensor dx (input)
 * @param convDesc           Convolution layer descriptor (input)
 * @param dwDesc             Tensor descriptor for weight tensor dw (input)
 * @param dw                 Weights delta tensor dw (input)
 * @param requestAlgoCount   Number of algorithms to return kernel times (input)
 * @param returnedAlgoCount  Pointer to number of algorithms returned (output)
 * @param perfResults        Pointer to union of best algorithm for forward and backwards (output)
 * @param workSpace          Pointer to workspace buffer (input).
 * @param workSpaceSize      Size in bytes of the workspace buffer (input).
 *                           The buffer must be allocated on the device by the caller.
 *                           The size of the buffer should be determined by calling
 *                           miopenConvolutionBackwardWeightsGetWorkSpaceSize(), see its
 *                           documentation for details.
 * @param exhaustiveSearch   A boolean to toggle a full search of all algorithms
 *                           and configurations (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFindConvolutionBackwardWeightsAlgorithm(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t dyDesc,
                                              const void* dy,
                                              const miopenTensorDescriptor_t xDesc,
                                              const void* x,
                                              const miopenConvolutionDescriptor_t convDesc,
                                              const miopenTensorDescriptor_t dwDesc,
                                              void* dw,
                                              const int requestAlgoCount,
                                              int* returnedAlgoCount,
                                              miopenConvAlgoPerf_t* perfResults,
                                              void* workSpace,
                                              size_t workSpaceSize,
                                              bool exhaustiveSearch);

/*! @brief Execute a backward weights convolution layer
 *
 * Runs the backward weights convolution layer based on the selected algorithm. The function
 * miopenFindConvolutionBackwardWeightsAlgorithm() must have
 * been executed previously to determine the required memory needed for the workspace and the
 * best convolutional algorithm.
 *
 * The backward weights convolution is designed to accommodate both packed and non-packed tensor
 * strides for multiple data types and dimensions across various platforms. This flexibility ensures
 * optimal performance in handling diverse computational scenarios. To configure tensor parameters,
 * including strides, users can utilize the APIs miopenSetTensorDescriptor() and
 * miopenGetTensorDescriptor(). These APIs empower developers to seamlessly set and retrieve tensor
 * information, facilitating a more intuitive and efficient workflow. The tensor strides are
 * non-packed by default.
 *
 * If using Group/Depthwise convolution mode, call miopenSetConvolutionGroupCount() before running
 * this.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param dyDesc         Tensor descriptor for data tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param xDesc          Tensor descriptor for data tensor x (input)
 * @param x              Data tensor x (input)
 * @param convDesc       Convolution layer descriptor (input)
 * @param algo           Algorithm selected (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dwDesc         Tensor descriptor for weight tensor dw (input)
 * @param dw             Weights delta tensor dw (output)
 * @param workSpace      Pointer to workspace required for the search (input)
 * @param workSpaceSize  Size in bytes of the memory needed for find (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBackwardWeights(miopenHandle_t handle,
                                 const void* alpha,
                                 const miopenTensorDescriptor_t dyDesc,
                                 const void* dy,
                                 const miopenTensorDescriptor_t xDesc,
                                 const void* x,
                                 const miopenConvolutionDescriptor_t convDesc,
                                 miopenConvBwdWeightsAlgorithm_t algo,
                                 const void* beta,
                                 const miopenTensorDescriptor_t dwDesc,
                                 void* dw,
                                 void* workSpace,
                                 size_t workSpaceSize);

/*! @brief Calculates the gradient with respect to the bias.
 *
 * @deprecated This function is deprecated and will be removed in a future release.
 *             The underlying OpenCL kernel (MIOpenConvBwdBias.cl) has been removed.
 *             This function now returns miopenStatusNotImplemented.
 *
 * Compute the convolution backwards gradient with respect to the bias tensor.
 * The scaling parameter alpha (float) and shift parameter beta (float) are only supported for
 * alpha = 1 and beta = 0.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dbDesc         Tensor descriptor for input bias tensor db (input)
 * @param db             Bias delta tensor db (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenConvolutionBackwardBias(miopenHandle_t handle,
                                                           const void* alpha,
                                                           const miopenTensorDescriptor_t dyDesc,
                                                           const void* dy,
                                                           const void* beta,
                                                           const miopenTensorDescriptor_t dbDesc,
                                                           void* db);

/** @} */
// CLOSEOUT CONVOLUTIONS DOXYGEN GROUP

// Pooling APIs
/** @addtogroup pooling
 *
 *  @{
 */

/*! @brief Creates a pooling layer descriptor
 *
 * @param poolDesc   Pointer to a pooling layer descriptor (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreatePoolingDescriptor(miopenPoolingDescriptor_t* poolDesc);

/*! @brief Set index data type for pooling layer. The default indexing type is uint8_t.
 * Users can set the index type to any of the miopenIndexType_t sizes; 8, 16, 32, or 64 bit
 * unsigned integers.
 *
 * @param poolDesc     Pointer to a pooling layer descriptor (input)
 * @param index_type   Index type (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetPoolingIndexType(miopenPoolingDescriptor_t poolDesc,
                                                       miopenIndexType_t index_type);

/*! @brief Get the index data type for pooling layer. The index type to any of the
 * miopenIndexType_t sizes; 8, 16, 32, or 64 bit unsigned integers.
 *
 * @param poolDesc     Pointer to a pooling layer descriptor (input)
 * @param index_type   Index type (output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetPoolingIndexType(miopenPoolingDescriptor_t poolDesc,
                                                       miopenIndexType_t* index_type);

/*! @brief Set workspace index mode for pooling layer. The default mode is
 * miopenPoolingWorkSpaceIndexMask.
 *
 * @param poolDesc         Pointer to a pooling layer descriptor (input/output)
 * @param workspace_index  Workspace index mode (input)
 * @return                 miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetPoolingWorkSpaceIndexMode(
    miopenPoolingDescriptor_t poolDesc, miopenPoolingWorkspaceIndexMode_t workspace_index);

/*! @brief Get workspace index mode for pooling layer.
 *
 * @param poolDesc         Pointer to a pooling layer descriptor (input)
 * @param workspace_index  Workspace index mode (output)
 * @return                 miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetPoolingWorkSpaceIndexMode(
    miopenPoolingDescriptor_t poolDesc, miopenPoolingWorkspaceIndexMode_t* workspace_index);

/*! @brief Sets a 2-D pooling layer descriptor details.
 *
 * Sets the window shape, padding, and stride for a previously created 2-D pooling descriptor.
 *
 * @param poolDesc       Pointer to a pooling layer descriptor (output)
 * @param mode           Pooling mode enum (input)
 * @param windowHeight   Input window height dimension (input)
 * @param windowWidth    Input window width dimension (input)
 * @param pad_h          Number of elements to pad height (input)
 * @param pad_w          Number of elements to pad width (input)
 * @param stride_h       Vertical stride (input)
 * @param stride_w       Horizontal stride (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSet2dPoolingDescriptor(miopenPoolingDescriptor_t poolDesc,
                                                          miopenPoolingMode_t mode,
                                                          int windowHeight,
                                                          int windowWidth,
                                                          int pad_h,
                                                          int pad_w,
                                                          int stride_h,
                                                          int stride_w);

/*! @brief Gets a 2-D pooling layer descriptor details
 *
 * Gets the window shape, padding, and stride for a previously created 2-D pooling descriptor.
 *
 * @param poolDesc       Pointer to a pooling layer descriptor (input)
 * @param mode           Pooling mode enum (output)
 * @param windowHeight   Input window height dimension (output)
 * @param windowWidth    Input window width dimension (output)
 * @param pad_h          Number of elements to pad height (output)
 * @param pad_w          Number of elements to pad width (output)
 * @param stride_h       Vertical stride (output)
 * @param stride_w       Horizontal stride (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGet2dPoolingDescriptor(const miopenPoolingDescriptor_t poolDesc,
                                                          miopenPoolingMode_t* mode,
                                                          int* windowHeight,
                                                          int* windowWidth,
                                                          int* pad_h,
                                                          int* pad_w,
                                                          int* stride_h,
                                                          int* stride_w);

/*! @brief Gets the shape of the output tensor for 2-D pooling
 *
 * Retrieve the tensor dimensions for the forward 2-D pooling. This call is required for
 * the forward if the output dimensions are different than the input tensor
 * dimensions.
 *
 * @param poolDesc   Pointer to a pooling layer descriptor (input)
 * @param tensorDesc Input tensor descriptor (input)
 * @param n	         Mini-batch dim (output)
 * @param c	         Number of channels (output)
 * @param h          Heights of input map (output)
 * @param w          Width of input map (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetPoolingForwardOutputDim(const miopenPoolingDescriptor_t poolDesc,
                                 const miopenTensorDescriptor_t tensorDesc,
                                 int* n,
                                 int* c,
                                 int* h,
                                 int* w);

/*! @brief Set details of a N-D pooling layer descriptor
 *
 * Set the window shape, padding, and stride for a previously created N-D pooling descriptor.
 *
 * @param poolDesc     Pointer to a pooling layer descriptor (input/output)
 * @param mode         Pooling mode enum (input)
 * @param nbDims       Dimension of the pooling (input)
 * @param windowDimA   Array of input window dimensions with length equal to or larger than
 * dimsRequested (input)
 * @param padA         Array of number of elements to padding with length equal to or larger than
 * dimsRequested (input)
 * @param stridesA     Array of stride parameter with length equal to or larger than dimsRequested
 * (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetNdPoolingDescriptor(miopenPoolingDescriptor_t poolDesc,
                                                          const miopenPoolingMode_t mode,
                                                          int nbDims,
                                                          const int* windowDimA,
                                                          const int* padA,
                                                          const int* stridesA);

/*! @brief Get details of a N-D pooling layer descriptor
 *
 * Get the window shape, padding, and stride for a previously created N-D pooling descriptor.
 *
 * @param poolDesc         Pointer to a pooling layer descriptor (input)
 * @param nbDimsRequested  Dimension of the expected pooling descriptor (input)
 * @param mode             Pooling mode enum (output)
 * @param nbDims           Actual dimension of the pooling descriptor (output)
 * @param windowDimA       Array of input window dimensions with length equal to or larger than
 * dimsRequested (output)
 * @param padA             Array of number of elements to padding with length equal to or larger
 * than dimsRequested (output)
 * @param stridesA         Array of stride parameter with length equal to or larger than
 * dimsRequested (output)
 * @return                 miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetNdPoolingDescriptor(const miopenPoolingDescriptor_t poolDesc,
                                                          int nbDimsRequested,
                                                          miopenPoolingMode_t* mode,
                                                          int* nbDims,
                                                          int* windowDimA,
                                                          int* padA,
                                                          int* stridesA);

/*! @brief Gets the shape of the output tensor for N-D pooling
 *
 * Retrieve the tensor dimensions for the forward N-D pooling. This call is required for
 * the forward if the output dimensions are different than the input tensor
 * dimensions.
 *
 * @param poolDesc      Pointer to a pooling layer descriptor (input)
 * @param tensorDesc    Input tensor descriptor (input)
 * @param dims          Dimension of the pooling (input)
 * @param tensorDimArr  Array of tensor dimension (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetPoolingNdForwardOutputDim(const miopenPoolingDescriptor_t poolDesc,
                                   const miopenTensorDescriptor_t tensorDesc,
                                   int dims,
                                   int* tensorDimArr);

/*! @brief Get the amount of GPU memory required for pooling
 *
 * Retrieves the amount of workspace in bytes require for pooling. This call is required to
 * determine the amount of GPU memory needed for the backwards pooling algorithms. For max-
 * pooling, an assumption is that index data type is uint8_t, therefore the returned
 * workspace size will be based on this assumption even if the user sets the index type with
 * miopenSetPoolingIndexType().
 *
 * @param yDesc          Descriptor for pooling layer (input)
 * @param workSpaceSize  Pointer to workSpaceSize (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenPoolingGetWorkSpaceSize(const miopenTensorDescriptor_t yDesc,
                                                           size_t* workSpaceSize);

/*! @brief Get the amount of GPU memory required for pooling
 *
 * Retrieves the amount of workspace in bytes require for pooling. This call is required to
 * determine the amount of GPU memory needed for the backwards pooling algorithms. For max-
 * pooling, there is no assumption on index data type. As the user can set the index datatype
 * size using miopenSetPoolingIndexType().
 *
 * @param poolDesc       Pointer to a pooling layer descriptor (input)
 * @param yDesc          Descriptor for pooling layer (input)
 * @param workSpaceSize  Pointer to workSpaceSize (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenPoolingGetWorkSpaceSizeV2(const miopenPoolingDescriptor_t poolDesc,
                                const miopenTensorDescriptor_t yDesc,
                                size_t* workSpaceSize);

/*! @brief Execute a forward pooling layer
 *
 * Runs forward pooling. miopenGetPoolingForwardOutputDim() should be called before
 * miopenPoolingForward().
 * If the parameter do_backward == 0, then set workSpace = nullptr and workSpaceSize = 0. However,
 * for back-propagation do_backwards must be set to 1 in miopenPoolingForward().
 *
 * @param handle         MIOpen handle (input)
 * @param poolDesc       Descriptor for pooling layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param do_backward    Boolean to toggle save data in workspace for backwards pass (input)
 * @param workSpace      Pointer user allocated memory (input)
 * @param workSpaceSize  Size in bytes of the memory needed (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenPoolingForward(miopenHandle_t handle,
                                                  const miopenPoolingDescriptor_t poolDesc,
                                                  const void* alpha,
                                                  const miopenTensorDescriptor_t xDesc,
                                                  const void* x,
                                                  const void* beta,
                                                  const miopenTensorDescriptor_t yDesc,
                                                  void* y,
                                                  bool do_backward,
                                                  void* workSpace,
                                                  size_t workSpaceSize);

/*! @brief Execute a backward pooling layer
 *
 * Runs backward pooling. miopenPoolingGetWorkSpaceSize() must be called before
 * miopenPoolingBackward() to determine the amount of workSpace to be allocated.
 *
 * @param handle         MIOpen handle (input)
 * @param poolDesc       Descriptor for pooling layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param xDesc          Tensor descriptor for output data tensor x (input)
 * @param x              Data tensor x (output)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for tensor dx (input)
 * @param dx             Weights delta tensor dx (output)
 * @param workSpace      Pointer to user allocated workspace (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenPoolingBackward(miopenHandle_t handle,
                                                   const miopenPoolingDescriptor_t poolDesc,
                                                   const void* alpha,
                                                   const miopenTensorDescriptor_t yDesc,
                                                   const void* y,
                                                   const miopenTensorDescriptor_t dyDesc,
                                                   const void* dy,
                                                   const miopenTensorDescriptor_t xDesc,
                                                   const void* x,
                                                   const void* beta,
                                                   const miopenTensorDescriptor_t dxDesc,
                                                   void* dx,
                                                   void* workSpace);

/*! @brief Destroys the pooling descriptor object
 *
 * @param poolDesc Pooling tensor descriptor type (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyPoolingDescriptor(miopenPoolingDescriptor_t poolDesc);

/** @} */
// CLOSEOUT POOLING DOXYGEN GROUP

// LRN APIs
/** @addtogroup LRN
 *
 *  @{
 */
/*! @brief Creates a local response normalization (LRN) layer descriptor
 *
 * @param lrnDesc    Pointer to a local response normalization layer descriptor type
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateLRNDescriptor(miopenLRNDescriptor_t* lrnDesc);

/*! @brief Sets a LRN layer descriptor details
 *
 * Sets all of the descriptor details for the LRN layer. The number of window elements lrnN is
 * a diameter and always odd.
 *
 * @param lrnDesc      Pointer to a LRN layer descriptor (output)
 * @param mode         LRN mode enum (input)
 * @param lrnN         Number of normalization window elements (input)
 * @param lrnAlpha     Scaling factor (input)
 * @param lrnBeta      Shift factor (input)
 * @param lrnK         K factor (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetLRNDescriptor(const miopenLRNDescriptor_t lrnDesc,
                                                    miopenLRNMode_t mode,
                                                    unsigned int lrnN,
                                                    double lrnAlpha,
                                                    double lrnBeta,
                                                    double lrnK);

/*! @brief Gets a LRN layer descriptor details
 *
 * Retrieve the LRN descriptor details.
 *
 * @param lrnDesc      Pointer to a LRN layer descriptor (input)
 * @param mode         LRN mode enum (output)
 * @param lrnN         Number of normalization window elements (output)
 * @param lrnAlpha     Scaling factor (output)
 * @param lrnBeta      Shift factor (output)
 * @param lrnK         K factor (output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetLRNDescriptor(const miopenLRNDescriptor_t lrnDesc,
                                                    miopenLRNMode_t* mode,
                                                    unsigned int* lrnN,
                                                    double* lrnAlpha,
                                                    double* lrnBeta,
                                                    double* lrnK);

/*! @brief Determine the workspace requirements.
 *
 * This function determines the GPU memory allocation required to execute the LRN layer based on the
 * LRN descriptor.
 *
 * @param yDesc           Pointer to a LRN layer descriptor (input)
 * @param workSpaceSize   Output variable for workspace size (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLRNGetWorkSpaceSize(const miopenTensorDescriptor_t yDesc,
                                                       size_t* workSpaceSize);

/*! @brief Execute a LRN forward layer
 *
 * Runs the forward layer normalization in the forward direction. If do_backward == 0, then
 * set workSpace = nullptr and workSpaceSize = 0. However, if the user wishes to execute backwards,
 * then they must set do_backwards = 1 in miopenLRNForward().
 *
 * @param handle         MIOpen handle (input)
 * @param lrnDesc        Descriptor for LRN layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param do_backward    Boolean to toggle save data in workspace for backwards pass (input)
 * @param workSpace      Pointer user allocated memory (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLRNForward(miopenHandle_t handle,
                                              const miopenLRNDescriptor_t lrnDesc,
                                              const void* alpha,
                                              const miopenTensorDescriptor_t xDesc,
                                              const void* x,
                                              const void* beta,
                                              const miopenTensorDescriptor_t yDesc,
                                              void* y,
                                              bool do_backward,
                                              void* workSpace);

/*! @brief Execute a LRN backward layer
 *
 * @param handle         MIOpen handle (input)
 * @param lrnDesc        Descriptor for LRN layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for data input tensor y (input)
 * @param y              Data tensor y (input)
 * @param dyDesc         Tensor descriptor for data input tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param xDesc          Tensor descriptor for input data tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for output data tensor dx(input)
 * @param dx             Data delta tensor x (output)
 * @param workSpace      Pointer user allocated memory (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLRNBackward(miopenHandle_t handle,
                                               const miopenLRNDescriptor_t lrnDesc,
                                               const void* alpha,
                                               const miopenTensorDescriptor_t yDesc,
                                               const void* y,
                                               const miopenTensorDescriptor_t dyDesc,
                                               const void* dy,
                                               const miopenTensorDescriptor_t xDesc,
                                               const void* x,
                                               const void* beta,
                                               const miopenTensorDescriptor_t dxDesc,
                                               void* dx,
                                               const void* workSpace);

/*! @brief Destroys the LRN descriptor object
 *
 * @param lrnDesc   LRN tensor descriptor type (input)
 * @return          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyLRNDescriptor(miopenLRNDescriptor_t lrnDesc);

/** @} */
// CLOSEOUT LRN DOXYGEN GROUP

#ifdef MIOPEN_BETA_API
// LayerNorm APIs
/** @addtogroup layernorm
 *
 *  @{
 */
/*! @brief Execute a layernorm forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param mode           LayerNorm mode (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param weightDesc     Tensor descriptor for data input tensor weight (input)
 * @param weight         Data tensor weight (input)
 * @param biasDesc       Tensor descriptor for data input tensor bias (input)
 * @param bias           Data tensor bias (input)
 * @param epsilon        Value to stabilize inverse variance calculation (input)
 * @param normalized_dim Normalized dimensions in the input array (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param meanDesc       Tensor descriptor for output data tensor mean (input)
 * @param mean           Data tensor mean (output)
 * @param rstdDesc       Tensor descriptor for output data tensor rstd (input)
 * @param rstd           Data tensor rstd (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLayerNormForward(miopenHandle_t handle,
                                                    miopenNormMode_t mode,
                                                    const miopenTensorDescriptor_t xDesc,
                                                    const void* x,
                                                    const miopenTensorDescriptor_t weightDesc,
                                                    const void* weight,
                                                    const miopenTensorDescriptor_t biasDesc,
                                                    const void* bias,
                                                    const float epsilon,
                                                    const int32_t normalized_dim,
                                                    const miopenTensorDescriptor_t yDesc,
                                                    void* y,
                                                    const miopenTensorDescriptor_t meanDesc,
                                                    void* mean,
                                                    const miopenTensorDescriptor_t rstdDesc,
                                                    void* rstd);

/*! @brief Helper function to query the minimum workspace size required by the layernorm backward
 * call
 *
 * @param handle                   MIOpen Handle (input)
 * @param mode                     LayerNorm mode (input)
 * @param dyDesc                   Tensor descriptor for data input tensor dy (input)
 * @param xDesc                    Tensor descriptor for data input tensor x (input)
 * @param weightDesc               Tensor descriptor for data input tensor weight (input)
 * @param meanDesc                 Tensor descriptor for data input tensor mean (input)
 * @param rstdDesc                 Tensor descriptor for data input tensor rstd (input)
 * @param normalized_dim           Normalized dimensions in the input array (input)
 * @param dxDesc                   Tensor descriptor for output data tensor dx (input)
 * @param dwDesc                   Tensor descriptor for output data tensor dw (input)
 * @param dbDesc                   Tensor descriptor for output data tensor db (input)
 * @param sizeInBytes              Pointer to data to return the minimum workspace size
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetLayerNormBackwardWorkspaceSize(miopenHandle_t handle,
                                        miopenNormMode_t mode,
                                        const miopenTensorDescriptor_t dyDesc,
                                        const miopenTensorDescriptor_t xDesc,
                                        const miopenTensorDescriptor_t weightDesc,
                                        const miopenTensorDescriptor_t meanDesc,
                                        const miopenTensorDescriptor_t rstdDesc,
                                        const int32_t normalized_dim,
                                        const miopenTensorDescriptor_t dxDesc,
                                        const miopenTensorDescriptor_t dwDesc,
                                        const miopenTensorDescriptor_t dbDesc,
                                        size_t* sizeInBytes);

/*! @brief Execute a layernorm backward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param mode                     LayerNorm mode (input)
 * @param workspace                Address of the allocated workspace data (input)
 * @param workspaceSizeInBytes     Size in bytes of the allocated workspace data (input)
 * @param dyDesc                   Tensor descriptor for data input tensor dy (input)
 * @param dy                       Data tensor dy (input)
 * @param xDesc                    Tensor descriptor for input data tensor x (input)
 * @param x                        Data tensor x (input)
 * @param weightDesc               Tensor descriptor for data input tensor weight (input)
 * @param weight                   Data tensor weight (input)
 * @param meanDesc                 Tensor descriptor for input data tensor mean (input)
 * @param mean                     Data tensor mean (input)
 * @param rstdDesc                 Tensor descriptor for input data tensor rstd (input)
 * @param rstd                     Data tensor rstd (input)
 * @param normalized_dim           Normalized dimensions in the input array (input)
 * @param dxDesc                   Tensor descriptor for output data tensor dx (input)
 * @param dx                       Data tensor dx (output)
 * @param dwDesc                   Tensor descriptor for output data tensor dw (input)
 * @param dw                       Data tensor dw (output)
 * @param dbDesc                   Tensor descriptor for output data tensor db (input)
 * @param db                       Data tensor db (output)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLayerNormBackward(miopenHandle_t handle,
                                                     miopenNormMode_t mode,
                                                     void* workspace,
                                                     size_t workspaceSizeInBytes,
                                                     const miopenTensorDescriptor_t dyDesc,
                                                     const void* dy,
                                                     const miopenTensorDescriptor_t xDesc,
                                                     const void* x,
                                                     const miopenTensorDescriptor_t weightDesc,
                                                     const void* weight,
                                                     const miopenTensorDescriptor_t meanDesc,
                                                     const void* mean,
                                                     const miopenTensorDescriptor_t rstdDesc,
                                                     const void* rstd,
                                                     const int32_t normalized_dim,
                                                     const miopenTensorDescriptor_t dxDesc,
                                                     void* dx,
                                                     const miopenTensorDescriptor_t dwDesc,
                                                     void* dw,
                                                     const miopenTensorDescriptor_t dbDesc,
                                                     void* db);

/** @} */
// CLOSEOUT LAYERNORM DOXYGEN GROUP
#endif

#ifdef MIOPEN_BETA_API
// Cat APIs
/** @addtogroup cat
 *
 *  @{
 */
/*! @brief Execute a cat forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param xCount         Number of input tensor x (input)
 * @param xDescs         Tensor descriptor of input tensor x (input)
 * @param xs             Source data tensor x (input)
 * @param yDesc          Tensor descriptor of output tensor y (input)
 * @param y              Data tensor y (output)
 * @param dim            Concatenation dimension (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCatForward(miopenHandle_t handle,
                                              const int32_t xCount,
                                              const miopenTensorDescriptor_t* xDescs,
                                              const void* const* xs,
                                              const miopenTensorDescriptor_t yDesc,
                                              void* y,
                                              const int32_t dim);

/** @} */
// CLOSEOUT CAT DOXYGEN GROUP
#endif

// Batch-Normalization APIs
/** @addtogroup batchnorm
 *
 *  @{
 */

/*! @brief Derive tensor for gamma and beta from input tensor descriptor
 *
 * This function takes the input tensor descriptor and outputs a derived tensor for the
 * normalization scale (gamma) and shift (beta) tensors.
 *
 * For an input tensor NCHW and spatial mode, the output derived tensor is 1C11, while for
 * per-activation the derived tensor is 1CHW.
 *
 * For an input tensor NCDHW and spatial mode, the output derived tensor is 1C111, while for
 * per-activation the derived tensor is 1CDHW.
 *
 * @param derivedBnDesc   Output derived tensor descriptor (output)
 * @param xDesc           Input tensor descriptor (input)
 * @param bn_mode         Batch Normalization mode (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDeriveBNTensorDescriptor(miopenTensorDescriptor_t derivedBnDesc,
                                                            const miopenTensorDescriptor_t xDesc,
                                                            miopenBatchNormMode_t bn_mode);

/*! @brief Execute forward training layer for batch normalization
 *
 * Batch normalization pass for forward training pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either resultSaveMean, or resultSaveInvVariance are null pointers then the values for the mean
 * and inverse variance will not be used.
 *
 * Likewise, if either resultRunningMean, or resultRunningVariance are null pointers then the values
 * for the running mean and variance will not be saved.
 * Running averages and variances are scaled using an exponential averaging factor: \f[
 * \mu_{old} = \mu_{new}*factor + \mu_{old}*(1-factor)
 * \f]
 * where \f[
 * factor=1/(1+iteration)
 * \f]
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param bnScaleBiasMeanVarDesc    Tensor descriptor for BN scaling, shifting, saved variance and
 * mean (input)
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param expAvgFactor              Exponential averaging factor (input)
 * @param resultRunningMean         Running average saved for inference (output)
 * @param resultRunningVariance     Running variance saved for inference (output)
 * @param epsilon                   Value to stablize inverse variance calculation (input)
 * @param resultSaveMean            Saved mini-batch mean for backwards pass (output)
 * @param resultSaveInvVariance     Saved mini-batch inverse variance for backwards pass (output)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationForwardTraining(miopenHandle_t handle,
                                        miopenBatchNormMode_t bn_mode,
                                        void* alpha,
                                        void* beta,
                                        const miopenTensorDescriptor_t xDesc,
                                        const void* x,
                                        const miopenTensorDescriptor_t yDesc,
                                        void* y,
                                        const miopenTensorDescriptor_t bnScaleBiasMeanVarDesc,
                                        void* bnScale,
                                        void* bnBias,
                                        double expAvgFactor,
                                        void* resultRunningMean,
                                        void* resultRunningVariance,
                                        double epsilon,
                                        void* resultSaveMean,
                                        void* resultSaveInvVariance);
/*! @brief Execute forward training layer for batch normalization
 *
 * Batch normalization pass for forward training pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either resultSaveMean, or resultSaveInvVariance are null pointers then the values for the mean
 * and inverse variance will not be used.
 *
 * Likewise, if either resultRunningMean, or resultRunningVariance are null pointers then the values
 * for the running mean and variance will not be saved.
 * Running averages and variances are scaled using an exponential averaging factor: \f[
 * \mu_{old} = \mu_{new}*factor + \mu_{old}*(1-factor)
 * \f]
 * where \f[
 * factor=1/(1+iteration)
 * \f]
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param savedMeanDesc             Tensor descriptor for BN saved Mean
 * @param savedVarDesc              Tensor descriptor for BN saved Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param expAvgFactor              Exponential averaging factor (input)
 * @param resultRunningMean         Running average saved for inference (output)
 * @param resultRunningVariance     Running variance saved for inference (output)
 * @param epsilon                   Value to stablize inverse variance calculation (input)
 * @param resultSaveMean            Saved mini-batch mean for backwards pass (output)
 * @param resultSaveInvVariance     Saved mini-batch inverse variance for backwards pass (output)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationForwardTraining_V2(miopenHandle_t handle,
                                           miopenBatchNormMode_t bn_mode,
                                           void* alpha,
                                           void* beta,
                                           const miopenTensorDescriptor_t xDesc,
                                           const void* x,
                                           const miopenTensorDescriptor_t yDesc,
                                           void* y,
                                           const miopenTensorDescriptor_t scaleDesc,
                                           const miopenTensorDescriptor_t biasVarDesc,
                                           const miopenTensorDescriptor_t savedMeanDesc,
                                           const miopenTensorDescriptor_t savedVarDesc,
                                           void* bnScale,
                                           void* bnBias,
                                           double expAvgFactor,
                                           void* resultRunningMean,
                                           void* resultRunningVariance,
                                           double epsilon,
                                           void* resultSaveMean,
                                           void* resultSaveInvVariance);
/*! @brief Execute forward training layer for batch normalization
 *
 * Batch normalization pass for forward training pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either resultSaveMean, or resultSaveInvVariance are null pointers then the values for the mean
 * and inverse variance will not be used.
 *
 * Likewise, if either resultRunningMean, or resultRunningVariance are null pointers then the values
 * for the running mean and variance will not be saved.
 * Running averages and variances are scaled using an exponential averaging factor: \f[
 * \mu_{old} = \mu_{new}*factor + \mu_{old}*(1-factor)
 * \f]
 * where \f[
 * factor=1/(1+iteration)
 * \f]
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param savedMeanDesc             Tensor descriptor for BN saved Mean
 * @param savedVarDesc              Tensor descriptor for BN saved Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param expAvgFactor              Exponential averaging factor (input)
 * @param prevResultRunningMean     Running mean from previous iteration, read-only (input)
 * @param prevResultRunningVariance Running variance from previous iteration, read-only (input)
 * @param nextResultRunningMean     Updated running mean for current iteration (output)
 * @param nextResultRunningVariance Updated running variance for current iteration (output)
 * @param epsilon                   Value to stablize inverse variance calculation (input)
 * @param resultSaveMean            Saved mini-batch mean for backwards pass (output)
 * @param resultSaveInvVariance     Saved mini-batch inverse variance for backwards pass (output)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationForwardTraining_V3(miopenHandle_t handle,
                                           miopenBatchNormMode_t bn_mode,
                                           void* alpha,
                                           void* beta,
                                           const miopenTensorDescriptor_t xDesc,
                                           const void* x,
                                           const miopenTensorDescriptor_t yDesc,
                                           void* y,
                                           const miopenTensorDescriptor_t scaleDesc,
                                           const miopenTensorDescriptor_t biasVarDesc,
                                           const miopenTensorDescriptor_t savedMeanDesc,
                                           const miopenTensorDescriptor_t savedVarDesc,
                                           void* bnScale,
                                           void* bnBias,
                                           double expAvgFactor,
                                           const void* prevResultRunningMean,
                                           const void* prevResultRunningVariance,
                                           void* nextResultRunningMean,
                                           void* nextResultRunningVariance,
                                           double epsilon,
                                           void* resultSaveMean,
                                           void* resultSaveInvVariance);
/*! @brief Execute forward training layer for batch normalization with fused activation
 *
 * Batch normalization pass for forward training pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either resultSaveMean, or resultSaveInvVariance are null pointers then the values for the mean
 * and inverse variance will not be used.
 *
 * Likewise, if either resultRunningMean, or resultRunningVariance are null pointers then the values
 * for the running mean and variance will not be saved.
 * Running averages and variances are scaled using an exponential averaging factor: \f[
 * \mu_{old} = \mu_{new}*factor + \mu_{old}*(1-factor)
 * \f]
 * where \f[
 * factor=1/(1+iteration)
 * \f]
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param savedMeanDesc             Tensor descriptor for BN saved Mean
 * @param savedVarDesc              Tensor descriptor for BN saved Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param expAvgFactor              Exponential averaging factor (input)
 * @param resultRunningMean         Running average saved for inference (output)
 * @param resultRunningVariance     Running variance saved for inference (output)
 * @param epsilon                   Value to stablize inverse variance calculation (input)
 * @param resultSaveMean            Saved mini-batch mean for backwards pass (output)
 * @param resultSaveInvVariance     Saved mini-batch inverse variance for backwards pass (output)
 * @param activDesc                 Activation descriptor
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormForwardTrainingActivation(miopenHandle_t handle,
                                         miopenBatchNormMode_t bn_mode,
                                         void* alpha,
                                         void* beta,
                                         const miopenTensorDescriptor_t xDesc,
                                         const void* x,
                                         const miopenTensorDescriptor_t yDesc,
                                         void* y,
                                         const miopenTensorDescriptor_t scaleDesc,
                                         const miopenTensorDescriptor_t biasVarDesc,
                                         const miopenTensorDescriptor_t savedMeanDesc,
                                         const miopenTensorDescriptor_t savedVarDesc,
                                         void* bnScale,
                                         void* bnBias,
                                         double expAvgFactor,
                                         void* resultRunningMean,
                                         void* resultRunningVariance,
                                         double epsilon,
                                         void* resultSaveMean,
                                         void* resultSaveInvVariance,
                                         const miopenActivationDescriptor_t activDesc);

/*! @brief Execute forward training layer for batch normalization with fused activation
 *
 * Batch normalization pass for forward training pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either resultSaveMean, or resultSaveInvVariance are null pointers then the values for the mean
 * and inverse variance will not be used.
 *
 * Likewise, if either resultRunningMean, or resultRunningVariance are null pointers then the values
 * for the running mean and variance will not be saved.
 * Running averages and variances are scaled using an exponential averaging factor: \f[
 * \mu_{old} = \mu_{new}*factor + \mu_{old}*(1-factor)
 * \f]
 * where \f[
 * factor=1/(1+iteration)
 * \f]
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param savedMeanDesc             Tensor descriptor for BN saved Mean
 * @param savedVarDesc              Tensor descriptor for BN saved Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param expAvgFactor              Exponential averaging factor (input)
 * @param prevResultRunningMean     Running mean from previous iteration, read-only (input)
 * @param prevResultRunningVariance Running variance from previous iteration, read-only (input)
 * @param nextResultRunningMean     Updated running mean for current iteration (output)
 * @param nextResultRunningVariance Updated running variance for current iteration (output)
 * @param epsilon                   Value to stablize inverse variance calculation (input)
 * @param resultSaveMean            Saved mini-batch mean for backwards pass (output)
 * @param resultSaveInvVariance     Saved mini-batch inverse variance for backwards pass (output)
 * @param activDesc                 Activation descriptor
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormForwardTrainingActivation_V2(miopenHandle_t handle,
                                            miopenBatchNormMode_t bn_mode,
                                            void* alpha,
                                            void* beta,
                                            const miopenTensorDescriptor_t xDesc,
                                            const void* x,
                                            const miopenTensorDescriptor_t yDesc,
                                            void* y,
                                            const miopenTensorDescriptor_t scaleDesc,
                                            const miopenTensorDescriptor_t biasVarDesc,
                                            const miopenTensorDescriptor_t savedMeanDesc,
                                            const miopenTensorDescriptor_t savedVarDesc,
                                            void* bnScale,
                                            void* bnBias,
                                            double expAvgFactor,
                                            const void* prevResultRunningMean,
                                            const void* prevResultRunningVariance,
                                            void* nextResultRunningMean,
                                            void* nextResultRunningVariance,
                                            double epsilon,
                                            void* resultSaveMean,
                                            void* resultSaveInvVariance,
                                            const miopenActivationDescriptor_t activDesc);

/*! @brief Execute forward inference layer for batch normalization
 *
 * Batch normalization pass for forward inference pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either estimatedMean, or estimatedVariance are null pointers then the values for the mean and
 * variance will be calculated from input data and this calculated mean and variance will be used
 * to update input values.
 * If variance is zero and epsilon is also zero, this function outputs NaN values.  Input epsilon
 * value should always be non zero positive value.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param bnScaleBiasMeanVarDesc    Tensor descriptor for BN scaling, shifting, saved variance and
 * mean (input)
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param estimatedMean             Running average saved during forward training (input)
 * @param estimatedVariance         Running variance saved during forward training (input)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationForwardInference(miopenHandle_t handle,
                                         miopenBatchNormMode_t bn_mode,
                                         void* alpha,
                                         void* beta,
                                         const miopenTensorDescriptor_t xDesc,
                                         const void* x,
                                         const miopenTensorDescriptor_t yDesc,
                                         void* y,
                                         const miopenTensorDescriptor_t bnScaleBiasMeanVarDesc,
                                         void* bnScale,
                                         void* bnBias,
                                         void* estimatedMean,
                                         void* estimatedVariance,
                                         double epsilon);

/*! @brief Execute forward inference layer for batch normalization
 *
 * Batch normalization pass for forward inference pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either estimatedMean, or estimatedVariance are null pointers then the values for the mean and
 * variance will be calculated from input data and this calculated mean and variance will be used
 * to update input values.
 * If variance is zero and epsilon is also zero, this function outputs NaN values.  Input epsilon
 * value should always be non zero positive value.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param estMeanDesc               Tensor descriptor for BN estimated Mean
 * @param estVarianceDesc           Tensor descriptor for BN estimated Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param estimatedMean             Running average saved during forward training (input)
 * @param estimatedVariance         Running variance saved during forward training (input)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationForwardInference_V2(miopenHandle_t handle,
                                            miopenBatchNormMode_t bn_mode,
                                            void* alpha,
                                            void* beta,
                                            const miopenTensorDescriptor_t xDesc,
                                            const void* x,
                                            const miopenTensorDescriptor_t yDesc,
                                            void* y,
                                            const miopenTensorDescriptor_t scaleDesc,
                                            const miopenTensorDescriptor_t biasDesc,
                                            const miopenTensorDescriptor_t estMeanDesc,
                                            const miopenTensorDescriptor_t estVarianceDesc,
                                            void* bnScale,
                                            void* bnBias,
                                            void* estimatedMean,
                                            void* estimatedVariance,
                                            double epsilon);

/*! @brief Execute forward inference layer for batch normalization using inverse variance
 *
 * Batch normalization pass for forward inference pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either estimatedMean, or estimatedInvVariance are null pointers then the values for the mean
 * and inverse variance will be calculated from input data using an epsilon of 1e-5, and this
 * calculated mean and inverse variance will be used to update input values.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param estMeanDesc               Tensor descriptor for BN estimated Mean
 * @param estInvVarianceDesc        Tensor descriptor for BN estimated inverse variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param estimatedMean             Running average saved during forward training (input)
 * @param estimatedInvVariance      Running inverse variance saved during forward training (input)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenBatchNormalizationForwardInferenceInvVariance(
    miopenHandle_t handle,
    miopenBatchNormMode_t bn_mode,
    void* alpha,
    void* beta,
    const miopenTensorDescriptor_t xDesc,
    const void* x,
    const miopenTensorDescriptor_t yDesc,
    void* y,
    const miopenTensorDescriptor_t scaleDesc,
    const miopenTensorDescriptor_t biasDesc,
    const miopenTensorDescriptor_t estMeanDesc,
    const miopenTensorDescriptor_t estInvVarianceDesc,
    void* bnScale,
    void* bnBias,
    void* estimatedMean,
    void* estimatedInvVariance);

/*! @brief Execute forward inference layer for batch normalization with fused activation using
 * inverse variance
 *
 * Batch normalization pass for forward inference pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either estimatedMean, or estimatedInvVariance are null pointers then the values for the mean
 * and inverse variance will be calculated from input data using an epsilon of 1e-5 and this
 * calculated mean and inverse variance will be used to update input values.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param estMeanDesc               Tensor descriptor for BN estimated Mean
 * @param estInvVarianceDesc        Tensor descriptor for BN estimated inverse variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param estimatedMean             Running average saved during forward training (input)
 * @param estimatedInvVariance      Running inverse variance saved during forward training (input)
 * @param activDesc                 Activation descriptor
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenBatchNormForwardInferenceActivationInvVariance(
    miopenHandle_t handle,
    miopenBatchNormMode_t bn_mode,
    void* alpha,
    void* beta,
    const miopenTensorDescriptor_t xDesc,
    const void* x,
    const miopenTensorDescriptor_t yDesc,
    void* y,
    const miopenTensorDescriptor_t scaleDesc,
    const miopenTensorDescriptor_t biasDesc,
    const miopenTensorDescriptor_t estMeanDesc,
    const miopenTensorDescriptor_t estInvVarianceDesc,
    void* bnScale,
    void* bnBias,
    void* estimatedMean,
    void* estimatedInvVariance,
    const miopenActivationDescriptor_t activDesc);

/*! @brief Execute forward inference layer for batch normalization with fused activation
 *
 * Batch normalization pass for forward inference pass.
 * Takes in batch normalization mode bn_mode and input tensor x, output tensor y, bnBias and bnScale
 * with their descriptor.
 *
 * If either estimatedMean, or estimatedVariance are null pointers then the values for the mean and
 * variance will be calculated from input data and this calculated mean and variance will be used
 * to update input values.
 * If variance is zero and epsilon is also zero, this function outputs NaN values.  Input epsilon
 * value should always be non zero positive value.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alpha                     Floating point scaling factor, allocated on the host (input)
 * @param beta                      Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param yDesc                     Tensor descriptor for output data tensor y (input)
 * @param y                         Data tensor y (output)
 * @param ScaleDesc                 Tensor descriptor for BN scaling
 * @param biasVarDesc               Tensor descriptor for BN bias
 * @param estMeanDesc               Tensor descriptor for BN estimated Mean
 * @param estVarianceDesc           Tensor descriptor for BN estimated Variance
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias, beta, tensor (input)
 * @param estimatedMean             Running average saved during forward training (input)
 * @param estimatedVariance         Running variance saved during forward training (input)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @param activDesc                 Activation descriptor
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormForwardInferenceActivation(miopenHandle_t handle,
                                          miopenBatchNormMode_t bn_mode,
                                          void* alpha,
                                          void* beta,
                                          const miopenTensorDescriptor_t xDesc,
                                          const void* x,
                                          const miopenTensorDescriptor_t yDesc,
                                          void* y,
                                          const miopenTensorDescriptor_t scaleDesc,
                                          const miopenTensorDescriptor_t biasDesc,
                                          const miopenTensorDescriptor_t estMeanDesc,
                                          const miopenTensorDescriptor_t estVarianceDesc,
                                          void* bnScale,
                                          void* bnBias,
                                          void* estimatedMean,
                                          void* estimatedVariance,
                                          double epsilon,
                                          const miopenActivationDescriptor_t activDesc);

/*! @brief Execute backwards propagation layer for batch normalization
 *
 * Batch normalization pass for backwards propagation training pass.
 * The method for backwards propagation batch normalization.
 *
 * Takes in batch normalization mode bn_mode and input tensor data x, input activation tensor dy,
 * output tensor dx, the learned tensors resultBNBiasDiff and resultBNScaleDiff with their
 * descriptor.
 *
 * If BOTH savedMean, and savedVariance are not null pointers then the method will use the saved
 * mean and variance calculated by the forward training phase.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alphaDataDiff             Floating point scaling factor, allocated on the host (input)
 * @param betaDataDiff              Floating point shift factor, allocated on the host (input)
 * @param alphaParamDiff            Floating point scaling factor, allocated on the host (input)
 * @param betaParamDiff             Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param dyDesc                    Tensor descriptor for output data tensor y (input)
 * @param dy                        Data tensor y (input)
 * @param dxDesc                    Tensor descriptor for output data tensor dx (input)
 * @param dx                        Data delta tensor dx (output)
 * @param bnScaleBiasDiffDesc       Tensor descriptor for BN scaling, shifting, saved variance and
 * mean (input)
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param resultBnScaleDiff         Tensor for dscale (output)
 * @param resultBnBiasDiff          Tensor for dbias (output)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @param savedMean                 Saved mini-batch mean for backwards pass (input)
 * @param savedInvVariance          Saved mini-batch inverse variance for backwards pass (input)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationBackward(miopenHandle_t handle,
                                 miopenBatchNormMode_t bn_mode,
                                 const void* alphaDataDiff,
                                 const void* betaDataDiff,
                                 const void* alphaParamDiff,
                                 const void* betaParamDiff,
                                 const miopenTensorDescriptor_t xDesc,
                                 const void* x,
                                 const miopenTensorDescriptor_t dyDesc,
                                 const void* dy,
                                 const miopenTensorDescriptor_t dxDesc,
                                 void* dx,
                                 const miopenTensorDescriptor_t bnScaleBiasDiffDesc,
                                 const void* bnScale,
                                 void* resultBnScaleDiff,
                                 void* resultBnBiasDiff,
                                 double epsilon,
                                 const void* savedMean,
                                 const void* savedInvVariance);

/*! @brief Execute backwards propagation layer for batch normalization
 *
 * Batch normalization pass for backwards propagation training pass.
 * The method for backwards propagation batch normalization.
 *
 * Takes in batch normalization mode bn_mode and input tensor data x, input activation tensor dy,
 * output tensor dx, the learned tensors resultBNBiasDiff and resultBNScaleDiff with their
 * descriptor.
 *
 * If BOTH savedMean, and savedVariance are not null pointers then the method will use the saved
 * mean and variance calculated by the forward training phase.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alphaDataDiff             Floating point scaling factor, allocated on the host (input)
 * @param betaDataDiff              Floating point shift factor, allocated on the host (input)
 * @param alphaParamDiff            Floating point scaling factor, allocated on the host (input)
 * @param betaParamDiff             Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param dyDesc                    Tensor descriptor for output data tensor y (input)
 * @param dy                        Data tensor y (input)
 * @param dxDesc                    Tensor descriptor for output data tensor dx (input)
 * @param dx                        Data delta tensor dx (output)
 * @param scaleDesc                 Tensor descriptor for scaling descriptor (input)
 * @param biasDesc                  Tensor descriptor for bias/shift descriptor (input)
 * @param savedMeanDesc             Tensor descriptor for saved Mean  descriptor (input)
 * @param savedVarDesc              Tensor descriptor for saved Variance descriptor (input)
 * , shifting, saved variance and
 * mean (input)
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param resultBnScaleDiff         Tensor for dscale (output)
 * @param resultBnBiasDiff          Tensor for dbias (output)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @param savedMean                 Saved mini-batch mean for backwards pass (input)
 * @param savedInvVariance          Saved mini-bathc inverse variance for backwards pass (input)
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormalizationBackward_V2(miopenHandle_t handle,
                                    miopenBatchNormMode_t bn_mode,
                                    const void* alphaDataDiff,
                                    const void* betaDataDiff,
                                    const void* alphaParamDiff,
                                    const void* betaParamDiff,
                                    const miopenTensorDescriptor_t xDesc,
                                    const void* x,
                                    const miopenTensorDescriptor_t dyDesc,
                                    const void* dy,
                                    const miopenTensorDescriptor_t dxDesc,
                                    void* dx,
                                    const miopenTensorDescriptor_t scaleDesc,
                                    const miopenTensorDescriptor_t biasDesc,
                                    const miopenTensorDescriptor_t savedMeanDesc,
                                    const miopenTensorDescriptor_t savedVarDesc,
                                    const void* bnScale,
                                    void* resultBnScaleDiff,
                                    void* resultBnBiasDiff,
                                    double epsilon,
                                    const void* savedMean,
                                    const void* savedInvVariance);

/*! @brief Execute backwards propagation layer for batch normalization with fused activation
 *
 * Batch normalization pass for backwards propagation training pass.
 * The method for backwards propagation batch normalization.
 *
 * Takes in batch normalization mode bn_mode and input tensor data x, input activation tensor dy,
 * output tensor dx, the learned tensors resultBNBiasDiff and resultBNScaleDiff with their
 * descriptor.
 *
 * If BOTH savedMean, and savedVariance are not null pointers then the method will use the saved
 * mean and variance calculated by the forward training phase.
 *
 * @param handle                    MIOpen handle (input)
 * @param bn_mode                   Batch normalization mode (input)
 * @param alphaDataDiff             Floating point scaling factor, allocated on the host (input)
 * @param betaDataDiff              Floating point shift factor, allocated on the host (input)
 * @param alphaParamDiff            Floating point scaling factor, allocated on the host (input)
 * @param betaParamDiff             Floating point shift factor, allocated on the host (input)
 * @param xDesc                     Tensor descriptor for data input tensor x (input)
 * @param x                         Data tensor x (input)
 * @param dyDesc                    Tensor descriptor for output data tensor y (input)
 * @param dy                        Data tensor y (input)
 * @param dxDesc                    Tensor descriptor for output data tensor dx (input)
 * @param dx                        Data delta tensor dx (output)
 * @param scaleDesc                 Tensor descriptor for scaling descriptor (input)
 * @param biasDesc                  Tensor descriptor for bias/shift descriptor (input)
 * @param savedMeanDesc             Tensor descriptor for saved Mean  descriptor (input)
 * @param savedVarDesc              Tensor descriptor for saved Variance descriptor (input)
 * , shifting, saved variance and
 * mean (input)
 * @param bnScale                   Batch norm scaling, gamma, tensor (input)
 * @param bnBias                    Batch norm bias (input)
 * @param resultBnScaleDiff         Tensor for dscale (output)
 * @param resultBnBiasDiff          Tensor for dbias (output)
 * @param epsilon                   Value to stabilize inverse variance calculation (input)
 * @param savedMean                 Saved mini-batch mean for backwards pass (input)
 * @param savedInvVariance          Saved mini-bathc inverse variance for backwards pass (input)
 * @param activDesc                 Activation descriptor
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenBatchNormBackwardActivation(miopenHandle_t handle,
                                  miopenBatchNormMode_t bn_mode,
                                  const void* alphaDataDiff,
                                  const void* betaDataDiff,
                                  const void* alphaParamDiff,
                                  const void* betaParamDiff,
                                  const miopenTensorDescriptor_t xDesc,
                                  const void* x,
                                  const miopenTensorDescriptor_t dyDesc,
                                  const void* dy,
                                  const miopenTensorDescriptor_t dxDesc,
                                  void* dx,
                                  const miopenTensorDescriptor_t scaleDesc,
                                  const miopenTensorDescriptor_t biasDesc,
                                  const miopenTensorDescriptor_t savedMeanDesc,
                                  const miopenTensorDescriptor_t savedVarianceDesc,
                                  const void* bnScale,
                                  const void* bnBias,
                                  void* resultBnScaleDiff,
                                  void* resultBnBiasDiff,
                                  double epsilon,
                                  const void* savedMean,
                                  const void* savedInvVariance,
                                  const miopenActivationDescriptor_t activDesc);
/** @} */
// CLOSEOUT BATCHNORM DOXYGEN GROUP

// Activation APIs
/** @addtogroup activation
 *
 *  @{
 */
/*! @brief Creates the Activation descriptor object
 *
 * @param activDesc Pointer to an activation tensor descriptor type
 * @return          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateActivationDescriptor(miopenActivationDescriptor_t* activDesc);

/*! @brief Sets the activation layer descriptor details
 *
 * Sets all of the descriptor details for the activation layer
 *
 * @param activDesc    Pointer to a activation layer descriptor (output)
 * @param mode         Activation mode enum (input)
 * @param activAlpha   Alpha value for some activation modes (input)
 * @param activBeta    Beta value for some activation modes (input)
 * @param activGamma   Gamma value for some activation modes (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetActivationDescriptor(const miopenActivationDescriptor_t activDesc,
                              miopenActivationMode_t mode,
                              double activAlpha,
                              double activBeta,
                              double activGamma);

/*! @brief Gets the activation layer descriptor details
 *
 * Retrieves all of the descriptor details for the activation layer.
 *
 * @param activDesc    Pointer to a activation layer descriptor (input)
 * @param mode         Activation mode enum (output)
 * @param activAlpha   Alpha value for some activation modes (output)
 * @param activBeta    Beta value for some activation modes (output)
 * @param activGamma   Gamma value for some activation modes (output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetActivationDescriptor(const miopenActivationDescriptor_t activDesc,
                              miopenActivationMode_t* mode,
                              double* activAlpha,
                              double* activBeta,
                              double* activGamma);

/*! @brief Execute an activation forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param activDesc      Descriptor for activation layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenActivationForward(miopenHandle_t handle,
                                                     const miopenActivationDescriptor_t activDesc,
                                                     const void* alpha,
                                                     const miopenTensorDescriptor_t xDesc,
                                                     const void* x,
                                                     const void* beta,
                                                     const miopenTensorDescriptor_t yDesc,
                                                     void* y);

/*! @brief Execute a activation backwards layer
 *
 * @param handle         MIOpen handle (input)
 * @param activDesc      Descriptor for activation layer (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for input data tensor y (input)
 * @param y              Data tensor y (input)
 * @param dyDesc         Tensor descriptor for input data tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for data output tensor dx (input)
 * @param dx             Output data delta tensor dx (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenActivationBackward(miopenHandle_t handle,
                                                      const miopenActivationDescriptor_t activDesc,
                                                      const void* alpha,
                                                      const miopenTensorDescriptor_t yDesc,
                                                      const void* y,
                                                      const miopenTensorDescriptor_t dyDesc,
                                                      const void* dy,
                                                      const miopenTensorDescriptor_t xDesc,
                                                      const void* x,
                                                      const void* beta,
                                                      const miopenTensorDescriptor_t dxDesc,
                                                      void* dx);

/*! @brief Destroys the activation descriptor object
 *
 * @param activDesc   Activation tensor descriptor type (input)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenDestroyActivationDescriptor(miopenActivationDescriptor_t activDesc);

/** @} */
// CLOSEOUT ACTIVATION DOXYGEN GROUP

#ifdef MIOPEN_BETA_API
/** @addtogroup activation
 *
 *  @{
 */

/*! @brief Execute a GLU forward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param inputDesc                Tensor descriptor for input tensor (input)
 * @param input                    Input tensor (input)
 * @param outputDesc               Tensor descriptor for output tensor (input)
 * @param output                   Output tensor (output)
 * @param dim                      Dimension to split the input (input)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGLUForward(miopenHandle_t handle,
                                              const miopenTensorDescriptor_t inputDesc,
                                              const void* input,
                                              const miopenTensorDescriptor_t outputDesc,
                                              void* output,
                                              const uint32_t dim);

/*! @brief Execute a GLU backward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param inputDesc                Tensor descriptor for input tensor (input)
 * @param input                    Input tensor (input)
 * @param outputGradDesc           Tensor descriptor for delta output tensor (input)
 * @param outputGrad               Delta output tensor (input)
 * @param inputGradDesc            Tensor descriptor for delta input tensor (input)
 * @param inputGrad                Delta input tensor (output)
 * @param dim                      Dimension to split the input (input)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGLUBackward(miopenHandle_t handle,
                                               const miopenTensorDescriptor_t inputDesc,
                                               const void* input,
                                               const miopenTensorDescriptor_t outputGradDesc,
                                               const void* outputGrad,
                                               const miopenTensorDescriptor_t inputGradDesc,
                                               void* inputGrad,
                                               const uint32_t dim);

/** @} */
// CLOSEOUT ACTIVATION DOXYGEN GROUP
#endif // MIOPEN_BETA_API

// Softmax APIs
/** @addtogroup softmax
 *
 *  @{
 */
/*! @brief Execute a softmax forward layer
 *
 * This API only implements the SOFTMAX_MODE_CHANNEL in SOFTMAX_ACCURATE path.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftmaxForward(miopenHandle_t handle,
                                                  const void* alpha,
                                                  const miopenTensorDescriptor_t xDesc,
                                                  const void* x,
                                                  const void* beta,
                                                  const miopenTensorDescriptor_t yDesc,
                                                  void* y);

/*! @brief Execute a softmax backwards layer
 *
 * This API only implements the SOFTMAX_MODE_CHANNEL in SOFTMAX_ACCURATE path.
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for input data tensor y (input)
 * @param y              Data tensor y (input)
 * @param dyDesc         Tensor descriptor for input data tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for data output tensor dx (input)
 * @param dx             Output data delta tensor dx (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftmaxBackward(miopenHandle_t handle,
                                                   const void* alpha,
                                                   const miopenTensorDescriptor_t yDesc,
                                                   const void* y,
                                                   const miopenTensorDescriptor_t dyDesc,
                                                   const void* dy,
                                                   const void* beta,
                                                   const miopenTensorDescriptor_t dxDesc,
                                                   void* dx);

/*! @brief Execute a softmax forward layer with expanded modes and algorithms
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param algorithm      Softmax implementation algorithm (input)
 * @param mode           Softmax mode (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftmaxForward_V2(miopenHandle_t handle,
                                                     const void* alpha,
                                                     const miopenTensorDescriptor_t xDesc,
                                                     const void* x,
                                                     const void* beta,
                                                     const miopenTensorDescriptor_t yDesc,
                                                     void* y,
                                                     miopenSoftmaxAlgorithm_t algorithm,
                                                     miopenSoftmaxMode_t mode);

/*! @brief Execute a softmax backwards layer with expanded modes and algorithms
 *
 * @param handle         MIOpen handle (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param yDesc          Tensor descriptor for input data tensor y (input)
 * @param y              Data tensor y (input)
 * @param dyDesc         Tensor descriptor for input data tensor dy (input)
 * @param dy             Data delta tensor dy (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param dxDesc         Tensor descriptor for data output tensor dx (input)
 * @param dx             Output data delta tensor dx (output)
 * @param algorithm      Softmax implementation algorithm (input)
 * @param mode           Softmax mode (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftmaxBackward_V2(miopenHandle_t handle,
                                                      const void* alpha,
                                                      const miopenTensorDescriptor_t yDesc,
                                                      const void* y,
                                                      const miopenTensorDescriptor_t dyDesc,
                                                      const void* dy,
                                                      const void* beta,
                                                      const miopenTensorDescriptor_t dxDesc,
                                                      void* dx,
                                                      miopenSoftmaxAlgorithm_t algorithm,
                                                      miopenSoftmaxMode_t mode);

/** @} */
// CLOSEOUT SOFTMAX DOXYGEN GROUP

/*! @ingroup FUSION
 * @brief MIOpen fusion interface
 */
MIOPEN_DECLARE_OBJECT(miopenFusionPlanDescriptor);
MIOPEN_DECLARE_OBJECT(miopenOperatorDescriptor);
MIOPEN_DECLARE_OBJECT(miopenOperatorArgs);

/** @addtogroup FUSION
 *
 *  @{
 */

/*! @enum miopenFusionDirection_t
 * @brief Kernel fusion direction in the network
 */
typedef enum
{
    miopenVerticalFusion   = 0, /*!< fuses layers vertically, current the only supported mode */
    miopenHorizontalFusion = 1, /*!< fuses layers horizontally, this is unimplemented */
} miopenFusionDirection_t;

/*! @brief Creates the kenrel fusion plan descriptor object
 *
 * @param fusePlanDesc  Pointer to a fusion plan (output)
 * @param fuseDirection Horizontal or Vertical fusion (input)
 * @param inputDesc     Descriptor to tensor for the input (input)
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateFusionPlan(miopenFusionPlanDescriptor_t* fusePlanDesc,
                                                    const miopenFusionDirection_t fuseDirection,
                                                    const miopenTensorDescriptor_t inputDesc);

/*! @brief Destroy the fusion plan descriptor object
 *
 * @param fusePlanDesc  A fusion plan descriptor type
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyFusionPlan(miopenFusionPlanDescriptor_t fusePlanDesc);

/*! @brief Compiles the fusion plan
 *
 * @param handle           MIOpen handle (input)
 * @param fusePlanDesc A fusion plan descriptor (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCompileFusionPlan(miopenHandle_t handle,
                                                     miopenFusionPlanDescriptor_t fusePlanDesc);

/*!
 * @brief Allows access to the operators in a fusion plan
 * @details This api call does bounds checking on the supplied op_idx and would
 *          return miopenStatusError if the index is out of bounds
 *
 * @param fusePlanDesc A fusion plan descriptor (input)
 * @param op_idx Index of the required operator in the fusion plan, in the order of insertion
 * @param op returned pointer to the operator
 * @return miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenFusionPlanGetOp(miopenFusionPlanDescriptor_t fusePlanDesc,
                                                   const int op_idx,
                                                   miopenFusionOpDescriptor_t* op);

/*! @brief Query the workspace size required for the fusion plan
 * @param handle         MIOpen handle (input)
 * @param fusePlanDesc   A fusion plan descriptor (input)
 * @param workSpaceSize  Pointer to memory to return size in bytes (output)
 * @param algo           Algorithm selected (inputs)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFusionPlanGetWorkSpaceSize(miopenHandle_t handle,
                                 miopenFusionPlanDescriptor_t fusePlanDesc,
                                 size_t* workSpaceSize,
                                 miopenConvFwdAlgorithm_t algo);

/*!
 * @brief Returns the supported algorithms for the convolution operator in the Fusion Plan
 *
 * @details A Convolution operator in a fusion plan may be implemented by different algorithms
 * representing different tradeoffs of memory and performance. The returned list of algorithms
 * is sorted in decreasing order of priority. Therefore, if the user does not request an
 * algorithm to be set using the miopenFusionPlanConvolutionSetAlgo call, the first algorithm
 * in the list would be used to execute the convolution in the fusion plan. Moreover this call
 * must be immediately preceded by the miopenCreateOpConvForward call for the op in question.
 *
 * @param fusePlanDesc A fusion plan descriptor (input)
 * @param requestAlgoCount Number of algorithms to return (input)
 * @param returnedAlgoCount The actual number of returned algorithms; always be less than
 * equal to requestAlgoCount (output)
 * @param returnedAlgos Pointer to the list of supported algorithms
 * @return miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFusionPlanConvolutionGetAlgo(miopenFusionPlanDescriptor_t fusePlanDesc,
                                   const int requestAlgoCount,
                                   int* returnedAlgoCount,
                                   miopenConvFwdAlgorithm_t* returnedAlgos);

/*! @brief Requests the fusion runtime to choose a particular algorithm for the added convolution
 * operation
 *
 * @details Please see the description for miopenFusionPlanConvolutionGetAlgo
 *
 * @param fusePlanDesc A fusion plan descriptor (input)
 * @param algo Requested algorithm for the convolution operator (input)
 * @return miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenFusionPlanConvolutionSetAlgo(
    miopenFusionPlanDescriptor_t fusePlanDesc, miopenConvFwdAlgorithm_t algo);

/*! @brief Creates forward convolution operator.
 *
 * @param fusePlanDesc   A fusion plan descriptor (input)
 * @param convOp         Pointer to an operator type (output)
 * @param convDesc       Convolution layer descriptor (input)
 * @param wDesc          Descriptor for the weights tensor (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateOpConvForward(miopenFusionPlanDescriptor_t fusePlanDesc,
                                                       miopenFusionOpDescriptor_t* convOp,
                                                       miopenConvolutionDescriptor_t convDesc,
                                                       const miopenTensorDescriptor_t wDesc);

//---

// Activation forward create ops ---
/*! @brief Creates a forward activation operator.
 *
 * @param fusePlanDesc    A fusion plan descriptor (input)
 * @param activFwdOp         Pointer to an operator type (output)
 * @param mode            Activation version (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateOpActivationForward(miopenFusionPlanDescriptor_t fusePlanDesc,
                                miopenFusionOpDescriptor_t* activFwdOp,
                                miopenActivationMode_t mode);

// Activation backward create ops ---
/*! @brief Creates a backward activation operator.
 *
 * @param fusePlanDesc    A fusion plan descriptor (input)
 * @param activBwdOp         Pointer to an operator type (output)
 * @param mode            Activation version (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateOpActivationBackward(miopenFusionPlanDescriptor_t fusePlanDesc,
                                 miopenFusionOpDescriptor_t* activBwdOp,
                                 miopenActivationMode_t mode);

// Bias create ops ---
/*! @brief Creates a forward bias operator.
 *
 * @param fusePlanDesc   A fusion plan descriptor (input)
 * @param biasOp         Pointer to an operator type (output)
 * @param bDesc          bias tensor descriptor (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateOpBiasForward(miopenFusionPlanDescriptor_t fusePlanDesc,
                                                       miopenFusionOpDescriptor_t* biasOp,
                                                       const miopenTensorDescriptor_t bDesc);

// Batch normalization create ops ---
/*! @brief Creates a forward inference batch normalization operator.
 *
 * @param fusePlanDesc           A fusion plan descriptor (input)
 * @param bnOp                   Pointer to an operator type (output)
 * @param bn_mode                Batch normalization layer mode (input)
 * @param bnScaleBiasMeanVarDesc Gamma, beta, mean, variance tensor descriptor (input)
 * @return                       miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateOpBatchNormInference(miopenFusionPlanDescriptor_t fusePlanDesc,
                                 miopenFusionOpDescriptor_t* bnOp,
                                 const miopenBatchNormMode_t bn_mode,
                                 const miopenTensorDescriptor_t bnScaleBiasMeanVarDesc);

/*! @brief Creates a forward training batch normalization operator.
 *
 * @param fusePlanDesc           A fusion plan descriptor (input)
 * @param bnFwdOp                   Pointer to an operator type (output)
 * @param bn_mode                Batch normalization layer mode (input)
 * @param runningMeanVariance    Toggles whether or not to save population statistics for inference;
 * batch statistic are required (input)
 * @return                       miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateOpBatchNormForward(miopenFusionPlanDescriptor_t fusePlanDesc,
                               miopenFusionOpDescriptor_t* bnFwdOp,
                               const miopenBatchNormMode_t bn_mode,
                               bool runningMeanVariance);

/*! @brief Creates a back propagation batch normalization operator.
 *
 * @param fusePlanDesc           A fusion plan descriptor (input)
 * @param bnBwdOp                   Pointer to an operator type (output)
 * @param bn_mode                Batch normalization layer mode (input)
 * @return                       miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateOpBatchNormBackward(miopenFusionPlanDescriptor_t fusePlanDesc,
                                miopenFusionOpDescriptor_t* bnBwdOp,
                                const miopenBatchNormMode_t bn_mode);

//---
/*! @brief Creates an operator argument object
 *
 * @param args        Pointer to an operator argument type (output)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateOperatorArgs(miopenOperatorArgs_t* args);

/*! @brief Destroys an operator argument object
 *
 * @param args        An operator argument type (output)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyOperatorArgs(miopenOperatorArgs_t args);

// Convolution set arguments ---
/*! @brief Sets the arguments for forward convolution op
 *
 * @param args    An arguments object type (output)
 * @param convOp  Forward convolution operator (input)
 * @param alpha   Floating point scaling factor, allocated on the host (input)
 * @param beta    Floating point shift factor, allocated on the host (input)
 * @param w       Pointer to tensor memory  (input)
 * @return        miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetOpArgsConvForward(miopenOperatorArgs_t args,
                                                        const miopenFusionOpDescriptor_t convOp,
                                                        const void* alpha,
                                                        const void* beta,
                                                        const void* w);
// Activation set arguments ---
/*! @brief Sets the arguments for forward activation op
 *
 * @param args    An arguments object type (output)
 * @param activFwdOp   Activation backwards operator (input)
 * @param alpha   Floating point scaling factor, allocated on the host (input)
 * @param beta    Floating point shift factor, allocated on the host (input)
 * @param activAlpha  Double precision activation parameter which depends on activation mode (input)
 * @param activBeta   Double precision activation parameter which depends on activation mode (input)
 * @param activGamma  Double precision activation parameter which depends on activation mode (input)
 * @return        miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetOpArgsActivForward(miopenOperatorArgs_t args,
                            const miopenFusionOpDescriptor_t activFwdOp,
                            const void* alpha,
                            const void* beta,
                            double activAlpha,
                            double activBeta,
                            double activGamma);

/*! @brief Sets the arguments for backward activation op
 *
 * @param args    An arguments object type (output)
 * @param activBwdOp   Activation backwards operator (input)
 * @param alpha   Floating point scaling factor, allocated on the host (input)
 * @param beta    Floating point shift factor, allocated on the host (input)
 * @param y        Data tensor y, output of activations in the forward direction (input)
 * @param reserved    Data tensor reserved memory space; currently should be nullptr (input)
 * @param activAlpha  Double precision activation parameter which depends on activation mode (input)
 * @param activBeta   Double precision activation parameter which depends on activation mode (input)
 * @param activGamma  Double precision activation parameter which depends on activation mode (input)
 * @return        miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetOpArgsActivBackward(miopenOperatorArgs_t args,
                             const miopenFusionOpDescriptor_t activBwdOp,
                             const void* alpha,
                             const void* beta,
                             const void* y,
                             const void* reserved,
                             double activAlpha,
                             double activBeta,
                             double activGamma);

// Batch Normalization set arguments ---
/*! @brief Sets the arguments for inference batch normalization op
 *
 * @param args               An arguments object type (output)
 * @param bnOp               Batch normalization inference operator (input)
 * @param alpha              Floating point scaling factor, allocated on the host (input)
 * @param beta               Floating point shift factor, allocated on the host (input)
 * @param bnScale            Pointer to the gamma tensor memory  (input)
 * @param bnBias             Pointer to the beta tensor memory  (input)
 * @param estimatedMean      Pointer to population mean memory  (input)
 * @param estimatedVariance  Pointer to population variance memory  (input)
 * @param epsilon            Scalar value for numerical stability (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetOpArgsBatchNormInference(miopenOperatorArgs_t args,
                                  const miopenFusionOpDescriptor_t bnOp,
                                  const void* alpha,
                                  const void* beta,
                                  const void* bnScale,
                                  const void* bnBias,
                                  const void* estimatedMean,
                                  const void* estimatedVariance,
                                  double epsilon);

/*! @brief Sets the arguments for forward batch normalization op
 *
 * @param args               An arguments object type (output)
 * @param bnOp               Batch normalization forward operator (input)
 * @param alpha              Floating point scaling factor, allocated on the host (input)
 * @param beta               Floating point shift factor, allocated on the host (input)
 * @param bnScale            Pointer to the gamma tensor memory  (input)
 * @param bnBias             Pointer to the beta tensor memory  (input)
 * @param savedMean          Pointer to batch mean memory  (input)
 * @param savedInvVariance   Pointer to batch inverse variance memory  (input)
 * @param runningMean        Pointer to population mean memory  (input)
 * @param runningVariance    Pointer to population variance memory  (input)
 * @param expAvgFactor       Scalar value for control of population statistics (input)
 * @param epsilon            Scalar value for numerical stability (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetOpArgsBatchNormForward(miopenOperatorArgs_t args,
                                                             const miopenFusionOpDescriptor_t bnOp,
                                                             const void* alpha,
                                                             const void* beta,
                                                             const void* bnScale,
                                                             const void* bnBias,
                                                             void* savedMean,
                                                             void* savedInvVariance,
                                                             void* runningMean,
                                                             void* runningVariance,
                                                             double expAvgFactor,
                                                             double epsilon);

/*! @brief Sets the arguments for backward batch normalization op
 *
 * @param args               An arguments object type (output)
 * @param bnOp               Batch normalization forward operator (input)
 * @param alpha              Floating point scaling factor, allocated on the host (input)
 * @param beta               Floating point shift factor, allocated on the host (input)
 * @param x                  Pointer to the forward input tensor memory  (input)
 * @param bnScale            Pointer to the gamma tensor memory  (input)
 * @param bnBias             Pointer to the beta tensor memory  (input)
 * @param resultBnScaleDiff  Pointer to the gamma gradient tensor memory  (output)
 * @param resultBnBiasDiff   Pointer to the beta gradient tensor memory  (output)
 * @param savedMean          Pointer to batch mean memory  (input)
 * @param savedInvVariance   Pointer to batch inverse variance memory  (input)
 * @return                   miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetOpArgsBatchNormBackward(miopenOperatorArgs_t args,
                                                              const miopenFusionOpDescriptor_t bnOp,
                                                              const void* alpha,
                                                              const void* beta,
                                                              const void* x,
                                                              const void* bnScale,
                                                              const void* bnBias,
                                                              void* resultBnScaleDiff,
                                                              void* resultBnBiasDiff,
                                                              const void* savedMean,
                                                              const void* savedInvVariance);

// Bias forward set arguments ---
/*! @brief Sets the arguments for forward bias op
 *
 * @param args           An arguments object type (output)
 * @param biasOp         Forward bias operator (input)
 * @param alpha          Floating point scaling factor, allocated on the host (input)
 * @param beta           Floating point shift factor, allocated on the host (input)
 * @param bias           Pointer to the forward bias input tensor memory  (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetOpArgsBiasForward(miopenOperatorArgs_t args,
                                                        const miopenFusionOpDescriptor_t biasOp,
                                                        const void* alpha,
                                                        const void* beta,
                                                        const void* bias);

/*! @brief Executes the fusion plan. Only compatible with NHWC/NDHWC tensor layouts.
 *
 *  @deprecated This function is deprecated and may be removed in a future release.
 *             Use miopenExecuteFusionPlan_v2 instead.
 *
 * @param handle           MIOpen handle (input)
 * @param fusePlanDesc     fused plan descriptor (input)
 * @param inputDesc        Descriptor of the input tensor (input)
 * @param input            Source data tensor  (input)
 * @param outputDesc       Descriptor of the output tensor (input)
 * @param output           Destination data tensor  (output)
 * @param args             An argument object of the fused kernel (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenExecuteFusionPlan(const miopenHandle_t handle,
                        const miopenFusionPlanDescriptor_t fusePlanDesc,
                        const miopenTensorDescriptor_t inputDesc,
                        const void* input,
                        const miopenTensorDescriptor_t outputDesc,
                        void* output,
                        miopenOperatorArgs_t args);

/*! @brief Executes the fusion plan with a workspace buffer for layout transformations.
 *
 *
 * @param handle           MIOpen handle (input)
 * @param fusePlanDesc     fused plan descriptor (input)
 * @param inputDesc        Descriptor of the input tensor (input)
 * @param input            Source data tensor  (input)
 * @param outputDesc       Descriptor of the output tensor (input)
 * @param output           Destination data tensor  (output)
 * @param args             An argument object of the fused kernel (input)
 * @param workspace        A pointer to an intermediate workspace (input)
 * @param workspaceSize Size of the memory in bytes pointed to by workSpace above (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenExecuteFusionPlan_v2(const miopenHandle_t handle,
                           const miopenFusionPlanDescriptor_t fusePlanDesc,
                           const miopenTensorDescriptor_t inputDesc,
                           const void* input,
                           const miopenTensorDescriptor_t outputDesc,
                           void* output,
                           miopenOperatorArgs_t args,
                           void* workspace,
                           size_t workspaceSize);

/*! @brief Prepares and executes the Convlution+Bias+Activation Fusion.
 *
 *
 * @param handle               MIOpen handle (input)
 * @param alpha1               floating point scaling factor, allocated on the host (input)
 * @param xDesc                Tensor descriptor for input data tensor x (input)
 * @param x                    Data tensor x (input)
 * @param wDesc                Tensor descriptor for weight tensor w (input)
 * @param w                    Weights tensor w (input)
 * @param convDesc             Convolution layer descriptor (input)
 * @param algo                 Algorithm selected (inputs)
 * @param workspace            Pointer to workspace required (input)
 * @param workspaceSizeInBytes Size of the memory in bytes pointed to by workSpace above
 * @param alpha2               floating point scaling factor, allocated on the host (input)
 * @param zDesc                Tensor descriptor for tensor z (input)
 * @param z                    Data tensor z (input)
 * @param biasDesc             Tensor descriptor for input data tensor x (input)
 * @param bias                 Data tensor bias (input)
 * @param activationDesc       Activation descriptor that specifies the activation mode
 * @param yDesc                Tensor descriptor for output data tensor y (input)
 * @param y                    Output data tensor
 */

MIOPEN_EXPORT miopenStatus_t
miopenConvolutionBiasActivationForward(miopenHandle_t handle,
                                       const void* alpha1,
                                       const miopenTensorDescriptor_t xDesc,
                                       const void* x,
                                       const miopenTensorDescriptor_t wDesc,
                                       const void* w,
                                       const miopenConvolutionDescriptor_t convDesc,
                                       miopenConvFwdAlgorithm_t algo,
                                       void* workspace,
                                       size_t workspaceSizeInBytes,
                                       const void* alpha2,
                                       const miopenTensorDescriptor_t zDesc,
                                       const void* z,
                                       const miopenTensorDescriptor_t biasDesc,
                                       const void* bias,
                                       const miopenActivationDescriptor_t activationDesc,
                                       const miopenTensorDescriptor_t yDesc,
                                       void* y);
/** @} */
// CLOSEOUT FUSION DOXYGEN GROUP

/** @addtogroup RNN
 *
 *  @{
 */

/*!  @enum miopenRNNMode_t
 * RNN mode selection for rnn layer preference
 */
typedef enum
{
    miopenRNNRELU = 0, /*!< RNN with ReLU activation */
    miopenRNNTANH = 1, /*!< RNN with tanh activation */
    miopenLSTM    = 2, /*!< LSTM */
    miopenGRU     = 3, /*!< GRU */
} miopenRNNMode_t;

/*! @enum miopenRNNInputMode_t
 * Recurrent Neural Network layer initial input mode
 */
typedef enum
{
    miopenRNNlinear = 0, /*!< Matrix multiplication at the input of the first layer */
    miopenRNNskip   = 1, /*!< No operation is performed at the input of the first layer. */
} miopenRNNInputMode_t;

/*! @enum miopenRNNAlgo_t
 * Recurrent Neural Network algorithm mode
 */
typedef enum
{
    miopenRNNdefault = 0,        /*!< Use dedicated gate-operation kernel for LSTM and fundamental
                                    algorithm for vanilla RNN & GRU */
    miopenRNNfundamental = 1,    /*!< Deprecated, low performance. Function by basic tensor
                                    operations, supported for vanilla RNN, LSTM, GRU */
    miopenRNNroundedDynamic = 2, /*!< The algorithm rounds some RNN parameters upwards
                                    to utilize the most optimal GEMM kernel in the computation.*/
} miopenRNNAlgo_t;

/*! @enum miopenRNNDirectionMode_t
 * Recurrent Neural Network bi-directional behavior
 */
typedef enum
{
    miopenRNNunidirection = 0, /*!< Forward in time only. */
    miopenRNNbidirection  = 1, /*!< Forward and backwards in time. */
} miopenRNNDirectionMode_t;

/*! @enum miopenRNNBiasMode_t
 * Recurrent Neural Network add on bias
 */
typedef enum
{
    miopenRNNNoBias   = 0, /*!< No Biases will be applied to GEMM operations */
    miopenRNNwithBias = 1, /*!< Biases will be applied to GEMM operations */
} miopenRNNBiasMode_t;

/*! @enum miopenRNNGEMMalgoMode_t
 * Recurrent Neural Network add on bias
 */
typedef enum
{
    miopenRNNAlgoGEMM = 0,
} miopenRNNGEMMalgoMode_t;

/*! @enum miopenRNNPaddingMode_t
 * Recurrent Neural Network input/output data padding mode
 */
typedef enum
{
    miopenRNNIONotPadded   = 0, /*!< Not padded data at RNN input/output */
    miopenRNNIOWithPadding = 1, /*!< Padded data at RNN input/output */
} miopenRNNPaddingMode_t;

/*! @enum miopenRNNFWDMode_t
 * Recurrent Neural Network Training/Inference mode
 */
typedef enum
{
    miopenRNNTraining  = 0, /*!< FWD, BWD, WRW */
    miopenRNNInference = 1, /*!< Only FWD-inference no back-propagation */
} miopenRNNFWDMode_t;

/*! @enum miopenRNNBaseLayout_t
 * Data layouts for RNN operations
 */
typedef enum
{
    miopenRNNDataUnknownLayout     = 0,
    miopenRNNDataSeqMajorNotPadded = 1,
    miopenRNNDataSeqMajorPadded    = 2,
    miopenRNNDataBatchMajorPadded  = 3,
} miopenRNNBaseLayout_t;

/*! @brief Create a RNN layer Descriptor
 *
 * API for creating an uninitialized RNN layer descriptor.
 * @param rnnDesc    Pointer to a tensor descriptor type
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateRNNDescriptor(miopenRNNDescriptor_t* rnnDesc);

/*! @brief Retrieves a RNN layer descriptor's details
 *
 * @param rnnDesc    RNN layer descriptor (input)
 * @param rnnMode    RNN mode (output)
 * @param algoMode   RNN algorithm mode (output)
 * @param inputMode  RNN data input mode (output)
 * @param dirMode    Uni or bi direction mode (output)
 * @param biasMode   Bias used (output)
 * @param hiddenSize Size of hidden state (output)
 * @param layer      Number of stacked layers (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
                                                    miopenRNNMode_t* rnnMode,
                                                    miopenRNNAlgo_t* algoMode,
                                                    miopenRNNInputMode_t* inputMode,
                                                    miopenRNNDirectionMode_t* dirMode,
                                                    miopenRNNBiasMode_t* biasMode,
                                                    int* hiddenSize,
                                                    int* layer);

/*! @brief Retrieves a RNN layer descriptor's details version 2. This version enables retrieving
 * information of the dropout descriptor of the rnn descriptor.
 *
 * @param rnnDesc     RNN layer descriptor (input)
 * @param hiddenSize  Size of hidden state (output)
 * @param layer       Number of stacked layers (output)
 * @param dropoutDesc Pre-configured dropout descriptor for dropout layer in between RNN layers
 * (output)
 * @param inputMode   RNN data input mode (output)
 * @param dirMode     Uni or bi direction mode (output)
 * @param rnnMode     RNN mode (output)
 * @param biasMode    Bias used (output)
 * @param algoMode    RNN algorithm mode (output)
 * @param dataType    Data type of RNN (output)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNDescriptor_V2(miopenRNNDescriptor_t rnnDesc,
                                                       int* hiddenSize,
                                                       int* layer,
                                                       miopenDropoutDescriptor_t* dropoutDesc,
                                                       miopenRNNInputMode_t* inputMode,
                                                       miopenRNNDirectionMode_t* dirMode,
                                                       miopenRNNMode_t* rnnMode,
                                                       miopenRNNBiasMode_t* biasMode,
                                                       miopenRNNAlgo_t* algoMode,
                                                       miopenDataType_t* dataType);

/*! @brief Destroys the tensor descriptor object
 *
 * @param rnnDesc RNN tensor descriptor type (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyRNNDescriptor(miopenRNNDescriptor_t rnnDesc);

/*! @brief Set the details of the RNN descriptor
 *
 * Interface for setting the values of the RNN descriptor object. This function requires specific
 * algorithm selection.
 * @param rnnDesc      RNN layer descriptor type (input)
 * @param hsize        Hidden layer size (input)
 * @param nlayers      Number of layers (input)
 * @param inMode       RNN first layer input mode (input)
 * @param direction    RNN direction (input)
 * @param rnnMode      RNN model type (input)
 * @param biasMode     RNN bias included (input)
 * @param algo         RNN algorithm selected (input)
 * @param dataType     MIOpen datatype (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetRNNDescriptor(miopenRNNDescriptor_t rnnDesc,
                                                    const int hsize,
                                                    const int nlayers,
                                                    miopenRNNInputMode_t inMode,
                                                    miopenRNNDirectionMode_t direction,
                                                    miopenRNNMode_t rnnMode,
                                                    miopenRNNBiasMode_t biasMode,
                                                    miopenRNNAlgo_t algo,
                                                    miopenDataType_t dataType);

/*! @brief Set the details of the RNN descriptor version 2. This version enables the use of dropout
 * in rnn.
 *
 * Interface for setting the values of the RNN descriptor object. This function requires specific
 * algorithm selection.
 * @param rnnDesc      RNN layer descriptor type (input/output)
 * @param hsize        Hidden layer size (input)
 * @param nlayers      Number of layers (input)
 * @param dropoutDesc  Pre-initialized dropout descriptor for dropout layer in between RNN layers
 * (input)
 * @param inMode       RNN first layer input mode (input)
 * @param direction    RNN direction (input)
 * @param rnnMode      RNN model type (input)
 * @param biasMode     RNN bias included (input)
 * @param algo         RNN algorithm selected (input)
 * @param dataType     MIOpen datatype (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetRNNDescriptor_V2(miopenRNNDescriptor_t rnnDesc,
                                                       const int hsize,
                                                       const int nlayers,
                                                       miopenDropoutDescriptor_t dropoutDesc,
                                                       miopenRNNInputMode_t inMode,
                                                       miopenRNNDirectionMode_t direction,
                                                       miopenRNNMode_t rnnMode,
                                                       miopenRNNBiasMode_t biasMode,
                                                       miopenRNNAlgo_t algo,
                                                       miopenDataType_t dataType);

/*! @brief Set shape of RNN seqData tensor
 *
 * Interface for setting tensor shape to be used as RNN input data
 *
 * @param seqTensorDesc     Tensor descriptor (input/output)
 * @param dataType          MIOpen datatype (input)
 * @param layout            One of the main supported layouts for RNN data(input)
 * @param maxSequenceLen      Sequence length limit within this SeqTensor(input)
 * @param batchSize         Number of sequences within this SeqTensor (input)
 * @param vectorSize        Vector size (input)
 * @param sequenceLenArray  Array containing the length of each sequence in the SeqTensor(input)
 * @param paddingMarker     Not used, should be NULL (input)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetRNNDataSeqTensorDescriptor(miopenSeqTensorDescriptor_t seqTensorDesc,
                                    miopenDataType_t dataType,
                                    miopenRNNBaseLayout_t layout,
                                    int maxSequenceLen,
                                    int batchSize,
                                    int vectorSize,
                                    const int* sequenceLenArray,
                                    void* paddingMarker);

/*! @brief Get shape of RNN seqData tensor
 *
 * Interface for setting tensor shape to be used as RNN input data
 *
 * @param seqTensorDesc             Tensor descriptor (input)
 * @param dataType                  MIOpen datatype (output)
 * @param layout                    One of the main supported layouts for RNN data(output)
 * @param maxSequenceLen              Sequence length limit within this SeqTensor(output)
 * @param batchSize                 Number of sequences within this SeqTensor (output)
 * @param vectorSize                Vector size (output)
 * @param sequenceLenArrayLimit  Limit for number of elements that can be returned to user
 * by sequenceLenArray (input)
 * @param sequenceLenArray          Array containing the length of each sequence in the
 * SeqTensor. This is allowed to be a NULL pointer if sequenceLenArrayLimit is 0 (output)
 * @param paddingMarker             Not used, should be NULL (input)
 * @return                          miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t
miopenGetRNNDataSeqTensorDescriptor(miopenSeqTensorDescriptor_t seqTensorDesc,
                                    miopenDataType_t* dataType,
                                    miopenRNNBaseLayout_t* layout,
                                    int* maxSequenceLen,
                                    int* batchSize,
                                    int* vectorSize,
                                    int sequenceLenArrayLimit,
                                    int* sequenceLenArray,
                                    void* paddingMarker);

/*! @brief Query the amount of memory required to execute the RNN layer
 *
 * This function calculates the amount of memory required to run the RNN layer given an RNN
 * descriptor and a tensor descriptor.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param sequenceLen     Number of iteration unrolls (input)
 * @param xDesc           An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param numBytes        Number of bytes required for RNN layer execution (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNWorkspaceSize(miopenHandle_t handle,
                                                       const miopenRNNDescriptor_t rnnDesc,
                                                       const int sequenceLen,
                                                       const miopenTensorDescriptor_t* xDesc,
                                                       size_t* numBytes);

/*! @brief Query the amount of memory required for RNN training
 *
 * This function calculates the amount of memory required to train the RNN layer given an
 * RNN descriptor and a tensor descriptor.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param sequenceLen     Number of iteration unrolls (input)
 * @param xDesc           An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param numBytes        Number of bytes required for RNN layer execution (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNTrainingReserveSize(miopenHandle_t handle,
                                                             miopenRNNDescriptor_t rnnDesc,
                                                             const int sequenceLen,
                                                             const miopenTensorDescriptor_t* xDesc,
                                                             size_t* numBytes);

/*! @brief Query the amount of additional memory required for this RNN layer execution.
 *
 * This function calculates the size of extra buffers, depending on the layer configuration, which
 * is determined by: RNN descriptor, isInference, and data descriptor. If isInference is True,
 * reserve_space_size is always zero, because the reserve_space buffer is not used in Inference
 * computation.
 *
 * @param handle           MIOpen handle (input)
 * @param rnnDesc          RNN layer descriptor type (input)
 * @param xDesc            Sequence data tensor descriptor (input)
 * @param fwdMode          Specifies in which mode the buffers will be used.
 * @param workSpaceSize    Minimum WorkSpace buffer size required for RNN layer execution (output)
 * @param reserveSpaceSize Minimum ReserveSpaceSize buffer size required for RNN layer execution
 * (output)
 * @return                 miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNTempSpaceSizes(miopenHandle_t handle,
                                                        miopenRNNDescriptor_t rnnDesc,
                                                        miopenSeqTensorDescriptor_t xDesc,
                                                        miopenRNNFWDMode_t fwdMode,
                                                        size_t* workSpaceSize,
                                                        size_t* reserveSpaceSize);

/*! @brief Query the amount of parameter memory required for RNN training
 *
 * This function calculates the amount of parameter memory required to train the RNN layer given an
 * RNN descriptor and a tensor descriptor.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param xDesc           A tensor descriptor (input)
 * @param numBytes        Number of bytes required for RNN layer execution (output)
 * @param dtype           MIOpen data type enum (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNParamsSize(miopenHandle_t handle,
                                                    miopenRNNDescriptor_t rnnDesc,
                                                    miopenTensorDescriptor_t xDesc,
                                                    size_t* numBytes,
                                                    miopenDataType_t dtype);

/*! @brief Obtain a weight tensor descriptor for RNNs
 *
 * This function populates a weight descriptor that describes the memory layout of the
 * weight matrix.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         Fully populated RNN layer descriptor type (input)
 * @param xDesc           A previously populated tensor descriptor (input)
 * @param wDesc           A previously allocated tensor descriptor (output)
 * @param dtype           MIOpen data type enum (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNParamsDescriptor(miopenHandle_t handle,
                                                          miopenRNNDescriptor_t rnnDesc,
                                                          miopenTensorDescriptor_t xDesc,
                                                          miopenTensorDescriptor_t wDesc,
                                                          miopenDataType_t dtype);

/*! @brief Obtain the size in bytes of the RNN input tensor
 *
 * This function determines the size in bytes of the allocation needed for the input data
 * tensor for an RNN layer. The number of bytes is derived from the array of
 * tensor descriptors.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         Fully populated RNN layer descriptor (input)
 * @param seqLen          Number of iteration unrolls (input)
 * @param xDesc           An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param numBytes        Number of bytes required for input tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNInputTensorSize(miopenHandle_t handle,
                                                         miopenRNNDescriptor_t rnnDesc,
                                                         const int seqLen,
                                                         miopenTensorDescriptor_t* xDesc,
                                                         size_t* numBytes);

/*! @brief Obtain the size in bytes of the RNN hidden tensor
 *
 * This function determines the size in bytes of the allocation needed for the
 * hidden tensor over all layers
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         Fully populated RNN layer descriptor type (input)
 * @param seqLen          Number of iteration unrolls (input)
 * @param xDesc           An array of previously populated tensor descriptors (input)
 * @param numBytes        Number of bytes required for input tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNHiddenTensorSize(miopenHandle_t handle,
                                                          miopenRNNDescriptor_t rnnDesc,
                                                          const int seqLen,
                                                          miopenTensorDescriptor_t* xDesc,
                                                          size_t* numBytes);

/*! @brief Gets the number of bytes of a parameter matrix
 *
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, paramID == 0 retrieves the
 * weight matrix associated with the in input GEMM, while paramID == 1 retrieves
 * the weight matrix associated with the hidden state GEMM.
 *
 * For miopenLSTM paramID 0 to 3 refer to the weight matrices associated
 * with the input GEMM, 4-7 are associated with matrices associated with the
 * hidden state GEMM.
 *
 * * paramID 0 and 4 are for the input gate.
 *
 * * paramID 1 and 5 are for the forget gate.
 *
 * * paramID 2 and 6 are for the output gate.
 *
 * * paramID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU paramID 0 to 2 refer to the weight matrix offset associated
 * with the input GEMM, while 3 through 5 are associated with the hidden state
 * GEMM.
 *
 * * paramID 0 and 3 are for the update gate.
 *
 * * paramID 1 and 4 are for the reset gate.
 *
 * * paramID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param paramID         ID of the internal parameter tensor (input)
 * @param numBytes        The number of bytes of the layer's parameter matrix (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerParamSize(miopenHandle_t handle,
                                                        miopenRNNDescriptor_t rnnDesc,
                                                        const int layer,
                                                        miopenTensorDescriptor_t xDesc,
                                                        const int paramID,
                                                        size_t* numBytes);

/*! @brief Gets the number of bytes of a bias
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, biasID == 0 retrieves the
 * weight matrix associated with the in input GEMM, while biasID == 1 retrieves
 * the bias associated with the hidden state GEMM.
 *
 * For miopenLSTM biasID 0 to 3 refer to the biases associated
 * with the input GEMM, 4-7 are associated with biases associated with the
 * hidden state GEMM.
 *
 * * biasID 0 and 4 are for the input gate.
 *
 * * biasID 1 and 5 are for the forget gate.
 *
 * * biasID 2 and 6 are for the output gate.
 *
 * * biasID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU biasID 0 to 2 refer to the biases associated with the input GEMM,
 * while 3 through 5 are associated with the hidden state GEMM.
 *
 * * biasID 0 and 3 are for the update gate.
 *
 * * biasID 1 and 4 are for the reset gate.
 *
 * * biasID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param biasID          ID of the internal parameter tensor (input)
 * @param numBytes        The number of bytes of the layer's bias (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerBiasSize(miopenHandle_t handle,
                                                       miopenRNNDescriptor_t rnnDesc,
                                                       const int layer,
                                                       const int biasID,
                                                       size_t* numBytes);

/*! @brief Gets a weight matrix for a specific layer in an RNN stack
 *
 * This function retrieves the weight matrix data for a specific layer and parameter ID
 * and copies the data into previously allocated device memory.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, paramID == 0 retrieves the
 * weight matrix associated with the in input GEMM, while paramID == 1 retrieves
 * the weight matrix associated with the hidden state GEMM.
 *
 * For miopenLSTM paramID 0 to 3 refer to the weight matrices associated
 * with the input GEMM, 4-7 are associated with matrices associated with the
 * hidden state GEMM.
 *
 * * paramID 0 and 4 are for the input gate.
 *
 * * paramID 1 and 5 are for the forget gate.
 *
 * * paramID 2 and 6 are for the output gate.
 *
 * * paramID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU paramID 0 to 2 refer to the weight matrix offset associated
 * with the input GEMM, while 3 through 5 are associated with the hidden state
 * GEMM.
 *
 * * paramID 0 and 3 are for the update gate.
 *
 * * paramID 1 and 4 are for the reset gate.
 *
 * * paramID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The output argument paramDesc is a previously created tensor descriptor that is populated
 * to describe the memory layout of the parameter matrix. It is full packed and is used when
 * calling to miopenSetRNNLayerParam()
 *
 * The argument layerParam should either be nullptr, or have device memory allocated
 * to allow copying of the entire layer parameter matrix into it. If layerParam is
 * nullptr then only the paramDesc is populated and returned. The size in bytes of the
 * layer parameter matrix can be determined by using miopenGetRNNLayerParamSize().
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenGetRNNLayerParam() will return
 * a error status miopenStatusBadParm for input paramID associated with the input GEMM.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param wDesc           A tensor descriptor to the parameter tensor (input)
 * @param w               Pointer to memory containing parameter tensor (input)
 * @param paramID         ID of the internal parameter tensor (input)
 * @param paramDesc       Tensor descriptor for the fully packed output parameter tensor (output)
 * @param layerParam      Pointer to the memory location of the parameter tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerParam(miopenHandle_t handle,
                                                    miopenRNNDescriptor_t rnnDesc,
                                                    const int layer,
                                                    miopenTensorDescriptor_t xDesc,
                                                    miopenTensorDescriptor_t wDesc,
                                                    const void* w,
                                                    const int paramID,
                                                    miopenTensorDescriptor_t paramDesc,
                                                    void* layerParam);

/*! @brief Gets a bias for a specific layer in an RNN stack
 *
 * This function retrieves the bias data for a specific layer and bias ID and copies
 * the data into previously allocated device memory.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, biasID == 0 retrieves the
 * bias associated with the in input GEMM, while biasID == 1 retrieves
 * the bias associated with the hidden state GEMM.
 *
 * For miopenLSTM biasID 0 to 3 refer to the biases associated
 * with the input GEMM, 4-7 are associated with biases associated with the
 * hidden state GEMM.
 *
 * * biasID 0 and 4 are for the input gate.
 *
 * * biasID 1 and 5 are for the forget gate.
 *
 * * biasID 2 and 6 are for the output gate.
 *
 * * biasID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU biasID 0 to 2 refer to the biases associated with the input GEMM,
 * while 3 through 5 are associated with the hidden state GEMM.
 *
 * * biasID 0 and 3 are for the update gate.
 *
 * * biasID 1 and 4 are for the reset gate.
 *
 * * biasID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The output argument biasDesc is a previously created tensor descriptor that is populated
 * to describe the memory layout of the bias. It is full packed and is used when
 * calling to miopenSetRNNLayerBias()
 *
 * The argument layerBias should either be nullptr, or have device memory allocated
 * to allow copying of the entire layer bias into it. If layerBias is
 * nullptr then only the biasDesc is populated and returned. The size in bytes of the
 * layer bias can be determined by using miopenGetRNNLayerBiasSize().
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenGetRNNLayerBias() will return
 * a error status miopenStatusBadParm for input biasID associated with the input GEMM.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param wDesc           A tensor descriptor to the parameter tensor (input)
 * @param w               Pointer to memory containing parameter tensor (input)
 * @param biasID          ID of the internal parameter tensor (input)
 * @param biasDesc        Descriptor of the parameter tensor (output)
 * @param layerBias       Pointer to the memory location of the bias tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerBias(miopenHandle_t handle,
                                                   miopenRNNDescriptor_t rnnDesc,
                                                   const int layer,
                                                   miopenTensorDescriptor_t xDesc,
                                                   miopenTensorDescriptor_t wDesc,
                                                   const void* w,
                                                   const int biasID,
                                                   miopenTensorDescriptor_t biasDesc,
                                                   void* layerBias);

/*! @brief Gets an index offset for a specific weight matrix for a layer in the
 *  RNN stack
 *
 * This function retrieves the index offset for a weight matrix in a layer.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, paramID == 0 retrieves the
 * weight matrix offset associated with the in input GEMM, while paramID == 1
 * retrieves the weight matrix offset associated with the hidden state GEMM.
 *
 * For miopenLSTM paramID 0 to 3 refer to the weight matrix offsets associated
 * with the input GEMM, 4-7 are associated with matrix offset associated with the
 * hidden state GEMM.
 *
 * * paramID 0 and 4 are for the input gate.
 *
 * * paramID 1 and 5 are for the forget gate.
 *
 * * paramID 2 and 6 are for the output gate.
 *
 * * paramID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU paramID 0 to 2 refer to the weight matrix offset associated
 * with the input GEMM, while 3 through 5 are associated with the hidden state
 * GEMM.
 *
 * * paramID 0 and 3 are for the update gate.
 *
 * * paramID 1 and 4 are for the reset gate.
 *
 * * paramID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The output argument paramDesc is a previously created tensor descriptor that is populated
 * to describe the memory layout of the parameter matrix. It is full packed and is used when
 * calling to miopenSetRNNLayerParam().
 *
 * The argument layerParamOffset should either be nullptr, or an address to place the
 * offset. If layerParamOffset is nullptr then only the paramDesc is populated and returned.
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenGetRNNLayerParamOffset() will return
 * a error status miopenStatusBadParm for input paramID associated with the input GEMM.
 *
 *
 * @param rnnDesc           RNN layer descriptor type (input)
 * @param layer             The layer number in the RNN stack (input)
 * @param xDesc             A tensor descriptor to input (input)
 * @param paramID           ID of the internal parameter tensor (input)
 * @param paramDesc         Tensor descriptor for the fully packed output parameter tensor (output)
 * @param layerParamOffset  Location for the parameter offset (output)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerParamOffset(miopenRNNDescriptor_t rnnDesc,
                                                          const int layer,
                                                          miopenTensorDescriptor_t xDesc,
                                                          const int paramID,
                                                          miopenTensorDescriptor_t paramDesc,
                                                          size_t* layerParamOffset);

/*! @brief Gets a bias index offset for a specific layer in an RNN stack
 *
 * This function retrieves the bias index offset for a specific layer and bias ID.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, biasID == 0 retrieves the
 * bias associated with the in input GEMM, while biasID == 1 retrieves
 * the weight matrix associated with the hidden state GEMM.
 *
 * For miopenLSTM biasID 0 to 3 refer to the bias offset associated
 * with the input GEMM, 4-7 are the bias offsets associated with the hidden state GEMM.
 *
 * * biasID 0 and 4 are for the input gate.
 *
 * * biasID 1 and 5 are for the forget gate.
 *
 * * biasID 2 and 6 are for the output gate.
 *
 * * biasID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU biasID 0 to 2 refer to the biases associated with the input GEMM,
 * while 3 through 5 are associated with the hidden state GEMM.
 *
 * * biasID 0 and 3 are for the update gate.
 *
 * * biasID 1 and 4 are for the reset gate.
 *
 * * biasID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The output argument biasDesc is a previously created tensor descriptor that is populated
 * to describe the memory layout of the bias. It is full packed and is used when
 * calling to miopenSetRNNLayerBias()
 *
 * The argument layerBiasOffset should either be nullptr, or point to an output address.
 * If layerBias is nullptr then only the biasDesc is populated and returned.
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenGetRNNLayerBiasOffset() will return
 * a error status miopenStatusBadParm for input biasID associated with the input GEMM.
 *
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param biasID          ID of the internal parameter tensor (input)
 * @param biasDesc        Descriptor of the parameter tensor (output)
 * @param layerBiasOffset Pointer to the memory location of the bias tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetRNNLayerBiasOffset(miopenRNNDescriptor_t rnnDesc,
                                                         const int layer,
                                                         miopenTensorDescriptor_t xDesc,
                                                         const int biasID,
                                                         miopenTensorDescriptor_t biasDesc,
                                                         size_t* layerBiasOffset);

/*! @brief Sets a weight matrix for a specific layer in an RNN stack
 *
 * This function sets the weight matrix data for a specific layer and parameter ID.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, paramID == 0 sets the
 * weight matrix associated with the in input GEMM, while paramID == 1 sets
 * the weight matrix associated with the hidden state GEMM.
 *
 *
 * For miopenLSTM paramID 0 to 3 refer to the weight matrices associated
 * with the input GEMM, 4-7 are associated with matrices associated with the
 * hidden state GEMM.
 *
 * * paramID 0 and 4 are for the input gate.
 *
 * * paramID 1 and 5 are for the forget gate.
 *
 * * paramID 2 and 6 are for the output gate.
 *
 * * paramID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU paramID 0 to 2 refer to the weight matrix offset associated
 * with the input GEMM, while 3 through 5 are associated with the hidden state
 * GEMM.
 *
 * * paramID 0 and 3 are for the update gate.
 *
 * * paramID 1 and 4 are for the reset gate.
 *
 * * paramID 2 and 5 are for the new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The input argument paramDesc is a previously populated tensor descriptor typically
 * by first calling miopenGetRNNLayerParam().
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenSetRNNLayerParam() will return
 * a error status miopenStatusBadParm for input paramID associated with the input GEMM.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param wDesc           A tensor descriptor to the parameter tensor (input)
 * @param w               Pointer to memory containing parameter tensor (input)
 * @param paramID         ID of the internal parameter tensor (input)
 * @param paramDesc       Descriptor of the parameter tensor (input)
 * @param layerParam      Pointer to the memory location of the parameter tensor (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetRNNLayerParam(miopenHandle_t handle,
                                                    miopenRNNDescriptor_t rnnDesc,
                                                    const int layer,
                                                    miopenTensorDescriptor_t xDesc,
                                                    miopenTensorDescriptor_t wDesc,
                                                    void* w,
                                                    const int paramID,
                                                    miopenTensorDescriptor_t paramDesc,
                                                    const void* layerParam);

/*! @brief Sets a bias for a specific layer in an RNN stack
 *
 * This function sets the bias data for a specific layer and bias ID.
 *
 * For RNN vanilla miopenRNNRELU and miopenRNNTANH, biasID == 0 retrieves the
 * weight matrix associated with the in input GEMM, while biasID == 1 retrieves
 * the bias associated with the hidden state GEMM.
 *
 * For miopenLSTM biasID 0 to 3 refer to the biases associated
 * with the input GEMM, 4-7 are associated with the biases associated with the
 * hidden state GEMM.
 *
 * * biasID 0 and 4 are for the input gate.
 *
 * * biasID 1 and 5 are for the forget gate.
 *
 * * biasID 2 and 6 are for the output gate.
 *
 * * biasID 3 and 7 are for the new memory gate.
 *
 * For miopenGRU biasID 0 to 2 refer to the biases associated with the input GEMM,
 * while 3 through 5 are associated with the hidden state GEMM.
 *
 * * biasID 0 and 3 are for the update gate.
 *
 * * biasID 1 and 4 are for the reset gate.
 *
 * * biasID 2 and 5 are for the new new memory gate.
 *
 * For bi-directional RNNs the backwards in time direction is numbered as the layer
 * directly after the forward in time direction.
 *
 * The input argument biasDesc is a previously populated tensor descriptor typically
 * by first calling miopenGetRNNLayeBias().
 *
 * Note: When inputSkip mode is selected there is no input layer matrix operation,
 * and therefore no associated memory. In this case miopenSetRNNLayerBias will return
 * a error status miopenStatusBadParm for input biasID associated with the input GEMM.
 *
 * @param handle          MIOpen handle (input)
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param layer           The layer number in the RNN stack (input)
 * @param xDesc           A tensor descriptor to input (input)
 * @param wDesc           A tensor descriptor to the bias tensor (input)
 * @param w               Pointer to memory containing bias tensor (input)
 * @param biasID          ID of the internal bias tensor (input)
 * @param biasDesc        Descriptor of the bias tensor (output)
 * @param layerBias       Pointer to the memory location of the bias tensor (output)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetRNNLayerBias(miopenHandle_t handle,
                                                   miopenRNNDescriptor_t rnnDesc,
                                                   const int layer,
                                                   miopenTensorDescriptor_t xDesc,
                                                   miopenTensorDescriptor_t wDesc,
                                                   void* w,
                                                   const int biasID,
                                                   miopenTensorDescriptor_t biasDesc,
                                                   const void* layerBias);

/*! @brief Sets a bias for a specific layer in an RNN stack
 *
 * This function changes padidng mode at previously created and initialized RNN descriptor.
 * This function must be called before using miopenGetRNNWorkspaceSize()
 * and miopenGetRNNTrainingReserveSize() functions.
 * By default, not padded data is expected at the RNN input/output.
 *
 * @param rnnDesc         RNN layer descriptor type (input/output)
 * @param paddingMode     RNN input/output data padding mode (input)
 * @return                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetRNNPaddingMode(miopenRNNDescriptor_t rnnDesc,
                                                     miopenRNNPaddingMode_t paddingMode);

/*! @brief This function retrieves the RNN padding mode from the RNN descriptor.
 *
 * @param rnnDesc         RNN layer descriptor type (input)
 * @param paddingMode     Pointer to the RNN padding mode (output)
 * @return                miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenGetRNNPaddingMode(miopenRNNDescriptor_t rnnDesc,
                                                     miopenRNNPaddingMode_t* paddingMode);

/*! @brief Execute forward training for recurrent layer.
 *
 * Interface for executing the forward training / inference pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)
 * @param fwdMode          Specifies in which mode the buffers will be used.
 * @param xDesc                 An input tensor descriptor for sequenced RNN data. This
 * miopenSeqTensorDescriptor_t should be initialized by `miopenSetRNNDataSeqTensorDescriptor`
 * function.(input)
 * @param x                     Pointer to input tensor (input)
 *
 * @param hDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param hy                    Pointer to the hidden layer output tensor. If hy is NULL,
 * then the final hidden state will not be saved. (output)
 *
 * @param cDesc                A cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cx                    Pointer to the cell layer input tensor. If cx is NULL,
 * then the initial cell state will be zero initialized. (input)
 * @param cy                    Pointer to the cell layer output tensor. If hy is NULL,
 * then the final cell state will not be saved. (output)
 *
 * @param yDesc                 An array of fully packed tensor descriptors associated
 * with the output from each time step. The first dimension of the tensor descriptors
 * must equal the first dimension of the first descriptor (batch size) in the xDesc
 * tensor array. The second dimension of the element of the descriptor array
 * depends on the direction mode selected. If the direction mode is unidirectional,
 * the second dimension is the hiddenSize. If direction mode is bidirectional
 * the second dimension is twice the hiddenSize. (input)
 * @param y                     Pointer to output tensor (output)
 *
 * @param w                     Pointer to input weights tensor (input)
 * @param weightSpaceSize       Number of allocated bytes in memory for the weights tensor
 * @param workSpace             Pointer to memory allocated for forward (input / output)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for hidden states used during training
 * (input / output)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward  (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNForward(miopenHandle_t handle,
                                              const miopenRNNDescriptor_t rnnDesc,
                                              miopenRNNFWDMode_t fwdMode,
                                              const miopenSeqTensorDescriptor_t xDesc,
                                              const void* x,
                                              const miopenTensorDescriptor_t hDesc,
                                              const void* hx,
                                              void* hy,
                                              const miopenTensorDescriptor_t cDesc,
                                              const void* cx,
                                              void* cy,
                                              const miopenSeqTensorDescriptor_t yDesc,
                                              void* y,
                                              const void* w,
                                              size_t weightSpaceSize,
                                              void* workSpace,
                                              size_t workSpaceNumBytes,
                                              void* reserveSpace,
                                              size_t reserveSpaceNumBytes);

/*! @brief Execute backward data for recurrent layer
 *
 * Interface for executing the backward data pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)

 * @param yDesc                 An output tensor descriptor for sequenced RNN data. This
 * miopenSeqTensorDescriptor_t should be initialized by `miopenSetRNNDataSeqTensorDescriptor`
 function.(input)
 * @param y                     Pointer to input tensor (input)
 * @param dy                    Pointer to the hidden layer input tensor (input)
 *
 * @param hDesc                An input hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param dhy                   Pointer to the cell layer input tensor (input)
 * @param dhx                   Pointer to the delta hidden layer output tensor. If dhx is NULL
 * the hidden gradient will not ouput. (output)
 *
 * @param cDesc                A input cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cx                    Pointer to the hidden layer input tensor. If cx is NULL,
 * then the initial cell state will be zero initialized. (input)
 * @param dcy                   Pointer to the cell layer input tensor. If dcy is NULL,
 * then the initial delta cell state will be zero initialized. (input)
 * @param dcx                   Pointer to the cell layer output tensor. If dcx is NULL
 * the cell gradient will not ouput. (output)

 * @param xDesc                 An input tensor descriptor for sequenced RNN data. This
 * miopenSeqTensorDescriptor_t should be initialized by `miopenSetRNNDataSeqTensorDescriptor`
 function.(input)
 * @param dx                    Pointer to the cell layer output tensor (output)
 *
 * @param w                     Pointer to input weights tensor (input)
 * @param weightSpaceSize       Number of allocated bytes in memory for the weights tensor
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for random states (input / output)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNBackwardSeqData(miopenHandle_t handle,
                                                      const miopenRNNDescriptor_t rnnDesc,
                                                      const miopenSeqTensorDescriptor_t yDesc,
                                                      const void* y,
                                                      const void* dy,
                                                      const miopenTensorDescriptor_t hDesc,
                                                      const void* hx,
                                                      const void* dhy,
                                                      void* dhx,
                                                      const miopenTensorDescriptor_t cDesc,
                                                      const void* cx,
                                                      const void* dcy,
                                                      void* dcx,
                                                      const miopenSeqTensorDescriptor_t xDesc,
                                                      void* dx,
                                                      const void* w,
                                                      size_t weightSpaceSize,
                                                      void* workSpace,
                                                      size_t workSpaceNumBytes,
                                                      void* reserveSpace,
                                                      size_t reserveSpaceNumBytes);

/*! @brief Execute backward weights for recurrent layer
 *
 * Interface for executing the backward weights pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)

 * @param xDesc                 An input tensor descriptor for sequenced RNN data. This
 * miopenSeqTensorDescriptor_t should be initialized by `miopenSetRNNDataSeqTensorDescriptor`
 function.(input)
 * @param x                     Pointer to input tensor (input)
 *
 * @param hDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 *
 * @param yDesc                 An output tensor descriptor for sequenced RNN data. This
 * miopenSeqTensorDescriptor_t should be initialized by `miopenSetRNNDataSeqTensorDescriptor`
 function.(input)
 * @param y                     Pointer to the output tensor (input)
 *
 * @param dw                    Pointer to input weights tensor (input / output)
 * @param weightSpaceSize       Number of allocated bytes in memory for the weights tensor
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for random states (input)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenRNNBackwardWeightsSeqTensor(miopenHandle_t handle,
                                  const miopenRNNDescriptor_t rnnDesc,
                                  const miopenSeqTensorDescriptor_t xDesc,
                                  const void* x,
                                  const miopenTensorDescriptor_t hDesc,
                                  const void* hx,
                                  const miopenSeqTensorDescriptor_t yDesc,
                                  const void* y,
                                  void* dw,
                                  size_t weightSpaceSize,
                                  void* workSpace,
                                  size_t workSpaceNumBytes,
                                  const void* reserveSpace,
                                  size_t reserveSpaceNumBytes);

/*! @brief Execute forward training for recurrent layer
 *
 * Interface for executing the forward training pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)
 * @param sequenceLen           Temporal iterations to unroll (input)
 * @param xDesc                 An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param x                     Pointer to input tensor (input)
 * @param hxDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param cxDesc                A cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cx                    Pointer to the cell layer input tensor. If cx is NULL,
 * then the initial cell state will be zero initialized. (input)
 * @param wDesc                 A weights tensor descriptor (input)
 * @param w                     Pointer to input weights tensor (input)
 * @param yDesc                 An array of fully packed tensor descriptors associated
 * with the output from each time step. The first dimension of the tensor descriptors
 * must equal the first dimension of the first descriptor (batch size) in the xDesc
 * tensor array. The second dimension of the element of the descriptor array
 * depends on the direction mode selected. If the direction mode is unidirectional,
 * the second dimension is the hiddenSize. If direction mode is bidirectional
 * the second dimension is twice the hiddenSize. (input)
 * @param y                     Pointer to output tensor (output)
 * @param hyDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hy                    Pointer to the hidden layer output tensor. If hy is NULL,
 * then the final hidden state will not be saved. (output)
 * @param cyDesc                A cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cy                    Pointer to the cell layer output tensor. If hy is NULL,
 * then the final cell state will not be saved. (output)
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for random states (input / output)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward  (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNForwardTraining(miopenHandle_t handle,
                                                      const miopenRNNDescriptor_t rnnDesc,
                                                      const int sequenceLen,
                                                      const miopenTensorDescriptor_t* xDesc,
                                                      const void* x,
                                                      const miopenTensorDescriptor_t hxDesc,
                                                      const void* hx,
                                                      const miopenTensorDescriptor_t cxDesc,
                                                      const void* cx,
                                                      const miopenTensorDescriptor_t wDesc,
                                                      const void* w,
                                                      const miopenTensorDescriptor_t* yDesc,
                                                      void* y,
                                                      const miopenTensorDescriptor_t hyDesc,
                                                      void* hy,
                                                      const miopenTensorDescriptor_t cyDesc,
                                                      void* cy,
                                                      void* workSpace,
                                                      size_t workSpaceNumBytes,
                                                      void* reserveSpace,
                                                      size_t reserveSpaceNumBytes);

/*! @brief Execute backward data for recurrent layer
 *
 * Interface for executing the backward data pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)
 * @param sequenceLen           Temporal iterations to unroll (input)
 * @param yDesc                 An array of tensor descriptors (input)
 * @param y                     Pointer to input tensor (input)
 * @param dyDesc                An array of fully packed tensor descriptors associated
 * with the output from each time step. The first dimension of the tensor descriptors
 * must equal the first dimension of the first descriptor (batch size) in the xDesc
 * tensor array. The second dimension of the element of the descriptor array
 * depends on the direction mode selected. If the direction mode is unidirectional,
 * the second dimension is the hiddenSize. If direction mode is bidirectional
 * the second dimension is twice the hiddenSize. (input)
 * @param dy                    Pointer to the hidden layer input tensor (input)
 * @param dhyDesc               A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param dhy                   Pointer to the cell layer input tensor (input)
 * @param dcyDesc               A cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param dcy                   Pointer to the cell layer input tensor. If dcy is NULL,
 * then the initial delta cell state will be zero initialized. (input)
 * @param wDesc                 A weights tensor descriptor (input)
 * @param w                     Pointer to input weights tensor (input)
 * @param hxDesc                An input hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param cxDesc                A input cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cx                    Pointer to the hidden layer input tensor. If cx is NULL,
 * then the initial cell state will be zero initialized. (input)
 * @param dxDesc                An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param dx                    Pointer to the cell layer output tensor (output)
 * @param dhxDesc               A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param dhx                   Pointer to the delta hidden layer output tensor. If dhx is NULL
 * the hidden gradient will not ouput. (output)
 * @param dcxDesc               A tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param dcx                   Pointer to the cell layer output tensor. If dcx is NULL
 * the cell gradient will not ouput. (output)
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for random states (input / output)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNBackwardData(miopenHandle_t handle,
                                                   const miopenRNNDescriptor_t rnnDesc,
                                                   const int sequenceLen,
                                                   const miopenTensorDescriptor_t* yDesc,
                                                   const void* y,
                                                   const miopenTensorDescriptor_t* dyDesc,
                                                   const void* dy,
                                                   const miopenTensorDescriptor_t dhyDesc,
                                                   const void* dhy,
                                                   const miopenTensorDescriptor_t dcyDesc,
                                                   const void* dcy,
                                                   const miopenTensorDescriptor_t wDesc,
                                                   const void* w,
                                                   const miopenTensorDescriptor_t hxDesc,
                                                   const void* hx,
                                                   const miopenTensorDescriptor_t cxDesc,
                                                   const void* cx,
                                                   const miopenTensorDescriptor_t* dxDesc,
                                                   void* dx,
                                                   const miopenTensorDescriptor_t dhxDesc,
                                                   void* dhx,
                                                   const miopenTensorDescriptor_t dcxDesc,
                                                   void* dcx,
                                                   void* workSpace,
                                                   size_t workSpaceNumBytes,
                                                   void* reserveSpace,
                                                   size_t reserveSpaceNumBytes);

/*! @brief Execute backward weights for recurrent layer
 *
 * Interface for executing the backward weights pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)
 * @param sequenceLen           Temporal iterations to unroll (input)
 * @param xDesc                 An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param x                     Pointer to input tensor (input)
 * @param hxDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param yDesc                 An array of fully packed tensor descriptors associated
 * with the output from each time step. The first dimension of the tensor descriptors
 * must equal the first dimension of the first descriptor (batch size) in the xDesc
 * tensor array. The second dimension of the element of the descriptor array
 * depends on the direction mode selected. If the direction mode is unidirectional,
 * the second dimension is the hiddenSize. If direction mode is bidirectional
 * the second dimension is twice the hiddenSize. (input)
 * @param y                     Pointer to the output tensor (input)
 * @param dwDesc                A weights tensor descriptor (input)
 * @param dw                    Pointer to input weights tensor (input / output)
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @param reserveSpace          Pointer to memory allocated for random states (input)
 * @param reserveSpaceNumBytes  Number of allocated bytes in memory for use in the forward (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNBackwardWeights(miopenHandle_t handle,
                                                      const miopenRNNDescriptor_t rnnDesc,
                                                      const int sequenceLen,
                                                      const miopenTensorDescriptor_t* xDesc,
                                                      const void* x,
                                                      const miopenTensorDescriptor_t hxDesc,
                                                      const void* hx,
                                                      const miopenTensorDescriptor_t* yDesc,
                                                      const void* y,
                                                      const miopenTensorDescriptor_t dwDesc,
                                                      void* dw,
                                                      void* workSpace,
                                                      size_t workSpaceNumBytes,
                                                      const void* reserveSpace,
                                                      size_t reserveSpaceNumBytes);

/*! @brief Execute forward inference for RNN layer
 *
 * Interface for executing the forward inference pass on a RNN.
 *
 * @param handle                MIOpen handle (input)
 * @param rnnDesc               RNN layer descriptor type (input)
 * @param sequenceLen           Temporal iterations to unroll (input)
 * @param xDesc                 An array of tensor descriptors. These are the
 * input descriptors to each time step. The first dimension of each descriptor is the
 * batch size and may decrease from element n to element n+1 and not increase in size.
 * The second dimension is the same for all descriptors in the array and is the input
 * vector length. (input)
 * @param x                     Pointer to input tensor (input)
 * @param hxDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hx                    Pointer to the hidden layer input tensor. If hx is NULL,
 * then the initial hidden state will be zero initialized. (input)
 * @param cxDesc                A cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cx                    Pointer to the cell layer input tensor. If cx is NULL,
 * then the initial cell state will be zero initialized. (input)
 * @param wDesc                 A weights tensor descriptor (input)
 * @param w                     Pointer to input weights tensor (input)
 * @param yDesc                 An array of fully packed tensor descriptors associated
 * with the output from each time step. The first dimension of the tensor descriptors
 * must equal the first dimension of the first descriptor (batch size) in the xDesc
 * tensor array. The second dimension of the element of the descriptor array
 * depends on the direction mode selected. If the direction mode is unidirectional,
 * the second dimension is the hiddenSize. If direction mode is bidirectional
 * the second dimension is twice the hiddenSize. (input)
 * @param y                     Pointer to output tensor (output)
 * @param hyDesc                A hidden tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param hy                    Pointer to the hidden layer output tensor. If hy is NULL,
 * then the final hidden state will not be saved. (output)
 * @param cyDesc                A output cell tensor descriptor that has as its first dimension
 * of the number of layers if the direction mode is unidirectional and twice the
 * number of layers if the direction mode is bidirectional. The second dimension of
 * the descriptor must equal the largest first dimension of the xDesc tensor descriptor
 * array. The third dimension equals the hiddenSize. (input)
 * @param cy                    Pointer to the cell layer output tensor. If cy is NULL,
 * then the final cell state will not be saved. (output)
 * @param workSpace             Pointer to memory allocated for forward training (input)
 * @param workSpaceNumBytes     Number of allocated bytes in memory for the workspace (input)
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRNNForwardInference(miopenHandle_t handle,
                                                       miopenRNNDescriptor_t rnnDesc,
                                                       const int sequenceLen,
                                                       const miopenTensorDescriptor_t* xDesc,
                                                       const void* x,
                                                       const miopenTensorDescriptor_t hxDesc,
                                                       const void* hx,
                                                       const miopenTensorDescriptor_t cxDesc,
                                                       const void* cx,
                                                       const miopenTensorDescriptor_t wDesc,
                                                       const void* w,
                                                       const miopenTensorDescriptor_t* yDesc,
                                                       void* y,
                                                       const miopenTensorDescriptor_t hyDesc,
                                                       void* hy,
                                                       const miopenTensorDescriptor_t cyDesc,
                                                       void* cy,
                                                       void* workSpace,
                                                       size_t workSpaceNumBytes);

/** @} */
// CLOSEOUT RNN DOXYGEN GROUP

/** @addtogroup LossFunction
 *
 *  @{
 */

/*! @enum miopenCTCLossAlgo_t
 * Algorithms available to execute the CTC loss operation
 */
typedef enum
{
    MIOPEN_CTC_LOSS_ALGO_DETERMINISTIC = 0, /*!< Results are guaranteed to be reproducible */
} miopenCTCLossAlgo_t;

/*! @brief Create a CTC loss function Descriptor
 *
 * API for creating an uninitialized CTC loss function descriptor.
 * @param ctcLossDesc  Pointer to the CTC loss function descriptor type (output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateCTCLossDescriptor(miopenCTCLossDescriptor_t* ctcLossDesc);

/*! @brief Retrieves a CTC loss function descriptor's details
 *
 * @param ctcLossDesc          CTC loss function descriptor (input)
 * @param dataType             Data type used in this CTC loss operation, only fp32 currently
 * supported (output)
 * @param blank_label_id       User defined index for blank label (output)
 * @param apply_softmax_layer  Boolean to toggle input layer property (output)
 * @return                     miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetCTCLossDescriptor(miopenCTCLossDescriptor_t ctcLossDesc,
                                                        miopenDataType_t* dataType,
                                                        int* blank_label_id,
                                                        bool* apply_softmax_layer);

/*! @brief Destroys a CTC loss function descriptor object
 *
 * @param ctcLossDesc  CTC loss function descriptor type (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyCTCLossDescriptor(miopenCTCLossDescriptor_t ctcLossDesc);

/*! @brief Set the details of a CTC loss function descriptor
 *
 * @param ctcLossDesc          CTC loss function descriptor type (input)
 * @param dataType             Data type used in this CTC loss operation, only fp32 currently
 * supported (input)
 * @param blank_label_id       User defined index for blank label, default 0 (input)
 * @param apply_softmax_layer  Boolean to toggle input layer property (input)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetCTCLossDescriptor(miopenCTCLossDescriptor_t ctcLossDesc,
                                                        miopenDataType_t dataType,
                                                        const int blank_label_id,
                                                        bool apply_softmax_layer);

/*! @brief Query the amount of memory required to execute miopenCTCLoss
 *
 * This function calculates the amount of memory required to run the CTC loss function given a CTC
 * loss function descriptor with the specified algorithm.
 * @param handle         MIOpen handle (input)
 * @param probsDesc      Tensor descriptor for probabilities (input)
 * @param gradientsDesc  Tensor descriptor for gradients (input)
 * @param labels         Pointer to the flattened labels list (input)
 * @param labelLengths   Pointer to the lengths list for "labels" (input)
 * @param inputLengths   Pointer to the list of the time steps in each batch (input)
 * @param algo           CTC loss algorithm selected (input)
 * @param ctcLossDesc    CTC loss function descriptor type (input)
 * @param workSpaceSize  Number of bytes of workspace required for CTC loss operation with selected
 * algorithm (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetCTCLossWorkspaceSize(miopenHandle_t handle,
                              const miopenTensorDescriptor_t probsDesc,
                              const miopenTensorDescriptor_t gradientsDesc,
                              const int* labels,
                              const int* labelLengths,
                              const int* inputLengths,
                              miopenCTCLossAlgo_t algo,
                              const miopenCTCLossDescriptor_t ctcLossDesc,
                              size_t* workSpaceSize);

/*! @brief Execute forward inference for CTCLoss layer
 *
 * Interface for executing the forward inference pass on a CTCLoss.
 * @param handle         MIOpen handle (input)
 * @param probsDesc      Tensor descriptor for probabilities (input)
 * @param probs          Pointer to the probabilities tensor (input)
 * @param labels         Pointer to the flattened labels list (input)
 * @param labelLengths   Pointer to the lengths list for "labels" (input)
 * @param inputLengths   Pointer to the list of the time steps in each batch (input)
 * @param losses         Pointer to the computed losses of CTC (Output)
 * @param gradientsDesc  Tensor descriptor for gradients (input)
 * @param gradients      Pointer to the computed gradients of CTC (Output)
 * @param algo           CTC loss algorithm selected (input)
 * @param ctcLossDesc    CTC loss function descriptor type (input)
 * @param workSpace      Pointer to memory allocated for execute CTC loss operation (input)
 * @param workSpaceSize  Number of bytes of workspace required for CTC loss operation with selected
 * algorithm (input)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCTCLoss(miopenHandle_t handle,
                                           const miopenTensorDescriptor_t probsDesc,
                                           const void* probs,
                                           const int* labels,
                                           const int* labelLengths,
                                           const int* inputLengths,
                                           void* losses,
                                           const miopenTensorDescriptor_t gradientsDesc,
                                           void* gradients,
                                           miopenCTCLossAlgo_t algo,
                                           const miopenCTCLossDescriptor_t ctcLossDesc,
                                           void* workSpace,
                                           size_t workSpaceSize);

/** @} */
// CLOSEOUT LossFunction DOXYGEN GROUP

// Dropout APIs
/** @addtogroup dropout
 *
 *  @{
 */

/*!  @enum miopenRNGType_t
 * random number generator type
 */
typedef enum
{
    MIOPEN_RNG_PSEUDO_XORWOW = 0, /*!< XORWOW pseudorandom generator */
} miopenRNGType_t;

/*! @brief Creates the dropout descriptor object
 *
 * @param dropoutDesc Pointer to a dropout descriptor type
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateDropoutDescriptor(miopenDropoutDescriptor_t* dropoutDesc);

/*! @brief Destroys the dropout descriptor object
 *
 * @param dropoutDesc Dropout descriptor type (input)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyDropoutDescriptor(miopenDropoutDescriptor_t dropoutDesc);

/*! @brief Query the amount of memory required to run dropout
 *
 * This function calculates the amount of memory required to run dropout.
 * @param xDesc                    Tensor descriptor for data tensor x (input)
 * @param reserveSpaceSizeInBytes  Number of bytes of reservespace required for executing dropout
 * (Output)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDropoutGetReserveSpaceSize(const miopenTensorDescriptor_t xDesc,
                                                              size_t* reserveSpaceSizeInBytes);

/*! @brief Query the amount of memory required to store the states of the random number generators
 *
 * This function calculates the amount of memory required to store the states of the random number
 * generators used by miopenDropoutForward.
 * @param handle            MIOpen handle (input)
 * @param stateSizeInBytes  Number of bytes required to store random generator states (Output)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDropoutGetStatesSize(miopenHandle_t handle,
                                                        size_t* stateSizeInBytes);

/*! @brief Get the details of the dropout descriptor
 *
 * Interface for querying the dropout descriptor
 * @param dropoutDesc  Dropout layer descriptor (input)
 * @param handle       MIOpen handle (input)
 * @param dropout      The probability by which the input is set to 0 in the dropout layer (Output)
 * @param states       Pointer to memory that holds random number generator states (Output)
 * @param seed         Seed used to initialize random number generator states (Output)
 * @param use_mask     Boolean flag indicating whether to use a saved mask (an existing or
 * user-defined dropout layout) in reserveSpace (Output)
 * @param state_evo    Boolean flag indicating whether to adopt state evolution strategy to update
 * the PRNG states by the end of each implementation (Output placeholder, currently not enabled)
 * @param rng_mode     Random number generator used to generate parallel random number sequences
 * (Output)
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetDropoutDescriptor(miopenDropoutDescriptor_t dropoutDesc,
                                                        miopenHandle_t handle,
                                                        float* dropout,
                                                        void** states,
                                                        unsigned long long* seed,
                                                        bool* use_mask,
                                                        bool* state_evo,
                                                        miopenRNGType_t* rng_mode);

/*! @brief Restore the dropout descriptor to a saved state
 *
 * This function restores the state of dropout descriptor using the address of a state buffer with
 * previously saved PRNG state pattern, without launching the expensive PRNG initialization process.
 *
 * Interface for restoring the dropout descriptor
 * @param dropoutDesc       Dropout layer descriptor (input/Output)
 * @param handle            MIOpen handle (input)
 * @param dropout           The probability by which the input is set to 0 in the dropout layer
 * (input)
 * @param states            Pointer to memory that holds random number generator states (input)
 * @param stateSizeInBytes  Number of bytes holding random generator states (input)
 * @param seed              Seed used to initialize random number generator states (input)
 * @param use_mask          Boolean flag indicating whether to use a saved mask (an existing or
 * user-defined dropout layout) in reserveSpace (input)
 * @param state_evo         Boolean flag indicating whether to adopt state evolution strategy to
 * update the PRNG states by the end of each implementation (input placeholder, currently not
 * enabled)
 * @param rng_mode          Random number generator used to generate parallel random number
 * sequences (input)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRestoreDropoutDescriptor(miopenDropoutDescriptor_t dropoutDesc,
                                                            miopenHandle_t handle,
                                                            float dropout,
                                                            void* states,
                                                            size_t stateSizeInBytes,
                                                            unsigned long long seed,
                                                            bool use_mask,
                                                            bool state_evo,
                                                            miopenRNGType_t rng_mode);

/*! @brief Initialize the dropout descriptor
 *
 * Interface for setting up the dropout descriptor
 * @param dropoutDesc       Dropout layer descriptor (input/Output)
 * @param handle            MIOpen handle (input)
 * @param dropout           The probability by which the input is set to 0 in the dropout layer
 * (input)
 * @param states            Pointer to memory that holds random number generator states (input)
 * @param stateSizeInBytes  Number of bytes provided for random generator states (input)
 * @param seed              Seed used to initialize random number generator states (input)
 * @param use_mask          Boolean flag indicating whether to use a saved mask (an existing or
 * user-defined dropout layout) in reserveSpace (input)
 * @param state_evo         Boolean flag indicating whether to adopt state evolution strategy to
 * update the PRNG states by the end of each implementation (input placeholder, currently not
 * enabled)
 * @param rng_mode          Random number generator used to generate parallel random number
 * sequences (input)
 * @return                  miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetDropoutDescriptor(miopenDropoutDescriptor_t dropoutDesc,
                                                        miopenHandle_t handle,
                                                        float dropout,
                                                        void* states,
                                                        size_t stateSizeInBytes,
                                                        unsigned long long seed,
                                                        bool use_mask,
                                                        bool state_evo,
                                                        miopenRNGType_t rng_mode);

/*! @brief Execute forward dropout operation
 *
 * Interface for executing the forward pass on a Dropout.
 * @param handle                   MIOpen handle (input)
 * @param dropoutDesc              Dropout layer descriptor (input)
 * @param noise_shape              Tensor descriptor for noise shape (input placeholder, currently
 * not enabled)
 * @param xDesc                    Tensor descriptor for data tensor x (input)
 * @param x                        Data tensor x (input)
 * @param yDesc                    Tensor descriptor for data tensor y (input)
 * @param y                        Data tensor y (Output)
 * @param reserveSpace             Pointer to memory allocated for executing forward dropout,
 * expecting reserveSpace unchanged before next call of miopenDropoutBackward (Output)
 * @param reserveSpaceSizeInBytes  Number of bytes of reservespace required for executing forward
 * dropout (input)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDropoutForward(miopenHandle_t handle,
                                                  const miopenDropoutDescriptor_t dropoutDesc,
                                                  const miopenTensorDescriptor_t noise_shape,
                                                  const miopenTensorDescriptor_t xDesc,
                                                  const void* x,
                                                  const miopenTensorDescriptor_t yDesc,
                                                  void* y,
                                                  void* reserveSpace,
                                                  size_t reserveSpaceSizeInBytes);

/*! @brief Execute backward dropout operation
 *
 * Interface for executing the backward pass on a Dropout.
 * @param handle                   MIOpen handle (input)
 * @param dropoutDesc              Dropout layer descriptor (input)
 * @param noise_shape              Tensor descriptor for noise shape (input placeholder, currently
 * not enabled)
 * @param dyDesc                   Tensor descriptor for data delta tensor dy (input)
 * @param dy                       Data delta tensor dy (input)
 * @param dxDesc                   Tensor descriptor for data delta tensor dx (input)
 * @param dx                       Data delta tensor dx (Output)
 * @param reserveSpace             Pointer to memory allocated for executing backward dropout,
 * expecting reserveSpace unchanged after previous call of miopenDropoutForward (input)
 * @param reserveSpaceSizeInBytes  Number of bytes of reservespace required for executing backward
 * dropout (input)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDropoutBackward(miopenHandle_t handle,
                                                   const miopenDropoutDescriptor_t dropoutDesc,
                                                   const miopenTensorDescriptor_t noise_shape,
                                                   const miopenTensorDescriptor_t dyDesc,
                                                   const void* dy,
                                                   const miopenTensorDescriptor_t dxDesc,
                                                   void* dx,
                                                   void* reserveSpace,
                                                   size_t reserveSpaceSizeInBytes);

/** @} */
// CLOSEOUT DROPOUT DOXYGEN GROUP

// TensorReduce APIs
/** @addtogroup TensorReduce
 *
 *  @{
 */

/*! @brief Creates the ReduceTensor descriptor object
 *
 * @param reduceTensorDesc Pointer to a ReduceTensor descriptor type
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateReduceTensorDescriptor(miopenReduceTensorDescriptor_t* reduceTensorDesc);

/*! @brief Destroy the ReduceTensor descriptor object
 *
 * @param reduceTensorDesc  ReduceTensor descriptor type (input)
 * @return            miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenDestroyReduceTensorDescriptor(miopenReduceTensorDescriptor_t reduceTensorDesc);

/*! @brief Initialize a ReduceTensor descriptor object
 *
 * @param reduceTensorDesc         Pointer to the ReduceTensor descriptor object (output)
 * @param reduceTensorOp           Enumerant specifying the operation used by ReduceTensor (input)
 * @param reduceTensorCompType     Enumerant specifying the data type used with ReduceTensor
 * operation (input)
 * @param reduceTensorNanOpt       Enumerant specifying the NaN number propagation mode (input)
 * @param reduceTensorIndices      Enumerant specifying the indices modes used by ReduceTensor
 * (input)
 * @param reduceTensorIndicesType  Enumerant specifying the data type of the indices (input)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetReduceTensorDescriptor(miopenReduceTensorDescriptor_t reduceTensorDesc,
                                miopenReduceTensorOp_t reduceTensorOp,
                                miopenDataType_t reduceTensorCompType,
                                miopenNanPropagation_t reduceTensorNanOpt,
                                miopenReduceTensorIndices_t reduceTensorIndices,
                                miopenIndicesType_t reduceTensorIndicesType);

/*! @brief Query a ReduceTensor descriptor object
 *
 * @param reduceTensorDesc         Pointer to the ReduceTensor descriptor object (input)
 * @param reduceTensorOp           Pointer to enumerant specifying the operation used by
 * ReduceTensor (output)
 * @param reduceTensorCompType     Pointer to enumerant specifying the data type used with
 * ReduceTensor operation (output)
 * @param reduceTensorNanOpt       Pointer to enumerant specifying the NaN number propagation mode
 * (output)
 * @param reduceTensorIndices      Pointer to enumerant specifying the indices modes used by
 * ReduceTensor (output)
 * @param reduceTensorIndicesType  Pointer to enumerant specifying the data type of the indices
 * (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetReduceTensorDescriptor(const miopenReduceTensorDescriptor_t reduceTensorDesc,
                                miopenReduceTensorOp_t* reduceTensorOp,
                                miopenDataType_t* reduceTensorCompType,
                                miopenNanPropagation_t* reduceTensorNanOpt,
                                miopenReduceTensorIndices_t* reduceTensorIndices,
                                miopenIndicesType_t* reduceTensorIndicesType);

/*! @brief Helper function to query the minimum index space size required by the ReduceTensor call
 *
 * @param handle                   MIOpen Handle (input)
 * @param reduceTensorDesc         Pointer to the ReduceTensor descriptor object (input)
 * @param aDesc                    Pointer to the input tensor descriptor (input)
 * @param cDesc                    Pointer to the output tensor descriptor (input)
 * @param sizeInBytes              Pointer to data to return the minimum index space size
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetReductionIndicesSize(miopenHandle_t handle,
                              const miopenReduceTensorDescriptor_t reduceTensorDesc,
                              const miopenTensorDescriptor_t aDesc,
                              const miopenTensorDescriptor_t cDesc,
                              size_t* sizeInBytes);

/*! @brief Helper function to query the minimum workspace size required by the ReduceTensor call
 *
 * @param handle                   MIOpen Handle (input)
 * @param reduceTensorDesc         Pointer to the ReduceTensor descriptor object (input)
 * @param aDesc                    Pointer to the input tensor descriptor (input)
 * @param cDesc                    Pointer to the output tensor descriptor (input)
 * @param sizeInBytes              Pointer to data to return the minimum workspace size
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetReductionWorkspaceSize(miopenHandle_t handle,
                                const miopenReduceTensorDescriptor_t reduceTensorDesc,
                                const miopenTensorDescriptor_t aDesc,
                                const miopenTensorDescriptor_t cDesc,
                                size_t* sizeInBytes);

/*! @brief TensorReduce function doing reduction on tensor A by implementing C = alpha * reduceOp(A)
 * + beta * C
 *
 * The length of each dimension of output tensor C must match the length of the corresponding
 * dimension of
 * input tensor A or must be equal to 1. The dimensions with length equal to 1 indicate the
 * dimensions
 * of A to be reduced.
 *
 * @param handle                   MIOpen Handle (input)
 * @param reduceTensorDesc         Pointer to the ReduceTensor descriptor object (input)
 * @param indices                  Address of the allocated indices data space (output)
 * @param indicesSizeInBytes       Size in bytes of the allocated indices data space (input)
 * @param workspace                Address of the allocated workspace data (input)
 * @param workspaceSizeInBytes     Size in bytes of the allocated workspace data (input)
 * @param alpha                    Pointer to scale factor for data in input tensor A (input)
 * @param aDesc                    Pointer to the tensor descriptor for input tensor A (input)
 * @param A                        Pointer to the data of input tensor A (input)
 * @param beta                     Pointer to scale factor for data in output tensor C (input)
 * @param cDesc                    Pointer to the tensor descriptor for output tensor C (input)
 * @param C                        Pointer to the data of output tensor C (output)
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenReduceTensor(miopenHandle_t handle,
                   const miopenReduceTensorDescriptor_t reduceTensorDesc,
                   void* indices,
                   size_t indicesSizeInBytes,
                   void* workspace,
                   size_t workspaceSizeInBytes,
                   const void* alpha,
                   const miopenTensorDescriptor_t aDesc,
                   const void* A,
                   const void* beta,
                   const miopenTensorDescriptor_t cDesc,
                   void* C);

/** @} */
// CLOSEOUT TensorReduce DOXYGEN GROUP

// Find 2.0 API
/** @addtogroup find2
 *
 *  @{
 */

/*! @brief Describes a problem for different miopen operations.
 *
 * For now, this is only used for convolution, but could be used for other
 * operators in the future(such as GEMM, Pooling, etc)
 */
MIOPEN_DECLARE_OBJECT(miopenProblem);

/*! @enum miopenProblemDirection_t
 * Directions of miopen operation.
 */
typedef enum
{
    miopenProblemDirectionForward         = 0,
    miopenProblemDirectionBackward        = 1,
    miopenProblemDirectionBackwardWeights = 2,
#ifdef MIOPEN_BETA_API
    miopenProblemDirectionInference = 4,
#endif
} miopenProblemDirection_t;

/*! @enum miopenTensorArgumentId_t
 * Identifiers for tensor arguments of problems and operations.
 */
typedef enum
{
    miopenTensorArgumentIdInvalid = 0,
    miopenTensorConvolutionX      = 1,
    miopenTensorConvolutionW      = 2,
    miopenTensorConvolutionY      = 3,

    miopenTensorMhaK                  = 4,
    miopenTensorMhaQ                  = 5,
    miopenTensorMhaV                  = 6,
    miopenTensorMhaDescaleK           = 7,
    miopenTensorMhaDescaleQ           = 8,
    miopenTensorMhaDescaleV           = 9,
    miopenTensorMhaDescaleS           = 10,
    miopenTensorMhaScaleS             = 11,
    miopenTensorMhaScaleO             = 12,
    miopenTensorMhaDropoutProbability = 13,
    miopenTensorMhaDropoutSeed        = 14,
    miopenTensorMhaDropoutOffset      = 15,
    miopenTensorMhaO                  = 16,
    miopenTensorMhaAmaxO              = 17,
    miopenTensorMhaAmaxS              = 18,
    miopenTensorMhaM                  = 19,
    miopenTensorMhaZInv               = 20,
    miopenTensorMhaDO                 = 21,
    miopenTensorMhaDescaleO           = 22,
    miopenTensorMhaDescaleDO          = 23,
    miopenTensorMhaDescaleDS          = 24,
    miopenTensorMhaScaleDS            = 25,
    miopenTensorMhaScaleDQ            = 26,
    miopenTensorMhaScaleDK            = 27,
    miopenTensorMhaScaleDV            = 28,
    miopenTensorMhaDQ                 = 29,
    miopenTensorMhaDK                 = 30,
    miopenTensorMhaDV                 = 31,
    miopenTensorMhaAmaxDQ             = 32,
    miopenTensorMhaAmaxDK             = 33,
    miopenTensorMhaAmaxDV             = 34,
    miopenTensorMhaAmaxDS             = 35,
    miopenTensorMhaBias               = 36,

#ifdef MIOPEN_BETA_API
    miopenTensorActivationX                = 37,
    miopenTensorActivationY                = 38,
    miopenTensorActivationDX               = 39,
    miopenTensorActivationDY               = 40,
    miopenTensorBiasX                      = 41,
    miopenTensorBiasY                      = 42,
    miopenTensorBias                       = 43,
    miopenTensorSoftmaxX                   = 44,
    miopenTensorSoftmaxY                   = 45,
    miopenTensorSoftmaxDX                  = 46,
    miopenTensorSoftmaxDY                  = 47,
    miopenTensorBatchnormX                 = 48,
    miopenTensorBatchnormY                 = 49,
    miopenTensorBatchnormRunningMean       = 50,
    miopenTensorBatchnormRunningVariance   = 51,
    miopenTensorBatchnormSavedMean         = 52,
    miopenTensorBatchnormSavedVariance     = 53,
    miopenTensorBatchnormScale             = 54,
    miopenTensorBatchnormScaleDiff         = 55,
    miopenTensorBatchnormEstimatedMean     = 56,
    miopenTensorBatchnormEstimatedVariance = 57,
    miopenTensorBatchnormBias              = 58,
    miopenTensorBatchnormBiasDiff          = 59,
    miopenTensorBatchnormDX                = 60,
    miopenTensorBatchnormDY                = 61,
#endif

    miopenTensorArgumentIsScalar = 1U << 31,

    miopenTensorMhaMask = miopenTensorArgumentIsScalar | 1,
#ifdef MIOPEN_BETA_API
    miopenScalarBatchnormExpAvgFactor = miopenTensorArgumentIsScalar | 2,
    miopenScalarBatchnormEpsilon      = miopenTensorArgumentIsScalar | 3,
#endif
} miopenTensorArgumentId_t;

/*! @enum miopenTensorArgumentId_t
 * Different ways to sort results of the find call.
 */
typedef enum
{
    miopenFindResultsOrderByTime          = 0,
    miopenFindResultsOrderByWorkspaceSize = 1,
} miopenFindResultsOrder_t;

/*! @brief Initializes a problem object describing a convolution operation.
 *
 * @param problem      Pointer to the problem to initialize
 * @param operatorDesc Descriptor of the operator to be used
 * @param direction    Direction of the operation
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateConvProblem(miopenProblem_t* problem,
                                                     miopenConvolutionDescriptor_t operatorDesc,
                                                     miopenProblemDirection_t direction);

/*! @brief Initializes a problem object describing a Mha operation.
 *
 * @param problem      Pointer to the problem to initialize
 * @param operatorDesc Descriptor of the operator to be used
 * @param direction    Direction of the operation
 * @return             miopenStatus_t
 */

/*! @enum miopenMhaMask_t
 * Different masks for Mha.
 */
typedef enum
{
    miopenMhaMaskNone   = 0,
    miopenMhaMaskCausal = 1,
} miopenMhaMask_t;

MIOPEN_EXPORT miopenStatus_t miopenCreateMhaProblem(miopenProblem_t* problem,
                                                    miopenMhaDescriptor_t operatorDesc,
                                                    miopenProblemDirection_t direction);

/*! @brief Creates the mha descriptor object
 *
 * @param mhaDesc     Pointer to a mha descriptor type
 * @return            miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenCreateMhaDescriptor(miopenMhaDescriptor_t* mhaDesc);

/*! @brief Sets the Mha descriptor details
 *
 * Sets all of the descriptor details for the Mha
 *
 * @param mhaDesc               Pointer to a Mha descriptor
 * @param scale                 Scale
 * @return                      miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenSetMhaDescriptor(miopenMhaDescriptor_t mhaDesc, float scale);

/*! @brief Gets the Mha descriptor details
 *
 * Retrieves all of the descriptor details for the Mha.
 *
 * @param mhaDesc       Pointer to a Mha descriptor
 * @param scale         Scale (output)
 * @return              miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenGetMhaDescriptor(miopenMhaDescriptor_t mhaDesc, float* scale);

/*! @brief Creates the Softmax descriptor object
 *
 * @param softmaxDesc Pointer to an softmax descriptor type
 * @return            miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenCreateSoftmaxDescriptor(miopenSoftmaxDescriptor_t* softmaxDesc);

/*! @brief Sets the softmax descriptor details
 *
 * Sets all of the descriptor details for the softmax layer
 *
 * @param softmaxDesc  Pointer to a softmax layer descriptor
 * @param alpha        Softmax alpha parameter
 * @param beta         Softmax beta parameter
 * @param algorithm    Softmax algorithm
 * @param mode         Softmax mode
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetSoftmaxDescriptor(miopenSoftmaxDescriptor_t softmaxDesc,
                                                        float alpha,
                                                        float beta,
                                                        miopenSoftmaxAlgorithm_t algorithm,
                                                        miopenSoftmaxMode_t mode);

/*! @brief Gets the softmax layer descriptor details
 *
 * Retrieves all of the descriptor details for the softmax layer.
 *
 * @param softmaxDesc   Pointer to a softmax layer descriptor (input)
 * @param alpha         Softmax alpha parameter (output)
 * @param beta          Softmax beta parameter (output)
 * @param algorithm     Softmax algorithm (output)
 * @param mode          Softmax mode (output)
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSoftmaxDescriptor(const miopenSoftmaxDescriptor_t softmaxDesc,
                                                        float* alpha,
                                                        float* beta,
                                                        miopenSoftmaxAlgorithm_t* algorithm,
                                                        miopenSoftmaxMode_t* mode);

/*! @brief Destroys a problem object.
 *
 * @param problem Problem to destroy
 * @return        miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyProblem(miopenProblem_t problem);

/*! @brief Sets a tensor descriptor for the specified argument.
 *
 * @param problem    Problem to update
 * @param id         Id of the argument for the descriptor
 * @param descriptor Tensor descriptor to set
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenSetProblemTensorDescriptor(miopenProblem_t problem,
                                 miopenTensorArgumentId_t id,
                                 const miopenTensorDescriptor_t descriptor);

/*! @brief The miopenFindOptions allows the user to configure how find will be used.
 */
MIOPEN_DECLARE_OBJECT(miopenFindOptions);

/*! @brief Initializes miopenFindOptions object.
 *
 * @param options    Pointer to options object to initialze
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateFindOptions(miopenFindOptions_t* options);

/*! @brief Destroys miopenFindOptions object.
 *
 * @param options    Options object to destroy
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroyFindOptions(miopenFindOptions_t options);

/*! @brief Sets the tuning find option. Default value is zero.
 *
 * @param options    Options object to update
 * @param value      Value of zero means no tuning, value of one means tuning enabled
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionTuning(miopenFindOptions_t options, int value);

/*! @brief Sets the results order find option. Default value is miopenFindResultsOrderByTime.
 *
 * @param options    Options object to update
 * @param value      Specifies what order should find results have
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionResultsOrder(miopenFindOptions_t options,
                                                             miopenFindResultsOrder_t value);

/*! @brief Sets the workspace limit find option. Default value is maximum of size_t
 *
 * @param options    Options object to update
 * @param value      Specifies the workspace limit for find call. All solvers exceeding the limit
 * would be ignored.
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionWorkspaceLimit(miopenFindOptions_t options,
                                                               size_t value);

/*! @brief Attaches the preallocated workspace to find options. Allocated by the library by default.
 *
 * @param options    Options object to update
 * @param buffer     Specifies the workspace for find call
 * @param size       Specifies the size of the buffer passed
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionPreallocatedWorkspace(miopenFindOptions_t options,
                                                                      void* buffer,
                                                                      size_t size);

/*! @brief Attaches a preallocated tensor to find options. If not used, buffers are allocated by
 * MIOpen internally, which is not recommended.
 *
 * @param options    Options object to update
 * @param id         Specifies the id of the tensor passed
 * @param buffer     Specifies the tensor for find call
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionPreallocatedTensor(miopenFindOptions_t options,
                                                                   miopenTensorArgumentId_t id,
                                                                   void* buffer);

/*! @brief Forces library to attach kernel binaries to solutions for later saving. This allows zero
 * lookup miopenRunSolution calls after miopenLoadSolution. Default value is 0.
 *
 * @param options    Options object to update
 * @param attach     1 means attaching, 0 - skipping, any other value - reserved for future use
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetFindOptionAttachBinaries(miopenFindOptions_t options,
                                                               unsigned attach);

/*! @brief The miopenSolution object describes a prepared solution.
 */
MIOPEN_DECLARE_OBJECT(miopenSolution);

/*! @brief Finds solutions to a problem by running different applicable solutions. Memory is
 * automatically allocated.
 *
 * @param handle       Handle to execute the kernels
 * @param problem      Problem to solve
 * @param options      Find options. When null default values would be used
 * @param solutions    Pointer to the first result. Must not be null
 * @param numSolutions Pointer to the amount of results. Ignored if null
 * @param maxSolutions Limits the amount of results
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenFindSolutions(miopenHandle_t handle,
                                                 miopenProblem_t problem,
                                                 miopenFindOptions_t options,
                                                 miopenSolution_t* solutions,
                                                 size_t* numSolutions,
                                                 size_t maxSolutions);

/*! @brief Values of a tensor or scalar argument for the miopenRunSolution function.
 */
struct miopenTensorArgument_t
{
    /* @brief Identifier of the tensor argument.
     */
    miopenTensorArgumentId_t id;
    /* @brief Tensor descriptor to override the value stored in the solution.
     *
     * Some solvers may support overriding input and output tensor descriptors, but right now there
     * is no way to tell from the API. Intended for the future use.
     */
    miopenTensorDescriptor_t* descriptor;
    /* @brief Pointer to the device memory buffer to use for the operation or to the host memory if
     * the value is scalar.
     */
    void* buffer;
};

/*! @brief Runs the solution using the passed in buffers.
 *
 * @param handle        Handle to execute the kernels
 * @param solution      Solution to execute
 * @param nInputs       Amount to inputs for the solution
 * @param tensors       Tensor arguments described by miopenTensorArgument_t
 * @param workspace     Pointer to device buffer used as workspace. May be null when not required.
 * Should not be less than expected
 * @param workspaceSize Size of the workspace buffer
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRunSolution(miopenHandle_t handle,
                                               miopenSolution_t solution,
                                               size_t nInputs,
                                               const miopenTensorArgument_t* tensors,
                                               void* workspace,
                                               size_t workspaceSize);

/*! @brief Destroys solution object.
 *
 * @param solution   Solution to destroy
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenDestroySolution(miopenSolution_t solution);

/*! @brief Loads solution object from binary data.
 *
 * @param solution   Pointer to the solution to load
 * @param data       Data to load the solution from
 * @param size       Size of the solution blob
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenLoadSolution(miopenSolution_t* solution,
                                                const char* data,
                                                size_t size);

/*! @brief Saves a solution object as binary data.
 *
 * @param solution   Solution to save
 * @param data       Pointer to a buffer to save solution to
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSaveSolution(miopenSolution_t solution, char* data);

/*! @brief Reads the expected size of a solution.
 *
 * @param solution   Solution to get size
 * @param size       Pointer to a location where to write the size of the solution blob
 * @return           miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSolutionSize(miopenSolution_t solution, size_t* size);

/*! @brief Reads the amount of workspace required to execute the solution.
 *
 * @param solution      Solution to get required workspace size
 * @param workspaceSize Pointer to a location where to write the workspace size
 * @return              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSolutionWorkspaceSize(miopenSolution_t solution,
                                                            size_t* workspaceSize);

/*! @brief Reads the time spent to execute the solution the last it was run.
 *
 * @param solution Solution to get execution time
 * @param time     Pointer to a location where to write the execution time
 * @return         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSolutionTime(miopenSolution_t solution, float* time);

/*! @brief Reads id of the solver referred by the solution.
 *
 * @param solution Solution to get solver id from
 * @param solverId Pointer to a location where to write the solver id
 * @return         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSolutionSolverId(miopenSolution_t solution,
                                                       uint64_t* solverId);

/*! @brief Gets the convolution algorithm implemented by a solver.
 *
 * @param solverId Solver id to get convolution algorithm of
 * @param result   Pointer to a location where to write the algorithm
 * @return         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetSolverIdConvAlgorithm(uint64_t solverId,
                                                            miopenConvAlgorithm_t* result);

#ifdef MIOPEN_BETA_API

/*! @brief Initializes a problem object describing an activation operation.
 * @note As of now there is no way to actually get any solution for this kind of problems.
 *
 * @param problem      Pointer to the problem to initialize
 * @param operatorDesc Descriptor of the operator to be used
 * @param direction    Direction of the operation
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenCreateActivationProblem(miopenProblem_t* problem,
                              miopenActivationDescriptor_t operatorDesc,
                              miopenProblemDirection_t direction);

/*! @brief Initializes a problem object describing an activation operation.
 * @note As of now there is no way to actually get any solution for this kind of problems.
 *
 * @param problem   Pointer to the problem to initialize
 * @param mode      Batchnorm mode
 * @param direction Direction of the operation
 * @return          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateBatchnormProblem(miopenProblem_t* problem,
                                                          miopenBatchNormMode_t mode,
                                                          bool runningMeanVariance,
                                                          miopenProblemDirection_t direction);

/*! @brief Fuse two problems into a single one. Problems can be either regular, or fused. No
 * problems are disposed in the process, so the problem2 should be destroyed manually if it is not
 * needed anymore.
 * @details
 * miopenProblem_t problem = makeSomeProblem1();\n
 * miopenProblem_t problem2 = makeSomeProblem2();\n
 * miopenProblem_t problem3 = makeSomeProblem3();\n
 * miopenFuseProblems(problem, problem2);\n
 * // Now problem contains {problem1, problem2}\n
 * miopenFuseProblems(problem, problem3);\n
 * // Now problem contains {problem1, problem2, problem3}\n
 * miopenDestroyProblem(problem2);\n
 * miopenDestroyProblem(problem3);
 * @note As of now there is no way to actually get any solution for this kind of problem.
 *
 * @param problem1     The first problem to fuse. The result would be stored here.
 * @param problem2     The second problem to fuse.
 * @return             miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenFuseProblems(miopenProblem_t problem1, miopenProblem_t problem2);

/*! @brief Initializes a problem object describing an bias operation.
 * @note As of now there is no way to actually get any solution for this kind of problems.
 *
 * @param problem        Pointer to the problem to initialize
 * @param direction      Direction of the operation
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenCreateBiasProblem(miopenProblem_t* problem,
                                                     miopenProblemDirection_t direction);

/*! @brief Initializes a problem object describing a softmax operation.
 *
 * @param problem      Pointer to the problem to initialize
 * @param operatorDesc Descriptor of the operator to be used
 * @param direction    Direction of the operation
 * @return             miopenStatus_t
 */

MIOPEN_EXPORT miopenStatus_t miopenCreateSoftmaxProblem(miopenProblem_t* problem,
                                                        miopenSoftmaxDescriptor_t operatorDesc,
                                                        miopenProblemDirection_t direction);

#endif

/** @} */
// CLOSEOUT find2 DOXYGEN GROUP

#ifdef MIOPEN_BETA_API

/*! @ingroup ReduceCalculation
 * @enum miopenReduceCalculationNanPropagation_t
 * Nan numbers propagation modes for reduce calculation
 */
typedef enum
{
    MIOPEN_REDUCE_CALCULATION_NOT_PROPAGATE_NAN = 0, /*!< does not propagate NaN number */
    MIOPEN_REDUCE_CALCULATION_PROPAGATE_NAN =
        1, /*!< propagate the NaN number by the Reduction operation */
} miopenReduceCalculationNanPropagation_t;

// ReduceCalculation APIs
/** @addtogroup reducecalculation
 *
 *  @{
 */

/*! @enum miopenReduceCalculationOp_t
 * Reduction Calculation operation types
 */
typedef enum
{
    MIOPEN_REDUCE_CALCULATION_PROD =
        1, /*!< the operation is multiplying the values of the reduced elements */
    MIOPEN_REDUCE_CALCULATION_SUM =
        2, /*!< the operation is adding the values of the reduced elements */
} miopenReduceCalculationOp_t;

/*! @brief Helper function to query the minimum workspace size required by the ReduceTensor call
 *
 * @param [in]   handle                   MIOpen Handle
 * @param [in]   xDesc                    Tensor descriptor for data input tensor x
 * @param [in]   dim                      Dimension to calculation.
 * @param [in]   yDesc                    Tensor descriptor for output data tensor y
 * @param [out]  sizeInBytes              Pointer to data to return the minimum workspace size
 * @return                                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetReduceCalculationWorkspaceSize(miopenHandle_t handle,
                                        const miopenTensorDescriptor_t xDesc,
                                        const int32_t dim,
                                        const miopenReduceCalculationOp_t reduceCalculationOp,
                                        const miopenTensorDescriptor_t reduceDesc,
                                        size_t* sizeInBytes);

/*! @brief Execute a reducecalculation forward layer
 *
 * @param [in]   handle                   MIOpen handle
 * @param [in]   nanPropagation           NaN number propagation mode
 * @param [in]   workspace                Address of the allocated workspace data
 * @param [in]   workspaceSizeInBytes     Size in bytes of the allocated workspace data
 * @param [in]   xDesc                    Tensor descriptor for data input tensor x
 * @param [in]   x                        Data tensor x
 * @param [in]   dim                      Dimension to calculation.
 * @param [in]   yDesc                    Tensor descriptor for output data tensor y
 * @param [out]  y                        Data tensor y
 * @return                                miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenReduceCalculationForward(miopenHandle_t handle,
                               miopenReduceCalculationNanPropagation_t nanPropagation,
                               void* workspace,
                               size_t workspaceSizeInBytes,
                               const miopenTensorDescriptor_t xDesc,
                               const void* x,
                               const int32_t dim,
                               const miopenReduceCalculationOp_t reduceCalculationOp,
                               const miopenTensorDescriptor_t reduceDesc,
                               void* y);

/** @} */
// CLOSEOUT REDUCE CALCULATION DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API

/*! @ingroup ReduceExtreme
 * @enum miopenReduceExtremeOp_t
 * Reduction Extreme operation types
 */
typedef enum
{
    MIOPEN_REDUCE_EXTREME_ARGMIN =
        1, /*!< the operation is getting the minimum index of the reduced elements */
    MIOPEN_REDUCE_EXTREME_ARGMAX =
        2, /*!< the operation is getting the maximum index of the reduced elements */
    MIOPEN_REDUCE_EXTREME_MIN =
        3, /*!< the operation is getting the minimum value and index of the reduced elements */
    MIOPEN_REDUCE_EXTREME_MAX =
        4, /*!< the operation is getting the maximum value and index of the reduced elements */
} miopenReduceExtremeOp_t;

// ReduceExtreme APIs
/** @addtogroup ReduceExtreme
 *
 *  @{
 */

/*! @brief Find the the extreme (minimum, maximum) value and index of a tensor across Dimension.
 *
 * @param handle                   MIOpen handle (input)
 * @param xDesc                    Tensor descriptor for data input tensor x (input)
 * @param x                        Data tensor x (input)
 * @param dim                      Dimension to reduce argmax. (input)
 * @param reduceExtremeOp          Enumerant specifying the operation used by ReduceExtreme (input)
 * @param yDesc                    Tensor descriptor for reduce data tensor y (input)
 * @param y                        Data tensor y (output)
 * @param indiceDesc               Tensor descriptor for reduce data tensor indice only int32_t
 * (input)
 * @param indice                   Data tensor indice (output)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenReduceExtremeForward(miopenHandle_t handle,
                           const miopenTensorDescriptor_t xDesc,
                           const void* x,
                           const int32_t dim,
                           const miopenReduceExtremeOp_t reduceExtremeOp,
                           const miopenTensorDescriptor_t yDesc,
                           void* y,
                           const miopenTensorDescriptor_t indiceDesc,
                           void* indice);

/** @} */
// CLOSEOUT REDUCEEXTREME DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// GroupNorm APIs
/** @addtogroup groupnorm
 *
 *  @{
 */
/*! @brief Execute a groupnorm forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param mode           GroupNorm mode (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param weightDesc     Tensor descriptor for data input tensor weight (input)
 * @param weight         Data tensor weight (input)
 * @param biasDesc       Tensor descriptor for data input tensor bias (input)
 * @param bias           Data tensor bias (input)
 * @param num_groups     Number of groups to separate the channels into (input)
 * @param epsilon        Value to stabilize inverse variance calculation (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param meanDesc       Tensor descriptor for output data tensor mean (input)
 * @param mean           Data tensor mean (output)
 * @param rstdDesc       Tensor descriptor for output data tensor rstd (input)
 * @param rstd           Data tensor rstd (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGroupNormForward(miopenHandle_t handle,
                                                    miopenNormMode_t mode,
                                                    const miopenTensorDescriptor_t xDesc,
                                                    const void* x,
                                                    const miopenTensorDescriptor_t weightDesc,
                                                    const void* weight,
                                                    const miopenTensorDescriptor_t biasDesc,
                                                    const void* bias,
                                                    const uint64_t num_groups,
                                                    const float epsilon,
                                                    const miopenTensorDescriptor_t yDesc,
                                                    void* y,
                                                    const miopenTensorDescriptor_t meanDesc,
                                                    void* mean,
                                                    const miopenTensorDescriptor_t rstdDesc,
                                                    void* rstd);

/** @} */
// CLOSEOUT groupnorm DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// LayerNorm APIs
/** @addtogroup layernorm
 *
 *  @{
 */
/*! @brief Execute a add and layernorm forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param mode           LayerNorm mode (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param x2Desc         Tensor descriptor for data input tensor x2 (input)
 * @param x2             Data tensor x2 (input)
 * @param weightDesc     Tensor descriptor for data input tensor weight (input)
 * @param weight         Data tensor weight (input)
 * @param biasDesc       Tensor descriptor for data input tensor bias (input)
 * @param bias           Data tensor bias (input)
 * @param epsilon        Value to stabilize inverse variance calculation (input)
 * @param normalized_dim Normalized dimensions in the input array (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param meanDesc       Tensor descriptor for output data tensor mean (input)
 * @param mean           Data tensor mean (output)
 * @param rstdDesc       Tensor descriptor for output data tensor rstd (input)
 * @param rstd           Data tensor rstd (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenAddLayerNormForward(miopenHandle_t handle,
                                                       miopenNormMode_t mode,
                                                       const miopenTensorDescriptor_t xDesc,
                                                       const void* x,
                                                       const miopenTensorDescriptor_t x2Desc,
                                                       const void* x2,
                                                       const miopenTensorDescriptor_t weightDesc,
                                                       const void* weight,
                                                       const miopenTensorDescriptor_t biasDesc,
                                                       const void* bias,
                                                       const float epsilon,
                                                       const int32_t normalized_dim,
                                                       const miopenTensorDescriptor_t yDesc,
                                                       void* y,
                                                       const miopenTensorDescriptor_t meanDesc,
                                                       void* mean,
                                                       const miopenTensorDescriptor_t rstdDesc,
                                                       void* rstd);

/** @} */
// CLOSEOUT LAYERNORM DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// LayerNorm APIs
/** @addtogroup layernorm
 *
 *  @{
 */
/*! @brief Execute a T5layernorm forward layer
 *
 * @param handle         MIOpen handle (input)
 * @param mode           LayerNorm mode (input)
 * @param xDesc          Tensor descriptor for data input tensor x (input)
 * @param x              Data tensor x (input)
 * @param weightDesc     Tensor descriptor for data input tensor weight (input)
 * @param weight         Data tensor weight (input)
 * @param epsilon        Value to stablize inverse variance calculation (input)
 * @param yDesc          Tensor descriptor for output data tensor y (input)
 * @param y              Data tensor y (output)
 * @param rstdDesc       Tensor descriptor for output data tensor rstd (input)
 * @param rstd           Data tensor rstd (output)
 * @return               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenT5LayerNormForward(miopenHandle_t handle,
                                                      miopenNormMode_t mode,
                                                      const miopenTensorDescriptor_t xDesc,
                                                      const void* x,
                                                      const miopenTensorDescriptor_t weightDesc,
                                                      const void* weight,
                                                      const float epsilon,
                                                      const miopenTensorDescriptor_t yDesc,
                                                      void* y,
                                                      const miopenTensorDescriptor_t rstdDesc,
                                                      void* rstd);

/*! @brief Helper function to query the minimum workspace size required by the T5layernorm backward
 * call
 *
 * @param handle                   MIOpen Handle (input)
 * @param mode                     LayerNorm mode (input)
 * @param dyDesc                   Tensor descriptor for data input tensor dy (input)
 * @param xDesc                    Tensor descriptor for data input tensor x (input)
 * @param weightDesc               Tensor descriptor for data input tensor weight (input)
 * @param rstdDesc                 Tensor descriptor for data input tensor rstd (input)
 * @param dxDesc                   Tensor descriptor for output data tensor dx (input)
 * @param dwDesc                   Tensor descriptor for output data tensor dw (input)
 * @param sizeInBytes              Pointer to data to return the minimum workspace size
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetT5LayerNormBackwardWorkspaceSize(miopenHandle_t handle,
                                          miopenNormMode_t mode,
                                          const miopenTensorDescriptor_t dyDesc,
                                          const miopenTensorDescriptor_t xDesc,
                                          const miopenTensorDescriptor_t weightDesc,
                                          const miopenTensorDescriptor_t rstdDesc,
                                          const miopenTensorDescriptor_t dxDesc,
                                          const miopenTensorDescriptor_t dwDesc,
                                          size_t* sizeInBytes);

/*! @brief Execute a T5layernorm backward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param mode                     LayerNorm mode (input)
 * @param workspace                Address of the allocated workspace data (input)
 * @param workspaceSizeInBytes     Size in bytes of the allocated workspace data (input)
 * @param dyDesc                   Tensor descriptor for data input tensor dy (input)
 * @param dy                       Data tensor dy (input)
 * @param xDesc                    Tensor descriptor for output data tensor x (input)
 * @param x                        Data tensor x (input)
 * @param weightDesc               Tensor descriptor for data input tensor weight (input)
 * @param weight                   Data tensor weight (input)
 * @param rstdDesc                 Tensor descriptor for output data tensor rstd (input)
 * @param rstd                     Data tensor rstd (output)
 * @param dxDesc                   Tensor descriptor for output data tensor dx (input)
 * @param dx                       Data tensor dx (output)
 * @param dwDesc                   Tensor descriptor for output data tensor dw (input)
 * @param dw                       Data tensor dw (output)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenT5LayerNormBackward(miopenHandle_t handle,
                                                       miopenNormMode_t mode,
                                                       void* workspace,
                                                       size_t workspaceSizeInBytes,
                                                       const miopenTensorDescriptor_t dyDesc,
                                                       const void* dy,
                                                       const miopenTensorDescriptor_t xDesc,
                                                       const void* x,
                                                       const miopenTensorDescriptor_t weightDesc,
                                                       const void* weight,
                                                       const miopenTensorDescriptor_t rstdDesc,
                                                       const void* rstd,
                                                       const miopenTensorDescriptor_t dxDesc,
                                                       void* dx,
                                                       const miopenTensorDescriptor_t dwDesc,
                                                       void* dw);
/** @} */
// CLOSEOUT LAYERNORM DOXYGEN GROUP
#endif // MIOPEN_BETA_API

/*! @brief Enum for specifying the alpha-beta case for convolution operations.
 *
 * Describes how alpha and beta scaling factors are applied in convolution operations.
 */
typedef enum
{
    /* IDENTITY      alpha = 1.0 and beta = 0.0 */
    /* SCALE         alpha = 4.2 and beta = 0.0 */
    /* BILINEAR      alpha = 3.2 and beta = 1.1 */
    /* ERROR_STATE   alpha = 0.0 and beta = 3.1 */

    DEFAULT     = 0, /* alpha = 1.0 and beta = 0.0.*/
    SCALE       = 1, /* alpha with some value and beta 0.0*/
    BILINEAR    = 2, /* both alpha and beta with some value*/
    ERROR_STATE = 3  /* alpha 0.0 and beta with some value, this should not occur.
                        But used to check for errors.*/
} miopenAlphaBetaCase_t;

#ifdef MIOPEN_BETA_API
// FusedAdam APIs
/** @addtogroup SGD
 *
 *  @{
 */
/*! @brief Perform Fused Adam optimization for a single tensor (Adaptive Moment Estimation).
 *
 * This function implements the Fused Adam optimization algorithm. Adam, short for Adaptive Moment
 * Estimation, extends the RMSProp optimizer. It combines the advantages of AdaGrad and RMSProp by
 * adaptively adjusting learning rates for each parameter using the first and second moments of
 * gradients. Fused Adam optimization efficiently combines multiple operations into a single kernel,
 * reducing memory access overhead and improving performance.
 *
 * Additionally, Fused Adam can be utilized in both adam w and Automatic Mixed Precision (AMP),
 * enabling accelerated model training and reduced memory consumption. AMP supports FP16
 * computation, optimizing model calculations using a mixture of FP32 and FP16 precision to enhance
 * training speed. When utilizing AMP, FoundInf, ScaleGrad, and step tensors should be employed. In
 * AMP mode, the execution of Adam is determined based on the FoundInf value. State Step accepts
 * both int values and int tensors. If a Step tensor is employed, the step received as an int is
 * disregarded, and if Adam is executed, the step tensor is incremented by 1.
 *
 * @code
 * // Execute Adam
 * miopenFusedAdam(handle,
 *                 paramDesc,
 *                 param,
 *                 gradDesc,
 *                 grad,
 *                 expAvgDesc,
 *                 expAvg,
 *                 expAvgSqDesc,
 *                 expAvgSq,
 *                 NULL,     // Unused maxExpAvgSqDesc because amsgrad is false
 *                 NULL,
 *                 NULL,     // Unused stateStep Tensor because use step integer argument
 *                 NULL,
 *                 step,
 *                 lr,
 *                 beta1,
 *                 beta2,
 *                 weight_decay,
 *                 eps,
 *                 false,    // amsgrad
 *                 false,    // maximize
 *                 false,    // adamw
 *                 NULL,     // Unused gradScale Tensor because not amp
 *                 NULL,
 *                 NULL,     // Unused foundInf Tensor because not amp
 *                 NULL);
 *
 * // Execute AdamW
 * miopenFusedAdam(handle,
 *                 paramDesc,
 *                 param,
 *                 gradDesc,
 *                 grad,
 *                 expAvgDesc,
 *                 expAvg,
 *                 expAvgSqDesc,
 *                 expAvgSq,
 *                 NULL,     // Unused maxExpAvgSqDesc because amsgrad is false
 *                 NULL,
 *                 NULL,     // Unused stateStep Tensor because use step integer argument
 *                 NULL,
 *                 step,
 *                 lr,
 *                 beta1,
 *                 beta2,
 *                 weight_decay,
 *                 eps,
 *                 false,    // amsgrad
 *                 false,    // maximize
 *                 true,     // adamw
 *                 NULL,     // Unused gradScale Tensor because not amp
 *                 NULL,
 *                 NULL,     // Unused foundInf Tensor because not amp
 *                 NULL);
 *
 * // Execute AMP Adam
 * miopenFusedAdam(handle,
 *                 paramDesc,
 *                 param,
 *                 gradDesc,
 *                 grad,
 *                 expAvgDesc,
 *                 expAvg,
 *                 expAvgSqDesc,
 *                 expAvgSq,
 *                 NULL,     // Unused maxExpAvgSqDesc because amsgrad is false
 *                 NULL,
 *                 stateStepDesc,
 *                 stateStep,
 *                 -1,       // Ignore step value because stateStep Tensor is used
 *                 lr,
 *                 beta1,
 *                 beta2,
 *                 weight_decay,
 *                 eps,
 *                 false,    // amsgrad
 *                 false,    // maximize
 *                 false,    // adamw
 *                 gradScaleDesc,
 *                 gradScale,
 *                 foundInfDesc,
 *                 foundInf);
 * @endcode
 *
 * @param handle              MIOpen handle (input)
 * @param paramDesc           Tensor descriptor for the input parameter tensor (input)
 * @param param               Input parameter tensor (input)
 * @param gradDesc            Tensor descriptor for the input gradient tensor (input)
 * @param grad                Input gradient tensor (input)
 * @param expAvgDesc          Tensor descriptor for the input exponential moving average tensor
 *                            (input)
 * @param expAvg              Input exponential moving average tensor (input)
 * @param expAvgSqDesc        Tensor descriptor for the input exponential moving average squared
 *                            tensor (input)
 * @param expAvgSq            Input exponential moving average squared tensor (input)
 * @param maxExpAvgSqDesc     Tensor descriptor for the input maximum exponential moving average
 *                            squared tensor. Used when amsgrad is true (input, optional)
 * @param maxExpAvgSq         Input maximum exponential moving average squared tensor. Used when
 *                            amsgrad is true (input, optional)
 * @param stateStepDesc       Tensor descriptor for the input state step tensor (input)
 * @param stateStep           Input state step tensor (input)
 * @param state_step          Input state step. used when the step tensor is null (input)
 * @param lr                  Learning rate (input)
 * @param beta1               Coefficient used for computing the first moment running average of
 *                            gradient (input)
 * @param beta2               Coefficient used for computing the second moment running average of
 *                            gradient (input)
 * @param weight_decay        Weight decay (input)
 * @param eps                 Term added to the denominator to improve numerical stability (input)
 * @param amsgrad             Flag indicating whether to use the AMSGrad variant of Adam (input)
 * @param maximize            Flag indicating whether to maximize the objective with respect to the
 *                            parameters (input)
 * @param adamw               If true, the operation becomes AdamW (input)
 * @param gradScaleDesc       Tensor descriptor for the input grad scale tensor (input, optional)
 * @param gradScale           Input grad scale tensor (input, optional)
 * @param foundInfDesc        Tensor descriptor for the input found inf tensor (input, optional)
 * @param foundInf            Tensor indicating the presence of inf or NaN in gradients. If true,
 *                            skips operation and step update (input, optional)
 * @return                    miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenFusedAdam(miopenHandle_t handle,
                                             const miopenTensorDescriptor_t paramDesc,
                                             void* param,
                                             const miopenTensorDescriptor_t gradDesc,
                                             const void* grad,
                                             const miopenTensorDescriptor_t expAvgDesc,
                                             void* expAvg,
                                             const miopenTensorDescriptor_t expAvgSqDesc,
                                             void* expAvgSq,
                                             const miopenTensorDescriptor_t maxExpAvgSqDesc,
                                             void* maxExpAvgSq,
                                             const miopenTensorDescriptor_t stateStepDesc,
                                             void* stateStep,
                                             const unsigned int state_step,
                                             const float lr,
                                             const float beta1,
                                             const float beta2,
                                             const float weight_decay,
                                             const float eps,
                                             const bool amsgrad,
                                             const bool maximize,
                                             const bool adamw,
                                             const miopenTensorDescriptor_t gradScaleDesc,
                                             const void* gradScale,
                                             const miopenTensorDescriptor_t foundInfDesc,
                                             const void* foundInf);

/*! @brief Execute single tensor Adam optimization and receive the result in a separate output
 * tensor.
 *
 * This function is equivalent to miopenFusedAdam but receives the result in a separate output
 * tensor.
 * @see miopenFusedAdam
 *
 * @code
 * // Execute Adam
 * miopenFusedAdamWithOutput(handle,
 *                           paramInDesc,
 *                           paramIn,
 *                           paramOutDesc,
 *                           paramOut,
 *                           NULL,   // Unused paramOutFloat16 tensor because is not amp
 *                           NULL,
 *                           gradInDesc,
 *                           gradIn,
 *                           expAvgInDesc,
 *                           expAvgIn,
 *                           expAvgOutDesc,
 *                           expAvgOut,
 *                           expAvgInSqDesc,
 *                           expAvgSqIn,
 *                           expAvgSqOutDesc,
 *                           expAvgSqOut,
 *                           NULL,   // Unused maxExpAvgSqIn tensor because amsgrad is false
 *                           NULL,
 *                           NULL,   // Unused maxExpAvgSqOut tensor because amsgrad is false
 *                           NULL,
 *                           NULL,   // Unused stateStepIn tensor because use step integer argument
 *                           NULL,
 *                           NULL,   // Unused stateStepOut tensor because use step integer argument
 *                           NULL,
 *                           step,
 *                           lr,
 *                           beta1,
 *                           beta2,
 *                           weight_decay,
 *                           eps,
 *                           false,  // amsgrad
 *                           false,  // maximize
 *                           false,  // adamw
 *                           NULL,   // Unused gradScale Tensor because not amp
 *                           NULL,
 *                           NULL,   // Unused foundInf Tensor because not amp
 *                           NULL);
 *
 * // Execute Amp Adam
 * miopenFusedAdamWithOutput(handle,
 *                           paramInDesc,
 *                           paramIn,
 *                           paramOutDesc,
 *                           paramOut,
 *                           paramOutFloat16Desc,  // paramOutFloat16 tensor is optional in amp
 *                           paramOutFloat16,
 *                           gradInDesc,
 *                           gradIn,
 *                           expAvgInDesc,
 *                           expAvgIn,
 *                           expAvgOutDesc,
 *                           expAvgOut,
 *                           expAvgInSqDesc,
 *                           expAvgSqIn,
 *                           expAvgSqIn,
 *                           expAvgSqOutDesc,
 *                           expAvgSqOut,
 *                           NULL,         // Unused maxExpAvgSqIn tensor because amsgrad is false
 *                           NULL,
 *                           NULL,         // Unused maxExpAvgSqOut tensor because amsgrad is false
 *                           NULL,
 *                           stateStepInDesc,
 *                           stateStepIn,
 *                           stateStepOutDesc,
 *                           stateStepOut
 *                           -1,           // Ignore step value because stateStep Tensor is used
 *                           lr, beta1, beta2, weight_decay, eps,
 *                           false,        // amsgrad
 *                           false,        // maximize
 *                           false,        // adamw
 *                           gradScaleDesc,
 *                           gradScale,
 *                           foundInfDesc,
 *                           foundInf);
 * @endcode
 *
 * @param handle              MIOpen handle (input)
 * @param paramInDesc         Tensor descriptor for the input parameter tensor (input)
 * @param paramIn             Input parameter tensor (input)
 * @param paramOutDesc        Tensor descriptor for the output parameter tensor (input)
 * @param paramOut            Output parameter tensor (output)
 * @param paramOutFloat16Desc Tensor descriptor for the output parameter tensor float16 (input,
 *                            optional)
 * @param paramOutFloat16     Output parameter tensor (output, optional)
 * @param gradInDesc          Tensor descriptor for the input gradient tensor (input)
 * @param gradIn              Input gradient tensor (input)
 * @param expAvgInDesc        Tensor descriptor for the input exponential moving average tensor
 *                            (input)
 * @param expAvgIn            Input exponential moving average tensor (input)
 * @param expAvgOutDesc       Tensor descriptor for the output exponential moving average tensor
 *                            (input)
 * @param expAvgOut           Output exponential moving average tensor (output)
 * @param expAvgSqInDesc      Tensor descriptor for the input exponential moving average squared
 *                            tensor (input)
 * @param expAvgSqIn          Input exponential moving average squared tensor (input)
 * @param expAvgSqOutDesc     Tensor descriptor for the output exponential moving average squared
 *                            tensor (input)
 * @param expAvgSqOut         Output exponential moving average squared tensor (output)
 * @param maxExpAvgSqInDesc   Tensor descriptor for the input maximum exponential moving average
 *                            squared tensor. Used when amsgrad is true (input, optional)
 * @param maxExpAvgSqIn       Input maximum exponential moving average squared tensor. Used when
 *                            amsgrad is true (input, optional)
 * @param maxExpAvgSqOutDesc  Tensor descriptor for the output maximum exponential moving average
 *                            squared tensor. Used when amsgrad is true (input, optional)
 * @param maxExpAvgSqOut      Output maximum exponential moving average squared tensor. Used when
 *                            amsgrad is true (output, optional)
 * @param stateStepInDesc     Tensor descriptor for the input state step tensor (input, optional)
 * @param stateStepIn         Input state step tensor (input, optional)
 * @param stateStepOutDesc    Tensor descriptor for the output state step tensor (input, optional)
 * @param stateStepOut        Output state step tensor that stores the updated step value. (output,
 *                            optional)
 * @param state_step          Input state step, It is used when the step tensor is null. (input)
 * @param lr                  Learning rate (input)
 * @param beta1               Coefficient used for computing the first moment running average of
 *                            gradient (input)
 * @param beta2               Coefficient used for computing the second moment running average of
 *                            gradient (input)
 * @param weight_decay        Weight decay (input)
 * @param eps                 Term added to the denominator to improve numerical stability (input)
 * @param amsgrad             Flag indicating whether to use the AMSGrad variant of Adam (input)
 * @param maximize            Flag indicating whether to maximize the objective with respect to the
 *                            parameters (input)
 * @param adamw               If it is true, the operation becomes AdamW (input)
 * @param gradScaleDesc       Tensor descriptor for the input grad scale tensor (input, optional)
 * @param gradScale           Input grad scale tensor (input, optional)
 * @param foundInfDesc        Tensor descriptor for the input found inf tensor (input, optional)
 * @param foundInf            Tensor indicating presence of inf or NaN in gradients. If true, skips
 *                            operation and step update. (input, optional)
 * @return                    miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenFusedAdamWithOutput(miopenHandle_t handle,
                          const miopenTensorDescriptor_t paramInDesc,
                          void* paramIn,
                          const miopenTensorDescriptor_t paramOutDesc,
                          void* paramOut,
                          const miopenTensorDescriptor_t paramOutFloat16Desc,
                          void* paramOutFloat16,
                          const miopenTensorDescriptor_t gradInDesc,
                          const void* gradIn,
                          const miopenTensorDescriptor_t expAvgInDesc,
                          void* expAvgIn,
                          const miopenTensorDescriptor_t expAvgOutDesc,
                          void* expAvgOut,
                          const miopenTensorDescriptor_t expAvgSqInDesc,
                          void* expAvgSqIn,
                          const miopenTensorDescriptor_t expAvgSqOutDesc,
                          void* expAvgSqOut,
                          const miopenTensorDescriptor_t maxExpAvgSqInDesc,
                          void* maxExpAvgSqIn,
                          const miopenTensorDescriptor_t maxExpAvgSqOutDesc,
                          void* maxExpAvgSqOut,
                          const miopenTensorDescriptor_t stateStepInDesc,
                          void* stateStepIn,
                          const miopenTensorDescriptor_t stateStepOutDesc,
                          void* stateStepOut,
                          const unsigned int state_step,
                          const float lr,
                          const float beta1,
                          const float beta2,
                          const float weight_decay,
                          const float eps,
                          const bool amsgrad,
                          const bool maximize,
                          const bool adamw,
                          const miopenTensorDescriptor_t gradScaleDesc,
                          const void* gradScale,
                          const miopenTensorDescriptor_t foundInfDesc,
                          const void* foundInf);

/** @} */
// CLOSEOUT SGD DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// TransformersAdamW APIs
/** @addtogroup SGD
 *
 *  @{
 */
/*! @brief Implements Adam algorithm with weight decay fix as introduced in
 * <a href="https://arxiv.org/abs/1711.05101">Decoupled Weight Decay Regularization</a>.
 * This is the fused kernel version of AdamW included in the Hugging Face Transformers module.
 *
 * @see miopenFusedAdam
 *
 * @code
 * // Execute Adam
 * miopenTransformersAdamW(handle,
 *                         paramDesc,
 *                         param,
 *                         gradDesc,
 *                         grad,
 *                         expAvgDesc,
 *                         expAvg,
 *                         expAvgSqDesc,
 *                         expAvgSq,
 *                         NULL,     // Unused stateStep Tensor because use step integer argument
 *                         NULL,
 *                         step,
 *                         lr,
 *                         beta1,
 *                         beta2,
 *                         weight_decay,
 *                         eps,
 *                         true,     // correct_bias
 *                         NULL,     // Unused gradScale Tensor because not amp
 *                         NULL,
 *                         NULL,     // Unused foundInf Tensor because not amp
 *                         NULL);
 *
 * // Execute AMP Adam
 * miopenTransformersAdamW(handle,
 *                         paramDesc,
 *                         param,
 *                         gradDesc,
 *                         grad,
 *                         expAvgDesc,
 *                         expAvg,
 *                         expAvgSqDesc,
 *                         expAvgSq,
 *                         stateStepDesc,
 *                         stateStep,
 *                         -1,       // Ignore step value because stateStep Tensor is used
 *                         lr,
 *                         beta1,
 *                         beta2,
 *                         weight_decay,
 *                         eps,
 *                         true,     // correct_bias
 *                         gradScaleDesc,
 *                         gradScale,
 *                         foundInfDesc,
 *                         foundInf);
 * @endcode
 *
 * @param handle              MIOpen handle (input)
 * @param paramDesc           Tensor descriptor for the input parameter tensor (input)
 * @param param               Input parameter tensor (input)
 * @param gradDesc            Tensor descriptor for the input gradient tensor (input)
 * @param grad                Input gradient tensor (input)
 * @param expAvgDesc          Tensor descriptor for the input exponential moving average tensor
 *                            (input)
 * @param expAvg              Input exponential moving average tensor (input)
 * @param expAvgSqDesc        Tensor descriptor for the input exponential moving average squared
 *                            tensor (input)
 * @param expAvgSq            Input exponential moving average squared tensor (input)
 * @param stateStepDesc       Tensor descriptor for the input state step tensor (input)
 * @param stateStep           Input state step tensor (input)
 * @param state_step          Input state step. used when the step tensor is null (input)
 * @param lr                  Learning rate (input)
 * @param beta1               Coefficient used for computing the first moment running average of
 *                            gradient (input)
 * @param beta2               Coefficient used for computing the second moment running average of
 *                            gradient (input)
 * @param weight_decay        Weight decay (input)
 * @param eps                 Term added to the denominator to improve numerical stability (input)
 * @param correct_bias        Whether or not to correct bias in Adam (for instance, in Bert TF
 *                            repository they use False).
 * @param gradScaleDesc       Tensor descriptor for the input grad scale tensor (input, optional)
 * @param gradScale           Input grad scale tensor (input, optional)
 * @param foundInfDesc        Tensor descriptor for the input found inf tensor (input, optional)
 * @param foundInf            Tensor indicating the presence of inf or NaN in gradients. If true,
 *                            skips operation and step update (input, optional)
 * @return                    miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenTransformersAdamW(miopenHandle_t handle,
                                                     const miopenTensorDescriptor_t paramDesc,
                                                     void* param,
                                                     const miopenTensorDescriptor_t gradDesc,
                                                     const void* grad,
                                                     const miopenTensorDescriptor_t expAvgDesc,
                                                     void* expAvg,
                                                     const miopenTensorDescriptor_t expAvgSqDesc,
                                                     void* expAvgSq,
                                                     const miopenTensorDescriptor_t stateStepDesc,
                                                     void* stateStep,
                                                     const unsigned int state_step,
                                                     const float lr,
                                                     const float beta1,
                                                     const float beta2,
                                                     const float weight_decay,
                                                     const float eps,
                                                     const bool correct_bias,
                                                     const miopenTensorDescriptor_t gradScaleDesc,
                                                     const void* gradScale,
                                                     const miopenTensorDescriptor_t foundInfDesc,
                                                     const void* foundInf);

/*! @brief Execute single tensor Adam optimization and receive the result in a separate output
 * tensor.
 *
 * This function is equivalent to miopenTransformersAdam but receives the result in a separate
 * output tensor.
 * @see miopenTransformersAdamW
 * @see miopenFusedAdamWithOutput
 *
 * @code
 * // Execute Adam
 * miopenTransformersAdamWWithOutput(handle,
 *                                   paramInDesc,
 *                                   paramIn,
 *                                   paramOutDesc,
 *                                   paramOut,
 *                                   NULL,   // Unused paramOutFloat16 tensor because is not amp
 *                                   NULL,
 *                                   gradInDesc,
 *                                   gradIn,
 *                                   expAvgInDesc,
 *                                   expAvgIn,
 *                                   expAvgOutDesc,
 *                                   expAvgOut,
 *                                   expAvgInSqDesc,
 *                                   expAvgSqIn,
 *                                   expAvgSqOutDesc,
 *                                   expAvgSqOut,
 *                                   NULL,   // Unused stateStepIn tensor because use step int
 *                                   NULL,
 *                                   NULL,   // Unused stateStepOut tensor because use step int
 *                                   NULL,
 *                                   step,
 *                                   lr,
 *                                   beta1,
 *                                   beta2,
 *                                   weight_decay,
 *                                   eps,
 *                                   -1,     // step_size
 *                                   true,   // correct_bias
 *                                   NULL,   // Unused gradScale Tensor because not amp
 *                                   NULL,
 *                                   NULL,   // Unused foundInf Tensor because not amp
 *                                   NULL);
 *
 * // Execute Amp Adam
 * miopenTransformersAdamWWithOutput(handle,
 *                                   paramInDesc,
 *                                   paramIn,
 *                                   paramOutDesc,
 *                                   paramOut,
 *                                   paramOutFloat16Desc,  // optional in amp
 *                                   paramOutFloat16,
 *                                   gradInDesc,
 *                                   gradIn,
 *                                   expAvgInDesc,
 *                                   expAvgIn,
 *                                   expAvgOutDesc,
 *                                   expAvgOut,
 *                                   expAvgInSqDesc,
 *                                   expAvgSqIn,
 *                                   expAvgSqIn,
 *                                   expAvgSqOutDesc,
 *                                   expAvgSqOut,
 *                                   stateStepInDesc,
 *                                   stateStepIn,
 *                                   stateStepOutDesc,
 *                                   stateStepOut
 *                                   -1,   // Ignore step value because stateStep Tensor is used
 *                                   lr,
 *                                   beta1,
 *                                   beta2,
 *                                   weight_decay,
 *                                   eps,
 *                                   -1,   // step_size
 *                                   true, // correct_bias
 *                                   NULL, // Unused gradScale Tensor because not amp
 *                                   NULL,
 *                                   NULL, // Unused foundInf Tensor because not amp
 *                                   NULL);
 * @endcode
 *
 * @param handle              MIOpen handle (input)
 * @param paramInDesc         Tensor descriptor for the input parameter tensor (input)
 * @param paramIn             Input parameter tensor (input)
 * @param paramOutDesc        Tensor descriptor for the output parameter tensor (input)
 * @param paramOut            Output parameter tensor (output)
 * @param paramOutFloat16Desc Tensor descriptor for the output parameter tensor float16 (input,
 *                            optional)
 * @param paramOutFloat16     Output parameter tensor (output, optional)
 * @param gradInDesc          Tensor descriptor for the input gradient tensor (input)
 * @param gradIn              Input gradient tensor (input)
 * @param expAvgInDesc        Tensor descriptor for the input exponential moving average tensor
 *                            (input)
 * @param expAvgIn            Input exponential moving average tensor (input)
 * @param expAvgOutDesc       Tensor descriptor for the output exponential moving average tensor
 *                            (input)
 * @param expAvgOut           Output exponential moving average tensor (output)
 * @param expAvgSqInDesc      Tensor descriptor for the input exponential moving average squared
 *                            tensor (input)
 * @param expAvgSqIn          Input exponential moving average squared tensor (input)
 * @param expAvgSqOutDesc     Tensor descriptor for the output exponential moving average squared
 *                            tensor (input)
 * @param expAvgSqOut         Output exponential moving average squared tensor (output)
 * @param stateStepInDesc     Tensor descriptor for the input state step tensor (input, optional)
 * @param stateStepIn         Input state step tensor (input, optional)
 * @param stateStepOutDesc    Tensor descriptor for the output state step tensor (input, optional)
 * @param stateStepOut        Output state step tensor that stores the updated step value. (output,
 *                            optional)
 * @param state_step          Input state step, It is used when the step tensor is null. (input)
 * @param lr                  Learning rate (input)
 * @param beta1               Coefficient used for computing the first moment running average of
 *                            gradient (input)
 * @param beta2               Coefficient used for computing the second moment running average of
 *                            gradient (input)
 * @param weight_decay        Weight decay (input)
 * @param eps                 Term added to the denominator to improve numerical stability (input)
 * @param step_size           Pre-calculated step_size, used for performance enhancement (input)
 * @param correct_bias        Whether or not to correct bias in Adam (for instance, in Bert TF
 *                            repository they use False) (input)
 * @param gradScaleDesc       Tensor descriptor for the input grad scale tensor (input, optional)
 * @param gradScale           Input grad scale tensor (input, optional)
 * @param foundInfDesc        Tensor descriptor for the input found inf tensor (input, optional)
 * @param foundInf            Tensor indicating presence of inf or NaN in gradients. If true, skips
 *                            operation and step update. (input, optional)
 * @return                    miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenTransformersAdamWWithOutput(miopenHandle_t handle,
                                  const miopenTensorDescriptor_t paramInDesc,
                                  void* paramIn,
                                  const miopenTensorDescriptor_t paramOutDesc,
                                  void* paramOut,
                                  const miopenTensorDescriptor_t paramOutFloat16Desc,
                                  void* paramOutFloat16,
                                  const miopenTensorDescriptor_t gradInDesc,
                                  const void* gradIn,
                                  const miopenTensorDescriptor_t expAvgInDesc,
                                  void* expAvgIn,
                                  const miopenTensorDescriptor_t expAvgOutDesc,
                                  void* expAvgOut,
                                  const miopenTensorDescriptor_t expAvgSqInDesc,
                                  void* expAvgSqIn,
                                  const miopenTensorDescriptor_t expAvgSqOutDesc,
                                  void* expAvgSqOut,
                                  const miopenTensorDescriptor_t stateStepInDesc,
                                  void* stateStepIn,
                                  const miopenTensorDescriptor_t stateStepOutDesc,
                                  void* stateStepOut,
                                  const unsigned int state_step,
                                  const float lr,
                                  const float beta1,
                                  const float beta2,
                                  const float weight_decay,
                                  const float eps,
                                  const float step_size,
                                  const bool correct_bias,
                                  const miopenTensorDescriptor_t gradScaleDesc,
                                  const void* gradScale,
                                  const miopenTensorDescriptor_t foundInfDesc,
                                  const void* foundInf);

/** @} */
// CLOSEOUT SGD DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// GetItem APIs
/** @addtogroup getitem
 *
 *  @{
 */
/*! @brief Helper function to query the minimum workspace size required by the getitem call
 *
 * @param [in]   handle                  MIOpen Handle
 * @param [in]   indexCount              Number of input tensor indexes
 * @param [in]   indexDescs              Tensor descriptor of input tensor indexes
 * @param [out]  sizeInBytes             Pointer to data to return the minimum workspace size
 * @return                        miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetGetitemWorkspaceSize(miopenHandle_t handle,
                              uint32_t indexCount,
                              const miopenTensorDescriptor_t* indexDescs,
                              size_t* sizeInBytes);

/*! @brief Execute a getitem backward layer
 *
 * Backward of getitem for tensor indexing, slicing, masking.
 *
 * @param [in]   handle                  MIOpen handle
 * @param [in]   workspace               Address of the allocated workspace data
 * @param [in]   workspaceSizeInBytes    Size in bytes of the allocated workspace data
 * @param [in]   dyDesc                  Tensor descriptor of input tensor dy
 * @param [in]   dy                      Source data tensor dy
 * @param [in]   indexCount              Number of input tensor indexs
 * @param [in]   indexDescs              Tensor descriptor of input tensor indexs(All indexs same
 * size)
 * @param [in]   indexs                  Source data tensor indexs
 * @param [in]   dxDesc                  Tensor descriptor of output tensor dx
 * @param [out]  dx                      Data tensor dx(It must be initialized to 0)
 * @param [in]   errorDesc               Tensor descriptor of output tensor error
 * @param [out]  error                   Data tensor error(It must be initialized to 0)
 * @param [in]   dimCount                Number of dimensions
 * @param [in]   dims                    Dimensions
 * @param [in]   sliceCount              Number of slices
 * @param [in]   slices                  Slices
 * @param [in]   offset                  Offset of output tensor dx
 * @return                               miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetitemBackward(miopenHandle_t handle,
                                                   void* workspace,
                                                   size_t workspaceSizeInBytes,
                                                   const miopenTensorDescriptor_t dyDesc,
                                                   const void* dy,
                                                   uint32_t indexCount,
                                                   const miopenTensorDescriptor_t* indexDescs,
                                                   const void* const* indexs,
                                                   const miopenTensorDescriptor_t dxDesc,
                                                   void* dx,
                                                   const miopenTensorDescriptor_t errorDesc,
                                                   void* error,
                                                   uint32_t dimCount,
                                                   const int32_t* dims,
                                                   uint32_t sliceCount,
                                                   const int32_t* slices,
                                                   uint32_t offset);

/** @} */
// CLOSEOUT GETITEM DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
// RotaryPositionalEmbeddings APIs
/** @addtogroup RotaryPositionalEmbeddings
 *
 *  @{
 */
/*! @brief Execute a rope forward layer
 *
 * @param [in]   handle         MIOpen handle
 * @param [in]   xDesc          Tensor descriptor for data input tensor x
 * @param [in]   x              Data tensor x
 * @param [in]   cosDesc        Tensor descriptor for data input tensor cos
 * @param [in]   cos            Data tensor cos
 * @param [in]   sinDesc        Tensor descriptor for data input tensor sin
 * @param [in]   sin            Data tensor sin
 * @param [in]   yDesc          Tensor descriptor for output data tensor y
 * @param [out]  y              Data tensor y
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRoPEForward(miopenHandle_t handle,
                                               const miopenTensorDescriptor_t xDesc,
                                               const void* x,
                                               const miopenTensorDescriptor_t cosDesc,
                                               const void* cos,
                                               const miopenTensorDescriptor_t sinDesc,
                                               const void* sin,
                                               const miopenTensorDescriptor_t yDesc,
                                               void* y);

/*! @brief Execute a rope backward layer
 *
 * @param [in]   handle         MIOpen handle
 * @param [in]   dyDesc         Tensor descriptor for data input tensor dy
 * @param [in]   dy             Data tensor dy
 * @param [in]   cosDesc        Tensor descriptor for output data tensor cos
 * @param [in]   cos            Data tensor cos
 * @param [in]   sinDesc        Tensor descriptor for data input tensor sin
 * @param [in]   sin            Data tensor sin
 * @param [in]   dxDesc         Tensor descriptor for output data tensor dx
 * @param [out]  dx             Data tensor dx
 * @return                      miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenRoPEBackward(miopenHandle_t handle,
                                                const miopenTensorDescriptor_t dyDesc,
                                                const void* dy,
                                                const miopenTensorDescriptor_t cosDesc,
                                                const void* cos,
                                                const miopenTensorDescriptor_t sinDesc,
                                                const void* sin,
                                                const miopenTensorDescriptor_t dxDesc,
                                                void* dx);
/** @} */
// CLOSEOUT ROPE DOXYGEN GROUP
// kthvalue APIs
/** @addtogroup kthvalue
 *
 *  @{
 */

/*! @brief Execute a Kthvalue forward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param inputDesc                Tensor descriptor for input tensor (input)
 * @param input                    Data tensor input (input)
 * @param outputDesc               Tensor descriptor for output tensor (input)
 * @param output                   Data tensor output (output)
 * @param indices                  Data tensor indices (output)
 * @param indicesDesc              Tensor descriptor for indices tensor (input)
 * @param k                        The k-th smallest element(input)
 * @param dim                      The dimension to find the kth value along (Default = -1)(input)
 * @param keepDim                  Whether the output tensor has dim retained or not (Default =
 * false)(input)
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenKthvalueForward(miopenHandle_t handle,
                                                   miopenTensorDescriptor_t inputDesc,
                                                   const void* input,
                                                   miopenTensorDescriptor_t outputDesc,
                                                   void* output,
                                                   miopenTensorDescriptor_t indicesDesc,
                                                   size_t* indices,
                                                   size_t k,
                                                   int32_t dim  = -1,
                                                   bool keepDim = false);

/** @} */
// CLOSEOUT kthvalue DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API
/** @addtogroup ReLU
 *
 *  @{
 */

/*! @brief Helper function to query the minimum workspace size required by the PReLU backward call
 *
 * @param handle                   MIOpen Handle (input)
 * @param inputDesc                Tensor descriptor for input tensor (input)
 * @param weightDesc               Tensor descriptor for weight tensor (input)
 * @param sizeInBytes              Pointer to data to return the minimum workspace size
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetPReLUBackwardWorkspaceSize(miopenHandle_t handle,
                                    miopenTensorDescriptor_t inputDesc,
                                    miopenTensorDescriptor_t weightDesc,
                                    size_t* sizeInBytes);

/*! @brief Execute a PReLU backward layer
 *
 * @param handle                   MIOpen handle (input)
 * @param workspace                Address of the allocated workspace data (input)
 * @param workspaceSizeInBytes     Size in bytes of the allocated workspace data (input)
 * @param inputDesc                Tensor descriptor for input tensor (input)
 * @param input                    Data tensor input (input)
 * @param weightDesc               Tensor descriptor for weight tensor (input)
 * @param weight                   Data tensor weight (input)
 * @param doutputDesc              Tensor descriptor for output gradient (input)
 * @param doutput                  Gradient of output (input)
 * @param dinputDesc               Tensor descriptor for input gradient (input)
 * @param dinput                   Gradient of input (output)
 * @param dweightDesc              Tensor descriptor for weight gradient (input)
 * @param dweight                  Gradient of weight (output)
 */
MIOPEN_EXPORT miopenStatus_t miopenPReLUBackward(miopenHandle_t handle,
                                                 void* workspace,
                                                 size_t workspaceSizeInBytes,
                                                 miopenTensorDescriptor_t inputDesc,
                                                 const void* input,
                                                 miopenTensorDescriptor_t weightDesc,
                                                 const void* weight,
                                                 miopenTensorDescriptor_t doutputDesc,
                                                 const void* doutput,
                                                 miopenTensorDescriptor_t dinputDesc,
                                                 void* dinput,
                                                 miopenTensorDescriptor_t dweightDesc,
                                                 void* dweight);

/** @} */
// CLOSEOUT RELU DOXYGEN GROUP
#endif // MIOPEN_BETA_API

#ifdef MIOPEN_BETA_API

/*! @ingroup LossFunction
 * @enum miopenLossReductionMode_t
 * Reduction mode for loss function
 */
typedef enum
{
    MIOPEN_LOSS_REDUCTION_NONE = 0, /*!< output tensor elements are not reduced */
    MIOPEN_LOSS_REDUCTION_SUM  = 1, /*!< output tensor elements are summed up */
    MIOPEN_LOSS_REDUCTION_MEAN = 2, /*!< output tensor elements are summed up and divided with total
                                       number of elements to get mean value */
} miopenLossReductionMode_t;

// SoftMarginLoss APIs
/** @addtogroup LossFunction
 *
 *  @{
 */

/*! @brief Helper function to query the minimum workspace size required by the
SoftMarginLossForward call
 *
 * @param [in]  handle              MIOpen Handle
 * @param [in]  inputDesc           Tensor descriptor for input tensor
 * @param [in]  targetDesc          Tensor descriptor for target tensor
 * @param [in]  outputDesc          Tensor descriptor for output tensor
*  @param [in]  reduction           Reduction mode (sum, mean). For none reduction we don't need to
use this function
 * @param [out] sizeInBytes         Pointer to data to return the minimum workspace size
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetSoftMarginLossForwardWorkspaceSize(miopenHandle_t handle,
                                            miopenTensorDescriptor_t inputDesc,
                                            miopenTensorDescriptor_t targetDesc,
                                            miopenTensorDescriptor_t outputDesc,
                                            miopenLossReductionMode_t reduction,
                                            size_t* sizeInBytes);

/*! @brief Execute a SoftMarginLoss forward layer
 *
 * @param [in]  handle                  MIOpen handle
 * @param [in]  inputDesc               Tensor descriptor for input tensor
 * @param [in]  input                   Data tensor input
 * @param [in]  targetDesc              Tensor descriptor for target tensor
 * @param [in]  target                  Data tensor target
 * @param [in]  outputDesc              Tensor descriptor for output tensor
 * @param [out] output                  Data tensor output
 * @param [in]  reduction               Reduction mode. If reduction mode is mean or sum, you must
 * provide param workspace and workspaceSizeInBytes. Call
 * miopenGetSoftMarginLossForwardWorkspaceSize to get workspaceSizeInBytes
 * @param [in]  workspace               Address of the allocated workspace data (Default = null)
 * @param [in]  workspaceSizeInBytes    Size in bytes of the allocated workspace data (Default = 0)
 * @return                              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftMarginLossForward(miopenHandle_t handle,
                                                         miopenTensorDescriptor_t inputDesc,
                                                         const void* input,
                                                         miopenTensorDescriptor_t targetDesc,
                                                         const void* target,
                                                         miopenTensorDescriptor_t outputDesc,
                                                         void* output,
                                                         miopenLossReductionMode_t reduction,
                                                         void* workspace             = nullptr,
                                                         size_t workspaceSizeInBytes = 0);

/*! @brief Execute a SoftMarginLoss backward layer
 *
 * @param [in]  handle                  MIOpen handle
 * @param [in]  inputDesc               Tensor descriptor for input tensor
 * @param [in]  input                   Data tensor input
 * @param [in]  targetDesc              Tensor descriptor for target tensor
 * @param [in]  target                  Data tensor target
 * @param [in]  doutputDesc             Tensor descriptor for output gradient
 * @param [in]  doutput                 Output gradient
 * @param [in]  dinputDesc              Tensor descriptor for input gradient
 * @param [out] dinput                  Input gradient
 * @param [in]  reduction               Reduction mode (none, sum, mean)
 * @return                              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSoftMarginLossBackward(miopenHandle_t handle,
                                                          miopenTensorDescriptor_t inputDesc,
                                                          const void* input,
                                                          miopenTensorDescriptor_t targetDesc,
                                                          const void* target,
                                                          miopenTensorDescriptor_t doutputDesc,
                                                          const void* doutput,
                                                          miopenTensorDescriptor_t dinputDesc,
                                                          void* dinput,
                                                          miopenLossReductionMode_t reduction);

/** @} */
// CLOSEOUT LossFunction DOXYGEN GROUP
#endif

#ifdef MIOPEN_BETA_API
// MultiMarginLoss APIs
/** @addtogroup LossFunction
 *
 *  @{
 */

/*! @brief Helper function to query the minimum workspace size required by the
MultiMarginLossForward call
 *
 * @param [in]  handle              MIOpen Handle
 * @param [in]  inputDesc           Tensor descriptor for input tensor (N, C) where N is the batch
size and C is the number of classes
 * @param [in]  targetDesc          Tensor descriptor for target tensor, must have shape (N). Each
value is between 0 and C - 1
 * @param [in]  weightDesc          Tensor descriptor for weight tensor. It is a manual rescaling
weight given to each class. It has to be a Tensor of size C
 * @param [in]  outputDesc          Tensor descriptor for output tensor. If reduction is 'none,
then it must have shape (N). Otherwise, it is a scalar
 * @param [in]  p                   Has a default value of 1. The only supported values are 1 and 2
 * @param [in]  margin              Has a default value of 1
 * @param [in]  reduction           Reduction mode (sum, mean)
 * @param [out] sizeInBytes         Pointer to data to return the minimum workspace size
 * @return                          miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t
miopenGetMultiMarginLossForwardWorkspaceSize(miopenHandle_t handle,
                                             miopenTensorDescriptor_t inputDesc,
                                             miopenTensorDescriptor_t targetDesc,
                                             miopenTensorDescriptor_t weightDesc,
                                             miopenTensorDescriptor_t outputDesc,
                                             long p,
                                             float margin,
                                             miopenLossReductionMode_t reduction,
                                             size_t* sizeInBytes);

/*! @brief Execute a MultiMarginLoss forward layer
 *
 * @param [in]  handle                  MIOpen handle
 * @param [in]  inputDesc               Tensor descriptor for input tensor (N, C) where N is the
batch size and C is the number of classes.
 * @param [in]  input                   Data tensor input
 * @param [in]  targetDesc              Tensor descriptor for target tensor, must have shape (N).
Each value is between 0 and C - 1
 * @param [in]  target                  Data tensor target
 * @param [in]  weightDesc              Tensor descriptor for weight tensor. It is a manual
rescaling weight given to each class. It has to be a Tensor of size C
 * @param [in]  weight                  Data tensor weight
 * @param [in]  outputDesc              Tensor descriptor for output tensor. If reduction is 'none,
then it must have shape (N). Otherwise, it is a scalar.
 * @param [out] output                  Data tensor output
 * @param [in]  p                       Has a default value of 1. The only supported values are 1
and 2
 * @param [in]  margin                  Has a default value of 1
 * @param [in]  reduction               Reduction mode. If reduction mode is mean or sum, you must
 * provide param workspace and workspaceSizeInBytes. Call
 * miopenGetMultiMarginLossForwardWorkspaceSize to get workspaceSizeInBytes
 * @param [in]  workspace               Address of the allocated workspace data. Set = nullptr if
reduction = 'none'
 * @param [in]  workspaceSizeInBytes    Size in bytes of the allocated workspace data. Set = 0 if
reduction = 'none
 * @return                              miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenMultiMarginLossForward(miopenHandle_t handle,
                                                          miopenTensorDescriptor_t inputDesc,
                                                          const void* input,
                                                          miopenTensorDescriptor_t targetDesc,
                                                          const void* target,
                                                          miopenTensorDescriptor_t weightDesc,
                                                          const void* weight,
                                                          miopenTensorDescriptor_t outputDesc,
                                                          void* output,
                                                          long p,
                                                          float margin,
                                                          miopenLossReductionMode_t reduction,
                                                          void* workspace,
                                                          size_t workspaceSizeInBytes);

/** @} */
// CLOSEOUT LossFunction DOXYGEN GROUP
#endif // MIOPEN_BETA_API

/*! @ingroup handle
 * @enum miopenTuningPolicy_t
 * Tuning policy for MIOpen Find-related calls.
 * Supports the following policies of MIOPEN_FIND_ENFORCE:
 * 1. None: Do not enforce anything.
 * 2. DbUpdate: Do not skip auto-tune even if PerfDb already contains optimized values.
 * 3. Search: Search the database first; if no record is found, tune and update the database.
 * 4. SearchDbUpdate: Combination of Search and DbUpdate.
 * 5. DbClean: Remove existing entry, do not tune.
 * Note: TuningPolicy has higher priority over MIOPEN_FIND_ENFORCE.
 */
typedef enum
{
    miopenTuningPolicyNone     = 1, /*!< do not enforce anything */
    miopenTuningPolicyDbUpdate = 2, /*!< tune and update the db  */
    miopenTuningPolicySearch =
        3, /*!< search db first, if record not found tune but do not update the db */
    miopenTuningPolicySearchDbUpdate = 4, /*!< combination of Search and DbUpdate */
    miopenTuningPolicyDbClean        = 5, /*!< remove existing entry, do not tune */
} miopenTuningPolicy_t;

/*! @ingroup handle
 * @brief Update tuning policy for a specific handle. API alternative for MIOPEN_FIND_ENFORCE
 * environment variable.
 *
 * @param [in] handle              MIOpen Handle to update
 * @param [in] newValue            New tuning policy value. Default value is miopenTuningPolicyNone
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenSetTuningPolicy(miopenHandle_t handle,
                                                   miopenTuningPolicy_t newValue);

/*! @ingroup handle
 * @brief Get tuning policy from a handle.
 *
 * @param [in] handle              MIOpen Handle to fetch value from
 * @param [in] value               Would be set to the current tuning policy value. Must not be null
 * @return                         miopenStatus_t
 */
MIOPEN_EXPORT miopenStatus_t miopenGetTuningPolicy(miopenHandle_t handle,
                                                   miopenTuningPolicy_t* value);

#ifdef __cplusplus
}
#endif

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#endif // MIOPEN_GUARD_MIOPEN_H_
