C++ Eigen: How to concatenate matrices dynamically (pointer issue?) - c++

I have the following problem:
I have several partial (eigen) MatrixXds I want to concatenate to another, larger, MatrixXd variable I only have as a pointer. However, both the size of the smaller matrices and their number are dynamic, so I cannot use the << operator easily.
So I'm trying the following (the smaller matrices are stored in list_subdiagrams, obviously, and basis->cols() defines the number of matrices), using Eigen's MatrixXd block funtionality:
// sd[] contains the smaller matrices to be concatenated; all are of the same size
// col defines the total number of smaller matrices
MatrixXd* ret = new MatrixXd(sd[0]->rows(), col*sd[0]->cols());
for (int i=0; i<col; ++i){
ret->block(0, i*sd[0]->cols(), sd[0]->rows(), sd[0]->cols()) = *(sd[i]);
}
This, unfortunately, appears to somehow overwrite some part of the *ret variable - for before the assignment via the block, the size is (in my test-case) correctly shown as being 2x1. After the assignment it becomes 140736006011136x140736006011376 ...
Thank you for your help!

What do you mean you don't know the size? You can use the member functions cols()/rows() to get the size. Also, I assume by concatenation you mean direct sum? In that case, you can do something like
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::MatrixXd *A = new Eigen::MatrixXd(2, 2);
Eigen::MatrixXd *B = new Eigen::MatrixXd(3, 3);
*A << 1, 2, 3, 4;
*B << 5, 6, 7, 8, 9, 10, 11, 12, 13;
Eigen::MatrixXd *result = new Eigen::MatrixXd(A->rows() + B->rows(), A->cols() + B->cols());
result->Zero(A->rows() + B->rows(), A->cols() + B->cols());
result->block(0, 0, A->rows(), A->cols()) = *A;
result->block(A->rows(), A->cols(), B->rows(), B->cols()) = *B;
std::cout << *result << std::endl;
delete A;
delete B;
delete result;
}
So first make sure it works for 2 matrices, test it, then extend it to N.

Related

Iterating the creation of objects in C++

I want to be able to create N skyscrapers. Using an inputdata string, I would like to give them coordinate values of their X and Y positions. My main function I used "i" to demonstrate that I am trying to create as many skyscrapers as I can using the input data. Essentially, I would like to create N/3 skyscrapers and assign the input to coordinates for each.
#include <iostream>
#include <vector>
#include <string>
#include <math.h>
using namespace std;
vector<int> inputData = {1, 4, 10, 3, 5, 7, 9, 10, 4, 11, 3, 2, 14, 5, 5};
int N = inputData.size();
class Buildings{
public:
int yCoordinateLow;
int yCoordinateHigh;
int xCoordinateLeft;
int xCoordinateRight;
};
int main(){
for(int i=0; i<N; i=i+3){
Buildings skyscraper;
skyscraper.xCoordianteLeft = inputData.at(i);
skyscraper.yCoordianteLow = 0;
skyscraper.yCoordinateHigh = inputData.at(i+1);
skyscraper.xCoordinateRight = inputData.at(i+2);
}
return 0;
}
Jeff Atwood once said: use the best tools money can buy. And those aren't even expensive: Visual Studio community edition is free. Such a proper IDE will tell you that the skyscraper is unused except for the assignments.
Since you probably want to do something with those skyscrapers later, you should store them somewhere, e.g. in another vector.
int main() {
vector<Buildings> skyscrapers;
for (int i = 0; i < N; i = i + 3) {
Buildings skyscraper{};
skyscraper.xCoordinateLeft = inputData.at(i);
skyscraper.yCoordinateLow = 0;
skyscraper.yCoordinateHigh = inputData.at(i + 1);
skyscraper.xCoordinateRight = inputData.at(i + 2);
skyscrapers.push_back(skyscraper);
}
return 0;
}
Other than that, I'd say the loop works fine as long as there are N*3 coordinates in the original vector.
If you e.g. implement a game, you would probably not hard code the skyscraper coordinates in a vector but rather read that data from a file, potentially per level.
Instead of doing all the error-prone coding, maybe you want to initialize the skyscrapers immediately
vector<Buildings> skyscrapers = {{1,0,4,10}, {3,0,5,7}, {9,0,10,4}, {11,0,3,4}, {14,0,5,5}};

How to calculate the sum of individual elements from two 2D arrays?

