mirror of
https://github.com/Magnus167/rustframe.git
synced 2025-08-20 04:19:59 +00:00
Merge 34cff9f05ee37babff757a12d227d41cc7db06c8 into d2d4764c17a3c9fc5dc0b24a4877f41a2d12ff4c
This commit is contained in:
commit
fcd5cc245e
@ -96,9 +96,10 @@ impl BoolOps for Frame<bool> {
|
||||
// }
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::frame::*;
|
||||
use crate::matrix::*;
|
||||
use super::*;
|
||||
use crate::matrix::Matrix;
|
||||
|
||||
#[test]
|
||||
fn test_series_ops() {
|
||||
|
@ -1,4 +1,6 @@
|
||||
use std::ops::{Index, IndexMut, Not};
|
||||
//! A simple column-major Matrix implementation with element-wise operations.
|
||||
|
||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Index, IndexMut, Mul, Not, Sub};
|
||||
|
||||
/// A column‑major 2D matrix of `T`
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -13,9 +15,15 @@ impl<T: Clone> Matrix<T> {
|
||||
pub fn from_cols(cols_data: Vec<Vec<T>>) -> Self {
|
||||
let cols = cols_data.len();
|
||||
assert!(cols > 0, "need at least one column");
|
||||
let rows = cols_data[0].len();
|
||||
assert!(rows > 0, "need at least one row");
|
||||
for (i, col) in cols_data.iter().enumerate().skip(1) {
|
||||
// Handle empty cols_data
|
||||
let rows = cols_data.get(0).map_or(0, |c| c.len());
|
||||
// Allow 0-row matrices if columns are empty, but not 0-col matrices if rows > 0
|
||||
assert!(
|
||||
rows > 0 || cols == 0,
|
||||
"need at least one row if columns exist"
|
||||
);
|
||||
|
||||
for (i, col) in cols_data.iter().enumerate() {
|
||||
assert!(
|
||||
col.len() == rows,
|
||||
"col {} has len {}, expected {}",
|
||||
@ -24,17 +32,34 @@ impl<T: Clone> Matrix<T> {
|
||||
rows
|
||||
);
|
||||
}
|
||||
let mut data = Vec::with_capacity(rows * cols);
|
||||
for col in cols_data {
|
||||
data.extend(col);
|
||||
}
|
||||
// Flatten column data directly
|
||||
let data = cols_data.into_iter().flatten().collect();
|
||||
Matrix { rows, cols, data }
|
||||
}
|
||||
|
||||
/// Build from a flat Vec, assuming column-major order.
|
||||
pub fn from_vec(data: Vec<T>, rows: usize, cols: usize) -> Self {
|
||||
assert!(rows > 0, "need at least one row");
|
||||
assert!(cols > 0, "need at least one column");
|
||||
assert_eq!(data.len(), rows * cols, "data length mismatch");
|
||||
assert!(
|
||||
rows > 0 || cols == 0,
|
||||
"need at least one row if columns exist"
|
||||
);
|
||||
assert!(
|
||||
cols > 0 || rows == 0,
|
||||
"need at least one column if rows exist"
|
||||
);
|
||||
if rows * cols != 0 {
|
||||
// Only assert length if matrix is non-empty
|
||||
assert_eq!(
|
||||
data.len(),
|
||||
rows * cols,
|
||||
"data length mismatch: expected {}, got {}",
|
||||
rows * cols,
|
||||
data.len()
|
||||
);
|
||||
} else {
|
||||
assert!(data.is_empty(), "data must be empty for 0-sized matrix");
|
||||
}
|
||||
|
||||
Matrix { rows, cols, data }
|
||||
}
|
||||
|
||||
@ -46,7 +71,13 @@ impl<T: Clone> Matrix<T> {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
pub fn as_vec(&self) -> Vec<T> {
|
||||
/// Consumes the Matrix and returns its underlying data Vec.
|
||||
pub fn into_vec(self) -> Vec<T> {
|
||||
self.data
|
||||
}
|
||||
|
||||
/// Creates a new Vec<T> containing the matrix data (cloned).
|
||||
pub fn to_vec(&self) -> Vec<T> {
|
||||
self.data.clone()
|
||||
}
|
||||
|
||||
@ -58,20 +89,36 @@ impl<T: Clone> Matrix<T> {
|
||||
self.cols
|
||||
}
|
||||
|
||||
/// Get element reference (immutable). Panics on out-of-bounds.
|
||||
pub fn get(&self, r: usize, c: usize) -> &T {
|
||||
&self[(r, c)]
|
||||
}
|
||||
|
||||
/// Get element reference (mutable). Panics on out-of-bounds.
|
||||
pub fn get_mut(&mut self, r: usize, c: usize) -> &mut T {
|
||||
&mut self[(r, c)]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn column(&self, c: usize) -> &[T] {
|
||||
assert!(
|
||||
c < self.cols,
|
||||
"column index {} out of bounds for {} columns",
|
||||
c,
|
||||
self.cols
|
||||
);
|
||||
let start = c * self.rows;
|
||||
&self.data[start..start + self.rows]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn column_mut(&mut self, c: usize) -> &mut [T] {
|
||||
assert!(
|
||||
c < self.cols,
|
||||
"column index {} out of bounds for {} columns",
|
||||
c,
|
||||
self.cols
|
||||
);
|
||||
let start = c * self.rows;
|
||||
&mut self.data[start..start + self.rows]
|
||||
}
|
||||
@ -87,11 +134,19 @@ impl<T: Clone> Matrix<T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Swaps two columns in the matrix.
|
||||
/// Swaps two columns in the matrix. Panics on out-of-bounds.
|
||||
pub fn swap_columns(&mut self, c1: usize, c2: usize) {
|
||||
assert!(
|
||||
c1 < self.cols && c2 < self.cols,
|
||||
"column index out of bounds"
|
||||
c1 < self.cols,
|
||||
"column index c1={} out of bounds for {} columns",
|
||||
c1,
|
||||
self.cols
|
||||
);
|
||||
assert!(
|
||||
c2 < self.cols,
|
||||
"column index c2={} out of bounds for {} columns",
|
||||
c2,
|
||||
self.cols
|
||||
);
|
||||
if c1 == c2 {
|
||||
// Indices are equal; no operation required
|
||||
@ -132,7 +187,7 @@ impl<T: Clone> Matrix<T> {
|
||||
impl<T: Clone> Matrix<T> {
|
||||
/// Adds a column to the matrix at the specified index.
|
||||
pub fn add_column(&mut self, index: usize, column: Vec<T>) {
|
||||
assert!(index <= self.cols, "column index out of bounds");
|
||||
assert!(index <= self.cols,"add_column index {} out of bounds for {} columns",index,self.cols);
|
||||
assert_eq!(column.len(), self.rows, "column length mismatch");
|
||||
|
||||
for (r, value) in column.into_iter().enumerate() {
|
||||
@ -143,8 +198,8 @@ impl<T: Clone> Matrix<T> {
|
||||
|
||||
/// Adds a row to the matrix at the specified index.
|
||||
pub fn add_row(&mut self, index: usize, row: Vec<T>) {
|
||||
assert!(index <= self.rows, "row index out of bounds");
|
||||
assert_eq!(row.len(), self.cols, "row length mismatch");
|
||||
assert!(index <= self.rows,"add_row index {} out of bounds for {} rows",index,self.rows);
|
||||
assert_eq!(row.len(),self.cols,"row length mismatch: expected {} (cols), got {}",self.cols,row.len());
|
||||
|
||||
for (c, value) in row.into_iter().enumerate() {
|
||||
self.data.insert(c * (self.rows + 1) + index, value);
|
||||
@ -159,7 +214,14 @@ impl<T> Index<(usize, usize)> for Matrix<T> {
|
||||
#[inline]
|
||||
fn index(&self, (r, c): (usize, usize)) -> &T {
|
||||
// Validate that the requested indices are within bounds
|
||||
assert!(r < self.rows && c < self.cols, "index out of bounds");
|
||||
assert!(
|
||||
r < self.rows && c < self.cols,
|
||||
"index out of bounds: ({}, {}) vs {}x{}",
|
||||
r,
|
||||
c,
|
||||
self.rows,
|
||||
self.cols
|
||||
);
|
||||
// Compute column-major offset and return reference
|
||||
&self.data[c * self.rows + r]
|
||||
}
|
||||
@ -169,7 +231,14 @@ impl<T> IndexMut<(usize, usize)> for Matrix<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, (r, c): (usize, usize)) -> &mut T {
|
||||
// Validate that the requested indices are within bounds
|
||||
assert!(r < self.rows && c < self.cols, "index out of bounds");
|
||||
assert!(
|
||||
r < self.rows && c < self.cols,
|
||||
"index out of bounds: ({}, {}) vs {}x{}",
|
||||
r,
|
||||
c,
|
||||
self.rows,
|
||||
self.cols
|
||||
);
|
||||
// Compute column-major offset and return mutable reference
|
||||
&mut self.data[c * self.rows + r]
|
||||
}
|
||||
@ -196,14 +265,16 @@ impl<'a, T> MatrixRow<'a, T> {
|
||||
/// Specifies the axis along which to perform a reduction operation.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Axis {
|
||||
/// Apply reduction along columns (vertical axis).
|
||||
/// Apply reduction along columns (vertical axis). Result has 1 row.
|
||||
Col,
|
||||
/// Apply reduction along rows (horizontal axis).
|
||||
/// Apply reduction along rows (horizontal axis). Result has 1 column.
|
||||
Row,
|
||||
}
|
||||
|
||||
// --- Broadcasting ---
|
||||
|
||||
/// A trait to turn either a `Matrix<T>` or a scalar T into a `Vec<T>` of
|
||||
/// length `rows*cols` (broadcasting the scalar).
|
||||
/// length `rows*cols` (broadcasting the scalar). Used for comparisons.
|
||||
pub trait Broadcastable<T> {
|
||||
fn to_vec(&self, rows: usize, cols: usize) -> Vec<T>;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user