runmat_runtime/
comparison.rs1use std::cmp::Ordering;
6
7use runmat_value::Tensor;
8
9use crate::builtins::common::tensor::tensor_values_f64_cow;
10use crate::builtins::logical::rel::integer_comparison::{
11 compare_integer_values, integer_f64_order, matches_optional_relation, matches_relation,
12 storage_value, IntegerComparisonOp,
13};
14
15pub fn matrix_gt(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
17 matrix_compare(a, b, ">", IntegerComparisonOp::Gt, |x, y| x > y)
18}
19
20pub fn matrix_ge(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
22 matrix_compare(a, b, ">=", IntegerComparisonOp::Ge, |x, y| x >= y)
23}
24
25pub fn matrix_lt(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
27 matrix_compare(a, b, "<", IntegerComparisonOp::Lt, |x, y| x < y)
28}
29
30pub fn matrix_le(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
32 matrix_compare(a, b, "<=", IntegerComparisonOp::Le, |x, y| x <= y)
33}
34
35pub fn matrix_eq(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
37 matrix_compare(a, b, "==", IntegerComparisonOp::Eq, |x, y| x == y)
38}
39
40pub fn matrix_ne(a: &Tensor, b: &Tensor) -> Result<Tensor, String> {
42 matrix_compare(a, b, "!=", IntegerComparisonOp::Ne, |x, y| x != y)
43}
44
45fn matrix_compare(
46 a: &Tensor,
47 b: &Tensor,
48 symbol: &str,
49 operation: IntegerComparisonOp,
50 float_compare: impl Fn(f64, f64) -> bool,
51) -> Result<Tensor, String> {
52 if a.rows() != b.rows() || a.cols() != b.cols() {
53 return Err(format!(
54 "Matrix dimensions must agree: {}x{} {} {}x{}",
55 a.rows(),
56 a.cols(),
57 symbol,
58 b.rows(),
59 b.cols()
60 ));
61 }
62
63 let data: Vec<f64> = match (a.integer_storage(), b.integer_storage()) {
64 (Some(left), Some(right)) => (0..left.len())
65 .map(|index| {
66 let ordering =
67 compare_integer_values(storage_value(left, index), storage_value(right, index));
68 logical_f64(matches_relation(ordering, operation))
69 })
70 .collect(),
71 (Some(left), None) => {
72 let right = tensor_values_f64_cow(b);
73 (0..left.len())
74 .map(|index| {
75 logical_f64(matches_optional_relation(
76 integer_f64_order(storage_value(left, index), right[index]),
77 operation,
78 ))
79 })
80 .collect()
81 }
82 (None, Some(right)) => {
83 let left = tensor_values_f64_cow(a);
84 (0..right.len())
85 .map(|index| {
86 let ordering = integer_f64_order(storage_value(right, index), left[index])
87 .map(Ordering::reverse);
88 logical_f64(matches_optional_relation(ordering, operation))
89 })
90 .collect()
91 }
92 (None, None) => {
93 let left = tensor_values_f64_cow(a);
94 let right = tensor_values_f64_cow(b);
95 left.iter()
96 .zip(right.iter())
97 .map(|(x, y)| logical_f64(float_compare(*x, *y)))
98 .collect()
99 }
100 };
101
102 Tensor::new_2d(data, a.rows(), a.cols())
103}
104
105fn logical_f64(value: bool) -> f64 {
106 if value {
107 1.0
108 } else {
109 0.0
110 }
111}