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