Access to 1D stored array representing 2D matrix - c++

I'm creating a 2D square matrix in Excel VBA
Dim Matrix(0 To Nrows, 0 To Ncols) as double
and then I pass it as argument ByRef to a function library,
My_foo(Matrix(0,0))
which calls a C++ code. In C++ code I want to access the matrix to get values and make other operations. On this purpose, I read these values as 1D array, so I created an index [R*Ncols + C], where R and C are the element position in 2D representation
void _stdcall My_foo(double* M, long Nrows, long Ncols){
double Value;
R = 10;
C = 0;
Value = M[R*Ncols + C];
}
At this point I expect to find the element having position (10,0), but I find the element (0,10). It seems my matrix is stored with an inverted column/rows order.
It would be enough to set an index like [C*Nrows + R], and access it by column. I tried this and it works, but it contradicts many blogs and posts...
Why? Is it normal?

While C/C++ uses a row-major format to represent multi-dimensional arrays, for other languages different choices were made, so it is not very surprising that Excel VBA uses a column-major format like it is also documented in this forum question.

Related

How does the dimention argument of `sgemm` work?

I'm trying to understand the documentation for sgemm as I am transitioning code from using this library to a different library.
The function prototype is
sgemm ( character TRANSA,
character TRANSB,
integer M,
integer N,
integer K,
real ALPHA,
real, dimension(lda,*) A,
integer LDA,
real, dimension(ldb,*) B,
integer LDB,
real BETA,
real, dimension(ldc,*) C,
integer LDC
)
I am having trouble understanding the role or LDA and LDB. The documentation says
LDA is INTEGER
On entry, LDA specifies the first dimension of A as declared
in the calling (sub) program. When TRANSA = 'N' or 'n' then
LDA must be at least max( 1, m ), otherwise LDA must be at
least max( 1, k ).
What does it mean that it specifies the first dimension of A? Is this like switching between row and column major? Or is this slicing the tensor?
LD stands for leading dimension. BLAS is originally a library of Fortran 77 subroutines and in Fortran matrices are stored column-wise: A(i,j) is immediately followed in memory by A(i+1,j), which is opposite of C/C++ where a[i][j] is followed by a[i][j+1]. In order to access element A(i,j) of a matrix that has dimensions A(LDA,*) (which reads as LDA rows and an unspecified number of columns), you need to look (j-1)*LDA + (i-1) elements from the beginning of the matrix (Fortran arrays are 1-indexed by default), therefore you need to know the value of LDA. You don't need to know the actual number of columns, therefore the * in the dummy argument.
It is the same in C/C++. If you have a 2D array declared as a[something][LDA], then element a[i][j] is located i*LDA + j positions after the start of the array, and you only need to know LDA - the value of something does not affect the calculation of the address of a[i][j].
Although GEMM operates on an M x K matrix A, the actual data may be embedded in a bigger matrix that is LDA x L, where LDA >= M and L >= K, therefore the LDA is specified explicitly. The same applies to LDB and LDC.
BLAS was developed many years ago when computer programming was quite different than what it is today. Memory management, in particular, was not as flexible as it is nowadays. Allocating one big matrix and then using and reusing portions of it to store smaller matrices was the norm. Also, GEMM is extensively used in, e.g., iterative algorithms that work on various sub-matrices and it is faster to keep the data in the original matrix and just specify the sub-matrix location and dimension, so you need to provide both dimensions.
Starting with Fortran 90, the language has array slicing and automatic array descriptors that allow one to discover both the dimensions of a slice and those of the bigger matrix, so if GEMM was written in Fortran 90 or later, it wouldn't be that verbose in respect to its arguments. But even if that was the case, C doesn't have array descriptors, so you'll still have to provide all those arguments in order to make GEMM callable from C. In C++, one can hide the descriptor inside a matrix class, and many math libraries actually do so (for example, Scythe).

Flatten and restore a complex vector into a double vector and back

