Add C++ implementations for xLAPY2 and xLAPY3. They are straight translations of the corresponding Fortran code, even though xLAPY2 can just call std:hypot. The code currently lives in eigen3/lapack/experimental. The plan is to finish development here, and once its done upstream it replacing all the f2c'ed code. PiperOrigin-RevId: 380897335
diff --git a/lapack/experimental/README.md b/lapack/experimental/README.md new file mode 100644 index 0000000..86aaace --- /dev/null +++ b/lapack/experimental/README.md
@@ -0,0 +1,3 @@ +This directory contains C++11 replacment for the f2c-ed functions in the lapack +directory. This is a temporary directory, which is being used to develop and +stage these changes, once this code is upstreamed, it will be deleted.
diff --git a/lapack/experimental/xlapy2.cpp b/lapack/experimental/xlapy2.cpp new file mode 100644 index 0000000..5992f9e --- /dev/null +++ b/lapack/experimental/xlapy2.cpp
@@ -0,0 +1,24 @@ +#include <algorithm> +#include <cmath> + +extern "C" { +float slapy2_(float* x, float* y); +double dlapy2_(double* x, double* y); +} + +// Compute sqrt(x*x + y*y) taking care not to cause unnecessary overflow. +template <typename T> +T xlapy2(const T x, const T y) { + const T xabs = std::abs(x); + const T yabs = std::abs(y); + const T w = std::fmax(xabs, yabs); + const T z = std::fmin(xabs, yabs); + if (z > T(0)) { + const T t = z / w; + return w * std::sqrt(T(1) + t * t); + } + return w; +} + +float slapy2_(float* x, float* y) { return xlapy2(*x, *y); } +double dlapy2_(double* x, double* y) { return xlapy2(*x, *y); }
diff --git a/lapack/experimental/xlapy3.cpp b/lapack/experimental/xlapy3.cpp new file mode 100644 index 0000000..9c935fa --- /dev/null +++ b/lapack/experimental/xlapy3.cpp
@@ -0,0 +1,30 @@ +#include <algorithm> +#include <cmath> + +extern "C" { +float slapy3_(float* x, float* y, float* z); +double dlapy3_(double* x, double* y, double* z); +} + +// Compute sqrt(x*x + y*y + z*z) taking care not to cause unnecessary overflow. +template <typename T> +T xlapy3(const T x, const T y, const T z) { + const T xabs = std::abs(x); + const T yabs = std::abs(y); + const T zabs = std::abs(z); + const T w = std::fmax(std::fmax(xabs, yabs), zabs); + + if (w == T(0)) { + // W can be zero for max(0,nan,0) adding all three entries together will + // make sure NaN will not disappear. + return (xabs + yabs + zabs); + } + + const T tx = xabs / w; + const T ty = yabs / w; + const T tz = zabs / w; + return w * std::sqrt(tx * tx + ty * ty + tz * tz); +} + +float slapy3_(float* x, float* y, float* z) { return xlapy3(*x, *y, *z); } +double dlapy3_(double* x, double* y, double* z) { return xlapy3(*x, *y, *z); }