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

// common.hpp
// 共通定義、例外、設定
//
// このファイルでは、MKL代数ライブラリ全体で使用される共通の定義、
// 例外クラス、グローバル設定、およびユーティリティ関数を提供します。
//
// 主な機能:
// - 名前空間の定義
// - バージョン情報
// - MKL検出と設定
// - 例外クラス階層
// - 共通ユーティリティ関数
// - コンパイル時設定
// - スレッド管理
// - 状態管理関連の例外と設定

#ifndef CALX_COMMON_HPP
#define CALX_COMMON_HPP

// コンパイラ互換マクロ
#ifdef _MSC_VER
#define CALX_FORCEINLINE __forceinline
#else
#define CALX_FORCEINLINE __attribute__((always_inline)) inline
#endif

// ==============================================================================
// DLL エクスポート/インポート マクロ
// ==============================================================================
// CALX_SHARED_LIB: DLL ビルド時に定義 (CMake が設定)
// CALX_BUILDING_CORE: calx_core ライブラリ自身をビルド中に定義
//
// 使い方:
//   class CALX_API Int { ... };          → DLL エクスポート/インポート対象
//   CALX_API int someFunction();         → 関数のエクスポート
//   ヘッダオンリーの template は不要     → テンプレートは CALX_API 不要
//
#ifdef CALX_SHARED_LIB
    #ifdef _MSC_VER
        #ifdef CALX_BUILDING_CORE
            #define CALX_API __declspec(dllexport)
        #else
            #define CALX_API __declspec(dllimport)
        #endif
    #else
        #define CALX_API __attribute__((visibility("default")))
    #endif
#else
    #define CALX_API
#endif

#include <math/core/basic_types.hpp>
#include <math/core/numeric_state.hpp>
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstddef>
#include <exception>
#include <limits>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
#include <sstream>

// ライブラリの名前空間
namespace calx {

    // バージョン情報構造体
    struct Version {
        static constexpr int major = VERSION_MAJOR;
        static constexpr int minor = VERSION_MINOR;
        static constexpr int patch = VERSION_PATCH;

        // バージョン文字列の取得
        static constexpr std::string_view string() {
            return "2.0.0"; // 実際には動的に生成すべきだが、constexprの制約により固定値
        }
    };

    // プラットフォーム検出
#if defined(_WIN32) || defined(_WIN64)
#define CALX_PLATFORM_WINDOWS
#elif defined(__APPLE__)
#define CALX_PLATFORM_MACOS
#elif defined(__linux__)
#define CALX_PLATFORM_LINUX
#else
#define CALX_PLATFORM_UNKNOWN
#endif

// コンパイラ検出
#if defined(_MSC_VER)
#define CALX_COMPILER_MSVC
#elif defined(__clang__)
#define CALX_COMPILER_CLANG
#elif defined(__GNUC__)
#define CALX_COMPILER_GCC
#else
#define CALX_COMPILER_UNKNOWN
#endif

// C++バージョン検出
#if defined(_MSC_VER)
    // Visual Studio の場合は /std:c++XX オプションを検出
#if defined(_MSVC_LANG)
#if _MSVC_LANG >= 202302L
#define CALX_CPP23
#define CALX_CPP20
#elif _MSVC_LANG >= 202002L
#define CALX_CPP20
#else
// C++20未満でもコンパイルできるようにエラーは無効化
// #error "C++20 or later is required"
#endif
#else
    // /std:c++XX オプションが指定されていない場合
// #error "Please specify /std:c++latest or /std:c++20 or later"
#endif
#else
    // 他のコンパイラ
#if __cplusplus >= 202302L
#define CALX_CPP23
#define CALX_CPP20
#elif __cplusplus >= 202002L
#define CALX_CPP20
#else
// C++20未満でもコンパイルできるようにエラーは無効化
// #error "C++20 or later is required"
#endif
#endif

// MKL検出
#if defined(CALX_USE_MKL)
#if defined(CALX_PLATFORM_WINDOWS)
#include <mkl.h>
#else
#include <mkl.h>
#endif
#define CALX_HAS_MKL 1
#else
#define CALX_HAS_MKL 0
#endif

// OpenBLAS検出（MKLのフォールバック）
#if !defined(CALX_HAS_MKL) && defined(CALX_USE_OPENBLAS)
#include <cblas.h>
#define CALX_HAS_OPENBLAS 1
#else
#define CALX_HAS_OPENBLAS 0
#endif