I have a vector containing complex values (either defined as std::vector<std::complex<double>> or arma::cx_vec) and would like to convert them into vectors containing double-values of twice the size. Afterwards I would like to convert them back again. Currently I use two loops (here from going from double-vectors to complex vectors and back):
//get x and dx as vectors containing real values, with a size of 2 * dim
arma::cx_colvec local_x(dim), local_dx(dim);
for(size_t i = 0; i < x.size(); i += 2) {
local_x(i / 2) = std::complex<double>(x(i), x(i + 1));
}
//Do something with local_x and local_dx
for(size_t i = 0; i < 2 * dim; i += 2) {
dx(i) = local_dx(i / 2).real();
dx(i + 1) = local_dx(i / 2).imag();
}
//Send dx back
I can imagine that that might be rather slow. Therefore, are there other possibilities of reshaping those vectors from complex to double and back? Ideally involving iterators (such that I can use methods such as transform()) instead of a loop over a size.
Background to this question is: I have complex input data which has to be put into a function A which I can not modify, but which calls a user-supplied function again (called U). This function does not support complex data types, only real types. Therefore, my intention was to flatten the vector before putting it into A, unflatten it in U, do the calculations on it, reflatten it and send it back again.
std::complex<double> is explicitly called out as something that can be treated as a double[2]
Array-oriented access
For any object z of type complex<T>, reinterpret_cast<T(&)[2]>(z)[0]
is the real part of z and reinterpret_cast<T(&)[2]>(z)[1] is the
imaginary part of z.
For any pointer to an element of an array of complex<T> named p and
any valid array index i, reinterpret_cast<T*>(p)[2*i] is the real part
of the complex number p[i], and reinterpret_cast<T*>(p)[2*i + 1] is
the imaginary part of the complex number p[i]
The intent of this requirement is to preserve binary compatibility
between the C++ library complex number types and the C language
complex number types (and arrays thereof), which have an identical
object representation requirement.
So you can use std::vector::data() to obtain a complex<double> *, and reinterpret it as a double * with twice as many elements.

Reordering of matrix in c++

I have a matrix in C++, A(n,n) and a vector P(n) which looks something like this:
P = [ 3 6 1 13 12 16 ... ]
it contains numbers 1:n but not in an ascending order but scrambled.
My aim is to change the rows and columns of matrix A to the same order. For example since P[0] = 3 I want the 3rd row and 3rd column to move to the 1st row and column in matrix A.
But because the matrix could be potentially really large, I can't use another matrix of size same as A because that would be wasteful.
In matlab this can be done simply by using the command:
A(P,P);
Any ideas on how to do the same thing in c++?
I will suggest using a level of indirection, to locate each matrix in a cell.
Let's say your matrix object is called M. Instead of using
M[R][C]
to refer to the cell in row R, column C (assuming row-major matrix ordering), you will have an associated pair of vectors, let's call them y and x, so the value of the cell in row R column C is:
M[y[R]][x[C]]
Initially, both y and x vectors map each "logical" row or column to the corresponding physical row and column, that is both y and x contain [0..max_row] and [0..max_col].
Then, to effect the swapping in your question, you simply copy your P vector to the y and x vectors.
You should implement your matrix not directly, as a two-dimensional std::vector, but as a standalone class:
class Matrix {
public:
// ...
auto operator()(size_t R, size_t C) const;
auto &operator()(size_t R, size_t C);
// ...
};
and implement the indirect mapping of rows and columns as part of the class implementation.
Easiest way is probably to just brute-force it. The best idea is probably to do it row by row. You'll need a helper array of length N which keeps track of the original row index, and one temporary row. Then, starting at row R=0, check if row R is in the right position. If not, copy it to the temporary row, copy the right row to row R (permuting it on the go), and copy the temporary row to the spot that was just freed. If a row happens to be in the right spot, copy it to the temporary row, and permute it when copying back.

