Mapping a complex matrix with Eigen - c++

I have the following matrix:
int N = 3;
complex<double>* complexvector = new complex<double>[N];
for(int i=0; i<N; i++)
{
complexvector[i]=complex<double>(i+1,i+1);
}
complex<double>** complexMatrix = new complex<double>*[N];
for(int i=0; i<N; i++)
{
complexMatrix[i] = new complex<double>[N];// allocate an array to each pointer
}
complexMatrix[0][0] = complex<double>(1,1);
complexMatrix[0][1] = complex<double>(2,2);
complexMatrix[0][2] = complex<double>(3,3);
complexMatrix[1][0] = complex<double>(4,4);
complexMatrix[1][1] = complex<double>(5,5);
complexMatrix[1][2] = complex<double>(6,6);
complexMatrix[2][0] = complex<double>(7,7);
complexMatrix[2][1] = complex<double>(8,8);
complexMatrix[2][2] = complex<double>(9,9);
complex<double>* returnvector = new complex<double>[N];
returnvector = preformcholesky(complexMatrix, complexvector, N);
And I do the Cholesky here:
complex<double>* preformcholesky(complex<double>** matrix, complex<double>* vector,
int size)
{
std::cout << "start cholesky" << std::endl;
Map<MatrixXcd, RowMajor> mat(*matrix,size,size);
Map<VectorXcd> vec(vector,size);
printMatrix(matrix,size);
std::cout << "mat" << mat << std::endl;
std::cout << "vec" << vec << std::endl;
//mat.llt();
VectorXcd x = mat.llt().solve(vec);
std::cout << "coeff" << x << std::endl;
return x.data();
}
The trouble is when printing out "mat", it goes like this:
mat (1,1) (0,3.21143e-322) (6,6)
(2,2) (4,4) (0,3.21143e-322)
(3,3) (5,5) (7,7)
Where do those (0,3.21143e-322) come from? If I print "matrix" then that is OK, so I think that the map has gone wrong. If you need some more code then just let me know. I am new to Eigen so maybe some basic mistake. I am using C++ and Linux.

There are several things wrong with that code. The return value of performcholesky, for example, is a pointer to a local variable that does not exist anymore after performcholesky has returned, and you overwrite a pointer to allocated memory with this dangling pointer, leaking that memory. Why don't you work with Eigen::MatrixXcd directly? You'd save yourself a world of pain debugging all that later.
Anyway, the problem you ran into this time is that the Eigen::Map constructor expects a flat array, not a pointer to pointer. It is to be used like this:
// It would also work with naked new, but naked new leads to pain, fear, anger,
// and suffering. Also to long hours of debugging.
std::vector<std::complex<double> > data(N * N);
for(int i = 0; i < N * N; ++i) {
data[i] = std::complex<double>(i, i);
}
Eigen::Map<Eigen::MatrixXcd, Eigen::RowMajor> mat(&data[0], N, N);
An interesting question is why the two arrays that you did not pass to the constructor nevertheless show up in the map, if somewhat shifted. The answer is: By pure happenstance, new gave you three slabs of memory that were right behind each other on the heap. This also explains the strange artifacts you see in the map; those are bookkeeping data of your heap implementation for the corresponding allocated blocks, reinterpreted as doubles. In essence, the memory around complexmatrix[0] looks like this:
the area that Eigen::Map uses
+-----------------------------------------------------------------+
|(1,1)|(2,2)|(3,3)|bookkeeping|(4,4)|(5,5)|(6,6)|bookkeeping|(7,7)|(8,8)|(9,9)|
+-----------------+ +-----------------+ +-----------------+
^-complexmatrix[0] ^-complexmatrix[1] ^-complexmatrix[2]
Naturally, this is not behavior you can depend upon. The code could just as well show any random data or crash with a segfault if the blocks new gives you are arranged in a different manner.

Related

C++ - problems with vector pointers

Imagine I want to manipulate a single vector with the content of two current vectors, such as:
vector<double> b(5),c(5);
vector<double*> point;
for (int i; i<5; i++) point.push_back(new double(b[i]));
for (int i; i<5; i++) point.push_back(new double(c[i]));
That's nice until here. How would one manipulate such vector?
I have been trying variations of:
point[7] = 33.12;
I am pretty sure I am missing something about reference since "point[7]" will be a memory address.
Since this is a vector of pointers, the subscript operator returns a pointer:
*point[0] = 33.12; // Assigns new value to the pointer
// Equivalent: *(point[0]), fetch a pointer and dereference it
For example:
vector<double*> point;
double d = 3.14;
point.push_back(&d);
*point[0] = 1.61;
std::cout << *point[0] << std::endl; // Prints 1.61
P.S. as specified in comments to the question, note the: int i in your for loop.

C++ Void double pointer interference with another

