1use crate::enums::MatrixOperation;
2use crate::error::MatrixError;
3use crate::types::{Matrix, MatrixRef};
4
5pub fn nonzero_positive_input<T>(msg: &str, desired_count: Option<T>) -> T
6where
7 T: std::str::FromStr + std::cmp::PartialOrd + std::fmt::Debug,
8 T: num_traits::Unsigned + num_traits::NumCast,
9{
10 use std::io::Write;
11
12 if let Some(count) = desired_count {
13 println!("Count inferred as: {count:?}");
14 return count;
15 }
16
17 let mut input = String::new();
18
19 loop {
20 print!("{}", msg);
21 std::io::stdout().flush().unwrap();
22 std::io::stdin()
23 .read_line(&mut input)
24 .expect("Failed to read line.");
25 println!();
26 match input.trim().parse::<T>() {
27 Ok(result) => {
28 if result < num_traits::cast(1).expect("Infalliable num trait cast.") {
29 input = String::new();
30 eprintln!("Error: The Input needs to be greater than 0.");
31 continue;
32 }
33 return result;
34 }
35 _ => {
36 input = String::new();
37 eprintln!("Error: invalid input");
38 continue;
39 }
40 };
41 }
42}
43
44pub fn numeric_input<T>(msg: &str, predefined: Option<T>) -> T
45where
46 T: std::str::FromStr + std::fmt::Debug + num_traits::Signed,
47{
48 use std::io::Write;
49
50 if let Some(input) = predefined {
51 println!("Input was inferred as: {input:?}");
52 return input;
53 }
54
55 let mut input = String::new();
56
57 loop {
58 print!("{}", msg);
59 std::io::stdout().flush().unwrap();
60 std::io::stdin()
61 .read_line(&mut input)
62 .expect("Failed to read line.");
63 println!();
64 match input.trim().parse::<T>() {
65 Ok(result) => {
66 return result;
67 }
68 _ => {
69 input = String::new();
70 eprintln!("Error: invalid input");
71 continue;
72 }
73 };
74 }
75}
76
77pub fn matrix(n: u32, cols: Option<usize>, rows: Option<usize>) -> Vec<Vec<i32>> {
78 let col_count =
79 nonzero_positive_input::<usize>(&format!("Enter column count for matrix {}: ", n), cols);
80 let row_count =
81 nonzero_positive_input::<usize>(&format!("Enter row count for matrix {}: ", n), rows);
82
83 let mut res: Vec<Vec<i32>> = vec![];
84
85 for col in 1..=col_count {
86 let mut row_content = Vec::with_capacity(col_count);
87 for row in 1..=row_count {
88 row_content.push(numeric_input::<i32>(
89 &format!(
90 "Enter item at row {} and column {} for matrix {n}: ",
91 row, col
92 ),
93 None,
94 ));
95 }
96 res.push(row_content);
97 }
98
99 res
100}
101
102pub fn matrix_operation_unchecked(
108 op: MatrixOperation,
109 m1: MatrixRef<'_, i32>,
110 m2: MatrixRef<'_, i32>,
111) -> Matrix<i32> {
112 use MatrixOperation as MO;
113
114 let operation: Box<dyn Fn(i32, i32) -> i32> = match op {
115 MO::Addition => Box::new(|a, b| a + b),
116 MO::Subtraction => Box::new(|a, b| a - b),
117 MO::Multiplication => Box::new(|a, b| a * b),
118 };
119
120 m1.iter()
121 .enumerate()
122 .map(|(i, col)| {
123 col.iter()
124 .enumerate()
125 .map(|(j, _)| operation(m1[i][j], m2[i][j]))
126 .collect::<Vec<i32>>()
127 })
128 .collect::<Matrix<i32>>()
129}
130
131#[allow(unused)]
132pub fn matrix_operation<'m>(
133 op: MatrixOperation,
134 m1: MatrixRef<'m, i32>,
135 m2: MatrixRef<'m, i32>,
136) -> Result<Vec<Vec<i32>>, MatrixError<'m, i32>> {
137 use MatrixError as ME;
138
139 if m1.is_empty() {
140 return Err(ME::Empty(m1));
141 }
142 if m2.is_empty() {
143 return Err(ME::Empty(m2));
144 }
145
146 if m1.len() != m2.len() || m1[0].len() != m2[0].len() {
147 return Err(ME::NotEqual(m1, m2));
148 }
149
150 Ok(matrix_operation_unchecked(op, m1, m2))
151}