00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_NEW_ALGEBRAIC_CONCEPTS_INCLUDE
00013 #define MTL_NEW_ALGEBRAIC_CONCEPTS_INCLUDE
00014
00015 #include <concepts>
00016 #include <boost/numeric/linear_algebra/intrinsic_concept_maps.hpp>
00017 #include <boost/numeric/linear_algebra/operators.hpp>
00018
00019
00020 namespace math {
00021
00022 concept Commutative<typename Operation, typename Element>
00023 : std::Callable2<Operation, Element, Element>
00024 {
00025 axiom Commutativity(Operation op, Element x, Element y)
00026 {
00027 op(x, y) == op(y, x);
00028 }
00029 };
00030
00031
00032 concept SemiGroup<typename Operation, typename Element>
00033 : std::Callable2<Operation, Element, Element>
00034 {
00035 axiom Associativity(Operation op, Element x, Element y, Element z)
00036 {
00037 op(x, op(y, z)) == op(op(x, y), z);
00038 }
00039 };
00040
00041
00042 concept Monoid<typename Operation, typename Element>
00043 : SemiGroup<Operation, Element>
00044 {
00045 typename identity_result_type;
00046 identity_result_type identity(Operation, Element);
00047
00048 axiom Neutrality(Operation op, Element x)
00049 {
00050 op( x, identity(op, x) ) == x;
00051 op( identity(op, x), x ) == x;
00052 }
00053 };
00054
00055
00056 auto concept Inversion<typename Operation, typename Element>
00057 {
00058 typename result_type;
00059 result_type inverse(Operation, Element);
00060
00061 };
00062
00063
00064 concept PIMonoid<typename Operation, typename Element>
00065 : Monoid<Operation, Element>,
00066 Inversion<Operation, Element>
00067 {
00068 bool is_invertible(Operation, Element);
00069
00070 requires std::Convertible<Inversion<Operation, Element>::result_type, Element>;
00071
00072 axiom Invertibility(Operation op, Element x)
00073 {
00074
00075 if (is_invertible(op, x))
00076 op( x, inverse(op, x) ) == identity(op, x);
00077 if ( is_invertible(op, x) )
00078 op( inverse(op, x), x ) == identity(op, x);
00079 }
00080 }
00081
00082 #if 0
00083
00084
00085 template <typename Operation, typename Element>
00086 requires PIMonoid<Operation, Element>
00087 concept_map PIMonoid<Operation, Inversion<Operation, Element>::result_type> {}
00088 #endif
00089
00090
00091 concept Group<typename Operation, typename Element>
00092 : PIMonoid<Operation, Element>
00093 {
00094 bool is_invertible(Operation, Element) { return true; }
00095
00096
00097 axiom AlwaysInvertible(Operation op, Element x)
00098 {
00099 is_invertible(op, x);
00100 }
00101
00102
00103
00104 axiom GlobalInvertibility(Operation op, Element x)
00105 {
00106 op( x, inverse(op, x) ) == identity(op, x);
00107 op( inverse(op, x), x ) == identity(op, x);
00108 }
00109 };
00110
00111
00112 auto concept AbelianGroup<typename Operation, typename Element>
00113 : Group<Operation, Element>, Commutative<Operation, Element>
00114 {};
00115
00116
00117
00118
00119
00120
00121
00122 concept Additive<typename Element>
00123 : std::HasPlus<Element>
00124 {
00125 typename plus_assign_result_type;
00126 plus_assign_result_type operator+=(Element& x, Element y)
00127 {
00128 x= x + y; return x;
00129 }
00130
00131 requires std::Convertible<plus_assign_result_type, Element&>;
00132
00133
00134
00135
00136
00137
00138 axiom Consistency(add<Element> op, Element x, Element y)
00139 {
00140 op(x, y) == x + y;
00141 op(x, y) == (x += y, x);
00142 }
00143 }
00144
00145
00146 auto concept AdditiveCommutative<typename Element>
00147 : Additive<Element>,
00148 Commutative< add<Element>, Element >
00149 {}
00150
00151
00152 auto concept AdditiveSemiGroup<typename Element>
00153 : Additive<Element>,
00154 SemiGroup< add<Element>, Element >
00155 {}
00156
00157
00158 #ifdef COMPILER_WITHOUT_OVERLOAD_ERROR // Uncompilable due to error in compiler
00159 concept AdditiveMonoid<typename Element>
00160 : AdditiveSemiGroup<Element>,
00161 Monoid< add<Element>, Element >
00162 {
00163 Element zero(Element x)
00164 {
00165 return identity(add<Element>(), x);
00166 }
00167
00168
00169 axiom IdentityConsistency (add<Element> op, Element x)
00170 {
00171 zero(x) == identity(op, x);
00172 }
00173 };
00174
00175 concept AdditivePIMonoid<typename Element>
00176 : std::HasMinus<Element>, AdditiveMonoid<Element>,
00177 PIMonoid< add<Element>, Element >
00178 {
00179 typename minus_assign_result_type;
00180 minus_assign_result_type operator-=(Element& x, Element y)
00181 {
00182 x= x - y; return x;
00183 }
00184
00185 requires std::Convertible<minus_assign_result_type, Element&>;
00186
00187 typename unary_result_type;
00188 unary_result_type operator-(Element x)
00189 {
00190 return zero(x) - x;
00191 }
00192
00193 axiom InverseConsistency(add<Element> op, Element x, Element y)
00194 {
00195
00196 if ( is_invertible(op, y) )
00197 op(x, inverse(op, y)) == x - y;
00198 if ( is_invertible(op, y) )
00199 op(x, y) == (x -= y, x);
00200
00201
00202 if ( is_invertible(op, y) )
00203 inverse(op, y) == -y;
00204
00205
00206 if ( is_invertible(op, x) )
00207 identity(op, x) - x == -x;
00208 }
00209 }
00210
00211
00212 auto concept AdditiveGroup<typename Element>
00213 : AdditivePIMonoid<Element>,
00214 Group< add<Element>, Element >
00215 {};
00216
00217
00218 auto concept AdditiveAbelianGroup<typename Element>
00219 : AdditiveGroup<Element>,
00220 Commutative< add<Element>, Element >
00221 {}
00222
00223 #endif
00224
00225
00226 concept Multiplicative<typename Element>
00227 : std::HasMultiply<Element>
00228 {
00229 typename times_assign_result_type;
00230 times_assign_result_type operator*=(Element& x, Element y)
00231 {
00232 x= x * y; return x;
00233 }
00234
00235 requires std::Convertible<times_assign_result_type, Element&>;
00236
00237
00238
00239
00240
00241
00242 axiom Consistency(mult<Element> op, Element x, Element y)
00243 {
00244 op(x, y) == x * y;
00245 op(x, y) == (x *= y, x);
00246 }
00247 }
00248
00249
00250 auto concept MultiplicativeCommutative<typename Element>
00251 : Multiplicative<Element>,
00252 Commutative< mult<Element>, Element >
00253 {}
00254
00255
00256 auto concept MultiplicativeSemiGroup<typename Element>
00257 : Multiplicative<Element>,
00258 SemiGroup< mult<Element>, Element >
00259 {}
00260
00261
00262 #ifdef COMPILER_WITHOUT_OVERLOAD_ERROR // Uncompilable due to error in compiler
00263 concept MultiplicativeMonoid<typename Element>
00264 : MultiplicativeSemiGroup<Element>,
00265 Monoid< mult<Element>, Element >
00266 {
00267 Element one(Element x)
00268 {
00269 return identity(mult<Element>(), x);
00270 }
00271
00272
00273 axiom IdentityConsistency (math::mult<Element> op, Element x)
00274 {
00275 one(x) == identity(op, x);
00276 }
00277 };
00278
00279 concept MultiplicativePIMonoid<typename Element>
00280 : std::HasDivide<Element>, MultiplicativeMonoid<Element>,
00281 PIMonoid< mult<Element>, Element >
00282 {
00283 typename divide_assign_result_type;
00284 divide_assign_result_type operator/=(Element& x, Element y)
00285 {
00286 x= x / y; return x;
00287 }
00288
00289 requires std::Convertible<divide_assign_result_type, Element&>;
00290
00291 axiom InverseConsistency(mult<Element> op, Element x, Element y)
00292 {
00293
00294 if ( is_invertible(op, y) )
00295 op(x, inverse(op, y)) == x / y;
00296 if ( is_invertible(op, y) )
00297 op(x, y) == (x /= y, x);
00298 }
00299 }
00300
00301
00302 auto concept MultiplicativeGroup<typename Element>
00303 : MultiplicativePIMonoid<Element>,
00304 Group< mult<Element>, Element >
00305 {};
00306
00307
00308 auto concept MultiplicativeAbelianGroup<typename Element>
00309 : MultiplicativeGroup<Element>,
00310 Commutative< mult<Element>, Element >
00311 {}
00312
00313
00314
00315
00316
00317
00318
00319
00320 concept Distributive<typename AddOp, typename MultOp, typename Element>
00321 {
00322 axiom Distributivity(AddOp add, MultOp mult, Element x, Element y, Element z)
00323 {
00324
00325 mult(x, add(y, z)) == add(mult(x, y), mult(x, z));
00326
00327 mult(add(x, y), z) == add(mult(x, z), mult(y, z));
00328 }
00329 }
00330
00331
00332 auto concept Ring<typename AddOp, typename MultOp, typename Element>
00333 : AbelianGroup<AddOp, Element>,
00334 SemiGroup<MultOp, Element>,
00335 Distributive<AddOp, MultOp, Element>
00336 {}
00337
00338
00339 auto concept RingWithIdentity<typename AddOp, typename MultOp, typename Element>
00340 : Ring<AddOp, MultOp, Element>,
00341 Monoid<MultOp, Element>
00342 {}
00343
00344
00345 concept DivisionRing<typename AddOp, typename MultOp, typename Element>
00346 : RingWithIdentity<AddOp, MultOp, Element>,
00347 Inversion<MultOp, Element>
00348 {
00349
00350 axiom ZeroIsDifferentFromOne(AddOp add, MultOp mult, Element x)
00351 {
00352 identity(add, x) != identity(mult, x);
00353 }
00354
00355
00356 axiom NonZeroDivisibility(AddOp add, MultOp mult, Element x)
00357 {
00358 if (x != identity(add, x))
00359 mult(inverse(mult, x), x) == identity(mult, x);
00360 if (x != identity(add, x))
00361 mult(x, inverse(mult, x)) == identity(mult, x);
00362 }
00363 }
00364
00365
00366 auto concept Field<typename AddOp, typename MultOp, typename Element>
00367 : DivisionRing<AddOp, MultOp, Element>,
00368 Commutative<MultOp, Element>
00369 {}
00370
00371
00372 auto concept OperatorRing<typename Element>
00373 : AdditiveAbelianGroup<Element>,
00374 MultiplicativeSemiGroup<Element>,
00375 Ring<add<Element>, mult<Element>, Element>
00376 {}
00377
00378
00379 auto concept OperatorRingWithIdentity<typename Element>
00380 : OperatorRing<Element>,
00381 MultiplicativeMonoid<Element>,
00382 RingWithIdentity<add<Element>, mult<Element>, Element>
00383 {}
00384
00385
00386 auto concept OperatorDivisionRing<typename Element>
00387 : OperatorRingWithIdentity<Element>,
00388 MultiplicativePIMonoid<Element>,
00389 DivisionRing<add<Element>, mult<Element>, Element>
00390 {}
00391
00392
00393 auto concept OperatorField<typename Element>
00394 : OperatorDivisionRing<Element>,
00395 Field<add<Element>, mult<Element>, Element>
00396 {}
00397
00398
00399
00400 #endif
00401
00402 concept IntrinsicType<typename T> {}
00403
00404 concept IntrinsicArithmetic<typename T> : IntrinsicType<T> {}
00405
00406 concept IntrinsicIntegral<typename T> : IntrinsicArithmetic<T> {}
00407
00408 concept IntrinsicSignedIntegral<typename T>
00409 : std::SignedIntegralLike<T>,
00410 IntrinsicIntegral<T>
00411 {}
00412
00413 concept IntrinsicUnsignedIntegral<typename T>
00414 : std::UnsignedIntegralLike<T>,
00415 IntrinsicIntegral<T>
00416 {}
00417
00418 concept IntrinsicFloatingPoint<typename T>
00419 : std::FloatingPointLike<T>,
00420 IntrinsicArithmetic<T>
00421 {}
00422
00423
00424
00425
00426 #if 0
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 template <typename T>
00441 requires IntrinsicSignedIntegral<T>
00442 concept_map OperatorRingWithIdentity<T> {}
00443
00444 template <typename T>
00445 requires IntrinsicSignedIntegral<T>
00446 concept_map MultiplicativeCommutative<T> {}
00447
00448
00449
00450
00451
00452
00453 template <typename T>
00454 requires IntrinsicUnsignedIntegral<T>
00455 concept_map AdditiveCommutative<T> {}
00456
00457 template <typename T>
00458 requires IntrinsicUnsignedIntegral<T>
00459 concept_map AdditiveMonoid<T> {}
00460
00461 template <typename T>
00462 requires IntrinsicUnsignedIntegral<T>
00463 concept_map MultiplicativeCommutative<T> {}
00464
00465 template <typename T>
00466 requires IntrinsicUnsignedIntegral<T>
00467 concept_map MultiplicativeMonoid<T> {}
00468
00469
00470
00471
00472
00473
00474 template <typename T>
00475 requires IntrinsicFloatingPoint<T>
00476 concept_map Field<T> {}
00477
00478 template <typename T>
00479 requires IntrinsicFloatingPoint<T>
00480 concept_map Field< std::complex<T> > {}
00481
00482
00483
00484
00485
00486
00487
00488 template <typename T>
00489 requires IntrinsicArithmetic<T>
00490 concept_map Commutative< max<T>, T > {}
00491
00492 template <typename T>
00493 requires IntrinsicArithmetic<T>
00494 concept_map Monoid< max<T>, T > {}
00495
00496 template <typename T>
00497 requires IntrinsicArithmetic<T>
00498 concept_map Commutative< min<T>, T > {}
00499
00500 template <typename T>
00501 requires IntrinsicArithmetic<T>
00502 concept_map Monoid< min<T>, T > {}
00503
00504
00505
00506
00507
00508
00509 template <typename T>
00510 requires Intrinsic<T> && std::HasLogicalAnd<T>
00511 concept_map Commutative< std::logical_and<T>, T > {}
00512
00513 template <typename T>
00514 requires Intrinsic<T> && std::HasLogicalAnd<T>
00515 concept_map Monoid< std::logical_and<T>, T > {}
00516
00517 template <typename T>
00518 requires Intrinsic<T> && std::HasLogicalOr<T>
00519 concept_map Commutative< std::logical_or<T>, T > {}
00520
00521 template <typename T>
00522 requires Intrinsic<T> && std::HasLogicalOr<T>
00523 concept_map Monoid< std::logical_or<T>, T > {}
00524
00525 template <typename T>
00526 requires Intrinsic<T> && std::HasLogicalAnd<T> && std::HasLogicalOr<T>
00527 concept_map Distributive<std::logical_and<T>, std::logical_or<T>, T> {}
00528
00529 template <typename T>
00530 requires Intrinsic<T> && std::HasLogicalAnd<T> && std::HasLogicalOr<T>
00531 concept_map Distributive<std::logical_or<T>, std::logical_and<T>, T> {}
00532
00533
00534
00535
00536
00537
00538
00539
00540 template <typename T>
00541 requires IntrinsicIntegral<T>
00542 concept_map Commutative< bit_and<T>, T > {}
00543
00544 template <typename T>
00545 requires IntrinsicIntegral<T>
00546 concept_map Monoid< bit_and<T>, T > {}
00547
00548 template <typename T>
00549 requires IntrinsicIntegral<T>
00550 concept_map Commutative< bit_or<T>, T > {}
00551
00552 template <typename T>
00553 requires IntrinsicIntegral<T>
00554 concept_map Monoid< bit_or<T>, T > {}
00555
00556 template <typename T>
00557 requires IntrinsicIntegral<T>
00558 concept_map Distributive<bit_and<T>, bit_or<T>, T> {}
00559
00560 template <typename T>
00561 requires IntrinsicIntegral<T>
00562 concept_map Distributive<bit_or<T>, bit_and<T>, T> {}
00563
00564 template <typename T>
00565 requires IntrinsicIntegral<T>
00566 concept_map Commutative< bit_xor<T>, T > {}
00567
00568 template <typename T>
00569 requires IntrinsicIntegral<T>
00570 concept_map SemiGroup< bit_xor<T>, T > {}
00571
00572
00573
00574
00575
00576 concept_map AdditiveMonoid<std::string> {}
00577
00578
00579 #endif
00580
00581
00582
00583 }
00584
00585 #endif // MTL_NEW_ALGEBRAIC_CONCEPTS_INCLUDE