use extended_matrix_float::MyFloatTrait;
use crate::FloatTrait;
use crate::{BasicOperationsTrait, Position, SquareMatrixTrait};
pub trait TryIntoSymmetricCompactedMatrixTrait: SquareMatrixTrait {
fn try_into_symmetric_compacted_matrix(
&self,
rel_tol: <Self as BasicOperationsTrait>::Value,
) -> Result<(Vec<<Self as BasicOperationsTrait>::Value>, Vec<i64>), String>
where
<Self as BasicOperationsTrait>::Value:
FloatTrait<Output = <Self as BasicOperationsTrait>::Value>,
{
let shape = self.get_shape();
let mut a = Vec::new();
let mut maxa = Vec::new();
let mut index = 0i64;
for column in 0..shape.1 {
if *self
.get_element_value(&Position(column, column))
.expect("Element is absent")
== <<Self as BasicOperationsTrait>::Value>::from(0f32)
{
return Err(format!(
"Diagonal element [{}, {}] equals to zero!",
column, column
));
}
let mut skyline = 0;
'skyline: while skyline < column {
if *self
.get_element_value(&Position(skyline, column))
.expect("Element is absent")
!= <<Self as BasicOperationsTrait>::Value>::from(0f32)
{
break 'skyline;
}
skyline += 1;
}
let mut row = column;
maxa.push(index);
index += 1;
if row > 0 {
while row > skyline {
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
return Err(format!(
"Element [{row}, {column}] does not match with \
[{column}, {row}]!"
));
}
a.push(value);
row -= 1;
if row != column {
index += 1;
}
}
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
return Err(format!(
"Element [{row}, {column}] does not match with \
[{column}, {row}]!"
));
}
a.push(value);
} else {
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
return Err(format!(
"Element [{row}, {column}] does not match with \
[{column}, {row}]!"
));
}
a.push(value);
}
}
maxa.push(index);
Ok((a, maxa))
}
fn forced_into_symmetric_compacted_matrix(
&self,
rel_tol: <Self as BasicOperationsTrait>::Value,
warnings: &mut Vec<Vec<(Position, <Self as BasicOperationsTrait>::Value)>>,
) -> (Vec<<Self as BasicOperationsTrait>::Value>, Vec<i64>)
where
<Self as BasicOperationsTrait>::Value:
FloatTrait<Output = <Self as BasicOperationsTrait>::Value>,
{
let shape = self.get_shape();
let mut a = Vec::new();
let mut maxa = Vec::new();
let mut index = 0i64;
for column in 0..shape.1 {
if *self
.get_element_value(&Position(column, column))
.expect("Element is absent")
== <<Self as BasicOperationsTrait>::Value>::from(0f32)
{
let warning = vec![(
Position(column, column),
<<Self as BasicOperationsTrait>::Value>::from(0f32),
)];
warnings.push(warning);
}
let mut skyline = 0;
'skyline: while skyline < column {
if *self
.get_element_value(&Position(skyline, column))
.expect("Element is absent")
!= <<Self as BasicOperationsTrait>::Value>::from(0f32)
{
break 'skyline;
}
skyline += 1;
}
let mut row = column;
maxa.push(index);
index += 1;
if row > 0 {
while row > skyline {
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
let warning = vec![
(Position(row, column), value),
(Position(column, row), symm_value),
];
warnings.push(warning);
}
a.push(value);
row -= 1;
if row != column {
index += 1;
}
}
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
let warning = vec![
(Position(row, column), value),
(Position(column, row), symm_value),
];
warnings.push(warning);
}
a.push(value);
} else {
let value = *self
.get_element_value(&Position(row, column))
.expect("Element is absent");
let symm_value = *self
.get_element_value(&Position(column, row))
.expect("Element is absent");
if (<<Self as BasicOperationsTrait>::Value>::from(1f32) - value / symm_value)
.my_abs()
> rel_tol
{
let warning = vec![
(Position(row, column), value),
(Position(column, row), symm_value),
];
warnings.push(warning);
}
a.push(value);
}
}
maxa.push(index);
(a, maxa)
}
}