text: /**
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements. See the NOTICE file distributed with this
   * work for additional information regarding copyright ownership. The ASF
   * licenses this file to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance with the
   * License. You may obtain a copy of the License at
   * http://www.apache.org/licenses/LICENSE-2.0.
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations
   * under the License.
   */
  
  #ifndef _ST_HPC_PPL_CV_CUDA_INTEGRAL_H_
  #define _ST_HPC_PPL_CV_CUDA_INTEGRAL_H_
  
  #include "cuda_runtime.h"
  
  #include "ppl/common/retcode.h"
  
  namespace ppl {
  namespace cv {
  namespace cuda {
  
  /**
   * @brief Calculates the integral of an image.
   * @tparam Tsrc The data type of input image, currently only uint8_t(uchar) and
   *         float are supported.
   * @tparam Tdst The data type of output image, currently only int and float are
   *         supported.
   * @tparam channels The number of channels of input image, only 1 is supported.
   * @param stream           cuda stream object.
   * @param inHeight         input image's height.
   * @param inWidth          input image's width.
   * @param inWidthStride    input image's width stride, it is `width * channels`
   *                         for cudaMalloc() allocated data, `pitch / sizeof(T)`
   *                         for 2D cudaMallocPitch() allocated data.
   * @param inData           input image data.
   * @param outHeight        output image's height.
   * @param outWidth         output image's width.
   * @param outWidthStride   the width stride of output image, similar to
   *                         inWidthStride.
   * @param outData          output image data.
   * @return The execution status, succeeds or fails with an error code.
   * @note 1 For best performance, a 2D array allocated by cudaMallocPitch() is
   *         recommended.
   *       2 There are 2 implementation, in version 1 the input&output have the
   *         same size; in version 2 outHeight = inHeight + 1 && outWidth =
   *         inWidth + 1. Version 2 is compatible with integral() in OpenCV 4.1.
   *         outHeight&outWidth decides which implementation will be run.
   * @warning All parameters must be valid, or undefined behaviour may occur.
   * @remark The fllowing table show which data type and channels are supported.
   * <table>
   * <tr><th>Data type(Tsrc)<th>Data type(Tdst)<th>channels
   * <tr><td>uint8_t(uchar)<td>int<td>1
   * <tr><td>float<td>float<td>1
   * </table>
   * <caption align="left">Requirements</caption>
   * <tr><td>CUDA platforms supported <td>CUDA 7.0
   * <tr><td>Header files  <td> #include "ppl/cv/cuda/integral.h"
   * <tr><td>Project       <td> ppl.cv
   * </table>
   * @since ppl.cv-v1.0.0
   * ###Example
   * @code{.cpp}
   * #include "ppl/cv/cuda/integral.h"
   * using namespace ppl::cv::cuda;
   *
   * int main(int argc, char** argv) {
   *   int width  = 640;
   *   int height = 480;
   *   int channels = 1;
   *
   *   float* gpu_input;
   *   float* gpu_output;
   *   size_t input_pitch, output_pitch;
   *   cudaMallocPitch(&gpu_input, &input_pitch,
   *                   width * channels * sizeof(float), height);
   *   cudaMallocPitch(&gpu_output, &output_pitch,
   *                   width * channels * sizeof(float), height);
   *
   *   cudaStream_t stream;
   *   cudaStreamCreate(&stream);
   *   Integral<float, float, 1>(stream, height, width,
   *                             input_pitch / sizeof(float), gpu_input,
   *                             height, width, output_pitch / sizeof(float),
   *                             gpu_output);
   *   cudaStreamSynchronize(stream);
   *   cudaStreamDestroy(stream);
   *
   *   cudaFree(gpu_input);
   *   cudaFree(gpu_output);
   *
   *   return 0;
   * }
   * @endcode
   */
  template <typename Tsrc, typename Tdst, int channels>
  ppl::common::RetCode Integral(cudaStream_t stream,
                                int inHeight,
                                int inWidth,
                                int inWidthStride,
                                const Tsrc* inData,
                                int outHeight,
                                int outWidth,
                                int outWidthStride,
                                Tdst* outData);
  
  }  // namespace cuda
  }  // namespace cv
  }  // namespace ppl
  
  #endif  // _ST_HPC_PPL_CV_CUDA_INTEGRAL_H_
  