perf(math): use checked MKL GER for rank-one products
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user