// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later

// IntTraits.hpp
// Int型のトレイト特殊化

#ifndef CALX_INT_TRAITS_HPP
#define CALX_INT_TRAITS_HPP

#include <math/core/mp/Int/IntBase.hpp>

namespace calx {

    // 前方宣言のみ行い、実装は traits.hpp に任せる
    // テンプレート特殊化が重複して定義されるのを防ぐ
    template<typename T> struct numeric_traits;
    template<typename T> struct numeric_state_traits;

    // Int型のnumeric_traits特殊化
    template<>
    struct numeric_traits<Int> {
        using value_type = Int;
        using category = integer_tag;

        static constexpr bool is_supported = true;
        static constexpr bool is_complex = false;
        static constexpr bool is_integer = true;
        static constexpr bool is_floating_point = false;

        static Int zero() { return Int(0); }
        static Int one() { return Int(1); }
        static Int epsilon() { return Int(1); } // 整数の最小単位は1

        // 無限大は特殊値を返す
        static Int infinity() { return Int::infinity(); }

        // NaNは特殊値を返す
        static Int quiet_NaN() { return Int::nan(); }

        static Int abs(const Int& value) {
            // 特殊状態の処理
            if (value.isNaN()) {
                return value;  // NaNの場合はそのまま
            }

            // 無限大の符号を調整
            if (value.isInfinite()) {
                if (value.getState() == NumericState::NegativeInfinity) {
                    return Int::infinity();  // 負の無限大を正の無限大に変換
                }
                return value;  // 正の無限大はそのまま
            }

            if (value.isZero()) {
                return Int(0);
            }

            // 通常値の処理
            if (value.getSign() < 0) {
                // 負の値を正に変換
                Int result = value;
                result.setSign(1);
                return result;
            }

            return value;
        }

        static Int conj(const Int& value) { return value; } // 整数は共役が自分自身
        static Int norm(const Int& value) {
            // 整数のノルムは絶対値
            return abs(value);
        }
        static bool pivotBetter(const Int& a, const Int& b) {
            return abs(a) > abs(b);
        }
    };

    // Int型のnumeric_state_traits特殊化
    template<>
    struct numeric_state_traits<Int> {
        static bool isNormal(const Int& value) { return value.isNormal(); }
        static bool isNaN(const Int& value) { return value.isNaN(); }
        static bool isInfinite(const Int& value) { return value.isInfinite(); }
        static bool isDivergent(const Int& value) { return value.isDivergent(); }
        static bool isOverflow(const Int& /*value*/) { return false; } // Intは内部でオーバーフローしない

        static NumericState getState(const Int& value) { return value.getState(); }
        static NumericError getError(const Int& value) { return value.getError(); }
        static int getSign(const Int& value) { return value.getSign(); }
        static DivergenceDetail getDivergenceDetail(const Int& value) { return value.getDivergenceDetail(); }
    };

} // namespace calx

#endif // CALX_INT_TRAITS_HPP