```{index} single: inner; PDL::Primitive function ``` ```{index} single: PDL::Primitive::inner; Perl function ``` # inner `inner($a, $b)` -- inner (dot) product along the first dimension. Given two ndarrays with matching first-axis length `n`, computes `c = sum_i a_i * b_i` as a 0-dim PDL. For 1-D inputs this is the standard dot product; for higher-rank inputs the contraction is over axis 0 and the remaining axes broadcast. ## Signature ```perl $c = inner($a, $b); # function form $c = $a->inner($b); # method form ``` Upstream also accepts a 3-arg form `inner($a, $b, $c)` writing into an output PDL `$c`; that form is not yet wired through the connector shim -- supply only two arguments. ## Broadcasting Upstream `inner` has signature `(a(n); b(n); [o]c())` and broadcasts over all axes beyond the contracted first axis. The connector shim currently implements the 1-D / whole-array case: it multiplies `$a * $b` element-wise (via the engine's `pdl_run_mult`, which _does_ broadcast) and then reduces the product with `sumover`. For genuinely 1-D inputs this matches upstream; for multi-axis inputs the result is a full reduction over _all_ axes, not the per-row inner product upstream gives. See the performance note below. ## Bad values Bad-value handling is inherited from `pdl_run_mult` and `pdl_run_sumover`: products containing a BAD operand propagate BAD, then `sumover` skips BAD cells. If every product is BAD the result PDL is BAD-flagged; otherwise it is clean. Matches the `=for bad` stanza in upstream `PDL::Primitive::inner`. ## Examples ```perl use PDL; my $a = pdl([1, 2, 3]); my $b = pdl([4, 5, 6]); print inner($a, $b); # 32 (1*4 + 2*5 + 3*6) print $a->inner($b); # 32 (method form) ## Scalar-on-vector also works (scalar broadcasts to each element) print inner(pdl([1, 2, 3]), 2); # 12 (1*2 + 2*2 + 3*2) ``` ## Errors Croaks via `croak_c_pdl_error` if either the `mult` or the `sumover` engine step returns an error (e.g. dimension mismatch inside `mult`). Returns `undef` when either input cannot be coerced to a PDL or scalar. ## Performance notes **Connector-side shim pending engine delivery.** PDL's `PP`-generated `inner` routine (`Primitive_pp_inner`) was not picked up by the c2rust transpile pass (the `readdata` codegen template is not supported), so until the engine ships a native `pdl_run_inner` we emulate it in two steps -- one `mult` allocation and one `sumover` reduction. Cost is one full pass over the product buffer plus its allocation; no SIMD fused multiply-add is used. This will be replaced by a direct call once the engine delivers the op. ## Upstream Mirrors `PDL::Primitive::inner` in `lib/PDL/Primitive.pm` (generated from `lib/PDL/Primitive.pd`); upstream signature `(a(n); b(n); [o]c())`.