/*
 * Copyright (c) 2020-2021 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.
 */
#include "arm_compute/runtime/NEON/functions/NELogical.h"

#include "arm_compute/runtime/NEON/NEScheduler.h"
#include "arm_compute/runtime/Tensor.h"

#include "src/common/utils/Log.h"
#include "src/core/NEON/kernels/NELogicalKernel.h"

namespace arm_compute
{
struct LogicalArgs
{
    std::unique_ptr<kernels::NELogicalKernel> kernel{nullptr};
    ITensorPack                               pack{};
};

struct NELogicalAnd::Impl : public LogicalArgs
{
};
NELogicalAnd::NELogicalAnd() : _impl(std::make_unique<Impl>())
{
}
NELogicalAnd::~NELogicalAnd() = default;

void NELogicalAnd::configure(const ITensor *input1, const ITensor *input2, ITensor *output)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output);
    ARM_COMPUTE_LOG_PARAMS(input1, input2, output);

    _impl->kernel = std::make_unique<kernels::NELogicalKernel>();
    _impl->kernel->configure(input1->info(), input2->info(), output->info(), LogicalOperation::And);

    _impl->pack = ITensorPack();
    _impl->pack.add_tensor(TensorType::ACL_SRC_0, input1);
    _impl->pack.add_tensor(TensorType::ACL_SRC_1, input2);
    _impl->pack.add_tensor(TensorType::ACL_DST, output);
}

Status NELogicalAnd::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
{
    return kernels::NELogicalKernel::validate(input1, input2, output, LogicalOperation::And);
}

void NELogicalAnd::run()
{
    NEScheduler::get().schedule_op(_impl->kernel.get(), Window::DimY, _impl->kernel->window(), _impl->pack);
}

struct NELogicalOr::Impl : public LogicalArgs
{
};
NELogicalOr::NELogicalOr() : _impl(std::make_unique<Impl>())
{
}
NELogicalOr::~NELogicalOr() = default;

void NELogicalOr::configure(const ITensor *input1, const ITensor *input2, ITensor *output)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output);
    ARM_COMPUTE_LOG_PARAMS(input1, input2, output);

    _impl->kernel = std::make_unique<kernels::NELogicalKernel>();
    _impl->kernel->configure(input1->info(), input2->info(), output->info(), LogicalOperation::Or);

    _impl->pack = ITensorPack();
    _impl->pack.add_tensor(TensorType::ACL_SRC_0, input1);
    _impl->pack.add_tensor(TensorType::ACL_SRC_1, input2);
    _impl->pack.add_tensor(TensorType::ACL_DST, output);
}

Status NELogicalOr::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output)
{
    return kernels::NELogicalKernel::validate(input1, input2, output, LogicalOperation::Or);
}

void NELogicalOr::run()
{
    NEScheduler::get().schedule_op(_impl->kernel.get(), Window::DimY, _impl->kernel->window(), _impl->pack);
}

struct NELogicalNot::Impl : public LogicalArgs
{
};
NELogicalNot::NELogicalNot() : _impl(std::make_unique<Impl>())
{
}
NELogicalNot::~NELogicalNot() = default;

void NELogicalNot::configure(const ITensor *input, ITensor *output)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
    ARM_COMPUTE_LOG_PARAMS(input, output);

    _impl->kernel = std::make_unique<kernels::NELogicalKernel>();
    _impl->kernel->configure(input->info(), nullptr, output->info(), LogicalOperation::Not);

    _impl->pack = ITensorPack();
    _impl->pack.add_tensor(TensorType::ACL_SRC_0, input);
    _impl->pack.add_tensor(TensorType::ACL_DST, output);
}

Status NELogicalNot::validate(const ITensorInfo *input, const ITensorInfo *output)
{
    return kernels::NELogicalKernel::validate(input, nullptr, output, LogicalOperation::Not);
}

void NELogicalNot::run()
{
    NEScheduler::get().schedule_op(_impl->kernel.get(), Window::DimY, _impl->kernel->window(), _impl->pack);
}
} // namespace arm_compute