Passing a pointer to an array of arrays to a function

I have a main function which sets up the following variables:
double matrix[numVectors][size] = {
{0.183963, 0.933146, 0.476773, 0.086125, 0.566566, 0.728107, 0.837345, 0.885175, 0.600559, 0.142238},
{0.086523, 0.025236, 0.252289, 0.089437, 0.382081, 0.420934, 0.038498, 0.626125, 0.468158, 0.247754},
{0.969345, 0.127753, 0.736213, 0.264992, 0.518971, 0.216767, 0.390992, 0.242241, 0.516135, 0.990155}
};
double result1[size], result2[size];
double *ptr_matrix = &matrix[0];
double *ptr_result1 = &result1[0];
double *ptr_result2 = &result2[0];
What the above is trying to do is:
Create an array with three rows of 10 doubles
Create two empty arrays of 10 doubles
Create a pointer to the matrix
Create pointers to the two empty arrays
Then, I'm trying to pass all three pointers to another function. This other function will iterate over the matrix rows (only the rows, it doesn't visit the whole matrix space), perform a computation using the row (as an array). The end result is the two empty arrays declared at the beginning end up each becoming one row from the matrix.
Here is the prototype of the second function:
void smallestSum(double (*mat)[size], int num, double *first, double *second)
This function goes through each combination of the matrix rows (0/1, 0/2, 1/2) and checks the sums of their values. The two arrays producing the smallest sum eventually become result1 and result2 from above.
Seeing as this is the first time I'm really delving into pointer/array/matrix territory, I have a few questions:
Am I correctly "getting" a pointer to the matrix? Or do I need to get a pointer to the first value of the matrix instead?
In smallestSum(), can I iterate over the array as I would normally (using for (int i = 0; i < num; i++)?
You need to change the definition of ptr_matrix, as it's not a pointer to a single double, but to the whole row:
double (*ptr_matrix)[size] = &matrix[0];
Then, you can call the function as follows:
smallestSum(ptr_matrix, numVectors, ptr_result1, ptr_result_2);
Inside smallestSum, you can iterate both over rows and over columns.
Note that size must be known at compilation time.
If the function doesn't modify the matrix, consider adding const to the type of its first argument.
The answer abacabadabacaba gave is mostly correct except that size does not need to be known at compile time. If you include size as a parameter to the function you can use it as part of the type for other parameters to that function:
void smallestSum(int size, double (*mat)[size], int num, double *first, double *second)

3d -> 1D array indexing

in C++, what is the indexing value for a W * H * D sized 3D array?
for a particular i, j, k is this the correct indexing:
i*W*H+j*W+k
What you have written is equivalent to the pointer arithmetic that this would do:
T x[D][H][W];
x[i][j][k]; // Pointer arithmetic done here
Obviously, depending on how you order D, H and W (or i, j, k), the calculation will differ.
There is no one "correct" order, but the version you've given should work. The order in which you apply the indices will determine whether you do row-major or column-major indexing. If you're porting Fortran code (for example) it can make sense to reverse the "normal" C order.
Width, height and depth are meaningless in this context. What you need to know is that multidimensional arrays are stored in row-major order.
Yes, assuming i varies from 0 ... D-1, j varies from 0 ... H-1, and k varies from 0 ... W-1.
Usually, though, the purpose of having an indexer, I thought, was to express relations within a sparse matrix so you didn't need to deal with the whole thing (and expend memory for it). If your data span the whole matrix, you might look into creating the 3d matrix as a pointer to an array of pointers, which themselves each point to an array of pointers. Using this allows you to use the x[i][j][k] notation but may be faster.
See http://www.nr.com/cpppages/chapappsel.pdf for a description.
If you need to to iterarate over all elements it is best to do in
for i
for j
for k
order. This way, it would be fastest, because index of array is incremented by one each time and values could be precached.
There is no only one correct way to do this but you probably chose best one.