use std::alloc::{Allocator, Global};
use super::convolution::ConvolutionAlgorithm;
use crate::divisibility::DivisibilityRing;
use crate::matrix::{AsPointerToSlice, SubmatrixMut};
use crate::pid::PrincipalIdealRing;
use crate::ring::*;
use crate::rings::extension::extension_impl::FreeAlgebraImplBase;
use crate::seq::VectorView;
pub mod extension;
pub mod gauss;
pub mod smith;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum SolveResult {
FoundSomeSolution,
FoundUniqueSolution,
NoSolution,
}
impl SolveResult {
pub fn is_solved(&self) -> bool {
match self {
Self::FoundSomeSolution | Self::FoundUniqueSolution => true,
Self::NoSolution => false,
}
}
pub fn assert_solved(&self) {
assert!(self.is_solved());
}
}
pub trait LinSolveRing: DivisibilityRing {
fn solve_right<V1, V2, V3, A>(
&self,
lhs: SubmatrixMut<V1, Self::Element>,
rhs: SubmatrixMut<V2, Self::Element>,
out: SubmatrixMut<V3, Self::Element>,
allocator: A,
) -> SolveResult
where
V1: AsPointerToSlice<Self::Element>,
V2: AsPointerToSlice<Self::Element>,
V3: AsPointerToSlice<Self::Element>,
A: Allocator;
}
pub trait LinSolveRingStore: RingStore
where
Self::Type: LinSolveRing,
{
fn solve_right<V1, V2, V3>(
&self,
lhs: SubmatrixMut<V1, El<Self>>,
rhs: SubmatrixMut<V2, El<Self>>,
out: SubmatrixMut<V3, El<Self>>,
) -> SolveResult
where
V1: AsPointerToSlice<El<Self>>,
V2: AsPointerToSlice<El<Self>>,
V3: AsPointerToSlice<El<Self>>,
{
self.get_ring().solve_right(lhs, rhs, out, Global)
}
#[stability::unstable(feature = "enable")]
fn solve_right_with<V1, V2, V3, A>(
&self,
lhs: SubmatrixMut<V1, El<Self>>,
rhs: SubmatrixMut<V2, El<Self>>,
out: SubmatrixMut<V3, El<Self>>,
allocator: A,
) -> SolveResult
where
V1: AsPointerToSlice<El<Self>>,
V2: AsPointerToSlice<El<Self>>,
V3: AsPointerToSlice<El<Self>>,
A: Allocator,
{
self.get_ring().solve_right(lhs, rhs, out, allocator)
}
}
impl<R> LinSolveRingStore for R
where
R: RingStore,
R::Type: LinSolveRing,
{
}
impl<R: ?Sized + PrincipalIdealRing> LinSolveRing for R {
default fn solve_right<V1, V2, V3, A>(
&self,
lhs: SubmatrixMut<V1, Self::Element>,
rhs: SubmatrixMut<V2, Self::Element>,
out: SubmatrixMut<V3, Self::Element>,
allocator: A,
) -> SolveResult
where
V1: AsPointerToSlice<Self::Element>,
V2: AsPointerToSlice<Self::Element>,
V3: AsPointerToSlice<Self::Element>,
A: Allocator,
{
smith::solve_right_using_pre_smith(RingRef::new(self), lhs, rhs, out, allocator)
}
}
impl<R, V, A_ring, C_ring> LinSolveRing for FreeAlgebraImplBase<R, V, A_ring, C_ring>
where
R: RingStore,
R::Type: LinSolveRing,
V: VectorView<El<R>>,
A_ring: Allocator + Clone,
C_ring: ConvolutionAlgorithm<R::Type>,
{
fn solve_right<V1, V2, V3, A>(
&self,
lhs: SubmatrixMut<V1, Self::Element>,
rhs: SubmatrixMut<V2, Self::Element>,
out: SubmatrixMut<V3, Self::Element>,
allocator: A,
) -> SolveResult
where
V1: AsPointerToSlice<Self::Element>,
V2: AsPointerToSlice<Self::Element>,
V3: AsPointerToSlice<Self::Element>,
A: Allocator,
{
extension::solve_right_over_extension(RingRef::new(self), lhs, rhs, out, allocator)
}
}