    // 利用可能なSIMD命令セットの検出
    constexpr SimdInstructionSet detect_simd_level() {
#if defined(__AVX512F__)
        return SimdInstructionSet::AVX512;
#elif defined(__AVX2__)
        return SimdInstructionSet::AVX2;
#elif defined(__AVX__)
        return SimdInstructionSet::AVX;
#elif defined(__SSE4_2__)
        return SimdInstructionSet::SSE4_2;
#elif defined(__SSE4_1__)
        return SimdInstructionSet::SSE4_1;
#elif defined(__SSSE3__)
        return SimdInstructionSet::SSSE3;
#elif defined(__SSE3__)
        return SimdInstructionSet::SSE3;
#elif defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
        return SimdInstructionSet::SSE2;
#elif defined(__ARM_NEON) || defined(__ARM_NEON__)
        return SimdInstructionSet::NEON;
#else
        return SimdInstructionSet::None;
#endif
    }

    // 利用可能なSIMD命令セット
    constexpr SimdInstructionSet available_simd_level = detect_simd_level();

    // 数学定数
    namespace constants {
        template <typename T>
        inline constexpr T pi = static_cast<T>(3.14159265358979323846);

        template <typename T>
        inline constexpr T e = static_cast<T>(2.71828182845904523536);

        template <typename T>
        inline constexpr T sqrt2 = static_cast<T>(1.41421356237309504880);

        template <typename T>
        inline constexpr T log2e = static_cast<T>(1.44269504088896340736);

        template <typename T>
        inline constexpr T log10e = static_cast<T>(0.43429448190325182765);
    }

    // 例外クラス階層

    // MKL代数ライブラリの基本例外クラス
    class MklAlgebraException : public std::exception {
    public:
        explicit MklAlgebraException(const std::string& message) : message_(message) {}
        explicit MklAlgebraException(std::string&& message) : message_(std::move(message)) {}

        const char* what() const noexcept override {
            return message_.c_str();
        }

    private:
        std::string message_;
    };

    // 数学的エラー（無効な操作、ドメインエラーなど）
    class MathError : public MklAlgebraException {
    public:
        using MklAlgebraException::MklAlgebraException;
    };

    // 次元エラー（行列やベクトルの次元の不一致）
    class DimensionError : public MklAlgebraException {
    public:
        using MklAlgebraException::MklAlgebraException;
    };

    // インデックスエラー（範囲外のインデックスアクセス）
    class IndexError : public MklAlgebraException {
    public:
        using MklAlgebraException::MklAlgebraException;
    };

    // 線形代数エラー（特異行列など）
    class LinearAlgebraError : public MklAlgebraException {
    public:
        using MklAlgebraException::MklAlgebraException;
    };

    // 収束エラー（数値アルゴリズムが収束しない）
    class ConvergenceError : public MklAlgebraException {
    public:
        using MklAlgebraException::MklAlgebraException;
    };

    // MKLエラー（MKL関数が失敗）
    class MklError : public MklAlgebraException {
    public:
        explicit MklError(const std::string& message, int error_code)
            : MklAlgebraException(message + " (error code: " + std::to_string(error_code) + ")"),
            error_code_(error_code) {
        }

        int error_code() const noexcept {
            return error_code_;
        }

    private:
        int error_code_;
    };

    // 数値状態関連のエラー
    class NumericStateError : public MathError {
    public:
        explicit NumericStateError(const std::string& message)
            : MathError(message), state_(NumericState::Normal), error_(NumericError::None) {
        }

