Hi!

Here is what this function can look like:

```
use nalgebra::{Matrix, MatrixMN, RealField, Dim, DefaultAllocator};
use nalgebra::allocator::Allocator;
use nalgebra::storage::Storage;
fn center_scale<N, R, C, S>(mat: &Matrix<N, R, C, S>) -> MatrixMN<N, R, C>
where N: RealField,
R: Dim,
C: Dim,
S: Storage<N, R, C>,
DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> {
let column_means = mat.column_mean();
let centered_mat = mat.map_with_location(|row, col, n| {
n - column_means[row]
});
let variance = mat.map(|n| n * n).sum() / nalgebra::convert(mat.len() as f64);
let stddev = variance.sqrt();
centered_mat.map(|n| n / stddev)
}
```

- The type parameter
`N`

means that the matrix is generic wrt. the scalar type. Here it can be any float type (`f32`

or `f64`

).
- The type parameter
`R`

means that the matrix is generic wrt. the number of rows.
- The type parameter
`C`

means that the matrix is generic wrt. the number of columns.
- The type parameter
`S`

means that the matrix is generic wrt. its internal storage type. This allows this function to be used on both matrixces that own their data as well as matrix slices.
- The return type is
`MatrixMN<N, R, C>`

does not include a parameter for its storage type. This is because its storage type must be deduced automatically by the `DefaultAllocator`

.
- The
`DefaultAllocator: Allocator<N, R, C>`

is here to deduce the storage type of the result matrix.
- The
`DefaultAllocator: Allocator<N, R>`

is required by `mat.column_mean()`

.
- I replaced
`column_means.get(row).unwrap()`

by direct indexing `column_means[row]`

because you unwrap it anyways.
- I replaced
`mat.len() as f64`

by `nalgebra::convert(mat.len() as f64)`

which will convert `usize -> f64 -> N`

.

For even more genericity, you can do this:

```
use nalgebra::{Matrix, MatrixMN, SimdComplexField, Dim, DefaultAllocator};
use nalgebra::allocator::Allocator;
use nalgebra::storage::Storage;
fn center_scale<N, R, C, S>(mat: &Matrix<N, R, C, S>) -> MatrixMN<N, R, C>
where N: SimdComplexField,
R: Dim,
C: Dim,
S: Storage<N, R, C>,
DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> {
let column_means = mat.column_mean();
let centered_mat = mat.map_with_location(|row, _, n| {
n - column_means[row]
});
let zero: N::SimdRealField = nalgebra::zero();
let variance: N::SimdRealField = mat.fold(zero, |acc, n| acc + n.simd_modulus_squared()) / nalgebra::convert(mat.len() as f64);
let stddev = variance.simd_sqrt();
centered_mat.unscale(stddev)
}
```

This will allow your function to work on matrices containing complex numbers too, as well as SIMD types (useful if you want to center four matrices simultaneously for example). Note that I replaced your `mat.map(...).sum()`

by a `mat.fold`

. You can do this on the first piece of code I mentioned too and it will avoid the allocation made by the `map`

.