tract_hir/ops/array/
reshape.rs

1use crate::infer::*;
2use crate::internal::*;
3
4#[derive(Debug, Clone, new, Default, Hash)]
5pub struct Reshape {}
6
7impl Expansion for Reshape {
8    fn name(&self) -> StaticName {
9        "Reshape".into()
10    }
11
12    fn rules<'r, 'p: 'r, 's: 'r>(
13        &'s self,
14        s: &mut Solver<'r>,
15        inputs: &'p [TensorProxy],
16        outputs: &'p [TensorProxy],
17    ) -> InferenceResult {
18        s.equals(&outputs[0].datum_type, &inputs[0].datum_type)?;
19        s.given_2(&inputs[0].shape, &inputs[1].value, move |s, ishape, shape| {
20            let shape = shape.cast_to::<TDim>()?;
21            let shape = shape.as_slice::<TDim>()?;
22            let oshape = tract_core::ops::change_axes::compute_shape_with_tf_rules(&ishape, shape)
23                .with_context(|| format!("Reshaping {ishape:?} to {shape:?}"))?;
24            s.equals(&outputs[0].shape, ShapeFactoid::from(oshape))
25        })
26    }
27
28    fn wire(
29        &self,
30        prefix: &str,
31        model: &mut TypedModel,
32        inputs: &[OutletId],
33    ) -> TractResult<TVec<OutletId>> {
34        if let Some(ref shape) = model.outlet_fact(inputs[1])?.konst {
35            let input_shape: TVec<TDim> = model.outlet_fact(inputs[0])?.shape.to_tvec();
36            let shape = shape.cast_to::<TDim>()?;
37            let shape = shape.as_slice::<TDim>()?;
38            let mut wire = tvec!(inputs[0]);
39            for (ix, op) in to_axis_ops_with_tf_rules(&input_shape, shape)?.into_iter().enumerate() {
40                wire = model.wire_node(format!("{prefix}.{ix}"), op, &wire)?;
41            }
42            return Ok(wire);
43        }
44        bail!("shape input is variable")
45    }
46}