Firstly, I appreciate the feedback.
Your first bullet is a good point. I'm somewhat inclined to agree; however, often times (math) vectors and matrices can be small. There is non-trivial memory savings in being able to convey size via type rather than via containing a size attribute. I imagine that could significantly bloat the memory footprint of a number of applications and thus be undesirable. I don't think such use cases are all that uncommon.
- I could see separating the fixed size tensor into a separate proposal to warrant further discussion.
- I could also see it as motivation for embracing the slightly more cumbersome extents type rather than using a variadic size type parameter. If the extents type
is entirely static, then it could be optimized out with [[no_unique_address]]. I am inclined to explore this.
- Along the same vain, I think I could and should collapse the matrix and vector classes into the tensor classes. I had thought I would have more special accessors and mutators for one and two dimensional tensors, but really only ended up with a few row / column functions for matrix and a subvector overload for vector (which arguably isn't needed). As such, vector and matrix could just be aliases for one and two dimensional tensors.
I'm trying to appreciate your other bullets and final point. Some of the wording I got a little confused by. Are you in favor of ...
- A) a matrix container which has an allocator and a multidimensional index operator (and does not necessarily conform to the existing named requirements for an STL container)?
- B) a matrix container which has an allocator and conforms to existing STL Container requirements?
- C) a matrix container adapter which adapts existing containers with a multi-dimensional accessor (which is pretty much mdarray)?
In either case, do you truly mean matrix in the two dimensional context or really referring to a tensor (which would be the more generic N dimensional case)?
- If A) I think that starts to look a lot like the dr_tensor.
- I think that could involve defining a set of named requirements for an STL MD Container and MD SequenceContainer analagous to the existing Container and SequenceContainer. I'm a bit hesitant to dive into that. I think the group behind mdspan, mdsubspan, and mdarray is considering what an MD iterator could look like (or was at one point) and am interested in the direction they would take. Furthermore, one would need to consider what operations like insert and erase could look like.
- If B) it sound like you're suggesting somehow a container which acts like a one dimensional container and thus can fit into an mdspan or mdarray, but actually somehow knows it is a multidimensional container and thus structure its memory appropriately for efficient resizing. That seems awkward and difficult to make work.
- If C) I'm not sure I want to step on what the mdarray proposal is trying to do, but am interested in how or if they would introduce resizing into their proposal.
I'm also trying to understand what you mean by the best features of std::valarry? If you're pointing out we should be optimize successive operations on a matrix, I agree and want to tackle that via expression types. I just didn't want to tackle that right out of gate so to speak. Add / subtract isn't hard, but multiplication and in general thinking through how to make expression types expandable to additional operations (like inverse) will take some work. My hope is with maybe a little work, construction from expression types could fit into the construct from lambda expression and thus wouldn't require modifying the existing interface.
Just some points on the extendibility...
- One goal was to not need to create new matrix classes when adding new matrix types like triangular, banded, symmetric, skew symmetric, etc. - just add new layout types. I think some work still needed to make it extendible in that way. Though I think something like block matrices would be a bridge too far (and getting too far ahead of myself). Also, given the current mdspan interface, I think one would need to have a custom accessor and layout class for something like a triangular matrix (where the layout would return an invalid index as a cue to the accessor when the client wanted a value from the zero part of the triangular matrix).
- The intent was to scope the requirements on the structs defining operations on tensor such that new types like a triangular matrix would conform to stricter requirements and thus appropriate overloads could be added without modifying the existing code.
--Finally I managed to read your code, so I can give you the full feedback. I have an overall idea of how your proposal can be changed, but I want to respond to your comments individually first.- it is true that several functions that one might expect to be in the interface of a math object only conditionally make sense if the underlying container supports dynamic memory allocation, but this can be applied to any object, such as an STL container. There are circumstances that lead a user to use a static std::list or std::vector, but this does not justify the creation of two identical containers that differ only in static or dynamic memory management. If this were done, the STL library would be much bloated, making the existence of the allocators partly useless: since the allocator is used to abstract the memory management (or rather, it is a handle to the memory), you can implement an allocator that is essentially a handle to a static array. In this way, although it is not very elegant, it is possible to create a custom fixed_vector or a fixed_list by passing, respectively, a static allocator to a std::vector or a std::list. It is up to the user to avoid calling member functions that can lead to memory resizing, such as reserve(), otherwise a std::bad_alloc is thrown, as if a simple dynamic allocation failed.- if you want to adopt a container adapter interface, as already present in all container adapters, you create two overloads for the constructors, one without an allocator and the other with an allocator (if the std::uses_allocator type trait is true).- although already-existing containers do not support efficient multidimensional resizing, it is still possible for the user to implement a custom container. It depends on what the user thinks.But your comment "existing containers don't support efficient multidimensional resizing" is precisely the key point: over the guarantee of a complete interface for performing linear algebra operations, does the matrix container offer advantages in terms of flexibility and performance?In my opinion, creating a matrix container, whose implementation takes the best features between std::valarray and mdarray would be the best. Without introducing new containers or container adapters, the matrix container could fill some of std::valarray's shortcomings by providing an interface that allows the user to perform easily simple and complex linear algebra operations on N-dimensional arrays.If that is okay, you can present a draft of the matrix container, especially highlighting the benefits of linear algebra operations and memory management.
Std-Proposals mailing list