What about this:
#import "@preview/mannot:0.3.1": *
#let labelmat(..args, dx:2em, dy:1em) = {
let mat = args.pos().at(0)
let labels = args.pos().slice(1)
let data = ()
let augment = (:)
if mat.has("augment") {
augment = mat.augment
if augment.at("stroke") == auto {
let _ = augment.remove("stroke")
}
}
let nrows = mat.rows.len()
let ncols = mat.rows.at(1).len()
if labels.len() != nrows + ncols {
panic("Number of labels must be equal to number of rows plus number of columns")
}
for i in range(nrows) {
let row = ()
for j in range(ncols) {
let elem = mat.rows.at(i).at(j)
if i == 0 {
elem = mark(elem, tag:label("c" + str(j)))
}
if j == 0 {
elem = mark(elem, tag:label("r" + str(i)))
}
row.push(elem)
}
data.push(row)
}
std.math.mat(augment:augment, ..data)
for i in range(nrows) {
annot(label("r" + str(i)), pos:center, dx:-dx, leader:false, labels.at(i))
}
for j in range(ncols) {
annot(label("c" + str(j)), pos:center, dy:-dy, leader:false, labels.at(nrows+j))
}
}
$
labelmat(
mat( augment:#(hline:4, vline:4),
1215.542, -357.771, -715.542, 357.771, -500.000, 0.000, 0.000, 0.000;
-357.771, 178.885, 357.771, -178.885, 0.000, 0.000, 0.000, 0.000;
-715.542, 357.771, 2146.625, -357.771, -715.542, -357.771, -715.542, 357.771;
357.771, -178.885, -357.771, 536.656, -357.771, -178.885, 357.771, -178.885;
-500.000, 0.000, -715.542, -357.771, 1215.542, 357.771, 0.000, 0.000;
0.000, 0.000, -357.771, -178.885, 357.771, 178.885, 0.000, 0.000;
0.000, 0.000, -715.542, 357.771, 0.000, 0.000, 715.542, -357.771;
0.000, 0.000, 357.771, -178.885, 0.000, 0.000, -357.771, 178.885 ),
f_(1x), f_(1y), f_(2x), f_(2y), f_(3x), f_(3y), f_(4x), f_(4y),
u_(1x), u_(1y), u_(2x), u_(2y), u_(3x), u_(3y), u_(4x), u_(4y),
dx:#{3.6em}, dy:#{1.3em},
)
mat( augment:#(hline:4), u_(1x); u_(1y); u_(2x); u_(2y); 0; 0; 0; 0 )
= mat( augment:#(hline:4), 0; -1; 0; -1; f_(3x); f_(3y); f_(4x); f_(4y) )
$