/*
 * Copyright (c) 2017 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_GC
#error "This example needs to be built with -DARM_COMPUTE_GC"
#endif /* ARM_COMPUTE_GC */

#include "arm_compute/runtime/GLES_COMPUTE/GCFunctions.h"
#include "arm_compute/runtime/GLES_COMPUTE/GCScheduler.h"
#include "half/half.hpp"
#include "utils/Utils.h"

using namespace arm_compute;
using namespace utils;

namespace
{
TensorShape get_output_shape(TensorShape in_shape, TensorShape kernel_shape, const PadStrideInfo &info)
{
    TensorShape out_shape(in_shape);
    const std::pair<unsigned int, unsigned int> scaled_dims = scaled_dimensions(in_shape.x(),
                                                                                in_shape.y(),
                                                                                kernel_shape.x(),
                                                                                kernel_shape.y(),
                                                                                info);
    out_shape.set(0, scaled_dims.first);
    out_shape.set(1, scaled_dims.second);
    out_shape.set(2, kernel_shape[3]);
    return out_shape;
}
} // namespace

void main_gc_dc(int argc, const char **argv)
{
    ARM_COMPUTE_UNUSED(argc);
    ARM_COMPUTE_UNUSED(argv);

    // init instance
    GCScheduler::get().default_init();

    const TensorShape  src_shape   = TensorShape{ 11U /* W */, 13U /* H */, 4U /* C */, 3U /* N */ };
    const unsigned int kernel_size = 3;
    const int          stride_x    = 1;
    const int          stride_y    = 1;
    const int          pad_x       = 0;
    const int          pad_y       = 0;
    const unsigned int num_kernels = 256;
    const DataType     data_type   = DataType::F16;

    // generate shape
    const TensorShape   weights_shape(kernel_size, kernel_size, src_shape.z(), num_kernels);
    const TensorShape   bias_shape(num_kernels);
    const PadStrideInfo pad_info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);

    // output shape should be 9*11*256*3 (W*H*C*N)
    const TensorShape dst_shape = get_output_shape(src_shape, weights_shape, pad_info);

    // create tensors
    GCTensor src, weights, bias, dst;
    src.allocator()->init(TensorInfo(src_shape, 1, data_type));
    weights.allocator()->init(TensorInfo(weights_shape, 1, data_type));
    bias.allocator()->init(TensorInfo(bias_shape, 1, data_type));
    dst.allocator()->init(TensorInfo(dst_shape, 1, data_type));

    // configure layer
    GCDirectConvolutionLayer conv;
    conv.configure(&src, &weights, &bias, &dst, pad_info);

    // allocate tensors
    src.allocator()->allocate();
    weights.allocator()->allocate();
    bias.allocator()->allocate();
    dst.allocator()->allocate();

    // To demonstrate how to fill tensor with some values...
    src.map();
    Window window;
    window.use_tensor_dimensions(src_shape);
    Iterator it(&src, window);
    execute_window_loop(window, [&](const Coordinates & id)
    {
        *reinterpret_cast<half_float::half *>(it.ptr()) = half_float::half(1.f);
    });
    src.unmap();

    // run the layer
    conv.run();

    // check result
    dst.map();
    // do something
    dst.unmap();
}

/** Main program for directconvolution test
 *
 * @param[in] argc Number of arguments
 * @param[in] argv Arguments
 */
int main(int argc, const char **argv)
{
    return utils::run_example(argc, argv, main_gc_dc);
}