I am trying to do a project that involves overloading new and delete. I am storing an array of void pointers (pointers to random memory that is allocated) in a double void pointer. Of course, this array will need to be resized to account for further void pointers that come in.
This is the intialization of the array, allocArraySize(int) is set to 4.
void** allocArray = (void**) calloc ( allocArraySize, sizeof(void*) );
Setting all values to nullptr..
for(int i=0; i<allocArraySize; i++){ *(allocArray + i*sizeof(void*)) = nullptr; }
However, when trying to resize the array, I noticed that my original array of void pointers is modified when I create a new temporary array(temp) to store them in.
// PRINTS THE ORIGINAL ARRAY
for(int i=0; i<allocArraySize; i++){std::cout<<i<<" = "<<*( allocArray + i*sizeof(void*))<<"\n";}
void** tempArray = (void**)calloc(allocArraySize, sizeof(void*));
// PRINTS THE ORIGINAL ARRAY
for(int i=0; i<allocArraySize; i++){std::cout<<i<<" = "<<*( allocArray + i*sizeof(void*))<<"\n";}`
Notice, I am not even putting the array values in the temp array yet and I am still getting this problem. Why is that? why is this random value being assigned to this spot when it is indeed initialized? How is this one new temp array variable messing with my array?
NOTE: This is basically the complete code. Only thing missing is a main function, iostream, and the declaration for allocArraySize. Yes, WELL aware that I am not freeing these poor double pointers. I just wanted to create the problem in simplest terms possible.
The sizeof multiplier shouldn't be there:
*(allocArray + i*sizeof(void*))
// ^^^^^^^^^^^^^^ this shouldn't be here
void** is strongly typed. It participates in proper offset calculation via pointer arithmetic. There is no need here for sizeof offset calculations. That loop, which appears to be crafted to dump the pointer values in the sequence, should therefore be:
for(int i=0; i<allocArraySize; i++)
{
std::cout<< i << " = " << allocArray[i] << "\n";
}
You are indexing the pointers incorrectly i * sizeof(void*) rather than i.
for(int i=0; i<allocArraySize; i++){ allocArray[i] = nullptr; }
Firstly, you rather shouldn't use calloc in C++ code. Especially if you program uses both new expression and calloc\malloc, it may lead to to UB due to mismatching deletors.
allocArraySize got type void** , so it's pointer to pointer. Result of expression *allocArraySize got same sizeof as void* or uintptr_t type. Arithmetic with pointers automatically increment pointer by amount required to point at next object of same type.
C++ way to write it doesn't even require such arcane knowledge either, all you should do is to use a new expression and list-initialize it with empty list to get same effect as calloc does in C.
void** allocArray = ::new void*[allocArraySize] {};
for(int i = 0; i < allocArraySize; ++i)
{
std::cout<< i << " = " << allocArray[i] << "\n";
}
When using new/delete from within of overloaded one, it's essential to use :: or it would lead to infinite recursion.
allocArray[i] is an equivalent of *(allocArray + i)
Overloading new\delete aside. But truly C++ way to do that is to avoid naked pointers and use containers if possible. New\delete might be wrappers around usage of some memory pool class.
// do we really need a vector of pointers?
auto allocArray = std::vector<void*>(allocArraySize, nullptr);
int i = 0;
for( auto &v : allocArray )
std::cout<< (i++) << " = " << v << "\n";
In C++20 range-based for loop becomes more contained thanks to init-statement
for(int i = 0; auto &v : allocArray )
std::cout<< (i++) << " = " << v << "\n";

c++ float* array as reference to std::vector<float>

I want to create a std::vector<float> vpd which will be a reference to float*.
float * old = new float[6];
for (int i = 0; i < 6; i++)
{
old[i] = i;
}
vector<float> vpd(6);
auto refasd = &*vpd.begin();
*refasd = *old;
vpd[0] = 23;
cout << old[0] << endl;
How should I modify the code, if I want get 23 from cout?
You can't. std::vector is not designed to take ownership of a raw pointer.
Maybe you can make do with std::unique_ptr<float[]>, but the better solution is to directly use std::vector.
As alternative, you might use std::span (C++20)
float* old = new float[6];
std::iota(old, old + 6, 0);
std::span<float> vpd(old, 6);
vpd[0] = 23;
std::cout << old[0] << std::endl;
delete[] old;
You could also create a vector of std::reference_wrapper objects that refer to the original float array - may that be std::vector<float> or a newed float*. An example:
vector<std::reference_wrapper<float>> vpd(old, old + 6); // ¹
vpd[0].get() = 23.f;
cout << old[0] << endl; // prints 23
¹) Thanks to #StoryTeller for pointing out that vpd can be directly initialized.
As std::vector has its own memory structure you cannot map vector<float> or even vector<float*> to an array of float. However you can map each vector item to an array one.
float* old = new float[6];
for (int i = 0; i < 6; i++)
{
old[i] = i;
}
vector<float*> vpd(6);
int i = 0;
for (auto it = vpd.begin(); it != vpd.end(); it++)
{
*it = &old[i++];
}
*vpd[0] = 23;
*vpd[2] = 45;
cout << old[0] << endl << old[2] << endl;
Output
23
45
Depending on version of C++ you'll have some options (if I understand the problem):
if you have an older c++ version then c++11 I would in this case declear std::vector as:
// then you really need to make sure u delete the memory as well
std::vector<float*> vpd(6);
If however you got c++11 or higher I would use either std::share_ptr or std::unique_ptr depending on if you would like to share the memory space or not. Either this will ensure the memory is deleted by it self without having to do a "delete float*;" which is nice.
You can read about std::shared_ptr at: https://en.cppreference.com/w/cpp/memory/shared_ptr and std::unique_ptr at: https://en.cppreference.com/w/cpp/memory/unique_ptr
// For unique_ptr
std::vector<std::unique_ptr<float>> vpd(6);
// for std::shared_ptr
std::vector<std::shared_ptr<float>> vpd(6);
I would say that if you can then use unique_ptr rather then shared_ptr due to shared_ptr has som extra komplexitity within to be make sure the memory not used before deleteing memory space.

3D array C++ using int [] operator

I'm new to C/C++ and I've been cracking my head but still got no idea how to make an "structure" like this
It's supposed to be a 3D dynamic array using pointers.
I started like this, but got stuck there
int x=5,y=4,z=3;
int ***sec=new int **[x];
It would be enough to know how to make it for a static size of y and z;
Please, I'd appreciate that you help me.
Thanks in advance.
To create dynamically 3D array of integers, it's better you understand 1D and 2D array first.
1D array: You can do this very easily by
const int MAX_SIZE=128;
int *arr1D = new int[MAX_SIZE];
Here, we are creating an int-pointer which will point to a chunk of memory where integers can be stored.
2D array: You may use the solution of above 1D array to create a 2D array. First, create a pointer which should point to a memory block where only other integer pointers are held which ultimately point to actual data. Since our first pointer points to an array of pointers so this will be called as pointer-to-pointer (double pointer).
const int HEIGHT=20;
const int WIDTH=20;
int **arr2D = new int*[WIDTH]; //create an array of int pointers (int*), that will point to
//data as described in 1D array.
for(int i = 0;i < WIDTH; i++){
arr2D[i] = new int[HEIGHT];
}
3D Array: This is what you want to do. Here you may try both the scheme used in above two cases. Apply the same logic as 2D array. Diagram in question explains all. The first array will be pointer-to-pointer-to-pointer (int*** - since it points to double pointers). The solution is as below:
const int X=20;
const int Y=20;
const int z=20;
int ***arr3D = new int**[X];
for(int i =0; i<X; i++){
arr3D[i] = new int*[Y];
for(int j =0; j<Y; j++){
arr3D[i][j] = new int[Z];
for(int k = 0; k<Z;k++){
arr3D[i][j][k] = 0;
}
}
}
// one-liner
typedef std::vector<std::vector<std::vector<int> > > ThreeDimensions;
// expanded
typedef std::vector<int> OneDimension;
typedef std::vector<OneDimension> TwoDimensions;
typedef std::vector<TwoDimension> ThreeDimensions;
(this is tagged c++, after all)
EDIT in response to Joe's question
hello again Joe =) sure. here's the example:
#include <vector>
#include <iostream>
int main(int argc, char* const argv[]) {
/* one-liner */
typedef std::vector<std::vector<std::vector<int> > >ThreeDimensions;
/* expanded */
typedef std::vector<int>OneDimension;
typedef std::vector<OneDimension>TwoDimensions;
typedef std::vector<TwoDimensions>ThreeDimensions;
/*
create 3 * 10 * 25 array filled with '12'
*/
const size_t NElements1(25);
const size_t NElements2(10);
const size_t NElements3(3);
const int InitialValueForAllEntries(12);
ThreeDimensions three_dim(NElements3, TwoDimensions(NElements2, OneDimension(NElements1, InitialValueForAllEntries)));
/* the easiest way to assign a value is to use the subscript operator */
three_dim[0][0][0] = 11;
/* now read the value: */
std::cout << "It should be 11: " << three_dim[0][0][0] << "\n";
/* every other value should be 12: */
std::cout << "It should be 12: " << three_dim[0][1][0] << "\n";
/* get a reference to a 2d vector: */
TwoDimensions& two_dim(three_dim[1]);
/* assignment */
two_dim[2][4] = -1;
/* read it: */
std::cout << "It should be -1: " << two_dim[2][4] << "\n";
/* get a reference to a 1d vector: */
OneDimension& one_dim(two_dim[2]);
/* read it (this is two_dim[2][4], aka three_dim[1][2][4]): */
std::cout << "It should be -1: " << one_dim[4] << "\n";
/* you can also use at(size_t): */
std::cout << "It should be 12: " << one_dim.at(5) << "\n";
return 0;
}
You can try:
for(int i=0;i<x;i++) {
sec[i] = new int *[y];
for(int j=0;j<y;j++) {
sec[i][j] = new int [z];
}
}
And once you are done using this memory you can deallocate it as:
for(int i=0;i<x;i++) {
for(int j=0;j<y;j++) {
delete [] sec[i][j];
}
delete [] sec[i];
}
delete [] sec;
Comprehensive answers.
If you are really writing this in C++ (not rough C) I think you should take another look at this complicated data structure. IMO redesign while keeping in mind what you are trying to do would be better.
What you're trying to do is not idiomatic in C++. Of course, you can use a int***pointer for this, but this is strongly discouraged. In C++ we have better ways to get there.
vector<vector<vector<int> > > foo (5,vector<vector<int> >(4, vector<int>(3)));
This will result in something with the memory layout similar to what you asked for. It supports dynamic resizing and inner vectors to have different sizes just like in your picture. In addition, you don't have to worry about manual allocation / deletion of any of it. Also, the vectors know their size so you don't have to remember it somewhere.
But if you just want a "rectangular" 3D array where all the elements are consecutivly stored in the same memory block, you could use a boost::multiarray.
OK let us take your beginnings
int ***sec = new int**[x];
sec is now an array of int**s of length x, so now I am just going to focus on making the zeroeth element be what you want
sec[0] = new int*[y];
Now sec[0] points to array of int*s of length y, now just need to get the last bit of the tree done, so
sec[0][0] = new int[z];
And finally to get it to the form in your diagram
sec[0][0][z-1] = 0;
This does seem a little like a homework question, make sure you actually understand the answer and why it works.
If it's the actual arrays you'r having problems with look here: Declaring a pointer to multidimensional array and allocating the array
Not sure exactly what you want but you might want to read up on about linked lists.

Expanding a dynamically allocated array

I have allocated an array as follows.
#include <iostream>
int main() {
const int first_dim = 3;
const int second_dim = 2;
// Allocate array and populate with dummy data
int** myArray = new int*[first_dim];
for (int i = 0; i < first_dim; i++) {
myArray[i] = new int[second_dim];
for (int j = 0; j < second_dim; j++) {
myArray[i][j] = i*second_dim + j;
std::cout << "[i = " << i << ", j = " << j << "] Value: " << myArray[i][j] << "\n";
}
}
// De-allocate array
for (int i = 0; i < first_dim; i++)
delete[] myArray[i];
delete[] myArray;
}
Let's say I want to add a 4th element to the first dimension, i.e. myArray[3]. Is this possible?
I've heard that Vectors are so much more efficient for this purpose, but I hardly know what they are and I've never used them before.
Yes, but in a very painful way. What you have to do is allocate new memory which now has your new desired dimensions, in this case 4 and 2, then copy all the contents of your matrix to your new matrix, and then free the memory of the previous matrix... that's painful. Now let's see how the same is done with vectors:
#include <vector>
using std::vector;
int main()
{
vector< vector <int> > matrix;
matrix.resize(3);
for(int i = 0; i < 3; ++i)
matrix[i].resize(2);
matrix[0][1] = 4;
//...
//now you want to make the first dimension 4? Piece of cake
matrix.resize(4);
matrix[3].resize(2);
}
HTH
edit:
some comments on your original code:
In C++ ALL_CAP_NAMES usually refer to macros (something you #define). Avoid using them in other contexts
why do you declare FIRSTDIM and SECONDDIM static? That is absolutely unnecessary. If a local variable is static it means informally that it will be the same variable next time you call the function with kept value. Since you technically can't call main a second sime this is useless. Even if you could do that it would still be useless.
you should wrire delete [] array[i]; and delete [] array; so the compiler knows that the int* and int** you're trying to delete actually point to an array, not just an int or int* respectively.
Let's say I want to add a 4th element to the first dimension, i.e. myArray[3]. Is this possible?
Yes, but it's a pain in the neck. It basically boils down to allocating a new array, just as your existing code does (hint: put it in the function and make the sizes arguments to that function) and copying compatible elements over.
Edit: One of the things that std::vector does for you is properly de-allocating you memory. In the code you have, failure to allocate one of the arrays along the 2nd dimension will result in a memory leak. A more robust solution would initialize pointers to 0 before performing any allocation. An exception block could then catch the exception and free whatever was partially allocated.
Because this code becomes complex quickly, people resort to allocating a single buffer and addressing using a stride or using a 1D array of 1D arrrays (i.e. std::vector of std::vectors).