Deconvolution/2D+: Difference between revisions

m
m (→‎{{header|Perl 6}}: Fixed up some formatting)
m (→‎{{header|Wren}}: Minor tidy)
 
(38 intermediate revisions by 13 users not shown)
Line 80:
</pre>
 
=={{header|C}}==
Very tedious code: unpacks 2D or 3D matrix into a vector with padding, do 1D FFT, then pack result back into matrix.
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
double PI;
typedef double complex cplx;
void _fft(cplx buf[], cplx out[], int n, int step)
{
if (step < n) {
_fft(out, buf, n, step * 2);
_fft(out + step, buf + step, n, step * 2);
for (int i = 0; i < n; i += 2 * step) {
cplx t = cexp(-I * PI * i / n) * out[i + step];
buf[i / 2] = out[i] + t;
buf[(i + n)/2] = out[i] - t;
}
}
}
void fft(cplx buf[], int n)
{
cplx out[n];
for (int i = 0; i < n; i++) out[i] = buf[i];
_fft(buf, out, n, 1);
}
/* pad array length to power of two */
cplx *pad_two(double g[], int len, int *ns)
{
int n = 1;
if (*ns) n = *ns;
else while (n < len) n *= 2;
cplx *buf = calloc(sizeof(cplx), n);
for (int i = 0; i < len; i++) buf[i] = g[i];
*ns = n;
return buf;
}
void deconv(double g[], int lg, double f[], int lf, double out[], int row_len) {
int ns = 0;
cplx *g2 = pad_two(g, lg, &ns);
cplx *f2 = pad_two(f, lf, &ns);
fft(g2, ns);
fft(f2, ns);
cplx h[ns];
for (int i = 0; i < ns; i++) h[i] = g2[i] / f2[i];
fft(h, ns);
 
for (int i = 0; i < ns; i++) {
if (cabs(creal(h[i])) < 1e-10)
h[i] = 0;
}
 
for (int i = 0; i > lf - lg - row_len; i--)
out[-i] = h[(i + ns) % ns]/32;
free(g2);
free(f2);
}
 
double* unpack2(void *m, int rows, int len, int to_len)
{
double *buf = calloc(sizeof(double), rows * to_len);
for (int i = 0; i < rows; i++)
for (int j = 0; j < len; j++)
buf[i * to_len + j] = ((double(*)[len])m)[i][j];
return buf;
}
 
void pack2(double * buf, int rows, int from_len, int to_len, void *out)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < to_len; j++)
((double(*)[to_len])out)[i][j] = buf[i * from_len + j] / 4;
}
 
void deconv2(void *g, int row_g, int col_g, void *f, int row_f, int col_f, void *out) {
double *g2 = unpack2(g, row_g, col_g, col_g);
double *f2 = unpack2(f, row_f, col_f, col_g);
 
double ff[(row_g - row_f + 1) * col_g];
deconv(g2, row_g * col_g, f2, row_f * col_g, ff, col_g);
pack2(ff, row_g - row_f + 1, col_g, col_g - col_f + 1, out);
 
free(g2);
free(f2);
}
 
double* unpack3(void *m, int x, int y, int z, int to_y, int to_z)
{
double *buf = calloc(sizeof(double), x * to_y * to_z);
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++) {
for (int k = 0; k < z; k++)
buf[(i * to_y + j) * to_z + k] =
((double(*)[y][z])m)[i][j][k];
}
return buf;
}
 
void pack3(double * buf, int x, int y, int z, int to_y, int to_z, void *out)
{
for (int i = 0; i < x; i++)
for (int j = 0; j < to_y; j++)
for (int k = 0; k < to_z; k++)
((double(*)[to_y][to_z])out)[i][j][k] =
buf[(i * y + j) * z + k] / 4;
}
 
void deconv3(void *g, int gx, int gy, int gz, void *f, int fx, int fy, int fz, void *out) {
double *g2 = unpack3(g, gx, gy, gz, gy, gz);
double *f2 = unpack3(f, fx, fy, fz, gy, gz);
 
double ff[(gx - fx + 1) * gy * gz];
deconv(g2, gx * gy * gz, f2, fx * gy * gz, ff, gy * gz);
pack3(ff, gx - fx + 1, gy, gz, gy - fy + 1, gz - fz + 1, out);
 
free(g2);
free(f2);
}
 
int main()
{
PI = atan2(1,1) * 4;
double h[2][3][4] = {
{{-6, -8, -5, 9}, {-7, 9, -6, -8}, { 2, -7, 9, 8}},
{{ 7, 4, 4, -6}, { 9, 9, 4, -4}, {-3, 7, -2, -3}}
};
int hx = 2, hy = 3, hz = 4;
double f[3][2][3] = { {{-9, 5, -8}, { 3, 5, 1}},
{{-1, -7, 2}, {-5, -6, 6}},
{{ 8, 5, 8}, {-2, -6, -4}} };
int fx = 3, fy = 2, fz = 3;
double g[4][4][6] = {
{ { 54, 42, 53, -42, 85, -72}, { 45,-170, 94, -36, 48, 73},
{-39, 65,-112, -16, -78, -72}, { 6, -11, -6, 62, 49, 8} },
{ {-57, 49, -23, 52, -135, 66},{-23, 127, -58, -5, -118, 64},
{ 87, -16, 121, 23, -41, -12},{-19, 29, 35,-148, -11, 45} },
{ {-55, -147, -146, -31, 55, 60},{-88, -45, -28, 46, -26,-144},
{-12, -107, -34, 150, 249, 66},{ 11, -15, -34, 27, -78, -50} },
{ { 56, 67, 108, 4, 2,-48},{ 58, 67, 89, 32, 32, -8},
{-42, -31,-103, -30,-23, -8},{ 6, 4, -26, -10, 26, 12}
}
};
int gx = 4, gy = 4, gz = 6;
 
double h2[gx - fx + 1][gy - fy + 1][gz - fz + 1];
deconv3(g, gx, gy, gz, f, fx, fy, fz, h2);
printf("deconv3(g, f):\n");
for (int i = 0; i < gx - fx + 1; i++) {
for (int j = 0; j < gy - fy + 1; j++) {
for (int k = 0; k < gz - fz + 1; k++)
printf("%g ", h2[i][j][k]);
printf("\n");
}
if (i < gx - fx) printf("\n");
}
 
double f2[gx - hx + 1][gy - hy + 1][gz - hz + 1];
deconv3(g, gx, gy, gz, h, hx, hy, hz, f2);
printf("\ndeconv3(g, h):\n");
for (int i = 0; i < gx - hx + 1; i++) {
for (int j = 0; j < gy - hy + 1; j++) {
for (int k = 0; k < gz - hz + 1; k++)
printf("%g ", f2[i][j][k]);
printf("\n");
}
if (i < gx - hx) printf("\n");
}
}
 
/* two-D case; since task doesn't require showing it, it's commented out */
/*
int main()
{
PI = atan2(1,1) * 4;
double h[][6] = { {-8, 1, -7, -2, -9, 4},
{4, 5, -5, 2, 7, -1},
{-6, -3, -3, -6, 9, 5} };
int hr = 3, hc = 6;
 
double f[][5] = { {-5, 2, -2, -6, -7},
{9, 7, -6, 5, -7},
{1, -1, 9, 2, -7},
{5, 9, -9, 2, -5},
{-8, 5, -2, 8, 5} };
int fr = 5, fc = 5;
double g[][10] = {
{40, -21, 53, 42, 105, 1, 87, 60, 39, -28},
{-92, -64, 19, -167, -71, -47, 128, -109, 40, -21},
{58, 85, -93, 37, 101, -14, 5, 37, -76, -56},
{-90, -135, 60, -125, 68, 53, 223, 4, -36, -48},
{78, 16, 7, -199, 156, -162, 29, 28, -103, -10},
{-62, -89, 69, -61, 66, 193, -61, 71, -8, -30},
{48, -6, 21, -9, -150, -22, -56, 32, 85, 25} };
int gr = 7, gc = 10;
 
double h2[gr - fr + 1][gc - fc + 1];
deconv2(g, gr, gc, f, fr, fc, h2);
for (int i = 0; i < gr - fr + 1; i++) {
for (int j = 0; j < gc - fc + 1; j++)
printf(" %g", h2[i][j]);
printf("\n");
}
 
double f2[gr - hr + 1][gc - hc + 1];
deconv2(g, gr, gc, h, hr, hc, f2);
for (int i = 0; i < gr - hr + 1; i++) {
for (int j = 0; j < gc - hc + 1; j++)
printf(" %g", f2[i][j]);
printf("\n");
}
}*/</syntaxhighlight>Output<syntaxhighlight lang="text">deconv3(g, f):
-6 -8 -5 9
-7 9 -6 -8
2 -7 9 8
 
7 4 4 -6
9 9 4 -4
-3 7 -2 -3
 
deconv3(g, h):
-9 5 -8
3 5 1
 
-1 -7 2
-5 -6 6
 
8 5 8
-2 -6 -4 </syntaxhighlight>
 
=={{header|D}}==
<syntaxhighlight lang="d">import std.stdio, std.conv, std.algorithm, std.numeric, std.range;
 
