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

// RationalTraits.hpp
// Rational型のトレイト特殊化

#ifndef CALX_RATIONAL_TRAITS_HPP
#define CALX_RATIONAL_TRAITS_HPP

#include <math/core/mp/Rational/RationalBase.hpp>

namespace calx {

    // 前方宣言
    struct real_tag;
    template<typename T> struct numeric_traits;
    template<typename T> struct numeric_state_traits;

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

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

        static Rational zero() { return Rational(); }
        static Rational one() { return Rational(1); }
        static Rational epsilon() { return Rational(); } // 有理数は稠密: 最小単位なし → 0

        static Rational abs(const Rational& value) {
            return calx::abs(value);
        }

        /// ピボット選択: 高さ (max(|分子|, |分母|)) が小さい方が良いピボット
        /// 係数膨張を抑制する
        static bool pivotBetter(const Rational& a, const Rational& b) {
            return height(a) < height(b);
        }

        static Rational conj(const Rational& value) {
            return value; // 実数は共役が自分自身
        }

        static Rational norm(const Rational& value) {
            return abs(value);
        }

        static bool isNaN(const Rational& value) {
            return value.isNaN();
        }

        static bool isInfinite(const Rational& /*value*/) {
            return false; // Rational は無限大を持たない
        }

        static bool isFinite(const Rational& value) {
            return !value.isNaN();
        }

        static int getSign(const Rational& value) {
            if (value.isNaN()) return 0;
            if (value.isZero()) return 0;
            return value.isNegative() ? -1 : 1;
        }
    };

    // Rational型のnumeric_state_traits特殊化
    template<>
    struct numeric_state_traits<Rational> {
        static bool isNormal(const Rational& value) { return !value.isNaN() && !value.isZero(); }
        static bool isNaN(const Rational& value) { return value.isNaN(); }
        static bool isInfinite(const Rational& /*value*/) { return false; }
        static bool isDivergent(const Rational& /*value*/) { return false; }
        static bool isOverflow(const Rational& /*value*/) { return false; }

        static NumericState getState(const Rational& value) {
            if (value.isNaN()) return NumericState::NaN;
            return NumericState::Normal;
        }

        static NumericError getError(const Rational& value) {
            if (value.isNaN()) return NumericError::ExplicitNaN;
            return NumericError::None;
        }

        static int getSign(const Rational& value) {
            if (value.isNaN()) return 0;
            if (value.isZero()) return 0;
            return value.isNegative() ? -1 : 1;
        }
    };

} // namespace calx

#endif // CALX_RATIONAL_TRAITS_HPP
