I would like to translate some existing Matlab code that quite naturally uses a lot of multidimensional arrays and I wonder what are the possible options. I want the containers to have copy constructors, default constructors, if possible clear error messages at compilation, access via A[i][j] and in general not to be troublesome. Preferably, they should use the std::move operation for speed.
As far as I can see the options boils down to:
std::vector iterated. It sure works, but it seems stupid to write std::vector<std::vector<std::vector<double> > >for a 3D array. I am also concerned with the overhead in speed and memory.
The boost::multiarray and blitz::Array offer most of the functionality but fails at the copy constructor (see stackoverflow) at runtime. It is unclear to me if there are valid reasons for that.
The Eigen library seems to be very fast but it does not allow copy at all, and has no default constructor, which means that another container has to be used.
The std::array has the disadvantage that the size has to be known when the object is created, so there is no default constructors.
Is there a simpler multidimensional container satisfying all the requests but more frugal than iterated std::vector?
There is good linear algebra package called Armadillo
http://arma.sourceforge.net/
used it with R, happy user
I am not sure this can answer all your needs but I myself had to handle multi-dimensional arrays for creating meshes/grid and wanted to create my own class for that.
My class let's call it MultiArray uses a a one-dimension vector as container.
For instance, writing MultiArray<4, float, 10, 15, 10, 18> A() would create a multi array A[10][15][10][18] in a vector of size 10*15*10*18.
I can access to elements by single index A(i) or by coordinates A[i][j][k][l] by calling A({i,j,k,l}). For performance purpose I have precomputed in the constructor the product of the dimensions in order to compute fastly coordinates->index or index->coordinates.
The code is generic for N dimensions. I can detail some parts if you want.
You have missed another option:
std::valarray
Depending on what your requirements are it could be useful.
http://www.cplusplus.com/reference/valarray/
Related
I'm a beginner in C++, and as a learning exercise I'm trying to write a library for doing matrix math (matrix multiplication, invertion and the like).
The first thing I want to do is to define a class "Matrix", which members are "rows"- the number of rows in the matrix, "cols"-the number of columns in the matrix, and "_matrix"-an array containing the elements of the matrix.
The problem is I don't have any idea how to build the constructor.
Can I write something like "Matrix(m,n,array)"? how do I make sure the array actually contains m*n elements?
I would love some guidence on how to procceed (well.. how to begin if I'm being honest :) )
thanks!
Another answer provides a typical solution one would expect a Matrix class constructor to have (i.e. Matrix(unsigned, unsigned)).
If you are doing it as an exercise and you are serious about learnig C++, I would also suggest implementing the following contructor:
Matrix(std::initializer_list<std::initializer_list<T>> init_list);
Therefore you could build your object like that:
Matrix m({{1,2,3},{4,5,6},{7,8,9}});
Note that you could take size of the constructed matrix straight from the std::initializer_lists provided and you could easily build templated matrices that way.
If I were using a matrix, I would expect a constructor like:
Matrix(unsigned int maximum_rows, unsigned int maximum_columns);
I don't care if the matrix is implemented by array, list or other data structure. I told it the size, so construct one.
Edit 1:
You want to hide the implementation of the Matrix from the user. The implementation of the constructor depends on your implementation.
The implementation may be different for a lower triangular matrix than a generic one. You may decide on a vector of vectors, a 2 dimensional array, a one dimensional array or a linked list.
I as the user don't really care how it's implemented. All I care is that the expected Matrix functionalities are implemented correctly, and in some cases, efficiently. So I may expect an overloaded operator + or an add method or both.
Again, search the internet to see examples of how other people have implemented a matrix.
Edit 2:
There may be cases where you want to have one class for the functionality and another class for the implementation. In that case, you may want to pass the implementation to the Matrix's constructor. (I would suggest using a reference to a base class the describes the implementation interface). But that may be overkill for what you need.
I am trying to apply a minimax type algorithm to a Reversi/Othello type game - the problem i'm finding is that each 1/2 ply will needs its' own "fake" game-board to test on.
Thus it appears, as arrays cannot be passed as parameters, that I either need a function with 64 parameters and an array for each 1/2 ply, or I need to hand code copies of the functions and arrays for each ply (i.e. checkMovePly1, checkMovePly2, etc.), or create the arrays locally (at which point the AI taking a move will result in the generation and creation of 64^(2*ply) arrays every turn, which seems like it could run somewhat slowly).
If I can solve the array problem, this seems like it should work for a few ply, as it will only be a time complexity of O(64^(2*ply)), though depending on method that may be 64^(2*ply) creations and destructions of arrays.
Any idea how to get around the multiple array issue, is this a reasonable approach?
C++ provides various containers that should be preferred to arrays. In this case, I would suggest an std::array. If you don't have std::array, an std::vector will also work.
void foobar(std::array<int, 64> board);
This function will copy the array passed in by value.
First arrays can be passed as parameters, but the function called will be operating directly on the original array, not its own copy (beware).
void foo(int[8][8] board);
Second, standard (or custom if need be) container classes are safer to use and easier to copy when needed. Native arrays don't copy easily without slightly hackish tricks, at which point using container classes should render your code easier to read anyway.
Third, this problem looks like a classic subject for a recursive algorithm, which could allow all work to be done on the same array (or container class) instance, thus keeping your resource requirements O(1): fixed gameboad size and known maximum resursion depth.
I have inherited some code which makes extensive use of double pointers to represent 2D arrays. I have little experience using Eigen but it seems easier to use and more robust than double pointers.
Does anyone have insight as to which would be preferable?
Both Eigen and Boost.uBLAS define expression hierarchies and abstract matrix data structures that can use any storage class that satisfies certain constraints. These libraries are written so that linear algebra operations can be clearly expressed and efficiently evaluated at a very high level. Both libraries use expression templates heavily, and are capable of doing pretty complicated compile-time expression transformations. In particular, Eigen can also use SIMD instructions, and is very competitive on several benchmarks.
For dense matrices, a common approach is to use a single pointer and keep track of additional row, column, and stride variables (the reason that you may need the third is because you may have allocated more memory than you really need to store x * y * sizeof(value_type) elements because of alignment). However, you have no mechanisms in place to check for out-of-range accessing, and nothing in the code to help you debug. You would only want to use this sort of approach if, for example, you need to implement some linear algebra operations for educational purposes. (Even if this is the case, I advise that you first consider which algorithms you would like to implement, and then take a look at std::unique_ptr, std::move, std::allocator, and operator overloading).
Remember Eigen has a Map capability that allows you to make an Eigen matrix to a contiguous array of data. If it's difficult to completely change the code you have inherited, mapping things to an Eigen matrix at least might make interoperating with raw pointers easier.
Yes definitely, for modern C++ you should be using a container rather than raw pointers.
Eigen
When using Eigen, take note that its fixed size classes (like Vector3d) use optimizations that require them to be properly aligned. This requires special care if you include those fixed size Eigen values as members in structures or classes. You also can't pass them by value, only by reference.
If you don't care about such optimizations, it's trivial enough to disable it: simply add
#define EIGEN_DONT_ALIGN
as the first line of all source files (.h, .cpp, ...) that use Eigen.
The other two options are:
Boost Matrix
#include <boost/numeric/ublas/matrix.hpp>
boost::numeric::ublas::matrix<double> m (3, 3);
std::vector
#include <vector>
std::vector<std::vector<double> > m(3, std::vector<double>(3));
i want to store some kind of distance-matrix (2D), where each entry has some alternatives (different coordinates). So i want to access the distance for example x=1 with x_alt=3 and y=3 with y_alt=1, looking in a 4-dim multi-array with array[1][3][3][1].
The important thing to notice is the following: the 2 most inner arrays/vectors don't have the same size for different values of the outer ones.
After a first init step, where i calculate the values, no more modifying is needed!
This should be easily possible with the use of stl-vectors:
vector<vector<vector<vector<double> > > >`extended_distance_matrix;
where i can dynamically iterate over the outer 2 dimensions and fill only as much alternatives to the inner 2 dimensions as i need (e.g. with push_back()).
Questions:
Is this kind of data-structure definition possible with Boost.MultiArray? How?
Is it a good idea to use Boost.MultiArray instead of the nested vectors? Performance (especially lookups! (Memory-layout))? Easy of use?
Thanks for any input!
sascha
PS: The boost documentation didn't help me. Maybe one can use multi_array_ref to get already sized arrays into the whole 4D-structure?
Edit:
At the moment i'm thinking of another approach: flattening the alternatives -> one bigger matrix with all the distances between the alternatives. Then i only need to calc the number of alternatives per node, build up the prefix sum (which is describing the matrix position/shift) and can then access the information in a 2-step-way.
But my questions are still open.
it sounds like you need:
multi_array<ublas::matrix<type>,2>
Boost.MultiArray deals with contiguous memory (arranged logically in many dimensions) so it is difficult to add elements in the inner dimensions. MultiArrays can be dynamically resized, e.g. to add elements in any dimension, but this is a costly operation that almost certainly need (internally) reallocation and copying.
Because of that requirement MultiArray is not the best option. But from what you say it looks like a combination of the two would be appropriate to you.
boost::multi_array<std::vector<std::vector<type>>, 2> data
The very nice thing is that the indexing interface doesn't change with respect to boost::multi_array<type, 4>. For example data[1][2][3][4] still makes sense.
I don't know from your post how you handle the inner dimension but it could even make sense to use this:
boost::multi_array<boost::multi_array<type>, 2>, 2> data
In any case, unless you really need to do linear algebra I would stay away from boost::ublas::array, or at most use it for the internal array if type is numeric. boost::multi_array<boost::ublas::array<type>, 2> data which is mentioned in the other answer.
I am trying to use the scythe statistical library (found here: http://scythe.wustl.edu/). I can initialize a matrix just fine with:
Matrix<double> A(2, 2, false);
But I would like to have a dynamic array of such matrices. Does anyone have any hints? Do I use vector? If so how?
Many thanks!
A std::vector would be an excellent choice, especially if you don't know until runtime how many matrices you need. For example,
std::vector<Matrix<double> > vectorOfMatrices;
vectorOfMatrices.push_back(Matrix<double>(2, 2, false));
// etc.
There are two classes suitable for your task:
a) std::vector - stores the objects in an array, can be accessed via index as well as iterator. Good for random access operations.
b) std::list - stores objects as a linked-list, accessed via iterators. Good for sequential-only access and frequent modifications.
So, if you just want an array of fixed or only rarely-changing size, go for std::vector. However, if you know these will change rather often, and you typically iterate over the whole thing, std::list is a better alternative.