class M(T) {
private size_t[] dim;
private size_t[] subsize;
private T[] d;
 
this(size_t[] dimension...) pure nothrow {
setDimension(dimension);
d[] = 0; // init each entry to zero;
}
 
M!T dup() {
auto m = new M!T(dim);
return m.set1DArray(d);
}
 
M!T setDimension(size_t[] dimension ...) pure nothrow {
foreach (const e; dimension)
assert(e > 0, "no zero dimension");
dim = dimension.dup;
subsize = dim.dup;
foreach (immutable i; 0 .. dim.length)
subsize[i] = reduce!q{a * b}(1, dim[i + 1 .. $]);
immutable dlength = dim[0] * subsize[0];
if (d.length != dlength)
d = new T[dlength];
return this;
}
 
M!T set1DArray(in T[] t ...) pure nothrow @nogc {
auto minLen = min(t.length, d.length);
d[] = 0;
d[0 .. minLen] = t[0 .. minLen];
return this;
}
 
size_t[] seq2idx(in size_t seq) const pure nothrow {
size_t acc = seq, tmp;
size_t[] idx;
foreach (immutable e; subsize) {
idx ~= tmp = acc / e;
acc = acc - tmp * e; // same as % (mod) e.
}
return idx;
}
 
size_t size() const pure nothrow @nogc @property {
return d.length;
}
 
size_t rank() const pure nothrow @nogc @property {
return dim.length;
}
 
size_t[] shape() const pure nothrow @property { return dim.dup; }
 
T[] raw() const pure nothrow @property { return d.dup; }
 
bool checkBound(size_t[] idx ...) const pure nothrow @nogc {
if (idx.length > dim.length)
return false;
foreach (immutable i, immutable dm; idx)
if (dm >= dim[i])
return false;
return true;
}
 
T opIndex(size_t[] idx ...) const pure nothrow @nogc {
assert(checkBound(idx), "OOPS");
return d[dotProduct(idx, subsize)];
}
 
T opIndexAssign(T v, size_t[] idx ...) pure nothrow @nogc {
assert(checkBound(idx), "OOPS");
d[dotProduct(idx, subsize)] = v;
return v;
}
 
override bool opEquals(Object o) const pure {
const rhs = to!(M!T)(o);
return dim == rhs.dim && d == rhs.d;
}
 
int opApply(int delegate(ref size_t[]) dg) const {
size_t[] yieldIdx;
foreach (immutable i; 0 .. d.length) {
yieldIdx = seq2idx(i);
if (dg(yieldIdx))
break;
}
return 0;
}
 
int opApply(int delegate(ref size_t[], ref T) dg) {
size_t idx1d = 0;
foreach (idx; this) {
if (dg(idx, d[idx1d++]))
break;
}
return 0;
}
 
// _this_ is h, rhs is f, output g.
M!T convolute(M!T rhs) const pure nothrow {
auto dm = dim.dup;
dm[] += rhs.dim[] - 1;
M!T m = new M!T(dm); // dm will be reused as m's idx.
auto bound = m.size;
foreach (immutable i; 0 .. d.length) {
auto thisIdx = seq2idx(i);
foreach (immutable j; 0 .. rhs.d.length) {
dm[] = thisIdx[] + rhs.seq2idx(j)[];
immutable midx1d = dotProduct(dm, m.subsize);
if (midx1d < bound)
m.d[midx1d] += d[i] * rhs.d[j];
else
break; // Bound reach, OK to break.
}
}
return m;
}
 
// _this_ is g, rhs is f, output is h.
M!T deconvolute(M!T rhs) const pure nothrow {
auto dm = dim.dup;
foreach (i, e; dm)
assert(e + 1 > rhs.dim[i],
"deconv : dimensions is zero or negative");
dm[] -= (rhs.dim[] - 1);
auto m = new M!T(dm); // dm will be reused as rhs' idx.
 
foreach (immutable i; 0 .. m.size) {
auto idx = m.seq2idx(i);
m.d[i] = this[idx];
foreach (immutable j; 0 .. i) {
immutable jdx = m.seq2idx(j);
dm[] = idx[] - jdx[];
if (rhs.checkBound(dm))
m.d[i] -= m.d[j] * rhs[dm];
}
m.d[i] /= rhs.d[0];
}
return m;
}
 
override string toString() const pure { return d.text; }
}
 
auto fold(T)(T[] arr, ref size_t[] d) pure {
if (d.length == 0)
d ~= arr.length;
 
static if (is(T U : U[])) { // Is arr an array of arrays?
assert(arr.length > 0, "no empty dimension");
d ~= arr[0].length;
foreach (e; arr)
assert(e.length == arr[0].length, "Not rectangular");
return fold(arr.reduce!q{a ~ b}, d);
} else {
assert(arr.length == d.reduce!q{a * b}, "Not same size");
return arr;
}
}
 
auto arr2M(T)(T a) pure {
size_t[] dm;
auto d = fold(a, dm);
alias E = ElementType!(typeof(d));
auto m = new M!E(dm);
m.set1DArray(d);
return m;
}
 
void main() {
alias Mi = M!int;
auto hh = [[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]],
[[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]];
auto ff = [[[-9, 5, -8], [3, 5, 1]],[[-1, -7, 2], [-5, -6, 6]],
[[8, 5, 8],[-2, -6, -4]]];
auto h = arr2M(hh);
auto f = arr2M(ff);
 
const g = h.convolute(f);
 
writeln("g == f convolute h ? ", g == f.convolute(h));
writeln("h == g deconv f ? ", h == g.deconvolute(f));
writeln("f == g deconv h ? ", f == g.deconvolute(h));
writeln(" f = ", f);
writeln("g deconv h = ", g.deconvolute(h));
}</syntaxhighlight>
''todo(may be not :): pretty print & convert to normal D array''
{{out}}
<pre>g == f convolute h ? true
h == g deconv f ? true
f == g deconv h ? true
f = [-9, 5, -8, 3, 5, 1, -1, -7, 2, -5, -6, 6, 8, 5, 8, -2, -6, -4]
g deconv h = [-9, 5, -8, 3, 5, 1, -1, -7, 2, -5, -6, 6, 8, 5, 8, -2, -6, -4]</pre>
 
=={{header|Go}}==
{{trans|C}}
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"math"
"math/cmplx"
)
 
func fft(buf []complex128, n int) {
out := make([]complex128, n)
copy(out, buf)
fft2(buf, out, n, 1)
}
 
func fft2(buf, out []complex128, n, step int) {
if step < n {
fft2(out, buf, n, step*2)
fft2(out[step:], buf[step:], n, step*2)
for j := 0; j < n; j += 2 * step {
fj, fn := float64(j), float64(n)
t := cmplx.Exp(-1i*complex(math.Pi, 0)*complex(fj, 0)/complex(fn, 0)) * out[j+step]
buf[j/2] = out[j] + t
buf[(j+n)/2] = out[j] - t
}
}
}
 
/* pad slice length to power of two */
func padTwo(g []float64, le int, ns *int) []complex128 {
n := 1
if *ns != 0 {
n = *ns
} else {
for n < le {
n *= 2
}
}
buf := make([]complex128, n)
for i := 0; i < le; i++ {
buf[i] = complex(g[i], 0)
}
*ns = n
return buf
}
 
func deconv(g []float64, lg int, f []float64, lf int, out []float64, rowLe int) {
ns := 0
g2 := padTwo(g, lg, &ns)
f2 := padTwo(f, lf, &ns)
fft(g2, ns)
fft(f2, ns)
h := make([]complex128, ns)
for i := 0; i < ns; i++ {
h[i] = g2[i] / f2[i]
}
fft(h, ns)
for i := 0; i < ns; i++ {
if math.Abs(real(h[i])) < 1e-10 {
h[i] = 0
}
}
for i := 0; i > lf-lg-rowLe; i-- {
out[-i] = real(h[(i+ns)%ns] / 32)
}
}
 
func unpack2(m [][]float64, rows, le, toLe int) []float64 {
buf := make([]float64, rows*toLe)
for i := 0; i < rows; i++ {
for j := 0; j < le; j++ {
buf[i*toLe+j] = m[i][j]
}
}
return buf
}
 
func pack2(buf []float64, rows, fromLe, toLe int, out [][]float64) {
for i := 0; i < rows; i++ {
for j := 0; j < toLe; j++ {
out[i][j] = buf[i*fromLe+j] / 4
}
}
}
 
func deconv2(g [][]float64, rowG, colG int, f [][]float64, rowF, colF int, out [][]float64) {
g2 := unpack2(g, rowG, colG, colG)
f2 := unpack2(f, rowF, colF, colG)
ff := make([]float64, (rowG-rowF+1)*colG)
deconv(g2, rowG*colG, f2, rowF*colG, ff, colG)
pack2(ff, rowG-rowF+1, colG, colG-colF+1, out)
}
 
func unpack3(m [][][]float64, x, y, z, toY, toZ int) []float64 {
buf := make([]float64, x*toY*toZ)
for i := 0; i < x; i++ {
for j := 0; j < y; j++ {
for k := 0; k < z; k++ {
buf[(i*toY+j)*toZ+k] = m[i][j][k]
}
}
}
return buf
}
 
