runmat_runtime/builtins/array/sorting_sets/
issortedrows.rs1use runmat_builtins::{
4 BuiltinCompletionPolicy, BuiltinDescriptor, BuiltinErrorDescriptor, BuiltinOutputMode,
5 BuiltinParamArity, BuiltinParamDescriptor, BuiltinParamType, BuiltinSignatureDescriptor, Value,
6};
7use runmat_macros::runtime_builtin;
8
9const OUTPUTS: [BuiltinParamDescriptor; 1] = [BuiltinParamDescriptor {
10 name: "tf",
11 ty: BuiltinParamType::LogicalArray,
12 arity: BuiltinParamArity::Required,
13 default: None,
14 description: "True when rows are sorted according to the requested row order.",
15}];
16
17const INPUTS: [BuiltinParamDescriptor; 2] = [
18 BuiltinParamDescriptor {
19 name: "A",
20 ty: BuiltinParamType::Any,
21 arity: BuiltinParamArity::Required,
22 default: None,
23 description: "Input matrix, character matrix, complex matrix, or table.",
24 },
25 BuiltinParamDescriptor {
26 name: "args",
27 ty: BuiltinParamType::Any,
28 arity: BuiltinParamArity::Variadic,
29 default: None,
30 description: "Column, direction, comparison, and missing-placement options.",
31 },
32];
33
34const SIGNATURES: [BuiltinSignatureDescriptor; 2] = [
35 BuiltinSignatureDescriptor {
36 label: "tf = issortedrows(A)",
37 inputs: &INPUTS,
38 outputs: &OUTPUTS,
39 },
40 BuiltinSignatureDescriptor {
41 label: "tf = issortedrows(A, args...)",
42 inputs: &INPUTS,
43 outputs: &OUTPUTS,
44 },
45];
46
47const ERROR_INVALID_INPUT: BuiltinErrorDescriptor = BuiltinErrorDescriptor {
48 code: "RM.ISSORTEDROWS.INVALID_INPUT",
49 identifier: Some("RunMat:issortedrows:InvalidInput"),
50 when: "Input or row-sorting arguments are invalid.",
51 message: "issortedrows: invalid input",
52};
53
54const ERRORS: [BuiltinErrorDescriptor; 1] = [ERROR_INVALID_INPUT];
55
56pub const ISSORTEDROWS_DESCRIPTOR: BuiltinDescriptor = BuiltinDescriptor {
57 signatures: &SIGNATURES,
58 output_mode: BuiltinOutputMode::Fixed,
59 completion_policy: BuiltinCompletionPolicy::Public,
60 errors: &ERRORS,
61};
62
63#[runtime_builtin(
64 name = "issortedrows",
65 category = "array/sorting_sets",
66 summary = "Determine whether matrix or table rows are sorted.",
67 keywords = "issortedrows,sortrows,rows,sorted,table",
68 accel = "sink",
69 sink = true,
70 descriptor(crate::builtins::array::sorting_sets::issortedrows::ISSORTEDROWS_DESCRIPTOR),
71 builtin_path = "crate::builtins::array::sorting_sets::issortedrows"
72)]
73async fn issortedrows_builtin(value: Value, rest: Vec<Value>) -> crate::BuiltinResult<Value> {
74 let evaluation = crate::builtins::array::sorting_sets::sortrows::evaluate(value, &rest).await?;
75 let indices = evaluation.indices_value();
76 let sorted = match indices {
77 Value::Tensor(tensor) => tensor
78 .data
79 .iter()
80 .enumerate()
81 .all(|(idx, value)| *value == idx as f64 + 1.0),
82 Value::Num(value) => value == 1.0,
83 Value::Int(value) => value.to_i64() == 1,
84 _ => false,
85 };
86 Ok(Value::Bool(sorted))
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use futures::executor::block_on;
93 use runmat_builtins::Tensor;
94
95 #[test]
96 fn issortedrows_detects_sorted_and_unsorted_numeric_rows() {
97 let sorted = Value::Tensor(Tensor::new(vec![1.0, 2.0, 1.0, 3.0], vec![2, 2]).unwrap());
98 assert_eq!(
99 block_on(issortedrows_builtin(sorted, Vec::new())).unwrap(),
100 Value::Bool(true)
101 );
102 let unsorted = Value::Tensor(Tensor::new(vec![2.0, 1.0, 1.0, 3.0], vec![2, 2]).unwrap());
103 assert_eq!(
104 block_on(issortedrows_builtin(unsorted, Vec::new())).unwrap(),
105 Value::Bool(false)
106 );
107 assert_eq!(
108 block_on(issortedrows_builtin(Value::Num(1.0), Vec::new())).unwrap(),
109 Value::Bool(true)
110 );
111 }
112}