feanor_math/algorithms/linsolve/
mod.rs1use std::alloc::{Allocator, Global};
2
3use super::convolution::ConvolutionAlgorithm;
4use crate::divisibility::DivisibilityRing;
5use crate::matrix::{AsPointerToSlice, SubmatrixMut};
6use crate::pid::PrincipalIdealRing;
7use crate::ring::*;
8use crate::rings::extension::extension_impl::FreeAlgebraImplBase;
9use crate::seq::VectorView;
10
11pub mod extension;
13pub mod gauss;
16pub mod smith;
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub enum SolveResult {
29 FoundSomeSolution,
32 FoundUniqueSolution,
34 NoSolution,
37}
38
39impl SolveResult {
40 pub fn is_solved(&self) -> bool {
42 match self {
43 Self::FoundSomeSolution | Self::FoundUniqueSolution => true,
44 Self::NoSolution => false,
45 }
46 }
47
48 pub fn assert_solved(&self) {
50 assert!(self.is_solved());
51 }
52}
53
54pub trait LinSolveRing: DivisibilityRing {
56 fn solve_right<V1, V2, V3, A>(
67 &self,
68 lhs: SubmatrixMut<V1, Self::Element>,
69 rhs: SubmatrixMut<V2, Self::Element>,
70 out: SubmatrixMut<V3, Self::Element>,
71 allocator: A,
72 ) -> SolveResult
73 where
74 V1: AsPointerToSlice<Self::Element>,
75 V2: AsPointerToSlice<Self::Element>,
76 V3: AsPointerToSlice<Self::Element>,
77 A: Allocator;
78}
79
80pub trait LinSolveRingStore: RingStore
82where
83 Self::Type: LinSolveRing,
84{
85 fn solve_right<V1, V2, V3>(
89 &self,
90 lhs: SubmatrixMut<V1, El<Self>>,
91 rhs: SubmatrixMut<V2, El<Self>>,
92 out: SubmatrixMut<V3, El<Self>>,
93 ) -> SolveResult
94 where
95 V1: AsPointerToSlice<El<Self>>,
96 V2: AsPointerToSlice<El<Self>>,
97 V3: AsPointerToSlice<El<Self>>,
98 {
99 self.get_ring().solve_right(lhs, rhs, out, Global)
100 }
101
102 #[stability::unstable(feature = "enable")]
106 fn solve_right_with<V1, V2, V3, A>(
107 &self,
108 lhs: SubmatrixMut<V1, El<Self>>,
109 rhs: SubmatrixMut<V2, El<Self>>,
110 out: SubmatrixMut<V3, El<Self>>,
111 allocator: A,
112 ) -> SolveResult
113 where
114 V1: AsPointerToSlice<El<Self>>,
115 V2: AsPointerToSlice<El<Self>>,
116 V3: AsPointerToSlice<El<Self>>,
117 A: Allocator,
118 {
119 self.get_ring().solve_right(lhs, rhs, out, allocator)
120 }
121}
122
123impl<R> LinSolveRingStore for R
124where
125 R: RingStore,
126 R::Type: LinSolveRing,
127{
128}
129
130impl<R: ?Sized + PrincipalIdealRing> LinSolveRing for R {
131 default fn solve_right<V1, V2, V3, A>(
132 &self,
133 lhs: SubmatrixMut<V1, Self::Element>,
134 rhs: SubmatrixMut<V2, Self::Element>,
135 out: SubmatrixMut<V3, Self::Element>,
136 allocator: A,
137 ) -> SolveResult
138 where
139 V1: AsPointerToSlice<Self::Element>,
140 V2: AsPointerToSlice<Self::Element>,
141 V3: AsPointerToSlice<Self::Element>,
142 A: Allocator,
143 {
144 smith::solve_right_using_pre_smith(RingRef::new(self), lhs, rhs, out, allocator)
145 }
146}
147
148impl<R, V, A_ring, C_ring> LinSolveRing for FreeAlgebraImplBase<R, V, A_ring, C_ring>
149where
150 R: RingStore,
151 R::Type: LinSolveRing,
152 V: VectorView<El<R>>,
153 A_ring: Allocator + Clone,
154 C_ring: ConvolutionAlgorithm<R::Type>,
155{
156 fn solve_right<V1, V2, V3, A>(
157 &self,
158 lhs: SubmatrixMut<V1, Self::Element>,
159 rhs: SubmatrixMut<V2, Self::Element>,
160 out: SubmatrixMut<V3, Self::Element>,
161 allocator: A,
162 ) -> SolveResult
163 where
164 V1: AsPointerToSlice<Self::Element>,
165 V2: AsPointerToSlice<Self::Element>,
166 V3: AsPointerToSlice<Self::Element>,
167 A: Allocator,
168 {
169 extension::solve_right_over_extension(RingRef::new(self), lhs, rhs, out, allocator)
170 }
171}