// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // numeric_state.hpp // 数値状態管理システム // // このファイルでは、多倍長整数や浮動小数点数などの数値型で // 共通して使用される状態管理システムを定義します。 // IEEE 754の特殊値や数値計算における様々な状態を表現します。 #ifndef CALX_NUMERIC_STATE_HPP #define CALX_NUMERIC_STATE_HPP #include #include #include #include namespace calx { /** * @brief 数値状態の特性に関するクラス * * このクラスは、数値状態の分類や特性を判定するためのメソッドを提供します。 */ class NumericStateTraits { public: /** * @brief 状態がNaNかどうかを判定 * @param state 判定する状態 * @return NaNである場合はtrue */ static constexpr bool isNaN(NumericState state) { return state == NumericState::NaN; } /** * @brief 状態が無限大かどうかを判定 * @param state 判定する状態 * @return 無限大である場合はtrue */ static constexpr bool isInfinite(NumericState state) { return state == NumericState::PositiveInfinity || state == NumericState::NegativeInfinity || state == NumericState::ComplexInfinity; } /** * @brief 状態が収束していないかどうかを判定 * @param state 判定する状態 * @return 収束していない場合はtrue */ static constexpr bool isNotConverged(NumericState state) { return state == NumericState::NotConverged; } /** * @brief 状態が発散しているかどうかを判定 * @param state 判定する状態 * @return 発散している場合はtrue */ static constexpr bool isDivergent(NumericState state) { return state == NumericState::Divergent || state == NumericState::NotConverged || state == NumericState::Oscillating || state == NumericState::SlowConvergence; } /** * @brief 状態が特殊状態かどうかを判定 * @param state 判定する状態 * @return 特殊状態である場合はtrue(正常以外) */ static constexpr bool isSpecial(NumericState state) { return state != NumericState::Normal; } /** * @brief 状態の文字列表現を取得 * @param state 状態 * @return 状態の文字列表現 */ static std::string toString(NumericState state) { switch (state) { case NumericState::Normal: return "Normal"; case NumericState::NaN: return "NaN"; case NumericState::PositiveInfinity: return "Infinity"; case NumericState::NegativeInfinity: return "-Infinity"; case NumericState::ComplexInfinity: return "ComplexInfinity"; case NumericState::Overflow: return "Overflow"; case NumericState::Underflow: return "Underflow"; case NumericState::Interrupted: return "Interrupted"; case NumericState::PrecisionLimit: return "PrecisionLimit"; case NumericState::PositiveZero: return "+Zero"; case NumericState::NegativeZero: return "-Zero"; case NumericState::Subnormal: return "Subnormal"; case NumericState::NotConverged: return "NotConverged"; case NumericState::Divergent: return "Divergent"; case NumericState::Oscillating: return "Oscillating"; case NumericState::SlowConvergence: return "SlowConvergence"; case NumericState::TruncatedConvergence: return "TruncatedConvergence"; default: return "Unknown"; } } /** * @brief 符号の文字列表現を取得 * @param sign 符号 * @return 符号の文字列表現 */ static std::string toString(int sign) { if (sign < 0) return "負"; else if (sign > 0) return "正"; else return "零"; } /** * @brief 発散詳細の文字列表現を取得 * @param detail 発散詳細 * @return 発散詳細の文字列表現 */ static std::string toString(DivergenceDetail detail) { switch (detail) { case DivergenceDetail::None: return "None"; case DivergenceDetail::Diverging: return "Diverging"; case DivergenceDetail::Oscillating: return "Oscillating"; case DivergenceDetail::Chaotic: return "Chaotic"; case DivergenceDetail::SlowConvergence: return "SlowConvergence"; case DivergenceDetail::TruncatedConvergence: return "TruncatedConvergence"; case DivergenceDetail::ConditionalConvergenceViolation: return "ConditionalConvergenceViolation"; case DivergenceDetail::AlternatingSeriesDivergence: return "AlternatingSeriesDivergence"; default: return "Unknown"; } } /** * @brief エラー原因の文字列表現を取得 * @param error エラー原因 * @return エラー原因の文字列表現 */ static std::string toString(NumericError error) { switch (error) { case NumericError::None: return "None"; case NumericError::DivideByZero: return "DivideByZero"; case NumericError::InfiniteIndeterminate: return "InfiniteIndeterminate"; case NumericError::ZeroTimesInfinity: return "ZeroTimesInfinity"; case NumericError::NegativeSqrt: return "NegativeSqrt"; case NumericError::ConversionError: return "ConversionError"; case NumericError::ExplicitNaN: return "ExplicitNaN"; case NumericError::Uninitialized: return "Uninitialized"; case NumericError::InvalidBitPattern: return "InvalidBitPattern"; case NumericError::InvalidStringConversion: return "InvalidStringConversion"; case NumericError::OutOfRangeInput: return "OutOfRangeInput"; case NumericError::NaNPropagation: return "NaNPropagation"; case NumericError::IntegerConversionError: return "IntegerConversionError"; case NumericError::FunctionDomainError: return "FunctionDomainError"; case NumericError::InvalidBitOperation: return "InvalidBitOperation"; case NumericError::DivergenceError: return "DivergenceError"; default: return "Unknown"; } } /** * @brief エラー原因から状態を決定 * @param error エラー原因 * @return 対応する状態 */ static NumericState errorToState(NumericError error) { switch (error) { case NumericError::None: return NumericState::Normal; case NumericError::DivideByZero: return NumericState::NaN; // 0/0の場合 // 注意: n/0の場合は符号に応じてPositiveInfinityまたはNegativeInfinityになる case NumericError::InfiniteIndeterminate: case NumericError::ZeroTimesInfinity: case NumericError::NegativeSqrt: case NumericError::ExplicitNaN: case NumericError::Uninitialized: case NumericError::InvalidBitPattern: case NumericError::InvalidStringConversion: case NumericError::NaNPropagation: case NumericError::FunctionDomainError: case NumericError::InvalidBitOperation: return NumericState::NaN; case NumericError::ConversionError: case NumericError::OutOfRangeInput: case NumericError::IntegerConversionError: return NumericState::Overflow; case NumericError::DivergenceError: return NumericState::Divergent; default: return NumericState::NaN; } } /** * @brief 状態からデフォルトのエラー原因を推定 * @param state 状態 * @return 推定されるエラー原因 * @note 1対1のマッピングではないため、完全な逆変換ではない */ static NumericError stateToDefaultError(NumericState state) { switch (state) { case NumericState::Normal: case NumericState::PositiveZero: case NumericState::NegativeZero: return NumericError::None; case NumericState::NaN: return NumericError::ExplicitNaN; case NumericState::PositiveInfinity: case NumericState::NegativeInfinity: case NumericState::ComplexInfinity: // デフォルトは不明な無限大 return NumericError::InfiniteIndeterminate; case NumericState::Overflow: return NumericError::OutOfRangeInput; case NumericState::Underflow: return NumericError::OutOfRangeInput; case NumericState::Interrupted: return NumericError::None; case NumericState::PrecisionLimit: return NumericError::None; case NumericState::Subnormal: return NumericError::None; case NumericState::NotConverged: case NumericState::Divergent: case NumericState::Oscillating: case NumericState::SlowConvergence: return NumericError::DivergenceError; default: return NumericError::None; } } /** * @brief 状態がエラーコードを必要とするかどうかを判定 * @param state 判定する状態 * @return エラーコードが必要な場合はtrue */ static bool requiresErrorCode(NumericState state) { return state != NumericState::Normal && state != NumericState::PositiveZero && state != NumericState::NegativeZero; } }; /** * @brief 数値状態の特性を提供するテンプレートクラス * * このテンプレートは数値型ごとに特殊化され、その型の状態管理機能を提供します。 * 代数系コンセプトとは独立した層として機能します。 */ template struct numeric_state_traits { // デフォルトでは未サポート static constexpr bool is_supported = false; // このままでは使用できないダミーメソッド static bool isNormal(const T&) { return true; } static bool isNaN(const T&) { return false; } static bool isInfinite(const T&) { return false; } static bool isNotConverged(const T&) { return false; } static NumericState getState(const T&) { return NumericState::Normal; } static NumericError getError(const T&) { return NumericError::None; } static int getSign(const T&) { return 0; } }; // 基本型のためのヘルパー関数 /** * @brief 符号を取得 * @param value 値 * @return 符号 */ template constexpr int getSign(T value) { return value < 0 ? -1 : value > 0 ? 1 : 0; } template constexpr int getSign(T value) { return value < 0 ? -1 : value > 0 ? 1 : 0; } /** * @brief 符号を反転 * @param sign 符号 * @return 反転した符号 */ constexpr int negateSign(int sign) { return -sign; } /** * @brief 二つの符号から乗算/除算結果の符号を決定 * @param a 第1符号 * @param b 第2符号 * @return 結果の符号 */ constexpr int combineSignsMultiply(int a, int b) { if (a == 0 || b == 0) return 0; return (a == b) ? 1 : -1; } /** * @brief 二つの符号から加算結果の符号を決定 * @param a 第1符号 * @param b 第2符号 * @param absCompare 絶対値の比較結果(負数: |a|<|b|, 0: |a|=|b|, 正数: |a|>|b|) * @return 結果の符号 */ constexpr int combineSignsAdd(int a, int b, int absCompare) { // 符号が同じ場合、結果の符号も同じ if (a == b) return a; // 符号が異なる場合、絶対値の大きい方の符号になる if (absCompare < 0) return b; // |a| < |b| else if (absCompare > 0) return a; // |a| > |b| else return 0; // |a| = |b| } // 状態管理のためのコンセプト /** * @brief 状態管理をサポートする型のコンセプト */ template concept HasNumericState = requires(T a) { { numeric_state_traits::isNormal(a) } -> std::convertible_to; { numeric_state_traits::getState(a) } -> std::convertible_to; { numeric_state_traits::getError(a) } -> std::convertible_to; { numeric_state_traits::getSign(a) } -> std::convertible_to; }; /** * @brief 発散詳細をサポートする型のコンセプト */ template concept HasDivergenceHandling = requires(T a) { { numeric_state_traits::isNotConverged(a) } -> std::convertible_to; { numeric_state_traits::getDivergenceDetail(a) } -> std::convertible_to; }; /** * @brief オーバーフロー検出をサポートする型のコンセプト */ template concept HasOverflowDetection = requires(T a) { { numeric_state_traits::isOverflow(a) } -> std::convertible_to; }; } // namespace calx #endif // CALX_NUMERIC_STATE_HPP