        explicit NumericStateError(const std::string& message, NumericState state, NumericError error = NumericError::None)
            : MathError(message), state_(state), error_(error) {
        }

        NumericState getState() const noexcept {
            return state_;
        }

        NumericError getError() const noexcept {
            return error_;
        }

    private:
        NumericState state_;
        NumericError error_;
    };

    // NaNエラー
    class NaNError : public NumericStateError {
    public:
        explicit NaNError(const std::string& message = "Operation resulted in NaN")
            : NumericStateError(message, NumericState::NaN, NumericError::ExplicitNaN) {
        }
    };

    // 無限大エラー
    class InfinityError : public NumericStateError {
    public:
        explicit InfinityError(const std::string& message = "Operation resulted in infinity",
            bool is_positive = true)
            : NumericStateError(message,
                is_positive ? NumericState::PositiveInfinity
                : NumericState::NegativeInfinity,
                NumericError::None),
            is_positive_(is_positive) {
        }

        bool isPositive() const noexcept {
            return is_positive_;
        }

    private:
        bool is_positive_;
    };

    // オーバーフローエラー
    class OverflowError : public NumericStateError {
    public:
        explicit OverflowError(const std::string& message = "Numeric overflow occurred")
            : NumericStateError(message, NumericState::Overflow, NumericError::OutOfRangeInput) {
        }
    };

    // アンダーフローエラー
    class UnderflowError : public NumericStateError {
    public:
        explicit UnderflowError(const std::string& message = "Numeric underflow occurred")
            : NumericStateError(message, NumericState::Underflow, NumericError::OutOfRangeInput) {
        }
    };

    // ゼロ除算エラー
    class DivideByZeroError : public NumericStateError {
    public:
        explicit DivideByZeroError(const std::string& message = "Division by zero")
            : NumericStateError(message, NumericState::NaN, NumericError::DivideByZero) {
        }
    };

    // 発散エラー
    class DivergenceStateError : public NumericStateError {
    public:
        explicit DivergenceStateError(const std::string& message = "Algorithm diverged",
            DivergenceDetail detail = DivergenceDetail::Diverging)
            : NumericStateError(message, NumericState::Divergent, NumericError::DivergenceError),
            detail_(detail) {
        }

        DivergenceDetail getDetail() const noexcept {
            return detail_;
        }

    private:
        DivergenceDetail detail_;
    };

    // 状態エラー処理設定
    struct StateErrorOptions {
        // 各エラータイプに対する処理モード
        StateErrorMode nan_error_mode = StateErrorMode::ReturnSpecial;            // NaNに関するエラー
        StateErrorMode infinity_error_mode = StateErrorMode::ReturnSpecial;       // 無限大に関するエラー
        StateErrorMode overflow_error_mode = StateErrorMode::ReturnSpecial;       // オーバーフローに関するエラー
        StateErrorMode underflow_error_mode = StateErrorMode::ReturnSpecial;      // アンダーフローに関するエラー
        StateErrorMode divide_by_zero_error_mode = StateErrorMode::ReturnSpecial; // ゼロ除算に関するエラー
        StateErrorMode divergence_error_mode = StateErrorMode::Exception;         // 発散に関するエラー

        // デフォルト設定
        static StateErrorOptions defaults() {
            return {};
        }

        // 例外のみのモード
        static StateErrorOptions exceptions_only() {
            StateErrorOptions options;
            options.nan_error_mode = StateErrorMode::Exception;
            options.infinity_error_mode = StateErrorMode::Exception;
            options.overflow_error_mode = StateErrorMode::Exception;
            options.underflow_error_mode = StateErrorMode::Exception;
            options.divide_by_zero_error_mode = StateErrorMode::Exception;
            options.divergence_error_mode = StateErrorMode::Exception;
            return options;
        }

