/*
 * Copyright (c) 2016-2019 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * 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.
 */
#ifndef ARM_COMPUTE_NEHOGDESCRIPTORKERNEL_H
#define ARM_COMPUTE_NEHOGDESCRIPTORKERNEL_H

#include "arm_compute/core/IHOG.h"
#include "arm_compute/core/NEON/INEKernel.h"
#include "arm_compute/core/Size2D.h"

namespace arm_compute
{
class ITensor;

/** NEON kernel to perform HOG Orientation Binning */
class NEHOGOrientationBinningKernel : public INEKernel
{
public:
    const char *name() const override
    {
        return "NEHOGOrientationBinningKernel";
    }
    /** Default constructor */
    NEHOGOrientationBinningKernel();
    /** Prevent instances of this class from being copied (As this class contains pointers) */
    NEHOGOrientationBinningKernel(const NEHOGOrientationBinningKernel &) = delete;
    /** Prevent instances of this class from being copied (As this class contains pointers) */
    NEHOGOrientationBinningKernel &operator=(const NEHOGOrientationBinningKernel &) = delete;
    /** Allow instances of this class to be moved */
    NEHOGOrientationBinningKernel(NEHOGOrientationBinningKernel &&) = default;
    /** Allow instances of this class to be moved */
    NEHOGOrientationBinningKernel &operator=(NEHOGOrientationBinningKernel &&) = default;
    /** Default destructor */
    ~NEHOGOrientationBinningKernel() = default;

    /**  Initialise the kernel's inputs, output and HOG's metadata
     *
     * @param[in]  input_magnitude Input tensor which stores the magnitude of the gradient for each pixel. Data type supported: S16.
     * @param[in]  input_phase     Input tensor which stores the phase of the gradient for each pixel. Data type supported: U8
     * @param[out] output          Output tensor which stores the local HOG for each cell. Data type supported: F32. Number of channels supported: equal to the number of histogram bins per cell
     * @param[in]  hog_info        HOG's metadata
     */
    void configure(const ITensor *input_magnitude, const ITensor *input_phase, ITensor *output, const HOGInfo *hog_info);

    // Inherited methods overridden:
    void run(const Window &window, const ThreadInfo &info) override;

private:
    /** Common signature for all the specialised block normalization functions
     *
     * @param[in]  mag_row_ptr   Pointer to the first row of the cell in the magnitude tensor
     * @param[in]  phase_row_ptr Pointer to the first row of the cell in the phase tensor
     * @param[out] output_ptr    Pointer to the output cell of hog space tensor
     * @param[in]  mag_stride    Stride of the magnitude tensor
     * @param[in]  phase_stride  Stride of the phase tensor
     * @param[in]  cell_width    Width of the cell
     * @param[in]  cell_height   Height of the cell
     * @param[in]  num_bins      Number of bins for each cell
     * @param[in]  phase_scale   Scale factor to apply to the phase in order to calculate the histogram index
     */
    using OrientBinFunc = void(const int16_t *__restrict mag_row_ptr, const uint8_t *__restrict phase_row_ptr, float *__restrict output_ptr, size_t mag_stride, size_t phase_stride, size_t cell_width,
                               size_t cell_height, size_t num_bins, float phase_scale);
    /** Orientation binning function to use for the particular cell width passed to configure() */
    OrientBinFunc *_func;
    const ITensor *_input_magnitude;
    const ITensor *_input_phase;
    ITensor       *_output;
    size_t         _cell_width;
    size_t         _cell_height;
    size_t         _num_bins;
    float          _phase_scale;
};

/** NEON kernel to perform HOG block normalization */
class NEHOGBlockNormalizationKernel : public INEKernel
{
public:
    const char *name() const override
    {
        return "NEHOGBlockNormalizationKernel";
    }
    /** Default constructor */
    NEHOGBlockNormalizationKernel();
    /** Prevent instances of this class from being copied (As this class contains pointers) */
    NEHOGBlockNormalizationKernel(const NEHOGBlockNormalizationKernel &) = delete;
    /** Prevent instances of this class from being copied (As this class contains pointers) */
    NEHOGBlockNormalizationKernel &operator=(const NEHOGBlockNormalizationKernel &) = delete;
    /** Allow instances of this class to be moved */
    NEHOGBlockNormalizationKernel(NEHOGBlockNormalizationKernel &&) = default;
    /** Allow instances of this class to be moved */
    NEHOGBlockNormalizationKernel &operator=(NEHOGBlockNormalizationKernel &&) = default;
    /** Default destructor */
    ~NEHOGBlockNormalizationKernel() = default;

    /** Initialise the kernel's input, output and HOG's metadata
     *
     * @param[in]  input    Input tensor which stores the local HOG for each cell. Data type supported: F32. Number of channels supported: equal to the number of histogram bins per cell
     * @param[out] output   Output tensor which stores the normalised blocks. Data type supported: F32. Number of channels supported: equal to the number of histogram bins per block
     * @param[in]  hog_info HOG's metadata
     */
    void configure(const ITensor *input, ITensor *output, const HOGInfo *hog_info);

    // Inherited methods overridden:
    void run(const Window &window, const ThreadInfo &info) override;

private:
    /** Common signature for all the specialised block normalization functions
     *
     * @param[in]  input_row_ptr              Pointer to the first row of the block in the input hog space tensor
     * @param[out] output_ptr                 Pointer to the output block of the hog normalized space
     * @param[in]  input_stride               Stride of the input hog space tensor
     * @param[in]  num_cells_per_block_height Number of cells per block along the Y direction
     * @param[in]  num_bins_block_x           Number of bins per block along the X direction
     * @param[in]  num_bins_block             Number of total bins per block
     * @param[in]  l2_hyst_threshold          Threshold to use for l2 hysteresis normalization
     */
    using BlockNormFunc = void(const float *input_row_ptr, float *output_ptr, size_t input_stride, size_t num_cells_per_block_height, size_t num_bins_block_x, size_t num_bins_block,
                               float l2_hyst_threshold);
    /** Block normalization function to use for the particular normalization type passed to configure() */
    BlockNormFunc *_func;
    const ITensor *_input;
    ITensor       *_output;
    Size2D         _num_cells_per_block;
    Size2D         _num_cells_per_block_stride;
    size_t         _num_bins;
    float          _l2_hyst_threshold;
};
} // namespace arm_compute
#endif /* ARM_COMPUTE_NEHOGDESCRIPTORKERNEL_H */
