#include "tensorstore/index_space/index_transform.h"
template <DimensionIndex InputRank,
         
 DimensionIndex OutputRank,
         
 ContainerKind CKind>
absl::Status tensorstore::PropagateBounds(
    
std::type_identity_t<BoxView<OutputRank>> b_domain,
    
DimensionSet b_implicit_lower_bounds,
    
DimensionSet b_implicit_upper_bounds,
    
const IndexTransform<InputRank, OutputRank, CKind> a_to_b,
    
std::type_identity_t<MutableBoxView<InputRank>> a_domain,
    
DimensionSeta_implicit_lower_bounds,
    
DimensionSeta_implicit_upper_bounds);
template <DimensionIndex InputRank,
         
 DimensionIndex OutputRank,
         
 ContainerKind CKind>
absl::Status tensorstore::PropagateBounds(
    
std::type_identity_t<BoxView<OutputRank>> b_domain,
    
DimensionSet b_implicit_lower_bounds,
    
DimensionSet b_implicit_upper_bounds,
    
const IndexTransform<InputRank, OutputRank, CKind> a_to_b,
    
std::type_identity_t<MutableBoxView<InputRank>> a_domain);

Propagates bounds on an output index space b back to each input dimension input_dim of the input index space a as follows:

  1. The inferred_bounds are computed as the intersection of the bounds due to each output_dim of a_to_b that specifies input_dim as a OutputIndexMethod::single_input_dimension output index map.

  2. If the existing_bounds specified by a_to_b for input_dim are explicit, they must be contained in inferred_bounds.

  3. The lower and upper bounds a[input_dim] are set to the corresponding lower or upper bounds from existing_bounds if explicit or if no dimensions of b contributed to inferred_bounds, or otherwise from inferred_bounds.

  4. Each resultant lower/upper bounds for a is implicit iff:

    1. The original bound specified in a_to_b is implicit; and

    2. All contributing (by way of a OutputIndexMethod::single_input_dimension map) bounds of b are implicit.

Also checks that any constant output index maps have an output offset within the b domain (implicit bounds of b are ignored).

Parameters:
std::type_identity_t<BoxView<OutputRank>> b_domain

The bounds in the b index space.

DimensionSet b_implicit_lower_bounds

Implicit indicator for each lower bound of b.

DimensionSet b_implicit_upper_bounds

Implicit indicator for each upper bound of b.

const IndexTransform<InputRank, OutputRank, CKind> a_to_b

The transform. May be null to indicate an identity transform.

out
std::type_identity_t<MutableBoxView<InputRank>> a_domain

The propagated bounds in the a index space.

out
DimensionSet &a_implicit_lower_bounds

Propagated implicit indicators for each lower bound of a.

out
DimensionSet &a_implicit_upper_bounds

Propagated implicit indicators for each upper bound of a.

Dchecks:

a_to_b.valid() || a_domain.rank() == b_domain.rank()

Dchecks:

!a_to_b.valid() || b_domain.rank() == a_to_b.output_rank()

Dchecks:

!a_to_b.valid() || a_domain.rank() == a_to_b.input_rank()

Error absl::StatusCode::kInvalidArgument:

if integer overflow occurs when propagating bounds.

Error absl::StatusCode::kOutOfRange:

if the bounds are incompatible.

Warning

This function does not check OutputIndexMethod::array output index maps (as they do not influence the inferred bounds). Those must be checked separately.