        // 特殊値のみのモード
        static StateErrorOptions special_values_only() {
            StateErrorOptions options;
            options.nan_error_mode = StateErrorMode::ReturnSpecial;
            options.infinity_error_mode = StateErrorMode::ReturnSpecial;
            options.overflow_error_mode = StateErrorMode::ReturnSpecial;
            options.underflow_error_mode = StateErrorMode::ReturnSpecial;
            options.divide_by_zero_error_mode = StateErrorMode::ReturnSpecial;
            options.divergence_error_mode = StateErrorMode::ReturnSpecial;
            return options;
        }

        // サイレントモード
        static StateErrorOptions silent() {
            StateErrorOptions options;
            options.nan_error_mode = StateErrorMode::Silent;
            options.infinity_error_mode = StateErrorMode::Silent;
            options.overflow_error_mode = StateErrorMode::Silent;
            options.underflow_error_mode = StateErrorMode::Silent;
            options.divide_by_zero_error_mode = StateErrorMode::Silent;
            options.divergence_error_mode = StateErrorMode::Silent;
            return options;
        }

        // NumericErrorに基づくモード取得
        StateErrorMode getModeForError(NumericError error) const {
            switch (error) {
            case NumericError::DivideByZero:
                return divide_by_zero_error_mode;
            case NumericError::NaNPropagation:
            case NumericError::ExplicitNaN:
                return nan_error_mode;
            case NumericError::OutOfRangeInput:
            case NumericError::ConversionError:
            case NumericError::IntegerConversionError:
                return overflow_error_mode;
            case NumericError::DivergenceError:
                return divergence_error_mode;
            default:
                return StateErrorMode::ReturnSpecial;
            }
        }

        // NumericStateに基づくモード取得
        StateErrorMode getModeForState(NumericState state) const {
            if (NumericStateTraits::isNaN(state)) {
                return nan_error_mode;
            }
            if (NumericStateTraits::isInfinite(state)) {
                return infinity_error_mode;
            }
            if (state == NumericState::Overflow) {
                return overflow_error_mode;
            }
            if (state == NumericState::Underflow) {
                return underflow_error_mode;
            }
            if (NumericStateTraits::isDivergent(state)) {
                return divergence_error_mode;
            }
            return StateErrorMode::ReturnSpecial;
        }
    };

    // グローバルな状態エラー処理設定（スレッドセーフではない）
    inline StateErrorOptions& global_state_error_options() {
        static StateErrorOptions options = StateErrorOptions::defaults();
        return options;
    }

    // StateErrorOptionsを一時的に変更し、スコープ終了時に元に戻すためのガードクラス
    class StateErrorOptionsGuard {
    private:
        StateErrorOptions& options_;
        StateErrorMode original_nan_mode_;
        StateErrorMode original_infinity_mode_;
        StateErrorMode original_overflow_mode_;
        StateErrorMode original_underflow_mode_;
        StateErrorMode original_divide_by_zero_mode_;
        StateErrorMode original_divergence_mode_;

    public:
        explicit StateErrorOptionsGuard(StateErrorOptions& options)
            : options_(options),
            original_nan_mode_(options.nan_error_mode),
            original_infinity_mode_(options.infinity_error_mode),
            original_overflow_mode_(options.overflow_error_mode),
            original_underflow_mode_(options.underflow_error_mode),
            original_divide_by_zero_mode_(options.divide_by_zero_error_mode),
            original_divergence_mode_(options.divergence_error_mode)
        {
        }

        ~StateErrorOptionsGuard() {
            // デストラクタで設定を元に戻す
            options_.nan_error_mode = original_nan_mode_;
            options_.infinity_error_mode = original_infinity_mode_;
            options_.overflow_error_mode = original_overflow_mode_;
            options_.underflow_error_mode = original_underflow_mode_;
            options_.divide_by_zero_error_mode = original_divide_by_zero_mode_;
            options_.divergence_error_mode = original_divergence_mode_;
        }

