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#

$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#

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()).