77//!
88//! The dynamic tensors module includes:
99//!
10- //! - `DynamicVector`: A flexible vector implementation with arbitrary dimension
11- //! - `DynamicDenseMatrix`: A matrix implementation with two storage orientation options:
12- //! - Row-major: Efficient for row operations
13- //! - Column-major: Efficient for column operations
10+ //! - `Vector`: A flexible vector implementation with arbitrary dimension
11+ //! - `Matrix`: A clean, ergonomic matrix implementation with block construction support
1412//!
1513//! ## Mathematical Foundation
1614//!
1715//! Tensors are mathematical objects that generalize vectors and matrices to higher dimensions.
1816//! The implementations in this module adhere to the algebraic properties of vector spaces
1917//! and linear transformations over arbitrary fields.
2018//!
21- //! ## Performance Considerations
22- //!
23- //! - Choose storage orientation based on the dominant operation pattern:
24- //! - Use row-major matrices when mostly operating on rows
25- //! - Use column-major matrices when mostly operating on columns
26- //! - Matrix-vector operations automatically use the most efficient implementation based on the
27- //! storage orientation
28- //!
2919//! ## Examples
3020//!
3121//! ```
3222//! use cova_algebra::{
3323//! prelude::*,
34- //! tensors::dynamic::{
35- //! matrix::{DynamicDenseMatrix, RowMajor},
36- //! vector::DynamicVector,
37- //! },
24+ //! tensors::dynamic::{matrix::Matrix, vector::Vector},
3825//! };
3926//!
4027//! // Create vectors
41- //! let v1 = DynamicVector ::from([1.0, 2.0, 3.0]);
42- //! let v2 = DynamicVector ::from([4.0, 5.0, 6.0]);
28+ //! let v1 = Vector ::from([1.0, 2.0, 3.0]);
29+ //! let v2 = Vector ::from([4.0, 5.0, 6.0]);
4330//!
4431//! // Create a matrix from rows
45- //! let mut matrix = DynamicDenseMatrix::<f64, RowMajor>::new();
46- //! matrix.append_row(v1);
47- //! matrix.append_row(v2);
32+ //! let matrix = Matrix::from_rows([v1, v2]);
33+ //!
34+ //! // Or using builder pattern
35+ //! let matrix = Matrix::<f64>::builder().row([1.0, 2.0, 3.0]).row([4.0, 5.0, 6.0]).build();
36+ //!
37+ //! // Block matrix construction
38+ //! let block_matrix = Matrix::<f64>::from_blocks(vec![
39+ //! vec![Matrix::identity(2), Matrix::zeros(2, 3)],
40+ //! vec![Matrix::zeros(3, 2), Matrix::identity(3)],
41+ //! ]);
4842//!
4943//! // Perform Gaussian elimination to row echelon form
50- //! let result = matrix.row_echelon_form ();
44+ //! let (rref, output) = matrix.into_row_echelon_form ();
5145//! ```
5246
53- use matrix:: { DynamicDenseMatrix , RowMajor } ;
54- use vector:: DynamicVector ;
47+ pub use matrix:: Matrix ;
48+ pub use vector:: Vector ;
5549
5650use super :: * ;
5751
58- pub mod block;
5952pub mod matrix;
6053pub mod vector;
6154
@@ -66,9 +59,9 @@ pub mod vector;
6659/// this method returns a basis for the quotient space V/U.
6760/// The input vectors are treated as column vectors.
6861pub fn compute_quotient_basis < F : Field + Copy > (
69- subspace_vectors : & [ DynamicVector < F > ] ,
70- space_vectors : & [ DynamicVector < F > ] ,
71- ) -> Vec < DynamicVector < F > > {
62+ subspace_vectors : & [ Vector < F > ] ,
63+ space_vectors : & [ Vector < F > ] ,
64+ ) -> Vec < Vector < F > > {
7265 if space_vectors. is_empty ( ) {
7366 return Vec :: new ( ) ;
7467 }
@@ -98,19 +91,15 @@ pub fn compute_quotient_basis<F: Field + Copy>(
9891 ) ;
9992 }
10093
101- let mut matrix = DynamicDenseMatrix :: < F , RowMajor > :: new ( ) ;
102-
103- for vec in subspace_vectors {
104- matrix. append_column ( vec) ;
105- }
106-
107- for vec in space_vectors {
108- matrix. append_column ( vec) ;
109- }
94+ // Create matrix from columns
95+ let mut all_columns = Vec :: new ( ) ;
96+ all_columns. extend_from_slice ( subspace_vectors) ;
97+ all_columns. extend_from_slice ( space_vectors) ;
11098
111- let echelon_output = matrix. row_echelon_form ( ) ;
99+ let matrix = Matrix :: from_cols ( all_columns) ;
100+ let ( _, echelon_output) = matrix. into_row_echelon_form ( ) ;
112101
113- let mut quotient_basis: Vec < DynamicVector < F > > = Vec :: new ( ) ;
102+ let mut quotient_basis: Vec < Vector < F > > = Vec :: new ( ) ;
114103 let num_subspace_cols = subspace_vectors. len ( ) ;
115104
116105 let pivot_cols_set: std:: collections:: HashSet < usize > =
@@ -129,15 +118,15 @@ pub fn compute_quotient_basis<F: Field + Copy>(
129118#[ cfg( test) ]
130119mod tests {
131120 use super :: compute_quotient_basis;
132- use crate :: { fixtures:: Mod7 , tensors:: dynamic:: vector:: DynamicVector } ;
121+ use crate :: { fixtures:: Mod7 , tensors:: dynamic:: vector:: Vector } ;
133122
134123 #[ test]
135124 fn test_quotient_simple_span ( ) {
136125 // V = span{[1,0,0], [0,1,0]}, U = span{[1,0,0]}
137126 // V/U should be span{[0,1,0]}
138- let u1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
139- let v_in_u = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
140- let v_new = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
127+ let u1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
128+ let v_in_u = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
129+ let v_new = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
141130
142131 let subspace_vectors = vec ! [ u1] ;
143132 // Order of space_vectors: putting v_in_u first
@@ -157,8 +146,8 @@ mod tests {
157146 fn test_quotient_subspace_equals_space ( ) {
158147 // V = span{[1,0], [0,1]}, U = span{[1,0], [0,1]}
159148 // V/U should be empty
160- let u1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
161- let u2 = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
149+ let u1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
150+ let u2 = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
162151 // space_vectors are the same as subspace_vectors
163152 let space_vectors = vec ! [ u1. clone( ) , u2. clone( ) ] ;
164153 let subspace_vectors = vec ! [ u1. clone( ) , u2. clone( ) ] ;
@@ -175,10 +164,10 @@ mod tests {
175164 fn test_quotient_trivial_subspace ( ) {
176165 // V = span{[1,0], [0,1]}, U = {} (trivial subspace)
177166 // V/U should be span{[1,0], [0,1]}
178- let v1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
179- let v2 = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
167+ let v1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
168+ let v2 = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
180169
181- let subspace_vectors: Vec < DynamicVector < Mod7 > > = vec ! [ ] ;
170+ let subspace_vectors: Vec < Vector < Mod7 > > = vec ! [ ] ;
182171 let space_vectors = vec ! [ v1. clone( ) , v2. clone( ) ] ;
183172
184173 let quotient_basis = compute_quotient_basis ( & subspace_vectors, & space_vectors) ;
@@ -192,10 +181,10 @@ mod tests {
192181 // V = span{[1,0], [2,0], [0,1]}, U = span{[1,0]}
193182 // [2,0] is dependent on [1,0].
194183 // V/U should be span{[0,1]}
195- let u1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
196- let v_in_u = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ; // Effectively in U
197- let v_dependent_on_u = DynamicVector :: from ( vec ! [ Mod7 :: new( 2 ) , Mod7 :: new( 0 ) ] ) ; // 2*u1
198- let v_new_independent = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
184+ let u1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
185+ let v_in_u = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ; // Effectively in U
186+ let v_dependent_on_u = Vector :: from ( vec ! [ Mod7 :: new( 2 ) , Mod7 :: new( 0 ) ] ) ; // 2*u1
187+ let v_new_independent = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
199188
200189 let subspace_vectors = vec ! [ u1. clone( ) ] ;
201190 let space_vectors = vec ! [ v_in_u. clone( ) , v_dependent_on_u. clone( ) , v_new_independent. clone( ) ] ;
@@ -223,11 +212,11 @@ mod tests {
223212 // Expected quotient basis: a basis for span{[0,1,0], [0,0,1]}, chosen from original space
224213 // vectors. So, should be [[0,1,0], [0,0,1]] if [0,2,0] is correctly identified as dependent
225214 // on [0,1,0] in context of quotient.
226- let u1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
215+ let u1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
227216
228- let v1_new = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
229- let v2_dependent_on_v1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 2 ) , Mod7 :: new( 0 ) ] ) ;
230- let v3_new = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
217+ let v1_new = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
218+ let v2_dependent_on_v1 = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 2 ) , Mod7 :: new( 0 ) ] ) ;
219+ let v3_new = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) , Mod7 :: new( 1 ) ] ) ;
231220
232221 let subspace_vectors = vec ! [ u1] ;
233222 // Order: v1_new, then its dependent v2_dependent_on_v1, then independent v3_new
@@ -250,19 +239,19 @@ mod tests {
250239
251240 #[ test]
252241 fn test_quotient_empty_space_vectors ( ) {
253- let u1 = DynamicVector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
242+ let u1 = Vector :: from ( vec ! [ Mod7 :: new( 1 ) , Mod7 :: new( 0 ) ] ) ;
254243 let subspace_vectors = vec ! [ u1] ;
255- let space_vectors: Vec < DynamicVector < Mod7 > > = vec ! [ ] ;
244+ let space_vectors: Vec < Vector < Mod7 > > = vec ! [ ] ;
256245
257246 let quotient_basis = compute_quotient_basis ( & subspace_vectors, & space_vectors) ;
258247 assert ! ( quotient_basis. is_empty( ) , "Quotient basis should be empty if space_vectors is empty" ) ;
259248 }
260249
261250 #[ test]
262251 fn test_quotient_zero_dimensional_vectors ( ) {
263- let u1_zero_dim = DynamicVector :: < Mod7 > :: new ( vec ! [ ] ) ;
264- let v1_zero_dim = DynamicVector :: < Mod7 > :: new ( vec ! [ ] ) ;
265- let v2_zero_dim = DynamicVector :: < Mod7 > :: new ( vec ! [ ] ) ;
252+ let u1_zero_dim = Vector :: < Mod7 > :: new ( vec ! [ ] ) ;
253+ let v1_zero_dim = Vector :: < Mod7 > :: new ( vec ! [ ] ) ;
254+ let v2_zero_dim = Vector :: < Mod7 > :: new ( vec ! [ ] ) ;
266255
267256 let subspace_vectors = vec ! [ u1_zero_dim] ;
268257 let space_vectors = vec ! [ v1_zero_dim, v2_zero_dim] ;
@@ -274,7 +263,7 @@ mod tests {
274263 ) ;
275264
276265 // Case: subspace empty, space has 0-dim vectors
277- let subspace_vectors_empty: Vec < DynamicVector < Mod7 > > = vec ! [ ] ;
266+ let subspace_vectors_empty: Vec < Vector < Mod7 > > = vec ! [ ] ;
278267 let quotient_basis_empty_sub = compute_quotient_basis ( & subspace_vectors_empty, & space_vectors) ;
279268 assert ! (
280269 quotient_basis_empty_sub. is_empty( ) ,
@@ -286,9 +275,9 @@ mod tests {
286275 fn test_quotient_all_zero_vectors_of_some_dimension ( ) {
287276 // V = span{[0,0], [0,0]}, U = span{[0,0]}
288277 // V/U should be empty
289- let u1_zero_vec = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
290- let v1_zero_vec = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
291- let v2_zero_vec = DynamicVector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
278+ let u1_zero_vec = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
279+ let v1_zero_vec = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
280+ let v2_zero_vec = Vector :: from ( vec ! [ Mod7 :: new( 0 ) , Mod7 :: new( 0 ) ] ) ;
292281
293282 let subspace_vectors = vec ! [ u1_zero_vec. clone( ) ] ;
294283 let space_vectors = vec ! [ v1_zero_vec. clone( ) , v2_zero_vec. clone( ) ] ;
0 commit comments