// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // algebraic_concepts.hpp // // Concept definitions for algebraic structures // // This file defines the major concepts of abstract algebra as C++ concepts. // This allows verifying at compile time that a type satisfies the requirements // of a particular algebraic structure (group, ring, field, etc.). // // Supported structures: // - Additive monoid, additive group // - Multiplicative monoid, multiplicative group // - Ring, commutative ring, division ring, field // - Ordered field // - Vector space // - Structural concepts: quaternion type, rational type // - Numeric state management #ifndef SANGI_ALGEBRAIC_CONCEPTS_HPP #define SANGI_ALGEBRAIC_CONCEPTS_HPP #include #include #include #include #include // use concepts from traits.hpp namespace sangi::concepts { //----------------------------------------------------------------------------- // Concepts for basic mathematical operations //----------------------------------------------------------------------------- // A type for which basic mathematical operations are defined template concept HasBasicArithmetic = requires(T a, T b) { { a + b } -> std::convertible_to; { a - b } -> std::convertible_to; { a* b } -> std::convertible_to; { a / b } -> std::convertible_to; { -a } -> std::convertible_to; }; // A type for which comparison operators are defined template concept Comparable = requires(T a, T b) { { a == b } -> std::convertible_to; { a != b } -> std::convertible_to; { a < b } -> std::convertible_to; { a <= b } -> std::convertible_to; { a > b } -> std::convertible_to; { a >= b } -> std::convertible_to; }; // A type that supports equality comparison only template concept EqualityComparable = requires(T a, T b) { { a == b } -> std::convertible_to; { a != b } -> std::convertible_to; }; // A type providing access to mathematical constants (π, e, etc.) template concept HasMathConstants = requires { { T::pi() } -> std::convertible_to; { T::e() } -> std::convertible_to; }; //----------------------------------------------------------------------------- // State management concepts - reuse definitions from traits.hpp //----------------------------------------------------------------------------- // A type capable of detecting and handling numeric states // Already defined in traits.hpp //----------------------------------------------------------------------------- // Concepts for algebraic structures //----------------------------------------------------------------------------- // Additive monoid // Requirements: associativity, identity element (zero) template concept AdditiveMonoid = requires(T a, T b) { { a + b } -> std::convertible_to; // binary operation (closed) { T{ 0 } } -> std::convertible_to; // additive identity // associativity (a + b) + c == a + (b + c) cannot be verified at compile time }; // Additive group // Requirements: additive monoid + inverse element template concept AdditiveGroup = AdditiveMonoid && requires(T a) { { -a } -> std::convertible_to; // additive inverse { a - T{ 0 } } -> std::convertible_to; // subtraction // commutativity a + b == b + a cannot be verified at compile time }; // Additive abelian group (commutative group) // Note: since C++ concepts cannot enforce commutativity, // this is defined as an additional concept that carries the meaning of having commutativity template concept AdditiveAbelianGroup = AdditiveGroup; // Multiplicative monoid // Requirements: associativity, identity element (1) template concept MultiplicativeMonoid = requires(T a, T b) { { a* b } -> std::convertible_to; // binary operation (closed) { T{ 1 } } -> std::convertible_to; // multiplicative identity // associativity (a * b) * c == a * (b * c) cannot be verified at compile time }; // Multiplicative group // Requirements: multiplicative monoid + inverse element template concept MultiplicativeGroup = MultiplicativeMonoid && requires(T a) { { T{ 1 } / a } -> std::convertible_to; // multiplicative inverse // commutativity a * b == b * a cannot be verified at compile time }; // Multiplicative abelian group (commutative group) template concept MultiplicativeAbelianGroup = MultiplicativeGroup; // Ring // Requirements: additive abelian group + multiplicative monoid + distributive law template concept Ring = AdditiveAbelianGroup && MultiplicativeMonoid; // distributive law a * (b + c) == a * b + a * c cannot be verified at compile time // Commutative ring // Requirements: ring + commutativity of multiplication template concept CommutativeRing = Ring; // commutativity of multiplication cannot be verified at compile time, but is conceptually important // Integral domain // Requirements: commutative ring + no zero divisors (ab=0 ⇒ a=0 or b=0) template concept IntegralDomain = CommutativeRing; // the property of having no zero divisors cannot be verified at compile time // Field // Already defined in traits.hpp, so used directly // The corresponding concept is consolidated into one // OrderedField is likewise used directly // Division ring (skew field, Division Ring) // Requirements: ring + every nonzero element has a multiplicative inverse // Difference from a field (Field): does not require commutativity of multiplication // Example: Quaternion (non-commutative); a field is a special case of a division ring template concept DivisionRing = Ring && MultiplicativeGroup; // Scalar field - a general concept representing a type usable as a scalar in code template concept Scalar = Field || std::integral; // Scalar with state management template concept ScalarWithStateManagement = Scalar && HasNumericState; //----------------------------------------------------------------------------- // Vector spaces and their extensions - prefer those already defined in traits.hpp //----------------------------------------------------------------------------- // Inner product space // Requirements: vector space + inner product operation template concept InnerProductSpace = VectorSpace&& requires(V v, V w) { { inner_product(v, w) } -> std::convertible_to; // inner product // properties of the inner product (positive definiteness, linearity, symmetry) cannot be verified at compile time }; // Inner product space with state management template concept InnerProductSpaceWithStateManagement = InnerProductSpace&& HasNumericState&& HasNumericState; // Normed space // Requirements: vector space + norm operation template concept NormedVectorSpace = VectorSpace&& requires(V v) { { norm(v) } -> std::convertible_to; // norm // properties of the norm (non-negativity, homogeneity, triangle inequality) cannot be verified at compile time }; // Normed space with state management template concept NormedVectorSpaceWithStateManagement = NormedVectorSpace&& HasNumericState&& HasNumericState; // Banach space (complete normed space) // Note: since completeness cannot be verified at compile time, // this is used as a conceptual marker template concept BanachSpace = NormedVectorSpace; // Hilbert space (complete inner product space) // Note: since completeness cannot be verified at compile time, // this is used as a conceptual marker template concept HilbertSpace = InnerProductSpace; // Concept of a linear map template concept LinearMap = VectorSpace&& VectorSpace&& requires(F f, V1 v, V1 w, S s) { { f(v) } -> std::convertible_to; { f(v + w) } -> std::convertible_to; // additivity { f(s * v) } -> std::convertible_to; // homogeneity }; // Linear map with state management template concept LinearMapWithStateManagement = LinearMap&& HasNumericState&& HasNumericState&& HasNumericState; // Concept of a conjugate-linear map template concept ConjugateLinearMap = VectorSpace&& VectorSpace&& requires(F f, V1 v, V1 w, S s) { { f(v) } -> std::convertible_to; { f(v + w) } -> std::convertible_to; // additivity { f(s * v) } -> std::convertible_to; // conjugate homogeneity // full verification of conjugate homogeneity is not possible (f(s * v) == conj(s) * f(v) cannot be checked at compile time) }; //----------------------------------------------------------------------------- // Concepts related to numerical computation //----------------------------------------------------------------------------- // A type that supports numerical operations template concept Numeric = HasBasicArithmetic && requires(T a) { { std::abs(a) } -> std::convertible_to; { std::max(a, a) } -> std::convertible_to; { std::min(a, a) } -> std::convertible_to; }; // Numeric type with state management template concept NumericWithState = Numeric && HasNumericState; // Concept for integer types template concept IntegerType = std::integral && Ring; // Concept for non-negative integer types // Used when guaranteeing non-negative values such as array indices, sizes, counters, etc. // unsigned types are not closed under additive inverse, so they do not qualify as a Ring or above. template concept NonNegativeIntegerType = std::unsigned_integral; // Integer type with state management template concept IntegerTypeWithStateManagement = IntegerType && HasNumericState; // Concept for floating-point types // std::floating_point is only float/double/long double, but // to also include multi-precision floats such as sangi::Float, we use OrderedField && !integral template concept FloatingPointType = OrderedField && !std::integral; // Floating-point type with state management template concept FloatingPointTypeWithStateManagement = FloatingPointType && HasNumericState; // Concept for complex number types template concept ComplexType = requires(T a) { typename T::value_type; // type of the real/imaginary parts requires FloatingPointType; { std::real(a) } -> std::convertible_to; { std::imag(a) } -> std::convertible_to; { std::abs(a) } -> std::convertible_to; { std::arg(a) } -> std::convertible_to; { std::conj(a) } -> std::convertible_to; }; // Complex number type with state management template concept ComplexTypeWithStateManagement = ComplexType && HasNumericState; // Concept for quaternion types (structural) // A type with 4 components (w, x, y, z), conjugate, norm, and inverse // Quaternion satisfies DivisionRing but not Field (non-commutative) template concept QuaternionType = requires(T q) { typename T::value_type; // type of the components { q.w } -> std::convertible_to; // scalar part { q.x } -> std::convertible_to; // i component { q.y } -> std::convertible_to; // j component { q.z } -> std::convertible_to; // k component { q.conj() } -> std::convertible_to; // conjugate { q.norm() } -> std::convertible_to; // norm { q.inverse() } -> std::convertible_to; // inverse }; // Concept for rational number types (structural) // A type with access to numerator and denominator // Since Rational satisfies Field → OrderedField → Scalar, // constraining generic algorithms with Field/Scalar is sufficient. // This concept is used when direct access to the numerator and denominator is required. template concept RationalType = Field && requires(T r) { { r.numerator() }; // numerator { r.denominator() }; // denominator }; //----------------------------------------------------------------------------- // Linear algebra concepts - prefer those already defined in traits.hpp //----------------------------------------------------------------------------- // Concept for square matrices template concept SquareMatrixOf = MatrixOf&& requires(M m) { requires m.rows() == m.cols(); { m.is_square() } -> std::convertible_to; }; // Concept for symmetric matrices template concept SymmetricMatrixOf = SquareMatrixOf; // Since the actual check for symmetry cannot be done at compile time, this concept // functions as a marker. Runtime verification is required separately. // Concept for orthogonal matrices template concept OrthogonalMatrixOf = SquareMatrixOf; // Since the actual check for orthogonality (m^T * m = I) cannot be done at compile time, // this concept functions as a marker. // Concept for tensors // A multidimensional array type with rank(), shape(i), size() template concept TensorOf = requires(T t, size_t i, size_t j) { { t.rank() } -> std::convertible_to; // rank { t.shape(i) } -> std::convertible_to; // dimension of each axis { t.size() } -> std::convertible_to; // total number of elements { t(i, j) } -> std::convertible_to; // element access (rank≥2) }; //----------------------------------------------------------------------------- // C++23 extensions (conditionally enabled) //----------------------------------------------------------------------------- #if __cplusplus >= 202302L // Concept of a real field template concept RealField = OrderedField && requires(T a) { { std::sqrt(a) } -> std::convertible_to; { std::abs(a) } -> std::convertible_to; { std::pow(a, a) } -> std::convertible_to; // other operations expected of a real field }; // Real field with state management template concept RealFieldWithStateManagement = RealField && HasNumericState; // Concept of a complex field template concept ComplexField = Field && requires(T a) { typename T::value_type; // type of the real/imaginary parts { std::real(a) } -> std::convertible_to; { std::imag(a) } -> std::convertible_to; { std::abs(a) } -> std::convertible_to; { std::arg(a) } -> std::convertible_to; { std::conj(a) } -> std::convertible_to; // other operations expected of a complex field }; // Complex field with state management template concept ComplexFieldWithStateManagement = ComplexField && HasNumericState; // Real vector space template concept RealVectorSpace = VectorSpace&& RealField; // Real vector space with state management template concept RealVectorSpaceWithStateManagement = RealVectorSpace&& HasNumericState&& HasNumericState; // Complex vector space template concept ComplexVectorSpace = VectorSpace&& ComplexField; // Complex vector space with state management template concept ComplexVectorSpaceWithStateManagement = ComplexVectorSpace&& HasNumericState&& HasNumericState; // Concept for special matrices template concept SparseMatrixOf = MatrixOf&& requires(M m) { { m.non_zeros() } -> std::convertible_to; // number of non-zero elements }; // Concept for band matrices template concept BandMatrixOf = MatrixOf&& requires(M m) { { m.lower_bandwidth() } -> std::convertible_to; { m.upper_bandwidth() } -> std::convertible_to; }; #endif // C++23 support //----------------------------------------------------------------------------- // Additional mathematical concepts //----------------------------------------------------------------------------- // Module - generalization of a vector space template concept Module = AdditiveAbelianGroup && Ring && requires(M m, M n, R r, R s) { { r* m } -> std::convertible_to; // scalar multiplication { m* r } -> std::convertible_to; // scalar multiplication (also possible from the right) // the module axioms cannot be verified at compile time }; // Module with state management template concept ModuleWithStateManagement = Module&& HasNumericState&& HasNumericState; // Algebra - a vector space equipped with a multiplication template concept Algebra = VectorSpace&& Ring&& requires(A a, A b, F f) { { f* (a * b) } -> std::convertible_to; // part of bilinearity // the algebra axioms cannot be verified at compile time }; // Algebra with state management template concept AlgebraWithStateManagement = Algebra&& HasNumericState&& HasNumericState; // Associative algebra - an algebra whose multiplication is associative template concept AssociativeAlgebra = Algebra; // Since associativity cannot be verified at compile time, this concept functions as a marker. // Finite-dimensional vector space // Note: since the actual dimension cannot be checked at compile time, // this is used only as a conceptual marker template concept FiniteDimensionalVectorSpace = VectorSpace&& requires(V v) { { v.size() } -> std::convertible_to; // must have a size method }; // Lie algebra - a non-associative algebra with anticommutativity template concept LieAlgebra = VectorSpace&& requires(L a, L b) { { a* b } -> std::convertible_to; // Lie bracket // anticommutativity and the Jacobi identity cannot be verified at compile time }; //----------------------------------------------------------------------------- // Helper functions and metafunctions - refer to those already defined in traits.hpp //----------------------------------------------------------------------------- // Removed because already defined in traits.hpp: // is_field_v, is_ordered_field_v, is_vector_space_v, is_matrix_of_v, is_vector_of_v // has_numeric_state_management_v, has_divergence_handling_v, has_overflow_detection_v // Duck typing support // Removed because already defined in traits.hpp: // has_addition_v, has_multiplication_v, has_division_v, has_negation_v // has_equality_v, has_comparison_v, has_abs_v, has_sqrt_v // has_is_normal_v, has_is_nan_v, has_is_infinite_v, has_is_divergent_v } // namespace sangi::concepts #endif // SANGI_ALGEBRAIC_CONCEPTS_HPP