backport some nice things from routing engine and cleanup a bit
[Mitarbeiter/Tim-Zeitz/stud-rust-base.git] / src / bin / compare_vector.rs
1 use stud_rust_base::{io::*, cli::CliErr};
2 use std::{env, fmt::Display, error::Error};
3
4 fn main() -> Result<(), Box<dyn Error>> {
5     let mut args = env::args();
6     args.next();
7
8     match &args.collect::<Vec<String>>()[..] {
9         [data_type, input1, input2] => {
10             match data_type.as_ref() {
11                 "i8" => { compare_values(&Vec::<i8>::load_from(input1)?, &Vec::<i8>::load_from(input2)?); Ok(()) },
12                 "u8" => { compare_values(&Vec::<u8>::load_from(input1)?, &Vec::<u8>::load_from(input2)?); Ok(()) },
13                 "i16" => { compare_values(&Vec::<i16>::load_from(input1)?, &Vec::<i16>::load_from(input2)?); Ok(()) },
14                 "u16" => { compare_values(&Vec::<u16>::load_from(input1)?, &Vec::<u16>::load_from(input2)?); Ok(()) },
15                 "i32" => { compare_values(&Vec::<i32>::load_from(input1)?, &Vec::<i32>::load_from(input2)?); Ok(()) },
16                 "u32" => { compare_values(&Vec::<u32>::load_from(input1)?, &Vec::<u32>::load_from(input2)?); Ok(()) },
17                 "i64" => { compare_values(&Vec::<i64>::load_from(input1)?, &Vec::<i64>::load_from(input2)?); Ok(()) },
18                 "u64" => { compare_values(&Vec::<u64>::load_from(input1)?, &Vec::<u64>::load_from(input2)?); Ok(()) },
19                 "f32" => { compare_values(&Vec::<f32>::load_from(input1)?, &Vec::<f32>::load_from(input2)?); Ok(()) },
20                 "f64" => { compare_values(&Vec::<f64>::load_from(input1)?, &Vec::<f64>::load_from(input2)?); Ok(()) },
21                 "int8" => { compare_values(&Vec::<i8>::load_from(input1)?, &Vec::<i8>::load_from(input2)?); Ok(()) },
22                 "uint8" => { compare_values(&Vec::<u8>::load_from(input1)?, &Vec::<u8>::load_from(input2)?); Ok(()) },
23                 "int16" => { compare_values(&Vec::<i16>::load_from(input1)?, &Vec::<i16>::load_from(input2)?); Ok(()) },
24                 "uint16" => { compare_values(&Vec::<u16>::load_from(input1)?, &Vec::<u16>::load_from(input2)?); Ok(()) },
25                 "int32" => { compare_values(&Vec::<i32>::load_from(input1)?, &Vec::<i32>::load_from(input2)?); Ok(()) },
26                 "uint32" => { compare_values(&Vec::<u32>::load_from(input1)?, &Vec::<u32>::load_from(input2)?); Ok(()) },
27                 "int64" => { compare_values(&Vec::<i64>::load_from(input1)?, &Vec::<i64>::load_from(input2)?); Ok(()) },
28                 "uint64" => { compare_values(&Vec::<u64>::load_from(input1)?, &Vec::<u64>::load_from(input2)?); Ok(()) },
29                 "float32" => { compare_values(&Vec::<f32>::load_from(input1)?, &Vec::<f32>::load_from(input2)?); Ok(()) },
30                 "float64" => { compare_values(&Vec::<f64>::load_from(input1)?, &Vec::<f64>::load_from(input2)?); Ok(()) },
31                 _ => {
32                     print_usage();
33                     Err(Box::new(CliErr("Invalid data type")))
34                 }
35             }
36         },
37         _ => {
38             print_usage();
39             Err(Box::new(CliErr("Invalid arguments")))
40         },
41     }
42 }
43
44 fn print_usage() {
45     eprintln!("Usage: decode_vector data_type vector1_file vector2_file
46
47 Compares two vectors of elements in binary format. data_type can be one of
48 * i8
49 * u8
50 * i16
51 * u16
52 * i32
53 * u32
54 * i64
55 * u64
56 * f32
57 * f64
58
59 ");
60 }
61
62 fn compare_values<T>(values1: &[T], values2: &[T]) where
63     T: Display,
64     T: PartialOrd
65 {
66     if values1.len() != values2.len() {
67         println!("0");
68         eprintln!("Can only compare vectors of equal size. The first vector has {} elements. The second vector has {} elements.", values1.len(), values2.len());
69         return
70     }
71
72     let mut v1_smaller_count = 0;
73     let mut v2_smaller_count = 0;
74     let mut first_diff = None;
75
76     for (i, (v1, v2)) in values1.iter().zip(values2.iter()).enumerate() {
77         if v1 < v2 { v1_smaller_count += 1; }
78         if v2 < v1 { v2_smaller_count += 1; }
79
80         if first_diff.is_none() && v1 != v2 {
81             first_diff = Some(i)
82         }
83     }
84
85     match first_diff {
86         Some(index) => {
87             eprintln!("The vectors differ.");
88             eprintln!("{} elements are smaller in the first vector.", v1_smaller_count);
89             eprintln!("{} elements are smaller in the second vector.", v2_smaller_count);
90             eprintln!("{} elements are the same.", values1.len() - v1_smaller_count - v2_smaller_count);
91             println!("{}", values1.len() - v1_smaller_count - v2_smaller_count);
92             eprintln!("{} elements are different.", v1_smaller_count + v2_smaller_count);
93             eprintln!("The vectors have {} elements.", values1.len());
94             eprintln!("The first element that differs is at index {}.", index);
95         },
96         None => {
97             println!("{}", values1.len());
98             eprintln!("The vectors are the same and have {} elements.", values1.len());
99         },
100     }
101 }