tract_hir/ops/array/
gather.rs1use tract_core::ops::cast::cast;
2
3use crate::infer::*;
4use crate::internal::*;
5
6#[derive(Debug, Clone, new, Default, Hash)]
7pub struct Gather {
8 axis: i64,
9}
10
11impl Gather {
12 pub fn to_type_op(&self, input_rank: usize) -> tract_core::ops::array::Gather {
13 let axis = if self.axis < 0 { self.axis + input_rank as i64 } else { self.axis } as usize;
14 tract_core::ops::array::Gather::new(axis)
15 }
16}
17
18impl Expansion for Gather {
19 fn name(&self) -> StaticName {
20 "Gather".into()
21 }
22
23 fn wire(
24 &self,
25 prefix: &str,
26 model: &mut TypedModel,
27 inputs: &[OutletId],
28 ) -> TractResult<TVec<OutletId>> {
29 let input_rank = model.outlet_fact(inputs[0])?.rank();
30 let mut inputs: TVec<OutletId> = inputs.into();
31 inputs[1] = model.wire_node(
32 format!("{prefix}.cast_to_i64"),
33 cast(i64::datum_type()),
34 &[inputs[1]],
35 )?[0];
36 model.wire_node(prefix, self.to_type_op(input_rank), &inputs)
37 }
38
39 fn rules<'r, 'p: 'r, 's: 'r>(
40 &'s self,
41 s: &mut Solver<'r>,
42 inputs: &'p [TensorProxy],
43 outputs: &'p [TensorProxy],
44 ) -> InferenceResult {
45 check_input_arity(inputs, 2)?;
46 check_output_arity(outputs, 1)?;
47 s.equals(&inputs[0].datum_type, &outputs[0].datum_type)?;
48 s.equals(inputs[0].rank.bex() - 1 + inputs[1].rank.bex(), outputs[0].rank.bex())?;
49 s.given_2(&inputs[0].shape, &inputs[1].shape, move |s, input_shape, indices_shape| {
50 let rank = input_shape.len();
51 let output_shape =
52 self.to_type_op(rank).compute_output_shape(&input_shape, &indices_shape)?;
53 s.equals(&outputs[0].shape, output_shape)?;
54 Ok(())
55 })?;
56 Ok(())
57 }
58}