// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later namespace calx { // Int型の前方宣言(循環参照を避けるため) class Int; // 数値状態管理のトレイト // 状態伝播ルールを定義するトレイト struct numeric_state_propagation_traits { // 二項演算の状態伝播ルール static NumericState propagate_binary_op(NumericState lhs, NumericState rhs, NumericError& resultError) { // NaNは常に優先される if (NumericStateTraits::isNaN(lhs) || NumericStateTraits::isNaN(rhs)) { resultError = NumericError::NaNPropagation; return NumericState::NaN; } // 無限大同士の演算で、符号が異なる場合はNaN if ((lhs == NumericState::PositiveInfinity && rhs == NumericState::NegativeInfinity) || (lhs == NumericState::NegativeInfinity && rhs == NumericState::PositiveInfinity)) { resultError = NumericError::InfiniteIndeterminate; return NumericState::NaN; } // 無限大と他の値の演算では無限大が優先される if (lhs == NumericState::PositiveInfinity || lhs == NumericState::NegativeInfinity) { resultError = NumericError::None; // 無限大自体はエラーではない return lhs; } if (rhs == NumericState::PositiveInfinity || rhs == NumericState::NegativeInfinity) { resultError = NumericError::None; // 無限大自体はエラーではない return rhs; } // 複素無限大の処理 if (lhs == NumericState::ComplexInfinity || rhs == NumericState::ComplexInfinity) { resultError = NumericError::None; // 無限大自体はエラーではない return NumericState::ComplexInfinity; } // オーバーフローは優先順位が高い if (lhs == NumericState::Overflow || rhs == NumericState::Overflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Overflow; } // アンダーフロー if (lhs == NumericState::Underflow || rhs == NumericState::Underflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Underflow; } // 発散状態 if (NumericStateTraits::isNotConverged(lhs) || NumericStateTraits::isNotConverged(rhs)) { resultError = NumericError::DivergenceError; return NumericState::NotConverged; } // サブノーマル if (lhs == NumericState::Subnormal || rhs == NumericState::Subnormal) { resultError = NumericError::None; return NumericState::Subnormal; } // 通常値(ゼロを含む) resultError = NumericError::None; return NumericState::Normal; } // 加算の状態伝播ルール static NumericState propagate_add(NumericState lhs, NumericState rhs, NumericError& resultError) { return propagate_binary_op(lhs, rhs, resultError); } // 減算の状態伝播ルール static NumericState propagate_subtract(NumericState lhs, NumericState rhs, NumericError& resultError) { // 減算では、rhs引数の符号を反転して加算のルールを適用 if (rhs == NumericState::PositiveInfinity) rhs = NumericState::NegativeInfinity; else if (rhs == NumericState::NegativeInfinity) rhs = NumericState::PositiveInfinity; return propagate_add(lhs, rhs, resultError); } // 乗算の状態伝播ルール static NumericState propagate_multiply(NumericState lhs, NumericState rhs, NumericError& resultError) { // NaNは常に優先される if (NumericStateTraits::isNaN(lhs) || NumericStateTraits::isNaN(rhs)) { resultError = NumericError::NaNPropagation; return NumericState::NaN; } // 無限大 * 0 = NaN // ここでは、具体的な値ではなく、isZero()メソッドを呼び出す側で判定する必要がある // そのため、ここでのゼロチェックは不要となる(値の符号は状態から判断できない) // 無限大 * 無限大 = 符号に基づく無限大 if (NumericStateTraits::isInfinite(lhs) && NumericStateTraits::isInfinite(rhs)) { bool positive = (lhs == NumericState::PositiveInfinity && rhs == NumericState::PositiveInfinity) || (lhs == NumericState::NegativeInfinity && rhs == NumericState::NegativeInfinity); resultError = NumericError::None; return positive ? NumericState::PositiveInfinity : NumericState::NegativeInfinity; } // 無限大 * 通常値 = 符号に基づく無限大 if (lhs == NumericState::PositiveInfinity) { if (rhs == NumericState::Normal) { // ここで本来は値の符号を見るべきだが、状態だけではわからないため通常は正を仮定 resultError = NumericError::None; return NumericState::PositiveInfinity; } } if (lhs == NumericState::NegativeInfinity) { if (rhs == NumericState::Normal) { // 同上 resultError = NumericError::None; return NumericState::NegativeInfinity; } } if (rhs == NumericState::PositiveInfinity || rhs == NumericState::NegativeInfinity) { // 同上 if (lhs == NumericState::Normal) { resultError = NumericError::None; return rhs; } } // 複素無限大の処理 if (lhs == NumericState::ComplexInfinity || rhs == NumericState::ComplexInfinity) { resultError = NumericError::None; return NumericState::ComplexInfinity; } // オーバーフロー if (lhs == NumericState::Overflow || rhs == NumericState::Overflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Overflow; } // アンダーフロー(小さい値同士の乗算) if (lhs == NumericState::Underflow || rhs == NumericState::Underflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Underflow; } // 発散状態 if (NumericStateTraits::isDivergent(lhs) || NumericStateTraits::isDivergent(rhs)) { resultError = NumericError::DivergenceError; return NumericState::NotConverged; } // サブノーマル if (lhs == NumericState::Subnormal || rhs == NumericState::Subnormal) { resultError = NumericError::None; return NumericState::Subnormal; } // 通常値(ゼロを含む) resultError = NumericError::None; return NumericState::Normal; } // 除算の状態伝播ルール static NumericState propagate_divide(NumericState lhs, NumericState rhs, NumericError& resultError) { // NaNは常に優先される if (NumericStateTraits::isNaN(lhs) || NumericStateTraits::isNaN(rhs)) { resultError = NumericError::NaNPropagation; return NumericState::NaN; } // 0除算チェックは、具体的な値でないとできないため、 // ここでは実装せず、呼び出し側でisZero()メソッドを使って判定する // 無限大 / 無限大 = NaN if (NumericStateTraits::isInfinite(lhs) && NumericStateTraits::isInfinite(rhs)) { resultError = NumericError::InfiniteIndeterminate; return NumericState::NaN; } // 通常値 / 無限大 = 0(これも値がわからないとサイズを判断できない) // 無限大 / 通常値 = 無限大(符号保持) if (lhs == NumericState::PositiveInfinity && rhs == NumericState::Normal) { resultError = NumericError::None; return NumericState::PositiveInfinity; } if (lhs == NumericState::NegativeInfinity && rhs == NumericState::Normal) { resultError = NumericError::None; return NumericState::NegativeInfinity; } // 複素無限大の処理 if (lhs == NumericState::ComplexInfinity) { if (rhs == NumericState::ComplexInfinity) { resultError = NumericError::InfiniteIndeterminate; return NumericState::NaN; } resultError = NumericError::None; return NumericState::ComplexInfinity; } if (rhs == NumericState::ComplexInfinity) { resultError = NumericError::None; return NumericState::Normal; // 通常は0になるがここでは判断できない } // オーバーフロー if (lhs == NumericState::Overflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Overflow; } if (rhs == NumericState::Underflow) { // 小さい値で割ると大きな値になる resultError = NumericError::OutOfRangeInput; return NumericState::Overflow; } // アンダーフロー if (lhs == NumericState::Underflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Underflow; } if (rhs == NumericState::Overflow) { // 大きな値で割ると小さな値になる resultError = NumericError::OutOfRangeInput; return NumericState::Underflow; } // 発散状態 if (NumericStateTraits::isDivergent(lhs) || NumericStateTraits::isDivergent(rhs)) { resultError = NumericError::DivergenceError; return NumericState::Divergent; } // 通常値(ゼロを含む) resultError = NumericError::None; return NumericState::Normal; } // 平方根演算の状態伝播ルール static NumericState propagate_sqrt(NumericState state, NumericError& resultError) { if (NumericStateTraits::isNaN(state)) { resultError = NumericError::NaNPropagation; return NumericState::NaN; } // 負の値の平方根 = NaN if (state == NumericState::NegativeInfinity) { resultError = NumericError::NegativeSqrt; return NumericState::NaN; } if (state == NumericState::PositiveInfinity) { resultError = NumericError::None; return NumericState::PositiveInfinity; } if (state == NumericState::ComplexInfinity) { resultError = NumericError::None; return NumericState::ComplexInfinity; } // オーバーフローの平方根は通常値になる可能性がある if (state == NumericState::Overflow) { resultError = NumericError::None; return NumericState::Normal; // または適切なオーバーフロー状態 } // アンダーフローの平方根はさらにアンダーフローになる if (state == NumericState::Underflow) { resultError = NumericError::OutOfRangeInput; return NumericState::Underflow; } if (NumericStateTraits::isDivergent(state)) { resultError = NumericError::DivergenceError; return NumericState::Divergent; } if (state == NumericState::Subnormal) { resultError = NumericError::None; return NumericState::Subnormal; } resultError = NumericError::None; return NumericState::Normal; } // 符号反転の状態伝播ルール static NumericState propagate_negate(NumericState state, NumericError& resultError) { if (state == NumericState::PositiveInfinity) { resultError = NumericError::None; return NumericState::NegativeInfinity; } if (state == NumericState::NegativeInfinity) { resultError = NumericError::None; return NumericState::PositiveInfinity; } // その他の状態は変わらない resultError = NumericError::None; return state; } // 絶対値の状態伝播ルール static NumericState propagate_abs(NumericState state, NumericError& resultError) { if (state == NumericState::NegativeInfinity) { resultError = NumericError::None; return NumericState::PositiveInfinity; } // 絶対値は負の値を正にするだけなので、他の状態は変わらない resultError = NumericError::None; return state; } // 発散詳細の伝播 static DivergenceDetail propagate_divergence(DivergenceDetail lhs, DivergenceDetail rhs) { // 振動が最も優先 if (lhs == DivergenceDetail::Oscillating || rhs == DivergenceDetail::Oscillating) return DivergenceDetail::Oscillating; // 次に発散 if (lhs == DivergenceDetail::Diverging || rhs == DivergenceDetail::Diverging) return DivergenceDetail::Diverging; // 収束速度が遅い場合 if (lhs == DivergenceDetail::SlowConvergence || rhs == DivergenceDetail::SlowConvergence) return DivergenceDetail::SlowConvergence; // 打ち切り誤差 if (lhs == DivergenceDetail::ConditionalConvergenceViolation || rhs == DivergenceDetail::ConditionalConvergenceViolation) return DivergenceDetail::ConditionalConvergenceViolation; // どちらも未定義ならNone return DivergenceDetail::None; } }; // ベクトル/行列特性 // ベクトル表現タグ struct vector_layout_tag {}; struct dense_vector_tag : vector_layout_tag {}; // 密ベクトル struct sparse_vector_tag : vector_layout_tag {}; // 疎ベクトル // 行列表現タグ struct matrix_layout_tag {}; struct row_major_tag : matrix_layout_tag {}; // 行優先 struct column_major_tag : matrix_layout_tag {}; // 列優先 struct dense_matrix_tag : matrix_layout_tag {}; // 密行列 struct sparse_matrix_tag : matrix_layout_tag {}; // 疎行列 struct banded_matrix_tag : matrix_layout_tag {}; // 帯行列 struct diagonal_matrix_tag : matrix_layout_tag {}; // 対角行列 struct symmetric_matrix_tag : matrix_layout_tag {}; // 対称行列 struct hermitian_matrix_tag : matrix_layout_tag {}; // エルミート行列 struct triangular_matrix_tag : matrix_layout_tag {}; // 三角行列 // ベクトル特性の基本テンプレート template struct vector_traits { // デフォルトは不明 static constexpr bool is_recognized = false; }; // 行列特性の基本テンプレート template struct matrix_traits { // デフォルトは不明 static constexpr bool is_recognized = false; // 行列が対称行列かどうかを判定する関数 // 修正:関数名を統一化(isSymmetric → is_symmetric) template static bool is_symmetric(const MatrixType& m) { const auto rows = m.rows(); const auto cols = m.cols(); // 正方行列でないなら対称行列ではない if (rows != cols) { return false; } // すべての(i,j)と(j,i)の組について一致するか確認 for (std::size_t i = 0; i < rows; ++i) { for (std::size_t j = i + 1; j < cols; ++j) { if (m(i, j) != m(j, i)) { return false; } } } return true; } }; // 行列/ベクトル演算のためのタグディスパッチ関数 // ベクトル加算用ディスパッチ template::layout_tag> struct vector_addition_impl { static void apply(const VectorType& a, const VectorType& b, VectorType& result) { // デフォルト実装(要素ごとの加算) const auto size = a.size(); for (std::size_t i = 0; i < size; ++i) { result[i] = a[i] + b[i]; } } }; // 行列加算用ディスパッチ template::layout_tag> struct matrix_addition_impl { static void apply(const MatrixType& a, const MatrixType& b, MatrixType& result) { // デフォルト実装(要素ごとの加算) const auto rows = a.rows(); const auto cols = a.cols(); for (std::size_t i = 0; i < rows; ++i) { for (std::size_t j = 0; j < cols; ++j) { result(i, j) = a(i, j) + b(i, j); } } } }; // 行列乗算用ディスパッチ template::layout_tag, typename TagB = typename matrix_traits::layout_tag> struct matrix_multiplication_impl { static void apply(const MatrixTypeA& a, const MatrixTypeB& b, MatrixTypeC& result) { // デフォルト実装(三重ループによる乗算) const auto m = a.rows(); const auto n = b.cols(); const auto k = a.cols(); // 結果を0で初期化 for (std::size_t i = 0; i < m; ++i) { for (std::size_t j = 0; j < n; ++j) { result(i, j) = numeric_traits::zero(); } } // 行列乗算: C = A * B for (std::size_t i = 0; i < m; ++i) { for (std::size_t j = 0; j < n; ++j) { for (std::size_t l = 0; l < k; ++l) { result(i, j) += a(i, l) * b(l, j); } } } } }; // カスタム型のためのトレイト拡張メカニズム // 数値トレイトのカスタマイズポイント template struct custom_numeric_traits {}; // カスタム数値トレイトを統合するためのヘルパー template struct numeric_traits_base : custom_numeric_traits { // カスタムトレイトがないか、サポートされていない場合のデフォルト static constexpr bool is_supported = false; }; // 数値トレイトの特殊化の選択 template struct numeric_traits_selector { using type = typename std::conditional< std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v> || std::is_same_v>, numeric_traits, // 標準型の場合は組み込みトレイトを使用 numeric_traits_base // カスタム型の場合はカスタマイズポイントを使用 > ::type; }; // トレイトのカスタマイズを簡単にするマクロ #define CALX_DECLARE_NUMERIC_TRAITS(Type, IsSupported, IsComplex, IsInteger, IsFloatingPoint) \ template<> \ struct custom_numeric_traits { \ using value_type = Type; \ static constexpr bool is_supported = IsSupported; \ static constexpr bool is_complex = IsComplex; \ static constexpr bool is_integer = IsInteger; \ static constexpr bool is_floating_point = IsFloatingPoint; \ }; // 状態管理トレイトのカスタマイズマクロ #define CALX_DECLARE_STATE_TRAITS(Type) \ template<> \ struct custom_numeric_traits { \ using value_type = Type; \ using state_type = NumericState; \ using error_type = NumericError; \ using divergence_detail_type = DivergenceDetail; \ static constexpr bool has_state_management = true; \ }; // ヘルパー関数とメタ関数 //----------------------------------------------------------------------------- // コンセプトチェック用のヘルパー template constexpr bool is_field_v = concepts::Field; template constexpr bool is_ordered_field_v = concepts::OrderedField; template constexpr bool is_vector_space_v = concepts::VectorSpace; template constexpr bool is_matrix_of_v = concepts::MatrixOf; template constexpr bool is_vector_of_v = concepts::VectorOf; // 状態管理のチェック用ヘルパー template constexpr bool has_numeric_state_management_v = concepts::HasNumericState; template constexpr bool has_divergence_handling_v = concepts::HasDivergenceHandling; template constexpr bool has_overflow_detection_v = concepts::HasOverflowDetection; // ダックタイピングサポート // これらの関数は、特定の操作が型に対して定義されているかを検査します template constexpr bool has_addition_v = requires(T a, T b) { { a + b } -> std::convertible_to; }; template constexpr bool has_multiplication_v = requires(T a, T b) { { a* b } -> std::convertible_to; }; template constexpr bool has_division_v = requires(T a, T b) { { a / b } -> std::convertible_to; }; template constexpr bool has_negation_v = requires(T a) { { -a } -> std::convertible_to; }; template constexpr bool has_equality_v = requires(T a, T b) { { a == b } -> std::convertible_to; }; template constexpr bool has_comparison_v = requires(T a, T b) { { a < b } -> std::convertible_to; }; template constexpr bool has_abs_v = requires(T a) { { std::abs(static_cast(a)) } -> std::convertible_to; }; template constexpr bool has_sqrt_v = requires(T a) { { std::sqrt(static_cast(a)) } -> std::convertible_to; }; // 状態管理用ヘルパー template constexpr bool has_is_normal_v = requires(T a) { { a.isNormal() } -> std::convertible_to; }; template constexpr bool has_is_nan_v = requires(T a) { { a.isNaN() } -> std::convertible_to; }; template constexpr bool has_is_infinite_v = requires(T a) { { a.isInfinite() } -> std::convertible_to; }; template constexpr bool has_is_divergent_v = requires(T a) { { a.isDivergent() } -> std::convertible_to; }; } // namespace calx