perf(math): use checked MKL GER for rank-one products

This commit is contained in:
KOKO\Mimi
2026-10-14 19:44:29 +09:00
parent c58d499727
commit 11af92809a
3 changed files with 148 additions and 1 deletions
+18 -1
View File
@@ -127,7 +127,24 @@ Matrix MultiplyTransposeLeft(const Matrix& left, const Matrix& right) {
bool OuterProduct(const double* left, const std::size_t rows,
const double* right, const std::size_t columns,
double* destination) {
return MultiplyTransposeRight(left, rows, right, columns, 1U, destination);
const auto m = ToMklSize(rows);
const auto n = ToMklSize(columns);
const auto maximum = std::numeric_limits<std::size_t>::max() / sizeof(double);
if (!m.HasValue() || !n.HasValue() || rows > maximum || columns > maximum ||
(columns != 0U && rows > maximum / columns))
throw std::length_error{"Dense product dimensions exceed backend limits."};
if (rows == 0U || columns == 0U) return true;
if (destination == nullptr || left == nullptr || right == nullptr)
throw std::invalid_argument{"Dense product requires nonnull storage."};
for (std::size_t i = 0U; i < rows; ++i)
if (!std::isfinite(left[i])) return false;
for (std::size_t i = 0U; i < columns; ++i)
if (!std::isfinite(right[i])) return false;
// GER updates A, so replace every destination entry only after validation.
std::fill_n(destination, rows * columns, 0.0);
cblas_dger(CblasRowMajor, m.Value(), n.Value(), 1.0, left, 1, right, 1,
destination, n.Value());
return true;
}
bool MultiplyTransposeRight(const double* left, const std::size_t rows,