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

// Int.hpp
// 多倍長整数ライブラリのメインヘッダーファイル
//
// このファイルでは、多倍長整数ライブラリのすべての機能を
// 1つのヘッダーからインクルードできるように統合しています。
//
// 主な機能:
// - 多倍長整数クラス（Int）
// - 基本的な算術演算
// - 特殊状態（NaN、無限大など）の処理
// - ストリーム入出力
// - 数論的機能
// - パフォーマンス最適化

#ifndef CALX_INT_HPP
#define CALX_INT_HPP

// 状態管理システム
#include <math/core/numeric_state.hpp>
#include <math/core/mp/error.hpp>
// 基本的なInt関連ヘッダー
#include <math/core/mp/Int/IntBase.hpp>
#include <math/core/mp/Int/IntOps.hpp>
#include <math/core/mp/Int/IntIO.hpp>
#include <math/core/mp/Int/IntSpecialStates.hpp>
#include <math/core/mp/Int/IntDivision.hpp>

namespace calx {

// バージョン情報
struct IntVersion {
    static constexpr int major = 2;  // 状態管理システム導入により主要バージョンを上げる
    static constexpr int minor = 0;
    static constexpr int patch = 0;
    
    static constexpr const char* string() {
        return "2.0.0";
    }
    
    static constexpr const char* name() {
        return "MKL Algebra Int Library";
    }
    
