2020-04-05 23:53:27 +08:00
|
|
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
|
|
|
|
|
use num::{One, Zero};
|
|
|
|
|
|
|
|
|
|
use alga::general::{
|
|
|
|
|
AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule,
|
|
|
|
|
AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul,
|
|
|
|
|
ClosedNeg, ComplexField, Field, Identity, JoinSemilattice, Lattice, MeetSemilattice, Module,
|
|
|
|
|
Multiplicative, RingCommutative, TwoSidedInverse,
|
|
|
|
|
};
|
|
|
|
|
use alga::linear::{
|
|
|
|
|
FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use crate::base::allocator::Allocator;
|
|
|
|
|
use crate::base::dimension::{Dim, DimName};
|
|
|
|
|
use crate::base::storage::{Storage, StorageMut};
|
2021-04-11 17:00:38 +08:00
|
|
|
|
use crate::base::{DefaultAllocator, OMatrix, Scalar};
|
2020-04-05 23:53:27 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Additive structures.
|
|
|
|
|
*
|
|
|
|
|
*/
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> Identity<Additive> for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Zero,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn identity() -> Self {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
Self::from_element(T::zero())
|
2020-04-05 23:53:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> AbstractMagma<Additive> for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + ClosedAdd,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn operate(&self, other: &Self) -> Self {
|
|
|
|
|
self + other
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> TwoSidedInverse<Additive> for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + ClosedNeg,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
|
|
|
fn two_sided_inverse(&self) -> Self {
|
|
|
|
|
-self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn two_sided_inverse_mut(&mut self) {
|
|
|
|
|
*self = -self.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! inherit_additive_structure(
|
|
|
|
|
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> $marker<$operator> for OMatrix<T, R, C>
|
|
|
|
|
where T: Scalar + $marker<$operator> $(+ $bounds)*,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C> { }
|
2020-04-05 23:53:27 +08:00
|
|
|
|
)*}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
inherit_additive_structure!(
|
|
|
|
|
AbstractSemigroup<Additive> + ClosedAdd,
|
|
|
|
|
AbstractMonoid<Additive> + Zero + ClosedAdd,
|
|
|
|
|
AbstractQuasigroup<Additive> + ClosedAdd + ClosedNeg,
|
|
|
|
|
AbstractLoop<Additive> + Zero + ClosedAdd + ClosedNeg,
|
|
|
|
|
AbstractGroup<Additive> + Zero + ClosedAdd + ClosedNeg,
|
|
|
|
|
AbstractGroupAbelian<Additive> + Zero + ClosedAdd + ClosedNeg
|
|
|
|
|
);
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> AbstractModule for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + RingCommutative,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
type AbstractRing = T;
|
2020-04-05 23:53:27 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn multiply_by(&self, n: T) -> Self {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self * n
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> Module for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + RingCommutative,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
type Ring = T;
|
2020-04-05 23:53:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> VectorSpace for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Field,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
type Field = T;
|
2020-04-05 23:53:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: DimName, C: DimName> FiniteDimVectorSpace for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Field,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn dimension() -> usize {
|
|
|
|
|
R::dim() * C::dim()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn canonical_basis_element(i: usize) -> Self {
|
|
|
|
|
assert!(i < Self::dimension(), "Index out of bound.");
|
|
|
|
|
|
|
|
|
|
let mut res = Self::zero();
|
|
|
|
|
unsafe {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
*res.data.get_unchecked_linear_mut(i) = T::one();
|
2020-04-05 23:53:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn dot(&self, other: &Self) -> T {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.dot(other)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
unsafe fn component_unchecked(&self, i: usize) -> &T {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.data.get_unchecked_linear(i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut T {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.data.get_unchecked_linear_mut(i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: ComplexField + simba::scalar::ComplexField<RealField = <T as ComplexField>::RealField>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
R: DimName,
|
|
|
|
|
C: DimName,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
> NormedSpace for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
<T as ComplexField>::RealField: simba::scalar::RealField,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
type RealField = <T as ComplexField>::RealField;
|
|
|
|
|
type ComplexField = T;
|
2020-04-05 23:53:27 +08:00
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn norm_squared(&self) -> <T as ComplexField>::RealField {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.norm_squared()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn norm(&self) -> <T as ComplexField>::RealField {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.norm()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
#[must_use = "Did you mean to use normalize_mut()?"]
|
|
|
|
|
fn normalize(&self) -> Self {
|
|
|
|
|
self.normalize()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn normalize_mut(&mut self) -> <T as ComplexField>::RealField {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.normalize_mut()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
#[must_use = "Did you mean to use try_normalize_mut()?"]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn try_normalize(&self, min_norm: <T as ComplexField>::RealField) -> Option<Self> {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.try_normalize(min_norm)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn try_normalize_mut(
|
|
|
|
|
&mut self,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
min_norm: <T as ComplexField>::RealField,
|
|
|
|
|
) -> Option<<T as ComplexField>::RealField> {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.try_normalize_mut(min_norm)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: ComplexField + simba::scalar::ComplexField<RealField = <T as ComplexField>::RealField>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
R: DimName,
|
|
|
|
|
C: DimName,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
> InnerSpace for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
<T as ComplexField>::RealField: simba::scalar::RealField,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn angle(&self, other: &Self) -> <T as ComplexField>::RealField {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.angle(other)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn inner_product(&self, other: &Self) -> T {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
self.dotc(other)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: specialization will greatly simplify this implementation in the future.
|
2020-04-05 23:53:27 +08:00
|
|
|
|
// In particular:
|
|
|
|
|
// − use `x()` instead of `::canonical_basis_element`
|
|
|
|
|
// − use `::new(x, y, z)` instead of `::from_slice`
|
|
|
|
|
impl<
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: ComplexField + simba::scalar::ComplexField<RealField = <T as ComplexField>::RealField>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
R: DimName,
|
|
|
|
|
C: DimName,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
> FiniteDimInnerSpace for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
<T as ComplexField>::RealField: simba::scalar::RealField,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn orthonormalize(vs: &mut [Self]) -> usize {
|
|
|
|
|
let mut nbasis_elements = 0;
|
|
|
|
|
|
|
|
|
|
for i in 0..vs.len() {
|
|
|
|
|
{
|
|
|
|
|
let (elt, basis) = vs[..i + 1].split_last_mut().unwrap();
|
|
|
|
|
|
|
|
|
|
for basis_element in &basis[..nbasis_elements] {
|
|
|
|
|
*elt -= &*basis_element * elt.dot(basis_element)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if vs[i]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
.try_normalize_mut(<T as ComplexField>::RealField::zero())
|
2020-04-05 23:53:27 +08:00
|
|
|
|
.is_some()
|
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: this will be efficient on dynamically-allocated vectors but for
|
2020-04-05 23:53:27 +08:00
|
|
|
|
// statically-allocated ones, `.clone_from` would be better.
|
|
|
|
|
vs.swap(nbasis_elements, i);
|
|
|
|
|
nbasis_elements += 1;
|
|
|
|
|
|
|
|
|
|
// All the other vectors will be dependent.
|
|
|
|
|
if nbasis_elements == Self::dimension() {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nbasis_elements
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn orthonormal_subspace_basis<F>(vs: &[Self], mut f: F)
|
|
|
|
|
where
|
|
|
|
|
F: FnMut(&Self) -> bool,
|
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: is this necessary?
|
2020-04-05 23:53:27 +08:00
|
|
|
|
assert!(
|
|
|
|
|
vs.len() <= Self::dimension(),
|
|
|
|
|
"The given set of vectors has no chance of being a free family."
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
match Self::dimension() {
|
|
|
|
|
1 => {
|
2021-07-04 11:19:07 +08:00
|
|
|
|
if vs.is_empty() {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
let _ = f(&Self::canonical_basis_element(0));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
2 => {
|
2021-07-04 11:19:07 +08:00
|
|
|
|
if vs.is_empty() {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
let _ = f(&Self::canonical_basis_element(0))
|
|
|
|
|
&& f(&Self::canonical_basis_element(1));
|
|
|
|
|
} else if vs.len() == 1 {
|
|
|
|
|
let v = &vs[0];
|
|
|
|
|
let res = Self::from_column_slice(&[-v[1], v[0]]);
|
|
|
|
|
|
|
|
|
|
let _ = f(&res.normalize());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, nothing.
|
|
|
|
|
}
|
|
|
|
|
3 => {
|
2021-07-04 11:19:07 +08:00
|
|
|
|
if vs.is_empty() {
|
2020-04-05 23:53:27 +08:00
|
|
|
|
let _ = f(&Self::canonical_basis_element(0))
|
|
|
|
|
&& f(&Self::canonical_basis_element(1))
|
|
|
|
|
&& f(&Self::canonical_basis_element(2));
|
|
|
|
|
} else if vs.len() == 1 {
|
|
|
|
|
let v = &vs[0];
|
|
|
|
|
let mut a;
|
|
|
|
|
|
|
|
|
|
if ComplexField::norm1(v[0]) > ComplexField::norm1(v[1]) {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
a = Self::from_column_slice(&[v[2], T::zero(), -v[0]]);
|
2020-04-05 23:53:27 +08:00
|
|
|
|
} else {
|
2021-04-11 17:00:38 +08:00
|
|
|
|
a = Self::from_column_slice(&[T::zero(), -v[2], v[1]]);
|
2020-04-05 23:53:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let _ = a.normalize_mut();
|
|
|
|
|
|
|
|
|
|
if f(&a.cross(v)) {
|
|
|
|
|
let _ = f(&a);
|
|
|
|
|
}
|
|
|
|
|
} else if vs.len() == 2 {
|
|
|
|
|
let _ = f(&vs[0].cross(&vs[1]).normalize());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
|
|
|
{
|
|
|
|
|
// XXX: use a GenericArray instead.
|
|
|
|
|
let mut known_basis = Vec::new();
|
|
|
|
|
|
|
|
|
|
for v in vs.iter() {
|
|
|
|
|
known_basis.push(v.normalize())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i in 0..Self::dimension() - vs.len() {
|
|
|
|
|
let mut elt = Self::canonical_basis_element(i);
|
|
|
|
|
|
|
|
|
|
for v in &known_basis {
|
|
|
|
|
elt -= v * elt.dot(v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(subsp_elt) =
|
2021-04-11 17:00:38 +08:00
|
|
|
|
elt.try_normalize(<T as ComplexField>::RealField::zero())
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
if !f(&subsp_elt) {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
known_basis.push(subsp_elt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
|
|
|
|
|
{
|
|
|
|
|
panic!("Cannot compute the orthogonal subspace basis of a vector with a dimension greater than 3 \
|
|
|
|
|
if #![no_std] is enabled and the 'alloc' feature is not enabled.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* Multiplicative structures.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*/
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, D: DimName> Identity<Multiplicative> for OMatrix<T, D, D>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Zero + One,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn identity() -> Self {
|
|
|
|
|
Self::identity()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, D: DimName> AbstractMagma<Multiplicative> for OMatrix<T, D, D>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Zero + One + ClosedAdd + ClosedMul,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn operate(&self, other: &Self) -> Self {
|
|
|
|
|
self * other
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! impl_multiplicative_structure(
|
|
|
|
|
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, D: DimName> $marker<$operator> for OMatrix<T, D, D>
|
|
|
|
|
where T: Scalar + Zero + One + ClosedAdd + ClosedMul + $marker<$operator> $(+ $bounds)*,
|
|
|
|
|
DefaultAllocator: Allocator<T, D, D> { }
|
2020-04-05 23:53:27 +08:00
|
|
|
|
)*}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
impl_multiplicative_structure!(
|
|
|
|
|
AbstractSemigroup<Multiplicative>,
|
|
|
|
|
AbstractMonoid<Multiplicative> + One
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Ordering
|
|
|
|
|
*
|
|
|
|
|
*/
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim> MeetSemilattice for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + MeetSemilattice,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn meet(&self, other: &Self) -> Self {
|
|
|
|
|
self.zip_map(other, |a, b| a.meet(&b))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim> JoinSemilattice for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + JoinSemilattice,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn join(&self, other: &Self) -> Self {
|
|
|
|
|
self.zip_map(other, |a, b| a.join(&b))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim> Lattice for OMatrix<T, R, C>
|
2020-04-05 23:53:27 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
T: Scalar + Lattice,
|
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-05 23:53:27 +08:00
|
|
|
|
{
|
|
|
|
|
#[inline]
|
|
|
|
|
fn meet_join(&self, other: &Self) -> (Self, Self) {
|
|
|
|
|
let shape = self.data.shape();
|
|
|
|
|
assert!(
|
|
|
|
|
shape == other.data.shape(),
|
|
|
|
|
"Matrix meet/join error: mismatched dimensions."
|
|
|
|
|
);
|
|
|
|
|
|
2021-02-25 21:30:04 +08:00
|
|
|
|
let mut mres = unsafe { crate::unimplemented_or_uninitialized_generic!(shape.0, shape.1) };
|
|
|
|
|
let mut jres = unsafe { crate::unimplemented_or_uninitialized_generic!(shape.0, shape.1) };
|
2020-04-05 23:53:27 +08:00
|
|
|
|
|
|
|
|
|
for i in 0..shape.0.value() * shape.1.value() {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mj = self
|
|
|
|
|
.data
|
|
|
|
|
.get_unchecked_linear(i)
|
|
|
|
|
.meet_join(other.data.get_unchecked_linear(i));
|
|
|
|
|
*mres.data.get_unchecked_linear_mut(i) = mj.0;
|
|
|
|
|
*jres.data.get_unchecked_linear_mut(i) = mj.1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(mres, jres)
|
|
|
|
|
}
|
|
|
|
|
}
|