I want to write a function addArrays which will, as parameters, take two 2D arrays of type int and of dimensions 3x4, and it's job is to add individual elements of each index from the given arrays and display it in the console.
In main(), I created two 2D arrays arrA and arrB of appropriate sizes with intitialized members and check the functionality of the created function.
My code so far:
#include <iostream>
using namespace std;
void addArrays(int x[3][4], int y[3][4]);
int main()
{
int arrA[3][4] = { {7, 8, 13, 22}, {56, 4, 78, 3}, {22, 13, 46, 5} };
int arrB[3][4] = { {32, 47, 56, 14}, {33, 100, 19, 64}, {4, 18, 157, 84} };
}
void addArrays(int x[3][4], int y[3][4])
{
}
Honestly, I know how to work with 1D arrays, but not displaying the sum of all individual elements. I know I have to use a for loop, but again, I'm confused as to how to pass in a 2D array and use it.
You mention you know how to work with 1D arrays, it's the same for 2D arrays, only with one more dimension.
In a 1D array you use arrA[0] to access the first element of the array, in a 2D array you use arrA[0][0] to access the first element in the first line of the array, arrA[0][1] to access the second element in the first line of the array. To access the first element in the second line you would use arrA[1][0] and so on, you get the idea.
So to loop through all the elements in the array you can use nested loops like so:
void addArrays(int x[3][4], int y[3][4])
{
for( int i = 0; i < 3; i++){ // make sure to use the correct dimensions
for(int j = 0; j < 4; j++){ // 3 lines and 4 columns
// x[i][j] accesses elements in array x
// y[i][j] accesses elements in array y
}
}
}
I think you'll manage to do the math yourself. After that you just need to send data to the standard output, i.e. to print data in the console. For that, as you may know, you use std::cout.
Side notes:
In the function void addArrays(int x[3][4], int y[3][4]){...} you may omit the first dimension of the array i.e. int x[][4] or int (*x)[4] instead of int x[3][4], since the argument will decay to a pointer to array.
Since it seems that you are not to change the values of the passed arrays, using const is recommend. You would have void addArrays(const int (*x)[4], const int (*y)[4]);
As you are using C++, you can take advantage of the possibility of using references, something like void addArrays(const int (&x)[3][4], const int (&y)[3][4]){/*same code*/}, the benefit being you must pass a correct object to the function otherwise the program will fail to compile whereas in the previous versions if you pass, for example, NULL, i.e. addArrays(arrA, NULL); the program will compile fine but will result in undefined behavior when you run it. References are safer and you should use them when possible.
It's more or less consensual among more experienced C++ programmers that the usage of using namespace std; is not a good practice, you can read more about it, and find alternatives following the link.
I will start this for you and try to give you an idea of the general structure, but since you have not shown your attempt at the problem I won't fill things in for you.
The basic idea here when looping through 2D arrays (of size MxN) is that you can really just think about it in terms of looping through M arrays of length N.
void loopThroughArray(int arr[M][N])
{
// Loop over M arrays
for (int m = 0; m < M; ++m) {
// For each m'th array, loop over its N contents
for (int n = 0; n < N; ++n) {
// Doing work
arr[m][n] = 1234;
}
}
}

Easy way to create multiple-dimension arrays in C++ with new operator

I need to create a lot of small 2-dimension arrays in C++ code.
The problem is that it's a lot of work to create even a simple array:
new int* [2]{
new int[2]{9, 9},
new int[2]{25, 19}
};
Is there any better way how to do that?
I wanted to avoid writing "new int[]..." every time.
If the dimensions are not decided at runtime, and all the inner arrays have the same dimensions, you do not need dynamic allocation here.
Just declare an array:
int myArray[2][2] = {
{9, 9},
{25, 19}
};
That's it!
I recommend allocating as a single dimension array. You can then treat the 1D array as a 2D array:
const unsigned int MAX_ROWS = 2U;
const unsigned int MAX_COLUMNS = 5U;
int example_array[MAX_ROWS * MAX_COLUMNS];
// Get value at [row][column]:
unsigned int one_dim_index = (row * MAX_COLUMNS) + column;
int value = example_array[one_dim_index];
For small array sizes, this would be more efficient since the processor can fit the entire contiguous array in the data cache. With your solution, an array of pointers, you have no idea where the sub-arrays are located and they may not be contiguous (thus requiring a refetch into the cache).
Edit 1: Initializing
You can initialize the array by making the rows and columns pretty:
int example_array[MAX_ROWS * MAX_COLUMNS] =
{
/* row 0 */ 1, 2, 3, 4, 5,
/* row 1 */ 6, 7, 8, 9, 10,
};
Maybe you can use nested for loops to do the task
const int ARRAY_SIZE = 2;
int **create_array() {
int **array = new int*[ARRAY_SIZE];
if (array == nullptr) { return nullptr; }
for (int i=0; i<ARRAY_SIZE; i++) {
array[i] = new int[ARRAY_SIZE];
if (array[i] == nullptr) { return nullptr; }
}
return array;
}
If you want to assing the values you can do it directly in here. But they should come from a function of i. If you want some really specific values it will need to be a manual job

