blob: 4785ec7d1e15f8cdaa287c45485273136466f421 [file] [edit]
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2024 The Eigen Authors
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0
#include "lapack_common.h"
#if !ISCOMPLEX
// Compute sqrt(x*x + y*y) taking care not to cause unnecessary overflow.
extern "C" EIGEN_LAPACK_API Scalar EIGEN_BLAS_FUNC_NAME(lapy2)(Scalar* x, Scalar* y) {
return Eigen::numext::hypot(*x, *y);
}
// Compute sqrt(x*x + y*y + z*z) taking care not to cause unnecessary overflow.
extern "C" EIGEN_LAPACK_API Scalar EIGEN_BLAS_FUNC_NAME(lapy3)(Scalar* x, Scalar* y, Scalar* z) {
return Eigen::internal::xlapy3(*x, *y, *z);
}
// Determines machine parameters according to LAPACK specification.
extern "C" EIGEN_LAPACK_API Scalar EIGEN_BLAS_FUNC_NAME(lamch)(const char* cmach) {
return Eigen::internal::xlamch<Scalar>(*cmach);
}
// xLAMC3 is intended to force A and B to be stored prior to doing
// the addition of A and B, for use in situations where optimizers
// might hold one of these in a register.
extern "C" EIGEN_LAPACK_API Scalar EIGEN_BLAS_FUNC_NAME(lamc3)(Scalar* a, Scalar* b) {
volatile Scalar retval = *a + *b;
return retval;
}
// Performs complex division in real arithmetic, avoiding unnecessary overflow.
// Consistent with LAPACK SLADIV / DLADIV (Smith's algorithm).
EIGEN_LAPACK_FUNC(ladiv)(const Scalar* a, const Scalar* b, const Scalar* c, const Scalar* d, Scalar* p, Scalar* q) {
const std::complex<Scalar> res = Eigen::internal::xladiv(*a, *b, *c, *d);
*p = Eigen::numext::real(res);
*q = Eigen::numext::imag(res);
}
// Last non-zero column/row scanning for real matrices.
extern "C" EIGEN_LAPACK_API int EIGEN_CAT(ila, EIGEN_CAT(SCALAR_SUFFIX, lc_))(int* m, int* n, Scalar* a, int* lda) {
return Eigen::internal::ilaxlc(*m, *n, a, *lda);
}
extern "C" EIGEN_LAPACK_API int EIGEN_CAT(ila, EIGEN_CAT(SCALAR_SUFFIX, lr_))(int* m, int* n, Scalar* a, int* lda) {
return Eigen::internal::ilaxlr(*m, *n, a, *lda);
}
#else
namespace {
template <typename T>
struct complex_return_type;
template <>
struct complex_return_type<float> {
using type = eigen_lapack_complex_float;
};
template <>
struct complex_return_type<double> {
using type = eigen_lapack_complex_double;
};
} // namespace
// Conjugates entries of vector x.
EIGEN_LAPACK_FUNC(lacgv)(int* n, RealScalar* px, int* incx) {
Eigen::internal::xlacgv(*n, reinterpret_cast<Scalar*>(px), *incx);
}
// Performs complex division avoiding unnecessary overflow.
// Consistent with LAPACK CLADIV / ZLADIV (Smith's algorithm).
// Note on calling convention: Returning a 2-element struct { RealScalar r, i; }
// by value adheres to the SysV AMD64 ABI (gfortran on Linux/x86_64), consistent
// with the return-by-value convention used for cdotc/zdotc in blas/complexdots.cpp.
// Non-SysV environments (such as MSVC or f2c) may use hidden-pointer return conventions
// for complex-valued Fortran functions.
extern "C" EIGEN_LAPACK_API typename complex_return_type<RealScalar>::type EIGEN_BLAS_FUNC_NAME(ladiv)(
const RealScalar* px, const RealScalar* py) {
const auto* x = reinterpret_cast<const Scalar*>(px);
const auto* y = reinterpret_cast<const Scalar*>(py);
const Scalar res = Eigen::internal::xladiv(*x, *y);
return {Eigen::numext::real(res), Eigen::numext::imag(res)};
}
// Last non-zero column/row scanning for complex matrices.
extern "C" EIGEN_LAPACK_API int EIGEN_CAT(ila, EIGEN_CAT(SCALAR_SUFFIX, lc_))(int* m, int* n, RealScalar* a, int* lda) {
return Eigen::internal::ilaxlc(*m, *n, reinterpret_cast<Scalar*>(a), *lda);
}
extern "C" EIGEN_LAPACK_API int EIGEN_CAT(ila, EIGEN_CAT(SCALAR_SUFFIX, lr_))(int* m, int* n, RealScalar* a, int* lda) {
return Eigen::internal::ilaxlr(*m, *n, reinterpret_cast<Scalar*>(a), *lda);
}
#endif