diff --git a/JCudnnJNI/src/JCudnn.cpp b/JCudnnJNI/src/JCudnn.cpp index dfc4070..a803ffa 100644 --- a/JCudnnJNI/src/JCudnn.cpp +++ b/JCudnnJNI/src/JCudnn.cpp @@ -2,7 +2,7 @@ * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA * Deep Neural Network library, to be used with JCuda * - * Copyright (c) 2015-2015 Marco Hutter - http://www.jcuda.org + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -352,7 +352,21 @@ JNIEXPORT jlong JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetVersionNative(JNIEnv *e return jniResult; } -// human-readable error messages +/** Returns CUDA Runtime version statically linked against cudnn */ +JNIEXPORT jlong JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCudartVersionNative(JNIEnv *env, jclass cls) +{ + // Log message + Logger::log(LOG_TRACE, "Executing cudnnGetCudartVersion()\n"); + + // Native function call + size_t jniResult_native = cudnnGetCudartVersion(); + + // Return the result + jlong jniResult = (jlong)jniResult_native; + return jniResult; +} + +/** human-readable error messages */ JNIEXPORT jstring JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetErrorStringNative(JNIEnv *env, jclass cls, jint status) { // Null-checks for non-primitive arguments @@ -378,6 +392,90 @@ JNIEXPORT jstring JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetErrorStringNative(JNI return env->NewStringUTF(jniResult_native); } +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnQueryRuntimeErrorNative(JNIEnv *env, jclass cls, jobject handle, jintArray rstatus, jint mode, jobject tag) +{ + // Null-checks for non-primitive arguments + if (handle == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnQueryRuntimeError"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + if (rstatus == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rstatus' is null for cudnnQueryRuntimeError"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + // mode is primitive + if (tag == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'tag' is null for cudnnQueryRuntimeError"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + + // Log message + Logger::log(LOG_TRACE, "Executing cudnnQueryRuntimeError(handle=%p, rstatus=%p, mode=%d, tag=%p)\n", + handle, rstatus, mode, tag); + + // Native variable declarations + cudnnHandle_t handle_native; + cudnnStatus_t rstatus_native; + cudnnErrQueryMode_t mode_native; + cudnnRuntimeTag_t * tag_native; + + // Obtain native variable values + handle_native = (cudnnHandle_t)getNativePointerValue(env, handle); + // rstatus is write-only + mode_native = (cudnnErrQueryMode_t)mode; + tag_native = (cudnnRuntimeTag_t *)getNativePointerValue(env, tag); + + // Native function call + cudnnStatus_t jniResult_native = cudnnQueryRuntimeError(handle_native, &rstatus_native, mode_native, tag_native); + + // Write back native variable values + // handle is read-only + if (!set(env, rstatus, 0, (jint)rstatus_native)) return JCUDNN_STATUS_INTERNAL_ERROR; + // mode is primitive + // tag is read-only + + // Return the result + jint jniResult = (jint)jniResult_native; + return jniResult; +} + +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetPropertyNative(JNIEnv *env, jclass cls, jint type, jintArray value) +{ + // Null-checks for non-primitive arguments + // type is primitive + if (value == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'value' is null for cudnnGetProperty"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + + // Log message + Logger::log(LOG_TRACE, "Executing cudnnGetProperty(type=%d, value=%p)\n", + type, value); + + // Native variable declarations + libraryPropertyType type_native; + int value_native; + + // Obtain native variable values + type_native = (libraryPropertyType)type; + // value is write-only + + // Native function call + cudnnStatus_t jniResult_native = cudnnGetProperty(type_native, &value_native); + + // Write back native variable values + // type is primitive + if (!set(env, value, 0, (jint)value_native)) return JCUDNN_STATUS_INTERNAL_ERROR; + + // Return the result + jint jniResult = (jint)jniResult_native; + return jniResult; +} + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateNative(JNIEnv *env, jclass cls, jobject handle) { // Null-checks for non-primitive arguments @@ -817,6 +915,56 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNdDescriptorNative return jniResult; } +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNdDescriptorExNative(JNIEnv *env, jclass cls, jobject tensorDesc, jint format, jint dataType, jint nbDims, jintArray dimA) +{ + // Null-checks for non-primitive arguments + if (tensorDesc == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'tensorDesc' is null for cudnnSetTensorNdDescriptorEx"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + // format is primitive + // dataType is primitive + // nbDims is primitive + if (dimA == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dimA' is null for cudnnSetTensorNdDescriptorEx"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + + // Log message + Logger::log(LOG_TRACE, "Executing cudnnSetTensorNdDescriptorEx(tensorDesc=%p, format=%d, dataType=%d, nbDims=%d, dimA=%p)\n", + tensorDesc, format, dataType, nbDims, dimA); + + // Native variable declarations + cudnnTensorDescriptor_t tensorDesc_native; + cudnnTensorFormat_t format_native; + cudnnDataType_t dataType_native; + int nbDims_native = 0; + int * dimA_native = NULL; + + // Obtain native variable values + tensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, tensorDesc); + format_native = (cudnnTensorFormat_t)format; + dataType_native = (cudnnDataType_t)dataType; + nbDims_native = (int)nbDims; + if (!initNative(env, dimA, dimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR; + + // Native function call + cudnnStatus_t jniResult_native = cudnnSetTensorNdDescriptorEx(tensorDesc_native, format_native, dataType_native, nbDims_native, dimA_native); + + // Write back native variable values + // tensorDesc is read-only + // format is primitive + // dataType is primitive + // nbDims is primitive + if (!releaseNative(env, dimA_native, dimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR; + + // Return the result + jint jniResult = (jint)jniResult_native; + return jniResult; +} + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetTensorNdDescriptorNative(JNIEnv *env, jclass cls, jobject tensorDesc, jint nbDimsRequested, jintArray dataType, jintArray nbDims, jintArray dimA, jintArray strideA) { // Null-checks for non-primitive arguments @@ -883,6 +1031,44 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetTensorNdDescriptorNative return jniResult; } +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetTensorSizeInBytesNative(JNIEnv *env, jclass cls, jobject tensorDesc, jlongArray size) +{ + // Null-checks for non-primitive arguments + if (tensorDesc == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'tensorDesc' is null for cudnnGetTensorSizeInBytes"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + if (size == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'size' is null for cudnnGetTensorSizeInBytes"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + + // Log message + Logger::log(LOG_TRACE, "Executing cudnnGetTensorSizeInBytes(tensorDesc=%p, size=%p)\n", + tensorDesc, size); + + // Native variable declarations + cudnnTensorDescriptor_t tensorDesc_native; + size_t size_native; + + // Obtain native variable values + tensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, tensorDesc); + // size is write-only + + // Native function call + cudnnStatus_t jniResult_native = cudnnGetTensorSizeInBytes(tensorDesc_native, &size_native); + + // Write back native variable values + // tensorDesc is read-only + if (!set(env, size, 0, (jlong)size_native)) return JCUDNN_STATUS_INTERNAL_ERROR; + + // Return the result + jint jniResult = (jint)jniResult_native; + return jniResult; +} + /** *
 * PixelOffset( n, c, h, w ) = n *input_stride + c * feature_stride + h * h_stride + w * w_stride
@@ -1273,7 +1459,8 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyOpTensorDescriptorNa
     return jniResult;
 }
 
-/** Tensor Bias operation : C = op( alpha1 * A, alpha2 * B ) + beta * C */
+/** Tensor operation : C = op( alpha1 * A, alpha2 * B ) + beta * C */
+/** B tensor is ignored for CUDNN_OP_TENSOR_SQRT, CUDNN_OP_TENSOR_NOT. */
 JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnOpTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject opTensorDesc, jobject alpha1, jobject aDesc, jobject A, jobject alpha2, jobject bDesc, jobject B, jobject beta, jobject cDesc, jobject C)
 {
     // Null-checks for non-primitive arguments
@@ -1399,1726 +1586,1618 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnOpTensorNative(JNIEnv *env,
     return jniResult;
 }
 
-/** Set all values of a tensor to a given value : y[i] = value[0] */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject yDesc, jobject y, jobject valuePtr)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateReduceTensorDescriptorNative(JNIEnv *env, jclass cls, jobject reduceTensorDesc)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetTensor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (yDesc == NULL)
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSetTensor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (y == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSetTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnCreateReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (valuePtr == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnCreateReduceTensorDescriptor(reduceTensorDesc=%p)\n",
+        reduceTensorDesc);
+
+    // Native variable declarations
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+
+    // Obtain native variable values
+    // reduceTensorDesc is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnCreateReduceTensorDescriptor(&reduceTensorDesc_native);
+
+    // Write back native variable values
+    setNativePointerValue(env, reduceTensorDesc, (jlong)reduceTensorDesc_native);
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetReduceTensorDescriptorNative(JNIEnv *env, jclass cls, jobject reduceTensorDesc, jint reduceTensorOp, jint reduceTensorCompType, jint reduceTensorNanOpt, jint reduceTensorIndices, jint reduceTensorIndicesType)
+{
+    // Null-checks for non-primitive arguments
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'valuePtr' is null for cudnnSetTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnSetReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
+    // reduceTensorOp is primitive
+    // reduceTensorCompType is primitive
+    // reduceTensorNanOpt is primitive
+    // reduceTensorIndices is primitive
+    // reduceTensorIndicesType is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetTensor(handle=%p, yDesc=%p, y=%p, valuePtr=%p)\n",
-        handle, yDesc, y, valuePtr);
+    Logger::log(LOG_TRACE, "Executing cudnnSetReduceTensorDescriptor(reduceTensorDesc=%p, reduceTensorOp=%d, reduceTensorCompType=%d, reduceTensorNanOpt=%d, reduceTensorIndices=%d, reduceTensorIndicesType=%d)\n",
+        reduceTensorDesc, reduceTensorOp, reduceTensorCompType, reduceTensorNanOpt, reduceTensorIndices, reduceTensorIndicesType);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    void * y_native = NULL;
-    void * valuePtr_native = NULL;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+    cudnnReduceTensorOp_t reduceTensorOp_native;
+    cudnnDataType_t reduceTensorCompType_native;
+    cudnnNanPropagation_t reduceTensorNanOpt_native;
+    cudnnReduceTensorIndices_t reduceTensorIndices_native;
+    cudnnIndicesType_t reduceTensorIndicesType_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    y_native = (void *)getPointer(env, y);
-    valuePtr_native = (void *)getPointer(env, valuePtr);
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
+    reduceTensorOp_native = (cudnnReduceTensorOp_t)reduceTensorOp;
+    reduceTensorCompType_native = (cudnnDataType_t)reduceTensorCompType;
+    reduceTensorNanOpt_native = (cudnnNanPropagation_t)reduceTensorNanOpt;
+    reduceTensorIndices_native = (cudnnReduceTensorIndices_t)reduceTensorIndices;
+    reduceTensorIndicesType_native = (cudnnIndicesType_t)reduceTensorIndicesType;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetTensor(handle_native, yDesc_native, y_native, valuePtr_native);
+    cudnnStatus_t jniResult_native = cudnnSetReduceTensorDescriptor(reduceTensorDesc_native, reduceTensorOp_native, reduceTensorCompType_native, reduceTensorNanOpt_native, reduceTensorIndices_native, reduceTensorIndicesType_native);
 
     // Write back native variable values
-    // handle is read-only
-    // yDesc is read-only
-    // y is a native pointer
-    // valuePtr is a native pointer
+    // reduceTensorDesc is read-only
+    // reduceTensorOp is primitive
+    // reduceTensorCompType is primitive
+    // reduceTensorNanOpt is primitive
+    // reduceTensorIndices is primitive
+    // reduceTensorIndicesType is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Scale all values of a tensor by a given factor : y[i] = alpha * y[i] */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnScaleTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject yDesc, jobject y, jobject alpha)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReduceTensorDescriptorNative(JNIEnv *env, jclass cls, jobject reduceTensorDesc, jintArray reduceTensorOp, jintArray reduceTensorCompType, jintArray reduceTensorNanOpt, jintArray reduceTensorIndices, jintArray reduceTensorIndicesType)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnScaleTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnGetReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (reduceTensorOp == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnScaleTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorOp' is null for cudnnGetReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (reduceTensorCompType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnScaleTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorCompType' is null for cudnnGetReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (alpha == NULL)
+    if (reduceTensorNanOpt == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnScaleTensor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorNanOpt' is null for cudnnGetReduceTensorDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (reduceTensorIndices == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorIndices' is null for cudnnGetReduceTensorDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (reduceTensorIndicesType == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorIndicesType' is null for cudnnGetReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnScaleTensor(handle=%p, yDesc=%p, y=%p, alpha=%p)\n",
-        handle, yDesc, y, alpha);
+    Logger::log(LOG_TRACE, "Executing cudnnGetReduceTensorDescriptor(reduceTensorDesc=%p, reduceTensorOp=%p, reduceTensorCompType=%p, reduceTensorNanOpt=%p, reduceTensorIndices=%p, reduceTensorIndicesType=%p)\n",
+        reduceTensorDesc, reduceTensorOp, reduceTensorCompType, reduceTensorNanOpt, reduceTensorIndices, reduceTensorIndicesType);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    void * y_native = NULL;
-    void * alpha_native = NULL;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+    cudnnReduceTensorOp_t reduceTensorOp_native;
+    cudnnDataType_t reduceTensorCompType_native;
+    cudnnNanPropagation_t reduceTensorNanOpt_native;
+    cudnnReduceTensorIndices_t reduceTensorIndices_native;
+    cudnnIndicesType_t reduceTensorIndicesType_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    y_native = (void *)getPointer(env, y);
-    PointerData *alpha_pointerData = initPointerData(env, alpha);
-    if (alpha_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    alpha_native = (void *)alpha_pointerData->getPointer(env);
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
+    // reduceTensorOp is write-only
+    // reduceTensorCompType is write-only
+    // reduceTensorNanOpt is write-only
+    // reduceTensorIndices is write-only
+    // reduceTensorIndicesType is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnScaleTensor(handle_native, yDesc_native, y_native, alpha_native);
+    cudnnStatus_t jniResult_native = cudnnGetReduceTensorDescriptor(reduceTensorDesc_native, &reduceTensorOp_native, &reduceTensorCompType_native, &reduceTensorNanOpt_native, &reduceTensorIndices_native, &reduceTensorIndicesType_native);
 
     // Write back native variable values
-    // handle is read-only
-    // yDesc is read-only
-    // y is a native pointer
-    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // reduceTensorDesc is read-only
+    if (!set(env, reduceTensorOp, 0, (jint)reduceTensorOp_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, reduceTensorCompType, 0, (jint)reduceTensorCompType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, reduceTensorNanOpt, 0, (jint)reduceTensorNanOpt_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, reduceTensorIndices, 0, (jint)reduceTensorIndices_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, reduceTensorIndicesType, 0, (jint)reduceTensorIndicesType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Create an instance of FilterStruct */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateFilterDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyReduceTensorDescriptorNative(JNIEnv *env, jclass cls, jobject reduceTensorDesc)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnCreateFilterDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnDestroyReduceTensorDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnCreateFilterDescriptor(filterDesc=%p)\n",
-        filterDesc);
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyReduceTensorDescriptor(reduceTensorDesc=%p)\n",
+        reduceTensorDesc);
 
     // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
 
     // Obtain native variable values
-    // filterDesc is write-only
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnCreateFilterDescriptor(&filterDesc_native);
+    cudnnStatus_t jniResult_native = cudnnDestroyReduceTensorDescriptor(reduceTensorDesc_native);
 
     // Write back native variable values
-    setNativePointerValue(env, filterDesc, (jlong)filterDesc_native);
+    // reduceTensorDesc is read-only
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetFilter4dDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint dataType, jint format, jint k, jint c, jint h, jint w)
+/** Helper function to return the minimum size of the index space to be passed to the reduction given the input and output tensors */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReductionIndicesSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject reduceTensorDesc, jobject aDesc, jobject cDesc, jlongArray sizeInBytes)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnSetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetReductionIndicesSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (reduceTensorDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnGetReductionIndicesSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (aDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'aDesc' is null for cudnnGetReductionIndicesSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cDesc' is null for cudnnGetReductionIndicesSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (sizeInBytes == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetReductionIndicesSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // dataType is primitive
-    // format is primitive
-    // k is primitive
-    // c is primitive
-    // h is primitive
-    // w is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetFilter4dDescriptor(filterDesc=%p, dataType=%d, format=%d, k=%d, c=%d, h=%d, w=%d)\n",
-        filterDesc, dataType, format, k, c, h, w);
+    Logger::log(LOG_TRACE, "Executing cudnnGetReductionIndicesSize(handle=%p, reduceTensorDesc=%p, aDesc=%p, cDesc=%p, sizeInBytes=%p)\n",
+        handle, reduceTensorDesc, aDesc, cDesc, sizeInBytes);
 
     // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
-    cudnnDataType_t dataType_native;
-    cudnnTensorFormat_t format_native;
-    int k_native = 0;
-    int c_native = 0;
-    int h_native = 0;
-    int w_native = 0;
+    cudnnHandle_t handle_native;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+    cudnnTensorDescriptor_t aDesc_native;
+    cudnnTensorDescriptor_t cDesc_native;
+    size_t sizeInBytes_native;
 
     // Obtain native variable values
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    dataType_native = (cudnnDataType_t)dataType;
-    format_native = (cudnnTensorFormat_t)format;
-    k_native = (int)k;
-    c_native = (int)c;
-    h_native = (int)h;
-    w_native = (int)w;
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
+    aDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, aDesc);
+    cDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cDesc);
+    // sizeInBytes is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetFilter4dDescriptor(filterDesc_native, dataType_native, format_native, k_native, c_native, h_native, w_native);
+    cudnnStatus_t jniResult_native = cudnnGetReductionIndicesSize(handle_native, reduceTensorDesc_native, aDesc_native, cDesc_native, &sizeInBytes_native);
 
     // Write back native variable values
-    // filterDesc is read-only
-    // dataType is primitive
-    // format is primitive
-    // k is primitive
-    // c is primitive
-    // h is primitive
-    // w is primitive
+    // handle is read-only
+    // reduceTensorDesc is read-only
+    // aDesc is read-only
+    // cDesc is read-only
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetFilter4dDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jintArray dataType, jintArray format, jintArray k, jintArray c, jintArray h, jintArray w)
+/** Helper function to return the minimum size of the workspace to be passed to the reduction given the input and output tensors */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReductionWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject reduceTensorDesc, jobject aDesc, jobject cDesc, jlongArray sizeInBytes)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetFilter4dDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dataType == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetFilter4dDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (format == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'format' is null for cudnnGetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetReductionWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (k == NULL)
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'k' is null for cudnnGetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnGetReductionWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (c == NULL)
+    if (aDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'c' is null for cudnnGetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'aDesc' is null for cudnnGetReductionWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (h == NULL)
+    if (cDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'h' is null for cudnnGetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cDesc' is null for cudnnGetReductionWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (sizeInBytes == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnGetFilter4dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetReductionWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetFilter4dDescriptor(filterDesc=%p, dataType=%p, format=%p, k=%p, c=%p, h=%p, w=%p)\n",
-        filterDesc, dataType, format, k, c, h, w);
+    Logger::log(LOG_TRACE, "Executing cudnnGetReductionWorkspaceSize(handle=%p, reduceTensorDesc=%p, aDesc=%p, cDesc=%p, sizeInBytes=%p)\n",
+        handle, reduceTensorDesc, aDesc, cDesc, sizeInBytes);
 
     // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
-    cudnnDataType_t dataType_native;
-    cudnnTensorFormat_t format_native;
-    int k_native;
-    int c_native;
-    int h_native;
-    int w_native;
+    cudnnHandle_t handle_native;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+    cudnnTensorDescriptor_t aDesc_native;
+    cudnnTensorDescriptor_t cDesc_native;
+    size_t sizeInBytes_native;
 
     // Obtain native variable values
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    // dataType is write-only
-    // format is write-only
-    // k is write-only
-    // c is write-only
-    // h is write-only
-    // w is write-only
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
+    aDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, aDesc);
+    cDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cDesc);
+    // sizeInBytes is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetFilter4dDescriptor(filterDesc_native, &dataType_native, &format_native, &k_native, &c_native, &h_native, &w_native);
+    cudnnStatus_t jniResult_native = cudnnGetReductionWorkspaceSize(handle_native, reduceTensorDesc_native, aDesc_native, cDesc_native, &sizeInBytes_native);
 
     // Write back native variable values
