fn get_boundary_constraints>()

in air/src/air/mod.rs [284:329]


    fn get_boundary_constraints<E: FieldElement<BaseField = Self::BaseField>>(
        &self,
        coefficients: &[(E, E)],
    ) -> Vec<BoundaryConstraintGroup<Self::BaseField, E>> {
        // compute inverse of the trace domain generator; this will be used for offset
        // computations when creating sequence constraints
        let inv_g = self.trace_domain_generator().inv();

        // cache inverse twiddles for multi-value assertions in this map so that we don't have
        // to re-build them for assertions with identical strides
        let mut twiddle_map = BTreeMap::new();

        // get the assertions for this computation and make sure that they are all valid in
        // the context of this computation; also, sort the assertions in the deterministic order
        // so that changing the order of assertions does not change random coefficients that
        // get assigned to them
        let assertions = prepare_assertions(self.get_assertions(), self.context());
        assert_eq!(
            assertions.len(),
            coefficients.len(),
            "number of assertions must match the number of coefficient tuples"
        );

        // iterate over all assertions, which are sorted first by stride and then by first_step
        // in ascending order
        let mut groups = BTreeMap::new();
        for (i, assertion) in assertions.into_iter().enumerate() {
            let key = (assertion.stride(), assertion.first_step());
            let group = groups.entry(key).or_insert_with(|| {
                BoundaryConstraintGroup::new(
                    ConstraintDivisor::from_assertion(&assertion, self.trace_length()),
                    self.trace_poly_degree(),
                    self.composition_degree(),
                )
            });

            // add a new assertion constraint to the current group (last group in the list)
            group.add(assertion, inv_g, &mut twiddle_map, coefficients[i]);
        }

        // make sure groups are sorted by adjustment degree
        let mut groups = groups.into_iter().map(|e| e.1).collect::<Vec<_>>();
        groups.sort_by_key(|c| c.degree_adjustment());

        groups
    }