Concepts — 代数的コンセプト

概要

sangi::concepts 名前空間は、抽象代数学の主要な構造を C++20 コンセプト として定義する。 群・環・体・ベクトル空間・ヒルベルト空間などの代数的要件をコンパイル時に検証でき、 テンプレート引数の型制約を明示的に表現できる。

  • コンパイル時型検証 — テンプレート引数が代数的要件を満たさない場合、明確なエラーメッセージが得られる
  • 階層的設計 — AdditiveMonoid → AdditiveGroup → Ring → Field のように、数学的な包含関係を反映
  • 40 以上のコンセプト — 基本演算、代数的構造、ベクトル空間、線形写像、数値型、行列・テンソル、代数・加群をカバー
  • ヘッダオンリー — リンク不要。#include するだけで使用可能
  • C++23 拡張SparseMatrixOf, BandMatrixOf, RealField, ComplexField などの追加コンセプト (C++23 モード)

数学的な公理 (結合律、交換律、分配法則など) はコンパイル時に検証できないため、 構文的要件 (演算子の存在、戻り値型の一致) のみを検査する。 意味的な正しさはユーザーの責任となる。

コンセプト階層

sangi の代数的コンセプトは数学的な包含関係を反映して階層化されている。 下図は主要な構造の包含関係を示す (矢印 A → B は「A は B の上位構造」、 すなわち B が A を満たすことを意味する)。

HasBasicArithmetic AdditiveMonoid AdditiveGroup AdditiveAbelian Group MultiplicativeMonoid MultiplicativeGroup Ring CommutativeRing IntegralDomain Field OrderedField DivisionRing (例: Quaternion) VectorSpace NormedVectorSpace BanachSpace InnerProductSpace HilbertSpace Module Algebra

主要型の代数的構造

RingIntegralDomainFieldOrderedField備考
int / long long整域だが体ではない (乗法逆元なし)
double / float順序体
sangi::Float多倍長浮動小数点
sangi::Complex<double>順序なし
sangi::Rational<T>有理数体
sangi::Quaternion<double>除環 (非可換、 DivisionRing は満たす)
sangi::Polynomial<double> (既定)整域。 一般には体ではない
sangi::Matrix<double>operator/ なし
unsigned intAdditiveGroup 不適合 (加法逆元が閉じない)

基本演算コンセプト

コンセプト要件
HasBasicArithmetic<T> +, -, *, /, 単項 - が定義済み double, float, Int, Float, Rational, Complex<double>
Comparable<T> ==, !=, <, <=, >, >= が定義済み double, int, Int, Float, Rational
EqualityComparable<T> ==, != のみ Complex<double>, Quaternion<double>, 全数値型
HasMathConstants<T> T::pi(), T::e() が定義済み Floatfloat/double は静的メソッド pi()/e() を持たないため適合しない。sangi::Float など独自型向け

HasBasicArithmetic<T> 適合表

適合備考
int / double / long double組込み数値型
sangi::Float多倍長浮動小数点
sangi::Complex<T>複素数
sangi::Rational<T>有理数
sangi::Quaternion<T>四元数 (非可換だが 5 演算は閉じる)
sangi::Polynomial<T>✓ (条件付き)既定では多項式除算の商を返すため適合。 SANGI_POLY_DIV_RATIONAL 定義時は operator/RationalFunction<T> を返すため不適合。 後述の注意を参照
sangi::Matrix<T>operator/ なし
sangi::Vector<T>operator/ なし、 operator* なし
std::string-, *, /, 単項 - なし
⚠ 注意 (Polynomial の operator/ 切替)

sangi::Polynomial<T>operator/ はビルド設定で挙動が変わる:

  • 既定: 多項式除算のを返す (Polynomial<T>)。 HasBasicArithmetic を満たす。
  • SANGI_POLY_DIV_RATIONAL 定義時: 有理関数 RationalFunction<T> を返す。 HasBasicArithmetic<Polynomial<T>> は満たさなくなる。

数学的にも Polynomial<T>整域 (IntegralDomain) であり、 一般には体ではないため Field<Polynomial<T>> はビルド設定にかかわらず満たさない。

代数的構造

以下の包含関係が成り立つ:

