diff --git a/librapid/include/librapid/array/arrayContainer.hpp b/librapid/include/librapid/array/arrayContainer.hpp index 9112da2c..a2831e10 100644 --- a/librapid/include/librapid/array/arrayContainer.hpp +++ b/librapid/include/librapid/array/arrayContainer.hpp @@ -71,12 +71,11 @@ namespace librapid { template struct IsArrayContainer : std::false_type {}; - template - struct IsArrayContainer, StorageScalar>> - : std::true_type {}; + template + struct IsArrayContainer> : std::true_type {}; - LIBRAPID_DEFINE_AS_TYPE(size_t dims COMMA typename StorageScalar, - array::ArrayContainer COMMA StorageScalar>); + LIBRAPID_DEFINE_AS_TYPE(typename StorageScalar, + array::ArrayContainer); LIBRAPID_DEFINE_AS_TYPE(typename StorageScalar, array::ArrayContainer); @@ -88,7 +87,7 @@ namespace librapid { public: using StorageType = StorageType_; using ShapeType = ShapeType_; - using StrideType = Stride<32>; + using StrideType = Stride; using SizeType = typename ShapeType::SizeType; using Scalar = typename StorageType::Scalar; using Packet = typename typetraits::TypeInfo::Packet; @@ -582,11 +581,11 @@ namespace librapid { auto subSize = res.shape().size(); int64_t storageSize = sizeof(typename StorageType_::Scalar); cl_buffer_region region {index * subSize * storageSize, subSize * storageSize}; - res.m_storage.set( + res.m_storage = StorageType_(m_storage.data().createSubBuffer( StorageType_::bufferFlags, CL_BUFFER_CREATE_TYPE_REGION, ®ion), subSize, - false)); + false); return res; #else LIBRAPID_ERROR("OpenCL support not enabled"); @@ -597,7 +596,7 @@ namespace librapid { res.m_shape = m_shape.subshape(1, ndim()); auto subSize = res.shape().size(); Scalar *begin = m_storage.begin().get() + index * subSize; - res.m_storage.set(StorageType_(begin, subSize, false)); + res.m_storage = StorageType_(begin, subSize, false); return res; #else LIBRAPID_ERROR("CUDA support not enabled"); @@ -610,7 +609,7 @@ namespace librapid { auto subSize = res.shape().size(); Scalar *begin = m_storage.begin() + index * subSize; Scalar *end = begin + subSize; - res.m_storage.set(StorageType_(begin, end, false)); + res.m_storage = StorageType_(begin, end, false); return res; } } @@ -845,7 +844,7 @@ namespace librapid { template LIBRAPID_ALWAYS_INLINE void ArrayContainer::str( const fmt::formatter &format, char bracket, char separator, Ctx &ctx) const { - GeneralArrayView(*this).str(format, bracket, separator, ctx); + createGeneralArrayView(*this).str(format, bracket, separator, ctx); } } // namespace array diff --git a/librapid/include/librapid/array/arrayTypeDef.hpp b/librapid/include/librapid/array/arrayTypeDef.hpp index cf3d5a1a..ef830d39 100644 --- a/librapid/include/librapid/array/arrayTypeDef.hpp +++ b/librapid/include/librapid/array/arrayTypeDef.hpp @@ -28,9 +28,10 @@ namespace librapid { /// `backend::CPU`, `backend::CUDA` or any Storage interface /// \tparam Scalar The scalar type of the array. /// \tparam StorageType The storage type of the array. - template + template::value, int> = 0> using Array = - array::ArrayContainer, + array::ArrayContainer::Type>; /// A definition for fixed-size array objects. @@ -38,15 +39,14 @@ namespace librapid { /// \tparam Dimensions The dimensions of the array. /// \see Array template - using ArrayF = - array::ArrayContainer, FixedStorage>; + using ArrayF = array::ArrayContainer>; /// A reference type for Array objects. Use this to accept Array objects as parameters since /// the compiler cannot determine the templates tingle for the Array typedef. For more /// granularity, you can also accept a raw ArrayContainer object. \tparam StorageType The /// storage type of the array. \see Array \see ArrayF \see Function \see FunctionRef template - using ArrayRef = array::ArrayContainer, StorageType>; + using ArrayRef = array::ArrayContainer; template using Matrix = diff --git a/librapid/include/librapid/array/generalArrayView.hpp b/librapid/include/librapid/array/generalArrayView.hpp index 4af8570d..59180173 100644 --- a/librapid/include/librapid/array/generalArrayView.hpp +++ b/librapid/include/librapid/array/generalArrayView.hpp @@ -14,27 +14,33 @@ namespace librapid { LIBRAPID_DEFINE_AS_TYPE(typename T, array::GeneralArrayView); } // namespace typetraits + template + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto createGeneralArrayView(T &&array) { + return array::GeneralArrayView(std::forward(array)); + } + namespace array { template class GeneralArrayView { public: - // using ArrayType = T; using BaseType = typename std::decay_t; using Scalar = typename typetraits::TypeInfo::Scalar; using Reference = BaseType &; using ConstReference = const BaseType &; using Backend = typename typetraits::TypeInfo::Backend; - using ArrayType = Array; - using StrideType = typename ArrayType::StrideType; - using ShapeType = typename ArrayType::ShapeType; - using Iterator = detail::ArrayIterator; + using StrideType = typename BaseType::StrideType; + using ShapeType = typename BaseType::ShapeType; + using StorageType = typename BaseType::StorageType; + // using ArrayType = Array; + using ArrayType = array::ArrayContainer; + using Iterator = detail::ArrayIterator; /// Default constructor should never be used GeneralArrayView() = delete; /// Copy an ArrayView object /// \param array The array to copy - LIBRAPID_ALWAYS_INLINE GeneralArrayView(ArrayViewType &array); + // LIBRAPID_ALWAYS_INLINE GeneralArrayView(ArrayViewType &array); /// Copy an ArrayView object (not const) /// \param array The array to copy @@ -57,7 +63,7 @@ namespace librapid { /// Assigns a temporary ArrayView to this ArrayView. /// \param other The ArrayView to move. /// \return A reference to this ArrayView. - // ArrayView &operator=(ArrayView &&other) noexcept = default; + GeneralArrayView &operator=(GeneralArrayView &&other) noexcept = default; /// Assign a scalar value to this ArrayView. This function should only be used to /// assign to a zero-dimensional "scalar" ArrayView, and will throw an error if used @@ -140,17 +146,17 @@ namespace librapid { Ctx &ctx) const; private: - ArrayViewType &m_ref; + ArrayViewType m_ref; ShapeType m_shape; StrideType m_stride; int64_t m_offset = 0; }; - template - LIBRAPID_ALWAYS_INLINE - GeneralArrayView::GeneralArrayView(ArrayViewType &array) : - m_ref(array), - m_shape(array.shape()), m_stride(array.shape()) {} + // template + // LIBRAPID_ALWAYS_INLINE + // GeneralArrayView::GeneralArrayView(ArrayViewType &array) : + // m_ref(array), + // m_shape(array.shape()), m_stride(array.shape()) {} template LIBRAPID_ALWAYS_INLINE @@ -202,7 +208,7 @@ namespace librapid { "Index {} out of bounds in ArrayContainer::operator[] with leading dimension={}", index, m_shape[0]); - GeneralArrayView view(m_ref); + GeneralArrayView view(createGeneralArrayView(m_ref)); const auto stride = Stride(m_shape); view.setShape(m_shape.subshape(1, ndim())); if (ndim() == 1) @@ -221,7 +227,7 @@ namespace librapid { "Index {} out of bounds in ArrayContainer::operator[] with leading dimension={}", index, m_shape[0]); - GeneralArrayView view(m_ref); + GeneralArrayView view(createGeneralArrayView(m_ref)); const auto stride = Stride(m_shape); view.setShape(m_shape.subshape(1, ndim())); if (ndim() == 1) diff --git a/librapid/include/librapid/array/linalg/transpose.hpp b/librapid/include/librapid/array/linalg/transpose.hpp index d5e698f9..26748561 100644 --- a/librapid/include/librapid/array/linalg/transpose.hpp +++ b/librapid/include/librapid/array/linalg/transpose.hpp @@ -634,9 +634,11 @@ namespace librapid { } }; // namespace array - template, - typename std::enable_if_t< - typetraits::TypeInfo::type == detail::LibRapidType::ArrayContainer, int> = 0> + template::type == + detail::LibRapidType::ArrayContainer && + typetraits::IsSizeType::value, + int> = 0> auto transpose(T &&array, const ShapeType &axes = ShapeType()) { // If axes is empty, transpose the array in reverse order ShapeType newAxes = axes; @@ -648,9 +650,11 @@ namespace librapid { return array::Transpose(array, newAxes); } - template, - typename std::enable_if_t< - typetraits::TypeInfo::type != detail::LibRapidType::ArrayContainer, int> = 0> + template::type != + detail::LibRapidType::ArrayContainer && + typetraits::IsSizeType::value, + int> = 0> auto transpose(const T &function, const ShapeType &axes = ShapeType()) { // If axes is empty, transpose the array in reverse order auto array = function.eval(); diff --git a/librapid/include/librapid/array/pseudoConstructors.hpp b/librapid/include/librapid/array/pseudoConstructors.hpp index 91c6427c..ae06ba12 100644 --- a/librapid/include/librapid/array/pseudoConstructors.hpp +++ b/librapid/include/librapid/array/pseudoConstructors.hpp @@ -51,9 +51,9 @@ namespace librapid { /// \tparam N Maximum number of dimensions of the Shape /// \param shape Shape of the Array /// \return Array filled with zeros - template - Array zeros(const Shape &shape) { + template::value, int> = 0> + Array zeros(const ShapeType &shape) { return Array(shape, Scalar(0)); } @@ -79,9 +79,9 @@ namespace librapid { /// \tparam N Maximum number of dimensions of the Shape /// \param shape Shape of the Array /// \return Array filled with ones - template - Array ones(const Shape &shape) { + template::value, int> = 0> + Array ones(const ShapeType &shape) { return Array(shape, Scalar(1)); } @@ -109,11 +109,11 @@ namespace librapid { /// \tparam N Maximum number of dimensions of the Shape /// \param shape Shape of the Array /// \return Array filled with numbers from 0 to N-1 - template - Array ordered(const Shape &shape) { + template::value, int> = 0> + Array ordered(const ShapeType &shape) { Array result(shape); - for (size_t i = 0; i < shape.size(); i++) { result.storage()[i] = Scalar(i); } + for (size_t i = 0; i < result.size(); i++) { result.storage()[i] = Scalar(i); } return result; } diff --git a/librapid/include/librapid/array/shape.hpp b/librapid/include/librapid/array/shape.hpp index b3b92673..1bc28e56 100644 --- a/librapid/include/librapid/array/shape.hpp +++ b/librapid/include/librapid/array/shape.hpp @@ -8,15 +8,14 @@ namespace librapid { namespace typetraits { - LIBRAPID_DEFINE_AS_TYPE(size_t N, Shape); + LIBRAPID_DEFINE_AS_TYPE_NO_TEMPLATE(Shape); LIBRAPID_DEFINE_AS_TYPE_NO_TEMPLATE(MatrixShape); } // namespace typetraits - template class Shape { public: using SizeType = uint32_t; - static constexpr size_t MaxDimensions = N; + static constexpr size_t MaxDimensions = LIBRAPID_MAX_ARRAY_DIMS; /// Default constructor LIBRAPID_ALWAYS_INLINE Shape() = default; @@ -49,20 +48,13 @@ namespace librapid { /// \param other Temporary Shape object to copy LIBRAPID_ALWAYS_INLINE Shape(Shape &&other) noexcept = default; - /// Create a Shape object from one with a different type and number of dimensions. - /// \tparam V Scalar type of the values - /// \tparam Dim Number of dimensions - /// \param other Shape object to copy - template - LIBRAPID_ALWAYS_INLINE Shape(const Shape &other); - /// Create a Shape object from one with a different type and number of dimensions, moving it /// instead of copying it. /// \tparam V Scalar type of the values /// \tparam Dim Number of dimensions /// \param other Temporary Shape object to move template - LIBRAPID_ALWAYS_INLINE Shape(Shape &&other) noexcept; + LIBRAPID_ALWAYS_INLINE Shape(Shape &&other) noexcept; /// Assign a Shape object to this object /// \tparam V Scalar type of the Shape @@ -143,7 +135,7 @@ namespace librapid { protected: int m_dims; - std::array m_data; + std::array m_data; }; class MatrixShape { @@ -178,9 +170,11 @@ namespace librapid { LIBRAPID_ALWAYS_INLINE MatrixShape &operator=(MatrixShape &&other) noexcept = default; static LIBRAPID_ALWAYS_INLINE auto zeros() -> MatrixShape; - static LIBRAPID_ALWAYS_INLINE auto ones() -> MatrixShape; + static LIBRAPID_ALWAYS_INLINE auto zeros(size_t) -> MatrixShape; + static LIBRAPID_ALWAYS_INLINE auto ones(size_t) -> MatrixShape; + template LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator[](Index index) const -> const SizeType &; @@ -193,7 +187,7 @@ namespace librapid { LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE constexpr auto ndim() const -> int; LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto subshape(size_t start, size_t end) const - -> Shape; + -> Shape; LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto size() const -> size_t; @@ -207,101 +201,56 @@ namespace librapid { namespace detail { template - Shape shapeFromFixedStorage(const FixedStorage &) { - return Shape({Dims...}); + Shape shapeFromFixedStorage(const FixedStorage &) { + return Shape({Dims...}); } } // namespace detail - template template - LIBRAPID_ALWAYS_INLINE Shape::Shape(const FixedStorage &) : + LIBRAPID_ALWAYS_INLINE Shape::Shape(const FixedStorage &) : m_data({Dimensions...}) {} - template template - LIBRAPID_ALWAYS_INLINE Shape::Shape(const std::initializer_list &vals) : + LIBRAPID_ALWAYS_INLINE Shape::Shape(const std::initializer_list &vals) : m_dims(vals.size()) { - LIBRAPID_ASSERT(vals.size() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - vals.size()); for (size_t i = 0; i < vals.size(); ++i) { m_data[i] = *(vals.begin() + i); } } - template template - LIBRAPID_ALWAYS_INLINE Shape::Shape(const std::vector &vals) : m_dims(vals.size()) { - LIBRAPID_ASSERT(vals.size() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - vals.size()); + LIBRAPID_ALWAYS_INLINE Shape::Shape(const std::vector &vals) : m_dims(vals.size()) { for (size_t i = 0; i < vals.size(); ++i) { m_data[i] = vals[i]; } } - template - template - LIBRAPID_ALWAYS_INLINE Shape::Shape(const Shape &other) : m_dims(other.ndim()) { - LIBRAPID_ASSERT(other.ndim() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - other.ndim()); - for (size_t i = 0; i < m_dims; ++i) { m_data[i] = other[i]; } - } - - template - template - LIBRAPID_ALWAYS_INLINE Shape::Shape(Shape &&other) noexcept : m_dims(other.ndim()) { - LIBRAPID_ASSERT(other.ndim() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - other.ndim()); - for (size_t i = 0; i < m_dims; ++i) { m_data[i] = other[i]; } - } - - template template - LIBRAPID_ALWAYS_INLINE auto Shape::operator=(const std::initializer_list &vals) - -> Shape & { - LIBRAPID_ASSERT(vals.size() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - vals.size()); + LIBRAPID_ALWAYS_INLINE auto Shape::operator=(const std::initializer_list &vals) -> Shape & { m_dims = vals.size(); for (int64_t i = 0; i < vals.size(); ++i) { m_data[i] = *(vals.begin() + i); } return *this; } - template template - LIBRAPID_ALWAYS_INLINE auto Shape::operator=(const std::vector &vals) -> Shape & { - LIBRAPID_ASSERT(vals.size() <= N, - "Shape object is limited to {} dimensions. Cannot initialize with {}", - N, - vals.size()); + LIBRAPID_ALWAYS_INLINE auto Shape::operator=(const std::vector &vals) -> Shape & { m_dims = vals.size(); for (int64_t i = 0; i < vals.size(); ++i) { m_data[i] = vals[i]; } return *this; } - template - LIBRAPID_ALWAYS_INLINE auto Shape::zeros(size_t dims) -> Shape { + LIBRAPID_ALWAYS_INLINE auto Shape::zeros(size_t dims) -> Shape { Shape res; res.m_dims = dims; for (size_t i = 0; i < dims; ++i) res.m_data[i] = 0; return res; } - template - LIBRAPID_ALWAYS_INLINE auto Shape::ones(size_t dims) -> Shape { + LIBRAPID_ALWAYS_INLINE auto Shape::ones(size_t dims) -> Shape { Shape res; res.m_dims = dims; for (size_t i = 0; i < dims; ++i) res.m_data[i] = 1; return res; } - template template - LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::operator[](Index index) const + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::operator[](Index index) const -> const SizeType & { static_assert(std::is_integral_v, "Index must be an integral type"); LIBRAPID_ASSERT(index < m_dims, "Index out of bounds"); @@ -309,17 +258,15 @@ namespace librapid { return m_data[index]; } - template template - LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::operator[](Index index) -> SizeType & { + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::operator[](Index index) -> SizeType & { static_assert(std::is_integral_v, "Index must be an integral type"); LIBRAPID_ASSERT(index < m_dims, "Index out of bounds"); LIBRAPID_ASSERT(index >= 0, "Index out of bounds"); return m_data[index]; } - template - LIBRAPID_ALWAYS_INLINE auto Shape::operator==(const Shape &other) const -> bool { + LIBRAPID_ALWAYS_INLINE auto Shape::operator==(const Shape &other) const -> bool { if (m_dims != other.m_dims) return false; for (size_t i = 0; i < m_dims; ++i) { if (m_data[i] != other.m_data[i]) return false; @@ -327,18 +274,13 @@ namespace librapid { return true; } - template - LIBRAPID_ALWAYS_INLINE auto Shape::operator!=(const Shape &other) const -> bool { + LIBRAPID_ALWAYS_INLINE auto Shape::operator!=(const Shape &other) const -> bool { return !(*this == other); } - template - LIBRAPID_NODISCARD auto Shape::ndim() const -> int { - return m_dims; - } + LIBRAPID_NODISCARD auto Shape::ndim() const -> int { return m_dims; } - template - LIBRAPID_NODISCARD auto Shape::subshape(size_t start, size_t end) const -> Shape { + LIBRAPID_NODISCARD auto Shape::subshape(size_t start, size_t end) const -> Shape { LIBRAPID_ASSERT(start <= end, "Start index must be less than end index"); LIBRAPID_ASSERT(end <= m_dims, "End index must be less than or equal to the number of dimensions"); @@ -350,17 +292,14 @@ namespace librapid { return res; } - template - LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::size() const -> size_t { + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto Shape::size() const -> size_t { size_t res = 1; for (size_t i = 0; i < m_dims; ++i) res *= m_data[i]; return res; } - template template - LIBRAPID_ALWAYS_INLINE void Shape::str(const fmt::formatter &format, - Ctx &ctx) const { + LIBRAPID_ALWAYS_INLINE void Shape::str(const fmt::formatter &format, Ctx &ctx) const { fmt::format_to(ctx.out(), "Shape("); for (size_t i = 0; i < m_dims; ++i) { format.format(m_data[i], ctx); @@ -406,9 +345,16 @@ namespace librapid { } LIBRAPID_ALWAYS_INLINE auto MatrixShape::zeros() -> MatrixShape { return MatrixShape({0, 0}); } - LIBRAPID_ALWAYS_INLINE auto MatrixShape::ones() -> MatrixShape { return MatrixShape({1, 1}); } + LIBRAPID_ALWAYS_INLINE auto MatrixShape::zeros(size_t) -> MatrixShape { + return MatrixShape({0, 0}); + } + + LIBRAPID_ALWAYS_INLINE auto MatrixShape::ones(size_t) -> MatrixShape { + return MatrixShape({1, 1}); + } + template LIBRAPID_ALWAYS_INLINE auto MatrixShape::operator[](Index index) const -> const SizeType & { static_assert(std::is_integral_v, "Index must be an integral type"); @@ -429,14 +375,13 @@ namespace librapid { LIBRAPID_ALWAYS_INLINE constexpr auto MatrixShape::ndim() const -> int { return 2; } - LIBRAPID_ALWAYS_INLINE auto MatrixShape::subshape(size_t start, size_t end) const - -> Shape { + LIBRAPID_ALWAYS_INLINE auto MatrixShape::subshape(size_t start, size_t end) const -> Shape { LIBRAPID_ASSERT(start <= end, "Start index must be less than end index"); LIBRAPID_ASSERT(end <= 2, "End index must be less than or equal to the number of dimensions"); LIBRAPID_ASSERT(start >= 0, "Start index must be greater than or equal to 0"); - Shape res; + Shape res; res[0] = m_rows; res[1] = m_cols; return res.subshape(start, end); @@ -454,27 +399,23 @@ namespace librapid { fmt::format_to(ctx.out(), ")"); } - template - LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator==(const Shape &lhs, + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator==(const Shape &lhs, const MatrixShape &rhs) -> bool { return lhs.ndim() == 2 && lhs[0] == rhs[0] && lhs[1] == rhs[1]; } - template LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator==(const MatrixShape &lhs, - const Shape &rhs) -> bool { + const Shape &rhs) -> bool { return rhs == lhs; } - template - LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator!=(const Shape &lhs, + LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator!=(const Shape &lhs, const MatrixShape &rhs) -> bool { return !(lhs == rhs); } - template LIBRAPID_NODISCARD LIBRAPID_ALWAYS_INLINE auto operator!=(const MatrixShape &lhs, - const Shape &rhs) -> bool { + const Shape &rhs) -> bool { return !(lhs == rhs); } @@ -482,8 +423,8 @@ namespace librapid { template struct IsSizeType : std::false_type {}; - template - struct IsSizeType> : std::true_type {}; + template<> + struct IsSizeType : std::true_type {}; template<> struct IsSizeType : std::true_type {}; @@ -537,19 +478,19 @@ namespace librapid { using Type = std::false_type; }; - template - struct ShapeTypeHelperImpl, Shape> { - using Type = Shape<(N > M ? N : M)>; + template<> + struct ShapeTypeHelperImpl { + using Type = Shape; }; - template - struct ShapeTypeHelperImpl, MatrixShape> { - using Type = Shape; + template<> + struct ShapeTypeHelperImpl { + using Type = Shape; }; - template - struct ShapeTypeHelperImpl> { - using Type = Shape; + template<> + struct ShapeTypeHelperImpl { + using Type = Shape; }; template<> @@ -572,11 +513,12 @@ namespace librapid { // Support FMT printing #ifdef FMT_API -template -struct fmt::formatter> { + +template<> +struct fmt::formatter { private: - using Type = librapid::Shape; - using SizeType = librapid::Shape::SizeType; + using Type = librapid::Shape; + using SizeType = librapid::Shape::SizeType; using Base = fmt::formatter; Base m_base; diff --git a/librapid/include/librapid/array/strideTools.hpp b/librapid/include/librapid/array/strideTools.hpp index 6d4af178..97684dae 100644 --- a/librapid/include/librapid/array/strideTools.hpp +++ b/librapid/include/librapid/array/strideTools.hpp @@ -3,7 +3,7 @@ namespace librapid { namespace typetraits { - LIBRAPID_DEFINE_AS_TYPE(size_t N, Stride); + LIBRAPID_DEFINE_AS_TYPE_NO_TEMPLATE(Stride); } /// A Stride is a vector of integers that describes the distance between elements in each @@ -13,44 +13,42 @@ namespace librapid { /// \tparam T The type of the Stride. Must be an integer type. /// \tparam N The number of dimensions in the Stride. /// \see Shape - template - class Stride : public Shape { + class Stride : public Shape { public: /// Default Constructor - Stride() = default; + LIBRAPID_ALWAYS_INLINE Stride() = default; /// Construct a Stride from a Shape object. This will assume that the data represented by /// the Shape object is a contiguous block of memory, and will calculate the corresponding /// strides based on this. /// \param shape - Stride(const Shape &shape); + LIBRAPID_ALWAYS_INLINE Stride(const Shape &shape); /// Copy a Stride object /// \param other The Stride object to copy. - Stride(const Stride &other) = default; + LIBRAPID_ALWAYS_INLINE Stride(const Stride &other) = default; /// Move a Stride object /// \param other The Stride object to move. - Stride(Stride &&other) noexcept = default; + LIBRAPID_ALWAYS_INLINE Stride(Stride &&other) noexcept = default; /// Assign a Stride object to this Stride object. /// \param other The Stride object to assign. - Stride &operator=(const Stride &other) = default; + LIBRAPID_ALWAYS_INLINE Stride &operator=(const Stride &other) = default; /// Move a Stride object to this Stride object. /// \param other The Stride object to move. - Stride &operator=(Stride &&other) noexcept = default; + LIBRAPID_ALWAYS_INLINE Stride &operator=(Stride &&other) noexcept = default; }; - template - Stride::Stride(const Shape &shape) : Shape(shape) { + LIBRAPID_ALWAYS_INLINE Stride::Stride(const Shape &shape) : Shape(shape) { if (this->m_dims == 0) { // Edge case for a zero-dimensional array this->m_data[0] = 1; return; } - typename Shape::SizeType tmp[N] {0}; + typename Shape::SizeType tmp[MaxDimensions] {0}; tmp[this->m_dims - 1] = 1; for (size_t i = this->m_dims - 1; i > 0; --i) tmp[i - 1] = tmp[i] * this->m_data[i]; for (size_t i = 0; i < this->m_dims; ++i) this->m_data[i] = tmp[i]; @@ -58,8 +56,12 @@ namespace librapid { } // namespace librapid // Support FMT printing -#ifdef FMT_API -LIBRAPID_SIMPLE_IO_IMPL(size_t N, librapid::Stride) -#endif // FMT_API +template<> +struct fmt::formatter : fmt::formatter { + template + auto format(const librapid::Stride &stride, FormatContext &ctx) { + return fmt::formatter::format(stride, ctx); + } +}; #endif // LIBRAPID_ARRAY_STRIDE_TOOLS_HPP \ No newline at end of file diff --git a/librapid/include/librapid/core/forward.hpp b/librapid/include/librapid/core/forward.hpp index 5790c769..9cdf0807 100644 --- a/librapid/include/librapid/core/forward.hpp +++ b/librapid/include/librapid/core/forward.hpp @@ -4,12 +4,8 @@ #ifndef LIBRAPID_DOXYGEN namespace librapid { - template class Shape; - class MatrixShape; - - template class Stride; template