use crate::{add, multiply, scpmat, scxmat};
use std::fmt;
use std::fs::File;
use std::io::{BufRead, BufReader, Write};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait Zero {
fn zero() -> Self;
}
impl Zero for i8 {
fn zero() -> Self {
0
}
}
impl Zero for i16 {
fn zero() -> Self {
0
}
}
impl Zero for i32 {
fn zero() -> Self {
0
}
}
impl Zero for i64 {
fn zero() -> Self {
0
}
}
impl Zero for isize {
fn zero() -> Self {
0
}
}
impl Zero for f32 {
fn zero() -> Self {
0.0
}
}
impl Zero for f64 {
fn zero() -> Self {
0.0
}
}
pub trait One {
fn one() -> Self;
}
impl One for i8 {
fn one() -> Self {
1
}
}
impl One for i16 {
fn one() -> Self {
1
}
}
impl One for i32 {
fn one() -> Self {
1
}
}
impl One for i64 {
fn one() -> Self {
1
}
}
impl One for isize {
fn one() -> Self {
1
}
}
impl One for f32 {
fn one() -> Self {
1.0
}
}
impl One for f64 {
fn one() -> Self {
1.0
}
}
pub trait Numeric<F>:
Add
+ AddAssign
+ Sub
+ SubAssign
+ Neg
+ Mul
+ MulAssign
+ Div
+ DivAssign
+ Copy
+ PartialEq
+ PartialOrd
+ Default
+ Zero
+ One
+ Add<Output = F>
+ Sub<Output = F>
+ Mul<Output = F>
+ Div<Output = F>
+ Neg<Output = F>
+ std::iter::Sum
+ fmt::Display
+ fmt::Debug
+ From<F>
{
fn abs(self) -> F;
fn max(self, other: F) -> F;
fn powf(self, exp: f64) -> F;
fn sqrt(self) -> F;
}
impl Numeric<f32> for f32 {
fn abs(self) -> f32 {
self.abs()
}
fn max(self, other: f32) -> f32 {
self.max(other)
}
fn powf(self, exp: f64) -> f32 {
self.powf(exp as f32)
}
fn sqrt(self) -> f32 {
self.sqrt()
}
}
impl Numeric<f64> for f64 {
fn abs(self) -> f64 {
self.abs()
}
fn max(self, other: f64) -> f64 {
self.max(other)
}
fn powf(self, exp: f64) -> f64 {
self.powf(exp)
}
fn sqrt(self) -> f64 {
self.sqrt()
}
}
fn cumsum(p: &mut [isize], c: &mut [isize], n: usize) -> usize {
let mut nz = 0;
for (p_i, c_i) in p.iter_mut().zip(c.iter_mut()).take(n) {
*p_i = nz;
nz += *c_i;
*c_i = *p_i;
}
p[n] = nz;
nz as usize
}
#[derive(Clone, Debug)]
pub struct Sprs<T: Numeric<T>> {
pub nzmax: usize,
pub m: usize,
pub n: usize,
pub p: Vec<isize>,
pub i: Vec<usize>,
pub x: Vec<T>,
}
impl<T: Numeric<T>> Sprs<T> {
pub fn new() -> Sprs<T> {
Sprs {
nzmax: 0,
m: 0,
n: 0,
p: Vec::new(),
i: Vec::new(),
x: Vec::new(),
}
}
pub fn zeros(m: usize, n: usize, nzmax: usize) -> Sprs<T> {
Sprs {
nzmax,
m,
n,
p: vec![0; n + 1],
i: vec![0; nzmax],
x: vec![T::zero(); nzmax],
}
}
pub fn eye(n: usize) -> Sprs<T> {
let mut s = Sprs::zeros(n, n, n);
for i in 0..n {
s.p[i] = i as isize;
s.i[i] = i;
s.x[i] = T::one();
}
s.p[n] = n as isize;
s
}
pub fn new_from_vec(t: &[Vec<T>]) -> Sprs<T> {
let mut s = Sprs::new();
s.from_vec(t);
s
}
pub fn new_from_trpl(t: &Trpl<T>) -> Sprs<T> {
let mut s = Sprs::new();
s.from_trpl(t);
s
}
pub fn get(&self, row: usize, column: usize) -> Option<T> {
for j in 0..self.p.len() - 1 {
for i in self.p[j]..self.p[j + 1] {
if (self.i[i as usize], j) == (row, column) {
return Some(self.x[i as usize]);
}
}
}
None
}
pub fn from_vec(&mut self, a: &[Vec<T>]) {
let r = a.len(); let c = a[0].len(); let mut idxptr = 0;
self.nzmax = r * c;
self.m = r;
self.n = c;
self.p = Vec::new();
self.i = Vec::new();
self.x = Vec::new();
for i in 0..c {
self.p.push(idxptr);
for (j, aj) in a.iter().enumerate().take(r) {
let elem = aj[i];
if elem != T::zero() {
self.x.push(elem);
self.i.push(j);
idxptr += 1
}
}
}
self.p.push(idxptr);
self.trim();
}
pub fn from_trpl(&mut self, t: &Trpl<T>) {
self.nzmax = t.x.len();
self.m = t.m;
self.n = t.n;
self.p = vec![0; t.n + 1];
self.i = vec![0; t.x.len()];
self.x = vec![T::zero(); t.x.len()];
let mut w = vec![0; self.n];
for k in 0..t.p.len() {
w[t.p[k] as usize] += 1; }
cumsum(&mut self.p[..], &mut w[..], self.n); let mut p;
for k in 0..t.p.len() {
p = w[t.p[k] as usize] as usize;
self.i[p] = t.i[k]; w[t.p[k] as usize] += 1;
self.x[p] = t.x[k];
}
}
pub fn trim(&mut self) {
for i in (0..self.x.len()).rev() {
if self.x[i] == T::zero() {
self.x.remove(i);
self.i.remove(i);
for j in (0..self.p.len()).rev() {
if (i as isize) < self.p[j] {
self.p[j] -= 1;
} else {
break;
}
}
}
}
self.nzmax = self.x.len();
}
pub fn quick_trim(&mut self) {
self.nzmax = self.p[self.n] as usize;
self.i.resize(self.nzmax, 0);
self.x.resize(self.nzmax, T::zero());
}
pub fn to_dense(&self) -> Vec<Vec<T>> {
let mut r = vec![vec![T::zero(); self.n]; self.m];
for j in 0..self.p.len() - 1 {
for i in self.p[j]..self.p[j + 1] {
r[self.i[i as usize]][j] = self.x[i as usize];
}
}
r
}
pub fn save(&self, path: &str) -> Result<(), std::io::Error> {
let mut f = File::create(path)?;
writeln!(f, "nzmax: {}", self.nzmax)?;
writeln!(f, "m: {}", self.m)?;
writeln!(f, "n: {}", self.n)?;
writeln!(f, "p: {:?}", self.p)?;
writeln!(f, "i: {:?}", self.i)?;
writeln!(f, "x: {:?}", self.x)?;
Ok(())
}
}
impl<T: Numeric<T> + std::str::FromStr> Sprs<T> {
pub fn load(&mut self, path: &str) -> Result<(), Box<dyn std::error::Error>>
where
<T as std::str::FromStr>::Err: std::error::Error,
<T as std::str::FromStr>::Err: 'static,
{
let f = File::open(path)?;
let reader = BufReader::new(f);
for line in reader.lines() {
let line_read = line?;
if line_read.contains("nzmax:") {
self.nzmax = (line_read.split(':').collect::<Vec<&str>>()[1].replace(' ', ""))
.parse::<usize>()?;
if self.nzmax == 0 {
self.nzmax = 0;
self.m = 0;
self.n = 0;
self.p = Vec::new();
self.i = Vec::new();
self.x = Vec::new();
return Ok(());
}
} else if line_read.contains("m:") {
self.m = (line_read.split(':').collect::<Vec<&str>>()[1].replace(' ', ""))
.parse::<usize>()?;
if self.m == 0 {
self.nzmax = 0;
self.m = 0;
self.n = 0;
self.p = Vec::new();
self.i = Vec::new();
self.x = Vec::new();
return Ok(());
}
} else if line_read.contains("n:") {
self.n = (line_read.split(':').collect::<Vec<&str>>()[1].replace(' ', ""))
.parse::<usize>()?;
if self.n == 0 {
self.nzmax = 0;
self.m = 0;
self.n = 0;
self.p = Vec::new();
self.i = Vec::new();
self.x = Vec::new();
return Ok(());
}
} else if line_read.contains("p:") {
let p_str = line_read.split(':').collect::<Vec<&str>>()[1];
let t = p_str.replace('[', "");
let p_str = t.replace(']', "");
for item in p_str.split(',') {
self.p.push(item.replace(' ', "").parse::<isize>()?);
}
} else if line_read.contains("i:") {
let i_str = line_read.split(':').collect::<Vec<&str>>()[1];
let t = i_str.replace('[', "");
let i_str = t.replace(']', "");
for item in i_str.split(',') {
self.i.push(item.replace(' ', "").parse::<usize>()?);
}
} else if line_read.contains("x:") {
let x_str = line_read.split(':').collect::<Vec<&str>>()[1];
let t = x_str.replace('[', "");
let x_str = t.replace(']', "");
for item in x_str.split(',') {
self.x.push(item.replace(' ', "").parse::<T>()?);
}
}
}
Ok(())
}
}
impl<T: Numeric<T>> Default for Sprs<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Numeric<T>> Add for Sprs<T> {
type Output = Self;
fn add(self, other: Sprs<T>) -> Sprs<T> {
add(&self, &other, T::one(), T::one())
}
}
impl<T: Numeric<T>> Add<&Sprs<T>> for Sprs<T> {
type Output = Self;
fn add(self, other: &Sprs<T>) -> Sprs<T> {
add(&self, other, T::one(), T::one())
}
}
impl<T: Numeric<T>> Add for &Sprs<T> {
type Output = Sprs<T>;
fn add(self, other: &Sprs<T>) -> Sprs<T> {
add(self, other, T::one(), T::one())
}
}
impl<T: Numeric<T>> Add<Sprs<T>> for &Sprs<T> {
type Output = Sprs<T>;
fn add(self, other: Sprs<T>) -> Sprs<T> {
add(self, &other, T::one(), T::one())
}
}
impl<T: Numeric<T>> Sub for Sprs<T> {
type Output = Self;
fn sub(self, other: Sprs<T>) -> Sprs<T> {
add(&self, &other, T::one(), -T::one())
}
}
impl<T: Numeric<T>> Sub<&Sprs<T>> for Sprs<T> {
type Output = Self;
fn sub(self, other: &Sprs<T>) -> Sprs<T> {
add(&self, other, T::one(), -T::one())
}
}
impl<T: Numeric<T>> Sub for &Sprs<T> {
type Output = Sprs<T>;
fn sub(self, other: &Sprs<T>) -> Sprs<T> {
add(self, other, T::one(), -T::one())
}
}
impl<T: Numeric<T>> Sub<Sprs<T>> for &Sprs<T> {
type Output = Sprs<T>;
fn sub(self, other: Sprs<T>) -> Sprs<T> {
add(self, &other, T::one(), -T::one())
}
}
impl<T: Numeric<T>> Mul for Sprs<T> {
type Output = Self;
fn mul(self, other: Sprs<T>) -> Sprs<T> {
multiply(&self, &other)
}
}
impl<T: Numeric<T>> Mul<&Sprs<T>> for Sprs<T> {
type Output = Self;
fn mul(self, other: &Sprs<T>) -> Sprs<T> {
multiply(&self, other)
}
}
impl<T: Numeric<T>> Mul for &Sprs<T> {
type Output = Sprs<T>;
fn mul(self, other: &Sprs<T>) -> Sprs<T> {
multiply(self, other)
}
}
impl<T: Numeric<T>> Mul<Sprs<T>> for &Sprs<T> {
type Output = Sprs<T>;
fn mul(self, other: Sprs<T>) -> Sprs<T> {
multiply(self, &other)
}
}
impl<T: Numeric<T>> Add<T> for Sprs<T> {
type Output = Self;
fn add(self, other: T) -> Sprs<T> {
scpmat(other, &self)
}
}
impl<T: Numeric<T>> Add<T> for &Sprs<T> {
type Output = Sprs<T>;
fn add(self, other: T) -> Sprs<T> {
scpmat(other, self)
}
}
impl<T: Numeric<T>> Sub<T> for Sprs<T> {
type Output = Self;
fn sub(self, other: T) -> Sprs<T> {
scpmat(-other, &self)
}
}
impl<T: Numeric<T>> Sub<T> for &Sprs<T> {
type Output = Sprs<T>;
fn sub(self, other: T) -> Sprs<T> {
scpmat(-other, self)
}
}
impl<T: Numeric<T>> Mul<T> for Sprs<T> {
type Output = Self;
fn mul(self, other: T) -> Sprs<T> {
scxmat(other, &self)
}
}
impl<T: Numeric<T>> Mul<T> for &Sprs<T> {
type Output = Sprs<T>;
fn mul(self, other: T) -> Sprs<T> {
scxmat(other, self)
}
}
impl<T: Numeric<T>> Div<T> for Sprs<T> {
type Output = Self;
fn div(self, other: T) -> Sprs<T> {
scxmat(T::one() / other, &self)
}
}
impl<T: Numeric<T>> Div<T> for &Sprs<T> {
type Output = Sprs<T>;
fn div(self, other: T) -> Sprs<T> {
scxmat(T::one() / other, self)
}
}
impl Add<Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn add(self, other: Sprs<f32>) -> Sprs<f32> {
scpmat(self, &other)
}
}
impl Add<Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn add(self, other: Sprs<f64>) -> Sprs<f64> {
scpmat(self, &other)
}
}
impl Add<&Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn add(self, other: &Sprs<f32>) -> Sprs<f32> {
scpmat(self, other)
}
}
impl Add<&Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn add(self, other: &Sprs<f64>) -> Sprs<f64> {
scpmat(self, other)
}
}
impl Sub<Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn sub(self, other: Sprs<f32>) -> Sprs<f32> {
scpmat(self, &scxmat(-1., &other))
}
}
impl Sub<Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn sub(self, other: Sprs<f64>) -> Sprs<f64> {
scpmat(self, &scxmat(-1., &other))
}
}
impl Sub<&Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn sub(self, other: &Sprs<f32>) -> Sprs<f32> {
scpmat(self, &scxmat(-1., other))
}
}
impl Sub<&Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn sub(self, other: &Sprs<f64>) -> Sprs<f64> {
scpmat(self, &scxmat(-1., other))
}
}
impl Mul<Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn mul(self, other: Sprs<f32>) -> Sprs<f32> {
scxmat(self, &other)
}
}
impl Mul<Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn mul(self, other: Sprs<f64>) -> Sprs<f64> {
scxmat(self, &other)
}
}
impl Mul<&Sprs<f32>> for f32 {
type Output = Sprs<f32>;
fn mul(self, other: &Sprs<f32>) -> Sprs<f32> {
scxmat(self, other)
}
}
impl Mul<&Sprs<f64>> for f64 {
type Output = Sprs<f64>;
fn mul(self, other: &Sprs<f64>) -> Sprs<f64> {
scxmat(self, other)
}
}
#[derive(Clone, Debug)]
pub struct Trpl<T: Numeric<T>> {
pub m: usize,
pub n: usize,
pub p: Vec<isize>,
pub i: Vec<usize>,
pub x: Vec<T>,
}
impl<T: Numeric<T> + for<'a> std::iter::Sum<&'a T>> Trpl<T> {
pub fn new() -> Trpl<T> {
Trpl {
m: 0,
n: 0,
p: Vec::new(),
i: Vec::new(),
x: Vec::new(),
}
}
pub fn append(&mut self, row: usize, column: usize, value: T) {
if row + 1 > self.m {
self.m = row + 1;
}
if column + 1 > self.n {
self.n = column + 1;
}
self.p.push(column as isize);
self.i.push(row);
self.x.push(value);
}
pub fn to_sprs(&self) -> Sprs<T> {
let mut s = Sprs {
nzmax: self.x.len(),
m: self.m,
n: self.n,
p: vec![0; self.n + 1],
i: vec![0; self.x.len()],
x: vec![T::zero(); self.x.len()],
};
let mut w = vec![0; s.n];
for k in 0..self.p.len() {
w[self.p[k] as usize] += 1; }
cumsum(&mut s.p[..], &mut w[..], s.n); let mut p;
for k in 0..self.p.len() {
p = w[self.p[k] as usize] as usize;
s.i[p] = self.i[k]; w[self.p[k] as usize] += 1;
s.x[p] = self.x[k];
}
s
}
pub fn sum_dupl(&mut self) {
for i in &self.i {
for j in &self.p {
let pos;
let val;
let g = self.get_all(*i, *j as usize);
if g.is_none() {
continue;
}
(pos, val) = g.unwrap();
for i in &pos[..pos.len()] {
self.x[*i] = T::zero();
}
self.x[pos[pos.len() - 1]] = val.iter().sum();
}
}
}
pub fn get(&self, row: usize, column: usize) -> Option<T> {
for i in 0..self.x.len() {
if (self.i[i], self.p[i] as usize) == (row, column) {
return Some(self.x[i]);
}
}
None
}
pub fn get_all(&self, row: usize, column: usize) -> Option<(Vec<usize>, Vec<T>)> {
let mut r = Vec::new();
let mut pos = Vec::new();
for i in 0..self.x.len() {
if (self.i[i], self.p[i] as usize) == (row, column) {
r.push(self.x[i]);
pos.push(i);
}
}
if !r.is_empty() {
Some((pos, r))
} else {
None
}
}
}
impl<T: Numeric<T> + for<'a> std::iter::Sum<&'a T>> Default for Trpl<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug)]
pub struct Symb {
pub pinv: Option<Vec<isize>>,
pub q: Option<Vec<isize>>,
pub parent: Vec<isize>,
pub cp: Vec<isize>,
pub m2: usize,
pub lnz: usize,
pub unz: usize,
}
impl Symb {
pub fn new() -> Symb {
Symb {
pinv: None,
q: None,
parent: Vec::new(),
cp: Vec::new(),
m2: 0,
lnz: 0,
unz: 0,
}
}
}
impl Default for Symb {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug)]
pub struct Nmrc<T: Numeric<T>> {
pub l: Sprs<T>,
pub u: Sprs<T>,
pub pinv: Option<Vec<isize>>,
pub b: Vec<T>,
}
impl<T: Numeric<T>> Nmrc<T> {
pub fn new() -> Nmrc<T> {
Nmrc {
l: Sprs::new(),
u: Sprs::new(),
pinv: None,
b: Vec::new(),
}
}
}
impl<T: Numeric<T>> Default for Nmrc<T> {
fn default() -> Self {
Self::new()
}
}