shape_broadcast.h#

Shared helpers for shape-inference functions of binary ONNX operators that support numpy-style (multidirectional) broadcasting.

namespace onnx_light

Alias that makes onnx-light headers compatible with code that references ONNX_LIGHT_NAMESPACE (the macro used in the standard onnx package).

Set to ONNX_LIGHT_NAMESPACE so both names resolve to the same namespace.

Symbol-visibility attribute for the public onnx-light C++ API.

Defined as empty because onnx-light does not require explicit __declspec(dllexport) or __attribute__((visibility("default"))) annotations — visibility is controlled at the shared-library level. The macro is provided so that vendored ONNX headers that decorate their declarations with ONNX_API compile without modification.

Namespace alias so that ONNX C++ code (and consumers such as onnxruntime) that refers to the literal onnx namespace — rather than the ONNX_NAMESPACE macro — resolves to the onnx-light namespace. The standard onnx package lives in namespace onnx; onnx-light uses onnx_light (via ONNX_LIGHT_NAMESPACE), so this alias keeps onnx-light a true drop-in. It is only introduced when the onnx-light namespace differs from onnx.

namespace onnx_optim
namespace shapes

Enums

enum class BroadcastDimOp#

Kind of elementwise arithmetic to apply when propagating :cpp:func:OptimTensor::ValueAsShape through a numpy-broadcasting binary operator with :cpp:func:PropagateValueAsShapeArithmetic.

Values:

enumerator kAdd#
enumerator kSub#

Functions

OptimShape BroadcastShapes(const OptimShape &a, const OptimShape &b)#

Computes the broadcast result shape of two :cpp:class:OptimShape operands following the ONNX (numpy-style) multidirectional broadcasting rules.

The shapes are right-aligned and the dimensions are paired starting from the trailing axis (missing leading dimensions are treated as 1). For each paired dimension (d_a, d_b) the resulting dimension is computed as follows:

  • if both are concrete integers: standard broadcasting rules are enforced — equal dimensions or a dimension of 1 paired with anything are accepted; mismatching non-unit integers throw std::invalid_argument;

  • if either is the integer 1: the result is the other dimension;

  • if both are equal (same integer or same symbolic expression): the result is that dimension;

  • if one is a concrete integer (different from 1) and the other is symbolic: the concrete integer wins (it is the only value compatible with broadcasting against itself);

  • if both are different symbolic expressions: a fresh symbolic dimension is produced, encoding the broadcast as "broadcast(<a>, <b>)" so that the symbolic information is preserved.

Throws:

std::invalid_argument – when two concrete integer dimensions are incompatible under broadcasting.

void ComputeShapeBinaryBroadcast(ShapesContext &ctx, const NodeProto &node, const char *input_a, const char *input_b, const char *expected_op_type, TensorType output_dtype)#

Generic shape-inference helper for binary ONNX operators that support numpy-style broadcasting. Reads the descriptors of input_a and input_b from ctx, computes the broadcast output shape and stores a new entry under node.output(0) with the given output_dtype.

The helper enforces the following preconditions:

  • node.op_type() must equal expected_op_type;

  • node must declare at least one output;

  • both input_a and input_b must be present in ctx.

Throws:
  • std::invalid_argument – if node.op_type() differs from expected_op_type or if node has no output, or if the two input shapes are not broadcast-compatible.

  • std::out_of_range – if either input name is missing from ctx.

void PropagateValueAsShapeArithmetic(ShapesContext &ctx, const NodeProto &node, const char *input_a, const char *input_b, BroadcastDimOp op)#

Propagates the ValueAsShape annotation through a numpy-broadcast binary operator that performs elementwise integer arithmetic (currently Add and Sub).

If both inputs of node carry a ValueAsShape annotation, the helper combines them with right-aligned broadcasting using the matching :cpp:func:expressions::dim_add / :cpp:func:expressions::dim_sub operation, and writes the resulting 1-D dim vector back as the ValueAsShape of node.output(0) (which must already exist in ctx). Missing leading dimensions on the shorter side are treated as the integer 1, matching numpy’s broadcasting rules.

Does nothing if either input is missing a ValueAsShape or if the resulting shape would exceed :cpp:var:kMaxOptimRank dims.