        // コピー禁止
        StateErrorOptionsGuard(const StateErrorOptionsGuard&) = delete;
        StateErrorOptionsGuard& operator=(const StateErrorOptionsGuard&) = delete;
    };

    // 結果型（エラー処理のためのユーティリティ）
    template<typename T>
    class Result {
    public:
        // 成功結果の作成
        static Result<T> success(T value) {
            return Result(std::move(value), std::nullopt);
        }

        // エラー結果の作成
        static Result<T> error(std::string error_message) {
            return Result(std::nullopt, std::move(error_message));
        }

        // 結果が成功かどうか
        bool is_success() const {
            return value_.has_value();
        }

        // 結果がエラーかどうか
        bool is_error() const {
            return error_message_.has_value();
        }

        // 値の取得（エラーの場合は例外を投げる）
        const T& value() const {
            if (is_error()) {
                throw MklAlgebraException(error_message_.value());
            }
            return value_.value();
        }

        // 値の取得（エラーの場合は例外を投げる）
        T& value() {
            if (is_error()) {
                throw MklAlgebraException(error_message_.value());
            }
            return value_.value();
        }

        // エラーメッセージの取得（成功の場合は空文字列）
        std::string error_message() const {
            return error_message_.value_or("");
        }

    private:
        Result(std::optional<T> value, std::optional<std::string> error_message)
            : value_(std::move(value)), error_message_(std::move(error_message)) {
        }

        std::optional<T> value_;
        std::optional<std::string> error_message_;
    };

    // ユーティリティ関数

    // 次元チェック（不一致の場合は例外を投げる）
    inline void check_dimensions(std::size_t expected, std::size_t actual, const std::string& message) {
        if (expected != actual) {
            throw DimensionError(message + ": expected " + std::to_string(expected) +
                ", got " + std::to_string(actual));
        }
    }

    // インデックスチェック（範囲外の場合は例外を投げる）
    inline void check_index(std::size_t index, std::size_t size, const std::string& message) {
        if (index >= size) {
            throw IndexError(message + ": index " + std::to_string(index) +
                " out of range for size " + std::to_string(size));
        }
    }

    // 正方行列チェック（非正方の場合は例外を投げる）
    inline void check_square(std::size_t rows, std::size_t cols, const std::string& message) {
        if (rows != cols) {
            throw DimensionError(message + ": matrix is not square (" +
                std::to_string(rows) + "x" + std::to_string(cols) + ")");
        }
    }

    // 数値状態チェック関数
    template<typename T>
    void check_numeric_state(T value, const std::string& operation = "Operation") {
        const auto& options = global_state_error_options();

        // NaNチェック
        if (std::isnan(value)) {
            switch (options.nan_error_mode) {
            case StateErrorMode::Exception:
                throw NaNError(operation + " resulted in NaN");
            case StateErrorMode::ReturnSpecial:
                // 特殊値を返す場合は何もしない（valueがすでにNaN）
                break;
            case StateErrorMode::Silent:
                // サイレントモードでは何もしない
                break;
            }
        }

        // 無限大チェック
        if (std::isinf(value)) {
            switch (options.infinity_error_mode) {
            case StateErrorMode::Exception:
                throw InfinityError(operation + " resulted in infinity");
            case StateErrorMode::ReturnSpecial:
                // 特殊値を返す場合は何もしない（valueがすでに無限大）
                break;
            case StateErrorMode::Silent:
                // サイレントモードでは何もしない
                break;
            }
        }

        // オーバーフローとアンダーフローのチェックは
        // 浮動小数点演算では難しいため、ここでは実装しない
    }

    // 除算前のゼロチェック
    inline void check_divide_by_zero(double divisor, const std::string& message = "Division") {
        if (divisor == 0.0) {
            const auto& options = global_state_error_options();
            switch (options.divide_by_zero_error_mode) {
            case StateErrorMode::Exception:
                throw DivideByZeroError(message + " by zero");
            case StateErrorMode::ReturnSpecial:
            case StateErrorMode::Silent:
                // これらのモードでは何もしない（呼び出し側で無限大か特殊値を生成）
                break;
            }
        }
    }