    static constexpr const char* description() {
        return "High-performance multiple precision integer library with state management for C++20/23";
    }
};

/**
 * @brief Int クラスの機能概要
 * 
 * このライブラリは高性能な多倍長整数を提供します。主な特徴:
 * 
 * - 任意精度の整数演算
 * - C++20/23のコンセプトに対応
 * - 特殊状態管理（NaN、無限大、発散など）
 * - 小さな整数用の最適化
 * - 高性能なアルゴリズム（カラツバ、FFTなど）
 * - SIMD命令と並列化による最適化
 * 
 * 使用例:
 * 
 * ```cpp
 * using namespace calx;
 * 
 * // 基本演算
 * Int a(123456789);
 * Int b("987654321");
 * Int c = a + b;
 * 
 * // 入出力
 * std::cout << "a + b = " << c << std::endl;
 * 
 * // 16進数表示
 * std::cout << "16進数: " << c.toString(16) << std::endl;
 * 
 * // ビット操作
 * Int d = (a << 100) | b;
 * 
 * // 特殊状態の処理
 * Int x = Int::infinity();   // 正の無限大
 * Int y = Int::negInfinity(); // 負の無限大
 * Int z = x + y;             // NaN（不定）
 * 
 * if (z.isNaN()) {
 *     std::cout << "結果は不定です" << std::endl;
 * }
 * ```
 * 
 * 詳細な使用方法はドキュメントを参照してください。
 */

// ユーティリティ関数

/**
 * @brief 最大公約数(GCD)を計算
 * @param a 第1引数
 * @param b 第2引数
 * @return 最大公約数
 */
Int gcd(const Int& a, const Int& b);

/**
 * @brief 最小公倍数(LCM)を計算
 * @param a 第1引数
 * @param b 第2引数
 * @return 最小公倍数
 */
Int lcm(const Int& a, const Int& b);

/**
 * @brief 累乗計算
 * @param base ベース
 * @param exponent 指数
 * @return base^exponent
 */
Int pow(const Int& base, const Int& exponent);

/**
 * @brief モジュラー指数計算
 * @param base ベース
 * @param exponent 指数
 * @param modulus 法
 * @return (base^exponent) mod modulus
 */
Int powMod(const Int& base, const Int& exponent, const Int& modulus);

/**
 * @brief 符号ビットを含めて、2の補数表現のビット長を返す
 * @param value 対象の値
 * @return ビット長
 */
size_t bitCount(const Int& value);

/**
 * @brief 素数判定（確率的アルゴリズム）
 * @param value 判定する値
 * @param iterations 反復回数（精度に影響）
 * @return 素数ならtrue
 */
bool isProbablePrime(const Int& value, int iterations);

// 特殊状態の検出と処理

/**
 * @brief 特殊状態を検出
 * @param value 対象の値
 * @return 正常値ならtrue、特殊状態（NaN、無限大など）ならfalse
 */
bool isNormal(const Int& value);

/**
 * @brief NaN（Not a Number）状態を検出
 * @param value 対象の値
 * @return NaNならtrue
 */
bool isNaN(const Int& value);

/**
 * @brief 無限大状態を検出
 * @param value 対象の値
 * @return 正または負の無限大ならtrue
 */
bool isInfinite(const Int& value);

/**
 * @brief 正の無限大状態を検出
 * @param value 対象の値
 * @return 正の無限大ならtrue
 */
bool isPosInfinite(const Int& value);

/**
 * @brief 負の無限大状態を検出
 * @param value 対象の値
 * @return 負の無限大ならtrue
 */
bool isNegInfinite(const Int& value);

/**
 * @brief オーバーフロー状態を検出
 * @param value 対象の値
 * @return オーバーフローが発生していればtrue
 */
bool isOverflow(const Int& value);

/**
 * @brief 発散状態を検出
 * @param value 対象の値
 * @return 発散（収束しないまたは収束が非常に遅い）状態ならtrue
 */
bool isDivergent(const Int& value);

/**
 * @brief 特殊状態の詳細を文字列で取得
 * @param value 対象の値
 * @return 状態を表す文字列
 */
std::string getStateDescription(const Int& value);

// 型変換ヘルパー

/**
 * @brief Int型から符号付き64ビット整数への変換
 * @param value 変換する値
 * @return 整数値（範囲外の場合は例外）
 */
int64_t toInt64(const Int& value);

/**
 * @brief Int型から符号なし64ビット整数への変換
 * @param value 変換する値
 * @return 符号なし整数値（範囲外の場合は例外）
 */
uint64_t toUInt64(const Int& value);

/**
 * @brief Int型から倍精度浮動小数点数への変換
 * @param value 変換する値
 * @return 浮動小数点数（精度損失の可能性あり）
 */
double toDouble(const Int& value);

/**
 * @brief 特殊状態の詳細情報を取得
 * @param value 対象の値
 * @return NumericState型の状態情報
 */
NumericState getNumericState(const Int& value);

/**
 * @brief 特殊状態の詳細情報を取得（発散詳細）
 * @param value 対象の値
 * @return DivergenceDetail型の発散詳細情報（該当する場合）
 */
DivergenceDetail getDivergenceDetail(const Int& value);

/**
 * @brief 状態エラーを処理するオプションを設定
 * @param options 状態エラー処理オプション
 */
void setStateErrorOptions(const StateErrorOptions& options);

/**
 * @brief 現在の状態エラー処理オプションを取得
 * @return 現在の状態エラー処理オプション
 */
StateErrorOptions getStateErrorOptions();

// 収束性評価関数

/**
     * @brief 収束判定のための閾値
     * 反復計算などで結果が収束したかを判定する際の差分閾値
     */
namespace convergence_detail {
    // 内部実装用に隠蔽
    inline Int convergence_threshold = Int(1);
    inline size_t max_iterations = 1000;
}

/**
 * @brief 収束閾値を設定
 * @param threshold 収束判定に使用する閾値
 */
inline void setConvergenceThreshold(const Int& threshold) {
    convergence_detail::convergence_threshold = threshold;
}

/**
 * @brief 最大反復回数を設定
 * @param maxIterations 最大反復回数
 */
inline void setMaxIterations(size_t maxIterations) {
    convergence_detail::max_iterations = maxIterations;
}

/**
 * @brief 現在の収束閾値を取得
 * @return 設定されている収束閾値
 */
inline Int getConvergenceThreshold() {
    return convergence_detail::convergence_threshold;
}

/**
 * @brief 現在の最大反復回数を取得
 * @return 設定されている最大反復回数
 */
inline size_t getMaxIterations() {
    return convergence_detail::max_iterations;
}

/**
 * @brief 値が収束閾値より小さいかを判定
 * @param value 判定する値
 * @return 収束閾値より小さければtrue
 */
inline bool isConverged(const Int& value) {
    return abs(value) < convergence_detail::convergence_threshold;
}

/**
 * @brief 収束状態を表すenum
 */
enum class ConvergenceState {
    Converged,           // 収束した
    Diverging,           // 発散している
    MaxIterationsReached, // 最大反復回数に達した
    Oscillating,         // 振動している
    Unknown              // 状態不明
};

} // namespace calx

// --- std::formatter 特殊化 ---
#include <format>

template<>
struct std::formatter<calx::Int> {
    int base_ = 10;
    bool uppercase_ = false;
    bool showBase_ = false;
    bool showSign_ = false;

    constexpr auto parse(std::format_parse_context& ctx) {
        auto it = ctx.begin();
        auto end = ctx.end();
        while (it != end && *it != '}') {
            switch (*it) {
                case 'd': base_ = 10; break;
                case 'x': base_ = 16; break;
                case 'X': base_ = 16; uppercase_ = true; break;
                case 'b': base_ = 2; break;
                case 'o': base_ = 8; break;
                case '#': showBase_ = true; break;
                case '+': showSign_ = true; break;
                default: throw std::format_error("invalid format spec for Int");
            }
            ++it;
        }
        return it;
    }

    auto format(const calx::Int& val, std::format_context& ctx) const {
        calx::FormatOptions opts;
        opts.base = base_;
        opts.uppercase = uppercase_;
        opts.showBase = showBase_;
        opts.showSign = showSign_;
        return std::format_to(ctx.out(), "{}", calx::IntIOUtils::format(val, opts));
    }
};

#endif // CALX_INT_HPP