$$\text{AdditiveMonoid} \subset \text{AdditiveGroup} \subset \text{AdditiveAbelianGroup}$$ $$\text{Ring} = \text{AdditiveAbelianGroup} \cap \text{MultiplicativeMonoid}$$ $$\text{Ring} \subset \text{CommutativeRing} \subset \text{IntegralDomain} \subset \text{Field} \subset \text{OrderedField}$$
コンセプト要件
AdditiveMonoid<T> a + b, T{0} (加法単位元) int, float, double, unsigned int, Int, Float
AdditiveGroup<T> AdditiveMonoid + 単項 -a, a - b int, float, double, Int, Float
AdditiveAbelianGroup<T> AdditiveGroup (交換律はマーカー) int, float, double, Int, Float
MultiplicativeMonoid<T> a * b, T{1} (乗法単位元) int, float, double, Int, Float
MultiplicativeGroup<T> MultiplicativeMonoid + T{1} / a (乗法逆元) float, double, Float, Rational, Complex<double>
MultiplicativeAbelianGroup<T> MultiplicativeGroup (交換律はマーカー) float, double, Float, Rational
Ring<T> AdditiveAbelianGroup + MultiplicativeMonoid int, float, double, Int, Float, Rational
CommutativeRing<T> Ring (乗法の交換律はマーカー) int, float, double, Int, Float, Rational
IntegralDomain<T> CommutativeRing (ゼロ因子なしはマーカー) int, float, double, Int, Float, Rational
DivisionRing<T> Ring + MultiplicativeGroup (非可換体を含む) float, double, Quaternion<double>, Complex<double>
Field<T> +, -, *, /, 単項-, T(0), T(1) double, float, Float, Rational, Complex<double>
OrderedField<T> Field + <, <=, >, >= double, float, Float, Rational
Scalar<T> Field<T> || std::integral<T> int, double, Float, Rational

unsigned 型に関する注意: unsigned int 等の符号なし整数型は AdditiveMonoid を満たすが、加法逆元 (-a) が数学的に閉じないため AdditiveGroup 以上の代数的構造 (Ring, Field 等) には適合しない。

「マーカー」について: 交換律・完備性・ゼロ因子の不在などの数学的性質はコンパイル時に検証できないため、これらのコンセプトは意図の表明 (マーカー) として機能する。 実行時チェックは行われず、型がその性質を満たすことはユーザーの責任となる。

Ring<T> 適合表

適合備考
int / long long整数環 $\mathbb{Z}$
double / sangi::Float体は環の特殊化
sangi::Rational<T>有理数
sangi::Complex<T>複素数
sangi::Polynomial<T> (既定)多項式環
sangi::Quaternion<T>四元数 (非可換環、 CommutativeRing は不適合)
unsigned int加法逆元が閉じない (AdditiveGroup 不適合)
sangi::Matrix<T>形状が一般に異なるため numeric_traits の特殊化非対応

Field<T> 適合表

適合備考
double / float / long double有限精度の体
sangi::Float多倍長浮動小数点
sangi::Rational<T>有理数体 $\mathbb{Q}$
sangi::Complex<double>複素数体 $\mathbb{C}$
int / long long乗法逆元なし (整域)
sangi::Quaternion<T>非可換 (DivisionRing は適合)
sangi::Polynomial<T>整域だが体ではない (詳細は下記注意)
sangi::Matrix<T>operator/ なし
⚠ 注意 (PolynomialField)

sangi::Polynomial<T>係数 T が体であっても、 多項式環 T[x] 自体は体ではない (一般に乗法逆元が存在しない)。 したがって Field<Polynomial<T>> はビルド設定にかかわらず満たさない。

商体に相当する sangi::RationalFunction<T> (= T[x] の分数体) が体であり、 SANGI_POLY_DIV_RATIONAL 定義時の Polynomial::operator/ はこちらに昇格する。 体の代数演算 (例: safe_inverse) を多項式で行いたい場合は RationalFunction<T> を直接使うのが推奨される。

DivisionRing<T> 適合表

適合備考
double / float / sangi::Float体は除環の特殊化
sangi::Complex<T>複素数体
sangi::Rational<T>有理数体
sangi::Quaternion<T>非可換除環 (Field は不適合だが DivisionRing は満たす)
int乗法逆元なし
sangi::Polynomial<T>整域だが除環ではない

OrderedField<T> 適合表

適合備考
double / float / long double実数の有限精度近似
sangi::Float多倍長実数
sangi::Rational<T>有理数体は順序体
sangi::Complex<T>複素数には自然な全順序が存在しない
sangi::Quaternion<T>非可換かつ順序なし