func pack3(buf []float64, x, y, z, toY, toZ int, out [][][]float64) {
for i := 0; i < x; i++ {
for j := 0; j < toY; j++ {
for k := 0; k < toZ; k++ {
out[i][j][k] = buf[(i*y+j)*z+k] / 4
}
}
}
}
 
func deconv3(g [][][]float64, gx, gy, gz int, f [][][]float64, fx, fy, fz int, out [][][]float64) {
g2 := unpack3(g, gx, gy, gz, gy, gz)
f2 := unpack3(f, fx, fy, fz, gy, gz)
ff := make([]float64, (gx-fx+1)*gy*gz)
deconv(g2, gx*gy*gz, f2, fx*gy*gz, ff, gy*gz)
pack3(ff, gx-fx+1, gy, gz, gy-fy+1, gz-fz+1, out)
}
 
func main() {
f := [][][]float64{
{{-9, 5, -8}, {3, 5, 1}},
{{-1, -7, 2}, {-5, -6, 6}},
{{8, 5, 8}, {-2, -6, -4}},
}
fx, fy, fz := len(f), len(f[0]), len(f[0][0])
 
g := [][][]float64{
{{54, 42, 53, -42, 85, -72}, {45, -170, 94, -36, 48, 73},
{-39, 65, -112, -16, -78, -72}, {6, -11, -6, 62, 49, 8}},
{{-57, 49, -23, 52, -135, 66}, {-23, 127, -58, -5, -118, 64},
{87, -16, 121, 23, -41, -12}, {-19, 29, 35, -148, -11, 45}},
{{-55, -147, -146, -31, 55, 60}, {-88, -45, -28, 46, -26, -144},
{-12, -107, -34, 150, 249, 66}, {11, -15, -34, 27, -78, -50}},
{{56, 67, 108, 4, 2, -48}, {58, 67, 89, 32, 32, -8},
{-42, -31, -103, -30, -23, -8}, {6, 4, -26, -10, 26, 12},
},
}
gx, gy, gz := len(g), len(g[0]), len(g[0][0])
 
h := [][][]float64{
{{-6, -8, -5, 9}, {-7, 9, -6, -8}, {2, -7, 9, 8}},
{{7, 4, 4, -6}, {9, 9, 4, -4}, {-3, 7, -2, -3}},
}
hx, hy, hz := gx-fx+1, gy-fy+1, gz-fz+1
 
h2 := make([][][]float64, hx)
for i := 0; i < hx; i++ {
h2[i] = make([][]float64, hy)
for j := 0; j < hy; j++ {
h2[i][j] = make([]float64, hz)
}
}
deconv3(g, gx, gy, gz, f, fx, fy, fz, h2)
fmt.Println("deconv3(g, f):\n")
for i := 0; i < hx; i++ {
for j := 0; j < hy; j++ {
for k := 0; k < hz; k++ {
fmt.Printf("% .10g ", h2[i][j][k])
}
fmt.Println()
}
if i < hx-1 {
fmt.Println()
}
}
 
kx, ky, kz := gx-hx+1, gy-hy+1, gz-hz+1
f2 := make([][][]float64, kx)
for i := 0; i < kx; i++ {
f2[i] = make([][]float64, ky)
for j := 0; j < ky; j++ {
f2[i][j] = make([]float64, kz)
}
}
deconv3(g, gx, gy, gz, h, hx, hy, hz, f2)
fmt.Println("\ndeconv(g, h):\n")
for i := 0; i < kx; i++ {
for j := 0; j < ky; j++ {
for k := 0; k < kz; k++ {
fmt.Printf("% .10g ", f2[i][j][k])
}
fmt.Println()
}
if i < kx-1 {
fmt.Println()
}
}
}</syntaxhighlight>
 
{{out}}
<pre>
deconv3(g, f):
 
-6 -8 -5 9
-7 9 -6 -8
2 -7 9 8
 
7 4 4 -6
9 9 4 -4
-3 7 -2 -3
 
deconv(g, h):
 
-9 5 -8
3 5 1
 
-1 -7 2
-5 -6 6
 
8 5 8
-2 -6 -4
</pre>
 
=={{header|J}}==
Actually it is a matter of setting up the linear equations and then solving them.
 
'''SolutionImplementation''': <langsyntaxhighlight lang="j">deconv3 =: 4 : 0
sz =. x >:@-&$ y NB. shape of z
poi =. ,<"1 ($y) ,"0/&(,@i.) sz NB. pair of indexes
Line 92 ⟶ 748:
sz $ 1e_8 round ({:"1 %. }:"1) T1
)
round=: [ * <.@%~</syntaxhighlight>
h3 -: g3 deconv3 f3 NB. h3 matches g3 deconv3 f3
1</lang>
 
'''Data''': <syntaxhighlight lang="j">h1=: _8 2 _9 _2 9 _8 _2
=={{header|Perl 6}}==
f1=: 6 _9 _7 _5
Works with Rakudo 2010.12.
g1=: _48 84 _16 95 125 _70 7 29 54 10
 
h2=: ".;._2]0 :0
Translation of Tcl.
_8 1 _7 _2 _9 4
<lang perl6># Deconvolution of N dimensional matricies.
4 5 _5 2 7 _1
sub deconv_ND ( @g, @f ) {
_6 _3 my_3 @gsize_6 =9 size_of @g;5
)
my @fsize = size_of @f;
my @hsize = @gsize >>-<< @fsize >>+>> 1;
 
f2=: ".;._2]0 :0
my @toSolve;
_5 2 _2 _6 _7
for loopcoords(@gsize) -> $coords {
9 7 _6 5 _7
@toSolve.push( [ row( @g, @f, @gsize, $coords, @fsize, @hsize ) ]);
1 _1 9 2 _7 }
5 9 _9 2 _5
_8 5 _2 8 5
)
 
g2=: ".;._2]0 :0
my @solved = rref( @toSolve );
40 _21 53 42 105 1 87 60 39 _28
_92 _64 19 _167 _71 _47 128 _109 40 _21
58 85 _93 37 101 _14 5 37 _76 _56
_90 _135 60 _125 68 53 223 4 _36 _48
78 16 7 _199 156 _162 29 28 _103 _10
_62 _89 69 _61 66 193 _61 71 _8 _30
48 _6 21 _9 _150 _22 _56 32 85 25
)
 
h3=: ".;._1;._2]0 :0
/ _6 _8 _5 9/ _7 9 _6 _8/ 2 _7 9 8
/ 7 4 4 _6/ 9 9 4 _4/ _3 7 _2 _3
)
 
f3=: ".;._1;._2]0 :0
/ _9 5 _8/ 3 5 1
/ _1 _7 2/ _5 _6 6
/ 8 5 8/_2 _6 _4
)
 
g3=: ".;._2;._1]0 :0
/ 54 42 53 _42 85 _72
45 _170 94 _36 48 73
_39 65 _112 _16 _78 _72
6 _11 _6 62 49 8
/ _57 49 _23 52 _135 66
_23 127 _58 _5 _118 64
87 _16 121 23 _41 _12
_19 29 35 _148 _11 45
/ _55 _147 _146 _31 55 60
_88 _45 _28 46 _26 _144
_12 _107 _34 150 249 66
11 _15 _34 27 _78 _50
/ 56 67 108 4 2 _48
58 67 89 32 32 _8
_42 _31 _103 _30 _23 _8
6 4 _26 _10 26 12
)</syntaxhighlight>
 
'''Tests''': <syntaxhighlight lang="j"> h1 -: g1 deconv3 f1
1
h2 -: g2 deconv3 f2
1
h3 -: g3 deconv3 f3 NB. -: checks for matching structure and data
1</syntaxhighlight>
 
=={{header|Julia}}==
Julia has a deconv() function that works on Julia's builtin multidimensional arrays, but not on the nested type 2D and 3D arrays used in the task. So, the solution function, deconvn(), sets up repackaging for 1D fft. The actual solving work is done on one line of ifft/fft, and the rest of the code is merely to repackage the nested arrays.
<syntaxhighlight lang="julia">using FFTW, DSP
 
const h1 = [-8, 2, -9, -2, 9, -8, -2]
const f1 = [ 6, -9, -7, -5]
const g1 = [-48, 84, -16, 95, 125, -70, 7, 29, 54, 10]
 
const h2nested = [
[-8, 1, -7, -2, -9, 4],
[4, 5, -5, 2, 7, -1],
[-6, -3, -3, -6, 9, 5]]
const f2nested = [
[-5, 2, -2, -6, -7],
[9, 7, -6, 5, -7],
[1, -1, 9, 2, -7],
[5, 9, -9, 2, -5],
[-8, 5, -2, 8, 5]]
const g2nested = [
[40, -21, 53, 42, 105, 1, 87, 60, 39, -28],
[-92, -64, 19, -167, -71, -47, 128, -109, 40, -21],
[58, 85, -93, 37, 101, -14, 5, 37, -76, -56],
[-90, -135, 60, -125, 68, 53, 223, 4, -36, -48],
[78, 16, 7, -199, 156, -162, 29, 28, -103, -10],
[-62, -89, 69, -61, 66, 193, -61, 71, -8, -30],
[48, -6, 21, -9, -150, -22, -56, 32, 85, 25]]
 