ComputeLibrary CLTensor data transfer

I am working with integrating ARM ComputeLibrary into a project.
It's not an API whose semantics I am familiar with, but I'm working my way through the docs and examples.
At the moment, I am trying to copy the contents of an std::vector to a CLTensor. Then use the ARMCL GEMM operation.
I've been building an MWE, shown below, with the aim of getting matrix multiplication working.
To get the input data from a standard C++ std::vector, or std::ifstream, I am trying an iterator based approach, based on this example shown in the docs.
However, I keep getting a segfault.
There is an example of sgemm using CLTensor in the source, which is also where I'm drawing inspiration from. However it gets its input data from Numpy arrays, so isn't relevant up to this point.
I'm not sure in ARMCL if CLTensor and Tensor have disjoint methods. But I feel like they are of a common interface ITensor. Still, I haven't been able to find an equivalent example that uses CLTensor instead of Tensor for this iterator based method.
You can see my code I'm working with below, which fails on line 64 (*reinterpret_cast..). I'm not entirely sure what the operations are that it performs, but my guess is that we have our ARMCL iterator input_it which is incremented n * m times, each iteration setting the value of the CLTensor at that address to the corresponding input value. reinterpret_cast is just to make the types play nicely together?
I reckon my Iterator and Window objects are okay, but can't be sure.
#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/CL/CLFunctions.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "arm_compute/runtime/CL/CLTuner.h"
#include "utils/Utils.h"
namespace armcl = arm_compute;
namespace armcl_utils = arm_compute::utils;
int main(int argc, char *argv[])
{
int n = 3;
int m = 2;
int p = 4;
std::vector<float> src_a = {2, 1,
6, 4,
2, 3};
std::vector<float> src_b = {5, 2, 1, 6,
3, 7, 4, 1};
std::vector<float> c_targets = {13, 11, 6, 13,
42, 40, 22, 40,
19, 25, 14, 15};
// Provides global access to a CL context and command queue.
armcl::CLTuner tuner{};
armcl::CLScheduler::get().default_init(&tuner);
armcl::CLTensor a{}, b{}, c{};
float alpha = 1;
float beta = 0;
// Initialize the tensors dimensions and type:
const armcl::TensorShape shape_a(m, n);
const armcl::TensorShape shape_b(p, m);
const armcl::TensorShape shape_c(p, n);
a.allocator()->init(armcl::TensorInfo(shape_a, 1, armcl::DataType::F32));
b.allocator()->init(armcl::TensorInfo(shape_b, 1, armcl::DataType::F32));
c.allocator()->init(armcl::TensorInfo(shape_c, 1, armcl::DataType::F32));
// configure sgemm
armcl::CLGEMM sgemm{};
sgemm.configure(&a, &b, nullptr, &c, alpha, beta);
// // Allocate the input / output tensors:
a.allocator()->allocate();
b.allocator()->allocate();
c.allocator()->allocate();
// // Fill the input tensor:
// // Simplest way: create an iterator to iterate through each element of the input tensor:
armcl::Window input_window;
armcl::Iterator input_it(&a, input_window);
input_window.use_tensor_dimensions(shape_a);
std::cout << " Dimensions of the input's iterator:\n";
std::cout << " X = [start=" << input_window.x().start() << ", end=" << input_window.x().end() << ", step=" << input_window.x().step() << "]\n";
std::cout << " Y = [start=" << input_window.y().start() << ", end=" << input_window.y().end() << ", step=" << input_window.y().step() << "]\n";
// // Iterate through the elements of src_data and copy them one by one to the input tensor:
execute_window_loop(input_window, [&](const armcl::Coordinates & id)
{
std::cout << "Setting item [" << id.x() << "," << id.y() << "]\n";
*reinterpret_cast<float *>(input_it.ptr()) = src_a[id.y() * m + id.x()]; //
},
input_it);
// armcl_utils::init_sgemm_output(dst, src0, src1, armcl::DataType::F32);
// Configure function
// Allocate all the images
// src0.allocator()->import_memory(armcl::Memory(&a));
//src0.allocator()->allocate();
//src1.allocator()->allocate();
// dst.allocator()->allocate();
// armcl_utils::fill_random_tensor(src0, -1.f, 1.f);
// armcl_utils::fill_random_tensor(src1, -1.f, 1.f);
// Dummy run for CLTuner
//sgemm.run();
std::vector<float> lin_c(n * p);
return 0;
}
The part you've missed (Which admittedly could be better explained in the documentation!) is that you need to map / unmap OpenCL buffers in order to make them accessible to the CPU.
If you look inside the fill_random_tensor (which is what's used in the cl_sgemm example you've got a call to tensor.map();
So if you map() your buffer before creating your iterator then I believe it should work:
a.map();
input_it(&a, input_window);
execute_window_loop(...)
{
}
a.unmap(); //Don't forget to unmap the buffer before using it on the GPU
Hope this helps

How to use memset or fill_n to initialize a dynamic two dimensional array in C++

I have a 2D array created dynamically.
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
}
I want to fill the array with some value (say 1). I can loop over each item and do it.
But is there a simpler way. I am trying to use memset and std::fill_n as mentioned in this post.
std::fill_n(abc, rows * cols, 1);
memset(abc, 1, rows * cols * sizeof(int));
Using memset crashes my program. Using fill_n gives a compile error.
invalid conversion from 'int' to 'int*' [-fpermissive]
What am I doing wrong here ?
You could just use vector:
std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1));
You cannot use std::fill_n or memset on abc directly, it simply will not work. You can only use either on the sub-arrays:
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(abc[i], cols, 1);
}
Or make the whole thing single-dimensional:
int *abc = new int[rows * cols];
std::fill_n(abc, rows*cols, 1);
Or I guess you could use std::generate_n in combination with std::fill_n, but this just seems confusing:
int **abc = new int*[rows];
std::generate_n(abc, rows, [cols]{
int* row = new int[cols];
std::fill_n(row, cols, 1);
return row;
});
I think that your main problem here is that you don't have an array of int values. You have an array of pointers to ints.
You probably should start with int* abc = new int[rows * cols]; and work from there, if I understand what you are trying to achieve here.
Just use with * inside the loop you already have:
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(*(abc+i), cols, sizeof(int));
}
fill_n don't know where the memory maps the new int array, so you must be carefully coding that way.
I recommend to read:
A proper way to create a matrix in c++
Since you've already got good, workable answers to solve your problem, I want to add just two pointers left and right from the standard path ;-)
a) is just a link to the documentation of Boost.MultiArray
and b) is something I don't recommend you use, but it might help you to understand what you've initially tried. And since your profile shows visual studio tags, you might come in contact with something like this in the win32 api. If that is the case the documentation usually tells you not to use free()/LocalFree()/... on the elements and the "outer" pointer-pointer but to use a specialized function.
(note: I'm not trying to make this code look pretty or clever; it's a mishmash of c and a little c++-ish junk ;-))
const std::size_t rows = 3, cols =4;
int main()
{
std::size_t x,y;
// allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints
int **abc = (int**)malloc( (rows*sizeof(int*)) + cols*rows*sizeof(int) );
// the memory behind abc is large enough to hold the pointers for abc[0...rows-1]
// + the actual data when accessing abc[0...rows-1][0....cols-1]
int* data = (int*)((abc+rows));
// data now points to the memory right after the int*-pointer array
// i.e. &(abc[0][0]) and data should point to the same location when we're done:
// make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1)....
for(y=0;y<rows; y++) {
abc[y] = &(data[y*cols]);
}
// now you can use abc almost like a stack 2d array
for(y=0; y<rows; y++) {
for (x=0; x<cols; x++) {
abc[y][x] = 127;
}
}
// and -since the memory block is continuos- you can also (with care) use memset
memset(&abc[0][0], 1, sizeof(int)*rows*cols);
// and with equal care ....
std::fill_n( &(abc[0][0]), rows*cols, 127);
// and get rid of the whole thing with just one call to free
free(abc);
return 0;
}