use crate::ir::{ArgType, Node, TensorType};
pub fn flatten_update_outputs(node: &mut Node) {
if node.inputs.len() != 1 {
panic!("Flatten: multiple inputs are not supported");
}
let tensor = node
.inputs
.iter()
.find_map(|input| match &input.ty {
ArgType::Tensor(tensor) => Some(tensor),
_ => None,
})
.unwrap();
node.outputs[0].ty = ArgType::Tensor(TensorType {
rank: 2,
..tensor.clone()
});
}
pub fn flatten_config(curr: &Node) -> usize {
let mut axis: i64 = 1;
if curr.inputs.len() != 1 {
panic!(
"Flatten: multiple inputs are not supported (got {:?})",
curr.inputs.len()
);
}
let tensor = match curr.inputs.first().unwrap().clone().ty {
ArgType::Tensor(tensor) => tensor,
_ => panic!("Only tensor input is valid"),
};
if tensor.rank < 2 {
panic!(
"Flatten: input tensor must have at least 2 dimensions (got {:?})",
tensor.rank
);
}
for (key, value) in curr.attrs.iter() {
if key.as_str() == "axis" {
axis = value.clone().into_i64()
}
}
if axis < 0 {
axis += tensor.rank as i64;
}
axis as usize
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ir::NodeType;
use crate::node::test_utils::NodeBuilder;
fn create_test_node(axis: i64) -> Node {
NodeBuilder::new(NodeType::Flatten, "test_flatten")
.input_tensor_f32("data", 4, None)
.output_tensor_f32("output", 2, None)
.attr_int("axis", axis)
.build()
}
#[test]
fn test_flatten_config_basic() {
let node = create_test_node(1);
let config = flatten_config(&node);
assert_eq!(config, 1);
}
#[test]
fn test_flatten_config_with_negative_axis() {
let node = create_test_node(-2);
let config = flatten_config(&node);
assert_eq!(config, 2); }
#[test]
#[should_panic(expected = "Flatten: input tensor must have at least 2 dimensions")]
fn test_flatten_config_with_low_rank() {
let mut node = create_test_node(1);
let input = NodeBuilder::new(NodeType::Identity, "temp")
.input_tensor_f32("x", 1, None)
.build()
.inputs
.pop()
.unwrap();
node.inputs[0] = input;
let _ = flatten_config(&node);
}
#[test]
#[should_panic(expected = "Flatten: multiple inputs are not supported")]
fn test_flatten_config_with_multiple_inputs() {
let mut node = create_test_node(1);
let extra_input = NodeBuilder::new(NodeType::Identity, "temp")
.input_tensor_f32("extra", 1, None)
.build()
.inputs
.pop()
.unwrap();
node.inputs.push(extra_input);
let _ = flatten_config(&node);
}
}