const h3nested = [
[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]],
[[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]]
const f3nested = [
[[-9, 5, -8], [3, 5, 1]],
[[-1, -7, 2], [-5, -6, 6]],
[[8, 5, 8],[-2, -6, -4]]]
const g3nested = [
[ [54, 42, 53, -42, 85, -72],
[45, -170, 94, -36, 48, 73],
[-39, 65, -112, -16, -78, -72],
[6, -11, -6, 62, 49, 8]],
[ [-57, 49, -23, 52, -135, 66],
[-23, 127, -58, -5, -118, 64],
[87, -16, 121, 23, -41, -12],
[-19, 29, 35, -148, -11, 45]],
[ [-55, -147, -146, -31, 55, 60],
[-88, -45, -28, 46, -26, -144],
[-12, -107, -34, 150, 249, 66],
[11, -15, -34, 27, -78, -50]],
[ [56, 67, 108, 4, 2, -48],
[58, 67, 89, 32, 32, -8],
[-42, -31, -103, -30, -23, -8],
[6, 4, -26, -10, 26, 12]]]
 
function flatnested2d(a, siz)
ret = zeros(Int, prod(siz))
for i in 1:length(a), j in 1:length(a[1])
ret[siz[2] * (i - 1) + j] = a[i][j]
end
Float64.(ret)
end
 
function flatnested3d(a, siz)
ret = zeros(Int, prod(siz))
for i in 1:length(a), j in 1:length(a[1]), k in 1:length(a[1][1])
ret[siz[2] * siz[3] * (i - 1) + siz[3] * (j - 1) + k] = a[i][j][k]
end
Float64.(ret)
end
 
topow2(siz) = map(x -> nextpow(2, x), siz)
deconv1d(f1, g1) = Int.(round.(deconv(Float64.(g1), Float64.(f1))))
 
function deconv2d(f2, g2, xd2)
siz = topow2([length(g2), length(g2[1])])
h2 = Int.(round.(real.(ifft(fft(flatnested2d(g2, siz)) ./ fft(flatnested2d(f2, siz))))))
[[h2[siz[2] * (i - 1) + j] for j in 1:xd2[2]] for i in 1:xd2[1]]
end
 
function deconv3d(f3, g3, xd3)
siz = topow2([length(g3), length(g3[1]), length(g3[1][1])])
h3 = Int.(round.(real.(ifft(fft(flatnested3d(g3, siz)) ./ fft(flatnested3d(f3, siz))))))
[[[h3[siz[2] * siz[3] *(i - 1) + siz[3] * (j - 1) + k] for k in 1:xd3[3]]
for j in 1:xd3[2]] for i in 1:xd3[1]]
end
 
deconvn(f, g, tup=()) = length(tup) < 2 ? deconv1d(f, g) :
length(tup) == 2 ? deconv2d(f, g, tup) :
length(tup) == 3 ? deconv3d(f, g, tup) :
println("Array nesting > 3D not supported")
 
deconvn(f1, g1) # 1D
deconvn(f2nested, g2nested, (length(h2nested), length(h2nested[1]))) # 2D
println(deconvn(f3nested, g3nested,
(length(h3nested), length(h3nested[1]), length(h3nested[1][1])))) # 3D
</syntaxhighlight>{{out}}
<pre>
Array{Array{Int64,1},1}[[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]], [[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]]
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">Round[ListDeconvolve[{6, -9, -7, -5}, {-48, 84, -16, 95, 125, -70, 7, 29, 54, 10}, Method -> "Wiener"]]
 
Round[ListDeconvolve[{{-5, 2, -2, -6, -7}, {9, 7, -6, 5, -7}, {1, -1, 9, 2, -7}, {5, 9, -9, 2, -5}, {-8, 5, -2, 8, 5}},
{{40, -21, 53, 42, 105, 1, 87, 60, 39, -28}, {-92, -64, 19, -167, -71, -47, 128, -109, 40, -21},
{58, 85, -93, 37, 101, -14, 5, 37, -76, -56}, {-90, -135, 60, -125, 68, 53, 223, 4, -36, -48},
{78, 16, 7, -199, 156, -162, 29, 28, -103, -10}, {-62, -89, 69, -61, 66, 193, -61, 71, -8, -30},
{48, -6, 21, -9, -150, -22, -56, 32, 85, 25}}, Method -> "Wiener"]]
 
Round[ListDeconvolve [{{{-9, 5, -8}, {3, 5, 1}}, {{-1, -7, 2}, {-5, -6, 6}}, {{8, 5, 8}, {-2, -6, -4}}},
{{{54, 42, 53, -42, 85, -72}, {45, -170, 94, -36, 48, 73}, {-39, 65, -112, -16, -78, -72},
{6, -11, -6, 62, 49, 8}}, {{-57, 49, -23, 52, -135, 66}, {-23, 127, -58, -5, -118, 64}, {87, -16, 121, 23, -41, -12},
{-19, 29, 35, -148, -11, 45}}, {{-55, -147, -146, -31, 55, 60}, {-88, -45, -28, 46, -26, -144},
{-12, -107, -34, 150, 249, 66}, {11, -15, -34, 27, -78, -50}}, {{56, 67, 108, 4, 2, -48}, {58, 67, 89, 32, 32, -8},
{-42, -31, -103, -30, -23, -8}, {6, 4, -26, -10, 26, 12}}}, Method -> "Wiener"]]</syntaxhighlight>
 
{{out}}
The built-in ListDeconvolve function pads output to the same dimensions as the original data...
 
