Re: [multi] Formal Review Begins
Hi everyone, here's my review of Boost.Multi: = What is your evaluation of the design? *Strong, with minor concerns.* Boost.Multi's core design insight — treating a D-dimensional array as a container of (D-1)-dimensional sub-arrays, recursively — is elegant and is what enables full standard library algorithm compatibility. This is the library's primary differentiator and it works well. The type hierarchy is well-motivated. The slicing API is expressive (A(_, 1) for columns, A({0,2}, {0,2}) for sub-blocks, A.strided(2), A.transposed()). The technical rationale includes Godbolt proofs that A[i][j][k] generates identical machine code to manual pointer arithmetic at -O2. *Concerns:* - ~A operator for transposition: A bit surprising — most C++ developers expect bitwise NOT; .transposed() is also available and should be preferred. - nelems() alongside num_elements() is redundant. = What is your evaluation of the implementation? *Solid engineering with areas that need cleanup.* The layout system (detail/layout.hpp) is stride-based and recursive. Extensions use a custom detail::tuple rather than std::tuple, presumably for GPU compatibility. Memory management is correctly implemented. The force_element_trivial<T> trait for opt-in trivial treatment of std::complex types is a practical and well-motivated choice for GPU/performance. Allocator and fancy pointer support is thorough throughout, which is genuinely rare in multidimensional array libraries. *Concerns:* - Lint suppression density: The source code has about 3000 NOLINT annotations (about 200 in array_ref.hpp). Many are justified, but this volume suggests a better approach is needed. - Iterator template complexity: array_iterator carries six template parameters, making compiler error messages potentially very difficult to read. There are no static_assert or concept checks to produce friendly diagnostics. - UB in strided/transposed end() iterators: The documentation acknowledges that end() iterators for strided or transposed views may point to invalid memory (undefined behavior). For a Boost library, this must be resolved or have a fully documented, safe workaround. - dynamic_array move constructor is noexcept(false): This is deliberate but should be prominently documented. - extensions_t<D> has manually unrolled constructors for D=1 through D=6 (~100 lines of near-duplicate code in layout.hpp), which is a maintenance burden. = What is your evaluation of the documentation? *Good tutorial; the reference sections need work.* *Strengths*: - The tutorial is genuinely well-written, building from the problem (manual index computation) up to sorting rows and columns with standard library algorithms. - Godbolt links throughout allow instant verification of claims. - The technical rationale section addresses key design questions honestly (why A[i][j][k], why static dimensionality, why C++17). - Comparison tables vs. mdspan, mdarray, xtensor, Boost.MultiArray are clear and fair. - The reference page has a useful cheat-sheet table. *Weaknesses:* - No automated API reference extraction: The reference is manually written, which could make it drift from the implementation. - Thread safety is undocumented: In particular, dynamic_array is described as useful for multithreaded contexts, but no formal guarantees are stated. - No migration/interop guide from Boost.MultiArray or std::mdspan. = What is your evaluation of the potential usefulness of the library? *High.* The library fills a genuine gap in the C++ ecosystem. No other library that I know of provides this combination of: - Full standard library algorithm compatibility: You can std::sort() rows, std::transform() columns, std::copy() sub-blocks. This is impossible or extremely awkward with std::mdspan, Eigen, or Boost.MultiArray. - An owning n-dimensional container: std::mdspan is non-owning only; std::mdarray is not yet standardized. - GPU memory support (CUDA + HIP). - Fancy pointer support (e.g. boost::interprocess::offset_ptr for persistent/shared memory). Target users include scientific computing, image processing, numerical simulation, and ML/AI. The examples include a heat equation solver, LU factorization, Gauss-Jordan solve, Boost.Interprocess mapped files, MPI usage, and Boost.GIL integration — all realistic use cases. I haven't used it in production, but its feature set directly addresses pain points I've run into in scientific C++ projects. = Did you try to use the library? With which compiler(s)? Did you have any problems? *I didn't compile the library, but I reviewed the source code, test suite, examples, benchmarks and CI configuration.* = How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? *In-depth study.* I cloned the repository and read the core headers, the full documentation source, the online rendered docs, the CMakeLists.txt, the test files, the examples, and benchmarks. I examined class hierarchy, iterator design, const-correctness, allocator support, and portability workarounds. = Are you knowledgeable about the problem domain? *Moderately knowledgeable.* I'm familiar with the math concepts and have some experience with scientific computing and numerical methods. = Verdict: CONDITIONAL ACCEPT Rationale for acceptance: - Fills a genuine, well-articulated gap (see above). - The API is well-designed with clear value/reference semantic distinctions. - Broad compiler support. - Good documentation with a strong tutorial and honest technical rationale. Conditions for acceptance: - Resolve the UB in strided/transposed end() iterators. - Document thread safety guarantees. - Reduce Lint suppression density. Suggestions (not conditions): - Add a migration/interop guide for Boost.MultiArray and std::mdspan users. - Consider removing operator~() in favor of transposed() only. - Decide between nelems() and num_elements(). - Add automated API reference generation (MrDocs?). - Reduce extensions_t constructor unrolling with variadic templates where compiler support allows. -- Gennaro Prota <https://prota.dev>
= Verdict: CONDITIONAL ACCEPT
Conditions for acceptance:
- Resolve the UB in strided/transposed end() iterators.
- Document thread safety guarantees.
- Reduce Lint suppression density.
Thank you Gennaro for your review and comments. Your conditions for acceptance are noted. Matt
Alfredo, Good job on updating the documentation and the new introduction is certainly more compelling! - Peter On Wed, Mar 11, 2026 at 6:22 AM Matt Borland via Boost < boost@lists.boost.org> wrote:
= Verdict: CONDITIONAL ACCEPT
Conditions for acceptance:
- Resolve the UB in strided/transposed end() iterators.
- Document thread safety guarantees.
- Reduce Lint suppression density.
Thank you Gennaro for your review and comments. Your conditions for acceptance are noted.
Matt_______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/SJYH4ZHR...
participants (3)
-
Gennaro Prota -
Matt Borland -
Peter Turcan