pub mod float;
pub mod exact;
#[cfg(test)]
use crate::homomorphism::*;
#[cfg(test)]
use crate::integer::IntegerRing;
#[cfg(test)]
use crate::matrix::*;
#[cfg(test)]
use crate::primitive_int::StaticRing;
#[cfg(test)]
use crate::ring::*;
#[cfg(test)]
use crate::rings::rational::RationalFieldBase;
#[cfg(test)]
use crate::seq::*;
#[cfg(test)]
fn norm_squared<I, V>(ring: I, col: &Column<V, El<I>>) -> El<I>
where
V: AsPointerToSlice<El<I>>,
I: RingStore,
{
<_ as RingStore>::sum(&ring, (0..col.len()).map(|i| ring.mul_ref(col.at(i), col.at(i))))
}
#[cfg(test)]
fn assert_lattice_isomorphic<R, S, V1, V2>(
small_ring: R,
large_ring: S,
lhs: Submatrix<V1, El<R>>,
rhs: Submatrix<V2, El<R>>,
) where
V1: AsPointerToSlice<El<R>>,
V2: AsPointerToSlice<El<R>>,
R: RingStore,
S: RingStore,
S::Type: IntegerRing + CanHomFrom<R::Type>,
{
use std::alloc::Global;
use crate::algorithms::linsolve::smith::solve_right_using_pre_smith;
let n = lhs.row_count();
assert_eq!(n, rhs.row_count());
let hom = large_ring.can_hom(&small_ring).unwrap();
let mut A: OwnedMatrix<_> = OwnedMatrix::zero(n, lhs.col_count(), &large_ring);
let mut B: OwnedMatrix<_> = OwnedMatrix::zero(n, rhs.col_count(), &large_ring);
for i in 0..n {
for j in 0..lhs.col_count() {
*A.at_mut(i, j) = hom.map_ref(lhs.at(i, j));
}
for j in 0..rhs.col_count() {
*B.at_mut(i, j) = hom.map_ref(rhs.at(i, j));
}
}
let mut U: OwnedMatrix<_> = OwnedMatrix::zero(lhs.col_count(), rhs.col_count(), &large_ring);
assert!(
solve_right_using_pre_smith(
&large_ring,
A.clone_matrix(&large_ring).data_mut(),
B.clone_matrix(&large_ring).data_mut(),
U.data_mut(),
Global
)
.is_solved()
);
let mut U: OwnedMatrix<_> = OwnedMatrix::zero(rhs.col_count(), lhs.col_count(), &large_ring);
assert!(
solve_right_using_pre_smith(
&large_ring,
B.clone_matrix(&large_ring).data_mut(),
A.clone_matrix(&large_ring).data_mut(),
U.data_mut(),
Global
)
.is_solved()
);
}
#[cfg(test)]
fn assert_rational_lattice_isomorphic<R, S, I, V1, V2>(
small_ring: R,
large_ring: S,
lhs: Submatrix<V1, El<R>>,
rhs: Submatrix<V2, El<R>>,
) where
V1: AsPointerToSlice<El<R>>,
V2: AsPointerToSlice<El<R>>,
R: RingStore,
S: RingStore<Type = RationalFieldBase<I>>,
S::Type: CanHomFrom<R::Type>,
I: RingStore,
I::Type: IntegerRing,
{
use std::alloc::Global;
use crate::algorithms::eea::signed_lcm;
use crate::algorithms::linsolve::smith::solve_right_using_pre_smith;
use crate::divisibility::DivisibilityRingStore;
let n = lhs.row_count();
assert_eq!(n, rhs.row_count());
let hom = large_ring.can_hom(&small_ring).unwrap();
let den_lcm =
lhs.row_iter()
.chain(rhs.row_iter())
.flat_map(|r| r.iter())
.fold(large_ring.base_ring().one(), |a, b| {
signed_lcm(
a,
large_ring
.base_ring()
.clone_el(large_ring.get_ring().den(&hom.map_ref(b))),
large_ring.base_ring(),
)
});
let mut A: OwnedMatrix<_> = OwnedMatrix::zero(n, lhs.col_count(), large_ring.base_ring());
let mut B: OwnedMatrix<_> = OwnedMatrix::zero(n, rhs.col_count(), large_ring.base_ring());
for i in 0..n {
for j in 0..lhs.col_count() {
let value = large_ring
.inclusion()
.mul_ref_snd_map(hom.map_ref(lhs.at(i, j)), &den_lcm);
*A.at_mut(i, j) = large_ring
.base_ring()
.checked_div(large_ring.get_ring().num(&value), large_ring.get_ring().den(&value))
.unwrap();
}
for j in 0..rhs.col_count() {
let value = large_ring
.inclusion()
.mul_ref_snd_map(hom.map_ref(rhs.at(i, j)), &den_lcm);
*B.at_mut(i, j) = large_ring
.base_ring()
.checked_div(large_ring.get_ring().num(&value), large_ring.get_ring().den(&value))
.unwrap();
}
}
let mut U: OwnedMatrix<_> = OwnedMatrix::zero(lhs.col_count(), rhs.col_count(), large_ring.base_ring());
assert!(
solve_right_using_pre_smith(
large_ring.base_ring(),
A.clone_matrix(large_ring.base_ring()).data_mut(),
B.clone_matrix(large_ring.base_ring()).data_mut(),
U.data_mut(),
Global
)
.is_solved()
);
let mut U: OwnedMatrix<_> = OwnedMatrix::zero(rhs.col_count(), lhs.col_count(), large_ring.base_ring());
assert!(
solve_right_using_pre_smith(
large_ring.base_ring(),
B.clone_matrix(large_ring.base_ring()).data_mut(),
A.clone_matrix(large_ring.base_ring()).data_mut(),
U.data_mut(),
Global
)
.is_solved()
);
}
#[test]
fn test_assert_lattice_isomorphic() {
let ZZ = StaticRing::<i64>::RING;
let lhs = [DerefArray::from([1, 2, 0]), DerefArray::from([1, 2, 4])];
let rhs = [DerefArray::from([1, -2]), DerefArray::from([1, 2])];
assert_lattice_isomorphic(ZZ, ZZ, Submatrix::from_2d(&lhs), Submatrix::from_2d(&rhs));
}
#[test]
#[should_panic]
fn test_assert_lattice_not_isomorphic() {
let ZZ = StaticRing::<i64>::RING;
let lhs = [DerefArray::from([1, 2, 0]), DerefArray::from([1, 3, 4])];
let rhs = [DerefArray::from([1, -2]), DerefArray::from([1, 2])];
assert_lattice_isomorphic(ZZ, ZZ, Submatrix::from_2d(&lhs), Submatrix::from_2d(&rhs));
}