    // 数値比較関数（浮動小数点比較）
    template<typename T>
    constexpr bool approximately_equal(T a, T b, T epsilon = std::numeric_limits<T>::epsilon() * T(100)) {
        if (a == b) return true;
        auto safe_abs = [](const T& x) -> T { return (x < T(0)) ? -x : x; };
        const T diff = safe_abs(a - b);
        const T norm = std::min((safe_abs(a) + safe_abs(b)), std::numeric_limits<T>::max());
        return diff < std::max(std::numeric_limits<T>::min(), epsilon * norm);
    }

    // 数値状態文字列変換
    inline std::string numeric_state_to_string(NumericState state) {
        return NumericStateTraits::toString(state);
    }

    // 発散詳細文字列変換
    inline std::string divergence_detail_to_string(DivergenceDetail detail) {
        return NumericStateTraits::toString(detail);
    }

    // エラー原因文字列変換
    inline std::string numeric_error_to_string(NumericError error) {
        return NumericStateTraits::toString(error);
    }

    // 状態とエラーを同時に文字列化
    inline std::string state_and_error_to_string(NumericState state, NumericError error) {
        if (error == NumericError::None) {
            return NumericStateTraits::toString(state);
        }
        else {
            return NumericStateTraits::toString(state) + " (" +
                NumericStateTraits::toString(error) + ")";
        }
    }

    // スレッド管理（MKLのスレッド数設定など）
#if CALX_HAS_MKL
    class ThreadManager {
    public:
        // 利用可能なスレッド数の取得
        static int get_max_threads() {
            return mkl_get_max_threads();
        }

        // 現在のスレッド数の取得
        static int get_num_threads() {
            return mkl_get_max_threads();
        }

        // スレッド数の設定
        static void set_num_threads(int num_threads) {
            mkl_set_num_threads(num_threads);
        }

        // スレッド数の一時的な変更（スコープが終了すると元に戻る）
        class ScopedThreads {
        public:
            explicit ScopedThreads(int num_threads)
                : previous_threads_(mkl_get_max_threads()) {
                mkl_set_num_threads(num_threads);
            }

            ~ScopedThreads() {
                mkl_set_num_threads(previous_threads_);
            }

            // コピー不可
            ScopedThreads(const ScopedThreads&) = delete;
            ScopedThreads& operator=(const ScopedThreads&) = delete;

        private:
            const int previous_threads_;
        };
    };
#else
    class ThreadManager {
    public:
        // MKLが利用できない場合のスタブ実装
        static int get_max_threads() {
            return std::thread::hardware_concurrency();
        }

        static int get_num_threads() {
            return 1;
        }

        static void set_num_threads(int /* num_threads */) {
            // スタブ実装では何もしない
        }

        class ScopedThreads {
        public:
            explicit ScopedThreads(int /* num_threads */) {}

            // コピー不可
            ScopedThreads(const ScopedThreads&) = delete;
            ScopedThreads& operator=(const ScopedThreads&) = delete;
        };
    };
#endif

    // メモリアラインメント関連
    namespace memory {
        // 必要なアラインメントの計算
        constexpr std::size_t simd_alignment() {
            switch (available_simd_level) {
            case SimdInstructionSet::AVX512:
                return 64;
            case SimdInstructionSet::AVX2:
            case SimdInstructionSet::AVX:
                return 32;
            case SimdInstructionSet::SSE4_2:
            case SimdInstructionSet::SSE4_1:
            case SimdInstructionSet::SSSE3:
            case SimdInstructionSet::SSE3:
            case SimdInstructionSet::SSE2:
            case SimdInstructionSet::NEON:
                return 16;
            default:
                return 8;
            }
        }

        // アラインメントの調整
        inline std::size_t align_to(std::size_t size, std::size_t alignment) {
            return (size + alignment - 1) & ~(alignment - 1);
        }

