user
This task is a straightforward generalization of Deconvolution/1D to higher dimensions. For example, the one dimensional case would be applicable to audio signals, whereas two dimensions would pertain to images. Define the discrete convolution in 

d
{\displaystyle {\displaystyle {\mathit {d}}}}
 dimensions of two functions

:   H
    ,
    F
    :


    Z

    d
    →

    R
    {\displaystyle {\displaystyle H,F:\mathbb {Z} ^{d}\rightarrow \mathbb {R} }}

taking 

d
{\displaystyle {\displaystyle {\mathit {d}}}}
-tuples of integers to real numbers as the function

:   G
    :


    Z

    d
    →

    R
    {\displaystyle {\displaystyle G:\mathbb {Z} ^{d}\rightarrow \mathbb {R} }}

also taking 

d
{\displaystyle {\displaystyle {\mathit {d}}}}
-tuples of integers to reals and satisfying

:   G
    (

    n

    0
    ,
    …
    ,

    n

    d
    −
    1
    )
    =

    ∑


    m

    0
    =
    −
    ∞

    ∞
    …

    ∑


    m

    d
    −
    1
    =
    −
    ∞

    ∞
    F
    (

    m

    0
    ,
    …
    ,

    m

    d
    −
    1
    )
    H
    (

    n

    0
    −

    m

    0
    ,
    …
    ,

    n

    d
    −
    1
    −

    m

    d
    −
    1
    )
    {\displaystyle {\displaystyle G(n\_{0},\dots ,n\_{d-1})=\sum \_{m\_{0}=-\infty }^{\infty }\dots \sum \_{m\_{d-1}=-\infty }^{\infty }F(m\_{0},\dots ,m\_{d-1})H(n\_{0}-m\_{0},\dots ,n\_{d-1}-m\_{d-1})}}

for all 

d
{\displaystyle {\displaystyle {\mathit {d}}}}
-tuples of integers 

(

n

0
,
…
,

n

d
−
1
)
∈


Z

d
{\displaystyle {\displaystyle (n\_{0},\dots ,n\_{d-1})\in \mathbb {Z} ^{d}}}
. Assume

F
{\displaystyle {\displaystyle {\mathit {F}}}}
 and 

H
{\displaystyle {\displaystyle {\mathit {H}}}}
 (and therefore 

G
{\displaystyle {\displaystyle {\mathit {G}}}}
) are non-zero over only a finite domain bounded by the origin, hence possible to represent as finite multi-dimensional arrays or nested lists 

f
{\displaystyle {\displaystyle {\mathit {f}}}}
, 

h
{\displaystyle {\displaystyle {\mathit {h}}}}
, and 

g
{\displaystyle {\displaystyle {\mathit {g}}}}
.

For this task, implement a function (or method, procedure, subroutine, etc.) `deconv` to perform *deconvolution* (i.e., the *inverse* of convolution) by solving for 

h
{\displaystyle {\displaystyle {\mathit {h}}}}
 given 

f
{\displaystyle {\displaystyle {\mathit {f}}}}
 and 

g
{\displaystyle {\displaystyle {\mathit {g}}}}
. (See Deconvolution/1D for details.)

* The function should work for 

  g
  {\displaystyle {\displaystyle {\mathit {g}}}}
   of arbitrary length in each dimension (i.e., not hard coded or constant) and 

  f
  {\displaystyle {\displaystyle {\mathit {f}}}}
   of any length up to that of 

  g
  {\displaystyle {\displaystyle {\mathit {g}}}}
   in the corresponding dimension.
* The `deconv` function will need to be parameterized by the dimension 

  d
  {\displaystyle {\displaystyle {\mathit {d}}}}
   unless the dimension can be inferred from the data structures representing 

  g
  {\displaystyle {\displaystyle {\mathit {g}}}}
   and 

  f
  {\displaystyle {\displaystyle {\mathit {f}}}}
  .
* There may be more equations than unknowns. If convenient, use a function from a library that finds the best fitting solution to an overdetermined system of linear equations (as in the Multiple regression task). Otherwise, prune the set of equations as needed and solve as in the Reduced row echelon form task.
* Debug your solution using this test data, of which a portion is shown below. Be sure to verify both that the deconvolution of 

  g
  {\displaystyle {\displaystyle {\mathit {g}}}}
   with 

  f
  {\displaystyle {\displaystyle {\mathit {f}}}}
   is 

  h
  {\displaystyle {\displaystyle {\mathit {h}}}}
   and that the deconvolution of 

  g
  {\displaystyle {\displaystyle {\mathit {g}}}}
   with 

  h
  {\displaystyle {\displaystyle {\mathit {h}}}}
   is 

  f
  {\displaystyle {\displaystyle {\mathit {f}}}}
  . Display the results in a human readable form for the three dimensional case *only*.

dimension 1:

```
h: [-8, 2, -9, -2, 9, -8, -2]
f: [ 6, -9, -7, -5]
g: [-48, 84, -16, 95, 125, -70, 7, 29, 54, 10]

```

dimension 2:

```
h: [
      [-8, 1, -7, -2, -9, 4], 
      [4, 5, -5, 2, 7, -1], 
      [-6, -3, -3, -6, 9, 5]]
f: [
      [-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]]
g: [
      [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]]

```

dimension 3:

```
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]]]

```
assistant
(formerly Perl 6)

Translation of Tcl.

```
# 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;
        my $i = $r;
        until @m[$i;$lead] {
            next unless ++$i == $rows;
            $i = $r;
            return @m if ++$lead == $cols;
        }
        @m[$i, $r] = @m[$r, $i] if $r != $i;
        @m[$r] »/=» $ = @m[$r;$lead];
        for ^$rows -> $n {
            next if $n == $r;
            @m[$n] »-=» @m[$r] »×» (@m[$n;$lead] // 0);
        }
        ++$lead;
    }
    @m
 }

# Reduce to N equations in N unknowns; a no-op unless rows > cols
sub trim-system (@m) {
    return @m unless @m ≥ @m[0]; 
    my (\vars, @t) = @m[0] - 1;
    for ^vars -> \lead {
        for ^@m -> \row {
            @t.append: @m.splice(row, 1) and last if @m[row;lead];
        }
    }
    while @t < vars and @m { @t.push: shift @m }
    @t
}

# Pretty printer for N dimensional arrays
# Assumes if first element in level is an array, then all are
sub pretty-print ( @array, $indent = 0 ) {
    if @array[0] ~~ Array {
        say ' ' x $indent,"[";
        pretty-print( $_, $indent + 2 ) for @array;
        say ' ' x $indent, "]{$indent??','!!''}";
    } else {
        say ' ' x $indent, "[{say_it(@array)} ]{$indent??','!!''}";
    }

    sub say_it ( @array ) { return join ",", @array».fmt("%4s"); }
}

my @f[3;2;3] = (
  [
    [ -9,  5, -8 ],
    [  3,  5,  1 ],
  ],
  [
    [ -1, -7,  2 ],
    [ -5, -6,  6 ],
  ],
  [
    [  8,  5,  8 ],
    [ -2, -6, -4 ],
  ]
);

my @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 ],
  ]
);

say "# {+@f.shape}D array:";
my @h = deconvolve-N( @g, @f );
say "h =";
pretty-print( @h );
my @h-shaped[2;3;4] = @(deconvolve-N( @g, @f ));
my @ff = deconvolve-N( @g, @h-shaped );
say "\nff =";
pretty-print( @ff );

```

Output:

```
# 3D array:
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 ],
  ],
]
```