ベクトル空間

ベクトル空間とその拡張。 スカラー型 S のデフォルトは double

テンプレート引数

引数説明
Vtypenameベクトル型
Stypenameスカラー型 (デフォルト double)
コンセプト要件
VectorSpace<V, S> v + w, v - w, s * v, v * s, -v Vector<double>, std::array<double, N>
InnerProductSpace<V, S> VectorSpace + inner_product(v, w) → S Vector<double> (inner_product 定義時)
NormedVectorSpace<V, S> VectorSpace + norm(v) → S Vector<double> (norm 定義時)
BanachSpace<V, S> NormedVectorSpace (完備性はマーカー — コンパイル時に完備性は検証できないため、意図の表明として機能する。実行時チェックは行われない) $\mathbb{R}^n$, $\ell^p$ 空間
HilbertSpace<V, S> InnerProductSpace (完備性はマーカー — コンパイル時に完備性は検証できないため、意図の表明として機能する。実行時チェックは行われない) $\mathbb{R}^n$, $\ell^2$ 空間
FiniteDimensionalVectorSpace<V, S> VectorSpace + v.size() → size_t Vector<double>

VectorSpace<V, S> 適合表

(V, S)適合備考
(sangi::Vector<double>, double)標準的なベクトル空間
(sangi::Vector<Complex<double>>, Complex<double>)複素ベクトル空間
(std::array<double, N>, double)固定長ベクトル
(sangi::Matrix<double>, double)行列もベクトル空間を成す
(double, double)1 次元ベクトル空間
(sangi::Vector<double>, int)int * Vector<double> の戻り型不一致
(std::string, double)スカラー乗法なし

線形写像

テンプレート引数

引数説明
Ftypename写像オブジェクト型 (関数オブジェクト)
V1typename定義域ベクトル空間
V2typename値域ベクトル空間
Stypename共通スカラー型 (デフォルト double)
コンセプト要件説明
LinearMap<F, V1, V2, S> f(v) → V2, f(v + w) → V2, f(s * v) → V2 $f(\alpha v + \beta w) = \alpha f(v) + \beta f(w)$。V1, V2 は VectorSpace
ConjugateLinearMap<F, V1, V2, S> LinearMap と同じ構文要件 $f(\alpha v) = \bar{\alpha} f(v)$。共役斉次性はコンパイル時検証不可

数値型コンセプト

コンセプト要件
Numeric<T> HasBasicArithmetic + std::abs, std::max, std::min short, int, float, double, unsigned int
IntegerType<T> std::integral<T> && Ring<T>。Ring の要件で numeric_traits の特殊化が必要 int, long longshortnumeric_traits の特殊化がないため不適合。unsigned 型は AdditiveGroup 要件を満たさないため不適合
NonNegativeIntegerType<T> std::unsigned_integral<T> unsigned int, size_t, uint64_t 等。配列 index・サイズ・カウンタなど非負値を保証したい場面で使用。加法逆元が閉じないため Ring 以上には適合しない
FloatingPointType<T> OrderedField<T> && !std::integral<T> float, double, long double, sangi::Float
ComplexType<T> T::value_type, std::real, std::imag, std::abs, std::arg, std::conj std::complex<double>, std::complex<float>
QuaternionType<T> T::value_type, q.w, q.x, q.y, q.z, q.conj(), q.norm(), q.inverse() Quaternion<double>, Quaternion<float>
RationalType<T> Field<T> + r.numerator(), r.denominator() Rational

行列・テンソル

テンプレート引数

引数説明
Mtypename行列型
Vtypenameベクトル型
T / Stypename要素型 (スカラー型)
コンセプト要件説明
MatrixOf<M, T> M::value_type, m(i,j) → T, m.rows(), m.cols() 任意の行列型。traits.hpp で定義
VectorOf<V, T> V::value_type, v[i] → T, v.size() 任意のベクトル型。traits.hpp で定義
SquareMatrixOf<M, T> MatrixOf + m.is_square() 正方行列
SymmetricMatrixOf<M, T> SquareMatrixOf (対称性はマーカー) 対称行列。実行時検証が別途必要
OrthogonalMatrixOf<M, T> SquareMatrixOf (直交性はマーカー) 直交行列 ($M^T M = I$)
TensorOf<T, S> t.rank(), t.shape(i), t.size(), t(i,j) → S 多次元テンソル
SparseMatrixOf<M, T> C++23 MatrixOf + m.non_zeros() 疎行列
BandMatrixOf<M, T> C++23 MatrixOf + m.lower_bandwidth(), m.upper_bandwidth() 帯行列

