Vectorize BLAS level 1/2 routines with Eigen expressions

libeigen/eigen!2404

Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
Rasmus Munk Larsen
2026-04-05 18:53:11 -07:00
parent 4ad90a60f1
commit 8eabfb5342
6 changed files with 294 additions and 204 deletions

View File

@@ -25,15 +25,19 @@ struct functor_traits<scalar_norm1_op> {
// computes the sum of magnitudes of all vector elements or, for a complex vector x, the sum
// res = |Rex1| + |Imx1| + |Rex2| + |Imx2| + ... + |Rexn| + |Imxn|, where x is a vector of order n
extern "C" RealScalar EIGEN_CAT(REAL_SCALAR_SUFFIX, EIGEN_BLAS_FUNC_NAME(asum))(int *n, RealScalar *px, int *incx) {
// std::cerr << "__asum " << *n << " " << *incx << "\n";
Complex *x = reinterpret_cast<Complex *>(px);
if (*n <= 0) return 0;
// std::complex<T> is layout-compatible with T[2], so we can reinterpret
// a complex vector of length n as a real vector of length 2*n and use
// the fully vectorized cwiseAbs().sum() path.
if (*incx == 1)
return make_vector(x, *n).unaryExpr<scalar_norm1_op>().sum();
else
return make_vector(px, 2 * *n).cwiseAbs().sum();
else {
// For non-unit stride, fall back to the scalar_norm1_op approach since
// the real components are not contiguous across complex elements.
Complex *x = reinterpret_cast<Complex *>(px);
return make_vector(x, *n, std::abs(*incx)).unaryExpr<scalar_norm1_op>().sum();
}
}
extern "C" int EIGEN_CAT(i, EIGEN_BLAS_FUNC_NAME(amax))(int *n, RealScalar *px, int *incx) {