        // アラインメント済みメモリの確保
        template<typename T>
        T* aligned_alloc(std::size_t size, std::size_t alignment = simd_alignment()) {
            // C++17のstd::aligned_allocまたは相当する関数を使用
#if defined(CALX_COMPILER_MSVC)
            return static_cast<T*>(_aligned_malloc(size * sizeof(T), alignment));
#elif defined(_POSIX_VERSION)
            void* ptr = nullptr;
            if (posix_memalign(&ptr, alignment, size * sizeof(T)) != 0) {
                return nullptr;
            }
            return static_cast<T*>(ptr);
#else
            // 一般的なマシンで使えるアライメント確保のフォールバック実装
            void* ptr = std::malloc(size * sizeof(T) + alignment);
            if (!ptr) return nullptr;
            
            std::size_t offset = alignment - (reinterpret_cast<std::uintptr_t>(ptr) % alignment);
            T* aligned = reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + offset);
            
            // ポインタを前に戻すために必要な情報を保存
            *(reinterpret_cast<void**>(aligned) - 1) = ptr;
            
            return aligned;
#endif
        }

        // アラインメント済みメモリの解放
        template<typename T>
        void aligned_free(T* ptr) {
#if defined(CALX_COMPILER_MSVC)
            _aligned_free(ptr);
#elif defined(_POSIX_VERSION)
            free(ptr);
#else
            // 一般的なマシンで使えるアライメント解放のフォールバック実装
            if (!ptr) return;
            // 元のポインタを取得して解放
            void* original = *(reinterpret_cast<void**>(ptr) - 1);
            std::free(original);
#endif
        }
    }

    // 一般的な数値状態チェック関数（更新版）
    inline void check_numeric_state(NumericState state, NumericError error, const std::string& message) {
        const auto& options = global_state_error_options();

        // エラーに基づくチェック
        if (error != NumericError::None) {
            switch (error) {
            case NumericError::DivideByZero:
                if (options.divide_by_zero_error_mode == StateErrorMode::Exception) {
                    throw DivideByZeroError(message);
                }
                break;
            case NumericError::NaNPropagation:
            case NumericError::ExplicitNaN:
            case NumericError::InvalidBitPattern:
                if (options.nan_error_mode == StateErrorMode::Exception) {
                    throw NaNError(message);
                }
                break;
            case NumericError::OutOfRangeInput:
            case NumericError::ConversionError:
            case NumericError::IntegerConversionError:
                if (options.overflow_error_mode == StateErrorMode::Exception) {
                    throw OverflowError(message);
                }
                break;
            case NumericError::DivergenceError:
                if (options.divergence_error_mode == StateErrorMode::Exception) {
                    throw DivergenceStateError(message);
                }
                break;
            default:
                // その他のエラーは特に処理しない
                break;
            }
        }

        // 状態に基づくチェック
        if (NumericStateTraits::isNaN(state)) {
            if (options.nan_error_mode == StateErrorMode::Exception) {
                throw NaNError(message);
            }
            return;
        }

        // 無限大チェック
        if (NumericStateTraits::isInfinite(state)) {
            if (options.infinity_error_mode == StateErrorMode::Exception) {
                throw InfinityError(message, state == NumericState::PositiveInfinity);
            }
            return;
        }

        // オーバーフローチェック
        if (state == NumericState::Overflow) {
            if (options.overflow_error_mode == StateErrorMode::Exception) {
                throw OverflowError(message);
            }
            return;
        }

        // アンダーフローチェック
        if (state == NumericState::Underflow) {
            if (options.underflow_error_mode == StateErrorMode::Exception) {
                throw UnderflowError(message);
            }
            return;
        }

        // 発散チェック
        if (NumericStateTraits::isDivergent(state)) {
            if (options.divergence_error_mode == StateErrorMode::Exception) {
                throw DivergenceStateError(message);
            }
            return;
        }
    }

} // namespace calx

#endif // CALX_COMMON_HPP