<pre>{-8, 2, -9, -2, 9, -8, -2, 0, 0, 0}
 
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, -8, 1, -7, -2, -9, 4, 0, 0},
{0, 0, 4, 5, -5, 2, 7, -1, 0, 0}, {0, 0, -6, -3, -3, -6, 9, 5, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
 
{{{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}, {{-6, -8, -5, 9, 0, 0}, {-7, 9, -6, -8, 0, 0},
{2, -7, 9, 8, 0, 0}, {0, 0, 0, 0, 0, 0}}, {{7, 4, 4, -6, 0, 0}, {9, 9, 4, -4, 0, 0}, {-3, 7, -2, -3, 0, 0},
{0, 0, 0, 0, 0, 0}}}</pre>
 
=={{header|Nim}}==
{{trans|D}}
<syntaxhighlight lang="nim">import sequtils, typetraits
 
type Size = uint64
 
type M[T: SomeNumber] = object
dims: seq[Size]
subsizes: seq[Size]
data: seq[T]
 
####################################################################################################
# Miscellaneous.
 
func dotProduct[T: SomeNumber](a, b: openArray[T]): T =
assert a.len == b.len
for i in 0..a.high:
result += a[i] * b[i]
 
 
####################################################################################################
# Operations on M objects.
 
func setDimensions(m: var M; dimensions: varargs[Size]) =
 
for dim in dimensions:
if dim == 0:
raise newException(IndexDefect, "wrong dimension: 0")
 
m.dims = @dimensions
m.subsizes = m.dims
for i in 0..dimensions.high:
m.subsizes[i] = m.dims[(i+1)..^1].foldl(a * b, Size(1))
 
let dlength = m.dims[0] * m.subsizes[0]
if Size(m.data.len) != dlength:
m.data.setLen(dlength)
 
#---------------------------------------------------------------------------------------------------
 
func initM(m: var M; dimensions: varargs[Size]) =
m.setDimensions(dimensions)
 
#---------------------------------------------------------------------------------------------------
 
func set1DArray(m: var M; t: varargs[m.T]) =
 
let minLen = min(m.data.len, t.len)
m.data.setLen(minLen)
m.data[0..<minLen] = t[0..<minLen]
 
#---------------------------------------------------------------------------------------------------
 
func seqToIdx(m: M; s: Size): seq[Size] =
 
var acc = s
for subsize in m.subsizes:
result.add(acc div subsize)
acc = acc mod subsize
 
#---------------------------------------------------------------------------------------------------
 
template size(m: M): Size = Size(m.data.len)
 
#---------------------------------------------------------------------------------------------------
 
func checkBounds(m: M; indexes: varargs[Size]): bool =
 
if indexes.len > m.dims.len:
return false
 
for i, dim in indexes:
if dim >= m.dims[i]:
return false
 
result = true
 
#---------------------------------------------------------------------------------------------------
 
func `[]`(m: M; indexes: varargs[Size]): m.T =
 
if not m.checkBounds(indexes):
raise newException(IndexDefect, "index out of range: " & $indexes)
 
m.data[dotProduct(indexes, m.subsizes)]
 
#---------------------------------------------------------------------------------------------------
 
func `[]=`(m: M; indexes: varargs[int]; val: m.T) =
 
if not m.checkBounds(indexes):
raise newException(IndexDefect, "index out of range: " & $indexes)
 
m.data[dotProduct(indexes, m.subsizes)] = val
 
#---------------------------------------------------------------------------------------------------
 
func `==`(a, b: M): bool = a.dims == b.dims and a.data == b.data
 
#---------------------------------------------------------------------------------------------------
 
func `$`(m: M): string = $m.data
 
 
####################################################################################################
# Convolution/deconvolution.
 
func convolute(h, f: M): M =
## Result is "g".
 
var dims = h.dims
for i in 0..dims.high:
dims[i] += f.dims[i] - 1
result.initM(dims)
 
let bound = result.size
for i in 0..<h.size:
let hIndexes = h.seqToIdx(i)
 
for j in 0..<f.size:
let fIndexes = f.seqToIdx(j)
for k in 0..dims.high:
dims[k] = hIndexes[k] + fIndexes[k]
let idx1d = dotProduct(dims, result.subsizes)
if idx1d < bound:
result.data[idx1d] += h.data[i] * f.data[j]
else:
break # Bound reached.
 
#---------------------------------------------------------------------------------------------------
 
func deconvolute(g, f: M): M =
## Result is "h".
 
var dims = g.dims
for i, d in dims:
if d + 1 <= f.dims[i]:
raise newException(IndexDefect, "a dimension is zero or negative")
 
for i in 0..dims.high:
dims[i] -= f.dims[i] - 1
result.initM(dims)
 
for i in 0..<result.size:
let iIndexes = result.seqToIdx(i)
result.data[i] = g[iIndexes]
 
for j in 0..<i:
let jIndexes = result.seqToIdx(j)
for k in 0..dims.high:
dims[k] = iIndexes[k] - jIndexes[k]
if f.checkBounds(dims):
result.data[i] -= result.data[j] * f[dims]
 
when result.T is SomeInteger:
result.data[i] = result.data[i] div f.data[0]
else:
result.data[i] /= f.data[0]
 
 
####################################################################################################
# Transformation of a sequence into an M object.
 
func fold[T](a: seq[T]; d: var seq[Size]): auto =
 
if d.len == 0:
d.add(Size(a.len))
 
when a.elementType is seq:
if a.len == 0:
raise newException(ValueError, "empty dimension")
d.add(Size(a[0].len))
for elem in a:
if elem.len != a[0].len:
raise newException(ValueError, "not rectangular")
result = fold(a.foldl(a & b), d)
 
else:
if Size(a.len) != d.foldl(a * b):
raise newException(ValueError, "not same size")
result = a
 
#---------------------------------------------------------------------------------------------------
 
func arrtoM[T](a: T): auto =
 
var dims: seq[Size]
let d = fold(a, dims)
var res: M[d.elementType]
res.initM(dims)
res.set1DArray(d)
return res
 
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
const H = @[ @[ @[-6, -8, -5, 9], @[-7, 9, -6, -8], @[ 2, -7, 9, 8] ],
@[ @[ 7, 4, 4, -6], @[ 9, 9, 4, -4], @[-3, 7, -2, -3] ] ]
 
const F = @[ @[ @[-9, 5, -8], @[ 3, 5, 1] ],
@[ @[-1, -7, 2], @[-5, -6, 6] ],
@[ @[ 8, 5, 8], @[-2, -6, -4] ] ]
 
let h = arrToM(H)
let f = arrToM(F)
 
let g = h.convolute(f)
 
echo "g == f convolute h ? ", g == f.convolute(h)
echo "h == g deconv f ? ", h == g.deconvolute(f)
echo "f == g deconv h ? ", f == g.deconvolute(h)
echo " f = ", f
echo "g deconv f = ", g.deconvolute(h)</syntaxhighlight>
 
{{out}}
<pre>g == f convolute h ? true
h == g deconv f ? true
f == g deconv h ? true
f = @[-9, 5, -8, 3, 5, 1, -1, -7, 2, -5, -6, 6, 8, 5, 8, -2, -6, -4]
g deconv f = @[-9, 5, -8, 3, 5, 1, -1, -7, 2, -5, -6, 6, 8, 5, 8, -2, -6, -4]</pre>
 
=={{header|Perl}}==
{{libheader|ntheory}}
{{trans|Raku}}
<syntaxhighlight lang="perl">use feature 'say';
use ntheory qw/forsetproduct/;
 
# Deconvolution of N dimensional matrices
# Uncomment if you want to see the rref system of equations.
sub deconvolve_N {
# pretty_print( @solved );
our @g; local *g = shift;
our @f; local *f = shift;
my @df = shape(@f);
my @dg = shape(@g);
my @hsize;
push @hsize, $dg[$_] - $df[$_] + 1 for 0..$#df;
my @toSolve = map { [row(\@g, \@f, \@hsize, $_)] } coords(shape(@g));
rref( \@toSolve );
 
my @h;
my $indexn = 0;
for loopcoords(coords(@hsize) -> @coords) {
insertmy( @h$k,$j,$i) @coords= split ' ', @solved[$index][*-1] )_;
$h[$i][$j][$k] = $toSolve[$indexn++][-1];
}
return @h;
 
# Inserts a value in the correct spot in an N dimensional array.
sub insert ( $array is rw, @coords is copy, $value ) {
my $level = @coords.shift;
if +@coords {
insert( $array[$level], @coords, $value );
} else {
$array[$level] = $value;
}
}
@h;
}
 
sub row {
# Returns a list containing the number of elements in
our @g; local *g = shift;
# each level of an N dimensional array.
our @f; local *f = shift;
sub size_of ( $m is copy ) {
our @hsize; local *hsize = shift;
my @size;
my @gc = reverse split ' ', shift;
while $m ~~ Array { @size.push(+$m); $m = $m[0]; }
return @size;
}
 
# Construct a row (equation) for each value in @g to be sent
# to the simultaneous equation solver.
# @Xsize = Dimensions of @X, # of elems per level.
# @Xcoords = Path to each element of @X given as a series of indicies.
sub row ( @g, @f, @gsize, @gcoords, @fsize, $hsize ) {
my @row;
my @fdim = shape(@f);
for loopcoords( $hsize ) -> @hcoords {
for (coords(@hsize)) {
my @fcoords;
formy ^@hcoordshc ->= $indexreverse {split ' ', $_;
my $window = @gcoords[$index] - @hcoords[$index]fc;
for my $i (0..$#hc) {
@fcoords.push($window) and next if 0 <= $window < @fsize[$index];
last;my $window = $gc[$i] - $hc[$i];
push(@fc, $window), next if 0 <= $window && $window < $fdim[$i];
}
@row.push( +@fcoordsrow, $#fc == +@hcoords$#hc ?? fetch( @$f, |@fcoords[$fc[0]] )[$fc[1]] !![$fc[2]] 0: )0;
}
@row.push( fetch( @grow, |@gcoords$g [$gc[0]] )[$gc[1]] )[$gc[2]];
return @row;
}
 
sub rref {
# Returns the value found in @array with the
our @m; local *m = shift;
# coordinates given in the list of @indicies.
@m or return;
sub fetch (@array, *@indicies) {
my ($lead, $rows, $cols) = (0, scalar(@m), scalar(@{$m[0]}));
my $index = @indicies.shift;
 
return @array[*-1] ~~ Array
foreach my $r (0 .. $rows - 1) {
?? fetch( @array[$index], @indicies )
$lead < $cols or !! @array[$index]return;
} my $i = $r;
 
until ($m[$i][$lead])
{++$i == $rows or next;
$i = $r;
++$lead == $cols and return;}
 
@m[$i, $r] = @m[$r, $i];
my $lv = $m[$r][$lead];
$_ /= $lv foreach @{ $m[$r] };
 
my @mr = @{ $m[$r] };
foreach my $i (0 .. $rows - 1)
{$i == $r and next;
($lv, my $n) = ($m[$i][$lead], -1);
$_ -= $lv * $mr[++$n] foreach @{ $m[$i] };}
 
++$lead;}
}
 
# Constructs an arrayAoA of arrayscoordinates to all elements of coordinatesN todimensional eacharray
sub coords {
# element in an N dimensional array.
my(@dimensions) = reverse @_;
sub loopcoords ( @hsize ) {
my (@hcoordsranges,@coords);
push @ranges, [0..$_-1] for @dimensions;
for ^([*] @hsize) -> $index {
forsetproduct { push @coords, "@_" } @ranges;
my @coords;
my $j = $index @coords;
}
for @hsize -> $dim {
 
@coords.push( $j % $dim );
sub shape {
$j div= $dim;
my(@dim);
}
@hcoords. push( [@coords]dim, )scalar @_;
push @dim, shape(@{$_[0]}) if 'ARRAY' eq ref $_[0];
@dim;
}
 
# Pretty printer for N dimensional arrays
# Assumes if first element in level is an array, then all are
sub pretty_print {
my($i, @a) = @_;
if ('ARRAY' eq ref $a[0]) {
say ' 'x$i, '[';
pretty_print($i+2, @$_) for @a;
say ' 'x$i, ']', $i ? ',' : '';
} else {
say ' 'x$i, '[', sprintf("@{['%5s'x@a]}",@a), ']', $i ? ',' : '';
}
return @hcoords;
}
 
my @f = (
# Reduced Row Echelon Form simultaneous equation solver.
[
# Can handle over-specified systems of equations.
[ -9, 5, -8 ],
# (n unknowns in n + m equations)
[ 3, 5, 1 ],
sub rref ($m is rw) {
],
return unless $m;
[
my ($lead, $rows, $cols) = 0, +$m, +$m[0];
[ -1, -7, 2 ],
[ -5, -6, 6 ],
],
[
[ 8, 5, 8 ],
[ -2, -6, -4 ],
]
);
 
my @g = (
# Trim off over specified rows if they exist.
[
# Not strictly necessary, but can save a lot of
[ 54, 42, 53, -42, 85, -72 ],
# redundant calculations.
[ 45,-170, 94, -36, 48, 73 ],
if $rows >= $cols {
[ -39, 65,-112, $m-16, =-78, trim_system($m);-72 ],
[ 6, $rows-11, = +$m;-6, 62, 49, 8 ],
],
[
[ -57, 49, -23, 52,-135, 66 ],
[ -23, 127, -58, -5,-118, 64 ],
[ 87, -16, 121, 23, -41, -12 ],
[ -19, 29, 35,-148, -11, 45 ],
],
[
[ -55,-147,-146, -31, 55, 60 ],
[ -88, -45, -28, 46, -26,-144 ],
[ -12,-107, -34, 150, 249, 66 ],
[ 11, -15, -34, 27, -78, -50 ],
],
[
[ 56, 67, 108, 4, 2, -48 ],
[ 58, 67, 89, 32, 32, -8 ],
[ -42, -31,-103, -30, -23, -8 ],
[ 6, 4, -26, -10, 26, 12 ],
]
);
 
my @h = deconvolve_N( \@g, \@f );
my @ff = deconvolve_N( \@g, \@h );
 
my $d = scalar shape(@g);
print "${d}D arrays:\n";
print "h =\n";
pretty_print(0,@h);
print "\nff =\n";
pretty_print(0,@ff);</syntaxhighlight>
{{out}}
<pre>3D arrays:
h =
[
[
[ -6 -8 -5 9],
[ -7 9 -6 -8],
[ 2 -7 9 8],
],
[
[ 7 4 4 -6],
[ 9 9 4 -4],
[ -3 7 -2 -3],
],
]
 
ff =
[
[
[ -9 5 -8],
[ 3 5 1],
],
[
[ -1 -7 2],
[ -5 -6 6],
],
[
[ 8 5 8],
[ -2 -6 -4],
],
]</pre>
 
=={{header|Phix}}==
{{trans|Tcl}}
Quite frankly I'm fairly astonished that it actually works...<br>
(be warned this contains an exciting mix of 0- and 1- based indexes)
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Deconvolution.exw</span>
<span style="color: #008080;">with</span> <span style="color: #000000;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">m_size</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- returns the size of a matrix as a list of lengths
--</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">me</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span>
<span style="color: #008080;">while</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">me</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">me</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">me</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">me</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">make_coordset</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">size</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- returns all points in the matrix, in zero-based indexes,
-- eg {{0,0,0}..{3,3,5}} for a 4x4x6 matrix [96 in total]
--</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">product</span><span style="color: #0000FF;">(</span><span style="color: #000000;">size</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">coords</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">size</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dimension</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">size</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">coords</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dimension</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">/</span><span style="color: #000000;">dimension</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">coords</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">row</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">gs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">gc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hs</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
--# Assembles a row, which is one of the simultaneous equations that needs
--# to be solved by reducing the whole set to reduced row echelon form. Note
--# that each row describes the equation for a single cell of the 'g' function.
--#
--# Arguments:
--# g The "result" matrix of the convolution being undone.
--# h The known "input" matrix of the convolution being undone.
--# gs The size descriptor of 'g', passed as argument for efficiency.
--# gc The coordinate in 'g' that we are generating the equation for.
--# fs The size descriptor of 'f', passed as argument for efficiency.
--# hs The size descriptor of 'h' (the unknown "input" matrix), passed
--# as argument for efficiency.
--</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">row</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
<span style="color: #000000;">coords</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">make_coordset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">coords</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">f</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">gc</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">hc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">fs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">row</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">row</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">gn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">g</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">gc</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">gn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">gn</span><span style="color: #0000FF;">[</span><span style="color: #000000;">gc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">row</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">row</span><span style="color: #0000FF;">,</span><span style="color: #000000;">gn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">row</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">toRREF</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- [renamed] copy of Reduced_row_echelon_form.htm#Phix
-- plus one small tweak, as noted below, exit-&gt;return,
-- not that said seems to make any actual difference.
--</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lead</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">rows</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">cols</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">rows</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lead</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">cols</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">lead</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">i</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rows</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
<span style="color: #000000;">lead</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000080;font-style:italic;">-- if lead=cols then exit end if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lead</span><span style="color: #0000FF;">=</span><span style="color: #000000;">cols</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">m</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">mi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]),</span>
<span style="color: #000000;">mr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">lead</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mi</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mr</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">rows</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">r</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">lead</span><span style="color: #0000FF;">],</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">lead</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">m</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">lset</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- helper routine: store v somewhere deep inside h</span>
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">i1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">h</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">h</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">h</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
--# Deconvolve a pair of matrixes. Solves for 'h' such that 'g = f convolve h'.
--#
--# Arguments:
--# g The matrix of data to be deconvolved.
--# f The matrix describing the convolution to be removed.
--
-- Compute the sizes of the various matrixes involved.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">gsize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">fsize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hsize</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">gsize</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fsize</span><span style="color: #0000FF;">),</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Prepare the set of simultaneous equations to solve</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">toSolve</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
<span style="color: #000000;">coords</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">make_coordset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">gsize</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">toSolve</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">toSolve</span><span style="color: #0000FF;">,</span><span style="color: #000000;">row</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">gsize</span><span style="color: #0000FF;">,</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">fsize</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hsize</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- Solve the equations</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toRREF</span><span style="color: #0000FF;">(</span><span style="color: #000000;">toSolve</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Create a result matrix of the right size</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hsize</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hsize</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- Fill the results from the equations into the result matrix</span>
<span style="color: #000000;">coords</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">make_coordset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hsize</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">coords</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">solved</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][$])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">h</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">f1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">g1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">84</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">95</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">125</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">29</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">54</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">h1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">h1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">f1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">f2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">}},</span>
<span style="color: #000000;">g2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">21</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">53</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">105</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">87</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">28</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">92</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">64</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">167</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">71</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">47</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">128</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">109</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">21</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">58</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">85</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">93</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">37</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">101</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">37</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">76</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">56</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">135</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">125</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">68</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">53</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">223</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">48</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">78</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">199</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">156</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">162</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">29</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">28</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">103</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">62</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">89</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">69</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">66</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">193</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">61</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">71</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">30</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">21</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">22</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">56</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">85</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">25</span><span style="color: #0000FF;">}},</span>
<span style="color: #000000;">h2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f2</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">h2</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h2</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">f2</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">f3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}}},</span>
<span style="color: #000000;">g3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span> <span style="color: #000000;">54</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">53</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">85</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">72</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">45</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">170</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">94</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">73</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">65</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">112</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">78</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">72</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">62</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">49</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{-</span><span style="color: #000000;">57</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">49</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">135</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">66</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">127</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">58</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">118</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">64</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">87</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">121</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">41</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">12</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">29</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">35</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">148</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">45</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{-</span><span style="color: #000000;">55</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">147</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">146</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">55</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">88</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">28</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">46</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">26</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">144</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">107</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">34</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">249</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">66</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">34</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">78</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">50</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">56</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">67</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">108</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">48</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">58</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">67</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">89</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">103</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">26</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">26</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">}}},</span>
<span style="color: #000000;">h3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}}}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f3</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">h3</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h3</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">f3</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">ppOpt</span><span style="color: #0000FF;">({</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_IntFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d"</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f3</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deconvolve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h3</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
{{{ -6, -8, -5, 9},
{ -7, 9, -6, -8},
{ 2, -7, 9, 8}},
{{ 7, 4, 4, -6},
{ 9, 9, 4, -4},
{ -3, 7, -2, -3}}}
{{{ -9, 5, -8},
{ 3, 5, 1}},
{{ -1, -7, 2},
{ -5, -6, 6}},
{{ 8, 5, 8},
{ -2, -6, -4}}}
</pre>
The version shipped in demo\rosetta contains the full 5 test sets: note that 5D takes a minute or two to complete.
 
=={{header|Python}}==
 
Tested on all 5 test cases.
 
Blows up with divide by zero error on 4d deconv(g,f) because
the fft(f) returns 0 for a sample. This shows the limits of
doing a deconvolution with fft.
 
https://math.stackexchange.com/questions/380720/is-deconvolution-simply-division-in-frequency-domain
 
<syntaxhighlight lang="python">
"""
 
https://rosettacode.org/wiki/Deconvolution/2D%2B
 
Working on 3 dimensional example using test data from the
RC task.
 
Python fft:
 
https://docs.scipy.org/doc/numpy/reference/routines.fft.html
 
"""
 
import numpy
import pprint
 
h = [
[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]],
[[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]]
f = [
[[-9, 5, -8], [3, 5, 1]],
[[-1, -7, 2], [-5, -6, 6]],
[[8, 5, 8],[-2, -6, -4]]]
g = [
[
[54, 42, 53, -42, 85, -72],
[45, -170, 94, -36, 48, 73],
[-39, 65, -112, -16, -78, -72],
[6, -11, -6, 62, 49, 8]],
[
[-57, 49, -23, 52, -135, 66],
[-23, 127, -58, -5, -118, 64],
[87, -16, 121, 23, -41, -12],
[-19, 29, 35, -148, -11, 45]],
[
[-55, -147, -146, -31, 55, 60],
[-88, -45, -28, 46, -26, -144],
[-12, -107, -34, 150, 249, 66],
[11, -15, -34, 27, -78, -50]],
[
[56, 67, 108, 4, 2, -48],
[58, 67, 89, 32, 32, -8],
[-42, -31, -103, -30, -23, -8],
[6, 4, -26, -10, 26, 12]]]
def trim_zero_empty(x):
"""
Takes a structure that represents an n dimensional example.
For a 2 dimensional example it will be a list of lists.
For a 3 dimensional one it will be a list of list of lists.
etc.
Actually these are multidimensional numpy arrays but I was thinking
in terms of lists.
Returns the same structure without trailing zeros in the inner
lists and leaves out inner lists with all zeros.
"""
if len(x) > 0:
if type(x[0]) != numpy.ndarray:
# x is 1d array
return list(numpy.trim_zeros(x))
else:
# x is a multidimentional array
new_x = []
for l in x:
tl = trim_zero_empty(l)
if len(tl) > 0:
new_x.append(tl)
return new_x
else:
# x is empty list
return x
def deconv(a, b):
"""
Returns function c such that b * c = a.
https://en.wikipedia.org/wiki/Deconvolution
"""
# Convert larger polynomial using fft
 
ffta = numpy.fft.fftn(a)
# Get it's shape so fftn will expand
# smaller polynomial to fit.
ashape = numpy.shape(a)
# Convert smaller polynomial with fft
# using the shape of the larger one
 
fftb = numpy.fft.fftn(b,ashape)
# Divide the two in frequency domain
 
fftquotient = ffta / fftb
# Convert back to polynomial coefficients using ifft
# Should give c but with some small extra components
 
c = numpy.fft.ifftn(fftquotient)
# Get rid of imaginary part and round up to 6 decimals
# to get rid of small real components
 
trimmedc = numpy.around(numpy.real(c),decimals=6)
# Trim zeros and eliminate
# empty rows of coefficients
cleanc = trim_zero_empty(trimmedc)
return cleanc
print("deconv(g,h)=")
 
pprint.pprint(deconv(g,h))
 
print(" ")
 
print("deconv(g,f)=")
 
pprint.pprint(deconv(g,f))
</syntaxhighlight>
 
Output:
 
<pre>
deconv(g,h)=
[[[-9.0, 5.0, -8.0], [3.0, 5.0, 1.0]],
[[-1.0, -7.0, 2.0], [-5.0, -6.0, 6.0]],
[[8.0, 5.0, 8.0], [-2.0, -6.0, -4.0]]]
deconv(g,f)=
[[[-6.0, -8.0, -5.0, 9.0], [-7.0, 9.0, -6.0, -8.0], [2.0, -7.0, 9.0, 8.0]],
[[7.0, 4.0, 4.0, -6.0], [9.0, 9.0, 4.0, -4.0], [-3.0, 7.0, -2.0, -3.0]]]
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
Translation of Tcl.
<syntaxhighlight lang="raku" line># Deconvolution of N dimensional matrices.
sub deconvolve-N ( @g, @f ) {
my @hsize = @g.shape »-« @f.shape »+» 1;
 
my @toSolve = coords(@g.shape).map:
{ [row(@g, @f, $^coords, @hsize)] };
 
my @solved = rref( @toSolve );
 
my @h;
for flat coords(@hsize) Z @solved[*;*-1] -> $_, $v {
@h.AT-POS(|$_) = $v;
}
@h
}
 
# Construct a row for each value in @g to be sent to the simultaneous equation solver
sub row ( @g, @f, @gcoord, $hsize ) {
my @row;
@gcoord = @gcoord[(^@f.shape)]; # clip extraneous values
for coords( $hsize ) -> @hc {
my @fcoord;
for ^@hc -> $i {
my $window = @gcoord[$i] - @hc[$i];
@fcoord.push($window) and next if 0 ≤ $window < @f.shape[$i];
last;
}
@row.push: @fcoord == @hc ?? @f.AT-POS(|@fcoord) !! 0;
}
@row.push: @g.AT-POS(|@gcoord);
@row
}
 
# Constructs an AoA of coordinates to all elements of N dimensional array
sub coords ( @dim ) {
@[reverse $_ for [X] ([^$_] for reverse @dim)]
}
 
# Reduced Row Echelon Form simultaneous equation solver
# Can handle over-specified systems (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 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 to N equations in N unknowns; a no-op unless rows > cols
# Reduce a system of equations to n equations with n unknowns.
sub trim-system (@m) {
# Looks for an equation with a true value for each position.
return @m unless @m ≥ @m[0];
# If it can't find one, assumes that it has already taken one
my (\vars, @t) = @m[0] - 1;
# and pushes in the first equation it sees. This assumtion
for ^vars -> \lead {
# will alway be successful except in some cases where an
for ^@m -> \row {
# under-specified system has been supplied, in which case,
@t.append: @m.splice(row, 1) and last if @m[row;lead];
# it would not have been able to reduce the system anyway.
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 }
}</lang>
@t
}
 
# Pretty printer for N dimensional arrays
Use with a pretty printer as follows:
# Assumes if first element in level is an array, then all are
<lang perl6># Pretty printer for N dimensional arrays. Assumes that
sub pretty-print ( @array, $indent = 0 ) {
# if the FIRST element in any particular level is an array,
# then ALL the elements at that level are arrays.
sub pretty_print ( @array, $indent = 0 ) {
my $tab = 2;
if @array[0] ~~ Array {
say ' ' x $indent,"[";
pretty_printpretty-print( $_, $indent + $tab2 ) for @array;
say ' ' x $indent, "]{$indent??','!!''}";
} else {
Line 253 ⟶ 1,836:
}
 
sub say_it ( @array ) { return join ",", @array».fmt("%4s"); }
return join ",", @array>>.fmt("%4s");
}
}
 
my @f[3;2;3] = (
[
[ -9, 5, -8 ], [ 3, 5, 1 ],
[ 3, 5, 1 ],
],
[
[ -1, -7, 2 ], [ -5, -6, 6 ],
[ -5, -6, 6 ],
],
[
[ 8, 5, 8 ], [ -2, -6, -4 ],
[ -2, -6, -4 ],
]
);
 
my @g[4;4;6] = (
[
[ 54, 42, 53, -42, 85, -72 ],
Line 297 ⟶ 1,881:
);
 
say "# {+@f.shape}D array:";
=begin skip_output
my @h = deconvolve-N( @g, @f );
 
say "g =";
pretty_print( @g );
 
say '-' x 79;
 
say "f =";
pretty_print( @f );
 
say '-' x 79;
=end skip_output
 
say "# {+size_of(@f)}D array:";
say "h =";
pretty-print( @h );
pretty_print( deconv_ND( @g, @f ) );</lang>
my @h-shaped[2;3;4] = @(deconvolve-N( @g, @f ));
my @ff = deconvolve-N( @g, @h-shaped );
say "\nff =";
pretty-print( @ff );</syntaxhighlight>
 
Output:
Line 327 ⟶ 1,903:
[ 9, 9, 4, -4 ],
[ -3, 7, -2, -3 ],
],
]
 
ff =
[
[
[ -9, 5, -8 ],
[ 3, 5, 1 ],
],
[
[ -1, -7, 2 ],
[ -5, -6, 6 ],
],
[
[ 8, 5, 8 ],
[ -2, -6, -4 ],
],
]</pre>
Line 333 ⟶ 1,925:
The trick to doing this (without using a library to do all the legwork for you) is to recast the higher-order solutions into solutions in the 1D case. This is done by regarding an ''n''-dimensional address as a coding of a 1-D address.
 
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
namespace path {::tcl::mathfunc ::tcl::mathop}
 
Line 497 ⟶ 2,089:
 
return $h
}</langsyntaxhighlight>
Demonstrating how to use for the 3-D case:
<langsyntaxhighlight lang="tcl"># A pretty-printer
proc pretty matrix {
set size [rank $matrix]
Line 550 ⟶ 2,142:
 
# Now do the deconvolution and print it out
puts h:\ [pretty [deconvolve $g $f]]</langsyntaxhighlight>
Output:
<pre>
Line 566 ⟶ 2,158:
the [http://www.netlib.org/lapack/lug/node27.html <code>dgelsd</code>] function from the Lapack library.
The <code>break</code> function breaks a long list into a sequence of sublists according to a given template, and the <code>band</code> function is taken from the [[Deconvolution/1D]] solution.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 579 ⟶ 2,171:
lapack..dgelsd^^(
(~&||0.!**+ ~&B^?a\~&Y@a ^lriFhNSS2iDrlYSK7LS2SL2rQ/~&alt band@alh2faltPrDPMX)^|\~&+ gang,
@t =>~&l ~&L+@r))</langsyntaxhighlight>
The equations tend to become increasingly sparse in higher dimensions,
so the following alternative implementation uses the sparse matrix
Line 585 ⟶ 2,177:
instead of Lapack, which is also callable in Ursala, adjusted as shown for the different
[http://www.basis.uklinux.net/avram/refman/umf-input-parameters.html calling convention].
<langsyntaxhighlight Ursalalang="ursala">deconv = # takes a number n to the n-dimensional deconvolution function
 
~&?\math..div! iota; ~&!*; @h|\; -+
Line 597 ⟶ 2,189:
~&rFS+ num*rSS+ zipt^*D/~&r ^lrrSPT/~&ltK33tx zipt^/~&r ~&lSNyCK33+ zipp0,
^/~&rx ~&B->NlNSPC ~&bt+-+-+-,
@t =>~&l ~&L+@r)+-</langsyntaxhighlight>
UMFPACK doesn't solve systems with more equations than unknowns, so
the system is pruned to a square matrix by first selecting an equation
Line 608 ⟶ 2,200:
However, some improvement may be possible by averaging the results over several runs.
Here is a test program.
<langsyntaxhighlight Ursalalang="ursala">h = <<<-6.,-8.,-5.,9.>,<-7.,9.,-6.,-8.>,<2.,-7.,9.,8.>>,<<7.,4.,4.,-6.>,<9.,9.,4.,-4.>,<-3.,7.,-2.,-3.>>>
f = <<<-9.,5.,-8.>,<3.,5.,1.>>,<<-1.,-7.,2.>,<-5.,-6.,6.>>,<<8.,5.,8.>,<-2.,-6.,-4.>>>
 
Line 642 ⟶ 2,234:
'h': deconv3(g,f),
'f': deconv3(g,h)>
</syntaxhighlight>
</lang>
output:
<pre style="height:25ex;overflow:scroll">
Line 689 ⟶ 2,281:
<8.000000e+00,5.000000e+00,8.000000e+00>,
<-2.000000e+00,-6.000000e+00,-4.000000e+00>>>>
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-complex}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./complex" for Complex
import "./fmt" for Fmt
 
var fft2 // recursive
fft2 = Fn.new { |buf, out, n, step, start|
if (step < n) {
fft2.call(out, buf, n, step*2, start)
fft2.call(out, buf, n, step*2, start + step)
var j = 0
while (j < n) {
var t = (Complex.imagMinusOne * Num.pi * j / n).exp * out[j+step+start]
buf[(j/2).floor + start] = out[j+start] + t
buf[((j+n)/2).floor + start] = out[j+start] - t
j = j + 2 * step
}
}
}
 
var fft = Fn.new { |buf, n|
var out = List.filled(n, null)
for (i in 0...n) out[i] = buf[i]
fft2.call(buf, out, n, 1, 0)
}
 
/* pad list length to power of two */
var padTwo = Fn.new { |g, le, nsl|
var n = 1
var ns = nsl[0]
if (ns != 0) {
n = ns
} else {
while (n < le) n = n * 2
}
var buf = List.filled(n, Complex.zero)
for (i in 0...le) buf[i] = Complex.new(g[i], 0)
nsl[0] = n
return buf
}
 
var deconv = Fn.new { |g, lg, f, lf, out, rowLe|
var ns = 0
var nsl = [ns]
var g2 = padTwo.call(g, lg, nsl)
var f2 = padTwo.call(f, lf, nsl)
ns = nsl[0]
fft.call(g2, ns)
fft.call(f2, ns)
var h = List.filled(ns, null)
for (i in 0...ns) h[i] = g2[i] / f2[i]
fft.call(h, ns)
for (i in 0...ns) {
if (h[i].real.abs < 1e-10) h[i] = Complex.zero
}
var i = 0
while (i > lf-lg-rowLe) {
out[-i] = (h[(i+ns)%ns]/32).real
i = i - 1
}
}
 
var unpack2 = Fn.new { |m, rows, le, toLe|
var buf = List.filled(rows*toLe, 0)
for (i in 0...rows) {
for (j in 0...le) buf[i*toLe+j] = m[i][j]
}
return buf
}
 
var pack2 = Fn.new { |buf, rows, fromLe, toLe, out|
for (i in 0...rows) {
for (j in 0...toLe) out[i][j] = buf[i*fromLe+j] / 4
}
}
 
var deconv2 = Fn.new { |g, rowG, colG, f, rowF, colF, out|
var g2 = unpack2.call(g, rowG, colG, colG)
var f2 = unpack2.call(f, rowF, colF, colG)
var ff = List.filled((rowG-rowF+1)*colG, 0)
deconv.call(g2, rowG*colG, f2, rowF*colG, ff, colG)
pack2.call(ff, rowG-rowF+1, colG, colG-colF+1, out)
}
 
var unpack3 = Fn.new { |m, x, y, z, toY, toZ|
var buf = List.filled(x*toY*toZ, 0)
for (i in 0...x) {
for (j in 0...y) {
for (k in 0...z) {
buf[(i*toY+j)*toZ+k] = m[i][j][k]
}
}
}
return buf
}
 
var pack3 = Fn.new { |buf, x, y, z, toY, toZ, out|
for (i in 0...x) {
for (j in 0...toY) {
for (k in 0...toZ) {
out[i][j][k] = buf[(i*y+j)*z+k] / 4
}
}
}
}
 
var deconv3 = Fn.new { |g, gx, gy, gz, f, fx, fy, fz, out|
var g2 = unpack3.call(g, gx, gy, gz, gy, gz)
var f2 = unpack3.call(f, fx, fy, fz, gy, gz)
var ff = List.filled((gx-fx+1)*gy*gz, 0)
deconv.call(g2, gx*gy*gz, f2, fx*gy*gz, ff, gy*gz)
pack3.call(ff, gx-fx+1, gy, gz, gy-fy+1, gz-fz+1, out)
}
 
var f = [
[[-9, 5, -8], [ 3, 5, 1]],
[[-1, -7, 2], [-5, -6, 6]],
[[ 8, 5, 8], [-2, -6, -4]]
]
var fx = f.count
var fy = f[0].count
var fz = f[0][0].count
 
var g = [
[[ 54, 42, 53, -42, 85, -72], [45, -170, 94, -36, 48, 73],
[-39, 65, -112, -16, -78, -72], [6, -11, -6, 62, 49, 8]],
[[-57, 49, -23, 52, -135, 66], [-23, 127, -58, -5, -118, 64],
[ 87, -16, 121, 23, -41, -12], [-19, 29, 35, -148, -11, 45]],
[[-55, -147, -146, -31, 55, 60], [-88, -45, -28, 46, -26, -144],
[-12, -107, -34, 150, 249, 66], [11, -15, -34, 27, -78, -50]],
[[ 56, 67, 108, 4, 2, -48], [58, 67, 89, 32, 32, -8],
[-42, -31, -103, -30, -23, -8], [6, 4, -26, -10, 26, 12]]
]
 
var gx = g.count
var gy = g[0].count
var gz = g[0][0].count
 
var h = [
[[-6, -8, -5, 9], [-7, 9, -6, -8], [ 2, -7, 9, 8]],
[[ 7, 4, 4, -6], [ 9, 9, 4, -4], [-3, 7, -2, -3]]
]
 
var hx = gx - fx + 1
var hy = gy - fy + 1
var hz = gz - fz + 1
 
var h2 = List.filled(hx, null)
for (i in 0...hx) {
h2[i] = List.filled(hy, 0)
for (j in 0...hy) h2[i][j] = List.filled(hz, 0)
}
deconv3.call(g, gx, gy, gz, f, fx, fy, fz, h2)
System.print("deconv3(g, f):\n")
for (i in 0...hx) {
for (j in 0...hy) {
for (k in 0...hz) Fmt.write("$9.6h ", h2[i][j][k])
System.print()
}
if (i < hx-1) System.print()
}
 
var kx = gx - hx + 1
var ky = gy - hy + 1
var kz = gz - hz + 1
var f2 = List.filled(kx, null)
for (i in 0...kx) {
f2[i] = List.filled(ky, 0)
for (j in 0...ky) f2[i][j] = List.filled(kz, 0)
}
deconv3.call(g, gx, gy, gz, h, hx, hy, hz, f2)
System.print("\ndeconv3(g, h):\n")
for (i in 0...kx) {
for (j in 0...ky) {
for (k in 0...kz) Fmt.write("$9.6h ", f2[i][j][k])
System.print()
}
if (i < kx-1) System.print()
}</syntaxhighlight>
 
{{out}}
<pre>
deconv3(g, f):
 
-6 -8 -5 9
-7 9 -6 -8
2 -7 9 8
 
7 4 4 -6
9 9 4 -4
-3 7 -2 -3
 
deconv3(g, h):
 
-9 5 -8
3 5 1
 
-1 -7 2
-5 -6 6
 
8 5 8
-2 -6 -4
</pre>
9,476

edits