-    // filterDesc is read-only
-    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, format, 0, (jint)format_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, k, 0, (jint)k_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, c, 0, (jint)c_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, h, 0, (jint)h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, w, 0, (jint)w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // handle is read-only
+    // reduceTensorDesc is read-only
+    // aDesc is read-only
+    // cDesc is read-only
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetFilterNdDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint dataType, jint format, jint nbDims, jintArray filterDimA)
+/** Tensor operation : C = reduce op( alpha * A ) + beta * C */
+/** The NaN propagation enum applies to only the min and max reduce ops; the other reduce ops propagate NaN as usual. */
+/** The indices space is ignored for reduce ops other than min or max. */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnReduceTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject reduceTensorDesc, jobject indices, jlong indicesSizeInBytes, jobject workspace, jlong workspaceSizeInBytes, jobject alpha, jobject aDesc, jobject A, jobject beta, jobject cDesc, jobject C)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnSetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnReduceTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // dataType is primitive
-    // format is primitive
-    // nbDims is primitive
-    if (filterDimA == NULL)
+    if (reduceTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDimA' is null for cudnnSetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reduceTensorDesc' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (indices == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'indices' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // indicesSizeInBytes is primitive
+    if (workspace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workspaceSizeInBytes is primitive
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (aDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'aDesc' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (A == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'A' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (beta == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cDesc' is null for cudnnReduceTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (C == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'C' is null for cudnnReduceTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetFilterNdDescriptor(filterDesc=%p, dataType=%d, format=%d, nbDims=%d, filterDimA=%p)\n",
-        filterDesc, dataType, format, nbDims, filterDimA);
+    Logger::log(LOG_TRACE, "Executing cudnnReduceTensor(handle=%p, reduceTensorDesc=%p, indices=%p, indicesSizeInBytes=%ld, workspace=%p, workspaceSizeInBytes=%ld, alpha=%p, aDesc=%p, A=%p, beta=%p, cDesc=%p, C=%p)\n",
+        handle, reduceTensorDesc, indices, indicesSizeInBytes, workspace, workspaceSizeInBytes, alpha, aDesc, A, beta, cDesc, C);
 
     // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
-    cudnnDataType_t dataType_native;
-    cudnnTensorFormat_t format_native;
-    int nbDims_native = 0;
-    int * filterDimA_native = NULL;
+    cudnnHandle_t handle_native;
+    cudnnReduceTensorDescriptor_t reduceTensorDesc_native;
+    void * indices_native = NULL;
+    size_t indicesSizeInBytes_native = 0;
+    void * workspace_native = NULL;
+    size_t workspaceSizeInBytes_native = 0;
+    void * alpha_native = NULL;
+    cudnnTensorDescriptor_t aDesc_native;
+    void * A_native = NULL;
+    void * beta_native = NULL;
+    cudnnTensorDescriptor_t cDesc_native;
+    void * C_native = NULL;
 
     // Obtain native variable values
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    dataType_native = (cudnnDataType_t)dataType;
-    format_native = (cudnnTensorFormat_t)format;
-    nbDims_native = (int)nbDims;
-    if (!initNative(env, filterDimA, filterDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    reduceTensorDesc_native = (cudnnReduceTensorDescriptor_t)getNativePointerValue(env, reduceTensorDesc);
+    indices_native = (void *)getPointer(env, indices);
+    indicesSizeInBytes_native = (size_t)indicesSizeInBytes;
+    workspace_native = (void *)getPointer(env, workspace);
+    workspaceSizeInBytes_native = (size_t)workspaceSizeInBytes;
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
+    aDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, aDesc);
+    A_native = (void *)getPointer(env, A);
+    PointerData *beta_pointerData = initPointerData(env, beta);
+    if (beta_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    beta_native = (void *)beta_pointerData->getPointer(env);
+    cDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cDesc);
+    C_native = (void *)getPointer(env, C);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetFilterNdDescriptor(filterDesc_native, dataType_native, format_native, nbDims_native, filterDimA_native);
+    cudnnStatus_t jniResult_native = cudnnReduceTensor(handle_native, reduceTensorDesc_native, indices_native, indicesSizeInBytes_native, workspace_native, workspaceSizeInBytes_native, alpha_native, aDesc_native, A_native, beta_native, cDesc_native, C_native);
 
     // Write back native variable values
-    // filterDesc is read-only
-    // dataType is primitive
-    // format is primitive
-    // nbDims is primitive
-    if (!releaseNative(env, filterDimA_native, filterDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // handle is read-only
+    // reduceTensorDesc is read-only
+    // indices is a native pointer
+    // indicesSizeInBytes is primitive
+    // workspace is a native pointer
+    // workspaceSizeInBytes is primitive
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // aDesc is read-only
+    // A is a native pointer
+    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // cDesc is read-only
+    // C is a native pointer
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetFilterNdDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint nbDimsRequested, jintArray dataType, jintArray format, jintArray nbDims, jintArray filterDimA)
+/** Set all values of a tensor to a given value : y[i] = value[0] */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject yDesc, jobject y, jobject valuePtr)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetFilterNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // nbDimsRequested is primitive
-    if (dataType == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (format == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'format' is null for cudnnGetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSetTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (nbDims == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'nbDims' is null for cudnnGetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSetTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (filterDimA == NULL)
+    if (valuePtr == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDimA' is null for cudnnGetFilterNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'valuePtr' is null for cudnnSetTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetFilterNdDescriptor(filterDesc=%p, nbDimsRequested=%d, dataType=%p, format=%p, nbDims=%p, filterDimA=%p)\n",
-        filterDesc, nbDimsRequested, dataType, format, nbDims, filterDimA);
+    Logger::log(LOG_TRACE, "Executing cudnnSetTensor(handle=%p, yDesc=%p, y=%p, valuePtr=%p)\n",
+        handle, yDesc, y, valuePtr);
 
     // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
-    int nbDimsRequested_native = 0;
-    cudnnDataType_t dataType_native;
-    cudnnTensorFormat_t format_native;
-    int nbDims_native;
-    int * filterDimA_native = NULL;
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
+    void * valuePtr_native = NULL;
 
     // Obtain native variable values
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    nbDimsRequested_native = (int)nbDimsRequested;
-    // dataType is write-only
-    // format is write-only
-    // nbDims is write-only
-    if (!initNative(env, filterDimA, filterDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
+    valuePtr_native = (void *)getPointer(env, valuePtr);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetFilterNdDescriptor(filterDesc_native, nbDimsRequested_native, &dataType_native, &format_native, &nbDims_native, filterDimA_native);
+    cudnnStatus_t jniResult_native = cudnnSetTensor(handle_native, yDesc_native, y_native, valuePtr_native);
 
     // Write back native variable values
-    // filterDesc is read-only
-    // nbDimsRequested is primitive
-    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, format, 0, (jint)format_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, nbDims, 0, (jint)nbDims_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, filterDimA_native, filterDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // handle is read-only
+    // yDesc is read-only
+    // y is a native pointer
+    // valuePtr is a native pointer
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyFilterDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc)
+/** Scale all values of a tensor by a given factor : y[i] = alpha * y[i] */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnScaleTensorNative(JNIEnv *env, jclass cls, jobject handle, jobject yDesc, jobject y, jobject alpha)
 {
     // Null-checks for non-primitive arguments
-    if (filterDesc == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnDestroyFilterDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnScaleTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-
-    // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnDestroyFilterDescriptor(filterDesc=%p)\n",
-        filterDesc);
-
-    // Native variable declarations
-    cudnnFilterDescriptor_t filterDesc_native;
-
-    // Obtain native variable values
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-
-    // Native function call
-    cudnnStatus_t jniResult_native = cudnnDestroyFilterDescriptor(filterDesc_native);
-
-    // Write back native variable values
-    // filterDesc is read-only
-
-    // Return the result
-    jint jniResult = (jint)jniResult_native;
-    return jniResult;
-}
-
-/** Create an instance of convolution descriptor */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateConvolutionDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc)
-{
-    // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnCreateConvolutionDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnScaleTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (y == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnScaleTensor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnScaleTensor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnCreateConvolutionDescriptor(convDesc=%p)\n",
-        convDesc);
+    Logger::log(LOG_TRACE, "Executing cudnnScaleTensor(handle=%p, yDesc=%p, y=%p, alpha=%p)\n",
+        handle, yDesc, y, alpha);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
+    void * alpha_native = NULL;
 
     // Obtain native variable values
-    // convDesc is write-only
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnCreateConvolutionDescriptor(&convDesc_native);
+    cudnnStatus_t jniResult_native = cudnnScaleTensor(handle_native, yDesc_native, y_native, alpha_native);
 
     // Write back native variable values
-    setNativePointerValue(env, convDesc, (jlong)convDesc_native);
+    // handle is read-only
+    // yDesc is read-only
+    // y is a native pointer
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint pad_h, jint pad_w, jint u, jint v, jint upscalex, jint upscaley, jint mode)
+/** Create an instance of FilterStruct */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateFilterDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnCreateFilterDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // pad_h is primitive
-    // pad_w is primitive
-    // u is primitive
-    // v is primitive
-    // upscalex is primitive
-    // upscaley is primitive
-    // mode is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetConvolution2dDescriptor(convDesc=%p, pad_h=%d, pad_w=%d, u=%d, v=%d, upscalex=%d, upscaley=%d, mode=%d)\n",
-        convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode);
+    Logger::log(LOG_TRACE, "Executing cudnnCreateFilterDescriptor(filterDesc=%p)\n",
+        filterDesc);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    int pad_h_native = 0;
-    int pad_w_native = 0;
-    int u_native = 0;
-    int v_native = 0;
-    int upscalex_native = 0;
-    int upscaley_native = 0;
-    cudnnConvolutionMode_t mode_native;
+    cudnnFilterDescriptor_t filterDesc_native;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    pad_h_native = (int)pad_h;
-    pad_w_native = (int)pad_w;
-    u_native = (int)u;
-    v_native = (int)v;
-    upscalex_native = (int)upscalex;
-    upscaley_native = (int)upscaley;
-    mode_native = (cudnnConvolutionMode_t)mode;
+    // filterDesc is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetConvolution2dDescriptor(convDesc_native, pad_h_native, pad_w_native, u_native, v_native, upscalex_native, upscaley_native, mode_native);
+    cudnnStatus_t jniResult_native = cudnnCreateFilterDescriptor(&filterDesc_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    // pad_h is primitive
-    // pad_w is primitive
-    // u is primitive
-    // v is primitive
-    // upscalex is primitive
-    // upscaley is primitive
-    // mode is primitive
+    setNativePointerValue(env, filterDesc, (jlong)filterDesc_native);
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptor_1v5Native(JNIEnv *env, jclass cls, jobject convDesc, jint pad_h, jint pad_w, jint u, jint v, jint upscalex, jint upscaley, jint mode, jint dataType)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetFilter4dDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint dataType, jint format, jint k, jint c, jint h, jint w)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolution2dDescriptor_v5");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnSetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // pad_h is primitive
-    // pad_w is primitive
-    // u is primitive
-    // v is primitive
-    // upscalex is primitive
-    // upscaley is primitive
-    // mode is primitive
     // dataType is primitive
+    // format is primitive
+    // k is primitive
+    // c is primitive
+    // h is primitive
+    // w is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetConvolution2dDescriptor_v5(convDesc=%p, pad_h=%d, pad_w=%d, u=%d, v=%d, upscalex=%d, upscaley=%d, mode=%d, dataType=%d)\n",
-        convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode, dataType);
+    Logger::log(LOG_TRACE, "Executing cudnnSetFilter4dDescriptor(filterDesc=%p, dataType=%d, format=%d, k=%d, c=%d, h=%d, w=%d)\n",
+        filterDesc, dataType, format, k, c, h, w);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    int pad_h_native = 0;
-    int pad_w_native = 0;
-    int u_native = 0;
-    int v_native = 0;
-    int upscalex_native = 0;
-    int upscaley_native = 0;
-    cudnnConvolutionMode_t mode_native;
+    cudnnFilterDescriptor_t filterDesc_native;
     cudnnDataType_t dataType_native;
+    cudnnTensorFormat_t format_native;
+    int k_native = 0;
+    int c_native = 0;
+    int h_native = 0;
+    int w_native = 0;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    pad_h_native = (int)pad_h;
-    pad_w_native = (int)pad_w;
-    u_native = (int)u;
-    v_native = (int)v;
-    upscalex_native = (int)upscalex;
-    upscaley_native = (int)upscaley;
-    mode_native = (cudnnConvolutionMode_t)mode;
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
     dataType_native = (cudnnDataType_t)dataType;
+    format_native = (cudnnTensorFormat_t)format;
+    k_native = (int)k;
+    c_native = (int)c;
+    h_native = (int)h;
+    w_native = (int)w;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetConvolution2dDescriptor_v5(convDesc_native, pad_h_native, pad_w_native, u_native, v_native, upscalex_native, upscaley_native, mode_native, dataType_native);
+    cudnnStatus_t jniResult_native = cudnnSetFilter4dDescriptor(filterDesc_native, dataType_native, format_native, k_native, c_native, h_native, w_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    // pad_h is primitive
-    // pad_w is primitive
-    // u is primitive
-    // v is primitive
-    // upscalex is primitive
-    // upscaley is primitive
-    // mode is primitive
+    // filterDesc is read-only
     // dataType is primitive
+    // format is primitive
+    // k is primitive
+    // c is primitive
+    // h is primitive
+    // w is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jintArray pad_h, jintArray pad_w, jintArray u, jintArray v, jintArray upscalex, jintArray upscaley, jintArray mode)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetFilter4dDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jintArray dataType, jintArray format, jintArray k, jintArray c, jintArray h, jintArray w)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolution2dDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (pad_h == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_h' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (pad_w == NULL)
+    if (dataType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_w' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (u == NULL)
+    if (format == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'u' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'format' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (v == NULL)
+    if (k == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'v' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'k' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (upscalex == NULL)
+    if (c == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscalex' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'c' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (upscaley == NULL)
+    if (h == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscaley' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'h' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (mode == NULL)
+    if (w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetConvolution2dDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnGetFilter4dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolution2dDescriptor(convDesc=%p, pad_h=%p, pad_w=%p, u=%p, v=%p, upscalex=%p, upscaley=%p, mode=%p)\n",
-        convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode);
+    Logger::log(LOG_TRACE, "Executing cudnnGetFilter4dDescriptor(filterDesc=%p, dataType=%p, format=%p, k=%p, c=%p, h=%p, w=%p)\n",
+        filterDesc, dataType, format, k, c, h, w);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    int pad_h_native;
-    int pad_w_native;
-    int u_native;
-    int v_native;
-    int upscalex_native;
-    int upscaley_native;
-    cudnnConvolutionMode_t mode_native;
+    cudnnFilterDescriptor_t filterDesc_native;
+    cudnnDataType_t dataType_native;
+    cudnnTensorFormat_t format_native;
+    int k_native;
+    int c_native;
+    int h_native;
+    int w_native;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    // pad_h is write-only
-    // pad_w is write-only
-    // u is write-only
-    // v is write-only
-    // upscalex is write-only
-    // upscaley is write-only
-    // mode is write-only
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    // dataType is write-only
+    // format is write-only
+    // k is write-only
+    // c is write-only
+    // h is write-only
+    // w is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolution2dDescriptor(convDesc_native, &pad_h_native, &pad_w_native, &u_native, &v_native, &upscalex_native, &upscaley_native, &mode_native);
+    cudnnStatus_t jniResult_native = cudnnGetFilter4dDescriptor(filterDesc_native, &dataType_native, &format_native, &k_native, &c_native, &h_native, &w_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    if (!set(env, pad_h, 0, (jint)pad_h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, pad_w, 0, (jint)pad_w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, u, 0, (jint)u_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, v, 0, (jint)v_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, upscalex, 0, (jint)upscalex_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, upscaley, 0, (jint)upscaley_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // filterDesc is read-only
+    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, format, 0, (jint)format_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, k, 0, (jint)k_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, c, 0, (jint)c_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, h, 0, (jint)h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, w, 0, (jint)w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptor_1v5Native(JNIEnv *env, jclass cls, jobject convDesc, jintArray pad_h, jintArray pad_w, jintArray u, jintArray v, jintArray upscalex, jintArray upscaley, jintArray mode, jintArray dataType)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetFilterNdDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint dataType, jint format, jint nbDims, jintArray filterDimA)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (pad_h == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_h' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (pad_w == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_w' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (u == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'u' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (v == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'v' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (upscalex == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscalex' is null for cudnnGetConvolution2dDescriptor_v5");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnSetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (upscaley == NULL)
+    // dataType is primitive
+    // format is primitive
+    // nbDims is primitive
+    if (filterDimA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscaley' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (mode == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetConvolution2dDescriptor_v5");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dataType == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetConvolution2dDescriptor_v5");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDimA' is null for cudnnSetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolution2dDescriptor_v5(convDesc=%p, pad_h=%p, pad_w=%p, u=%p, v=%p, upscalex=%p, upscaley=%p, mode=%p, dataType=%p)\n",
-        convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode, dataType);
+    Logger::log(LOG_TRACE, "Executing cudnnSetFilterNdDescriptor(filterDesc=%p, dataType=%d, format=%d, nbDims=%d, filterDimA=%p)\n",
+        filterDesc, dataType, format, nbDims, filterDimA);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    int pad_h_native;
-    int pad_w_native;
-    int u_native;
-    int v_native;
-    int upscalex_native;
-    int upscaley_native;
-    cudnnConvolutionMode_t mode_native;
+    cudnnFilterDescriptor_t filterDesc_native;
     cudnnDataType_t dataType_native;
+    cudnnTensorFormat_t format_native;
+    int nbDims_native = 0;
+    int * filterDimA_native = NULL;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    // pad_h is write-only
-    // pad_w is write-only
-    // u is write-only
-    // v is write-only
-    // upscalex is write-only
-    // upscaley is write-only
-    // mode is write-only
-    // dataType is write-only
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    dataType_native = (cudnnDataType_t)dataType;
+    format_native = (cudnnTensorFormat_t)format;
+    nbDims_native = (int)nbDims;
+    if (!initNative(env, filterDimA, filterDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolution2dDescriptor_v5(convDesc_native, &pad_h_native, &pad_w_native, &u_native, &v_native, &upscalex_native, &upscaley_native, &mode_native, &dataType_native);
+    cudnnStatus_t jniResult_native = cudnnSetFilterNdDescriptor(filterDesc_native, dataType_native, format_native, nbDims_native, filterDimA_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    if (!set(env, pad_h, 0, (jint)pad_h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, pad_w, 0, (jint)pad_w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, u, 0, (jint)u_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, v, 0, (jint)v_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, upscalex, 0, (jint)upscalex_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, upscaley, 0, (jint)upscaley_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // filterDesc is read-only
+    // dataType is primitive
+    // format is primitive
+    // nbDims is primitive
+    if (!releaseNative(env, filterDimA_native, filterDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Helper function to return the dimensions of the output tensor given a convolution descriptor */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dForwardOutputDimNative(JNIEnv *env, jclass cls, jobject convDesc, jobject inputTensorDesc, jobject filterDesc, jintArray n, jintArray c, jintArray h, jintArray w)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetFilterNdDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc, jint nbDimsRequested, jintArray dataType, jintArray format, jintArray nbDims, jintArray filterDimA)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolution2dForwardOutputDim");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (inputTensorDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputTensorDesc' is null for cudnnGetConvolution2dForwardOutputDim");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
     if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolution2dForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (n == NULL)
+    // nbDimsRequested is primitive
+    if (dataType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'n' is null for cudnnGetConvolution2dForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (c == NULL)
+    if (format == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'c' is null for cudnnGetConvolution2dForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'format' is null for cudnnGetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (h == NULL)
+    if (nbDims == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'h' is null for cudnnGetConvolution2dForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'nbDims' is null for cudnnGetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (filterDimA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnGetConvolution2dForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDimA' is null for cudnnGetFilterNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolution2dForwardOutputDim(convDesc=%p, inputTensorDesc=%p, filterDesc=%p, n=%p, c=%p, h=%p, w=%p)\n",
-        convDesc, inputTensorDesc, filterDesc, n, c, h, w);
+    Logger::log(LOG_TRACE, "Executing cudnnGetFilterNdDescriptor(filterDesc=%p, nbDimsRequested=%d, dataType=%p, format=%p, nbDims=%p, filterDimA=%p)\n",
+        filterDesc, nbDimsRequested, dataType, format, nbDims, filterDimA);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t inputTensorDesc_native;
     cudnnFilterDescriptor_t filterDesc_native;
-    int n_native;
-    int c_native;
-    int h_native;
-    int w_native;
+    int nbDimsRequested_native = 0;
+    cudnnDataType_t dataType_native;
+    cudnnTensorFormat_t format_native;
+    int nbDims_native;
+    int * filterDimA_native = NULL;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    inputTensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, inputTensorDesc);
     filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    // n is write-only
-    // c is write-only
-    // h is write-only
-    // w is write-only
+    nbDimsRequested_native = (int)nbDimsRequested;
+    // dataType is write-only
+    // format is write-only
+    // nbDims is write-only
+    if (!initNative(env, filterDimA, filterDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolution2dForwardOutputDim(convDesc_native, inputTensorDesc_native, filterDesc_native, &n_native, &c_native, &h_native, &w_native);
+    cudnnStatus_t jniResult_native = cudnnGetFilterNdDescriptor(filterDesc_native, nbDimsRequested_native, &dataType_native, &format_native, &nbDims_native, filterDimA_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    // inputTensorDesc is read-only
     // filterDesc is read-only
-    if (!set(env, n, 0, (jint)n_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, c, 0, (jint)c_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, h, 0, (jint)h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, w, 0, (jint)w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // nbDimsRequested is primitive
+    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, format, 0, (jint)format_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, nbDims, 0, (jint)nbDims_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, filterDimA_native, filterDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionNdDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint arrayLength, jintArray padA, jintArray filterStrideA, jintArray upscaleA, jint mode, jint dataType)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyFilterDescriptorNative(JNIEnv *env, jclass cls, jobject filterDesc)
 {
     // Null-checks for non-primitive arguments
-    if (convDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // arrayLength is primitive
-    if (padA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'padA' is null for cudnnSetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (filterStrideA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterStrideA' is null for cudnnSetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (upscaleA == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscaleA' is null for cudnnSetConvolutionNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnDestroyFilterDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // mode is primitive
-    // dataType is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetConvolutionNdDescriptor(convDesc=%p, arrayLength=%d, padA=%p, filterStrideA=%p, upscaleA=%p, mode=%d, dataType=%d)\n",
-        convDesc, arrayLength, padA, filterStrideA, upscaleA, mode, dataType);
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyFilterDescriptor(filterDesc=%p)\n",
+        filterDesc);
 
     // Native variable declarations
-    cudnnConvolutionDescriptor_t convDesc_native;
-    int arrayLength_native = 0;
-    int * padA_native = NULL;
-    int * filterStrideA_native = NULL;
-    int * upscaleA_native = NULL;
-    cudnnConvolutionMode_t mode_native;
-    cudnnDataType_t dataType_native;
+    cudnnFilterDescriptor_t filterDesc_native;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    arrayLength_native = (int)arrayLength;
-    if (!initNative(env, padA, padA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!initNative(env, filterStrideA, filterStrideA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!initNative(env, upscaleA, upscaleA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    mode_native = (cudnnConvolutionMode_t)mode;
-    dataType_native = (cudnnDataType_t)dataType;
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetConvolutionNdDescriptor(convDesc_native, arrayLength_native, padA_native, filterStrideA_native, upscaleA_native, mode_native, dataType_native);
+    cudnnStatus_t jniResult_native = cudnnDestroyFilterDescriptor(filterDesc_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    // arrayLength is primitive
-    if (!releaseNative(env, padA_native, padA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, filterStrideA_native, filterStrideA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, upscaleA_native, upscaleA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // mode is primitive
-    // dataType is primitive
+    // filterDesc is read-only
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionNdDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint arrayLengthRequested, jintArray arrayLength, jintArray padA, jintArray strideA, jintArray upscaleA, jintArray mode, jintArray dataType)
+/** Create an instance of convolution descriptor */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateConvolutionDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc)
 {
     // Null-checks for non-primitive arguments
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // arrayLengthRequested is primitive
-    if (arrayLength == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'arrayLength' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (padA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'padA' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (strideA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'strideA' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (upscaleA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'upscaleA' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (mode == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetConvolutionNdDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dataType == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetConvolutionNdDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnCreateConvolutionDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionNdDescriptor(convDesc=%p, arrayLengthRequested=%d, arrayLength=%p, padA=%p, strideA=%p, upscaleA=%p, mode=%p, dataType=%p)\n",
-        convDesc, arrayLengthRequested, arrayLength, padA, strideA, upscaleA, mode, dataType);
+    Logger::log(LOG_TRACE, "Executing cudnnCreateConvolutionDescriptor(convDesc=%p)\n",
+        convDesc);
 
     // Native variable declarations
     cudnnConvolutionDescriptor_t convDesc_native;
-    int arrayLengthRequested_native = 0;
-    int arrayLength_native;
-    int * padA_native = NULL;
-    int * strideA_native = NULL;
-    int * upscaleA_native = NULL;
-    cudnnConvolutionMode_t mode_native;
-    cudnnDataType_t dataType_native;
 
     // Obtain native variable values
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    arrayLengthRequested_native = (int)arrayLengthRequested;
-    // arrayLength is write-only
-    if (!initNative(env, padA, padA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!initNative(env, strideA, strideA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!initNative(env, upscaleA, upscaleA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // mode is write-only
-    // dataType is write-only
+    // convDesc is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionNdDescriptor(convDesc_native, arrayLengthRequested_native, &arrayLength_native, padA_native, strideA_native, upscaleA_native, &mode_native, &dataType_native);
+    cudnnStatus_t jniResult_native = cudnnCreateConvolutionDescriptor(&convDesc_native);
 
     // Write back native variable values
-    // convDesc is read-only
-    // arrayLengthRequested is primitive
-    if (!set(env, arrayLength, 0, (jint)arrayLength_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, padA_native, padA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, strideA_native, strideA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, upscaleA_native, upscaleA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    setNativePointerValue(env, convDesc, (jlong)convDesc_native);
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Helper function to return the dimensions of the output tensor given a convolution descriptor */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionNdForwardOutputDimNative(JNIEnv *env, jclass cls, jobject convDesc, jobject inputTensorDesc, jobject filterDesc, jint nbDims, jintArray tensorOuputDimA)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionMathTypeNative(JNIEnv *env, jclass cls, jobject convDesc, jint mathType)
 {
     // Null-checks for non-primitive arguments
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (inputTensorDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputTensorDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (filterDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // nbDims is primitive
-    if (tensorOuputDimA == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'tensorOuputDimA' is null for cudnnGetConvolutionNdForwardOutputDim");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolutionMathType");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
+    // mathType is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionNdForwardOutputDim(convDesc=%p, inputTensorDesc=%p, filterDesc=%p, nbDims=%d, tensorOuputDimA=%p)\n",
-        convDesc, inputTensorDesc, filterDesc, nbDims, tensorOuputDimA);
+    Logger::log(LOG_TRACE, "Executing cudnnSetConvolutionMathType(convDesc=%p, mathType=%d)\n",
+        convDesc, mathType);
 
     // Native variable declarations
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t inputTensorDesc_native;
-    cudnnFilterDescriptor_t filterDesc_native;
-    int nbDims_native = 0;
-    int * tensorOuputDimA_native = NULL;
+    cudnnMathType_t mathType_native;
 
     // Obtain native variable values
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    inputTensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, inputTensorDesc);
-    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
-    nbDims_native = (int)nbDims;
-    if (!initNative(env, tensorOuputDimA, tensorOuputDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    mathType_native = (cudnnMathType_t)mathType;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionNdForwardOutputDim(convDesc_native, inputTensorDesc_native, filterDesc_native, nbDims_native, tensorOuputDimA_native);
+    cudnnStatus_t jniResult_native = cudnnSetConvolutionMathType(convDesc_native, mathType_native);
 
     // Write back native variable values
     // convDesc is read-only
-    // inputTensorDesc is read-only
-    // filterDesc is read-only
-    // nbDims is primitive
-    if (!releaseNative(env, tensorOuputDimA_native, tensorOuputDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // mathType is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Destroy an instance of convolution descriptor */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyConvolutionDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionMathTypeNative(JNIEnv *env, jclass cls, jobject convDesc, jintArray mathType)
 {
     // Null-checks for non-primitive arguments
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnDestroyConvolutionDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionMathType");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-
-    // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnDestroyConvolutionDescriptor(convDesc=%p)\n",
-        convDesc);
+    if (mathType == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mathType' is null for cudnnGetConvolutionMathType");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionMathType(convDesc=%p, mathType=%p)\n",
+        convDesc, mathType);
 
     // Native variable declarations
     cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnMathType_t mathType_native;
 
     // Obtain native variable values
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    // mathType is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnDestroyConvolutionDescriptor(convDesc_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionMathType(convDesc_native, &mathType_native);
 
     // Write back native variable values
     // convDesc is read-only
+    if (!set(env, mathType, 0, (jint)mathType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionForwardAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionGroupCountNative(JNIEnv *env, jclass cls, jobject convDesc, jint groupCount)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionForwardAlgorithm");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (xDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionForwardAlgorithm");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionForwardAlgorithm");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionForwardAlgorithm");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (yDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnFindConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolutionGroupCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // requestedAlgoCount is primitive
-    if (returnedAlgoCount == NULL)
+    // groupCount is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetConvolutionGroupCount(convDesc=%p, groupCount=%d)\n",
+        convDesc, groupCount);
+
+    // Native variable declarations
+    cudnnConvolutionDescriptor_t convDesc_native;
+    int groupCount_native = 0;
+
+    // Obtain native variable values
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    groupCount_native = (int)groupCount;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSetConvolutionGroupCount(convDesc_native, groupCount_native);
+
+    // Write back native variable values
+    // convDesc is read-only
+    // groupCount is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionGroupCountNative(JNIEnv *env, jclass cls, jobject convDesc, jintArray groupCount)
+{
+    // Null-checks for non-primitive arguments
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionGroupCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (perfResults == NULL)
+    if (groupCount == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'groupCount' is null for cudnnGetConvolutionGroupCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionForwardAlgorithm(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
-        handle, xDesc, wDesc, convDesc, yDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionGroupCount(convDesc=%p, groupCount=%p)\n",
+        convDesc, groupCount);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t xDesc_native;
-    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    int requestedAlgoCount_native = 0;
-    int returnedAlgoCount_native;
-    cudnnConvolutionFwdAlgoPerf_t * perfResults_native;
+    int groupCount_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    requestedAlgoCount_native = (int)requestedAlgoCount;
-    // returnedAlgoCount is write-only
-    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // groupCount is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionForwardAlgorithm(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionGroupCount(convDesc_native, &groupCount_native);
 
     // Write back native variable values
-    // handle is read-only
-    // xDesc is read-only
-    // wDesc is read-only
     // convDesc is read-only
-    // yDesc is read-only
-    // requestedAlgoCount is primitive
-    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, groupCount, 0, (jint)groupCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionForwardAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject wDesc, jobject w, jobject convDesc, jobject yDesc, jobject y, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint pad_h, jint pad_w, jint u, jint v, jint dilation_h, jint dilation_w, jint mode, jint computeType)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionForwardAlgorithmEx");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (xDesc == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (x == NULL)
+    // pad_h is primitive
+    // pad_w is primitive
+    // u is primitive
+    // v is primitive
+    // dilation_h is primitive
+    // dilation_w is primitive
+    // mode is primitive
+    // computeType is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetConvolution2dDescriptor(convDesc=%p, pad_h=%d, pad_w=%d, u=%d, v=%d, dilation_h=%d, dilation_w=%d, mode=%d, computeType=%d)\n",
+        convDesc, pad_h, pad_w, u, v, dilation_h, dilation_w, mode, computeType);
+
+    // Native variable declarations
+    cudnnConvolutionDescriptor_t convDesc_native;
+    int pad_h_native = 0;
+    int pad_w_native = 0;
+    int u_native = 0;
+    int v_native = 0;
+    int dilation_h_native = 0;
+    int dilation_w_native = 0;
+    cudnnConvolutionMode_t mode_native;
+    cudnnDataType_t computeType_native;
+
+    // Obtain native variable values
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    pad_h_native = (int)pad_h;
+    pad_w_native = (int)pad_w;
+    u_native = (int)u;
+    v_native = (int)v;
+    dilation_h_native = (int)dilation_h;
+    dilation_w_native = (int)dilation_w;
+    mode_native = (cudnnConvolutionMode_t)mode;
+    computeType_native = (cudnnDataType_t)computeType;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSetConvolution2dDescriptor(convDesc_native, pad_h_native, pad_w_native, u_native, v_native, dilation_h_native, dilation_w_native, mode_native, computeType_native);
+
+    // Write back native variable values
+    // convDesc is read-only
+    // pad_h is primitive
+    // pad_w is primitive
+    // u is primitive
+    // v is primitive
+    // dilation_h is primitive
+    // dilation_w is primitive
+    // mode is primitive
+    // computeType is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jintArray pad_h, jintArray pad_w, jintArray u, jintArray v, jintArray dilation_h, jintArray dilation_w, jintArray mode, jintArray computeType)
+{
+    // Null-checks for non-primitive arguments
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (pad_h == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_h' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (pad_w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'pad_w' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (u == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'u' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (v == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'v' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (dilation_h == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dilation_h' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // requestedAlgoCount is primitive
-    if (returnedAlgoCount == NULL)
+    if (dilation_w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dilation_w' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (perfResults == NULL)
+    if (mode == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (workSpace == NULL)
+    if (computeType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionForwardAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'computeType' is null for cudnnGetConvolution2dDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionForwardAlgorithmEx(handle=%p, xDesc=%p, x=%p, wDesc=%p, w=%p, convDesc=%p, yDesc=%p, y=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
-        handle, xDesc, x, wDesc, w, convDesc, yDesc, y, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolution2dDescriptor(convDesc=%p, pad_h=%p, pad_w=%p, u=%p, v=%p, dilation_h=%p, dilation_w=%p, mode=%p, computeType=%p)\n",
+        convDesc, pad_h, pad_w, u, v, dilation_h, dilation_w, mode, computeType);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t xDesc_native;
-    void * x_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
-    void * w_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    void * y_native = NULL;
-    int requestedAlgoCount_native = 0;
-    int returnedAlgoCount_native;
-    cudnnConvolutionFwdAlgoPerf_t * perfResults_native;
-    void * workSpace_native = NULL;
-    size_t workSpaceSizeInBytes_native = 0;
+    int pad_h_native;
+    int pad_w_native;
+    int u_native;
+    int v_native;
+    int dilation_h_native;
+    int dilation_w_native;
+    cudnnConvolutionMode_t mode_native;
+    cudnnDataType_t computeType_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    x_native = (void *)getPointer(env, x);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    w_native = (void *)getPointer(env, w);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    y_native = (void *)getPointer(env, y);
-    requestedAlgoCount_native = (int)requestedAlgoCount;
-    // returnedAlgoCount is write-only
-    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    workSpace_native = (void *)getPointer(env, workSpace);
-    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    // pad_h is write-only
+    // pad_w is write-only
+    // u is write-only
+    // v is write-only
+    // dilation_h is write-only
+    // dilation_w is write-only
+    // mode is write-only
+    // computeType is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionForwardAlgorithmEx(handle_native, xDesc_native, x_native, wDesc_native, w_native, convDesc_native, yDesc_native, y_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolution2dDescriptor(convDesc_native, &pad_h_native, &pad_w_native, &u_native, &v_native, &dilation_h_native, &dilation_w_native, &mode_native, &computeType_native);
 
     // Write back native variable values
-    // handle is read-only
-    // xDesc is read-only
-    // x is a native pointer
-    // wDesc is read-only
-    // w is a native pointer
     // convDesc is read-only
-    // yDesc is read-only
-    // y is a native pointer
-    // requestedAlgoCount is primitive
-    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // workSpace is a native pointer
-    // workSpaceSizeInBytes is primitive
+    if (!set(env, pad_h, 0, (jint)pad_h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, pad_w, 0, (jint)pad_w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, u, 0, (jint)u_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, v, 0, (jint)v_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, dilation_h, 0, (jint)dilation_h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, dilation_w, 0, (jint)dilation_w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, computeType, 0, (jint)computeType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
+/** Helper function to return the dimensions of the output tensor given a convolution descriptor */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dForwardOutputDimNative(JNIEnv *env, jclass cls, jobject convDesc, jobject inputTensorDesc, jobject filterDesc, jintArray n, jintArray c, jintArray h, jintArray w)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (xDesc == NULL)
+    if (inputTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputTensorDesc' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (n == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'n' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (c == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'c' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // preference is primitive
-    // memoryLimitInBytes is primitive
-    if (algo == NULL)
+    if (h == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionForwardAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'h' is null for cudnnGetConvolution2dForwardOutputDim");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (w == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnGetConvolution2dForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardAlgorithm(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
-        handle, xDesc, wDesc, convDesc, yDesc, preference, memoryLimitInBytes, algo);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolution2dForwardOutputDim(convDesc=%p, inputTensorDesc=%p, filterDesc=%p, n=%p, c=%p, h=%p, w=%p)\n",
+        convDesc, inputTensorDesc, filterDesc, n, c, h, w);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t xDesc_native;
-    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    cudnnConvolutionFwdPreference_t preference_native;
-    size_t memoryLimitInBytes_native = 0;
-    cudnnConvolutionFwdAlgo_t algo_native;
+    cudnnTensorDescriptor_t inputTensorDesc_native;
+    cudnnFilterDescriptor_t filterDesc_native;
+    int n_native;
+    int c_native;
+    int h_native;
+    int w_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    preference_native = (cudnnConvolutionFwdPreference_t)preference;
-    memoryLimitInBytes_native = (size_t)memoryLimitInBytes;
-    // algo is write-only
+    inputTensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, inputTensorDesc);
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    // n is write-only
+    // c is write-only
+    // h is write-only
+    // w is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardAlgorithm(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolution2dForwardOutputDim(convDesc_native, inputTensorDesc_native, filterDesc_native, &n_native, &c_native, &h_native, &w_native);
 
     // Write back native variable values
-    // handle is read-only
-    // xDesc is read-only
-    // wDesc is read-only
     // convDesc is read-only
-    // yDesc is read-only
-    // preference is primitive
-    // memoryLimitInBytes is primitive
-    if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // inputTensorDesc is read-only
+    // filterDesc is read-only
+    if (!set(env, n, 0, (jint)n_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, c, 0, (jint)c_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, h, 0, (jint)h_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, w, 0, (jint)w_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/**
-*  convolution algorithm (which requires potentially some workspace)
-*/
-/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint algo, jlongArray sizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionNdDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint arrayLength, jintArray padA, jintArray filterStrideA, jintArray dilationA, jint mode, jint computeType)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (xDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnSetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    // arrayLength is primitive
+    if (padA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'padA' is null for cudnnSetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (filterStrideA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterStrideA' is null for cudnnSetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // algo is primitive
-    if (sizeInBytes == NULL)
+    if (dilationA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dilationA' is null for cudnnSetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
+    // mode is primitive
+    // computeType is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardWorkspaceSize(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, algo=%d, sizeInBytes=%p)\n",
-        handle, xDesc, wDesc, convDesc, yDesc, algo, sizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnSetConvolutionNdDescriptor(convDesc=%p, arrayLength=%d, padA=%p, filterStrideA=%p, dilationA=%p, mode=%d, computeType=%d)\n",
+        convDesc, arrayLength, padA, filterStrideA, dilationA, mode, computeType);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnTensorDescriptor_t xDesc_native;
-    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t yDesc_native;
-    cudnnConvolutionFwdAlgo_t algo_native;
-    size_t sizeInBytes_native;
+    int arrayLength_native = 0;
+    int * padA_native = NULL;
+    int * filterStrideA_native = NULL;
+    int * dilationA_native = NULL;
+    cudnnConvolutionMode_t mode_native;
+    cudnnDataType_t computeType_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    algo_native = (cudnnConvolutionFwdAlgo_t)algo;
-    // sizeInBytes is write-only
+    arrayLength_native = (int)arrayLength;
+    if (!initNative(env, padA, padA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!initNative(env, filterStrideA, filterStrideA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!initNative(env, dilationA, dilationA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    mode_native = (cudnnConvolutionMode_t)mode;
+    computeType_native = (cudnnDataType_t)computeType;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardWorkspaceSize(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, algo_native, &sizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnSetConvolutionNdDescriptor(convDesc_native, arrayLength_native, padA_native, filterStrideA_native, dilationA_native, mode_native, computeType_native);
 
     // Write back native variable values
-    // handle is read-only
-    // xDesc is read-only
-    // wDesc is read-only
     // convDesc is read-only
-    // yDesc is read-only
-    // algo is primitive
-    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // arrayLength is primitive
+    if (!releaseNative(env, padA_native, padA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, filterStrideA_native, filterStrideA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, dilationA_native, dilationA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // mode is primitive
+    // computeType is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Convolution functions: All of the form "output = alpha * Op(inputs) + beta * output" */
-/** Function to perform the forward pass for batch convolution */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionForwardNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject xDesc, jobject x, jobject wDesc, jobject w, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject yDesc, jobject y)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionNdDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc, jint arrayLengthRequested, jintArray arrayLength, jintArray padA, jintArray strideA, jintArray dilationA, jintArray mode, jintArray computeType)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionForward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (alpha == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionForward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (xDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnConvolutionForward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (x == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnConvolutionForward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    // arrayLengthRequested is primitive
+    if (arrayLength == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'arrayLength' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (padA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'padA' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // algo is primitive
-    if (workSpace == NULL)
+    if (strideA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'strideA' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
-    if (beta == NULL)
+    if (dilationA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dilationA' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (mode == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (computeType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnConvolutionForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'computeType' is null for cudnnGetConvolutionNdDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnConvolutionForward(handle=%p, alpha=%p, xDesc=%p, x=%p, wDesc=%p, w=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, yDesc=%p, y=%p)\n",
-        handle, alpha, xDesc, x, wDesc, w, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, yDesc, y);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionNdDescriptor(convDesc=%p, arrayLengthRequested=%d, arrayLength=%p, padA=%p, strideA=%p, dilationA=%p, mode=%p, computeType=%p)\n",
+        convDesc, arrayLengthRequested, arrayLength, padA, strideA, dilationA, mode, computeType);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    void * alpha_native = NULL;
-    cudnnTensorDescriptor_t xDesc_native;
-    void * x_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
-    void * w_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnConvolutionFwdAlgo_t algo_native;
-    void * workSpace_native = NULL;
-    size_t workSpaceSizeInBytes_native = 0;
-    void * beta_native = NULL;
-    cudnnTensorDescriptor_t yDesc_native;
-    void * y_native = NULL;
+    int arrayLengthRequested_native = 0;
+    int arrayLength_native;
+    int * padA_native = NULL;
+    int * strideA_native = NULL;
+    int * dilationA_native = NULL;
+    cudnnConvolutionMode_t mode_native;
+    cudnnDataType_t computeType_native;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    PointerData *alpha_pointerData = initPointerData(env, alpha);
-    if (alpha_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    alpha_native = (void *)alpha_pointerData->getPointer(env);
-    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    x_native = (void *)getPointer(env, x);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    w_native = (void *)getPointer(env, w);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    algo_native = (cudnnConvolutionFwdAlgo_t)algo;
-    workSpace_native = (void *)getPointer(env, workSpace);
-    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
-    PointerData *beta_pointerData = initPointerData(env, beta);
-    if (beta_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    beta_native = (void *)beta_pointerData->getPointer(env);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    y_native = (void *)getPointer(env, y);
+    arrayLengthRequested_native = (int)arrayLengthRequested;
+    // arrayLength is write-only
+    if (!initNative(env, padA, padA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!initNative(env, strideA, strideA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!initNative(env, dilationA, dilationA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // mode is write-only
+    // computeType is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnConvolutionForward(handle_native, alpha_native, xDesc_native, x_native, wDesc_native, w_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, yDesc_native, y_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionNdDescriptor(convDesc_native, arrayLengthRequested_native, &arrayLength_native, padA_native, strideA_native, dilationA_native, &mode_native, &computeType_native);
 
     // Write back native variable values
-    // handle is read-only
-    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // xDesc is read-only
-    // x is a native pointer
-    // wDesc is read-only
-    // w is a native pointer
     // convDesc is read-only
-    // algo is primitive
-    // workSpace is a native pointer
-    // workSpaceSizeInBytes is primitive
-    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // yDesc is read-only
-    // y is a native pointer
+    // arrayLengthRequested is primitive
+    if (!set(env, arrayLength, 0, (jint)arrayLength_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, padA_native, padA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, strideA_native, strideA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, dilationA_native, dilationA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, computeType, 0, (jint)computeType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Function to compute the bias gradient for batch convolution */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardBiasNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject dyDesc, jobject dy, jobject beta, jobject dbDesc, jobject db)
+/** Helper function to return the dimensions of the output tensor given a convolution descriptor */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionNdForwardOutputDimNative(JNIEnv *env, jclass cls, jobject convDesc, jobject inputTensorDesc, jobject filterDesc, jint nbDims, jintArray tensorOuputDimA)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardBias");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (alpha == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardBias");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dyDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardBias");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dy == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardBias");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (beta == NULL)
+    if (inputTensorDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardBias");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputTensorDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dbDesc == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dbDesc' is null for cudnnConvolutionBackwardBias");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolutionNdForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (db == NULL)
+    // nbDims is primitive
+    if (tensorOuputDimA == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'db' is null for cudnnConvolutionBackwardBias");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'tensorOuputDimA' is null for cudnnGetConvolutionNdForwardOutputDim");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardBias(handle=%p, alpha=%p, dyDesc=%p, dy=%p, beta=%p, dbDesc=%p, db=%p)\n",
-        handle, alpha, dyDesc, dy, beta, dbDesc, db);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionNdForwardOutputDim(convDesc=%p, inputTensorDesc=%p, filterDesc=%p, nbDims=%d, tensorOuputDimA=%p)\n",
+        convDesc, inputTensorDesc, filterDesc, nbDims, tensorOuputDimA);
 
     // Native variable declarations
-    cudnnHandle_t handle_native;
-    void * alpha_native = NULL;
-    cudnnTensorDescriptor_t dyDesc_native;
-    void * dy_native = NULL;
-    void * beta_native = NULL;
-    cudnnTensorDescriptor_t dbDesc_native;
-    void * db_native = NULL;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t inputTensorDesc_native;
+    cudnnFilterDescriptor_t filterDesc_native;
+    int nbDims_native = 0;
+    int * tensorOuputDimA_native = NULL;
 
     // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    PointerData *alpha_pointerData = initPointerData(env, alpha);
-    if (alpha_pointerData == NULL)
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    inputTensorDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, inputTensorDesc);
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    nbDims_native = (int)nbDims;
+    if (!initNative(env, tensorOuputDimA, tensorOuputDimA_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionNdForwardOutputDim(convDesc_native, inputTensorDesc_native, filterDesc_native, nbDims_native, tensorOuputDimA_native);
+
+    // Write back native variable values
+    // convDesc is read-only
+    // inputTensorDesc is read-only
+    // filterDesc is read-only
+    // nbDims is primitive
+    if (!releaseNative(env, tensorOuputDimA_native, tensorOuputDimA, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Destroy an instance of convolution descriptor */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyConvolutionDescriptorNative(JNIEnv *env, jclass cls, jobject convDesc)
+{
+    // Null-checks for non-primitive arguments
+    if (convDesc == NULL)
     {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnDestroyConvolutionDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    alpha_native = (void *)alpha_pointerData->getPointer(env);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    dy_native = (void *)getPointer(env, dy);
-    PointerData *beta_pointerData = initPointerData(env, beta);
-    if (beta_pointerData == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyConvolutionDescriptor(convDesc=%p)\n",
+        convDesc);
+
+    // Native variable declarations
+    cudnnConvolutionDescriptor_t convDesc_native;
+
+    // Obtain native variable values
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDestroyConvolutionDescriptor(convDesc_native);
+
+    // Write back native variable values
+    // convDesc is read-only
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithmMaxCountNative(JNIEnv *env, jclass cls, jobject handle, jintArray count)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
     {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardAlgorithmMaxCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    beta_native = (void *)beta_pointerData->getPointer(env);
-    dbDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dbDesc);
-    db_native = (void *)getPointer(env, db);
+    if (count == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'count' is null for cudnnGetConvolutionForwardAlgorithmMaxCount");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardAlgorithmMaxCount(handle=%p, count=%p)\n",
+        handle, count);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    int count_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    // count is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardBias(handle_native, alpha_native, dyDesc_native, dy_native, beta_native, dbDesc_native, db_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardAlgorithmMaxCount(handle_native, &count_native);
 
     // Write back native variable values
     // handle is read-only
-    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dyDesc is read-only
-    // dy is a native pointer
-    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dbDesc is read-only
-    // db is a native pointer
+    if (!set(env, count, 0, (jint)count_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilterAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject dwDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionForwardAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (wDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dwDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // requestedAlgoCount is primitive
     if (returnedAlgoCount == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (perfResults == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardFilterAlgorithm(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, dwDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
-        handle, xDesc, dyDesc, convDesc, dwDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionForwardAlgorithm(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, xDesc, wDesc, convDesc, yDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     cudnnTensorDescriptor_t xDesc_native;
-    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnFilterDescriptor_t dwDesc_native;
+    cudnnTensorDescriptor_t yDesc_native;
     int requestedAlgoCount_native = 0;
     int returnedAlgoCount_native;
-    cudnnConvolutionBwdFilterAlgoPerf_t * perfResults_native;
+    cudnnConvolutionFwdAlgoPerf_t * perfResults_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
     requestedAlgoCount_native = (int)requestedAlgoCount;
     // returnedAlgoCount is write-only
     if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardFilterAlgorithm(handle_native, xDesc_native, dyDesc_native, convDesc_native, dwDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionForwardAlgorithm(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
 
     // Write back native variable values
     // handle is read-only
     // xDesc is read-only
-    // dyDesc is read-only
+    // wDesc is read-only
     // convDesc is read-only
-    // dwDesc is read-only
+    // yDesc is read-only
     // requestedAlgoCount is primitive
     if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
     if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
@@ -3128,83 +3207,83 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilt
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilterAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject dyDesc, jobject y, jobject convDesc, jobject dwDesc, jobject dw, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionForwardAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject wDesc, jobject w, jobject convDesc, jobject yDesc, jobject y, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (x == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (wDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dwDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dw == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // requestedAlgoCount is primitive
     if (returnedAlgoCount == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (perfResults == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (workSpace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionForwardAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // workSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardFilterAlgorithmEx(handle=%p, xDesc=%p, x=%p, dyDesc=%p, y=%p, convDesc=%p, dwDesc=%p, dw=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
-        handle, xDesc, x, dyDesc, y, convDesc, dwDesc, dw, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionForwardAlgorithmEx(handle=%p, xDesc=%p, x=%p, wDesc=%p, w=%p, convDesc=%p, yDesc=%p, y=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
+        handle, xDesc, x, wDesc, w, convDesc, yDesc, y, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     cudnnTensorDescriptor_t xDesc_native;
     void * x_native = NULL;
-    cudnnTensorDescriptor_t dyDesc_native;
-    void * y_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnFilterDescriptor_t dwDesc_native;
-    void * dw_native = NULL;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
     int requestedAlgoCount_native = 0;
     int returnedAlgoCount_native;
-    cudnnConvolutionBwdFilterAlgoPerf_t * perfResults_native;
+    cudnnConvolutionFwdAlgoPerf_t * perfResults_native;
     void * workSpace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
 
@@ -3212,11 +3291,11 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilt
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
     x_native = (void *)getPointer(env, x);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    y_native = (void *)getPointer(env, y);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
-    dw_native = (void *)getPointer(env, dw);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
     requestedAlgoCount_native = (int)requestedAlgoCount;
     // returnedAlgoCount is write-only
     if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
@@ -3224,17 +3303,17 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilt
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardFilterAlgorithmEx(handle_native, xDesc_native, x_native, dyDesc_native, y_native, convDesc_native, dwDesc_native, dw_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionForwardAlgorithmEx(handle_native, xDesc_native, x_native, wDesc_native, w_native, convDesc_native, yDesc_native, y_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
     // xDesc is read-only
     // x is a native pointer
-    // dyDesc is read-only
-    // y is a native pointer
+    // wDesc is read-only
+    // w is a native pointer
     // convDesc is read-only
-    // dwDesc is read-only
-    // dw is a native pointer
+    // yDesc is read-only
+    // y is a native pointer
     // requestedAlgoCount is primitive
     if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
     if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
@@ -3246,75 +3325,75 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilt
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject dwDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (wDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dwDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // preference is primitive
     // memoryLimitInBytes is primitive
     if (algo == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionForwardAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterAlgorithm(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, dwDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
-        handle, xDesc, dyDesc, convDesc, dwDesc, preference, memoryLimitInBytes, algo);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardAlgorithm(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
+        handle, xDesc, wDesc, convDesc, yDesc, preference, memoryLimitInBytes, algo);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     cudnnTensorDescriptor_t xDesc_native;
-    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnFilterDescriptor_t dwDesc_native;
-    cudnnConvolutionBwdFilterPreference_t preference_native;
+    cudnnTensorDescriptor_t yDesc_native;
+    cudnnConvolutionFwdPreference_t preference_native;
     size_t memoryLimitInBytes_native = 0;
-    cudnnConvolutionBwdFilterAlgo_t algo_native;
+    cudnnConvolutionFwdAlgo_t algo_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
-    preference_native = (cudnnConvolutionBwdFilterPreference_t)preference;
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    preference_native = (cudnnConvolutionFwdPreference_t)preference;
     memoryLimitInBytes_native = (size_t)memoryLimitInBytes;
     // algo is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterAlgorithm(handle_native, xDesc_native, dyDesc_native, convDesc_native, dwDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardAlgorithm(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
 
     // Write back native variable values
     // handle is read-only
     // xDesc is read-only
-    // dyDesc is read-only
+    // wDesc is read-only
     // convDesc is read-only
-    // dwDesc is read-only
+    // yDesc is read-only
     // preference is primitive
     // memoryLimitInBytes is primitive
     if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
@@ -3324,76 +3403,158 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilte
     return jniResult;
 }
 
-/**
-*  convolution algorithm (which requires potentially some workspace)
-*/
-/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject gradDesc, jint algo, jlongArray sizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithm_1v7Native(JNIEnv *env, jclass cls, jobject handle, jobject srcDesc, jobject filterDesc, jobject convDesc, jobject destDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (xDesc == NULL)
+    if (srcDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'srcDesc' is null for cudnnGetConvolutionForwardAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (filterDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolutionForwardAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionForwardAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (gradDesc == NULL)
+    if (destDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'destDesc' is null for cudnnGetConvolutionForwardAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnGetConvolutionForwardAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (perfResults == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnGetConvolutionForwardAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardAlgorithm_v7(handle=%p, srcDesc=%p, filterDesc=%p, convDesc=%p, destDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, srcDesc, filterDesc, convDesc, destDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t srcDesc_native;
+    cudnnFilterDescriptor_t filterDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t destDesc_native;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionFwdAlgoPerf_t * perfResults_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    srcDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, srcDesc);
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    destDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, destDesc);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardAlgorithm_v7(handle_native, srcDesc_native, filterDesc_native, convDesc_native, destDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // srcDesc is read-only
+    // filterDesc is read-only
+    // convDesc is read-only
+    // destDesc is read-only
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/**
+*  convolution algorithm (which requires potentially some workspace)
+*/
+/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject wDesc, jobject convDesc, jobject yDesc, jint algo, jlongArray sizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (yDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnGetConvolutionForwardWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // algo is primitive
     if (sizeInBytes == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionForwardWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterWorkspaceSize(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, gradDesc=%p, algo=%d, sizeInBytes=%p)\n",
-        handle, xDesc, dyDesc, convDesc, gradDesc, algo, sizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionForwardWorkspaceSize(handle=%p, xDesc=%p, wDesc=%p, convDesc=%p, yDesc=%p, algo=%d, sizeInBytes=%p)\n",
+        handle, xDesc, wDesc, convDesc, yDesc, algo, sizeInBytes);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     cudnnTensorDescriptor_t xDesc_native;
-    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnFilterDescriptor_t wDesc_native;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnFilterDescriptor_t gradDesc_native;
-    cudnnConvolutionBwdFilterAlgo_t algo_native;
+    cudnnTensorDescriptor_t yDesc_native;
+    cudnnConvolutionFwdAlgo_t algo_native;
     size_t sizeInBytes_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    gradDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, gradDesc);
-    algo_native = (cudnnConvolutionBwdFilterAlgo_t)algo;
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    algo_native = (cudnnConvolutionFwdAlgo_t)algo;
     // sizeInBytes is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterWorkspaceSize(handle_native, xDesc_native, dyDesc_native, convDesc_native, gradDesc_native, algo_native, &sizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionForwardWorkspaceSize(handle_native, xDesc_native, wDesc_native, convDesc_native, yDesc_native, algo_native, &sizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
     // xDesc is read-only
-    // dyDesc is read-only
+    // wDesc is read-only
     // convDesc is read-only
-    // gradDesc is read-only
+    // yDesc is read-only
     // algo is primitive
     if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
@@ -3402,85 +3563,87 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilte
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardFilterNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject xDesc, jobject x, jobject dyDesc, jobject dy, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject dwDesc, jobject dw)
+/** Convolution functions: All of the form "output = alpha * Op(inputs) + beta * output" */
+/** Function to perform the forward pass for batch convolution */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionForwardNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject xDesc, jobject x, jobject wDesc, jobject w, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject yDesc, jobject y)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (alpha == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (x == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (wDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dy == NULL)
+    if (w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // algo is primitive
     if (workSpace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // workSpaceSizeInBytes is primitive
     if (beta == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dwDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dw == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnConvolutionBackwardFilter");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnConvolutionForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardFilter(handle=%p, alpha=%p, xDesc=%p, x=%p, dyDesc=%p, dy=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, dwDesc=%p, dw=%p)\n",
-        handle, alpha, xDesc, x, dyDesc, dy, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, dwDesc, dw);
+    Logger::log(LOG_TRACE, "Executing cudnnConvolutionForward(handle=%p, alpha=%p, xDesc=%p, x=%p, wDesc=%p, w=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, yDesc=%p, y=%p)\n",
+        handle, alpha, xDesc, x, wDesc, w, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, yDesc, y);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     void * alpha_native = NULL;
     cudnnTensorDescriptor_t xDesc_native;
     void * x_native = NULL;
-    cudnnTensorDescriptor_t dyDesc_native;
-    void * dy_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnConvolutionBwdFilterAlgo_t algo_native;
+    cudnnConvolutionFwdAlgo_t algo_native;
     void * workSpace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
     void * beta_native = NULL;
-    cudnnFilterDescriptor_t dwDesc_native;
-    void * dw_native = NULL;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
@@ -3492,10 +3655,10 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardFilterNa
     alpha_native = (void *)alpha_pointerData->getPointer(env);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
     x_native = (void *)getPointer(env, x);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    dy_native = (void *)getPointer(env, dy);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    algo_native = (cudnnConvolutionBwdFilterAlgo_t)algo;
+    algo_native = (cudnnConvolutionFwdAlgo_t)algo;
     workSpace_native = (void *)getPointer(env, workSpace);
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
     PointerData *beta_pointerData = initPointerData(env, beta);
@@ -3504,730 +3667,1712 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardFilterNa
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     beta_native = (void *)beta_pointerData->getPointer(env);
-    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
-    dw_native = (void *)getPointer(env, dw);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardFilter(handle_native, alpha_native, xDesc_native, x_native, dyDesc_native, dy_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, dwDesc_native, dw_native);
+    cudnnStatus_t jniResult_native = cudnnConvolutionForward(handle_native, alpha_native, xDesc_native, x_native, wDesc_native, w_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, yDesc_native, y_native);
 
     // Write back native variable values
     // handle is read-only
     if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
     // xDesc is read-only
     // x is a native pointer
-    // dyDesc is read-only
-    // dy is a native pointer
+    // wDesc is read-only
+    // w is a native pointer
     // convDesc is read-only
     // algo is primitive
     // workSpace is a native pointer
     // workSpaceSizeInBytes is primitive
     if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dwDesc is read-only
-    // dw is a native pointer
+    // yDesc is read-only
+    // y is a native pointer
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardDataAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
+/** Fused conv/bias/activation operation : y = Act( alpha1 * conv(x) + alpha2 * z + bias ) */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBiasActivationForwardNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha1, jobject xDesc, jobject x, jobject wDesc, jobject w, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject alpha2, jobject zDesc, jobject z, jobject biasDesc, jobject bias, jobject activationDesc, jobject yDesc, jobject y)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (alpha1 == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha1' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (x == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    if (wDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // requestedAlgoCount is primitive
-    if (returnedAlgoCount == NULL)
+    if (w == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (perfResults == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-
-    // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardDataAlgorithm(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
-        handle, wDesc, dyDesc, convDesc, dxDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
-
-    // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnFilterDescriptor_t wDesc_native;
-    cudnnTensorDescriptor_t dyDesc_native;
-    cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t dxDesc_native;
-    int requestedAlgoCount_native = 0;
-    int returnedAlgoCount_native;
-    cudnnConvolutionBwdDataAlgoPerf_t * perfResults_native;
-
-    // Obtain native variable values
-    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
-    requestedAlgoCount_native = (int)requestedAlgoCount;
-    // returnedAlgoCount is write-only
-    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
-
-    // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardDataAlgorithm(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
-
-    // Write back native variable values
-    // handle is read-only
-    // wDesc is read-only
-    // dyDesc is read-only
-    // convDesc is read-only
-    // dxDesc is read-only
-    // requestedAlgoCount is primitive
-    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-
-    // Return the result
-    jint jniResult = (jint)jniResult_native;
-    return jniResult;
-}
-
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardDataAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject w, jobject dyDesc, jobject dy, jobject convDesc, jobject dxDesc, jobject dx, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
-{
-    // Null-checks for non-primitive arguments
-    if (handle == NULL)
+    // algo is primitive
+    if (workSpace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    // workSpaceSizeInBytes is primitive
+    if (alpha2 == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha2' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (zDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'zDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (z == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'z' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dy == NULL)
+    if (biasDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'biasDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (bias == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'bias' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    if (activationDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'activationDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dx == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // requestedAlgoCount is primitive
-    if (returnedAlgoCount == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (perfResults == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (workSpace == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnConvolutionBiasActivationForward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardDataAlgorithmEx(handle=%p, wDesc=%p, w=%p, dyDesc=%p, dy=%p, convDesc=%p, dxDesc=%p, dx=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
-        handle, wDesc, w, dyDesc, dy, convDesc, dxDesc, dx, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBiasActivationForward(handle=%p, alpha1=%p, xDesc=%p, x=%p, wDesc=%p, w=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, alpha2=%p, zDesc=%p, z=%p, biasDesc=%p, bias=%p, activationDesc=%p, yDesc=%p, y=%p)\n",
+        handle, alpha1, xDesc, x, wDesc, w, convDesc, algo, workSpace, workSpaceSizeInBytes, alpha2, zDesc, z, biasDesc, bias, activationDesc, yDesc, y);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
+    void * alpha1_native = NULL;
+    cudnnTensorDescriptor_t xDesc_native;
+    void * x_native = NULL;
     cudnnFilterDescriptor_t wDesc_native;
     void * w_native = NULL;
-    cudnnTensorDescriptor_t dyDesc_native;
-    void * dy_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t dxDesc_native;
-    void * dx_native = NULL;
-    int requestedAlgoCount_native = 0;
-    int returnedAlgoCount_native;
-    cudnnConvolutionBwdDataAlgoPerf_t * perfResults_native;
+    cudnnConvolutionFwdAlgo_t algo_native;
     void * workSpace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
+    void * alpha2_native = NULL;
+    cudnnTensorDescriptor_t zDesc_native;
+    void * z_native = NULL;
+    cudnnTensorDescriptor_t biasDesc_native;
+    void * bias_native = NULL;
+    cudnnActivationDescriptor_t activationDesc_native;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    PointerData *alpha1_pointerData = initPointerData(env, alpha1);
+    if (alpha1_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha1_native = (void *)alpha1_pointerData->getPointer(env);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
+    x_native = (void *)getPointer(env, x);
     wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
     w_native = (void *)getPointer(env, w);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    dy_native = (void *)getPointer(env, dy);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
-    dx_native = (void *)getPointer(env, dx);
-    requestedAlgoCount_native = (int)requestedAlgoCount;
-    // returnedAlgoCount is write-only
-    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    algo_native = (cudnnConvolutionFwdAlgo_t)algo;
     workSpace_native = (void *)getPointer(env, workSpace);
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    PointerData *alpha2_pointerData = initPointerData(env, alpha2);
+    if (alpha2_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha2_native = (void *)alpha2_pointerData->getPointer(env);
+    zDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, zDesc);
+    z_native = (void *)getPointer(env, z);
+    biasDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, biasDesc);
+    bias_native = (void *)getPointer(env, bias);
+    activationDesc_native = (cudnnActivationDescriptor_t)getNativePointerValue(env, activationDesc);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardDataAlgorithmEx(handle_native, wDesc_native, w_native, dyDesc_native, dy_native, convDesc_native, dxDesc_native, dx_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnConvolutionBiasActivationForward(handle_native, alpha1_native, xDesc_native, x_native, wDesc_native, w_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, alpha2_native, zDesc_native, z_native, biasDesc_native, bias_native, activationDesc_native, yDesc_native, y_native);
 
     // Write back native variable values
     // handle is read-only
+    if (!releasePointerData(env, alpha1_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // xDesc is read-only
+    // x is a native pointer
     // wDesc is read-only
     // w is a native pointer
-    // dyDesc is read-only
-    // dy is a native pointer
     // convDesc is read-only
-    // dxDesc is read-only
-    // dx is a native pointer
-    // requestedAlgoCount is primitive
-    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // algo is primitive
     // workSpace is a native pointer
     // workSpaceSizeInBytes is primitive
+    if (!releasePointerData(env, alpha2_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // zDesc is read-only
+    // z is a native pointer
+    // biasDesc is read-only
+    // bias is a native pointer
+    // activationDesc is read-only
+    // yDesc is read-only
+    // y is a native pointer
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
+/** Function to compute the bias gradient for batch convolution */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardBiasNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject dyDesc, jobject dy, jobject beta, jobject dbDesc, jobject db)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (alpha == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (dyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (convDesc == NULL)
+    if (dy == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    if (beta == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // preference is primitive
-    // memoryLimitInBytes is primitive
-    if (algo == NULL)
+    if (dbDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dbDesc' is null for cudnnConvolutionBackwardBias");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (db == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'db' is null for cudnnConvolutionBackwardBias");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataAlgorithm(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
-        handle, wDesc, dyDesc, convDesc, dxDesc, preference, memoryLimitInBytes, algo);
+    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardBias(handle=%p, alpha=%p, dyDesc=%p, dy=%p, beta=%p, dbDesc=%p, db=%p)\n",
+        handle, alpha, dyDesc, dy, beta, dbDesc, db);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
-    cudnnFilterDescriptor_t wDesc_native;
+    void * alpha_native = NULL;
     cudnnTensorDescriptor_t dyDesc_native;
-    cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t dxDesc_native;
-    cudnnConvolutionBwdDataPreference_t preference_native;
-    size_t memoryLimitInBytes_native = 0;
-    cudnnConvolutionBwdDataAlgo_t algo_native;
+    void * dy_native = NULL;
+    void * beta_native = NULL;
+    cudnnTensorDescriptor_t dbDesc_native;
+    void * db_native = NULL;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
     dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
-    preference_native = (cudnnConvolutionBwdDataPreference_t)preference;
-    memoryLimitInBytes_native = (size_t)memoryLimitInBytes;
-    // algo is write-only
+    dy_native = (void *)getPointer(env, dy);
+    PointerData *beta_pointerData = initPointerData(env, beta);
+    if (beta_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    beta_native = (void *)beta_pointerData->getPointer(env);
+    dbDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dbDesc);
+    db_native = (void *)getPointer(env, db);
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataAlgorithm(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
+    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardBias(handle_native, alpha_native, dyDesc_native, dy_native, beta_native, dbDesc_native, db_native);
 
     // Write back native variable values
     // handle is read-only
-    // wDesc is read-only
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
     // dyDesc is read-only
-    // convDesc is read-only
-    // dxDesc is read-only
-    // preference is primitive
-    // memoryLimitInBytes is primitive
-    if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dy is a native pointer
+    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dbDesc is read-only
+    // db is a native pointer
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint algo, jlongArray sizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithmMaxCountNative(JNIEnv *env, jclass cls, jobject handle, jintArray count)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dyDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (convDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dxDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterAlgorithmMaxCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // algo is primitive
-    if (sizeInBytes == NULL)
+    if (count == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'count' is null for cudnnGetConvolutionBackwardFilterAlgorithmMaxCount");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataWorkspaceSize(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, algo=%d, sizeInBytes=%p)\n",
-        handle, wDesc, dyDesc, convDesc, dxDesc, algo, sizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterAlgorithmMaxCount(handle=%p, count=%p)\n",
+        handle, count);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
-    cudnnFilterDescriptor_t wDesc_native;
-    cudnnTensorDescriptor_t dyDesc_native;
-    cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnTensorDescriptor_t dxDesc_native;
-    cudnnConvolutionBwdDataAlgo_t algo_native;
-    size_t sizeInBytes_native;
+    int count_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
-    algo_native = (cudnnConvolutionBwdDataAlgo_t)algo;
-    // sizeInBytes is write-only
+    // count is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataWorkspaceSize(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, algo_native, &sizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterAlgorithmMaxCount(handle_native, &count_native);
 
     // Write back native variable values
     // handle is read-only
-    // wDesc is read-only
-    // dyDesc is read-only
-    // convDesc is read-only
-    // dxDesc is read-only
-    // algo is primitive
-    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, count, 0, (jint)count_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardDataNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject wDesc, jobject w, jobject dyDesc, jobject dy, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject dxDesc, jobject dx)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilterAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject dwDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (alpha == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (dyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dy == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // algo is primitive
-    if (workSpace == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
-    if (beta == NULL)
+    if (dwDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dx == NULL)
+    if (perfResults == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnConvolutionBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardData(handle=%p, alpha=%p, wDesc=%p, w=%p, dyDesc=%p, dy=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, dxDesc=%p, dx=%p)\n",
-        handle, alpha, wDesc, w, dyDesc, dy, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, dxDesc, dx);
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardFilterAlgorithm(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, dwDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, xDesc, dyDesc, convDesc, dwDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
-    void * alpha_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
-    void * w_native = NULL;
+    cudnnTensorDescriptor_t xDesc_native;
     cudnnTensorDescriptor_t dyDesc_native;
-    void * dy_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    cudnnConvolutionBwdDataAlgo_t algo_native;
-    void * workSpace_native = NULL;
-    size_t workSpaceSizeInBytes_native = 0;
-    void * beta_native = NULL;
-    cudnnTensorDescriptor_t dxDesc_native;
-    void * dx_native = NULL;
+    cudnnFilterDescriptor_t dwDesc_native;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdFilterAlgoPerf_t * perfResults_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    PointerData *alpha_pointerData = initPointerData(env, alpha);
-    if (alpha_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    alpha_native = (void *)alpha_pointerData->getPointer(env);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    w_native = (void *)getPointer(env, w);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
     dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
-    dy_native = (void *)getPointer(env, dy);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    algo_native = (cudnnConvolutionBwdDataAlgo_t)algo;
-    workSpace_native = (void *)getPointer(env, workSpace);
-    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
-    PointerData *beta_pointerData = initPointerData(env, beta);
-    if (beta_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    beta_native = (void *)beta_pointerData->getPointer(env);
-    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
-    dx_native = (void *)getPointer(env, dx);
+    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardData(handle_native, alpha_native, wDesc_native, w_native, dyDesc_native, dy_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, dxDesc_native, dx_native);
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardFilterAlgorithm(handle_native, xDesc_native, dyDesc_native, convDesc_native, dwDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
 
     // Write back native variable values
     // handle is read-only
-    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // wDesc is read-only
-    // w is a native pointer
+    // xDesc is read-only
     // dyDesc is read-only
-    // dy is a native pointer
     // convDesc is read-only
-    // algo is primitive
-    // workSpace is a native pointer
-    // workSpaceSizeInBytes is primitive
-    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dxDesc is read-only
-    // dx is a native pointer
+    // dwDesc is read-only
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnIm2ColNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject wDesc, jobject convDesc, jobject colBuffer)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardFilterAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject dyDesc, jobject y, jobject convDesc, jobject dwDesc, jobject dw, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (x == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (dyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (y == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (colBuffer == NULL)
+    if (dwDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'colBuffer' is null for cudnnIm2Col");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dw == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (perfResults == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (workSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionBackwardFilterAlgorithmEx");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
+    // workSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnIm2Col(handle=%p, xDesc=%p, x=%p, wDesc=%p, convDesc=%p, colBuffer=%p)\n",
-        handle, xDesc, x, wDesc, convDesc, colBuffer);
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardFilterAlgorithmEx(handle=%p, xDesc=%p, x=%p, dyDesc=%p, y=%p, convDesc=%p, dwDesc=%p, dw=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
+        handle, xDesc, x, dyDesc, y, convDesc, dwDesc, dw, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
     cudnnTensorDescriptor_t xDesc_native;
     void * x_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
+    cudnnTensorDescriptor_t dyDesc_native;
+    void * y_native = NULL;
     cudnnConvolutionDescriptor_t convDesc_native;
-    void * colBuffer_native = NULL;
+    cudnnFilterDescriptor_t dwDesc_native;
+    void * dw_native = NULL;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdFilterAlgoPerf_t * perfResults_native;
+    void * workSpace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
     x_native = (void *)getPointer(env, x);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    y_native = (void *)getPointer(env, y);
     convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
-    colBuffer_native = (void *)getPointer(env, colBuffer);
+    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    dw_native = (void *)getPointer(env, dw);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    workSpace_native = (void *)getPointer(env, workSpace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnIm2Col(handle_native, xDesc_native, x_native, wDesc_native, convDesc_native, colBuffer_native);
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardFilterAlgorithmEx(handle_native, xDesc_native, x_native, dyDesc_native, y_native, convDesc_native, dwDesc_native, dw_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
     // xDesc is read-only
     // x is a native pointer
-    // wDesc is read-only
+    // dyDesc is read-only
+    // y is a native pointer
     // convDesc is read-only
-    // colBuffer is a native pointer
+    // dwDesc is read-only
+    // dw is a native pointer
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // workSpace is a native pointer
+    // workSpaceSizeInBytes is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Softmax functions: All of the form "output = alpha * Op(inputs) + beta * output" */
-/** Function to perform forward softmax */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSoftmaxForwardNative(JNIEnv *env, jclass cls, jobject handle, jint algo, jint mode, jobject alpha, jobject xDesc, jobject x, jobject beta, jobject yDesc, jobject y)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject dwDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSoftmaxForward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // algo is primitive
-    // mode is primitive
-    if (alpha == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (xDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (x == NULL)
+    if (dyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (beta == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (dwDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    // preference is primitive
+    // memoryLimitInBytes is primitive
+    if (algo == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSoftmaxForward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionBackwardFilterAlgorithm");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSoftmaxForward(handle=%p, algo=%d, mode=%d, alpha=%p, xDesc=%p, x=%p, beta=%p, yDesc=%p, y=%p)\n",
-        handle, algo, mode, alpha, xDesc, x, beta, yDesc, y);
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterAlgorithm(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, dwDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
+        handle, xDesc, dyDesc, convDesc, dwDesc, preference, memoryLimitInBytes, algo);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
-    cudnnSoftmaxAlgorithm_t algo_native;
-    cudnnSoftmaxMode_t mode_native;
-    void * alpha_native = NULL;
     cudnnTensorDescriptor_t xDesc_native;
-    void * x_native = NULL;
-    void * beta_native = NULL;
-    cudnnTensorDescriptor_t yDesc_native;
-    void * y_native = NULL;
+    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnFilterDescriptor_t dwDesc_native;
+    cudnnConvolutionBwdFilterPreference_t preference_native;
+    size_t memoryLimitInBytes_native = 0;
+    cudnnConvolutionBwdFilterAlgo_t algo_native;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    algo_native = (cudnnSoftmaxAlgorithm_t)algo;
-    mode_native = (cudnnSoftmaxMode_t)mode;
-    PointerData *alpha_pointerData = initPointerData(env, alpha);
-    if (alpha_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    alpha_native = (void *)alpha_pointerData->getPointer(env);
     xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
-    x_native = (void *)getPointer(env, x);
-    PointerData *beta_pointerData = initPointerData(env, beta);
-    if (beta_pointerData == NULL)
-    {
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    beta_native = (void *)beta_pointerData->getPointer(env);
-    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
-    y_native = (void *)getPointer(env, y);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    preference_native = (cudnnConvolutionBwdFilterPreference_t)preference;
+    memoryLimitInBytes_native = (size_t)memoryLimitInBytes;
+    // algo is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSoftmaxForward(handle_native, algo_native, mode_native, alpha_native, xDesc_native, x_native, beta_native, yDesc_native, y_native);
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterAlgorithm(handle_native, xDesc_native, dyDesc_native, convDesc_native, dwDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
 
     // Write back native variable values
     // handle is read-only
-    // algo is primitive
-    // mode is primitive
-    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
     // xDesc is read-only
-    // x is a native pointer
-    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // yDesc is read-only
-    // y is a native pointer
+    // dyDesc is read-only
+    // convDesc is read-only
+    // dwDesc is read-only
+    // preference is primitive
+    // memoryLimitInBytes is primitive
+    if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/** Function to perform backward softmax */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSoftmaxBackwardNative(JNIEnv *env, jclass cls, jobject handle, jint algo, jint mode, jobject alpha, jobject yDesc, jobject y, jobject dyDesc, jobject dy, jobject beta, jobject dxDesc, jobject dx)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithm_1v7Native(JNIEnv *env, jclass cls, jobject handle, jobject srcDesc, jobject diffDesc, jobject convDesc, jobject gradDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSoftmaxBackward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // algo is primitive
-    // mode is primitive
-    if (alpha == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnSoftmaxBackward");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (yDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (srcDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'srcDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dyDesc == NULL)
+    if (diffDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'diffDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dy == NULL)
+    if (convDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (beta == NULL)
+    if (gradDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradDesc' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dx == NULL)
+    if (perfResults == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnSoftmaxBackward");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnGetConvolutionBackwardFilterAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterAlgorithm_v7(handle=%p, srcDesc=%p, diffDesc=%p, convDesc=%p, gradDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, srcDesc, diffDesc, convDesc, gradDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t srcDesc_native;
+    cudnnTensorDescriptor_t diffDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnFilterDescriptor_t gradDesc_native;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdFilterAlgoPerf_t * perfResults_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    srcDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, srcDesc);
+    diffDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, diffDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    gradDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, gradDesc);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterAlgorithm_v7(handle_native, srcDesc_native, diffDesc_native, convDesc_native, gradDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // srcDesc is read-only
+    // diffDesc is read-only
+    // convDesc is read-only
+    // gradDesc is read-only
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/**
+*  convolution algorithm (which requires potentially some workspace)
+*/
+/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject dyDesc, jobject convDesc, jobject gradDesc, jint algo, jlongArray sizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (gradDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradDesc' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    if (sizeInBytes == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionBackwardFilterWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardFilterWorkspaceSize(handle=%p, xDesc=%p, dyDesc=%p, convDesc=%p, gradDesc=%p, algo=%d, sizeInBytes=%p)\n",
+        handle, xDesc, dyDesc, convDesc, gradDesc, algo, sizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t xDesc_native;
+    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnFilterDescriptor_t gradDesc_native;
+    cudnnConvolutionBwdFilterAlgo_t algo_native;
+    size_t sizeInBytes_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    gradDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, gradDesc);
+    algo_native = (cudnnConvolutionBwdFilterAlgo_t)algo;
+    // sizeInBytes is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardFilterWorkspaceSize(handle_native, xDesc_native, dyDesc_native, convDesc_native, gradDesc_native, algo_native, &sizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // xDesc is read-only
+    // dyDesc is read-only
+    // convDesc is read-only
+    // gradDesc is read-only
+    // algo is primitive
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardFilterNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject xDesc, jobject x, jobject dyDesc, jobject dy, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject dwDesc, jobject dw)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (x == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    if (workSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+    if (beta == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dwDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dw == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnConvolutionBackwardFilter");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardFilter(handle=%p, alpha=%p, xDesc=%p, x=%p, dyDesc=%p, dy=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, dwDesc=%p, dw=%p)\n",
+        handle, alpha, xDesc, x, dyDesc, dy, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, dwDesc, dw);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    void * alpha_native = NULL;
+    cudnnTensorDescriptor_t xDesc_native;
+    void * x_native = NULL;
+    cudnnTensorDescriptor_t dyDesc_native;
+    void * dy_native = NULL;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnConvolutionBwdFilterAlgo_t algo_native;
+    void * workSpace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
+    void * beta_native = NULL;
+    cudnnFilterDescriptor_t dwDesc_native;
+    void * dw_native = NULL;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
+    x_native = (void *)getPointer(env, x);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    dy_native = (void *)getPointer(env, dy);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    algo_native = (cudnnConvolutionBwdFilterAlgo_t)algo;
+    workSpace_native = (void *)getPointer(env, workSpace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    PointerData *beta_pointerData = initPointerData(env, beta);
+    if (beta_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    beta_native = (void *)beta_pointerData->getPointer(env);
+    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    dw_native = (void *)getPointer(env, dw);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardFilter(handle_native, alpha_native, xDesc_native, x_native, dyDesc_native, dy_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, dwDesc_native, dw_native);
+
+    // Write back native variable values
+    // handle is read-only
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // xDesc is read-only
+    // x is a native pointer
+    // dyDesc is read-only
+    // dy is a native pointer
+    // convDesc is read-only
+    // algo is primitive
+    // workSpace is a native pointer
+    // workSpaceSizeInBytes is primitive
+    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dwDesc is read-only
+    // dw is a native pointer
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithmMaxCountNative(JNIEnv *env, jclass cls, jobject handle, jintArray count)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataAlgorithmMaxCount");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (count == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'count' is null for cudnnGetConvolutionBackwardDataAlgorithmMaxCount");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataAlgorithmMaxCount(handle=%p, count=%p)\n",
+        handle, count);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    int count_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    // count is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataAlgorithmMaxCount(handle_native, &count_native);
+
+    // Write back native variable values
+    // handle is read-only
+    if (!set(env, count, 0, (jint)count_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardDataAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (perfResults == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardDataAlgorithm(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, wDesc, dyDesc, convDesc, dxDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnFilterDescriptor_t wDesc_native;
+    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t dxDesc_native;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdDataAlgoPerf_t * perfResults_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardDataAlgorithm(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // wDesc is read-only
+    // dyDesc is read-only
+    // convDesc is read-only
+    // dxDesc is read-only
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnFindConvolutionBackwardDataAlgorithmExNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject w, jobject dyDesc, jobject dy, jobject convDesc, jobject dxDesc, jobject dx, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults, jobject workSpace, jlong workSpaceSizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (w == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (perfResults == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (workSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnFindConvolutionBackwardDataAlgorithmEx");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnFindConvolutionBackwardDataAlgorithmEx(handle=%p, wDesc=%p, w=%p, dyDesc=%p, dy=%p, convDesc=%p, dxDesc=%p, dx=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p, workSpace=%p, workSpaceSizeInBytes=%ld)\n",
+        handle, wDesc, w, dyDesc, dy, convDesc, dxDesc, dx, requestedAlgoCount, returnedAlgoCount, perfResults, workSpace, workSpaceSizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
+    cudnnTensorDescriptor_t dyDesc_native;
+    void * dy_native = NULL;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t dxDesc_native;
+    void * dx_native = NULL;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdDataAlgoPerf_t * perfResults_native;
+    void * workSpace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    dy_native = (void *)getPointer(env, dy);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
+    dx_native = (void *)getPointer(env, dx);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    workSpace_native = (void *)getPointer(env, workSpace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnFindConvolutionBackwardDataAlgorithmEx(handle_native, wDesc_native, w_native, dyDesc_native, dy_native, convDesc_native, dxDesc_native, dx_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native, workSpace_native, workSpaceSizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // wDesc is read-only
+    // w is a native pointer
+    // dyDesc is read-only
+    // dy is a native pointer
+    // convDesc is read-only
+    // dxDesc is read-only
+    // dx is a native pointer
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // workSpace is a native pointer
+    // workSpaceSizeInBytes is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithmNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint preference, jlong memoryLimitInBytes, jintArray algo)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // preference is primitive
+    // memoryLimitInBytes is primitive
+    if (algo == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetConvolutionBackwardDataAlgorithm");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataAlgorithm(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, preference=%d, memoryLimitInBytes=%ld, algo=%p)\n",
+        handle, wDesc, dyDesc, convDesc, dxDesc, preference, memoryLimitInBytes, algo);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnFilterDescriptor_t wDesc_native;
+    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t dxDesc_native;
+    cudnnConvolutionBwdDataPreference_t preference_native;
+    size_t memoryLimitInBytes_native = 0;
+    cudnnConvolutionBwdDataAlgo_t algo_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
+    preference_native = (cudnnConvolutionBwdDataPreference_t)preference;
+    memoryLimitInBytes_native = (size_t)memoryLimitInBytes;
+    // algo is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataAlgorithm(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, preference_native, memoryLimitInBytes_native, &algo_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // wDesc is read-only
+    // dyDesc is read-only
+    // convDesc is read-only
+    // dxDesc is read-only
+    // preference is primitive
+    // memoryLimitInBytes is primitive
+    if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithm_1v7Native(JNIEnv *env, jclass cls, jobject handle, jobject filterDesc, jobject diffDesc, jobject convDesc, jobject gradDesc, jint requestedAlgoCount, jintArray returnedAlgoCount, jobjectArray perfResults)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (filterDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'filterDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (diffDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'diffDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (gradDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradDesc' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // requestedAlgoCount is primitive
+    if (returnedAlgoCount == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'returnedAlgoCount' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (perfResults == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'perfResults' is null for cudnnGetConvolutionBackwardDataAlgorithm_v7");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataAlgorithm_v7(handle=%p, filterDesc=%p, diffDesc=%p, convDesc=%p, gradDesc=%p, requestedAlgoCount=%d, returnedAlgoCount=%p, perfResults=%p)\n",
+        handle, filterDesc, diffDesc, convDesc, gradDesc, requestedAlgoCount, returnedAlgoCount, perfResults);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnFilterDescriptor_t filterDesc_native;
+    cudnnTensorDescriptor_t diffDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t gradDesc_native;
+    int requestedAlgoCount_native = 0;
+    int returnedAlgoCount_native;
+    cudnnConvolutionBwdDataAlgoPerf_t * perfResults_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    filterDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, filterDesc);
+    diffDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, diffDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    gradDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, gradDesc);
+    requestedAlgoCount_native = (int)requestedAlgoCount;
+    // returnedAlgoCount is write-only
+    if (!initNative(env, perfResults, perfResults_native, requestedAlgoCount)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataAlgorithm_v7(handle_native, filterDesc_native, diffDesc_native, convDesc_native, gradDesc_native, requestedAlgoCount_native, &returnedAlgoCount_native, perfResults_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // filterDesc is read-only
+    // diffDesc is read-only
+    // convDesc is read-only
+    // gradDesc is read-only
+    // requestedAlgoCount is primitive
+    if (!set(env, returnedAlgoCount, 0, (jint)returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!releaseNative(env, perfResults_native, perfResults, returnedAlgoCount_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject wDesc, jobject dyDesc, jobject convDesc, jobject dxDesc, jint algo, jlongArray sizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    if (sizeInBytes == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetConvolutionBackwardDataWorkspaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetConvolutionBackwardDataWorkspaceSize(handle=%p, wDesc=%p, dyDesc=%p, convDesc=%p, dxDesc=%p, algo=%d, sizeInBytes=%p)\n",
+        handle, wDesc, dyDesc, convDesc, dxDesc, algo, sizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnFilterDescriptor_t wDesc_native;
+    cudnnTensorDescriptor_t dyDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnTensorDescriptor_t dxDesc_native;
+    cudnnConvolutionBwdDataAlgo_t algo_native;
+    size_t sizeInBytes_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
+    algo_native = (cudnnConvolutionBwdDataAlgo_t)algo;
+    // sizeInBytes is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetConvolutionBackwardDataWorkspaceSize(handle_native, wDesc_native, dyDesc_native, convDesc_native, dxDesc_native, algo_native, &sizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // wDesc is read-only
+    // dyDesc is read-only
+    // convDesc is read-only
+    // dxDesc is read-only
+    // algo is primitive
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardDataNative(JNIEnv *env, jclass cls, jobject handle, jobject alpha, jobject wDesc, jobject w, jobject dyDesc, jobject dy, jobject convDesc, jint algo, jobject workSpace, jlong workSpaceSizeInBytes, jobject beta, jobject dxDesc, jobject dx)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (w == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    if (workSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSpace' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+    if (beta == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnConvolutionBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnConvolutionBackwardData(handle=%p, alpha=%p, wDesc=%p, w=%p, dyDesc=%p, dy=%p, convDesc=%p, algo=%d, workSpace=%p, workSpaceSizeInBytes=%ld, beta=%p, dxDesc=%p, dx=%p)\n",
+        handle, alpha, wDesc, w, dyDesc, dy, convDesc, algo, workSpace, workSpaceSizeInBytes, beta, dxDesc, dx);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    void * alpha_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
+    cudnnTensorDescriptor_t dyDesc_native;
+    void * dy_native = NULL;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    cudnnConvolutionBwdDataAlgo_t algo_native;
+    void * workSpace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
+    void * beta_native = NULL;
+    cudnnTensorDescriptor_t dxDesc_native;
+    void * dx_native = NULL;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
+    dyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dyDesc);
+    dy_native = (void *)getPointer(env, dy);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    algo_native = (cudnnConvolutionBwdDataAlgo_t)algo;
+    workSpace_native = (void *)getPointer(env, workSpace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    PointerData *beta_pointerData = initPointerData(env, beta);
+    if (beta_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    beta_native = (void *)beta_pointerData->getPointer(env);
+    dxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dxDesc);
+    dx_native = (void *)getPointer(env, dx);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnConvolutionBackwardData(handle_native, alpha_native, wDesc_native, w_native, dyDesc_native, dy_native, convDesc_native, algo_native, workSpace_native, workSpaceSizeInBytes_native, beta_native, dxDesc_native, dx_native);
+
+    // Write back native variable values
+    // handle is read-only
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // wDesc is read-only
+    // w is a native pointer
+    // dyDesc is read-only
+    // dy is a native pointer
+    // convDesc is read-only
+    // algo is primitive
+    // workSpace is a native pointer
+    // workSpaceSizeInBytes is primitive
+    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dxDesc is read-only
+    // dx is a native pointer
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnIm2ColNative(JNIEnv *env, jclass cls, jobject handle, jobject xDesc, jobject x, jobject wDesc, jobject convDesc, jobject colBuffer)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (x == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (convDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'convDesc' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (colBuffer == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'colBuffer' is null for cudnnIm2Col");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnIm2Col(handle=%p, xDesc=%p, x=%p, wDesc=%p, convDesc=%p, colBuffer=%p)\n",
+        handle, xDesc, x, wDesc, convDesc, colBuffer);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t xDesc_native;
+    void * x_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    cudnnConvolutionDescriptor_t convDesc_native;
+    void * colBuffer_native = NULL;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
+    x_native = (void *)getPointer(env, x);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    convDesc_native = (cudnnConvolutionDescriptor_t)getNativePointerValue(env, convDesc);
+    colBuffer_native = (void *)getPointer(env, colBuffer);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnIm2Col(handle_native, xDesc_native, x_native, wDesc_native, convDesc_native, colBuffer_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // xDesc is read-only
+    // x is a native pointer
+    // wDesc is read-only
+    // convDesc is read-only
+    // colBuffer is a native pointer
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Softmax functions: All of the form "output = alpha * Op(inputs) + beta * output" */
+/** Function to perform forward softmax */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSoftmaxForwardNative(JNIEnv *env, jclass cls, jobject handle, jint algo, jint mode, jobject alpha, jobject xDesc, jobject x, jobject beta, jobject yDesc, jobject y)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    // mode is primitive
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (x == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (beta == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (yDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (y == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSoftmaxForward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSoftmaxForward(handle=%p, algo=%d, mode=%d, alpha=%p, xDesc=%p, x=%p, beta=%p, yDesc=%p, y=%p)\n",
+        handle, algo, mode, alpha, xDesc, x, beta, yDesc, y);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnSoftmaxAlgorithm_t algo_native;
+    cudnnSoftmaxMode_t mode_native;
+    void * alpha_native = NULL;
+    cudnnTensorDescriptor_t xDesc_native;
+    void * x_native = NULL;
+    void * beta_native = NULL;
+    cudnnTensorDescriptor_t yDesc_native;
+    void * y_native = NULL;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    algo_native = (cudnnSoftmaxAlgorithm_t)algo;
+    mode_native = (cudnnSoftmaxMode_t)mode;
+    PointerData *alpha_pointerData = initPointerData(env, alpha);
+    if (alpha_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    alpha_native = (void *)alpha_pointerData->getPointer(env);
+    xDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xDesc);
+    x_native = (void *)getPointer(env, x);
+    PointerData *beta_pointerData = initPointerData(env, beta);
+    if (beta_pointerData == NULL)
+    {
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    beta_native = (void *)beta_pointerData->getPointer(env);
+    yDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, yDesc);
+    y_native = (void *)getPointer(env, y);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSoftmaxForward(handle_native, algo_native, mode_native, alpha_native, xDesc_native, x_native, beta_native, yDesc_native, y_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // algo is primitive
+    // mode is primitive
+    if (!releasePointerData(env, alpha_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // xDesc is read-only
+    // x is a native pointer
+    if (!releasePointerData(env, beta_pointerData, JNI_ABORT)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // yDesc is read-only
+    // y is a native pointer
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Function to perform backward softmax */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSoftmaxBackwardNative(JNIEnv *env, jclass cls, jobject handle, jint algo, jint mode, jobject alpha, jobject yDesc, jobject y, jobject dyDesc, jobject dy, jobject beta, jobject dxDesc, jobject dx)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // algo is primitive
+    // mode is primitive
+    if (alpha == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'alpha' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (yDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (y == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (beta == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'beta' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnSoftmaxBackward");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnSoftmaxBackward");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
@@ -5036,7 +6181,7 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateActivationDescriptorN
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetActivationDescriptorNative(JNIEnv *env, jclass cls, jobject activationDesc, jint mode, jint reluNanOpt, jdouble reluCeiling)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetActivationDescriptorNative(JNIEnv *env, jclass cls, jobject activationDesc, jint mode, jint reluNanOpt, jdouble coef)
 {
     // Null-checks for non-primitive arguments
     if (activationDesc == NULL)
@@ -5046,39 +6191,39 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetActivationDescriptorNati
     }
     // mode is primitive
     // reluNanOpt is primitive
-    // reluCeiling is primitive
+    // coef is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetActivationDescriptor(activationDesc=%p, mode=%d, reluNanOpt=%d, reluCeiling=%lf)\n",
-        activationDesc, mode, reluNanOpt, reluCeiling);
+    Logger::log(LOG_TRACE, "Executing cudnnSetActivationDescriptor(activationDesc=%p, mode=%d, reluNanOpt=%d, coef=%lf)\n",
+        activationDesc, mode, reluNanOpt, coef);
 
     // Native variable declarations
     cudnnActivationDescriptor_t activationDesc_native;
     cudnnActivationMode_t mode_native;
     cudnnNanPropagation_t reluNanOpt_native;
-    double reluCeiling_native = 0.0;
+    double coef_native = 0.0;
 
     // Obtain native variable values
     activationDesc_native = (cudnnActivationDescriptor_t)getNativePointerValue(env, activationDesc);
     mode_native = (cudnnActivationMode_t)mode;
     reluNanOpt_native = (cudnnNanPropagation_t)reluNanOpt;
-    reluCeiling_native = (double)reluCeiling;
+    coef_native = (double)coef;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetActivationDescriptor(activationDesc_native, mode_native, reluNanOpt_native, reluCeiling_native);
+    cudnnStatus_t jniResult_native = cudnnSetActivationDescriptor(activationDesc_native, mode_native, reluNanOpt_native, coef_native);
 
     // Write back native variable values
     // activationDesc is read-only
     // mode is primitive
     // reluNanOpt is primitive
-    // reluCeiling is primitive
+    // coef is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetActivationDescriptorNative(JNIEnv *env, jclass cls, jobject activationDesc, jintArray mode, jintArray reluNanOpt, jdoubleArray reluCeiling)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetActivationDescriptorNative(JNIEnv *env, jclass cls, jobject activationDesc, jintArray mode, jintArray reluNanOpt, jdoubleArray coef)
 {
     // Null-checks for non-primitive arguments
     if (activationDesc == NULL)
@@ -5096,36 +6241,36 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetActivationDescriptorNati
         ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reluNanOpt' is null for cudnnGetActivationDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (reluCeiling == NULL)
+    if (coef == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reluCeiling' is null for cudnnGetActivationDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'coef' is null for cudnnGetActivationDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnGetActivationDescriptor(activationDesc=%p, mode=%p, reluNanOpt=%p, reluCeiling=%p)\n",
-        activationDesc, mode, reluNanOpt, reluCeiling);
+    Logger::log(LOG_TRACE, "Executing cudnnGetActivationDescriptor(activationDesc=%p, mode=%p, reluNanOpt=%p, coef=%p)\n",
+        activationDesc, mode, reluNanOpt, coef);
 
     // Native variable declarations
     cudnnActivationDescriptor_t activationDesc_native;
     cudnnActivationMode_t mode_native;
     cudnnNanPropagation_t reluNanOpt_native;
-    double reluCeiling_native;
+    double coef_native;
 
     // Obtain native variable values
     activationDesc_native = (cudnnActivationDescriptor_t)getNativePointerValue(env, activationDesc);
     // mode is write-only
     // reluNanOpt is write-only
-    // reluCeiling is write-only
+    // coef is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnGetActivationDescriptor(activationDesc_native, &mode_native, &reluNanOpt_native, &reluCeiling_native);
+    cudnnStatus_t jniResult_native = cudnnGetActivationDescriptor(activationDesc_native, &mode_native, &reluNanOpt_native, &coef_native);
 
     // Write back native variable values
     // activationDesc is read-only
     if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
     if (!set(env, reluNanOpt, 0, (jint)reluNanOpt_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    if (!set(env, reluCeiling, 0, (jdouble)reluCeiling_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, coef, 0, (jdouble)coef_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
@@ -7132,111 +8277,232 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDropoutGetStatesSizeNative(
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    // sizeInBytes is write-only
+    // sizeInBytes is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDropoutGetStatesSize(handle_native, &sizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/**helper function to determine size of the reserve space to be passed to dropout forward/backward calls */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDropoutGetReserveSpaceSizeNative(JNIEnv *env, jclass cls, jobject xdesc, jlongArray sizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (xdesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xdesc' is null for cudnnDropoutGetReserveSpaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (sizeInBytes == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnDropoutGetReserveSpaceSize");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnDropoutGetReserveSpaceSize(xdesc=%p, sizeInBytes=%p)\n",
+        xdesc, sizeInBytes);
+
+    // Native variable declarations
+    cudnnTensorDescriptor_t xdesc_native;
+    size_t sizeInBytes_native;
+
+    // Obtain native variable values
+    xdesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xdesc);
+    // sizeInBytes is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDropoutGetReserveSpaceSize(xdesc_native, &sizeInBytes_native);
+
+    // Write back native variable values
+    // xdesc is read-only
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetDropoutDescriptorNative(JNIEnv *env, jclass cls, jobject dropoutDesc, jobject handle, jfloat dropout, jobject states, jlong stateSizeInBytes, jlong seed)
+{
+    // Null-checks for non-primitive arguments
+    if (dropoutDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // dropout is primitive
+    if (states == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'states' is null for cudnnSetDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // stateSizeInBytes is primitive
+    // seed is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetDropoutDescriptor(dropoutDesc=%p, handle=%p, dropout=%f, states=%p, stateSizeInBytes=%ld, seed=%ld)\n",
+        dropoutDesc, handle, dropout, states, stateSizeInBytes, seed);
+
+    // Native variable declarations
+    cudnnDropoutDescriptor_t dropoutDesc_native;
+    cudnnHandle_t handle_native;
+    float dropout_native = 0.0f;
+    void * states_native = NULL;
+    size_t stateSizeInBytes_native = 0;
+    unsigned long long seed_native;
+
+    // Obtain native variable values
+    dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc);
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    dropout_native = (float)dropout;
+    states_native = (void *)getPointer(env, states);
+    stateSizeInBytes_native = (size_t)stateSizeInBytes;
+    seed_native = (unsigned long long)seed;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnDropoutGetStatesSize(handle_native, &sizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnSetDropoutDescriptor(dropoutDesc_native, handle_native, dropout_native, states_native, stateSizeInBytes_native, seed_native);
 
     // Write back native variable values
+    // dropoutDesc is read-only
     // handle is read-only
-    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dropout is primitive
+    // states is a native pointer
+    // stateSizeInBytes is primitive
+    // seed is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-/**helper function to determine size of the reserve space to be passed to dropout forward/backward calls */
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDropoutGetReserveSpaceSizeNative(JNIEnv *env, jclass cls, jobject xdesc, jlongArray sizeInBytes)
+// Restores the dropout descriptor to a previously saved-off state
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRestoreDropoutDescriptorNative(JNIEnv *env, jclass cls, jobject dropoutDesc, jobject handle, jfloat dropout, jobject states, jlong stateSizeInBytes, jlong seed)
 {
     // Null-checks for non-primitive arguments
-    if (xdesc == NULL)
+    if (dropoutDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xdesc' is null for cudnnDropoutGetReserveSpaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnRestoreDropoutDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (sizeInBytes == NULL)
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnDropoutGetReserveSpaceSize");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRestoreDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // dropout is primitive
+    if (states == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'states' is null for cudnnRestoreDropoutDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
+    // stateSizeInBytes is primitive
+    // seed is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnDropoutGetReserveSpaceSize(xdesc=%p, sizeInBytes=%p)\n",
-        xdesc, sizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnRestoreDropoutDescriptor(dropoutDesc=%p, handle=%p, dropout=%f, states=%p, stateSizeInBytes=%ld, seed=%ld)\n",
+        dropoutDesc, handle, dropout, states, stateSizeInBytes, seed);
 
     // Native variable declarations
-    cudnnTensorDescriptor_t xdesc_native;
-    size_t sizeInBytes_native;
+    cudnnDropoutDescriptor_t dropoutDesc_native;
+    cudnnHandle_t handle_native;
+    float dropout_native = 0.0f;
+    void * states_native = NULL;
+    size_t stateSizeInBytes_native = 0;
+    unsigned long long seed_native;
 
     // Obtain native variable values
-    xdesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, xdesc);
-    // sizeInBytes is write-only
+    dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc);
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    dropout_native = (float)dropout;
+    states_native = (void *)getPointer(env, states);
+    stateSizeInBytes_native = (size_t)stateSizeInBytes;
+    seed_native = (unsigned long long)seed;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnDropoutGetReserveSpaceSize(xdesc_native, &sizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnRestoreDropoutDescriptor(dropoutDesc_native, handle_native, dropout_native, states_native, stateSizeInBytes_native, seed_native);
 
     // Write back native variable values
-    // xdesc is read-only
-    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dropoutDesc is read-only
+    // handle is read-only
+    // dropout is primitive
+    // states is a native pointer
+    // stateSizeInBytes is primitive
+    // seed is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetDropoutDescriptorNative(JNIEnv *env, jclass cls, jobject dropoutDesc, jobject handle, jfloat dropout, jobject states, jlong stateSizeInBytes, jlong seed)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetDropoutDescriptorNative(JNIEnv *env, jclass cls, jobject dropoutDesc, jobject handle, jfloatArray dropout, jobject states, jlongArray seed)
 {
     // Null-checks for non-primitive arguments
     if (dropoutDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetDropoutDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnGetDropoutDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetDropoutDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dropout == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropout' is null for cudnnGetDropoutDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // dropout is primitive
     if (states == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'states' is null for cudnnSetDropoutDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'states' is null for cudnnGetDropoutDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (seed == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'seed' is null for cudnnGetDropoutDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // stateSizeInBytes is primitive
-    // seed is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetDropoutDescriptor(dropoutDesc=%p, handle=%p, dropout=%f, states=%p, stateSizeInBytes=%ld, seed=%ld)\n",
-        dropoutDesc, handle, dropout, states, stateSizeInBytes, seed);
+    Logger::log(LOG_TRACE, "Executing cudnnGetDropoutDescriptor(dropoutDesc=%p, handle=%p, dropout=%p, states=%p, seed=%p)\n",
+        dropoutDesc, handle, dropout, states, seed);
 
     // Native variable declarations
     cudnnDropoutDescriptor_t dropoutDesc_native;
     cudnnHandle_t handle_native;
-    float dropout_native = 0.0f;
-    void * states_native = NULL;
-    size_t stateSizeInBytes_native = 0;
+    float dropout_native;
+    void * * states_native = NULL;
     unsigned long long seed_native;
 
     // Obtain native variable values
     dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc);
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    dropout_native = (float)dropout;
-    states_native = (void *)getPointer(env, states);
-    stateSizeInBytes_native = (size_t)stateSizeInBytes;
-    seed_native = (unsigned long long)seed;
+    // dropout is write-only
+    states_native = (void * *)getPointer(env, states);
+    // seed is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetDropoutDescriptor(dropoutDesc_native, handle_native, dropout_native, states_native, stateSizeInBytes_native, seed_native);
+    cudnnStatus_t jniResult_native = cudnnGetDropoutDescriptor(dropoutDesc_native, handle_native, &dropout_native, states_native, &seed_native);
 
     // Write back native variable values
     // dropoutDesc is read-only
     // handle is read-only
-    // dropout is primitive
+    if (!set(env, dropout, 0, (jfloat)dropout_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
     // states is a native pointer
-    // stateSizeInBytes is primitive
-    // seed is primitive
+    if (!set(env, seed, 0, (jlong)seed_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
@@ -7437,100 +8703,364 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateRNNDescriptorNative(J
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyRNNDescriptorNative(JNIEnv *env, jclass cls, jobject rnnDesc)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyRNNDescriptorNative(JNIEnv *env, jclass cls, jobject rnnDesc)
+{
+    // Null-checks for non-primitive arguments
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnDestroyRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyRNNDescriptor(rnnDesc=%p)\n",
+        rnnDesc);
+
+    // Native variable declarations
+    cudnnRNNDescriptor_t rnnDesc_native;
+
+    // Obtain native variable values
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDestroyRNNDescriptor(rnnDesc_native);
+
+    // Write back native variable values
+    // rnnDesc is read-only
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Expensive. Creates the plan for the specific settings. */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreatePersistentRNNPlanNative(JNIEnv *env, jclass cls, jobject rnnDesc, jint minibatch, jint dataType, jobject plan)
+{
+    // Null-checks for non-primitive arguments
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnCreatePersistentRNNPlan");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // minibatch is primitive
+    // dataType is primitive
+    if (plan == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'plan' is null for cudnnCreatePersistentRNNPlan");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnCreatePersistentRNNPlan(rnnDesc=%p, minibatch=%d, dataType=%d, plan=%p)\n",
+        rnnDesc, minibatch, dataType, plan);
+
+    // Native variable declarations
+    cudnnRNNDescriptor_t rnnDesc_native;
+    int minibatch_native = 0;
+    cudnnDataType_t dataType_native;
+    cudnnPersistentRNNPlan_t plan_native;
+
+    // Obtain native variable values
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    minibatch_native = (int)minibatch;
+    dataType_native = (cudnnDataType_t)dataType;
+    // plan is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnCreatePersistentRNNPlan(rnnDesc_native, minibatch_native, dataType_native, &plan_native);
+
+    // Write back native variable values
+    // rnnDesc is read-only
+    // minibatch is primitive
+    // dataType is primitive
+    setNativePointerValue(env, plan, (jlong)plan_native);
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** Attaches the plan to the descriptor. */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetPersistentRNNPlanNative(JNIEnv *env, jclass cls, jobject rnnDesc, jobject plan)
+{
+    // Null-checks for non-primitive arguments
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnSetPersistentRNNPlan");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (plan == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'plan' is null for cudnnSetPersistentRNNPlan");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetPersistentRNNPlan(rnnDesc=%p, plan=%p)\n",
+        rnnDesc, plan);
+
+    // Native variable declarations
+    cudnnRNNDescriptor_t rnnDesc_native;
+    cudnnPersistentRNNPlan_t plan_native;
+
+    // Obtain native variable values
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    plan_native = (cudnnPersistentRNNPlan_t)getNativePointerValue(env, plan);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSetPersistentRNNPlan(rnnDesc_native, plan_native);
+
+    // Write back native variable values
+    // rnnDesc is read-only
+    // plan is read-only
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyPersistentRNNPlanNative(JNIEnv *env, jclass cls, jobject plan)
+{
+    // Null-checks for non-primitive arguments
+    if (plan == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'plan' is null for cudnnDestroyPersistentRNNPlan");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyPersistentRNNPlan(plan=%p)\n",
+        plan);
+
+    // Native variable declarations
+    cudnnPersistentRNNPlan_t plan_native;
+
+    // Obtain native variable values
+    plan_native = (cudnnPersistentRNNPlan_t)getNativePointerValue(env, plan);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDestroyPersistentRNNPlan(plan_native);
+
+    // Write back native variable values
+    // plan is read-only
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptorNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint hiddenSize, jint numLayers, jobject dropoutDesc, jint inputMode, jint direction, jint mode, jint algo, jint dataType)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnSetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // hiddenSize is primitive
+    // numLayers is primitive
+    if (dropoutDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // inputMode is primitive
+    // direction is primitive
+    // mode is primitive
+    // algo is primitive
+    // dataType is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetRNNDescriptor(handle=%p, rnnDesc=%p, hiddenSize=%d, numLayers=%d, dropoutDesc=%p, inputMode=%d, direction=%d, mode=%d, algo=%d, dataType=%d)\n",
+        handle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnRNNDescriptor_t rnnDesc_native;
+    int hiddenSize_native = 0;
+    int numLayers_native = 0;
+    cudnnDropoutDescriptor_t dropoutDesc_native;
+    cudnnRNNInputMode_t inputMode_native;
+    cudnnDirectionMode_t direction_native;
+    cudnnRNNMode_t mode_native;
+    cudnnRNNAlgo_t algo_native;
+    cudnnDataType_t dataType_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    hiddenSize_native = (int)hiddenSize;
+    numLayers_native = (int)numLayers;
+    dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc);
+    inputMode_native = (cudnnRNNInputMode_t)inputMode;
+    direction_native = (cudnnDirectionMode_t)direction;
+    mode_native = (cudnnRNNMode_t)mode;
+    algo_native = (cudnnRNNAlgo_t)algo;
+    dataType_native = (cudnnDataType_t)dataType;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSetRNNDescriptor(handle_native, rnnDesc_native, hiddenSize_native, numLayers_native, dropoutDesc_native, inputMode_native, direction_native, mode_native, algo_native, dataType_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // rnnDesc is read-only
+    // hiddenSize is primitive
+    // numLayers is primitive
+    // dropoutDesc is read-only
+    // inputMode is primitive
+    // direction is primitive
+    // mode is primitive
+    // algo is primitive
+    // dataType is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetRNNDescriptorNative(JNIEnv *env, jclass cls, jobject cudnnHandle, jobject rnnDesc, jintArray hiddenSize, jintArray numLayers, jobject dropoutDesc, jintArray inputMode, jintArray direction, jintArray mode, jintArray algo, jintArray dataType)
 {
     // Null-checks for non-primitive arguments
+    if (cudnnHandle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cudnnHandle' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
     if (rnnDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnDestroyRNNDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (hiddenSize == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hiddenSize' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (numLayers == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'numLayers' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dropoutDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (inputMode == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputMode' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (direction == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'direction' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (mode == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'mode' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (algo == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'algo' is null for cudnnGetRNNDescriptor");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dataType == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dataType' is null for cudnnGetRNNDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnDestroyRNNDescriptor(rnnDesc=%p)\n",
-        rnnDesc);
+    Logger::log(LOG_TRACE, "Executing cudnnGetRNNDescriptor(cudnnHandle=%p, rnnDesc=%p, hiddenSize=%p, numLayers=%p, dropoutDesc=%p, inputMode=%p, direction=%p, mode=%p, algo=%p, dataType=%p)\n",
+        cudnnHandle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType);
 
     // Native variable declarations
+    cudnnHandle_t cudnnHandle_native;
     cudnnRNNDescriptor_t rnnDesc_native;
+    int hiddenSize_native;
+    int numLayers_native;
+    cudnnDropoutDescriptor_t * dropoutDesc_native;
+    cudnnRNNInputMode_t inputMode_native;
+    cudnnDirectionMode_t direction_native;
+    cudnnRNNMode_t mode_native;
+    cudnnRNNAlgo_t algo_native;
+    cudnnDataType_t dataType_native;
 
     // Obtain native variable values
+    cudnnHandle_native = (cudnnHandle_t)getNativePointerValue(env, cudnnHandle);
     rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    // hiddenSize is write-only
+    // numLayers is write-only
+    dropoutDesc_native = (cudnnDropoutDescriptor_t *)getNativePointerValue(env, dropoutDesc);
+    // inputMode is write-only
+    // direction is write-only
+    // mode is write-only
+    // algo is write-only
+    // dataType is write-only
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnDestroyRNNDescriptor(rnnDesc_native);
+    cudnnStatus_t jniResult_native = cudnnGetRNNDescriptor(cudnnHandle_native, rnnDesc_native, &hiddenSize_native, &numLayers_native, dropoutDesc_native, &inputMode_native, &direction_native, &mode_native, &algo_native, &dataType_native);
 
     // Write back native variable values
+    // cudnnHandle is read-only
     // rnnDesc is read-only
+    if (!set(env, hiddenSize, 0, (jint)hiddenSize_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, numLayers, 0, (jint)numLayers_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dropoutDesc is read-only
+    if (!set(env, inputMode, 0, (jint)inputMode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, direction, 0, (jint)direction_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, mode, 0, (jint)mode_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, algo, 0, (jint)algo_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, dataType, 0, (jint)dataType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptorNative(JNIEnv *env, jclass cls, jobject rnnDesc, jint hiddenSize, jint numLayers, jobject dropoutDesc, jint inputMode, jint direction, jint mode, jint dataType)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNMatrixMathTypeNative(JNIEnv *env, jclass cls, jobject desc, jint math)
 {
     // Null-checks for non-primitive arguments
-    if (rnnDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnSetRNNDescriptor");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // hiddenSize is primitive
-    // numLayers is primitive
-    if (dropoutDesc == NULL)
+    if (desc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetRNNDescriptor");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'desc' is null for cudnnSetRNNMatrixMathType");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // inputMode is primitive
-    // direction is primitive
-    // mode is primitive
-    // dataType is primitive
+    // math is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnSetRNNDescriptor(rnnDesc=%p, hiddenSize=%d, numLayers=%d, dropoutDesc=%p, inputMode=%d, direction=%d, mode=%d, dataType=%d)\n",
-        rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, dataType);
+    Logger::log(LOG_TRACE, "Executing cudnnSetRNNMatrixMathType(desc=%p, math=%d)\n",
+        desc, math);
 
     // Native variable declarations
-    cudnnRNNDescriptor_t rnnDesc_native;
-    int hiddenSize_native = 0;
-    int numLayers_native = 0;
-    cudnnDropoutDescriptor_t dropoutDesc_native;
-    cudnnRNNInputMode_t inputMode_native;
-    cudnnDirectionMode_t direction_native;
-    cudnnRNNMode_t mode_native;
-    cudnnDataType_t dataType_native;
+    cudnnRNNDescriptor_t desc_native;
+    cudnnMathType_t math_native;
 
     // Obtain native variable values
-    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
-    hiddenSize_native = (int)hiddenSize;
-    numLayers_native = (int)numLayers;
-    dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc);
-    inputMode_native = (cudnnRNNInputMode_t)inputMode;
-    direction_native = (cudnnDirectionMode_t)direction;
-    mode_native = (cudnnRNNMode_t)mode;
-    dataType_native = (cudnnDataType_t)dataType;
+    desc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, desc);
+    math_native = (cudnnMathType_t)math;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnSetRNNDescriptor(rnnDesc_native, hiddenSize_native, numLayers_native, dropoutDesc_native, inputMode_native, direction_native, mode_native, dataType_native);
+    cudnnStatus_t jniResult_native = cudnnSetRNNMatrixMathType(desc_native, math_native);
 
     // Write back native variable values
-    // rnnDesc is read-only
-    // hiddenSize is primitive
-    // numLayers is primitive
-    // dropoutDesc is read-only
-    // inputMode is primitive
-    // direction is primitive
-    // mode is primitive
-    // dataType is primitive
+    // desc is read-only
+    // math is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-// dataType in the RNN descriptor is used to determine math precision
-// dataType in weight descriptors and input descriptors is used to describe storage
+/** dataType in the RNN descriptor is used to determine math precision */
+/** dataType in weight descriptors and input descriptors is used to describe storage */
 JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetRNNWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray xDesc, jlongArray sizeInBytes)
 {
     // Null-checks for non-primitive arguments
@@ -7933,44 +9463,216 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardInferenceNative(J
     }
     if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (y == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (hyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hyDesc' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (hy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hy' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cyDesc' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cy' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (workspace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNForwardInference");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnRNNForwardInference(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, wDesc=%p, w=%p, yDesc=%p, y=%p, hyDesc=%p, hy=%p, cyDesc=%p, cy=%p, workspace=%p, workSpaceSizeInBytes=%ld)\n",
+        handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, cxDesc, cx, wDesc, w, yDesc, y, hyDesc, hy, cyDesc, cy, workspace, workSpaceSizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnRNNDescriptor_t rnnDesc_native;
+    int seqLength_native = 0;
+    cudnnTensorDescriptor_t * xDesc_native;
+    void * x_native = NULL;
+    cudnnTensorDescriptor_t hxDesc_native;
+    void * hx_native = NULL;
+    cudnnTensorDescriptor_t cxDesc_native;
+    void * cx_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
+    cudnnTensorDescriptor_t * yDesc_native;
+    void * y_native = NULL;
+    cudnnTensorDescriptor_t hyDesc_native;
+    void * hy_native = NULL;
+    cudnnTensorDescriptor_t cyDesc_native;
+    void * cy_native = NULL;
+    void * workspace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    seqLength_native = (int)seqLength;
+    if (!initNative(env, xDesc, xDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    x_native = (void *)getPointer(env, x);
+    hxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hxDesc);
+    hx_native = (void *)getPointer(env, hx);
+    cxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cxDesc);
+    cx_native = (void *)getPointer(env, cx);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
+    if (!initNative(env, yDesc, yDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    y_native = (void *)getPointer(env, y);
+    hyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hyDesc);
+    hy_native = (void *)getPointer(env, hy);
+    cyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cyDesc);
+    cy_native = (void *)getPointer(env, cy);
+    workspace_native = (void *)getPointer(env, workspace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnRNNForwardInference(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, cxDesc_native, cx_native, wDesc_native, w_native, yDesc_native, y_native, hyDesc_native, hy_native, cyDesc_native, cy_native, workspace_native, workSpaceSizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // rnnDesc is read-only
+    // seqLength is primitive
+    if (!releaseNative(env, xDesc_native, xDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // x is a native pointer
+    // hxDesc is read-only
+    // hx is a native pointer
+    // cxDesc is read-only
+    // cx is a native pointer
+    // wDesc is read-only
+    // w is a native pointer
+    if (!releaseNative(env, yDesc_native, yDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // y is a native pointer
+    // hyDesc is read-only
+    // hy is a native pointer
+    // cyDesc is read-only
+    // cy is a native pointer
+    // workspace is a native pointer
+    // workSpaceSizeInBytes is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray xDesc, jobject x, jobject hxDesc, jobject hx, jobject cxDesc, jobject cx, jobject wDesc, jobject w, jobjectArray yDesc, jobject y, jobject hyDesc, jobject hy, jobject cyDesc, jobject cy, jobject workspace, jlong workSpaceSizeInBytes, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // seqLength is primitive
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (x == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (hxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (hx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cxDesc' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (cx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cx' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (w == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (yDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (hyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hyDesc' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hyDesc' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (hy == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hy' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hy' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (cyDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cyDesc' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cyDesc' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (cy == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cy' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cy' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (workspace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNForwardInference");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNForwardTraining");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // workSpaceSizeInBytes is primitive
+    if (reserveSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNForwardTraining");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // reserveSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnRNNForwardInference(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, wDesc=%p, w=%p, yDesc=%p, y=%p, hyDesc=%p, hy=%p, cyDesc=%p, cy=%p, workspace=%p, workSpaceSizeInBytes=%ld)\n",
-        handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, cxDesc, cx, wDesc, w, yDesc, y, hyDesc, hy, cyDesc, cy, workspace, workSpaceSizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnRNNForwardTraining(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, wDesc=%p, w=%p, yDesc=%p, y=%p, hyDesc=%p, hy=%p, cyDesc=%p, cy=%p, workspace=%p, workSpaceSizeInBytes=%ld, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n",
+        handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, cxDesc, cx, wDesc, w, yDesc, y, hyDesc, hy, cyDesc, cy, workspace, workSpaceSizeInBytes, reserveSpace, reserveSpaceSizeInBytes);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
@@ -7992,6 +9694,8 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardInferenceNative(J
     void * cy_native = NULL;
     void * workspace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
+    void * reserveSpace_native = NULL;
+    size_t reserveSpaceSizeInBytes_native = 0;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
@@ -8013,9 +9717,11 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardInferenceNative(J
     cy_native = (void *)getPointer(env, cy);
     workspace_native = (void *)getPointer(env, workspace);
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    reserveSpace_native = (void *)getPointer(env, reserveSpace);
+    reserveSpaceSizeInBytes_native = (size_t)reserveSpaceSizeInBytes;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnRNNForwardInference(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, cxDesc_native, cx_native, wDesc_native, w_native, yDesc_native, y_native, hyDesc_native, hy_native, cyDesc_native, cy_native, workspace_native, workSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnRNNForwardTraining(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, cxDesc_native, cx_native, wDesc_native, w_native, yDesc_native, y_native, hyDesc_native, hy_native, cyDesc_native, cy_native, workspace_native, workSpaceSizeInBytes_native, reserveSpace_native, reserveSpaceSizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
@@ -8037,112 +9743,310 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardInferenceNative(J
     // cy is a native pointer
     // workspace is a native pointer
     // workSpaceSizeInBytes is primitive
+    // reserveSpace is a native pointer
+    // reserveSpaceSizeInBytes is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray xDesc, jobject x, jobject hxDesc, jobject hx, jobject cxDesc, jobject cx, jobject wDesc, jobject w, jobjectArray yDesc, jobject y, jobject hyDesc, jobject hy, jobject cyDesc, jobject cy, jobject workspace, jlong workSpaceSizeInBytes, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardDataNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray yDesc, jobject y, jobjectArray dyDesc, jobject dy, jobject dhyDesc, jobject dhy, jobject dcyDesc, jobject dcy, jobject wDesc, jobject w, jobject hxDesc, jobject hx, jobject cxDesc, jobject cx, jobjectArray dxDesc, jobject dx, jobject dhxDesc, jobject dhx, jobject dcxDesc, jobject dcx, jobject workspace, jlong workSpaceSizeInBytes, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (rnnDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // seqLength is primitive
-    if (xDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (x == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dhyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhyDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dhy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhy' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dcyDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcyDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dcy == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcy' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (wDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (w == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (hxDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (hx == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (cxDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cxDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cxDesc' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     if (cx == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cx' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cx' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (wDesc == NULL)
+    if (dxDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnRNNBackwardData");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    if (dx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dhxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhxDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dhx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhx' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dcxDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcxDesc' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (dcx == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcx' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (workspace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+    if (reserveSpace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNBackwardData");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // reserveSpaceSizeInBytes is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnRNNBackwardData(handle=%p, rnnDesc=%p, seqLength=%d, yDesc=%p, y=%p, dyDesc=%p, dy=%p, dhyDesc=%p, dhy=%p, dcyDesc=%p, dcy=%p, wDesc=%p, w=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, dxDesc=%p, dx=%p, dhxDesc=%p, dhx=%p, dcxDesc=%p, dcx=%p, workspace=%p, workSpaceSizeInBytes=%ld, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n",
+        handle, rnnDesc, seqLength, yDesc, y, dyDesc, dy, dhyDesc, dhy, dcyDesc, dcy, wDesc, w, hxDesc, hx, cxDesc, cx, dxDesc, dx, dhxDesc, dhx, dcxDesc, dcx, workspace, workSpaceSizeInBytes, reserveSpace, reserveSpaceSizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnRNNDescriptor_t rnnDesc_native;
+    int seqLength_native = 0;
+    cudnnTensorDescriptor_t * yDesc_native;
+    void * y_native = NULL;
+    cudnnTensorDescriptor_t * dyDesc_native;
+    void * dy_native = NULL;
+    cudnnTensorDescriptor_t dhyDesc_native;
+    void * dhy_native = NULL;
+    cudnnTensorDescriptor_t dcyDesc_native;
+    void * dcy_native = NULL;
+    cudnnFilterDescriptor_t wDesc_native;
+    void * w_native = NULL;
+    cudnnTensorDescriptor_t hxDesc_native;
+    void * hx_native = NULL;
+    cudnnTensorDescriptor_t cxDesc_native;
+    void * cx_native = NULL;
+    cudnnTensorDescriptor_t * dxDesc_native;
+    void * dx_native = NULL;
+    cudnnTensorDescriptor_t dhxDesc_native;
+    void * dhx_native = NULL;
+    cudnnTensorDescriptor_t dcxDesc_native;
+    void * dcx_native = NULL;
+    void * workspace_native = NULL;
+    size_t workSpaceSizeInBytes_native = 0;
+    void * reserveSpace_native = NULL;
+    size_t reserveSpaceSizeInBytes_native = 0;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
+    seqLength_native = (int)seqLength;
+    if (!initNative(env, yDesc, yDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    y_native = (void *)getPointer(env, y);
+    if (!initNative(env, dyDesc, dyDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    dy_native = (void *)getPointer(env, dy);
+    dhyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dhyDesc);
+    dhy_native = (void *)getPointer(env, dhy);
+    dcyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dcyDesc);
+    dcy_native = (void *)getPointer(env, dcy);
+    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
+    w_native = (void *)getPointer(env, w);
+    hxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hxDesc);
+    hx_native = (void *)getPointer(env, hx);
+    cxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cxDesc);
+    cx_native = (void *)getPointer(env, cx);
+    if (!initNative(env, dxDesc, dxDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    dx_native = (void *)getPointer(env, dx);
+    dhxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dhxDesc);
+    dhx_native = (void *)getPointer(env, dhx);
+    dcxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dcxDesc);
+    dcx_native = (void *)getPointer(env, dcx);
+    workspace_native = (void *)getPointer(env, workspace);
+    workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    reserveSpace_native = (void *)getPointer(env, reserveSpace);
+    reserveSpaceSizeInBytes_native = (size_t)reserveSpaceSizeInBytes;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnRNNBackwardData(handle_native, rnnDesc_native, seqLength_native, yDesc_native, y_native, dyDesc_native, dy_native, dhyDesc_native, dhy_native, dcyDesc_native, dcy_native, wDesc_native, w_native, hxDesc_native, hx_native, cxDesc_native, cx_native, dxDesc_native, dx_native, dhxDesc_native, dhx_native, dcxDesc_native, dcx_native, workspace_native, workSpaceSizeInBytes_native, reserveSpace_native, reserveSpaceSizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // rnnDesc is read-only
+    // seqLength is primitive
+    if (!releaseNative(env, yDesc_native, yDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // y is a native pointer
+    if (!releaseNative(env, dyDesc_native, dyDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dy is a native pointer
+    // dhyDesc is read-only
+    // dhy is a native pointer
+    // dcyDesc is read-only
+    // dcy is a native pointer
+    // wDesc is read-only
+    // w is a native pointer
+    // hxDesc is read-only
+    // hx is a native pointer
+    // cxDesc is read-only
+    // cx is a native pointer
+    if (!releaseNative(env, dxDesc_native, dxDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // dx is a native pointer
+    // dhxDesc is read-only
+    // dhx is a native pointer
+    // dcxDesc is read-only
+    // dcx is a native pointer
+    // workspace is a native pointer
+    // workSpaceSizeInBytes is primitive
+    // reserveSpace is a native pointer
+    // reserveSpaceSizeInBytes is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardWeightsNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray xDesc, jobject x, jobject hxDesc, jobject hx, jobjectArray yDesc, jobject y, jobject workspace, jlong workSpaceSizeInBytes, jobject dwDesc, jobject dw, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNBackwardWeights");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (rnnDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNBackwardWeights");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // seqLength is primitive
+    if (xDesc == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnRNNBackwardWeights");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    if (x == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (hxDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    if (hx == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hyDesc == NULL)
+    if (yDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hyDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hy == NULL)
+    if (y == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hy' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (cyDesc == NULL)
+    if (workspace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cyDesc' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (cy == NULL)
+    // workSpaceSizeInBytes is primitive
+    if (dwDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cy' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (workspace == NULL)
+    if (dw == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
     if (reserveSpace == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNForwardTraining");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNBackwardWeights");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
     // reserveSpaceSizeInBytes is primitive
 
     // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnRNNForwardTraining(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, wDesc=%p, w=%p, yDesc=%p, y=%p, hyDesc=%p, hy=%p, cyDesc=%p, cy=%p, workspace=%p, workSpaceSizeInBytes=%ld, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n",
-        handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, cxDesc, cx, wDesc, w, yDesc, y, hyDesc, hy, cyDesc, cy, workspace, workSpaceSizeInBytes, reserveSpace, reserveSpaceSizeInBytes);
+    Logger::log(LOG_TRACE, "Executing cudnnRNNBackwardWeights(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, yDesc=%p, y=%p, workspace=%p, workSpaceSizeInBytes=%ld, dwDesc=%p, dw=%p, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n",
+        handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, yDesc, y, workspace, workSpaceSizeInBytes, dwDesc, dw, reserveSpace, reserveSpaceSizeInBytes);
 
     // Native variable declarations
     cudnnHandle_t handle_native;
@@ -8152,18 +10056,12 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JN
     void * x_native = NULL;
     cudnnTensorDescriptor_t hxDesc_native;
     void * hx_native = NULL;
-    cudnnTensorDescriptor_t cxDesc_native;
-    void * cx_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
-    void * w_native = NULL;
     cudnnTensorDescriptor_t * yDesc_native;
     void * y_native = NULL;
-    cudnnTensorDescriptor_t hyDesc_native;
-    void * hy_native = NULL;
-    cudnnTensorDescriptor_t cyDesc_native;
-    void * cy_native = NULL;
     void * workspace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
+    cudnnFilterDescriptor_t dwDesc_native;
+    void * dw_native = NULL;
     void * reserveSpace_native = NULL;
     size_t reserveSpaceSizeInBytes_native = 0;
 
@@ -8175,23 +10073,17 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JN
     x_native = (void *)getPointer(env, x);
     hxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hxDesc);
     hx_native = (void *)getPointer(env, hx);
-    cxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cxDesc);
-    cx_native = (void *)getPointer(env, cx);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    w_native = (void *)getPointer(env, w);
     if (!initNative(env, yDesc, yDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
     y_native = (void *)getPointer(env, y);
-    hyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hyDesc);
-    hy_native = (void *)getPointer(env, hy);
-    cyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cyDesc);
-    cy_native = (void *)getPointer(env, cy);
     workspace_native = (void *)getPointer(env, workspace);
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
+    dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc);
+    dw_native = (void *)getPointer(env, dw);
     reserveSpace_native = (void *)getPointer(env, reserveSpace);
     reserveSpaceSizeInBytes_native = (size_t)reserveSpaceSizeInBytes;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnRNNForwardTraining(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, cxDesc_native, cx_native, wDesc_native, w_native, yDesc_native, y_native, hyDesc_native, hy_native, cyDesc_native, cy_native, workspace_native, workSpaceSizeInBytes_native, reserveSpace_native, reserveSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnRNNBackwardWeights(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, yDesc_native, y_native, workspace_native, workSpaceSizeInBytes_native, dwDesc_native, dw_native, reserveSpace_native, reserveSpaceSizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
@@ -8201,18 +10093,12 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JN
     // x is a native pointer
     // hxDesc is read-only
     // hx is a native pointer
-    // cxDesc is read-only
-    // cx is a native pointer
-    // wDesc is read-only
-    // w is a native pointer
     if (!releaseNative(env, yDesc_native, yDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
     // y is a native pointer
-    // hyDesc is read-only
-    // hy is a native pointer
-    // cyDesc is read-only
-    // cy is a native pointer
     // workspace is a native pointer
     // workSpaceSizeInBytes is primitive
+    // dwDesc is read-only
+    // dw is a native pointer
     // reserveSpace is a native pointer
     // reserveSpaceSizeInBytes is primitive
 
@@ -8221,356 +10107,488 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNForwardTrainingNative(JN
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardDataNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray yDesc, jobject y, jobjectArray dyDesc, jobject dy, jobject dhyDesc, jobject dhy, jobject dcyDesc, jobject dcy, jobject wDesc, jobject w, jobject hxDesc, jobject hx, jobject cxDesc, jobject cx, jobjectArray dxDesc, jobject dx, jobject dhxDesc, jobject dhx, jobject dcxDesc, jobject dcx, jobject workspace, jlong workSpaceSizeInBytes, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
+/**
+* Create an instance of a CTC (Connectionist Temporal Classification) loss descriptor
+*/
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateCTCLossDescriptorNative(JNIEnv *env, jclass cls, jobject ctcLossDesc)
 {
     // Null-checks for non-primitive arguments
-    if (handle == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (rnnDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // seqLength is primitive
-    if (yDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (y == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dyDesc == NULL)
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dyDesc' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dy == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dy' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dhyDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhyDesc' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dhy == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhy' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnCreateCTCLossDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dcyDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcyDesc' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (dcy == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcy' is null for cudnnRNNBackwardData");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (wDesc == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnCreateCTCLossDescriptor(ctcLossDesc=%p)\n",
+        ctcLossDesc);
+
+    // Native variable declarations
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
+
+    // Obtain native variable values
+    // ctcLossDesc is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnCreateCTCLossDescriptor(&ctcLossDesc_native);
+
+    // Write back native variable values
+    setNativePointerValue(env, ctcLossDesc, (jlong)ctcLossDesc_native);
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetCTCLossDescriptorNative(JNIEnv *env, jclass cls, jobject ctcLossDesc, jint compType)
+{
+    // Null-checks for non-primitive arguments
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'wDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnSetCTCLossDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (w == NULL)
+    // compType is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnSetCTCLossDescriptor(ctcLossDesc=%p, compType=%d)\n",
+        ctcLossDesc, compType);
+
+    // Native variable declarations
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
+    cudnnDataType_t compType_native;
+
+    // Obtain native variable values
+    ctcLossDesc_native = (cudnnCTCLossDescriptor_t)getNativePointerValue(env, ctcLossDesc);
+    compType_native = (cudnnDataType_t)compType;
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnSetCTCLossDescriptor(ctcLossDesc_native, compType_native);
+
+    // Write back native variable values
+    // ctcLossDesc is read-only
+    // compType is primitive
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCTCLossDescriptorNative(JNIEnv *env, jclass cls, jobject ctcLossDesc, jintArray compType)
+{
+    // Null-checks for non-primitive arguments
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'w' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnGetCTCLossDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hxDesc == NULL)
+    if (compType == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'compType' is null for cudnnGetCTCLossDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hx == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetCTCLossDescriptor(ctcLossDesc=%p, compType=%p)\n",
+        ctcLossDesc, compType);
+
+    // Native variable declarations
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
+    cudnnDataType_t compType_native;
+
+    // Obtain native variable values
+    ctcLossDesc_native = (cudnnCTCLossDescriptor_t)getNativePointerValue(env, ctcLossDesc);
+    // compType is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetCTCLossDescriptor(ctcLossDesc_native, &compType_native);
+
+    // Write back native variable values
+    // ctcLossDesc is read-only
+    if (!set(env, compType, 0, (jint)compType_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyCTCLossDescriptorNative(JNIEnv *env, jclass cls, jobject ctcLossDesc)
+{
+    // Null-checks for non-primitive arguments
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnDestroyCTCLossDescriptor");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (cxDesc == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnDestroyCTCLossDescriptor(ctcLossDesc=%p)\n",
+        ctcLossDesc);
+
+    // Native variable declarations
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
+
+    // Obtain native variable values
+    ctcLossDesc_native = (cudnnCTCLossDescriptor_t)getNativePointerValue(env, ctcLossDesc);
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnDestroyCTCLossDescriptor(ctcLossDesc_native);
+
+    // Write back native variable values
+    // ctcLossDesc is read-only
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/** return the ctc costs and gradients, given the probabilities and labels */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCTCLossNative(JNIEnv *env, jclass cls, jobject handle, jobject probsDesc, jobject probs, jintArray labels, jintArray labelLengths, jintArray inputLengths, jobject costs, jobject gradientsDesc, jobject gradients, jint algo, jobject ctcLossDesc, jobject workspace, jlong workSpaceSizeInBytes)
+{
+    // Null-checks for non-primitive arguments
+    if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cxDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (cx == NULL)
+    if (probsDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'cx' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'probsDesc' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dxDesc == NULL)
+    if (probs == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dxDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'probs' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dx == NULL)
+    if (labels == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dx' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'labels' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dhxDesc == NULL)
+    if (labelLengths == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhxDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'labelLengths' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dhx == NULL)
+    if (inputLengths == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dhx' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputLengths' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dcxDesc == NULL)
+    if (costs == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcxDesc' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'costs' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (dcx == NULL)
+    if (gradientsDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dcx' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradientsDesc' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (workspace == NULL)
+    if (gradients == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradients' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
-    if (reserveSpace == NULL)
+    // algo is primitive
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNBackwardData");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnCTCLoss");
         return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    // reserveSpaceSizeInBytes is primitive
-
-    // Log message
-    Logger::log(LOG_TRACE, "Executing cudnnRNNBackwardData(handle=%p, rnnDesc=%p, seqLength=%d, yDesc=%p, y=%p, dyDesc=%p, dy=%p, dhyDesc=%p, dhy=%p, dcyDesc=%p, dcy=%p, wDesc=%p, w=%p, hxDesc=%p, hx=%p, cxDesc=%p, cx=%p, dxDesc=%p, dx=%p, dhxDesc=%p, dhx=%p, dcxDesc=%p, dcx=%p, workspace=%p, workSpaceSizeInBytes=%ld, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n",
-        handle, rnnDesc, seqLength, yDesc, y, dyDesc, dy, dhyDesc, dhy, dcyDesc, dcy, wDesc, w, hxDesc, hx, cxDesc, cx, dxDesc, dx, dhxDesc, dhx, dcxDesc, dcx, workspace, workSpaceSizeInBytes, reserveSpace, reserveSpaceSizeInBytes);
-
-    // Native variable declarations
-    cudnnHandle_t handle_native;
-    cudnnRNNDescriptor_t rnnDesc_native;
-    int seqLength_native = 0;
-    cudnnTensorDescriptor_t * yDesc_native;
-    void * y_native = NULL;
-    cudnnTensorDescriptor_t * dyDesc_native;
-    void * dy_native = NULL;
-    cudnnTensorDescriptor_t dhyDesc_native;
-    void * dhy_native = NULL;
-    cudnnTensorDescriptor_t dcyDesc_native;
-    void * dcy_native = NULL;
-    cudnnFilterDescriptor_t wDesc_native;
-    void * w_native = NULL;
-    cudnnTensorDescriptor_t hxDesc_native;
-    void * hx_native = NULL;
-    cudnnTensorDescriptor_t cxDesc_native;
-    void * cx_native = NULL;
-    cudnnTensorDescriptor_t * dxDesc_native;
-    void * dx_native = NULL;
-    cudnnTensorDescriptor_t dhxDesc_native;
-    void * dhx_native = NULL;
-    cudnnTensorDescriptor_t dcxDesc_native;
-    void * dcx_native = NULL;
+    }
+    if (workspace == NULL)
+    {
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnCTCLoss");
+        return JCUDNN_STATUS_INTERNAL_ERROR;
+    }
+    // workSpaceSizeInBytes is primitive
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnCTCLoss(handle=%p, probsDesc=%p, probs=%p, labels=%p, labelLengths=%p, inputLengths=%p, costs=%p, gradientsDesc=%p, gradients=%p, algo=%d, ctcLossDesc=%p, workspace=%p, workSpaceSizeInBytes=%ld)\n",
+        handle, probsDesc, probs, labels, labelLengths, inputLengths, costs, gradientsDesc, gradients, algo, ctcLossDesc, workspace, workSpaceSizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t probsDesc_native;
+    void * probs_native = NULL;
+    int labels_native;
+    int labelLengths_native;
+    int inputLengths_native;
+    void * costs_native = NULL;
+    cudnnTensorDescriptor_t gradientsDesc_native;
+    void * gradients_native = NULL;
+    cudnnCTCLossAlgo_t algo_native;
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
     void * workspace_native = NULL;
     size_t workSpaceSizeInBytes_native = 0;
-    void * reserveSpace_native = NULL;
-    size_t reserveSpaceSizeInBytes_native = 0;
 
     // Obtain native variable values
     handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
-    rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc);
-    seqLength_native = (int)seqLength;
-    if (!initNative(env, yDesc, yDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    y_native = (void *)getPointer(env, y);
-    if (!initNative(env, dyDesc, dyDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    dy_native = (void *)getPointer(env, dy);
-    dhyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dhyDesc);
-    dhy_native = (void *)getPointer(env, dhy);
-    dcyDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dcyDesc);
-    dcy_native = (void *)getPointer(env, dcy);
-    wDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, wDesc);
-    w_native = (void *)getPointer(env, w);
-    hxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hxDesc);
-    hx_native = (void *)getPointer(env, hx);
-    cxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, cxDesc);
-    cx_native = (void *)getPointer(env, cx);
-    if (!initNative(env, dxDesc, dxDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    dx_native = (void *)getPointer(env, dx);
-    dhxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dhxDesc);
-    dhx_native = (void *)getPointer(env, dhx);
-    dcxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, dcxDesc);
-    dcx_native = (void *)getPointer(env, dcx);
+    probsDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, probsDesc);
+    probs_native = (void *)getPointer(env, probs);
+    // labels is write-only
+    // labelLengths is write-only
+    // inputLengths is write-only
+    costs_native = (void *)getPointer(env, costs);
+    gradientsDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, gradientsDesc);
+    gradients_native = (void *)getPointer(env, gradients);
+    algo_native = (cudnnCTCLossAlgo_t)algo;
+    ctcLossDesc_native = (cudnnCTCLossDescriptor_t)getNativePointerValue(env, ctcLossDesc);
     workspace_native = (void *)getPointer(env, workspace);
     workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes;
-    reserveSpace_native = (void *)getPointer(env, reserveSpace);
-    reserveSpaceSizeInBytes_native = (size_t)reserveSpaceSizeInBytes;
 
     // Native function call
-    cudnnStatus_t jniResult_native = cudnnRNNBackwardData(handle_native, rnnDesc_native, seqLength_native, yDesc_native, y_native, dyDesc_native, dy_native, dhyDesc_native, dhy_native, dcyDesc_native, dcy_native, wDesc_native, w_native, hxDesc_native, hx_native, cxDesc_native, cx_native, dxDesc_native, dx_native, dhxDesc_native, dhx_native, dcxDesc_native, dcx_native, workspace_native, workSpaceSizeInBytes_native, reserveSpace_native, reserveSpaceSizeInBytes_native);
+    cudnnStatus_t jniResult_native = cudnnCTCLoss(handle_native, probsDesc_native, probs_native, &labels_native, &labelLengths_native, &inputLengths_native, costs_native, gradientsDesc_native, gradients_native, algo_native, ctcLossDesc_native, workspace_native, workSpaceSizeInBytes_native);
 
     // Write back native variable values
     // handle is read-only
-    // rnnDesc is read-only
-    // seqLength is primitive
-    if (!releaseNative(env, yDesc_native, yDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // y is a native pointer
-    if (!releaseNative(env, dyDesc_native, dyDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dy is a native pointer
-    // dhyDesc is read-only
-    // dhy is a native pointer
-    // dcyDesc is read-only
-    // dcy is a native pointer
-    // wDesc is read-only
-    // w is a native pointer
-    // hxDesc is read-only
-    // hx is a native pointer
-    // cxDesc is read-only
-    // cx is a native pointer
-    if (!releaseNative(env, dxDesc_native, dxDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR;
-    // dx is a native pointer
-    // dhxDesc is read-only
-    // dhx is a native pointer
-    // dcxDesc is read-only
-    // dcx is a native pointer
+    // probsDesc is read-only
+    // probs is a native pointer
+    if (!set(env, labels, 0, (jint)labels_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, labelLengths, 0, (jint)labelLengths_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, inputLengths, 0, (jint)inputLengths_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // costs is a native pointer
+    // gradientsDesc is read-only
+    // gradients is a native pointer
+    // algo is primitive
+    // ctcLossDesc is read-only
     // workspace is a native pointer
     // workSpaceSizeInBytes is primitive
-    // reserveSpace is a native pointer
-    // reserveSpaceSizeInBytes is primitive
 
     // Return the result
     jint jniResult = (jint)jniResult_native;
     return jniResult;
 }
 
-JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardWeightsNative(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint seqLength, jobjectArray xDesc, jobject x, jobject hxDesc, jobject hx, jobjectArray yDesc, jobject y, jobject workspace, jlong workSpaceSizeInBytes, jobject dwDesc, jobject dw, jobject reserveSpace, jlong reserveSpaceSizeInBytes)
+/** return the workspace size needed for ctc */
+JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCTCLossWorkspaceSizeNative(JNIEnv *env, jclass cls, jobject handle, jobject probsDesc, jobject gradientsDesc, jintArray labels, jintArray labelLengths, jintArray inputLengths, jint algo, jobject ctcLossDesc, jlongArray sizeInBytes)
 {
     // Null-checks for non-primitive arguments
     if (handle == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnRNNBackwardWeights");
-        return JCUDNN_STATUS_INTERNAL_ERROR;
-    }
-    if (rnnDesc == NULL)
-    {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // seqLength is primitive
-    if (xDesc == NULL)
+    if (probsDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'xDesc' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'probsDesc' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (x == NULL)
+    if (gradientsDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'x' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'gradientsDesc' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hxDesc == NULL)
+    if (labels == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hxDesc' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'labels' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (hx == NULL)
+    if (labelLengths == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'hx' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'labelLengths' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (yDesc == NULL)
+    if (inputLengths == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'yDesc' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'inputLengths' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (y == NULL)
+    // algo is primitive
+    if (ctcLossDesc == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'y' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'ctcLossDesc' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    if (workspace == NULL)
+    if (sizeInBytes == NULL)
     {
-        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workspace' is null for cudnnRNNBackwardWeights");
+        ThrowByName(env, "java/lang/NullPointerException", "Parameter 'sizeInBytes' is null for cudnnGetCTCLossWorkspaceSize");
         return JCUDNN_STATUS_INTERNAL_ERROR;
     }
-    // workSpaceSizeInBytes is primitive
-    if (dwDesc == NULL)
+
+    // Log message
+    Logger::log(LOG_TRACE, "Executing cudnnGetCTCLossWorkspaceSize(handle=%p, probsDesc=%p, gradientsDesc=%p, labels=%p, labelLengths=%p, inputLengths=%p, algo=%d, ctcLossDesc=%p, sizeInBytes=%p)\n",
+        handle, probsDesc, gradientsDesc, labels, labelLengths, inputLengths, algo, ctcLossDesc, sizeInBytes);
+
+    // Native variable declarations
+    cudnnHandle_t handle_native;
+    cudnnTensorDescriptor_t probsDesc_native;
+    cudnnTensorDescriptor_t gradientsDesc_native;
+    int labels_native;
+    int labelLengths_native;
+    int inputLengths_native;
+    cudnnCTCLossAlgo_t algo_native;
+    cudnnCTCLossDescriptor_t ctcLossDesc_native;
+    size_t sizeInBytes_native;
+
+    // Obtain native variable values
+    handle_native = (cudnnHandle_t)getNativePointerValue(env, handle);
+    probsDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, probsDesc);
+    gradientsDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, gradientsDesc);
+    // labels is write-only
+    // labelLengths is write-only
+    // inputLengths is write-only
+    algo_native = (cudnnCTCLossAlgo_t)algo;
+    ctcLossDesc_native = (cudnnCTCLossDescriptor_t)getNativePointerValue(env, ctcLossDesc);
+    // sizeInBytes is write-only
+
+    // Native function call
+    cudnnStatus_t jniResult_native = cudnnGetCTCLossWorkspaceSize(handle_native, probsDesc_native, gradientsDesc_native, &labels_native, &labelLengths_native, &inputLengths_native, algo_native, ctcLossDesc_native, &sizeInBytes_native);
+
+    // Write back native variable values
+    // handle is read-only
+    // probsDesc is read-only
+    // gradientsDesc is read-only
+    if (!set(env, labels, 0, (jint)labels_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, labelLengths, 0, (jint)labelLengths_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    if (!set(env, inputLengths, 0, (jint)inputLengths_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+    // algo is primitive
+    // ctcLossDesc is read-only
+    if (!set(env, sizeInBytes, 0, (jlong)sizeInBytes_native)) return JCUDNN_STATUS_INTERNAL_ERROR;
+
+    // Return the result
+    jint jniResult = (jint)jniResult_native;
+    return jniResult;
+}
+
+/**
+* 
+* DEPRECATED routines to be removed next release :
+User should use the non-suffixed version (which has the API and functionality of _v6 version)
+Routines with _v5 suffix has the functionality of the non-suffixed routines in the CUDNN V6
+* 
+*/ +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptor_1v6Native(JNIEnv *env, jclass cls, jobject handle, jobject rnnDesc, jint hiddenSize, jint numLayers, jobject dropoutDesc, jint inputMode, jint direction, jint mode, jint algo, jint dataType) +{ + // Null-checks for non-primitive arguments + if (handle == NULL) { - ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dwDesc' is null for cudnnRNNBackwardWeights"); + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cudnnSetRNNDescriptor_v6"); return JCUDNN_STATUS_INTERNAL_ERROR; } - if (dw == NULL) + if (rnnDesc == NULL) { - ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dw' is null for cudnnRNNBackwardWeights"); + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnSetRNNDescriptor_v6"); return JCUDNN_STATUS_INTERNAL_ERROR; } - if (reserveSpace == NULL) + // hiddenSize is primitive + // numLayers is primitive + if (dropoutDesc == NULL) { - ThrowByName(env, "java/lang/NullPointerException", "Parameter 'reserveSpace' is null for cudnnRNNBackwardWeights"); + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetRNNDescriptor_v6"); return JCUDNN_STATUS_INTERNAL_ERROR; } - // reserveSpaceSizeInBytes is primitive + // inputMode is primitive + // direction is primitive + // mode is primitive + // algo is primitive + // dataType is primitive // Log message - Logger::log(LOG_TRACE, "Executing cudnnRNNBackwardWeights(handle=%p, rnnDesc=%p, seqLength=%d, xDesc=%p, x=%p, hxDesc=%p, hx=%p, yDesc=%p, y=%p, workspace=%p, workSpaceSizeInBytes=%ld, dwDesc=%p, dw=%p, reserveSpace=%p, reserveSpaceSizeInBytes=%ld)\n", - handle, rnnDesc, seqLength, xDesc, x, hxDesc, hx, yDesc, y, workspace, workSpaceSizeInBytes, dwDesc, dw, reserveSpace, reserveSpaceSizeInBytes); + Logger::log(LOG_TRACE, "Executing cudnnSetRNNDescriptor_v6(handle=%p, rnnDesc=%p, hiddenSize=%d, numLayers=%d, dropoutDesc=%p, inputMode=%d, direction=%d, mode=%d, algo=%d, dataType=%d)\n", + handle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType); // Native variable declarations cudnnHandle_t handle_native; cudnnRNNDescriptor_t rnnDesc_native; - int seqLength_native = 0; - cudnnTensorDescriptor_t * xDesc_native; - void * x_native = NULL; - cudnnTensorDescriptor_t hxDesc_native; - void * hx_native = NULL; - cudnnTensorDescriptor_t * yDesc_native; - void * y_native = NULL; - void * workspace_native = NULL; - size_t workSpaceSizeInBytes_native = 0; - cudnnFilterDescriptor_t dwDesc_native; - void * dw_native = NULL; - void * reserveSpace_native = NULL; - size_t reserveSpaceSizeInBytes_native = 0; + int hiddenSize_native = 0; + int numLayers_native = 0; + cudnnDropoutDescriptor_t dropoutDesc_native; + cudnnRNNInputMode_t inputMode_native; + cudnnDirectionMode_t direction_native; + cudnnRNNMode_t mode_native; + cudnnRNNAlgo_t algo_native; + cudnnDataType_t dataType_native; // Obtain native variable values handle_native = (cudnnHandle_t)getNativePointerValue(env, handle); rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc); - seqLength_native = (int)seqLength; - if (!initNative(env, xDesc, xDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR; - x_native = (void *)getPointer(env, x); - hxDesc_native = (cudnnTensorDescriptor_t)getNativePointerValue(env, hxDesc); - hx_native = (void *)getPointer(env, hx); - if (!initNative(env, yDesc, yDesc_native, true)) return JCUDNN_STATUS_INTERNAL_ERROR; - y_native = (void *)getPointer(env, y); - workspace_native = (void *)getPointer(env, workspace); - workSpaceSizeInBytes_native = (size_t)workSpaceSizeInBytes; - dwDesc_native = (cudnnFilterDescriptor_t)getNativePointerValue(env, dwDesc); - dw_native = (void *)getPointer(env, dw); - reserveSpace_native = (void *)getPointer(env, reserveSpace); - reserveSpaceSizeInBytes_native = (size_t)reserveSpaceSizeInBytes; + hiddenSize_native = (int)hiddenSize; + numLayers_native = (int)numLayers; + dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc); + inputMode_native = (cudnnRNNInputMode_t)inputMode; + direction_native = (cudnnDirectionMode_t)direction; + mode_native = (cudnnRNNMode_t)mode; + algo_native = (cudnnRNNAlgo_t)algo; + dataType_native = (cudnnDataType_t)dataType; // Native function call - cudnnStatus_t jniResult_native = cudnnRNNBackwardWeights(handle_native, rnnDesc_native, seqLength_native, xDesc_native, x_native, hxDesc_native, hx_native, yDesc_native, y_native, workspace_native, workSpaceSizeInBytes_native, dwDesc_native, dw_native, reserveSpace_native, reserveSpaceSizeInBytes_native); + cudnnStatus_t jniResult_native = cudnnSetRNNDescriptor_v6(handle_native, rnnDesc_native, hiddenSize_native, numLayers_native, dropoutDesc_native, inputMode_native, direction_native, mode_native, algo_native, dataType_native); // Write back native variable values // handle is read-only // rnnDesc is read-only - // seqLength is primitive - if (!releaseNative(env, xDesc_native, xDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR; - // x is a native pointer - // hxDesc is read-only - // hx is a native pointer - if (!releaseNative(env, yDesc_native, yDesc, false)) return JCUDNN_STATUS_INTERNAL_ERROR; - // y is a native pointer - // workspace is a native pointer - // workSpaceSizeInBytes is primitive - // dwDesc is read-only - // dw is a native pointer - // reserveSpace is a native pointer - // reserveSpaceSizeInBytes is primitive + // hiddenSize is primitive + // numLayers is primitive + // dropoutDesc is read-only + // inputMode is primitive + // direction is primitive + // mode is primitive + // algo is primitive + // dataType is primitive + + // Return the result + jint jniResult = (jint)jniResult_native; + return jniResult; +} + +JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptor_1v5Native(JNIEnv *env, jclass cls, jobject rnnDesc, jint hiddenSize, jint numLayers, jobject dropoutDesc, jint inputMode, jint direction, jint mode, jint dataType) +{ + // Null-checks for non-primitive arguments + if (rnnDesc == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'rnnDesc' is null for cudnnSetRNNDescriptor_v5"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + // hiddenSize is primitive + // numLayers is primitive + if (dropoutDesc == NULL) + { + ThrowByName(env, "java/lang/NullPointerException", "Parameter 'dropoutDesc' is null for cudnnSetRNNDescriptor_v5"); + return JCUDNN_STATUS_INTERNAL_ERROR; + } + // inputMode is primitive + // direction is primitive + // mode is primitive + // dataType is primitive + + // Log message + Logger::log(LOG_TRACE, "Executing cudnnSetRNNDescriptor_v5(rnnDesc=%p, hiddenSize=%d, numLayers=%d, dropoutDesc=%p, inputMode=%d, direction=%d, mode=%d, dataType=%d)\n", + rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, dataType); + + // Native variable declarations + cudnnRNNDescriptor_t rnnDesc_native; + int hiddenSize_native = 0; + int numLayers_native = 0; + cudnnDropoutDescriptor_t dropoutDesc_native; + cudnnRNNInputMode_t inputMode_native; + cudnnDirectionMode_t direction_native; + cudnnRNNMode_t mode_native; + cudnnDataType_t dataType_native; + + // Obtain native variable values + rnnDesc_native = (cudnnRNNDescriptor_t)getNativePointerValue(env, rnnDesc); + hiddenSize_native = (int)hiddenSize; + numLayers_native = (int)numLayers; + dropoutDesc_native = (cudnnDropoutDescriptor_t)getNativePointerValue(env, dropoutDesc); + inputMode_native = (cudnnRNNInputMode_t)inputMode; + direction_native = (cudnnDirectionMode_t)direction; + mode_native = (cudnnRNNMode_t)mode; + dataType_native = (cudnnDataType_t)dataType; + + // Native function call + cudnnStatus_t jniResult_native = cudnnSetRNNDescriptor_v5(rnnDesc_native, hiddenSize_native, numLayers_native, dropoutDesc_native, inputMode_native, direction_native, mode_native, dataType_native); + + // Write back native variable values + // rnnDesc is read-only + // hiddenSize is primitive + // numLayers is primitive + // dropoutDesc is read-only + // inputMode is primitive + // direction is primitive + // mode is primitive + // dataType is primitive // Return the result jint jniResult = (jint)jniResult_native; @@ -8579,3 +10597,4 @@ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardWeightsNative(JN + diff --git a/JCudnnJNI/src/JCudnn.hpp b/JCudnnJNI/src/JCudnn.hpp index 808b5a5..44777a1 100644 --- a/JCudnnJNI/src/JCudnn.hpp +++ b/JCudnnJNI/src/JCudnn.hpp @@ -2,7 +2,7 @@ * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA * Deep Neural Network library, to be used with JCuda * - * Copyright (c) 2015-2016 Marco Hutter - http://www.jcuda.org + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -26,9 +26,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/* DO NOT EDIT THIS FILE - it is machine generated */ + /* DO NOT EDIT THIS FILE - it is machine generated */ #include -/* Header for class jcuda_jcudnn_JCudnn */ + /* Header for class jcuda_jcudnn_JCudnn */ #ifndef _Included_jcuda_jcudnn_JCudnn #define _Included_jcuda_jcudnn_JCudnn @@ -36,13 +36,13 @@ extern "C" { #endif #undef jcuda_jcudnn_JCudnn_CUDNN_MAJOR -#define jcuda_jcudnn_JCudnn_CUDNN_MAJOR 5L +#define jcuda_jcudnn_JCudnn_CUDNN_MAJOR 7L #undef jcuda_jcudnn_JCudnn_CUDNN_MINOR -#define jcuda_jcudnn_JCudnn_CUDNN_MINOR 1L +#define jcuda_jcudnn_JCudnn_CUDNN_MINOR 0L #undef jcuda_jcudnn_JCudnn_CUDNN_PATCHLEVEL -#define jcuda_jcudnn_JCudnn_CUDNN_PATCHLEVEL 5L +#define jcuda_jcudnn_JCudnn_CUDNN_PATCHLEVEL 2L #undef jcuda_jcudnn_JCudnn_CUDNN_VERSION -#define jcuda_jcudnn_JCudnn_CUDNN_VERSION 5105L +#define jcuda_jcudnn_JCudnn_CUDNN_VERSION 7002L #undef jcuda_jcudnn_JCudnn_CUDNN_DIM_MAX #define jcuda_jcudnn_JCudnn_CUDNN_DIM_MAX 8L #undef jcuda_jcudnn_JCudnn_CUDNN_BN_MIN_EPSILON @@ -63,6 +63,14 @@ extern "C" { JNIEXPORT jlong JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetVersionNative (JNIEnv *, jclass); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetCudartVersionNative + * Signature: ()J + */ + JNIEXPORT jlong JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCudartVersionNative + (JNIEnv *, jclass); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnGetErrorStringNative @@ -71,6 +79,22 @@ extern "C" { JNIEXPORT jstring JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetErrorStringNative (JNIEnv *, jclass, jint); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnQueryRuntimeErrorNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;[IILjcuda/jcudnn/cudnnRuntimeTag;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnQueryRuntimeErrorNative + (JNIEnv *, jclass, jobject, jintArray, jint, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetPropertyNative + * Signature: (I[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetPropertyNative + (JNIEnv *, jclass, jint, jintArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnCreateNative @@ -143,6 +167,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNdDescriptorNative (JNIEnv *, jclass, jobject, jint, jint, jintArray, jintArray); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetTensorNdDescriptorExNative + * Signature: (Ljcuda/jcudnn/cudnnTensorDescriptor;III[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetTensorNdDescriptorExNative + (JNIEnv *, jclass, jobject, jint, jint, jint, jintArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnGetTensorNdDescriptorNative @@ -151,6 +183,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetTensorNdDescriptorNative (JNIEnv *, jclass, jobject, jint, jintArray, jintArray, jintArray, jintArray); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetTensorSizeInBytesNative + * Signature: (Ljcuda/jcudnn/cudnnTensorDescriptor;[J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetTensorSizeInBytesNative + (JNIEnv *, jclass, jobject, jlongArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnDestroyTensorDescriptorNative @@ -215,6 +255,62 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnOpTensorNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnCreateReduceTensorDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnReduceTensorDescriptor;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateReduceTensorDescriptorNative + (JNIEnv *, jclass, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetReduceTensorDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnReduceTensorDescriptor;IIIII)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetReduceTensorDescriptorNative + (JNIEnv *, jclass, jobject, jint, jint, jint, jint, jint); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetReduceTensorDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnReduceTensorDescriptor;[I[I[I[I[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReduceTensorDescriptorNative + (JNIEnv *, jclass, jobject, jintArray, jintArray, jintArray, jintArray, jintArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnDestroyReduceTensorDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnReduceTensorDescriptor;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyReduceTensorDescriptorNative + (JNIEnv *, jclass, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetReductionIndicesSizeNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnReduceTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;[J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReductionIndicesSizeNative + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jlongArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetReductionWorkspaceSizeNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnReduceTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;[J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetReductionWorkspaceSizeNative + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jlongArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnReduceTensorNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnReduceTensorDescriptor;Ljcuda/Pointer;JLjcuda/Pointer;JLjcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnReduceTensorNative + (JNIEnv *, jclass, jobject, jobject, jobject, jlong, jobject, jlong, jobject, jobject, jobject, jobject, jobject, jobject); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnSetTensorNative @@ -289,34 +385,50 @@ extern "C" { /* * Class: jcuda_jcudnn_JCudnn - * Method: cudnnSetConvolution2dDescriptorNative - * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;IIIIIII)I + * Method: cudnnSetConvolutionMathTypeNative + * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;I)I */ - JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptorNative - (JNIEnv *, jclass, jobject, jint, jint, jint, jint, jint, jint, jint); + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionMathTypeNative + (JNIEnv *, jclass, jobject, jint); /* * Class: jcuda_jcudnn_JCudnn - * Method: cudnnSetConvolution2dDescriptor_v5Native - * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;IIIIIIII)I + * Method: cudnnGetConvolutionMathTypeNative + * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;[I)I */ - JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptor_1v5Native - (JNIEnv *, jclass, jobject, jint, jint, jint, jint, jint, jint, jint, jint); + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionMathTypeNative + (JNIEnv *, jclass, jobject, jintArray); /* * Class: jcuda_jcudnn_JCudnn - * Method: cudnnGetConvolution2dDescriptorNative - * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;[I[I[I[I[I[I[I)I + * Method: cudnnSetConvolutionGroupCountNative + * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;I)I */ - JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptorNative - (JNIEnv *, jclass, jobject, jintArray, jintArray, jintArray, jintArray, jintArray, jintArray, jintArray); + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolutionGroupCountNative + (JNIEnv *, jclass, jobject, jint); /* * Class: jcuda_jcudnn_JCudnn - * Method: cudnnGetConvolution2dDescriptor_v5Native + * Method: cudnnGetConvolutionGroupCountNative + * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionGroupCountNative + (JNIEnv *, jclass, jobject, jintArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetConvolution2dDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;IIIIIIII)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetConvolution2dDescriptorNative + (JNIEnv *, jclass, jobject, jint, jint, jint, jint, jint, jint, jint, jint); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolution2dDescriptorNative * Signature: (Ljcuda/jcudnn/cudnnConvolutionDescriptor;[I[I[I[I[I[I[I[I)I */ - JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptor_1v5Native + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolution2dDescriptorNative (JNIEnv *, jclass, jobject, jintArray, jintArray, jintArray, jintArray, jintArray, jintArray, jintArray, jintArray); /* @@ -359,6 +471,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyConvolutionDescriptorNative (JNIEnv *, jclass, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionForwardAlgorithmMaxCountNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithmMaxCountNative + (JNIEnv *, jclass, jobject, jintArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnFindConvolutionForwardAlgorithmNative @@ -383,6 +503,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithmNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jlong, jintArray); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionForwardAlgorithm_v7Native + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnFilterDescriptor;Ljcuda/jcudnn/cudnnConvolutionDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;I[I[Ljcuda/jcudnn/cudnnConvolutionFwdAlgoPerf;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionForwardAlgorithm_1v7Native + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jintArray, jobjectArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnGetConvolutionForwardWorkspaceSizeNative @@ -399,6 +527,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionForwardNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jint, jobject, jlong, jobject, jobject, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnConvolutionBiasActivationForwardNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnFilterDescriptor;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnConvolutionDescriptor;ILjcuda/Pointer;JLjcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;Ljcuda/jcudnn/cudnnActivationDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBiasActivationForwardNative + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jint, jobject, jlong, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnConvolutionBackwardBiasNative @@ -407,6 +543,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardBiasNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jobject, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionBackwardFilterAlgorithmMaxCountNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithmMaxCountNative + (JNIEnv *, jclass, jobject, jintArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnFindConvolutionBackwardFilterAlgorithmNative @@ -431,6 +575,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithmNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jlong, jintArray); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionBackwardFilterAlgorithm_v7Native + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnConvolutionDescriptor;Ljcuda/jcudnn/cudnnFilterDescriptor;I[I[Ljcuda/jcudnn/cudnnConvolutionBwdFilterAlgoPerf;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardFilterAlgorithm_1v7Native + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jintArray, jobjectArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnGetConvolutionBackwardFilterWorkspaceSizeNative @@ -447,6 +599,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnConvolutionBackwardFilterNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jint, jobject, jlong, jobject, jobject, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionBackwardDataAlgorithmMaxCountNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithmMaxCountNative + (JNIEnv *, jclass, jobject, jintArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnFindConvolutionBackwardDataAlgorithmNative @@ -471,6 +631,14 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithmNative (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jlong, jintArray); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetConvolutionBackwardDataAlgorithm_v7Native + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnFilterDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnConvolutionDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;I[I[Ljcuda/jcudnn/cudnnConvolutionBwdDataAlgoPerf;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetConvolutionBackwardDataAlgorithm_1v7Native + (JNIEnv *, jclass, jobject, jobject, jobject, jobject, jobject, jint, jintArray, jobjectArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnGetConvolutionBackwardDataWorkspaceSizeNative @@ -831,6 +999,22 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetDropoutDescriptorNative (JNIEnv *, jclass, jobject, jobject, jfloat, jobject, jlong, jlong); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnRestoreDropoutDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnDropoutDescriptor;Ljcuda/jcudnn/cudnnHandle;FLjcuda/Pointer;JJ)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRestoreDropoutDescriptorNative + (JNIEnv *, jclass, jobject, jobject, jfloat, jobject, jlong, jlong); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetDropoutDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnDropoutDescriptor;Ljcuda/jcudnn/cudnnHandle;[FLjcuda/Pointer;[J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetDropoutDescriptorNative + (JNIEnv *, jclass, jobject, jobject, jfloatArray, jobject, jlongArray); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnDropoutForwardNative @@ -863,13 +1047,53 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyRNNDescriptorNative (JNIEnv *, jclass, jobject); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnCreatePersistentRNNPlanNative + * Signature: (Ljcuda/jcudnn/cudnnRNNDescriptor;IILjcuda/jcudnn/cudnnPersistentRNNPlan;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreatePersistentRNNPlanNative + (JNIEnv *, jclass, jobject, jint, jint, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetPersistentRNNPlanNative + * Signature: (Ljcuda/jcudnn/cudnnRNNDescriptor;Ljcuda/jcudnn/cudnnPersistentRNNPlan;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetPersistentRNNPlanNative + (JNIEnv *, jclass, jobject, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnDestroyPersistentRNNPlanNative + * Signature: (Ljcuda/jcudnn/cudnnPersistentRNNPlan;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyPersistentRNNPlanNative + (JNIEnv *, jclass, jobject); + /* * Class: jcuda_jcudnn_JCudnn * Method: cudnnSetRNNDescriptorNative - * Signature: (Ljcuda/jcudnn/cudnnRNNDescriptor;IILjcuda/jcudnn/cudnnDropoutDescriptor;IIII)I + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnRNNDescriptor;IILjcuda/jcudnn/cudnnDropoutDescriptor;IIIII)I */ JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptorNative - (JNIEnv *, jclass, jobject, jint, jint, jobject, jint, jint, jint, jint); + (JNIEnv *, jclass, jobject, jobject, jint, jint, jobject, jint, jint, jint, jint, jint); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetRNNDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnRNNDescriptor;[I[ILjcuda/jcudnn/cudnnDropoutDescriptor;[I[I[I[I[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetRNNDescriptorNative + (JNIEnv *, jclass, jobject, jobject, jintArray, jintArray, jobject, jintArray, jintArray, jintArray, jintArray, jintArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetRNNMatrixMathTypeNative + * Signature: (Ljcuda/jcudnn/cudnnRNNDescriptor;I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNMatrixMathTypeNative + (JNIEnv *, jclass, jobject, jint); /* * Class: jcuda_jcudnn_JCudnn @@ -943,6 +1167,70 @@ extern "C" { JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnRNNBackwardWeightsNative (JNIEnv *, jclass, jobject, jobject, jint, jobjectArray, jobject, jobject, jobject, jobjectArray, jobject, jobject, jlong, jobject, jobject, jobject, jlong); + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnCreateCTCLossDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnCTCLossDescriptor;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCreateCTCLossDescriptorNative + (JNIEnv *, jclass, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetCTCLossDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnCTCLossDescriptor;I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetCTCLossDescriptorNative + (JNIEnv *, jclass, jobject, jint); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetCTCLossDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnCTCLossDescriptor;[I)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCTCLossDescriptorNative + (JNIEnv *, jclass, jobject, jintArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnDestroyCTCLossDescriptorNative + * Signature: (Ljcuda/jcudnn/cudnnCTCLossDescriptor;)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnDestroyCTCLossDescriptorNative + (JNIEnv *, jclass, jobject); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnCTCLossNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;[I[I[ILjcuda/Pointer;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/Pointer;ILjcuda/jcudnn/cudnnCTCLossDescriptor;Ljcuda/Pointer;J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnCTCLossNative + (JNIEnv *, jclass, jobject, jobject, jobject, jintArray, jintArray, jintArray, jobject, jobject, jobject, jint, jobject, jobject, jlong); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnGetCTCLossWorkspaceSizeNative + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnTensorDescriptor;Ljcuda/jcudnn/cudnnTensorDescriptor;[I[I[IILjcuda/jcudnn/cudnnCTCLossDescriptor;[J)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnGetCTCLossWorkspaceSizeNative + (JNIEnv *, jclass, jobject, jobject, jobject, jintArray, jintArray, jintArray, jint, jobject, jlongArray); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetRNNDescriptor_v6Native + * Signature: (Ljcuda/jcudnn/cudnnHandle;Ljcuda/jcudnn/cudnnRNNDescriptor;IILjcuda/jcudnn/cudnnDropoutDescriptor;IIIII)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptor_1v6Native + (JNIEnv *, jclass, jobject, jobject, jint, jint, jobject, jint, jint, jint, jint, jint); + + /* + * Class: jcuda_jcudnn_JCudnn + * Method: cudnnSetRNNDescriptor_v5Native + * Signature: (Ljcuda/jcudnn/cudnnRNNDescriptor;IILjcuda/jcudnn/cudnnDropoutDescriptor;IIII)I + */ + JNIEXPORT jint JNICALL Java_jcuda_jcudnn_JCudnn_cudnnSetRNNDescriptor_1v5Native + (JNIEnv *, jclass, jobject, jint, jint, jobject, jint, jint, jint, jint); + #ifdef __cplusplus } #endif diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/JCudnn.java b/JCudnnJava/src/main/java/jcuda/jcudnn/JCudnn.java index 0bef8ac..148dd99 100644 --- a/JCudnnJava/src/main/java/jcuda/jcudnn/JCudnn.java +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/JCudnn.java @@ -2,7 +2,7 @@ * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA * Deep Neural Network library, to be used with JCuda * - * Copyright (c) 2015-2015 Marco Hutter - http://www.jcuda.org + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -40,9 +40,9 @@ */ public class JCudnn { - public static final int CUDNN_MAJOR = 5; - public static final int CUDNN_MINOR = 1; - public static final int CUDNN_PATCHLEVEL = 5; + public static final int CUDNN_MAJOR = 7; + public static final int CUDNN_MINOR = 0; + public static final int CUDNN_PATCHLEVEL = 2; public static final int CUDNN_VERSION = (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL); @@ -161,7 +161,15 @@ public static long cudnnGetVersion() private static native long cudnnGetVersionNative(); - // human-readable error messages + /** Returns CUDA Runtime version statically linked against cudnn */ + public static long cudnnGetCudartVersion() + { + return cudnnGetCudartVersionNative(); + } + private static native long cudnnGetCudartVersionNative(); + + + /** human-readable error messages */ public static String cudnnGetErrorString( int status) { @@ -171,6 +179,32 @@ private static native String cudnnGetErrorStringNative( int status); + public static int cudnnQueryRuntimeError( + cudnnHandle handle, + int[] rstatus, + int mode, + cudnnRuntimeTag tag) + { + return checkResult(cudnnQueryRuntimeErrorNative(handle, rstatus, mode, tag)); + } + private static native int cudnnQueryRuntimeErrorNative( + cudnnHandle handle, + int[] rstatus, + int mode, + cudnnRuntimeTag tag); + + + public static int cudnnGetProperty( + int type, + int[] value) + { + return checkResult(cudnnGetPropertyNative(type, value)); + } + private static native int cudnnGetPropertyNative( + int type, + int[] value); + + public static int cudnnCreate( cudnnHandle handle) { @@ -211,7 +245,7 @@ private static native int cudnnGetStreamNative( cudaStream_t streamId); - /* Create an instance of a generic Tensor descriptor */ + /** Create an instance of a generic Tensor descriptor */ public static int cudnnCreateTensorDescriptor( cudnnTensorDescriptor tensorDesc) { @@ -224,31 +258,31 @@ private static native int cudnnCreateTensorDescriptorNative( public static int cudnnSetTensor4dDescriptor( cudnnTensorDescriptor tensorDesc, int format, - int dataType, // image data type - int n, // number of inputs (batch size) - int c, // number of input feature maps - int h, // height of input section - int w)// width of input section + int dataType, /** image data type */ + int n, /** number of inputs (batch size) */ + int c, /** number of input feature maps */ + int h, /** height of input section */ + int w)/** width of input section */ { return checkResult(cudnnSetTensor4dDescriptorNative(tensorDesc, format, dataType, n, c, h, w)); } private static native int cudnnSetTensor4dDescriptorNative( cudnnTensorDescriptor tensorDesc, int format, - int dataType, // image data type - int n, // number of inputs (batch size) - int c, // number of input feature maps - int h, // height of input section - int w);// width of input section + int dataType, /** image data type */ + int n, /** number of inputs (batch size) */ + int c, /** number of input feature maps */ + int h, /** height of input section */ + int w);/** width of input section */ public static int cudnnSetTensor4dDescriptorEx( cudnnTensorDescriptor tensorDesc, - int dataType, // image data type - int n, // number of inputs (batch size) - int c, // number of input feature maps - int h, // height of input section - int w, // width of input section + int dataType, /** image data type */ + int n, /** number of inputs (batch size) */ + int c, /** number of input feature maps */ + int h, /** height of input section */ + int w, /** width of input section */ int nStride, int cStride, int hStride, @@ -258,11 +292,11 @@ public static int cudnnSetTensor4dDescriptorEx( } private static native int cudnnSetTensor4dDescriptorExNative( cudnnTensorDescriptor tensorDesc, - int dataType, // image data type - int n, // number of inputs (batch size) - int c, // number of input feature maps - int h, // height of input section - int w, // width of input section + int dataType, /** image data type */ + int n, /** number of inputs (batch size) */ + int c, /** number of input feature maps */ + int h, /** height of input section */ + int w, /** width of input section */ int nStride, int cStride, int hStride, @@ -271,11 +305,11 @@ private static native int cudnnSetTensor4dDescriptorExNative( public static int cudnnGetTensor4dDescriptor( cudnnTensorDescriptor tensorDesc, - int[] dataType, // image data type - int[] n, // number of inputs (batch size) - int[] c, // number of input feature maps - int[] h, // height of input section - int[] w, // width of input section + int[] dataType, /** image data type */ + int[] n, /** number of inputs (batch size) */ + int[] c, /** number of input feature maps */ + int[] h, /** height of input section */ + int[] w, /** width of input section */ int[] nStride, int[] cStride, int[] hStride, @@ -285,11 +319,11 @@ public static int cudnnGetTensor4dDescriptor( } private static native int cudnnGetTensor4dDescriptorNative( cudnnTensorDescriptor tensorDesc, - int[] dataType, // image data type - int[] n, // number of inputs (batch size) - int[] c, // number of input feature maps - int[] h, // height of input section - int[] w, // width of input section + int[] dataType, /** image data type */ + int[] n, /** number of inputs (batch size) */ + int[] c, /** number of input feature maps */ + int[] h, /** height of input section */ + int[] w, /** width of input section */ int[] nStride, int[] cStride, int[] hStride, @@ -313,6 +347,23 @@ private static native int cudnnSetTensorNdDescriptorNative( int[] strideA); + public static int cudnnSetTensorNdDescriptorEx( + cudnnTensorDescriptor tensorDesc, + int format, + int dataType, + int nbDims, + int[] dimA) + { + return checkResult(cudnnSetTensorNdDescriptorExNative(tensorDesc, format, dataType, nbDims, dimA)); + } + private static native int cudnnSetTensorNdDescriptorExNative( + cudnnTensorDescriptor tensorDesc, + int format, + int dataType, + int nbDims, + int[] dimA); + + public static int cudnnGetTensorNdDescriptor( cudnnTensorDescriptor tensorDesc, int nbDimsRequested, @@ -332,7 +383,18 @@ private static native int cudnnGetTensorNdDescriptorNative( int[] strideA); - /* + public static int cudnnGetTensorSizeInBytes( + cudnnTensorDescriptor tensorDesc, + long[] size) + { + return checkResult(cudnnGetTensorSizeInBytesNative(tensorDesc, size)); + } + private static native int cudnnGetTensorSizeInBytesNative( + cudnnTensorDescriptor tensorDesc, + long[] size); + + + /** *
      * PixelOffset( n, c, h, w ) = n *input_stride + c * feature_stride + h * h_stride + w * w_stride
     
@@ -357,7 +419,7 @@ private static native int cudnnGetTensorNdDescriptorNative(
     
      * 
*/ - /* Destroy an instance of Tensor4d descriptor */ + /** Destroy an instance of Tensor4d descriptor */ public static int cudnnDestroyTensorDescriptor( cudnnTensorDescriptor tensorDesc) { @@ -367,7 +429,7 @@ private static native int cudnnDestroyTensorDescriptorNative( cudnnTensorDescriptor tensorDesc); - /* Tensor layout conversion helper (y = alpha * x + beta * y) */ + /** Tensor layout conversion helper (y = alpha * x + beta * y) */ public static int cudnnTransformTensor( cudnnHandle handle, Pointer alpha, @@ -389,7 +451,7 @@ private static native int cudnnTransformTensorNative( Pointer y); - /* Tensor Bias addition : C = alpha * A + beta * C */ + /** Tensor Bias addition : C = alpha * A + beta * C */ public static int cudnnAddTensor( cudnnHandle handle, Pointer alpha, @@ -459,7 +521,8 @@ private static native int cudnnDestroyOpTensorDescriptorNative( cudnnOpTensorDescriptor opTensorDesc); - /* Tensor Bias operation : C = op( alpha1 * A, alpha2 * B ) + beta * C */ + /** Tensor operation : C = op( alpha1 * A, alpha2 * B ) + beta * C */ + /** B tensor is ignored for CUDNN_OP_TENSOR_SQRT, CUDNN_OP_TENSOR_NOT. */ public static int cudnnOpTensor( cudnnHandle handle, cudnnOpTensorDescriptor opTensorDesc, @@ -489,7 +552,133 @@ private static native int cudnnOpTensorNative( Pointer C); - /* Set all values of a tensor to a given value : y[i] = value[0] */ + public static int cudnnCreateReduceTensorDescriptor( + cudnnReduceTensorDescriptor reduceTensorDesc) + { + return checkResult(cudnnCreateReduceTensorDescriptorNative(reduceTensorDesc)); + } + private static native int cudnnCreateReduceTensorDescriptorNative( + cudnnReduceTensorDescriptor reduceTensorDesc); + + + public static int cudnnSetReduceTensorDescriptor( + cudnnReduceTensorDescriptor reduceTensorDesc, + int reduceTensorOp, + int reduceTensorCompType, + int reduceTensorNanOpt, + int reduceTensorIndices, + int reduceTensorIndicesType) + { + return checkResult(cudnnSetReduceTensorDescriptorNative(reduceTensorDesc, reduceTensorOp, reduceTensorCompType, reduceTensorNanOpt, reduceTensorIndices, reduceTensorIndicesType)); + } + private static native int cudnnSetReduceTensorDescriptorNative( + cudnnReduceTensorDescriptor reduceTensorDesc, + int reduceTensorOp, + int reduceTensorCompType, + int reduceTensorNanOpt, + int reduceTensorIndices, + int reduceTensorIndicesType); + + + public static int cudnnGetReduceTensorDescriptor( + cudnnReduceTensorDescriptor reduceTensorDesc, + int[] reduceTensorOp, + int[] reduceTensorCompType, + int[] reduceTensorNanOpt, + int[] reduceTensorIndices, + int[] reduceTensorIndicesType) + { + return checkResult(cudnnGetReduceTensorDescriptorNative(reduceTensorDesc, reduceTensorOp, reduceTensorCompType, reduceTensorNanOpt, reduceTensorIndices, reduceTensorIndicesType)); + } + private static native int cudnnGetReduceTensorDescriptorNative( + cudnnReduceTensorDescriptor reduceTensorDesc, + int[] reduceTensorOp, + int[] reduceTensorCompType, + int[] reduceTensorNanOpt, + int[] reduceTensorIndices, + int[] reduceTensorIndicesType); + + + public static int cudnnDestroyReduceTensorDescriptor( + cudnnReduceTensorDescriptor reduceTensorDesc) + { + return checkResult(cudnnDestroyReduceTensorDescriptorNative(reduceTensorDesc)); + } + private static native int cudnnDestroyReduceTensorDescriptorNative( + cudnnReduceTensorDescriptor reduceTensorDesc); + + + /** Helper function to return the minimum size of the index space to be passed to the reduction given the input and output tensors */ + public static int cudnnGetReductionIndicesSize( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + cudnnTensorDescriptor aDesc, + cudnnTensorDescriptor cDesc, + long[] sizeInBytes) + { + return checkResult(cudnnGetReductionIndicesSizeNative(handle, reduceTensorDesc, aDesc, cDesc, sizeInBytes)); + } + private static native int cudnnGetReductionIndicesSizeNative( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + cudnnTensorDescriptor aDesc, + cudnnTensorDescriptor cDesc, + long[] sizeInBytes); + + + /** Helper function to return the minimum size of the workspace to be passed to the reduction given the input and output tensors */ + public static int cudnnGetReductionWorkspaceSize( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + cudnnTensorDescriptor aDesc, + cudnnTensorDescriptor cDesc, + long[] sizeInBytes) + { + return checkResult(cudnnGetReductionWorkspaceSizeNative(handle, reduceTensorDesc, aDesc, cDesc, sizeInBytes)); + } + private static native int cudnnGetReductionWorkspaceSizeNative( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + cudnnTensorDescriptor aDesc, + cudnnTensorDescriptor cDesc, + long[] sizeInBytes); + + + /** Tensor operation : C = reduce op( alpha * A ) + beta * C */ + /** The NaN propagation enum applies to only the min and max reduce ops; the other reduce ops propagate NaN as usual. */ + /** The indices space is ignored for reduce ops other than min or max. */ + public static int cudnnReduceTensor( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + Pointer indices, + long indicesSizeInBytes, + Pointer workspace, + long workspaceSizeInBytes, + Pointer alpha, + cudnnTensorDescriptor aDesc, + Pointer A, + Pointer beta, + cudnnTensorDescriptor cDesc, + Pointer C) + { + return checkResult(cudnnReduceTensorNative(handle, reduceTensorDesc, indices, indicesSizeInBytes, workspace, workspaceSizeInBytes, alpha, aDesc, A, beta, cDesc, C)); + } + private static native int cudnnReduceTensorNative( + cudnnHandle handle, + cudnnReduceTensorDescriptor reduceTensorDesc, + Pointer indices, + long indicesSizeInBytes, + Pointer workspace, + long workspaceSizeInBytes, + Pointer alpha, + cudnnTensorDescriptor aDesc, + Pointer A, + Pointer beta, + cudnnTensorDescriptor cDesc, + Pointer C); + + + /** Set all values of a tensor to a given value : y[i] = value[0] */ public static int cudnnSetTensor( cudnnHandle handle, cudnnTensorDescriptor yDesc, @@ -505,7 +694,7 @@ private static native int cudnnSetTensorNative( Pointer valuePtr); - /* Scale all values of a tensor by a given factor : y[i] = alpha * y[i] */ + /** Scale all values of a tensor by a given factor : y[i] = alpha * y[i] */ public static int cudnnScaleTensor( cudnnHandle handle, cudnnTensorDescriptor yDesc, @@ -521,7 +710,7 @@ private static native int cudnnScaleTensorNative( Pointer alpha); - /* Create an instance of FilterStruct */ + /** Create an instance of FilterStruct */ public static int cudnnCreateFilterDescriptor( cudnnFilterDescriptor filterDesc) { @@ -533,49 +722,49 @@ private static native int cudnnCreateFilterDescriptorNative( public static int cudnnSetFilter4dDescriptor( cudnnFilterDescriptor filterDesc, - int dataType, // image data type + int dataType, /** image data type */ int format, - int k, // number of output feature maps - int c, // number of input feature maps - int h, // height of each input filter - int w)// width of each input filter + int k, /** number of output feature maps */ + int c, /** number of input feature maps */ + int h, /** height of each input filter */ + int w)/** width of each input filter */ { return checkResult(cudnnSetFilter4dDescriptorNative(filterDesc, dataType, format, k, c, h, w)); } private static native int cudnnSetFilter4dDescriptorNative( cudnnFilterDescriptor filterDesc, - int dataType, // image data type + int dataType, /** image data type */ int format, - int k, // number of output feature maps - int c, // number of input feature maps - int h, // height of each input filter - int w);// width of each input filter + int k, /** number of output feature maps */ + int c, /** number of input feature maps */ + int h, /** height of each input filter */ + int w);/** width of each input filter */ public static int cudnnGetFilter4dDescriptor( cudnnFilterDescriptor filterDesc, - int[] dataType, // image data type + int[] dataType, /** image data type */ int[] format, - int[] k, // number of output feature maps - int[] c, // number of input feature maps - int[] h, // height of each input filter - int[] w)// width of each input filter + int[] k, /** number of output feature maps */ + int[] c, /** number of input feature maps */ + int[] h, /** height of each input filter */ + int[] w)/** width of each input filter */ { return checkResult(cudnnGetFilter4dDescriptorNative(filterDesc, dataType, format, k, c, h, w)); } private static native int cudnnGetFilter4dDescriptorNative( cudnnFilterDescriptor filterDesc, - int[] dataType, // image data type + int[] dataType, /** image data type */ int[] format, - int[] k, // number of output feature maps - int[] c, // number of input feature maps - int[] h, // height of each input filter - int[] w);// width of each input filter + int[] k, /** number of output feature maps */ + int[] c, /** number of input feature maps */ + int[] h, /** height of each input filter */ + int[] w);/** width of each input filter */ public static int cudnnSetFilterNdDescriptor( cudnnFilterDescriptor filterDesc, - int dataType, // image data type + int dataType, /** image data type */ int format, int nbDims, int[] filterDimA) @@ -584,7 +773,7 @@ public static int cudnnSetFilterNdDescriptor( } private static native int cudnnSetFilterNdDescriptorNative( cudnnFilterDescriptor filterDesc, - int dataType, // image data type + int dataType, /** image data type */ int format, int nbDims, int[] filterDimA); @@ -593,7 +782,7 @@ private static native int cudnnSetFilterNdDescriptorNative( public static int cudnnGetFilterNdDescriptor( cudnnFilterDescriptor filterDesc, int nbDimsRequested, - int[] dataType, // image data type + int[] dataType, /** image data type */ int[] format, int[] nbDims, int[] filterDimA) @@ -603,7 +792,7 @@ public static int cudnnGetFilterNdDescriptor( private static native int cudnnGetFilterNdDescriptorNative( cudnnFilterDescriptor filterDesc, int nbDimsRequested, - int[] dataType, // image data type + int[] dataType, /** image data type */ int[] format, int[] nbDims, int[] filterDimA); @@ -618,7 +807,7 @@ private static native int cudnnDestroyFilterDescriptorNative( cudnnFilterDescriptor filterDesc); - /* Create an instance of convolution descriptor */ + /** Create an instance of convolution descriptor */ public static int cudnnCreateConvolutionDescriptor( cudnnConvolutionDescriptor convDesc) { @@ -628,103 +817,101 @@ private static native int cudnnCreateConvolutionDescriptorNative( cudnnConvolutionDescriptor convDesc); - public static int cudnnSetConvolution2dDescriptor( + public static int cudnnSetConvolutionMathType( cudnnConvolutionDescriptor convDesc, - int pad_h, // zero-padding height - int pad_w, // zero-padding width - int u, // vertical filter stride - int v, // horizontal filter stride - int upscalex, // upscale the input in x-direction - int upscaley, // upscale the input in y-direction - int mode) + int mathType) { - return checkResult(cudnnSetConvolution2dDescriptorNative(convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode)); + return checkResult(cudnnSetConvolutionMathTypeNative(convDesc, mathType)); } - private static native int cudnnSetConvolution2dDescriptorNative( + private static native int cudnnSetConvolutionMathTypeNative( cudnnConvolutionDescriptor convDesc, - int pad_h, // zero-padding height - int pad_w, // zero-padding width - int u, // vertical filter stride - int v, // horizontal filter stride - int upscalex, // upscale the input in x-direction - int upscaley, // upscale the input in y-direction - int mode); + int mathType); - public static int cudnnSetConvolution2dDescriptor_v5( + public static int cudnnGetConvolutionMathType( cudnnConvolutionDescriptor convDesc, - int pad_h, // zero-padding height - int pad_w, // zero-padding width - int u, // vertical filter stride - int v, // horizontal filter stride - int upscalex, // upscale the input in x-direction - int upscaley, // upscale the input in y-direction - int mode, - int dataType) + int[] mathType) { - return checkResult(cudnnSetConvolution2dDescriptor_v5Native(convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode, dataType)); + return checkResult(cudnnGetConvolutionMathTypeNative(convDesc, mathType)); } - private static native int cudnnSetConvolution2dDescriptor_v5Native( + private static native int cudnnGetConvolutionMathTypeNative( cudnnConvolutionDescriptor convDesc, - int pad_h, // zero-padding height - int pad_w, // zero-padding width - int u, // vertical filter stride - int v, // horizontal filter stride - int upscalex, // upscale the input in x-direction - int upscaley, // upscale the input in y-direction - int mode, - int dataType); + int[] mathType); - public static int cudnnGetConvolution2dDescriptor( + public static int cudnnSetConvolutionGroupCount( cudnnConvolutionDescriptor convDesc, - int[] pad_h, // zero-padding height - int[] pad_w, // zero-padding width - int[] u, // vertical filter stride - int[] v, // horizontal filter stride - int[] upscalex, // upscale the input in x-direction - int[] upscaley, // upscale the input in y-direction - int[] mode) + int groupCount) { - return checkResult(cudnnGetConvolution2dDescriptorNative(convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode)); + return checkResult(cudnnSetConvolutionGroupCountNative(convDesc, groupCount)); } - private static native int cudnnGetConvolution2dDescriptorNative( + private static native int cudnnSetConvolutionGroupCountNative( + cudnnConvolutionDescriptor convDesc, + int groupCount); + + + public static int cudnnGetConvolutionGroupCount( + cudnnConvolutionDescriptor convDesc, + int[] groupCount) + { + return checkResult(cudnnGetConvolutionGroupCountNative(convDesc, groupCount)); + } + private static native int cudnnGetConvolutionGroupCountNative( + cudnnConvolutionDescriptor convDesc, + int[] groupCount); + + + public static int cudnnSetConvolution2dDescriptor( + cudnnConvolutionDescriptor convDesc, + int pad_h, /** zero-padding height */ + int pad_w, /** zero-padding width */ + int u, /** vertical filter stride */ + int v, /** horizontal filter stride */ + int dilation_h, /** filter dilation in the vertical dimension */ + int dilation_w, /** filter dilation in the horizontal dimension */ + int mode, + int computeType) + { + return checkResult(cudnnSetConvolution2dDescriptorNative(convDesc, pad_h, pad_w, u, v, dilation_h, dilation_w, mode, computeType)); + } + private static native int cudnnSetConvolution2dDescriptorNative( cudnnConvolutionDescriptor convDesc, - int[] pad_h, // zero-padding height - int[] pad_w, // zero-padding width - int[] u, // vertical filter stride - int[] v, // horizontal filter stride - int[] upscalex, // upscale the input in x-direction - int[] upscaley, // upscale the input in y-direction - int[] mode); + int pad_h, /** zero-padding height */ + int pad_w, /** zero-padding width */ + int u, /** vertical filter stride */ + int v, /** horizontal filter stride */ + int dilation_h, /** filter dilation in the vertical dimension */ + int dilation_w, /** filter dilation in the horizontal dimension */ + int mode, + int computeType); - public static int cudnnGetConvolution2dDescriptor_v5( + public static int cudnnGetConvolution2dDescriptor( cudnnConvolutionDescriptor convDesc, - int[] pad_h, // zero-padding height - int[] pad_w, // zero-padding width - int[] u, // vertical filter stride - int[] v, // horizontal filter stride - int[] upscalex, // upscale the input in x-direction - int[] upscaley, // upscale the input in y-direction + int[] pad_h, /** zero-padding height */ + int[] pad_w, /** zero-padding width */ + int[] u, /** vertical filter stride */ + int[] v, /** horizontal filter stride */ + int[] dilation_h, /** filter dilation in the vertical dimension */ + int[] dilation_w, /** filter dilation in the horizontal dimension */ int[] mode, - int[] dataType) + int[] computeType) { - return checkResult(cudnnGetConvolution2dDescriptor_v5Native(convDesc, pad_h, pad_w, u, v, upscalex, upscaley, mode, dataType)); + return checkResult(cudnnGetConvolution2dDescriptorNative(convDesc, pad_h, pad_w, u, v, dilation_h, dilation_w, mode, computeType)); } - private static native int cudnnGetConvolution2dDescriptor_v5Native( + private static native int cudnnGetConvolution2dDescriptorNative( cudnnConvolutionDescriptor convDesc, - int[] pad_h, // zero-padding height - int[] pad_w, // zero-padding width - int[] u, // vertical filter stride - int[] v, // horizontal filter stride - int[] upscalex, // upscale the input in x-direction - int[] upscaley, // upscale the input in y-direction + int[] pad_h, /** zero-padding height */ + int[] pad_w, /** zero-padding width */ + int[] u, /** vertical filter stride */ + int[] v, /** horizontal filter stride */ + int[] dilation_h, /** filter dilation in the vertical dimension */ + int[] dilation_w, /** filter dilation in the horizontal dimension */ int[] mode, - int[] dataType); + int[] computeType); - /* Helper function to return the dimensions of the output tensor given a convolution descriptor */ + /** Helper function to return the dimensions of the output tensor given a convolution descriptor */ public static int cudnnGetConvolution2dForwardOutputDim( cudnnConvolutionDescriptor convDesc, cudnnTensorDescriptor inputTensorDesc, @@ -748,23 +935,23 @@ private static native int cudnnGetConvolution2dForwardOutputDimNative( public static int cudnnSetConvolutionNdDescriptor( cudnnConvolutionDescriptor convDesc, - int arrayLength, /* nbDims-2 size */ + int arrayLength, /** nbDims-2 size */ int[] padA, int[] filterStrideA, - int[] upscaleA, + int[] dilationA, int mode, - int dataType)// convolution data type + int computeType)/** convolution data type */ { - return checkResult(cudnnSetConvolutionNdDescriptorNative(convDesc, arrayLength, padA, filterStrideA, upscaleA, mode, dataType)); + return checkResult(cudnnSetConvolutionNdDescriptorNative(convDesc, arrayLength, padA, filterStrideA, dilationA, mode, computeType)); } private static native int cudnnSetConvolutionNdDescriptorNative( cudnnConvolutionDescriptor convDesc, - int arrayLength, /* nbDims-2 size */ + int arrayLength, /** nbDims-2 size */ int[] padA, int[] filterStrideA, - int[] upscaleA, + int[] dilationA, int mode, - int dataType);// convolution data type + int computeType);/** convolution data type */ public static int cudnnGetConvolutionNdDescriptor( @@ -773,11 +960,11 @@ public static int cudnnGetConvolutionNdDescriptor( int[] arrayLength, int[] padA, int[] strideA, - int[] upscaleA, + int[] dilationA, int[] mode, - int[] dataType)// convolution data type + int[] computeType)/** convolution data type */ { - return checkResult(cudnnGetConvolutionNdDescriptorNative(convDesc, arrayLengthRequested, arrayLength, padA, strideA, upscaleA, mode, dataType)); + return checkResult(cudnnGetConvolutionNdDescriptorNative(convDesc, arrayLengthRequested, arrayLength, padA, strideA, dilationA, mode, computeType)); } private static native int cudnnGetConvolutionNdDescriptorNative( cudnnConvolutionDescriptor convDesc, @@ -785,12 +972,12 @@ private static native int cudnnGetConvolutionNdDescriptorNative( int[] arrayLength, int[] padA, int[] strideA, - int[] upscaleA, + int[] dilationA, int[] mode, - int[] dataType);// convolution data type + int[] computeType);/** convolution data type */ - /* Helper function to return the dimensions of the output tensor given a convolution descriptor */ + /** Helper function to return the dimensions of the output tensor given a convolution descriptor */ public static int cudnnGetConvolutionNdForwardOutputDim( cudnnConvolutionDescriptor convDesc, cudnnTensorDescriptor inputTensorDesc, @@ -808,7 +995,7 @@ private static native int cudnnGetConvolutionNdForwardOutputDimNative( int[] tensorOuputDimA); - /* Destroy an instance of convolution descriptor */ + /** Destroy an instance of convolution descriptor */ public static int cudnnDestroyConvolutionDescriptor( cudnnConvolutionDescriptor convDesc) { @@ -818,6 +1005,17 @@ private static native int cudnnDestroyConvolutionDescriptorNative( cudnnConvolutionDescriptor convDesc); + public static int cudnnGetConvolutionForwardAlgorithmMaxCount( + cudnnHandle handle, + int[] count) + { + return checkResult(cudnnGetConvolutionForwardAlgorithmMaxCountNative(handle, count)); + } + private static native int cudnnGetConvolutionForwardAlgorithmMaxCountNative( + cudnnHandle handle, + int[] count); + + public static int cudnnFindConvolutionForwardAlgorithm( cudnnHandle handle, cudnnTensorDescriptor xDesc, @@ -897,10 +1095,33 @@ private static native int cudnnGetConvolutionForwardAlgorithmNative( int[] algo); - /* + public static int cudnnGetConvolutionForwardAlgorithm_v7( + cudnnHandle handle, + cudnnTensorDescriptor srcDesc, + cudnnFilterDescriptor filterDesc, + cudnnConvolutionDescriptor convDesc, + cudnnTensorDescriptor destDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionFwdAlgoPerf[] perfResults) + { + return checkResult(cudnnGetConvolutionForwardAlgorithm_v7Native(handle, srcDesc, filterDesc, convDesc, destDesc, requestedAlgoCount, returnedAlgoCount, perfResults)); + } + private static native int cudnnGetConvolutionForwardAlgorithm_v7Native( + cudnnHandle handle, + cudnnTensorDescriptor srcDesc, + cudnnFilterDescriptor filterDesc, + cudnnConvolutionDescriptor convDesc, + cudnnTensorDescriptor destDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionFwdAlgoPerf[] perfResults); + + + /** * convolution algorithm (which requires potentially some workspace) */ - /* Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ + /** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ public static int cudnnGetConvolutionForwardWorkspaceSize( cudnnHandle handle, cudnnTensorDescriptor xDesc, @@ -922,8 +1143,8 @@ private static native int cudnnGetConvolutionForwardWorkspaceSizeNative( long[] sizeInBytes); - /* Convolution functions: All of the form "output = alpha * Op(inputs) + beta * output" */ - /* Function to perform the forward pass for batch convolution */ + /** Convolution functions: All of the form "output = alpha * Op(inputs) + beta * output" */ + /** Function to perform the forward pass for batch convolution */ public static int cudnnConvolutionForward( cudnnHandle handle, Pointer alpha, @@ -957,7 +1178,51 @@ private static native int cudnnConvolutionForwardNative( Pointer y); - /* Function to compute the bias gradient for batch convolution */ + /** Fused conv/bias/activation operation : y = Act( alpha1 * conv(x) + alpha2 * z + bias ) */ + public static int cudnnConvolutionBiasActivationForward( + cudnnHandle handle, + Pointer alpha1, + cudnnTensorDescriptor xDesc, + Pointer x, + cudnnFilterDescriptor wDesc, + Pointer w, + cudnnConvolutionDescriptor convDesc, + int algo, + Pointer workSpace, + long workSpaceSizeInBytes, + Pointer alpha2, + cudnnTensorDescriptor zDesc, + Pointer z, + cudnnTensorDescriptor biasDesc, + Pointer bias, + cudnnActivationDescriptor activationDesc, + cudnnTensorDescriptor yDesc, + Pointer y) + { + return checkResult(cudnnConvolutionBiasActivationForwardNative(handle, alpha1, xDesc, x, wDesc, w, convDesc, algo, workSpace, workSpaceSizeInBytes, alpha2, zDesc, z, biasDesc, bias, activationDesc, yDesc, y)); + } + private static native int cudnnConvolutionBiasActivationForwardNative( + cudnnHandle handle, + Pointer alpha1, + cudnnTensorDescriptor xDesc, + Pointer x, + cudnnFilterDescriptor wDesc, + Pointer w, + cudnnConvolutionDescriptor convDesc, + int algo, + Pointer workSpace, + long workSpaceSizeInBytes, + Pointer alpha2, + cudnnTensorDescriptor zDesc, + Pointer z, + cudnnTensorDescriptor biasDesc, + Pointer bias, + cudnnActivationDescriptor activationDesc, + cudnnTensorDescriptor yDesc, + Pointer y); + + + /** Function to compute the bias gradient for batch convolution */ public static int cudnnConvolutionBackwardBias( cudnnHandle handle, Pointer alpha, @@ -979,6 +1244,17 @@ private static native int cudnnConvolutionBackwardBiasNative( Pointer db); + public static int cudnnGetConvolutionBackwardFilterAlgorithmMaxCount( + cudnnHandle handle, + int[] count) + { + return checkResult(cudnnGetConvolutionBackwardFilterAlgorithmMaxCountNative(handle, count)); + } + private static native int cudnnGetConvolutionBackwardFilterAlgorithmMaxCountNative( + cudnnHandle handle, + int[] count); + + public static int cudnnFindConvolutionBackwardFilterAlgorithm( cudnnHandle handle, cudnnTensorDescriptor xDesc, @@ -1058,10 +1334,33 @@ private static native int cudnnGetConvolutionBackwardFilterAlgorithmNative( int[] algo); - /* + public static int cudnnGetConvolutionBackwardFilterAlgorithm_v7( + cudnnHandle handle, + cudnnTensorDescriptor srcDesc, + cudnnTensorDescriptor diffDesc, + cudnnConvolutionDescriptor convDesc, + cudnnFilterDescriptor gradDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionBwdFilterAlgoPerf[] perfResults) + { + return checkResult(cudnnGetConvolutionBackwardFilterAlgorithm_v7Native(handle, srcDesc, diffDesc, convDesc, gradDesc, requestedAlgoCount, returnedAlgoCount, perfResults)); + } + private static native int cudnnGetConvolutionBackwardFilterAlgorithm_v7Native( + cudnnHandle handle, + cudnnTensorDescriptor srcDesc, + cudnnTensorDescriptor diffDesc, + cudnnConvolutionDescriptor convDesc, + cudnnFilterDescriptor gradDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionBwdFilterAlgoPerf[] perfResults); + + + /** * convolution algorithm (which requires potentially some workspace) */ - /* Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ + /** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ public static int cudnnGetConvolutionBackwardFilterWorkspaceSize( cudnnHandle handle, cudnnTensorDescriptor xDesc, @@ -1116,6 +1415,17 @@ private static native int cudnnConvolutionBackwardFilterNative( Pointer dw); + public static int cudnnGetConvolutionBackwardDataAlgorithmMaxCount( + cudnnHandle handle, + int[] count) + { + return checkResult(cudnnGetConvolutionBackwardDataAlgorithmMaxCountNative(handle, count)); + } + private static native int cudnnGetConvolutionBackwardDataAlgorithmMaxCountNative( + cudnnHandle handle, + int[] count); + + public static int cudnnFindConvolutionBackwardDataAlgorithm( cudnnHandle handle, cudnnFilterDescriptor wDesc, @@ -1195,7 +1505,30 @@ private static native int cudnnGetConvolutionBackwardDataAlgorithmNative( int[] algo); - /* Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ + public static int cudnnGetConvolutionBackwardDataAlgorithm_v7( + cudnnHandle handle, + cudnnFilterDescriptor filterDesc, + cudnnTensorDescriptor diffDesc, + cudnnConvolutionDescriptor convDesc, + cudnnTensorDescriptor gradDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionBwdDataAlgoPerf[] perfResults) + { + return checkResult(cudnnGetConvolutionBackwardDataAlgorithm_v7Native(handle, filterDesc, diffDesc, convDesc, gradDesc, requestedAlgoCount, returnedAlgoCount, perfResults)); + } + private static native int cudnnGetConvolutionBackwardDataAlgorithm_v7Native( + cudnnHandle handle, + cudnnFilterDescriptor filterDesc, + cudnnTensorDescriptor diffDesc, + cudnnConvolutionDescriptor convDesc, + cudnnTensorDescriptor gradDesc, + int requestedAlgoCount, + int[] returnedAlgoCount, + cudnnConvolutionBwdDataAlgoPerf[] perfResults); + + + /** Helper function to return the minimum size of the workspace to be passed to the convolution given an algo*/ public static int cudnnGetConvolutionBackwardDataWorkspaceSize( cudnnHandle handle, cudnnFilterDescriptor wDesc, @@ -1269,8 +1602,8 @@ private static native int cudnnIm2ColNative( Pointer colBuffer); - /* Softmax functions: All of the form "output = alpha * Op(inputs) + beta * output" */ - /* Function to perform forward softmax */ + /** Softmax functions: All of the form "output = alpha * Op(inputs) + beta * output" */ + /** Function to perform forward softmax */ public static int cudnnSoftmaxForward( cudnnHandle handle, int algo, @@ -1296,7 +1629,7 @@ private static native int cudnnSoftmaxForwardNative( Pointer y); - /* Function to perform backward softmax */ + /** Function to perform backward softmax */ public static int cudnnSoftmaxBackward( cudnnHandle handle, int algo, @@ -1326,7 +1659,7 @@ private static native int cudnnSoftmaxBackwardNative( Pointer dx); - /* Create an instance of pooling descriptor */ + /** Create an instance of pooling descriptor */ public static int cudnnCreatePoolingDescriptor( cudnnPoolingDescriptor poolingDesc) { @@ -1464,7 +1797,7 @@ private static native int cudnnGetPooling2dForwardOutputDimNative( int[] w); - /* Destroy an instance of pooling descriptor */ + /** Destroy an instance of pooling descriptor */ public static int cudnnDestroyPoolingDescriptor( cudnnPoolingDescriptor poolingDesc) { @@ -1474,8 +1807,8 @@ private static native int cudnnDestroyPoolingDescriptorNative( cudnnPoolingDescriptor poolingDesc); - /* Pooling functions: All of the form "output = alpha * Op(inputs) + beta * output" */ - /* Function to perform forward pooling */ + /** Pooling functions: All of the form "output = alpha * Op(inputs) + beta * output" */ + /** Function to perform forward pooling */ public static int cudnnPoolingForward( cudnnHandle handle, cudnnPoolingDescriptor poolingDesc, @@ -1499,7 +1832,7 @@ private static native int cudnnPoolingForwardNative( Pointer y); - /* Function to perform backward pooling */ + /** Function to perform backward pooling */ public static int cudnnPoolingBackward( cudnnHandle handle, cudnnPoolingDescriptor poolingDesc, @@ -1531,7 +1864,7 @@ private static native int cudnnPoolingBackwardNative( Pointer dx); - /* Activation functions: All of the form "output = alpha * Op(inputs) + beta * output" */ + /** Activation functions: All of the form "output = alpha * Op(inputs) + beta * output" */ public static int cudnnCreateActivationDescriptor( cudnnActivationDescriptor activationDesc) { @@ -1545,30 +1878,30 @@ public static int cudnnSetActivationDescriptor( cudnnActivationDescriptor activationDesc, int mode, int reluNanOpt, - double reluCeiling) + double coef)/** ceiling for clipped RELU, alpha for ELU */ { - return checkResult(cudnnSetActivationDescriptorNative(activationDesc, mode, reluNanOpt, reluCeiling)); + return checkResult(cudnnSetActivationDescriptorNative(activationDesc, mode, reluNanOpt, coef)); } private static native int cudnnSetActivationDescriptorNative( cudnnActivationDescriptor activationDesc, int mode, int reluNanOpt, - double reluCeiling); + double coef);/** ceiling for clipped RELU, alpha for ELU */ public static int cudnnGetActivationDescriptor( cudnnActivationDescriptor activationDesc, int[] mode, int[] reluNanOpt, - double[] reluCeiling) + double[] coef)/** ceiling for clipped RELU, alpha for ELU */ { - return checkResult(cudnnGetActivationDescriptorNative(activationDesc, mode, reluNanOpt, reluCeiling)); + return checkResult(cudnnGetActivationDescriptorNative(activationDesc, mode, reluNanOpt, coef)); } private static native int cudnnGetActivationDescriptorNative( cudnnActivationDescriptor activationDesc, int[] mode, int[] reluNanOpt, - double[] reluCeiling); + double[] coef);/** ceiling for clipped RELU, alpha for ELU */ public static int cudnnDestroyActivationDescriptor( @@ -1580,7 +1913,7 @@ private static native int cudnnDestroyActivationDescriptorNative( cudnnActivationDescriptor activationDesc); - /* Function to perform forward activation */ + /** Function to perform forward activation */ public static int cudnnActivationForward( cudnnHandle handle, cudnnActivationDescriptor activationDesc, @@ -1604,7 +1937,7 @@ private static native int cudnnActivationForwardNative( Pointer y); - /* Function to perform backward activation */ + /** Function to perform backward activation */ public static int cudnnActivationBackward( cudnnHandle handle, cudnnActivationDescriptor activationDesc, @@ -1636,7 +1969,7 @@ private static native int cudnnActivationBackwardNative( Pointer dx); - /* + /** *
     * Create an instance of LRN (Local Response Normalization) descriptor
     * Uses lrnN=5, lrnAlpha=1e-4, lrnBeta=0.75, lrnK=2.0 as defaults from Krizhevsky'12 ImageNet paper
@@ -1651,7 +1984,7 @@ private static native int cudnnCreateLRNDescriptorNative(
         cudnnLRNDescriptor normDesc);
 
 
-    /*
+    /**
      * 
     * Uses a window [center-lookBehind, center+lookAhead], where
     * lookBehind = floor( (lrnN-1)/2 ), lookAhead = lrnN-lookBehind-1.
@@ -1675,7 +2008,7 @@ private static native int cudnnSetLRNDescriptorNative(
         double lrnK);
 
 
-    /*
+    /**
      * 
     * Retrieve the settings currently stored in an LRN layer descriptor
     * Any of the provided pointers can be NULL (no corresponding value will be returned)
@@ -1698,7 +2031,7 @@ private static native int cudnnGetLRNDescriptorNative(
         double[] lrnK);
 
 
-    /* Destroy an instance of LRN descriptor */
+    /** Destroy an instance of LRN descriptor */
     public static int cudnnDestroyLRNDescriptor(
         cudnnLRNDescriptor lrnDesc)
     {
@@ -1708,8 +2041,8 @@ private static native int cudnnDestroyLRNDescriptorNative(
         cudnnLRNDescriptor lrnDesc);
 
 
-    /* LRN functions: output = alpha * normalize(x) + beta * old_y */
-    /* LRN cross-channel forward computation. Double parameters cast to tensor data type */
+    /** LRN functions: output = alpha * normalize(x) + beta * old_y */
+    /** LRN cross-channel forward computation. Double parameters cast to tensor data type */
     public static int cudnnLRNCrossChannelForward(
         cudnnHandle handle, 
         cudnnLRNDescriptor normDesc, 
@@ -1735,7 +2068,7 @@ private static native int cudnnLRNCrossChannelForwardNative(
         Pointer y);
 
 
-    /* LRN cross-channel backward computation. Double parameters cast to tensor data type */
+    /** LRN cross-channel backward computation. Double parameters cast to tensor data type */
     public static int cudnnLRNCrossChannelBackward(
         cudnnHandle handle, 
         cudnnLRNDescriptor normDesc, 
@@ -1769,15 +2102,15 @@ private static native int cudnnLRNCrossChannelBackwardNative(
         Pointer dx);
 
 
-    /* LCN/divisive normalization functions: y = alpha * normalize(x) + beta * y */
+    /** LCN/divisive normalization functions: y = alpha * normalize(x) + beta * y */
     public static int cudnnDivisiveNormalizationForward(
         cudnnHandle handle, 
         cudnnLRNDescriptor normDesc, 
         int mode, 
         Pointer alpha, 
-        cudnnTensorDescriptor xDesc, // same desc for means, temp, temp2
+        cudnnTensorDescriptor xDesc, /** same desc for means, temp, temp2 */
         Pointer x, 
-        Pointer means, // if NULL, means are assumed to be zero
+        Pointer means, /** if NULL, means are assumed to be zero */
         Pointer temp, 
         Pointer temp2, 
         Pointer beta, 
@@ -1791,9 +2124,9 @@ private static native int cudnnDivisiveNormalizationForwardNative(
         cudnnLRNDescriptor normDesc, 
         int mode, 
         Pointer alpha, 
-        cudnnTensorDescriptor xDesc, // same desc for means, temp, temp2
+        cudnnTensorDescriptor xDesc, /** same desc for means, temp, temp2 */
         Pointer x, 
-        Pointer means, // if NULL, means are assumed to be zero
+        Pointer means, /** if NULL, means are assumed to be zero */
         Pointer temp, 
         Pointer temp2, 
         Pointer beta, 
@@ -1806,16 +2139,16 @@ public static int cudnnDivisiveNormalizationBackward(
         cudnnLRNDescriptor normDesc, 
         int mode, 
         Pointer alpha, 
-        cudnnTensorDescriptor xDesc, // same desc for x, means, dy, temp, temp2
+        cudnnTensorDescriptor xDesc, /** same desc for x, means, dy, temp, temp2 */
         Pointer x, 
-        Pointer means, // if NULL, means are assumed to be zero
+        Pointer means, /** if NULL, means are assumed to be zero */
         Pointer dy, 
         Pointer temp, 
         Pointer temp2, 
         Pointer beta, 
-        cudnnTensorDescriptor dXdMeansDesc, // same desc for dx, dMeans
-        Pointer dx, // output x differential
-        Pointer dMeans)// output means differential, can be NULL
+        cudnnTensorDescriptor dXdMeansDesc, /** same desc for dx, dMeans */
+        Pointer dx, /** output x differential */
+        Pointer dMeans)/** output means differential, can be NULL */
     {
         return checkResult(cudnnDivisiveNormalizationBackwardNative(handle, normDesc, mode, alpha, xDesc, x, means, dy, temp, temp2, beta, dXdMeansDesc, dx, dMeans));
     }
@@ -1824,19 +2157,19 @@ private static native int cudnnDivisiveNormalizationBackwardNative(
         cudnnLRNDescriptor normDesc, 
         int mode, 
         Pointer alpha, 
-        cudnnTensorDescriptor xDesc, // same desc for x, means, dy, temp, temp2
+        cudnnTensorDescriptor xDesc, /** same desc for x, means, dy, temp, temp2 */
         Pointer x, 
-        Pointer means, // if NULL, means are assumed to be zero
+        Pointer means, /** if NULL, means are assumed to be zero */
         Pointer dy, 
         Pointer temp, 
         Pointer temp2, 
         Pointer beta, 
-        cudnnTensorDescriptor dXdMeansDesc, // same desc for dx, dMeans
-        Pointer dx, // output x differential
-        Pointer dMeans);// output means differential, can be NULL
+        cudnnTensorDescriptor dXdMeansDesc, /** same desc for dx, dMeans */
+        Pointer dx, /** output x differential */
+        Pointer dMeans);/** output means differential, can be NULL */
 
 
-    /*
+    /**
      * 
     * Derives a tensor descriptor from layer data descriptor for BatchNormalization 
     * scale, invVariance, bnBias, bnScale tensors. Use this tensor desc for 
@@ -1856,17 +2189,17 @@ private static native int cudnnDeriveBNTensorDescriptorNative(
         int mode);
 
 
-    /* Computes y = BN(x). Also accumulates moving averages of mean and inverse variances */
+    /** Computes y = BN(x). Also accumulates moving averages of mean and inverse variances */
     public static int cudnnBatchNormalizationForwardTraining(
         cudnnHandle handle, 
         int mode, 
-        Pointer alpha, // alpha[0] = result blend factor
-        Pointer beta, // beta[0] = dest layer blend factor
+        Pointer alpha, /** alpha[0] = result blend factor */
+        Pointer beta, /** beta[0] = dest layer blend factor */
         cudnnTensorDescriptor xDesc, 
-        Pointer x, // NxCxHxW
+        Pointer x, /** NxCxHxW */
         cudnnTensorDescriptor yDesc, 
-        Pointer y, // NxCxHxW
-        /*
+        Pointer y, /** NxCxHxW */
+        /**
          * 
          * Shared desc for the next 6 tensors in the argument list.
                                            Data type to be set as follows:
@@ -1879,10 +2212,10 @@ public static int cudnnBatchNormalizationForwardTraining(
          * 
*/ cudnnTensorDescriptor bnScaleBiasMeanVarDesc, - // 'Gamma' and 'Beta' respectively in Ioffe and Szegedy's paper's notation + /** 'Gamma' and 'Beta' respectively in Ioffe and Szegedy's paper's notation */ Pointer bnScale, Pointer bnBias, - /* + /** *
          * MUST use factor=1 in the very first call of a complete training cycle.
                                            Use a factor=1/(1+n) at N-th call to the function to get
@@ -1894,15 +2227,15 @@ Cumulative Moving Average (CMA) behavior
          * 
*/ double exponentialAverageFactor, - /* Used in Training phase only. + /** Used in Training phase only. runningMean = newMean*factor + runningMean*(1-factor) */ Pointer resultRunningMean, - /* Output in training mode, input in inference. Is the moving average + /** Output in training mode, input in inference. Is the moving average of variance[x] (factor is applied in the same way as for runningMean) */ Pointer resultRunningVariance, - /* Has to be >= CUDNN_BN_MIN_EPSILON. Should be the same in forward and backward functions. */ + /** Has to be >= CUDNN_BN_MIN_EPSILON. Should be the same in forward and backward functions. */ double epsilon, - /* Optionally save intermediate results from the forward pass here + /** Optionally save intermediate results from the forward pass here - can be reused to speed up backward pass. NULL if unused */ Pointer resultSaveMean, Pointer resultSaveInvVariance) @@ -1912,13 +2245,13 @@ Cumulative Moving Average (CMA) behavior private static native int cudnnBatchNormalizationForwardTrainingNative( cudnnHandle handle, int mode, - Pointer alpha, // alpha[0] = result blend factor - Pointer beta, // beta[0] = dest layer blend factor + Pointer alpha, /** alpha[0] = result blend factor */ + Pointer beta, /** beta[0] = dest layer blend factor */ cudnnTensorDescriptor xDesc, - Pointer x, // NxCxHxW + Pointer x, /** NxCxHxW */ cudnnTensorDescriptor yDesc, - Pointer y, // NxCxHxW - /* + Pointer y, /** NxCxHxW */ + /** *
          * Shared desc for the next 6 tensors in the argument list.
                                            Data type to be set as follows:
@@ -1931,10 +2264,10 @@ private static native int cudnnBatchNormalizationForwardTrainingNative(
          * 
*/ cudnnTensorDescriptor bnScaleBiasMeanVarDesc, - // 'Gamma' and 'Beta' respectively in Ioffe and Szegedy's paper's notation + /** 'Gamma' and 'Beta' respectively in Ioffe and Szegedy's paper's notation */ Pointer bnScale, Pointer bnBias, - /* + /** *
          * MUST use factor=1 in the very first call of a complete training cycle.
                                            Use a factor=1/(1+n) at N-th call to the function to get
@@ -1946,21 +2279,21 @@ Cumulative Moving Average (CMA) behavior
          * 
*/ double exponentialAverageFactor, - /* Used in Training phase only. + /** Used in Training phase only. runningMean = newMean*factor + runningMean*(1-factor) */ Pointer resultRunningMean, - /* Output in training mode, input in inference. Is the moving average + /** Output in training mode, input in inference. Is the moving average of variance[x] (factor is applied in the same way as for runningMean) */ Pointer resultRunningVariance, - /* Has to be >= CUDNN_BN_MIN_EPSILON. Should be the same in forward and backward functions. */ + /** Has to be >= CUDNN_BN_MIN_EPSILON. Should be the same in forward and backward functions. */ double epsilon, - /* Optionally save intermediate results from the forward pass here + /** Optionally save intermediate results from the forward pass here - can be reused to speed up backward pass. NULL if unused */ Pointer resultSaveMean, Pointer resultSaveInvVariance); - /* + /** *
     * Performs Batch Normalization during Inference: 
     * y[i] = bnScale[k]*(x[i]-estimatedMean[k])/sqrt(epsilon+estimatedVariance[k]) + bnBias[k]
@@ -1972,12 +2305,12 @@ Cumulative Moving Average (CMA) behavior
     public static int cudnnBatchNormalizationForwardInference(
         cudnnHandle handle, 
         int mode, 
-        Pointer alpha, // alpha[0] = result blend factor
-        Pointer beta, // beta[0] = dest layer blend factor
+        Pointer alpha, /** alpha[0] = result blend factor */
+        Pointer beta, /** beta[0] = dest layer blend factor */
         cudnnTensorDescriptor xDesc, 
-        Pointer x, // NxCxHxW
+        Pointer x, /** NxCxHxW */
         cudnnTensorDescriptor yDesc, 
-        Pointer y, // NxCxHxW
+        Pointer y, /** NxCxHxW */
         cudnnTensorDescriptor bnScaleBiasMeanVarDesc, 
         Pointer bnScale, 
         Pointer bnBias, 
@@ -1990,12 +2323,12 @@ public static int cudnnBatchNormalizationForwardInference(
     private static native int cudnnBatchNormalizationForwardInferenceNative(
         cudnnHandle handle, 
         int mode, 
-        Pointer alpha, // alpha[0] = result blend factor
-        Pointer beta, // beta[0] = dest layer blend factor
+        Pointer alpha, /** alpha[0] = result blend factor */
+        Pointer beta, /** beta[0] = dest layer blend factor */
         cudnnTensorDescriptor xDesc, 
-        Pointer x, // NxCxHxW
+        Pointer x, /** NxCxHxW */
         cudnnTensorDescriptor yDesc, 
-        Pointer y, // NxCxHxW
+        Pointer y, /** NxCxHxW */
         cudnnTensorDescriptor bnScaleBiasMeanVarDesc, 
         Pointer bnScale, 
         Pointer bnBias, 
@@ -2004,7 +2337,7 @@ private static native int cudnnBatchNormalizationForwardInferenceNative(
         double epsilon);
 
 
-    /* Performs backward pass of Batch Normalization layer. Returns x gradient,
+    /** Performs backward pass of Batch Normalization layer. Returns x gradient,
     * bnScale gradient and bnBias gradient */
     public static int cudnnBatchNormalizationBackward(
         cudnnHandle handle, 
@@ -2013,21 +2346,21 @@ public static int cudnnBatchNormalizationBackward(
         Pointer betaDataDiff, 
         Pointer alphaParamDiff, 
         Pointer betaParamDiff, 
-        cudnnTensorDescriptor xDesc, // same desc for x, dx, dy
+        cudnnTensorDescriptor xDesc, /** same desc for x, dx, dy */
         Pointer x, 
         cudnnTensorDescriptor dyDesc, 
         Pointer dy, 
         cudnnTensorDescriptor dxDesc, 
         Pointer dx, 
-        /* Shared tensor desc for the 4 tensors below */
+        /** Shared tensor desc for the 4 tensors below */
         cudnnTensorDescriptor dBnScaleBiasDesc, 
-        Pointer bnScale, // bnBias doesn't affect backpropagation
-        /* scale and bias diff are not backpropagated below this layer */
+        Pointer bnScale, /** bnBias doesn't affect backpropagation */
+        /** scale and bias diff are not backpropagated below this layer */
         Pointer dBnScaleResult, 
         Pointer dBnBiasResult, 
-        /* Same epsilon as forward pass */
+        /** Same epsilon as forward pass */
         double epsilon, 
-        /* Optionally cached intermediate results from
+        /** Optionally cached intermediate results from
                                            forward pass */
         Pointer savedMean, 
         Pointer savedInvVariance)
@@ -2041,21 +2374,21 @@ private static native int cudnnBatchNormalizationBackwardNative(
         Pointer betaDataDiff, 
         Pointer alphaParamDiff, 
         Pointer betaParamDiff, 
-        cudnnTensorDescriptor xDesc, // same desc for x, dx, dy
+        cudnnTensorDescriptor xDesc, /** same desc for x, dx, dy */
         Pointer x, 
         cudnnTensorDescriptor dyDesc, 
         Pointer dy, 
         cudnnTensorDescriptor dxDesc, 
         Pointer dx, 
-        /* Shared tensor desc for the 4 tensors below */
+        /** Shared tensor desc for the 4 tensors below */
         cudnnTensorDescriptor dBnScaleBiasDesc, 
-        Pointer bnScale, // bnBias doesn't affect backpropagation
-        /* scale and bias diff are not backpropagated below this layer */
+        Pointer bnScale, /** bnBias doesn't affect backpropagation */
+        /** scale and bias diff are not backpropagated below this layer */
         Pointer dBnScaleResult, 
         Pointer dBnBiasResult, 
-        /* Same epsilon as forward pass */
+        /** Same epsilon as forward pass */
         double epsilon, 
-        /* Optionally cached intermediate results from
+        /** Optionally cached intermediate results from
                                            forward pass */
         Pointer savedMean, 
         Pointer savedInvVariance);
@@ -2204,7 +2537,7 @@ private static native int cudnnDestroyDropoutDescriptorNative(
         cudnnDropoutDescriptor dropoutDesc);
 
 
-    /*helper function to determine size of the states to be passed to cudnnSetDropoutDescriptor */
+    /**helper function to determine size of the states to be passed to cudnnSetDropoutDescriptor */
     public static int cudnnDropoutGetStatesSize(
         cudnnHandle handle, 
         long[] sizeInBytes)
@@ -2216,7 +2549,7 @@ private static native int cudnnDropoutGetStatesSizeNative(
         long[] sizeInBytes);
 
 
-    /*helper function to determine size of the reserve space to be passed to dropout forward/backward calls */
+    /**helper function to determine size of the reserve space to be passed to dropout forward/backward calls */
     public static int cudnnDropoutGetReserveSpaceSize(
         cudnnTensorDescriptor xdesc, 
         long[] sizeInBytes)
@@ -2247,6 +2580,43 @@ private static native int cudnnSetDropoutDescriptorNative(
         long seed);
 
 
+    // Restores the dropout descriptor to a previously saved-off state
+    public static int cudnnRestoreDropoutDescriptor(
+        cudnnDropoutDescriptor dropoutDesc, 
+        cudnnHandle handle, 
+        float dropout, 
+        Pointer states, 
+        long stateSizeInBytes, 
+        long seed)
+    {
+        return checkResult(cudnnRestoreDropoutDescriptorNative(dropoutDesc, handle, dropout, states, stateSizeInBytes, seed));
+    }
+    private static native int cudnnRestoreDropoutDescriptorNative(
+        cudnnDropoutDescriptor dropoutDesc, 
+        cudnnHandle handle, 
+        float dropout, 
+        Pointer states, 
+        long stateSizeInBytes, 
+        long seed);
+
+
+    public static int cudnnGetDropoutDescriptor(
+        cudnnDropoutDescriptor dropoutDesc, 
+        cudnnHandle handle, 
+        float[] dropout, 
+        Pointer states, 
+        long[] seed)
+    {
+        return checkResult(cudnnGetDropoutDescriptorNative(dropoutDesc, handle, dropout, states, seed));
+    }
+    private static native int cudnnGetDropoutDescriptorNative(
+        cudnnDropoutDescriptor dropoutDesc, 
+        cudnnHandle handle, 
+        float[] dropout, 
+        Pointer states, 
+        long[] seed);
+
+
     public static int cudnnDropoutForward(
         cudnnHandle handle, 
         cudnnDropoutDescriptor dropoutDesc, 
@@ -2311,31 +2681,110 @@ private static native int cudnnDestroyRNNDescriptorNative(
         cudnnRNNDescriptor rnnDesc);
 
 
+    /** Expensive. Creates the plan for the specific settings. */
+    public static int cudnnCreatePersistentRNNPlan(
+        cudnnRNNDescriptor rnnDesc, 
+        int minibatch, 
+        int dataType, 
+        cudnnPersistentRNNPlan plan)
+    {
+        return checkResult(cudnnCreatePersistentRNNPlanNative(rnnDesc, minibatch, dataType, plan));
+    }
+    private static native int cudnnCreatePersistentRNNPlanNative(
+        cudnnRNNDescriptor rnnDesc, 
+        int minibatch, 
+        int dataType, 
+        cudnnPersistentRNNPlan plan);
+
+
+    /** Attaches the plan to the descriptor. */
+    public static int cudnnSetPersistentRNNPlan(
+        cudnnRNNDescriptor rnnDesc, 
+        cudnnPersistentRNNPlan plan)
+    {
+        return checkResult(cudnnSetPersistentRNNPlanNative(rnnDesc, plan));
+    }
+    private static native int cudnnSetPersistentRNNPlanNative(
+        cudnnRNNDescriptor rnnDesc, 
+        cudnnPersistentRNNPlan plan);
+
+
+    public static int cudnnDestroyPersistentRNNPlan(
+        cudnnPersistentRNNPlan plan)
+    {
+        return checkResult(cudnnDestroyPersistentRNNPlanNative(plan));
+    }
+    private static native int cudnnDestroyPersistentRNNPlanNative(
+        cudnnPersistentRNNPlan plan);
+
+
     public static int cudnnSetRNNDescriptor(
+        cudnnHandle handle, 
         cudnnRNNDescriptor rnnDesc, 
         int hiddenSize, 
         int numLayers, 
-        cudnnDropoutDescriptor dropoutDesc, // Between layers, not between recurrent steps.
+        cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */
         int inputMode, 
         int direction, 
         int mode, 
+        int algo, 
         int dataType)
     {
-        return checkResult(cudnnSetRNNDescriptorNative(rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, dataType));
+        return checkResult(cudnnSetRNNDescriptorNative(handle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType));
     }
     private static native int cudnnSetRNNDescriptorNative(
+        cudnnHandle handle, 
         cudnnRNNDescriptor rnnDesc, 
         int hiddenSize, 
         int numLayers, 
-        cudnnDropoutDescriptor dropoutDesc, // Between layers, not between recurrent steps.
+        cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */
         int inputMode, 
         int direction, 
         int mode, 
+        int algo, 
         int dataType);
 
 
-    // dataType in the RNN descriptor is used to determine math precision
-    // dataType in weight descriptors and input descriptors is used to describe storage
+    public static int cudnnGetRNNDescriptor(
+        cudnnHandle cudnnHandle, 
+        cudnnRNNDescriptor rnnDesc, 
+        int[] hiddenSize, 
+        int[] numLayers, 
+        cudnnDropoutDescriptor dropoutDesc, 
+        int[] inputMode, 
+        int[] direction, 
+        int[] mode, 
+        int[] algo, 
+        int[] dataType)
+    {
+        return checkResult(cudnnGetRNNDescriptorNative(cudnnHandle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType));
+    }
+    private static native int cudnnGetRNNDescriptorNative(
+        cudnnHandle cudnnHandle, 
+        cudnnRNNDescriptor rnnDesc, 
+        int[] hiddenSize, 
+        int[] numLayers, 
+        cudnnDropoutDescriptor dropoutDesc, 
+        int[] inputMode, 
+        int[] direction, 
+        int[] mode, 
+        int[] algo, 
+        int[] dataType);
+
+
+    public static int cudnnSetRNNMatrixMathType(
+        cudnnRNNDescriptor desc, 
+        int math)
+    {
+        return checkResult(cudnnSetRNNMatrixMathTypeNative(desc, math));
+    }
+    private static native int cudnnSetRNNMatrixMathTypeNative(
+        cudnnRNNDescriptor desc, 
+        int math);
+
+
+    /** dataType in the RNN descriptor is used to determine math precision */
+    /** dataType in weight descriptors and input descriptors is used to describe storage */
     public static int cudnnGetRNNWorkspaceSize(
         cudnnHandle handle, 
         cudnnRNNDescriptor rnnDesc, 
@@ -2629,6 +3078,166 @@ private static native int cudnnRNNBackwardWeightsNative(
         long reserveSpaceSizeInBytes);
 
 
+    /** 
+    * Create an instance of a CTC (Connectionist Temporal Classification) loss descriptor
+    */
+    public static int cudnnCreateCTCLossDescriptor(
+        cudnnCTCLossDescriptor ctcLossDesc)
+    {
+        return checkResult(cudnnCreateCTCLossDescriptorNative(ctcLossDesc));
+    }
+    private static native int cudnnCreateCTCLossDescriptorNative(
+        cudnnCTCLossDescriptor ctcLossDesc);
+
+
+    public static int cudnnSetCTCLossDescriptor(
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        int compType)
+    {
+        return checkResult(cudnnSetCTCLossDescriptorNative(ctcLossDesc, compType));
+    }
+    private static native int cudnnSetCTCLossDescriptorNative(
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        int compType);
+
+
+    public static int cudnnGetCTCLossDescriptor(
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        int[] compType)
+    {
+        return checkResult(cudnnGetCTCLossDescriptorNative(ctcLossDesc, compType));
+    }
+    private static native int cudnnGetCTCLossDescriptorNative(
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        int[] compType);
+
+
+    public static int cudnnDestroyCTCLossDescriptor(
+        cudnnCTCLossDescriptor ctcLossDesc)
+    {
+        return checkResult(cudnnDestroyCTCLossDescriptorNative(ctcLossDesc));
+    }
+    private static native int cudnnDestroyCTCLossDescriptorNative(
+        cudnnCTCLossDescriptor ctcLossDesc);
+
+
+    /** return the ctc costs and gradients, given the probabilities and labels */
+    public static int cudnnCTCLoss(
+        cudnnHandle handle, 
+        cudnnTensorDescriptor probsDesc, /** Tensor descriptor for probabilities, the dimensions are T,N,A (T is the timing steps, N is the mini batch size, A is the alphabet size)  */
+        Pointer probs, /** probabilities after softmax, in GPU memory */
+        int[] labels, /** labels, in CPU memory */
+        int[] labelLengths, /** the length of each label, in CPU memory */
+        int[] inputLengths, /** the lengths of timing steps in each batch, in CPU memory */
+        Pointer costs, /** the returned costs of CTC, in GPU memory */
+        cudnnTensorDescriptor gradientsDesc, /** Tensor descriptor for gradients, the dimensions are T,N,A */
+        Pointer gradients, /** the returned CTC gradients, in GPU memory, to compute costs only, set it to NULL */
+        int algo, /** algorithm selected, supported now 0 and 1 */
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        Pointer workspace, /** pointer to the workspace, in GPU memory */
+        long workSpaceSizeInBytes)/** the workspace size needed */
+    {
+        return checkResult(cudnnCTCLossNative(handle, probsDesc, probs, labels, labelLengths, inputLengths, costs, gradientsDesc, gradients, algo, ctcLossDesc, workspace, workSpaceSizeInBytes));
+    }
+    private static native int cudnnCTCLossNative(
+        cudnnHandle handle, 
+        cudnnTensorDescriptor probsDesc, /** Tensor descriptor for probabilities, the dimensions are T,N,A (T is the timing steps, N is the mini batch size, A is the alphabet size)  */
+        Pointer probs, /** probabilities after softmax, in GPU memory */
+        int[] labels, /** labels, in CPU memory */
+        int[] labelLengths, /** the length of each label, in CPU memory */
+        int[] inputLengths, /** the lengths of timing steps in each batch, in CPU memory */
+        Pointer costs, /** the returned costs of CTC, in GPU memory */
+        cudnnTensorDescriptor gradientsDesc, /** Tensor descriptor for gradients, the dimensions are T,N,A */
+        Pointer gradients, /** the returned CTC gradients, in GPU memory, to compute costs only, set it to NULL */
+        int algo, /** algorithm selected, supported now 0 and 1 */
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        Pointer workspace, /** pointer to the workspace, in GPU memory */
+        long workSpaceSizeInBytes);/** the workspace size needed */
+
+
+    /** return the workspace size needed for ctc */
+    public static int cudnnGetCTCLossWorkspaceSize(
+        cudnnHandle handle, 
+        cudnnTensorDescriptor probsDesc, /** Tensor descriptor for probabilities, the dimensions are T,N,A (T is the timing steps, N is the mini batch size, A is the alphabet size) */
+        cudnnTensorDescriptor gradientsDesc, /** Tensor descriptor for gradients, the dimensions are T,N,A. To compute costs only, set it to NULL */
+        int[] labels, /** labels, in CPU memory */
+        int[] labelLengths, /** the length of each label, in CPU memory */
+        int[] inputLengths, /** the lengths of timing steps in each batch, in CPU memory */
+        int algo, /** algorithm selected, supported now 0 and 1 */
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        long[] sizeInBytes)/** pointer to the returned workspace size */
+    {
+        return checkResult(cudnnGetCTCLossWorkspaceSizeNative(handle, probsDesc, gradientsDesc, labels, labelLengths, inputLengths, algo, ctcLossDesc, sizeInBytes));
+    }
+    private static native int cudnnGetCTCLossWorkspaceSizeNative(
+        cudnnHandle handle, 
+        cudnnTensorDescriptor probsDesc, /** Tensor descriptor for probabilities, the dimensions are T,N,A (T is the timing steps, N is the mini batch size, A is the alphabet size) */
+        cudnnTensorDescriptor gradientsDesc, /** Tensor descriptor for gradients, the dimensions are T,N,A. To compute costs only, set it to NULL */
+        int[] labels, /** labels, in CPU memory */
+        int[] labelLengths, /** the length of each label, in CPU memory */
+        int[] inputLengths, /** the lengths of timing steps in each batch, in CPU memory */
+        int algo, /** algorithm selected, supported now 0 and 1 */
+        cudnnCTCLossDescriptor ctcLossDesc, 
+        long[] sizeInBytes);/** pointer to the returned workspace size */
+
+
+    /**
+     * 
+     * DEPRECATED routines to be removed next release :
+       User should use the non-suffixed version (which has the API and functionality of _v6 version)
+       Routines with _v5 suffix has the functionality of the non-suffixed routines in the CUDNN V6
+     * 
+ */ + public static int cudnnSetRNNDescriptor_v6( + cudnnHandle handle, + cudnnRNNDescriptor rnnDesc, + int hiddenSize, + int numLayers, + cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */ + int inputMode, + int direction, + int mode, + int algo, + int dataType) + { + return checkResult(cudnnSetRNNDescriptor_v6Native(handle, rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, algo, dataType)); + } + private static native int cudnnSetRNNDescriptor_v6Native( + cudnnHandle handle, + cudnnRNNDescriptor rnnDesc, + int hiddenSize, + int numLayers, + cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */ + int inputMode, + int direction, + int mode, + int algo, + int dataType); + + + public static int cudnnSetRNNDescriptor_v5( + cudnnRNNDescriptor rnnDesc, + int hiddenSize, + int numLayers, + cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */ + int inputMode, + int direction, + int mode, + int dataType) + { + return checkResult(cudnnSetRNNDescriptor_v5Native(rnnDesc, hiddenSize, numLayers, dropoutDesc, inputMode, direction, mode, dataType)); + } + private static native int cudnnSetRNNDescriptor_v5Native( + cudnnRNNDescriptor rnnDesc, + int hiddenSize, + int numLayers, + cudnnDropoutDescriptor dropoutDesc, /** Between layers, not between recurrent steps. */ + int inputMode, + int direction, + int mode, + int dataType); + + } diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossAlgo.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossAlgo.java new file mode 100644 index 0000000..03b614e --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossAlgo.java @@ -0,0 +1,58 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +public class cudnnCTCLossAlgo +{ + public static final int CUDNN_CTC_LOSS_ALGO_DETERMINISTIC = 0; + public static final int CUDNN_CTC_LOSS_ALGO_NON_DETERMINISTIC = 1; + + /** + * Private constructor to prevent instantiation + */ + private cudnnCTCLossAlgo() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_CTC_LOSS_ALGO_DETERMINISTIC: return "CUDNN_CTC_LOSS_ALGO_DETERMINISTIC"; + case CUDNN_CTC_LOSS_ALGO_NON_DETERMINISTIC: return "CUDNN_CTC_LOSS_ALGO_NON_DETERMINISTIC"; + } + return "INVALID cudnnCTCLossAlgo: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossDescriptor.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossDescriptor.java new file mode 100644 index 0000000..ff4074e --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnCTCLossDescriptor.java @@ -0,0 +1,58 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +import jcuda.NativePointerObject; + +/** + * Java port of a cudnnCTCLossDescriptor + */ +public class cudnnCTCLossDescriptor extends NativePointerObject +{ + /** + * Creates a new, uninitialized cudnnCTCLossDescriptor + */ + public cudnnCTCLossDescriptor() + { + // Default constructor + } + + /** + * Returns a String representation of this object. + * + * @return A String representation of this object. + */ + @Override + public String toString() + { + return "cudnnCTCLossDescriptor["+ + "nativePointer=0x"+Long.toHexString(getNativePointer())+"]"; + } +} + + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnDeterminism.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnDeterminism.java new file mode 100644 index 0000000..68383b7 --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnDeterminism.java @@ -0,0 +1,61 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +/** + * CUDNN Determinism + */ +public class cudnnDeterminism +{ + public static final int CUDNN_NON_DETERMINISTIC = 0; + public static final int CUDNN_DETERMINISTIC = 1; + + /** + * Private constructor to prevent instantiation + */ + private cudnnDeterminism() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_NON_DETERMINISTIC: return "CUDNN_NON_DETERMINISTIC"; + case CUDNN_DETERMINISTIC: return "CUDNN_DETERMINISTIC"; + } + return "INVALID cudnnDeterminism: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnErrQueryMode.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnErrQueryMode.java new file mode 100644 index 0000000..b25d0f2 --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnErrQueryMode.java @@ -0,0 +1,60 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +public class cudnnErrQueryMode +{ + public static final int CUDNN_ERRQUERY_RAWCODE = 0; + public static final int CUDNN_ERRQUERY_NONBLOCKING = 1; + public static final int CUDNN_ERRQUERY_BLOCKING = 2; + + /** + * Private constructor to prevent instantiation + */ + private cudnnErrQueryMode() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_ERRQUERY_RAWCODE: return "CUDNN_ERRQUERY_RAWCODE"; + case CUDNN_ERRQUERY_NONBLOCKING: return "CUDNN_ERRQUERY_NONBLOCKING"; + case CUDNN_ERRQUERY_BLOCKING: return "CUDNN_ERRQUERY_BLOCKING"; + } + return "INVALID cudnnErrQueryMode: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnIndicesType.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnIndicesType.java new file mode 100644 index 0000000..c7ba42d --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnIndicesType.java @@ -0,0 +1,68 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +/** + *
+* CUDNN tensor indices type size (all unsigned)
+* Currently not supported, default is 32 bit unsigned.
+ * 
+ */ +public class cudnnIndicesType +{ + public static final int CUDNN_32BIT_INDICES = 0; + public static final int CUDNN_64BIT_INDICES = 1; + public static final int CUDNN_16BIT_INDICES = 2; + public static final int CUDNN_8BIT_INDICES = 3; + + /** + * Private constructor to prevent instantiation + */ + private cudnnIndicesType() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_32BIT_INDICES: return "CUDNN_32BIT_INDICES"; + case CUDNN_64BIT_INDICES: return "CUDNN_64BIT_INDICES"; + case CUDNN_16BIT_INDICES: return "CUDNN_16BIT_INDICES"; + case CUDNN_8BIT_INDICES: return "CUDNN_8BIT_INDICES"; + } + return "INVALID cudnnIndicesType: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnMathType.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnMathType.java new file mode 100644 index 0000000..7512e3c --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnMathType.java @@ -0,0 +1,61 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +/** +* CUDNN math type +*/ +public class cudnnMathType +{ + public static final int CUDNN_DEFAULT_MATH = 0; + public static final int CUDNN_TENSOR_OP_MATH = 1; + + /** + * Private constructor to prevent instantiation + */ + private cudnnMathType() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_DEFAULT_MATH: return "CUDNN_DEFAULT_MATH"; + case CUDNN_TENSOR_OP_MATH: return "CUDNN_TENSOR_OP_MATH"; + } + return "INVALID cudnnMathType: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnPersistentRNNPlan.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnPersistentRNNPlan.java new file mode 100644 index 0000000..5f8bb65 --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnPersistentRNNPlan.java @@ -0,0 +1,58 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +import jcuda.NativePointerObject; + +/** + * Java port of a cudnnPersistentRNNPlan + */ +public class cudnnPersistentRNNPlan extends NativePointerObject +{ + /** + * Creates a new, uninitialized cudnnPersistentRNNPlan + */ + public cudnnPersistentRNNPlan() + { + // Default constructor + } + + /** + * Returns a String representation of this object. + * + * @return A String representation of this object. + */ + @Override + public String toString() + { + return "cudnnPersistentRNNPlan["+ + "nativePointer=0x"+Long.toHexString(getNativePointer())+"]"; + } +} + + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRNNAlgo.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRNNAlgo.java new file mode 100644 index 0000000..50e268a --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRNNAlgo.java @@ -0,0 +1,60 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +public class cudnnRNNAlgo +{ + public static final int CUDNN_RNN_ALGO_STANDARD = 0; + public static final int CUDNN_RNN_ALGO_PERSIST_STATIC = 1; + public static final int CUDNN_RNN_ALGO_PERSIST_DYNAMIC = 2; + + /** + * Private constructor to prevent instantiation + */ + private cudnnRNNAlgo() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_RNN_ALGO_STANDARD: return "CUDNN_RNN_ALGO_STANDARD"; + case CUDNN_RNN_ALGO_PERSIST_STATIC: return "CUDNN_RNN_ALGO_PERSIST_STATIC"; + case CUDNN_RNN_ALGO_PERSIST_DYNAMIC: return "CUDNN_RNN_ALGO_PERSIST_DYNAMIC"; + } + return "INVALID cudnnRNNAlgo: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorDescriptor.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorDescriptor.java new file mode 100644 index 0000000..f3d02ed --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorDescriptor.java @@ -0,0 +1,58 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +import jcuda.NativePointerObject; + +/** + * Java port of a cudnnReduceTensorDescriptor + */ +public class cudnnReduceTensorDescriptor extends NativePointerObject +{ + /** + * Creates a new, uninitialized cudnnReduceTensorDescriptor + */ + public cudnnReduceTensorDescriptor() + { + // Default constructor + } + + /** + * Returns a String representation of this object. + * + * @return A String representation of this object. + */ + @Override + public String toString() + { + return "cudnnReduceTensorDescriptor["+ + "nativePointer=0x"+Long.toHexString(getNativePointer())+"]"; + } +} + + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorIndices.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorIndices.java new file mode 100644 index 0000000..df38fbd --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorIndices.java @@ -0,0 +1,61 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +/** +* CUDNN ReduceTensor indices type +*/ +public class cudnnReduceTensorIndices +{ + public static final int CUDNN_REDUCE_TENSOR_NO_INDICES = 0; + public static final int CUDNN_REDUCE_TENSOR_FLATTENED_INDICES = 1; + + /** + * Private constructor to prevent instantiation + */ + private cudnnReduceTensorIndices() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_REDUCE_TENSOR_NO_INDICES: return "CUDNN_REDUCE_TENSOR_NO_INDICES"; + case CUDNN_REDUCE_TENSOR_FLATTENED_INDICES: return "CUDNN_REDUCE_TENSOR_FLATTENED_INDICES"; + } + return "INVALID cudnnReduceTensorIndices: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorOp.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorOp.java new file mode 100644 index 0000000..e44c762 --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnReduceTensorOp.java @@ -0,0 +1,75 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +/** +* CUDNN ReduceTensor op type +*/ +public class cudnnReduceTensorOp +{ + public static final int CUDNN_REDUCE_TENSOR_ADD = 0; + public static final int CUDNN_REDUCE_TENSOR_MUL = 1; + public static final int CUDNN_REDUCE_TENSOR_MIN = 2; + public static final int CUDNN_REDUCE_TENSOR_MAX = 3; + public static final int CUDNN_REDUCE_TENSOR_AMAX = 4; + public static final int CUDNN_REDUCE_TENSOR_AVG = 5; + public static final int CUDNN_REDUCE_TENSOR_NORM1 = 6; + public static final int CUDNN_REDUCE_TENSOR_NORM2 = 7; + public static final int CUDNN_REDUCE_TENSOR_MUL_NO_ZEROS = 8; + + /** + * Private constructor to prevent instantiation + */ + private cudnnReduceTensorOp() + { + // Private constructor to prevent instantiation + } + + /** + * Returns a string representation of the given constant + * + * @return A string representation of the given constant + */ + public static String stringFor(int n) + { + switch (n) + { + case CUDNN_REDUCE_TENSOR_ADD: return "CUDNN_REDUCE_TENSOR_ADD"; + case CUDNN_REDUCE_TENSOR_MUL: return "CUDNN_REDUCE_TENSOR_MUL"; + case CUDNN_REDUCE_TENSOR_MIN: return "CUDNN_REDUCE_TENSOR_MIN"; + case CUDNN_REDUCE_TENSOR_MAX: return "CUDNN_REDUCE_TENSOR_MAX"; + case CUDNN_REDUCE_TENSOR_AMAX: return "CUDNN_REDUCE_TENSOR_AMAX"; + case CUDNN_REDUCE_TENSOR_AVG: return "CUDNN_REDUCE_TENSOR_AVG"; + case CUDNN_REDUCE_TENSOR_NORM1: return "CUDNN_REDUCE_TENSOR_NORM1"; + case CUDNN_REDUCE_TENSOR_NORM2: return "CUDNN_REDUCE_TENSOR_NORM2"; + case CUDNN_REDUCE_TENSOR_MUL_NO_ZEROS: return "CUDNN_REDUCE_TENSOR_MUL_NO_ZEROS"; + } + return "INVALID cudnnReduceTensorOp: "+n; + } +} + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRuntimeTag.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRuntimeTag.java new file mode 100644 index 0000000..df2e25e --- /dev/null +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnRuntimeTag.java @@ -0,0 +1,58 @@ +/* + * JCudnn - Java bindings for cuDNN, the NVIDIA CUDA + * Deep Neural Network library, to be used with JCuda + * + * Copyright (c) 2015-2017 Marco Hutter - http://www.jcuda.org + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +package jcuda.jcudnn; + +import jcuda.NativePointerObject; + +/** + * Java port of a cudnnRuntimeTag + */ +public class cudnnRuntimeTag extends NativePointerObject +{ + /** + * Creates a new, uninitialized cudnnRuntimeTag + */ + public cudnnRuntimeTag() + { + // Default constructor + } + + /** + * Returns a String representation of this object. + * + * @return A String representation of this object. + */ + @Override + public String toString() + { + return "cudnnRuntimeTag["+ + "nativePointer=0x"+Long.toHexString(getNativePointer())+"]"; + } +} + + diff --git a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnStatus.java b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnStatus.java index 95590b1..808c90a 100644 --- a/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnStatus.java +++ b/JCudnnJava/src/main/java/jcuda/jcudnn/cudnnStatus.java @@ -43,6 +43,9 @@ public class cudnnStatus public static final int CUDNN_STATUS_EXECUTION_FAILED = 8; public static final int CUDNN_STATUS_NOT_SUPPORTED = 9; public static final int CUDNN_STATUS_LICENSE_ERROR = 10; + public static final int CUDNN_STATUS_RUNTIME_PREREQUISITE_MISSING = 11; + public static final int CUDNN_STATUS_RUNTIME_IN_PROGRESS = 12; + public static final int CUDNN_STATUS_RUNTIME_FP_OVERFLOW = 13; /** * An internal JCudnn error occurred @@ -75,6 +78,9 @@ public static String stringFor(int n) case CUDNN_STATUS_NOT_SUPPORTED: return "CUDNN_STATUS_NOT_SUPPORTED"; case CUDNN_STATUS_LICENSE_ERROR: return "CUDNN_STATUS_LICENSE_ERROR"; case JCUDNN_STATUS_INTERNAL_ERROR: return "JCUDNN_STATUS_INTERNAL_ERROR"; + case CUDNN_STATUS_RUNTIME_PREREQUISITE_MISSING: return "CUDNN_STATUS_RUNTIME_PREREQUISITE_MISSING"; + case CUDNN_STATUS_RUNTIME_IN_PROGRESS: return "CUDNN_STATUS_RUNTIME_IN_PROGRESS"; + case CUDNN_STATUS_RUNTIME_FP_OVERFLOW: return "CUDNN_STATUS_RUNTIME_FP_OVERFLOW"; } return "INVALID cudnnStatus: "+n; }