Toroidally magnify-blur a matrix Task

Given a matrix of numbers \$M\$ with \$r\$ rows and \$c\$ columns, and the magnification factor \$n\$, build the matrix with \$rn\$ rows and \$cn\$ columns where the original elements are spaced \$n\$ units apart and the gaps are filled by piecewise linear interpolation:

$$
    \begin{bmatrix}
    a_{11} &amp; a_{12} &amp; \cdots \\
    a_{21} &amp; a_{22} &amp; \cdots \\
    \vdots &amp; \vdots &amp; \ddots \\
    \end{bmatrix} \Rightarrow
    \begin{bmatrix}
    a_{11} &amp; \frac{(n-1)a_{11} + a_{12}}{n} &amp; \cdots &amp; a_{12} &amp; \cdots \\
    \frac{(n-1)a_{11} + a_{21}}{n} &amp; \frac{(n-1) \frac{(n-1)a_{11} + a_{21}}{n} + \frac{(n-1)a_{12} + a_{22}}{n}}{n} &amp; \cdots &amp; \frac{(n-1)a_{12} + a_{22}}{n} &amp; \cdots \\
    \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\
    a_{21} &amp; \frac{(n-1)a_{21} + a_{22}}{n} &amp; \cdots &amp; a_{22} &amp; \cdots \\
    \vdots &amp; \vdots &amp; &amp; \vdots &amp; \ddots \\
    \end{bmatrix}
$$

Because the operation is toroidal, the "gaps" between the \$r\$-th row and the 1st row (resp. the \$c\$-th column and the 1st column) must also be filled, which is placed below the original elements of the \$r\$-th row (resp. on the right side of the \$c\$-th column).

You can take \$M\$ and \$n\$ (and optionally \$r\$ and \$c\$) as input and output the resulting matrix in any suitable format. \$n\$ is guaranteed to be a positive integer. The input matrix and the result may have non-integers.

Standard code-golf rules apply. The shortest code in bytes wins.

Test cases

# one-element matrix
M = [[1]], n = 3
[[1, 1, 1],
 [1, 1, 1],
 [1, 1, 1]]

# one-element matrix, large n
M = [[1]], n = 100
(100-by-100 matrix of ones)

# one-row matrix
M = [[0, 6, 3, 6]], n = 3
[[0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2],
 [0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2],
 [0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2]]

# one-column matrix
M = [[0], [6], [3], [6]], n = 3
(transpose of the above)

# n = 1
M = [[1, 9, 8, 3],
     [5, 4, 2, 7],
     [3, 8, 5, 1]], n = 1
(same as M)

# 2-by-2 matrix; here the result is rounded to 2 decimal places for convenience.
# An answer doesn't need to round them, though one may choose to do so.
M = [[0, 9],
     [3, 6]], n = 3
[[0, 3,    6,    9, 6,    3],
 [1, 3.33, 5.67, 8, 5.67, 3.33],
 [2, 3.67, 5.33, 7, 5.33, 3.67],
 [3, 4,    5,    6, 5,    4],
 [2, 3.67, 5.33, 7, 5.33, 3.67],
 [1, 3.33, 5.67, 8, 5.67, 3.33]]

# a larger test case
M = [[0, 25, 0],
     [25, 0, 0],
     [0, 0, 25]], n = 5
[[0, 5, 10, 15, 20, 25, 20, 15, 10, 5, 0, 0, 0, 0, 0],
 [5, 8, 11, 14, 17, 20, 16, 12, 8, 4, 0, 1, 2, 3, 4],
 [10, 11, 12, 13, 14, 15, 12, 9, 6, 3, 0, 2, 4, 6, 8],
 [15, 14, 13, 12, 11, 10, 8, 6, 4, 2, 0, 3, 6, 9, 12],
 [20, 17, 14, 11, 8, 5, 4, 3, 2, 1, 0, 4, 8, 12, 16],
 [25, 20, 15, 10, 5, 0, 0, 0, 0, 0, 0, 5, 10, 15, 20],
 [20, 16, 12, 8, 4, 0, 1, 2, 3, 4, 5, 8, 11, 14, 17],
 [15, 12, 9, 6, 3, 0, 2, 4, 6, 8, 10, 11, 12, 13, 14],
 [10, 8, 6, 4, 2, 0, 3, 6, 9, 12, 15, 14, 13, 12, 11],
 [5, 4, 3, 2, 1, 0, 4, 8, 12, 16, 20, 17, 14, 11, 8],
 [0, 0, 0, 0, 0, 0, 5, 10, 15, 20, 25, 20, 15, 10, 5],
 [0, 1, 2, 3, 4, 5, 8, 11, 14, 17, 20, 16, 12, 8, 4],
 [0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 15, 12, 9, 6, 3],
 [0, 3, 6, 9, 12, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2],
 [0, 4, 8, 12, 16, 20, 17, 14, 11, 8, 5, 4, 3, 2, 1]]
APL (Dyalog Extended), 27 26 bytes

-1 thanks to Bubbler.

Anonymous infix lambda. Takes \$n\$ as left argument and \$M\$ as right argument.



{⊃+⌿,(⍳⍺)⍉⍤⌽\⍣2⊂⍺/⍺⌿⍵÷⍺*2}


Try it online! (the \$n=100\$ case run out of memory on TIO gives by default, but works offline)

{…} "dfn"; ⍺ is \$n\$ and ⍵ is \$M\$

 ⍺*2 \$n^2\$

 ⍵÷ \$M\over n^2\$

 ⍺⌿ replicate vertically so each row becomes \$n\$ copies

 ⍺/ replicate horizontally so each column becomes \$n\$ copies

 ⊂ enclose to work on entire matrix

 (⍳⍺)…⍣2 do the following twice, each time with the \$0,1…n-1\$ as left argument:

  \ outer "product" using the following tacit function instead of multiplication:

   ⌽ cyclically rotate the rows by the indices

   ⍤ then:

    ⍉ transpose

 , flatten

 +⌿ sum

 ⊃ disclose (since the summation reduced rank from 1 to 0 by enclosing)