nalgebra/base/
constraint.rs

1//! Compatibility constraints between matrix shapes, e.g., for addition or multiplication.
2
3use crate::base::dimension::{Dim, DimName, Dyn};
4
5/// A type used in `where` clauses for enforcing constraints.
6#[derive(Copy, Clone, Debug)]
7pub struct ShapeConstraint;
8
9/// Constrains `C1` and `R2` to be equivalent.
10pub trait AreMultipliable<R1: Dim, C1: Dim, R2: Dim, C2: Dim>: DimEq<C1, R2> {}
11
12impl<R1: Dim, C1: Dim, R2: Dim, C2: Dim> AreMultipliable<R1, C1, R2, C2> for ShapeConstraint where
13    ShapeConstraint: DimEq<C1, R2>
14{
15}
16
17/// Constrains `D1` and `D2` to be equivalent.
18pub trait DimEq<D1: Dim, D2: Dim> {
19    /// This is either equal to `D1` or `D2`, always choosing the one (if any) which is a type-level
20    /// constant.
21    type Representative: Dim;
22
23    /// This constructs a value of type `Representative` with the
24    /// correct value
25    fn representative(d1: D1, d2: D2) -> Option<Self::Representative> {
26        if d1.value() != d2.value() {
27            None
28        } else {
29            Some(Self::Representative::from_usize(d1.value()))
30        }
31    }
32}
33
34impl<D: Dim> DimEq<D, D> for ShapeConstraint {
35    type Representative = D;
36}
37
38impl<D: DimName> DimEq<D, Dyn> for ShapeConstraint {
39    type Representative = D;
40}
41
42impl<D: DimName> DimEq<Dyn, D> for ShapeConstraint {
43    type Representative = D;
44}
45
46macro_rules! equality_trait_decl(
47    ($($doc: expr, $Trait: ident),* $(,)*) => {$(
48        // XXX: we can't do something like `DimEq<D1> for D2` because we would require a blanket impl…
49        #[doc = $doc]
50        pub trait $Trait<D1: Dim, D2: Dim>: DimEq<D1, D2> + DimEq<D2, D1> {
51            /// This is either equal to `D1` or `D2`, always choosing the one (if any) which is a type-level
52            /// constant.
53            type Representative: Dim;
54
55            /// Returns a representative dimension instance if the two are equal,
56            /// otherwise `None`.
57            fn representative(d1: D1, d2: D2) -> Option<<Self as $Trait<D1, D2>>::Representative> {
58                <Self as DimEq<D1, D2>>::representative(d1, d2)
59                    .map(|common_dim| <Self as $Trait<D1, D2>>::Representative::from_usize(common_dim.value()))
60            }
61        }
62
63        impl<D: Dim> $Trait<D, D> for ShapeConstraint {
64            type Representative = D;
65        }
66
67        impl<D: DimName> $Trait<D, Dyn> for ShapeConstraint {
68            type Representative = D;
69        }
70
71        impl<D: DimName> $Trait<Dyn, D> for ShapeConstraint {
72            type Representative = D;
73        }
74    )*}
75);
76
77equality_trait_decl!(
78    "Constrains `D1` and `D2` to be equivalent. \
79     They are both assumed to be the number of \
80     rows of a matrix.",
81    SameNumberOfRows,
82    "Constrains `D1` and `D2` to be equivalent. \
83     They are both assumed to be the number of \
84     columns of a matrix.",
85    SameNumberOfColumns
86);
87
88/// Constrains D1 and D2 to be equivalent, where they both designate dimensions of algebraic
89/// entities (e.g. square matrices).
90pub trait SameDimension<D1: Dim, D2: Dim>:
91    SameNumberOfRows<D1, D2> + SameNumberOfColumns<D1, D2>
92{
93    /// This is either equal to `D1` or `D2`, always choosing the one (if any) which is a type-level
94    /// constant.
95    type Representative: Dim;
96}
97
98impl<D: Dim> SameDimension<D, D> for ShapeConstraint {
99    type Representative = D;
100}
101
102impl<D: DimName> SameDimension<D, Dyn> for ShapeConstraint {
103    type Representative = D;
104}
105
106impl<D: DimName> SameDimension<Dyn, D> for ShapeConstraint {
107    type Representative = D;
108}