59 lines
1.6 KiB
Raku
59 lines
1.6 KiB
Raku
sub deconvolve (@g, @f) {
|
||
my \h = 1 + @g - @f;
|
||
my @m;
|
||
@m[^@g;^h] »+=» 0;
|
||
@m[^@g; h] »=« @g;
|
||
for ^h -> \j { for @f.kv -> \k, \v { @m[j+k;j] = v } }
|
||
(rref @m)[^h;h]
|
||
}
|
||
|
||
sub convolve (@f, @h) {
|
||
my @g = 0 xx + @f + @h - 1;
|
||
@g[^@f X+ ^@h] »+=« (@f X× @h);
|
||
@g
|
||
}
|
||
|
||
# Reduced Row Echelon Form simultaneous equation solver
|
||
# Can handle over-specified systems of equations (N unknowns in N + M equations)
|
||
sub rref (@m) {
|
||
@m = trim-system @m;
|
||
my ($lead, $rows, $cols) = 0, @m, @m[0];
|
||
for ^$rows -> $r {
|
||
return @m unless $lead < $cols;
|
||
my $i = $r;
|
||
until @m[$i;$lead] {
|
||
next unless ++$i == $rows;
|
||
$i = $r;
|
||
return @m if ++$lead == $cols;
|
||
}
|
||
@m[$i, $r] = @m[$r, $i] if $r != $i;
|
||
@m[$r] »/=» $ = @m[$r;$lead];
|
||
for ^$rows -> $n {
|
||
next if $n == $r;
|
||
@m[$n] »-=» @m[$r] »×» (@m[$n;$lead] // 0);
|
||
}
|
||
++$lead;
|
||
}
|
||
@m
|
||
}
|
||
|
||
# Reduce to N equations in N unknowns; a no-op unless rows > cols
|
||
sub trim-system (@m) {
|
||
return @m unless @m ≥ @m[0];
|
||
my (\vars, @t) = @m[0] - 1;
|
||
for ^vars -> \lead {
|
||
for ^@m -> \row {
|
||
@t.append: @m.splice(row, 1) and last if @m[row;lead];
|
||
}
|
||
}
|
||
while @t < vars and @m { @t.push: shift @m }
|
||
@t
|
||
}
|
||
|
||
my @h = (-8,-9,-3,-1,-6,7);
|
||
my @f = (-3,-6,-1,8,-6,3,-1,-9,-9,3,-2,5,2,-2,-7,-1);
|
||
my @g = (24,75,71,-34,3,22,-45,23,245,25,52,25,-67,-96,96,31,55,36,29,-43,-7);
|
||
|
||
.say for ~@g, ~convolve(@f, @h),'';
|
||
.say for ~@h, ~deconvolve(@g, @f),'';
|
||
.say for ~@f, ~deconvolve(@g, @h),'';
|