Deconvolution/1D: Difference between revisions

m
→‎{{header|Raku}}: better sigil, consistent matrix notation, bells, whistles
No edit summary
m (→‎{{header|Raku}}: better sigil, consistent matrix notation, bells, whistles)
Line 1,264:
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.02}}
 
Translation of Python, using a modified version of the Reduced Row Echelon Form subroutine <code>rref()</code> from [[Reduced row echelon form#Raku|here Reduced row echelon form]] task.
 
<lang perl6>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 } }
return (rref( @m )[^$h;$h];
}
 
sub convolve (@f, @h) {
my @g = 0 xx + @f + @h - 1;
@g[^@f X+ ^@h] >>»+=<<« (@f X* @h);
return @g;
}
# Reduced Row Echelon Form simultaneous equation solver.
# Can handle over-specified systems of equations. (N unknowns in N + M equations)
sub rref ($@m is copy) {
# (n unknowns in n + m equations)
@m = trim-system @m;
sub rref ($m is copy) {
my ($lead, $rows, $cols) = 0, +$@m, +$@m[0];
return unless $m;
my ($lead, $rows, $cols) = 0, +$m, +$m[0];
 
# Trim off over specified rows if they exist, for efficiency
if $rows >= $cols {
$m = trim_system($m);
$rows = +$m;
}
 
for ^$rows -> $r {
return @m unless $lead < $cols or return $m;
my $i = $r;
until $@m[$i][;$lead] {
next unless ++$i == $rows or next;
$i = $r;
return @m if ++$lead == $cols and return $m;
}
$@m[$i, $r] = $@m[$r, $i] if $r != $i;
my @m[$lvr] »/=» $ = @m[$r][;$lead];
$m[$r] >>/=>> $lv;
for ^$rows -> $n {
next if $n == $r;
$@m[$n] >>»-=>>» $@m[$r] >>*>>»×» ($@m[$n][;$lead] // 0);
}
++$lead;
}
return $@m;
}
 
# Reduce a system of equations to n equations with n unknowns.
# Reduce to N equations in N unknowns; a no-op unless rows > cols
# Looks for an equation with a true value for each position.
sub trim-system (@m) {
# If it can't find one, assumes that it has already taken one
return @m unless $@m ≥ @m[0];
# and pushes in the first equation it sees. This assumtion
my ($\vars, @t) = +$@m[0] - 1, ();
# will alway be successful except in some cases where an
for ^$vars -> $\lead {
# under-specified system has been supplied, in which case,
for ^$@m -> $\row {
# it would not have been able to reduce the system anyway.
@t.pushappend: | $@m.splice( $row, 1 ) and last if $@m[$row][$;lead];
sub trim_system ($m is rw) {
my ($vars, @t) = +$m[0]-1, ();
for ^$vars -> $lead {
for ^$m -> $row {
@t.push: | $m.splice( $row, 1 ) and last if $m[$row][$lead];
}
}
while (+@t < $vars) and +$m { @t.push: $m.splice( 0, 1 ) };
return @t;
}
while (+@t < $vars) and +$@m { @t.push: $shift @m.splice( 0, 1 ) };
}@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 ~@g, ~convolve(@f, @h),'';
.say for ~@h, ~deconvolve(@g, @f),'';
.say for ~@f, ~deconvolve(@g, @h),'';</lang>
 
{{out}}
<pre>24 75 71 -34 3 22 -45 23 245 25 52 25 -67 -96 96 31 55 36 29 -43 -7
<pre>
24 75 71 -34 3 22 -45 23 245 25 52 25 -67 -96 96 31 55 36 29 -43 -7
24 75 71 -34 3 22 -45 23 245 25 52 25 -67 -96 96 31 55 36 29 -43 -7
 
Line 1,355 ⟶ 1,335:
 
-3 -6 -1 8 -6 3 -1 -9 -9 3 -2 5 2 -2 -7 -1
-3 -6 -1 8 -6 3 -1 -9 -9 3 -2 5 2 -2 -7 -1</pre>
</pre>
 
=={{header|REXX}}==
2,392

edits