I am wondering whether there is a cpp equivalent to accessing array locations in fortran via indexes stored in other arrays
I am novice to cpp but experienced in oop fortran. I am thinking about leaving fortran behind for the much better support of oop in recent cpp (oop in fortran is probably at the stage of year 2000 cpp).
However, my applications are heavily geared towards linear algebra. Contrarily to cpp, fortran has a lot of compiler built in support for this. But I would happily load libraries in cpp for gaining elaborate oop support.
But if the below construct is missing in cpp that would be really annoying.
As I haven't found anything related yet I would appreciate if some experienced cpp programmer could comment.
An assignment to a 1D array location in fortan using a cascade of vector subscripts can be a complex as this:
iv1(ivcr(val(i,j)))=1
where iv1 is a 1D integer vector, ivcr is a 1D integer vector, val is a 2D integer array and i and j are scalars. I am wondering whether I could write this in a similar compact form in cpp.
A only slightly more complex example would be:
iv1(ivcr(val(i:j,j)))=1
which will fill a section in iv1 with "1".
How would cpp deal with that problem in the shortest possible way.
Given (suitably initialized):
std::vector<int> iv1, ivcr;
std::vector<std::vector<int>> val;
Then your iv1(ivcr(val(i,j)))=1 is simply
iv1[ivcr[val[i][j]]] = 1;
As for iv1(ivcr(val(i:j,j)))=1, or just val(i:j, j), there is no inbuilt way to slice into arrays like this. To be able to assign 1 to these kinds of nested datastructure accesses, you would need datastructures that provide expression templates. The Eigen library has just that and is one of the major linear algebra libraries for C++. Check out their documentation for indexing and slicing here:
https://eigen.tuxfamily.org/dox-devel/group__TutorialSlicingIndexing.html
Related
I am using Eigen to do some linear algebra computations in my code. However, all of mathematical formulas are based on the fact that indexing starts from 1. So, each time that I want to implement them in the code, I have to check if my indexing in the code is consistent with them or not. I was wondering that if it is possible to tell Eigen to start the indexing from 1 instead of 0.
Indexing operations in Eigen allow, in addition to indexing with integers, indexing with symbolic indices. You should be able implement your own custom symbolic index, derived from Eigen::symbolic::BaseExpr, that could be used as a 1-based index API, where its eval_impl method simply subtracts 1 from its arg. E.g.:
template<typename Arg0>
class MyIndexExpr : public BaseExpr<MyIndexExpr<Arg0> >
{
public:
MyIndexExpr(const Arg0& arg0) : m_arg0(arg0) {}
template<typename T>
Index eval_impl(const T& values) const { return m_arg0.eval_impl(values) - 1; }
protected:
Arg0 m_arg0;
};
To use this in product code, however, would most likely be a very bad idea, likely to lead to confusion, possible bugs as well as an extra non-motivated run-time overhead for any indexing. As you are coding in C++, you might want to stick to its zero-based indexing practice. Maybe you could consider symbolic indexing for when writing tests for your formulas, but using integer zero-based indexing for your product code.
The answer is "not really".
Of course, as #πάνταῥεῖ suggested, you could write a wrapper or inherit from Eigen types and overwrite the indexing operators accordingly. Alternatively, you could implement a custom Index type which, when converted to Eigen::Index, will subtract 1.
But both approaches are error-prone and will likely rather increase confusion, especially if you miss some relevant parts. Also it will extremely confuse any C++ programmer looking at your code, as 0-based indexing is the most natural way in C/C++ (and many languages whose syntax is derived from them, like Java, C#, ...)
Finally, (as also suggested by #dfri) if you code in C++ get used to 0-based indexing, this will save you a lot of trouble in the long run.
I remember c++ primer said that 2d vector is very inefficient and should be avoided.
but 2d array seems to be rather inconvenient in terms of both creating and deleting.
is there any other way to do it? or 2d vector still competable against 2d array?
I doubt that it matters. There are other factors that will matter more.
I would question the starting premise:
2d vector is inefficient
Sometimes we trade off pure speed for better abstraction. I'll bet the std::string class can be considered inefficient by some measures when compared to raw byte or character array, but I'd still use it.
You'll have a better case if you stop worrying about broad statements and focus on your use case.
The most common application of 2D arrays I know of is for vectors, matricies, and linear algebra. There are other factors for that problem that will be far more important than the choice of underlying data structure.
Since C++ is an object-oriented language, you can solve this easily by starting with an interface and creating implementations that use vector and array. Test them against a meaningful data set and measure.
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 7 years ago.
So I have started learning about coding in C++ and I'm just starting on arrays, but I just don't understand the concept of multidimensional arrays, does it save memory and make the program faster or something else? And also under what circumstance should I use them?
Thanks
Answer not specifically C or C++.
Imagine a chess board, it has some squares. Each square can have a playing piece on it. You could store the state of each square in an array.
If you number the squares 0, 1, 2, 3 … 63 then you can put them in a one dimensional array. To go left add 1, to go right subtract 1, to go down add width (8), to go up subtract width (8) (With some bounds checking).
Alternatively you can use a 2 dimensional array 0…7, 0…7 now you do not add 8 you just add one to y dimension. Note the computer converts it all to one dimensional in the end, but C and C++ arrays have no bounds checking, and you have to keep telling it the width. There are some good classes in the library to make things easier.
Also you can have 3, 4, 5 or any other number of dimensions.
you'll get it just in practice! there are lot's of situationts where you use bidimensional arrays, just because it'll be not enough to use a simple array, for example simple backtracking problems such as labyrinths, sudoku, the lee's algorithm. Or another example: you have a table of data of students from your class, the columns is data of every student, but the raws can be: the first raw the average grade, the second raw his height, the third raw his number, and so on
In practice, don't use multidimensional arrays in C or C++. Just use a single dimension array, perhaps by making a class containing it with some getter and setter methods.
However, there are many occasions where you would use a container of containers, e.g. types like std::set<std::vector<long>> or occasionally std::vector<std::array<double,3>> etc...
The practical exception for using raw 2D arrays might be for matrixes whose dimensions are a compile-time constant. So a 3D linear transform (from R3 to itself) might be represented by a double m[3][3]; ; then a good optimizing compiler might even be able to vectorize the code.
But for a matrix whose both dimensions are only known at runtime, making it a bidimensional array is generally a mistake or an overkill (and this is why the STL does not provide you with a std::matrix template). You could use std::vector<std::vector<double>> but that requires allocating each row of your matrix.
Of course, you'll find a lot of existing linear algebra libraries like LAPACK, BLAS, etc... Use them for 2D or 3D computations. Some of them might even use hardware acceleration (e.g. using OpenCL to run on a GPGPU).
More generally, very often you should use and combine existing C++ standard containers (or even define your own templates providing your containers, perhaps by combining existing ones).
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 have a quick question for you all. I'm trying to convert over some ActionScript code to C++ and am having a difficult time with this one line:
private var edges:Vector.<Array>
What is this exactly? Is this essentially a multidimensional vector then? Or is this simply declaring the vector as a container? I understand from researching that vectors, like C++ vectors, have to be declared with a type. However, in C++ I can't just put down Array, I have to use another vector (probably) so it looks like:
vector<vector<T> example;
or possibly even
vector<int[]> example;
I don't expect you guys to know the C++ equivalent because I'm primarily posting this with AS tags, but if you could confirm my understand of the AS half, that would be great. I did some googling but didn't find any cases where someone used Array as it's type.
From Mike Chambers (adobe evangelist) :
"Essentially, the Vector class is a typed Array, and in addition to ensuring your collection is type safe, can also provide (sometimes significant) performance improvements over using an Array."
http://www.mikechambers.com/blog/2008/08/19/using-vectors-in-actionscript-3-and-flash-player-10/
Essentially the vector in C++ is based on the same principles. As far as porting a vector of Arrays in AS3 to C++, well that's not a conversion that is clear cut in principle, as you could have a collection (array) of various types in C++, such as a char array. However, it appears you've got the idea, as you've pretty much posted examples of both avenues in your question.
I would post some code but I think you've got it exactly. Weather you use a vector within a vector or you declare a specifically typed collection I think comes down to a matter of what works best for you specific project.
Also you might be interested in:
http://www.mikechambers.com/blog/2008/09/24/actioscript-3-vector-array-performance-comparison/