// Copyright 2026 Tencent
// SPDX-License-Identifier: BSD-3-Clause

#include "unaryop_x86.h"

#include "cpu.h"
#include "layer.h"
#include "layer_type.h"
#include "mat.h"
#include "x86_activation.h"
#include "x86_usability.h"

namespace ncnn {

namespace UnaryOp_x86_functor {

#include "unaryop_functor.h"

} // namespace UnaryOp_x86_functor

#include "unaryop_bf16s.h"

int unaryop_bf16s_sse_avx512bf16(Mat& bottom_top_blob, int op_type, const Option& opt)
{
    using namespace UnaryOp_x86_functor;
    if (op_type == UnaryOp::Operation_ABS)
        return unary_op_inplace_bf16s<unary_op_abs>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_NEG)
        return unary_op_inplace_bf16s<unary_op_neg>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_FLOOR)
        return unary_op_inplace_bf16s<unary_op_floor>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_CEIL)
        return unary_op_inplace_bf16s<unary_op_ceil>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_SQUARE)
        return unary_op_inplace_bf16s<unary_op_square>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_SQRT)
        return unary_op_inplace_bf16s<unary_op_sqrt>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_RSQRT)
        return unary_op_inplace_bf16s<unary_op_rsqrt>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_EXP)
        return unary_op_inplace_bf16s<unary_op_exp>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_LOG)
        return unary_op_inplace_bf16s<unary_op_log>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_SIN)
        return unary_op_inplace_bf16s<unary_op_sin>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_COS)
        return unary_op_inplace_bf16s<unary_op_cos>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_TAN)
        return unary_op_inplace_bf16s<unary_op_tan>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ASIN)
        return unary_op_inplace_bf16s<unary_op_asin>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ACOS)
        return unary_op_inplace_bf16s<unary_op_acos>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ATAN)
        return unary_op_inplace_bf16s<unary_op_atan>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_RECIPROCAL)
        return unary_op_inplace_bf16s<unary_op_reciprocal>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_TANH)
        return unary_op_inplace_bf16s<unary_op_tanh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_LOG10)
        return unary_op_inplace_bf16s<unary_op_log10>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ROUND)
    {
        // round to nearest even
#ifdef FE_TONEAREST
        int old_rm = fegetround();
        fesetround(FE_TONEAREST);
#endif
        int ret = unary_op_inplace_bf16s<unary_op_round>(bottom_top_blob, opt);
#ifdef FE_TONEAREST
        fesetround(old_rm);
#endif
        return ret;
    }

    if (op_type == UnaryOp::Operation_TRUNC)
        return unary_op_inplace_bf16s<unary_op_trunc>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_SIGN)
        return unary_op_inplace_bf16s<unary_op_sign>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_EXPM1)
        return unary_op_inplace_bf16s<unary_op_expm1>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_SINH)
        return unary_op_inplace_bf16s<unary_op_sinh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ASINH)
        return unary_op_inplace_bf16s<unary_op_asinh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_COSH)
        return unary_op_inplace_bf16s<unary_op_cosh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ACOSH)
        return unary_op_inplace_bf16s<unary_op_acosh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_ATANH)
        return unary_op_inplace_bf16s<unary_op_atanh>(bottom_top_blob, opt);

    if (op_type == UnaryOp::Operation_LOG1P)
        return unary_op_inplace_bf16s<unary_op_log1p>(bottom_top_blob, opt);

    return 0;
}

} // namespace ncnn
