use crate::array::Array;
use crate::error::Result;
use crate::matrix::Matrix;
use std::convert::TryFrom;
pub fn hilbert(n: usize) -> Matrix<f64> {
let mut data = Vec::with_capacity(n * n);
for i in 0..n {
for j in 0..n {
data.push(1.0 / ((i + j + 1) as f64));
}
}
let array = Array::from_vec(data).reshape(&[n, n]);
Matrix::new(array).expect("hilbert: n x n array is always a valid matrix")
}
pub fn vandermonde(x: Vec<f64>, n: Option<usize>) -> Matrix<f64> {
let rows = x.len();
let cols = n.unwrap_or(rows);
let mut data = Vec::with_capacity(rows * cols);
#[allow(clippy::needless_range_loop)]
for i in 0..rows {
for j in 0..cols {
data.push(x[i].powi(j as i32));
}
}
let array = Array::from_vec(data).reshape(&[rows, cols]);
Matrix::new(array).expect("vandermonde: rows x cols array is always a valid matrix")
}
pub fn toeplitz(c: Vec<f64>, r: Option<Vec<f64>>) -> Result<Matrix<f64>> {
let rows = c.len();
let first_row = match r {
Some(row) => row,
None => vec![c[0]], };
let cols = first_row.len();
let mut data = Vec::with_capacity(rows * cols);
for i in 0..rows {
for j in 0..cols {
if i == 0 {
data.push(first_row[j]);
} else if j == 0 {
data.push(c[i]);
} else {
if i >= j {
data.push(c[i - j]);
} else {
data.push(first_row[j - i]);
}
}
}
}
let array = Array::from_vec(data).reshape(&[rows, cols]);
Matrix::new(array)
}
pub fn circulant(first_row: Vec<f64>) -> Matrix<f64> {
let n = first_row.len();
let mut data = Vec::with_capacity(n * n);
for i in 0..n {
for j in 0..n {
let idx = (j + i) % n;
data.push(first_row[idx]);
}
}
let array = Array::from_vec(data).reshape(&[n, n]);
Matrix::new(array).expect("circulant: n x n array is always a valid matrix")
}
pub fn hankel(c: Vec<f64>, r: Option<Vec<f64>>) -> Result<Matrix<f64>> {
let rows = c.len();
let last_row = match r {
Some(row) => row,
None => vec![0.0; rows], };
let cols = last_row.len();
let mut data = Vec::with_capacity(rows * cols);
for i in 0..rows {
for j in 0..cols {
let sum = i + j;
if sum < rows {
data.push(c[sum]);
} else {
data.push(last_row[sum - rows + 1]);
}
}
}
let array = Array::from_vec(data).reshape(&[rows, cols]);
Matrix::new(array)
}
pub fn leslie(f: Vec<f64>, s: Vec<f64>) -> Result<Matrix<f64>> {
if f.len() != s.len() + 1 {
return Err(crate::error::NumRs2Error::DimensionMismatch(format!(
"Leslie matrix requires f.len() to be s.len() + 1, got f.len() = {} and s.len() = {}",
f.len(),
s.len()
)));
}
let n = f.len();
let mut data = Vec::with_capacity(n * n);
for i in 0..n {
for j in 0..n {
if i == 0 {
data.push(f[j]);
} else if j == i - 1 {
data.push(s[j]);
} else {
data.push(0.0);
}
}
}
let array = Array::from_vec(data).reshape(&[n, n]);
Matrix::new(array)
}
pub fn companion(coefficients: Vec<f64>) -> Result<Matrix<f64>> {
if coefficients.len() < 2 {
return Err(crate::error::NumRs2Error::InvalidOperation(
"Companion matrix requires at least 2 coefficients".to_string(),
));
}
let a0 = coefficients[0];
let normalized: Vec<f64> = coefficients.iter().map(|&x| x / a0).collect();
let n = normalized.len() - 1; let mut data = Vec::with_capacity(n * n);
for i in 0..n {
for j in 0..n {
if i == j + 1 {
data.push(1.0);
} else if j == n - 1 {
data.push(-normalized[i + 1]);
} else {
data.push(0.0);
}
}
}
let array = Array::from_vec(data).reshape(&[n, n]);
Matrix::new(array)
}
pub fn hadamard(n: usize) -> Result<Matrix<f64>> {
if n != 1 && n != 2 && !n.is_multiple_of(4) {
return Err(crate::error::NumRs2Error::InvalidOperation(format!(
"Hadamard matrices are only defined for orders 1, 2, or multiples of 4, got {}",
n
)));
}
if n == 1 {
return Ok(Matrix::try_from(Array::from_vec(vec![1.0]))
.expect("hadamard: 1x1 array is always a valid matrix"));
}
if n == 2 {
let h2 = vec![1.0, 1.0, 1.0, -1.0];
return Ok(Matrix::try_from(Array::from_vec(h2).reshape(&[2, 2]))
.expect("hadamard: 2x2 array is always a valid matrix"));
}
let mut h = vec![vec![1.0, 1.0], vec![1.0, -1.0]];
let mut order = 2;
while order < n {
let mut h_new = vec![vec![0.0; order * 2]; order * 2];
for i in 0..order {
for j in 0..order {
h_new[i][j] = h[i][j]; h_new[i][j + order] = h[i][j]; h_new[i + order][j] = h[i][j]; h_new[i + order][j + order] = -h[i][j]; }
}
h = h_new;
order *= 2;
}
let mut data = Vec::with_capacity(n * n);
for row in h.iter() {
data.extend_from_slice(row);
}
let array = Array::from_vec(data).reshape(&[n, n]);
Matrix::new(array)
}