From 21cd3fe20990a5ac1d683806f605110962aac3f1 Mon Sep 17 00:00:00 2001 From: Charles Schlosser Date: Mon, 10 Jul 2023 17:40:17 +0000 Subject: [PATCH] Optimize check_rows_cols_for_overflow --- Eigen/src/Core/PlainObjectBase.h | 43 +++++++++++++++------ Eigen/src/Core/util/XprHelper.h | 4 +- unsupported/Eigen/CXX11/src/Tensor/Tensor.h | 2 +- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h index 1b8630460..ba6e51d31 100644 --- a/Eigen/src/Core/PlainObjectBase.h +++ b/Eigen/src/Core/PlainObjectBase.h @@ -28,21 +28,40 @@ namespace Eigen { namespace internal { -template struct check_rows_cols_for_overflow { +template +struct check_rows_cols_for_overflow { + EIGEN_STATIC_ASSERT(MaxRowsAtCompileTime * MaxColsAtCompileTime == MaxSizeAtCompileTime,YOU MADE A PROGRAMMING MISTAKE) template EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index) {} }; -template<> struct check_rows_cols_for_overflow { +template +struct check_rows_cols_for_overflow { + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index cols) { + constexpr Index MaxIndex = NumTraits::highest(); + bool error = cols > MaxIndex / MaxRowsAtCompileTime; + if (error) throw_std_bad_alloc(); + } +}; + +template +struct check_rows_cols_for_overflow { + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index) { + constexpr Index MaxIndex = NumTraits::highest(); + bool error = rows > MaxIndex / MaxColsAtCompileTime; + if (error) throw_std_bad_alloc(); + } +}; + +template <> +struct check_rows_cols_for_overflow { template EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index cols) { - // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 - // we assume Index is signed - Index max_index = (std::size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed - bool error = (rows == 0 || cols == 0) ? false - : (rows > max_index / cols); - if (error) - throw_std_bad_alloc(); + constexpr Index MaxIndex = NumTraits::highest(); + bool error = cols == 0 ? false : (rows > MaxIndex / cols); + if (error) throw_std_bad_alloc(); } }; @@ -268,7 +287,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type && internal::check_implication(RowsAtCompileTime==Dynamic && MaxRowsAtCompileTime!=Dynamic, rows<=MaxRowsAtCompileTime) && internal::check_implication(ColsAtCompileTime==Dynamic && MaxColsAtCompileTime!=Dynamic, cols<=MaxColsAtCompileTime) && rows>=0 && cols>=0 && "Invalid sizes when resizing a matrix or array."); - internal::check_rows_cols_for_overflow::run(rows, cols); + internal::check_rows_cols_for_overflow::run(rows, cols); #ifdef EIGEN_INITIALIZE_COEFFS Index size = rows*cols; bool size_changed = size != this->size(); @@ -340,7 +359,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type EIGEN_STRONG_INLINE void resizeLike(const EigenBase& _other) { const OtherDerived& other = _other.derived(); - internal::check_rows_cols_for_overflow::run(other.rows(), other.cols()); + internal::check_rows_cols_for_overflow::run(other.rows(), other.cols()); const Index othersize = other.rows()*other.cols(); if(RowsAtCompileTime == 1) { @@ -965,7 +984,7 @@ struct conservative_resize_like_impl && (( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows (!Derived::IsRowMajor && _this.rows() == rows) )) // column-major and we change only the number of columns { - internal::check_rows_cols_for_overflow::run(rows, cols); + internal::check_rows_cols_for_overflow::run(rows, cols); _this.derived().m_storage.conservativeResize(rows*cols,rows,cols); } else diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index ccc6d4313..d8ac1b340 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -311,7 +311,9 @@ constexpr inline unsigned compute_matrix_flags(int Options) { } constexpr inline int size_at_compile_time(int rows, int cols) { - return (rows==Dynamic || cols==Dynamic) ? Dynamic : rows * cols; + if (rows == 0 || cols == 0) return 0; + if (rows == Dynamic || cols == Dynamic) return Dynamic; + return rows * cols; } template struct size_of_xpr_at_compile_time diff --git a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h index b830984f7..f873f2b9f 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h +++ b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h @@ -360,7 +360,7 @@ class Tensor : public TensorBase::run(size, dimensions[i]); + internal::check_rows_cols_for_overflow::run(size, dimensions[i]); size *= dimensions[i]; } #ifdef EIGEN_INITIALIZE_COEFFS