MatrixOf<M, T> 適合表

(M, T)適合備考
(sangi::Matrix<double>, double)密行列
(sangi::Matrix<Complex<double>>, Complex<double>)複素密行列
(sangi::SparseMatrix<double>, double)疎行列。 SparseMatrixOf も満たす
(sangi::Matrix<double>, float)value_type 不一致
(sangi::Vector<double>, double)operator(i,j) なし
(std::vector<std::vector<double>>, double)rows()/cols()/value_type なし

代数と加群

テンプレート引数

引数説明
Mtypename加群型
Rtypename係数環型
A / Ltypename代数 / リー代数を成すベクトル空間型
Ftypename係数体型
コンセプト要件説明
Module<M, R> AdditiveAbelianGroup<M> + Ring<R> + r * m, m * r 加群 (ベクトル空間の一般化。スカラーが体ではなく環)
Algebra<A, F> VectorSpace<A,F> + Ring<A> + f * (a * b) 代数 (ベクトル空間に乗法構造を追加)
AssociativeAlgebra<A, F> Algebra (結合律はマーカー) 結合代数。行列環など
LieAlgebra<L, F> VectorSpace<L,F> + a * b → L (リー積) リー代数。$\mathfrak{so}(3)$, $\mathfrak{se}(3)$ など

使用例

体で制約された汎用関数

#include <math/concepts/algebraic_concepts.hpp>
using namespace sangi::concepts;

// Field を満たす任意の型で動作する逆元計算
template<Field T>
T safe_inverse(const T& x) {
    if (x == T(0)) return T(0);  // ゼロ除算回避
    return T(1) / x;
}

// double, Float, Rational, Complex<double> で使用可能
auto inv_d = safe_inverse(3.14);
auto inv_r = safe_inverse(Rational(3, 7));
// 実行結果:
//   inv_d = 0.318471337579618
//   inv_r = 7/3
//   safe_inverse(0.0) = 0     (ゼロガード発火)

ベクトル空間のアルゴリズム

// VectorSpace を満たす型に対する線形結合
template<typename V, typename S>
    requires VectorSpace<V, S>
V linear_combination(S a, const V& v, S b, const V& w) {
    return a * v + b * w;
}
// 実行結果:
//   v = {1,2,3}, w = {4,5,6}, a = 2.0, b = 3.0
//   linear_combination = {14, 19, 24}

環の上での多項式評価

// Ring を満たす任意の型に対する Horner 法
template<Ring T>
T horner(const std::vector<T>& coeffs, const T& x) {
    T result = T{0};
    for (auto it = coeffs.rbegin(); it != coeffs.rend(); ++it) {
        result = result * x + *it;
    }
    return result;
}

// int, double, Int, Float, Rational で使用可能
std::vector<double> poly = {1.0, -2.0, 3.0}; // 3x^2 - 2x + 1
double val = horner(poly, 2.0); // = 9.0
// 実行結果: val = 9   (= 3·4 − 2·2 + 1)

四元数型の判定

// QuaternionType と DivisionRing を組み合わせた制約
template<typename T>
    requires QuaternionType<T> && DivisionRing<T>
auto rotation_axis(const T& q) {
    auto v_norm = std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
    return std::make_tuple(q.x / v_norm, q.y / v_norm, q.z / v_norm);
}
// 実行結果:
//   Quaternion(0, 1, 2, 2) → axis = (1/3, 2/3, 2/3)、 |axis| = 1

コンセプトによるオーバーロード

// OrderedField: 比較可能な体 (double, Float, Rational)
template<OrderedField T>
T clamp(const T& x, const T& lo, const T& hi) {
    if (x < lo) return lo;
    if (x > hi) return hi;
    return x;
}

// Field: 比較不可の体も含む (Complex<double>)
template<Field T>
T midpoint(const T& a, const T& b) {
    return (a + b) / T(2);
}
// 実行結果:
//   clamp(2.5, 0, 1)         = 1
//   clamp(-0.3, 0, 1)        = 0
//   midpoint(1.0, 5.0)       = 3
//   midpoint(1+0i, 3+4i)     = 2+2i

コンセプト判定は static_assert サニティチェックで確認できる。