I have an object of std::vector<std::array<double, 16>>
vector entry Data
[0] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[1] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[2] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[...] - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
This is intended to represent a 4x4 matrix in ravel format.
To not duplicate information I would like to create a pointer to extract a 3x3 from the above structure:
I have mathematical operations for the 3x3 structure (std::array<double, 9>)
someStructure: pointing to data elements [0, 1, 2, 4, 5, 6, 8, 9 10]
The end goal is do: std::array<double, 9> tst = someStructure[0] + someStructure[1];
Is this doable?
Best Regards
The 3x3 part is not contiguous, hence a pointer alone wont help here.
You can write a view_as_3x3 that allows you to access elements of the submatrix of the 4x4 as if it was contiguous:
struct view_as_3x3 {
double& operator[](size_t index) {
static const size_t mapping[] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
return parent[mapping[index]];
}
std::array<double, 16>& parent;
};
Such that for example
for (size_t = 0; i< 9; ++i) std::cout << " " << view_as_3x3{orignal_matrix}[i];
is printing the 9 elements of the 3x3 sub-matrix of the original 4x4 original_matrix.
Then you could more easily apply your 3x3 algorithms to the 3x3 submatrix of a 4x4 matrix. You just need to replace the std::array<double, 9> with some generic T. For example change
double sum_of_elements(const std::array<double, 9>& arr) {
double res = 0;
for (int i=0;i <9; ++i) res += arr[i];
return res;
}
To:
template <typename T>
double sum_of_elements(const T& arr) {
double res = 0;
for (int i=0;i <9; ++i) res += arr[i];
return res;
}
The calls are then
std::array<double, 16> matrix4x4;
sum_of_elements(view_as_3x3{matrix4x4});
// or
std::array<double, 9> matrix3x3;
sum_of_elements(matrix3x3);
It would be nicer to use iterators instead of indices, however, writing the view with custom iterators requires considerable amount of boilerplate. On the other hand, I would not suggest to use naked std::arrays in the first place, but rather some my_4x4matrix that holds the array as member and provides iterators and more convenience methods.
Related
I want to reindex a Eigen:Matrix by rolling N∈ℤ rows like this (here N=+1):
1 4 7 -> 3 6 9
2 5 8 1 4 7
3 6 9 2 5 8
Is there a simple way, or do I have to create a new matrix and copy over the data?
I suggest setting up a new matrix and copying the data. Eigen's block operations allow doing this in an efficient way. Here is how a shift by n rows can be done for the example above.
MatrixXi A(3,3);
A << 1, 2, 3, 4, 5, 6, 7, 8, 9;
A.transposeInPlace();
int n = 1; // number of shifts
n = n % A.rows();
MatrixXi B(A.rows(), A.cols());
B.bottomRows(A.rows() - n) = A.topRows(A.rows() - n);
B.topRows(n) = A.bottomRows(n);
std::cout << "B = " << B << std::endl;
If you are interested in a matlab-like syntax you can also use
MatrixXd A;
//... fill A
VectorXi indices = {{2,0,1}};
A(indices, Eigen::all);
I don't know, whether this internally makes a copy.
Note: This does not work for Sparse matrices, see Subset columns of sparse eigen matrix
I'm trying to use the MKL routine mkl_dcsradd to add an upper-triangular matrix to its transpose. In this case, the upper triangular matrix stores part of the adjacency matrix of a graph, and I need the full version for implementing another algorithm.
In this simplified example, I start with a list of (11) edges, and build an upper-triangular CSR matrix from it. I have checked that this much works. However, when I try to add it to its transpose, dcsradd stops on the final row, saying it's run out of space. However, this shouldn't be the case. An upper triangular matrix (no zeros along the diagonal) with n non-zero entries, when added to its transpose, should result in a matrix with 2n (22) non-zeros.
When I supply dcsradd with a maximum non-zeros of 22, it fails, but when I supply it with 23 (an excessive value), it works correctly. Why is this?
I've simplified my code down to a minimal example demonstrating the error:
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <mkl.h>
int main()
{
int nnz = 11;
int numVertices = 10;
int32_t u[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1 };
int32_t v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 5, 8 };
double w[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int fullNnz = nnz * 2;
int dim = numVertices;
double triData[nnz];
int triCols[nnz];
int triRows[dim];
// COO to upper-triangular CSR
int info = -1;
int job [] = { 2, 1, 0, 0, nnz, 0 };
mkl_dcsrcoo(job, &dim,
triData, triCols, triRows,
&nnz, w, u, v,
&info);
printf("info = %d\n", info);
// Allocate final memory
double data[fullNnz];
int cols[fullNnz];
int rows[dim];
// B = A + A^T (to make a full adjacency matrix)
int request = 0, sort = 0;
double beta = 1.0;
int WRONG_NNZ = fullNnz + 1; // What is happening here?
mkl_dcsradd("t", &request, &sort, &dim, &dim,
triData, triCols, triRows,
&beta, triData, triCols, triRows,
data, cols, rows,
&WRONG_NNZ, &info);
printf("info = %d\n", info);
// Convert back to 0-based indexing (via Cilk)
cols[:]--;
rows[:]--;
printf("data:");
for (double d : data) printf("%.0f ", d);
printf("\ncols:");
for (int c : cols) printf("%d ", c);
printf("\nrows:");
for (int r : rows) printf("%d ", r);
printf("\n");
return 0;
}
I compile with:
icc -O3 -std=c++11 -xHost main.cpp -o main -openmp -L/opt/intel/composerxe/mkl/lib -lmkl_intel_lp64 -lmkl_core -lmkl_intel_thread -lpthread -lm
When I give 22, the output is:
info = 0
info = 10
data:1 10 1 2 11 2 3 3 4 4 5 10 5 6 6 7 7 8 11 8 9 0
cols:1 5 0 2 8 1 3 2 4 3 5 0 4 6 5 7 6 8 1 7 9 -1
rows:0 2 5 7 9 11 14 16 18 21
But, when I give 23, the output is:
info = 0
info = 0
data:1 10 1 2 11 2 3 3 4 4 5 10 5 6 6 7 7 8 11 8 9 9
cols:1 5 0 2 8 1 3 2 4 3 5 0 4 6 5 7 6 8 1 7 9 8
rows:0 2 5 7 9 11 14 16 18 21
I want to loop an array then during each loop I want to loop backwards over the previous 5 elements.
So given this array
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
and this nested loop
for(int i=0;i<arr.size;i++)
{
for(int h=i-5; h<i; h++)
{
//things happen
}
}
So, if i=0, second loop would loop last few elements 4,6,2,6,5.
How could you handle this?
I'm assuming that:
You only want to go over previous values (i.e. no wrap around) You
You don't actually want arr to be a multi-dimensional array as suggested
by your choice of tags
You want to include the current i in your five values
This is just a small modification to your code that will do (what I think) you are asking:
#include <math>
int main()
{
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
for(int i=0;i<arr.size;i++)
{
for(int h = max(i-4, 0); h < i+1; h++)
{
//things happen
}
}
}
note the h = max(i-4, 0) and h < i+1This will reduce the number of iterations of the inner loop so that it starts from index 0 and loops up through the five values up to and including i. (four values and i). h will always be within bounds.
The case where i==arr.size won't be a problem in the inner loop as the outer loop will terminate before that happens (i is always within bounds).
Edit: I saw this comment:
I want the first element to consider the last final 5 elements of the array though.
in which case, your loops should look like:
for(int i=0;i<arr.size;i++)
{
for(int h=0; h<5; h++)
{
int index = (i + arr.size - h) % arr.size;
//things happen
//access array with arr[index];
}
}
This should do what you want:
When i=0, h=0 index=(0+24-0)%24 which is 0. For h=1 we go one less, index=(0+24-1)%24 = 23 and so on for the next values of h.
The code gets the last 5 values, wrapping round, inclusive of the current value. (so will get 20,21,22,23,0 when i=0, 21,22,23,0,1 when i=1)
If you want the five before, non-inclusive, then inner loop should be:
for(int h=1; h<=5; h++)
here is the current output of the loop as it stands:
i 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 ... 22 22 22 22 22 23 23 23 23 23
h 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 ... 0 1 2 3 4 0 1 2 3 4
index 0 23 22 21 20 1 0 23 22 21 2 1 0 23 22 3 2 1 0 23 ... 22 21 20 19 18 23 22 21 20 19
I assume you want it to loop around (don't know why). if so, use modulo:
int index = (h + arr.size) % arr.size;
Using the modulo operator.
for (int i = 0; i < arr.size; i++)
{
for (int h = 5; h > 0; h--)
{
const int array_length = sizeof(arr) / sizeof(arr[0]);
int index = (i - h + array_length) % array_length; // Use 'sizeof(arr) / sizeof(arr[0])' to get the size of the array
//things happen
}
}
Is using if statement not an option?
const int array_size = 24;
int arr[array_size] = { 1,3,4,5,...,2 }
for(int i=0;i<array_size;i++)
{
for(int h=i-5; h<i; h++)
{
int arr_index = (h >= 0) ? h : (array_size + h);
//do your things with arr[arr_index]
}
}
you may also start the nested loop with something like:
for(int h=i-min(i,5);h<i;++h)
{
}
which let you process first 5 cells as well. also, if you are dealing with some kind of signal or image processing consider extending arr to have 29 elements with preceding 5 zeros or whatever value would be suitable, and start the first for-loop with 5th element.
Just make an if statement in nested loop. Something like this
for( int h = i-5; h < i; h++ )
{
// do stuff
if( i == 0 )
break;
}
Assume that I have a vector:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
What I need to do is split this vector into block sizes of blocksize with an overlap
blocksize = 4
overlap = 2
The result, would be a 2D vector with size 4 containing 6 values.
x[0] = [1, 3, 5, 7, 9, 11]
x[1] = [ 2 4 6 8 10 12]
....
I have tried to implement this with the following functions:
std::vector<std::vector<double> > stride_windows(std::vector<double> &data, std::size_t
NFFT, std::size_t overlap)
{
std::vector<std::vector<double> > blocks(NFFT);
for(unsigned i=0; (i < data.size()); i++)
{
blocks[i].resize(NFFT+overlap);
for(unsigned j=0; (j < blocks[i].size()); j++)
{
std::cout << data[i*overlap+j] << std::endl;
}
}
}
This is wrong, and, segments.
std::vector<std::vector<double> > frame(std::vector<double> &signal, int N, int M)
{
unsigned int n = signal.size();
unsigned int num_blocks = n / N;
unsigned int maxblockstart = n - N;
unsigned int lastblockstart = maxblockstart - (maxblockstart % M);
unsigned int numbblocks = (lastblockstart)/M + 1;
std::vector<std::vector<double> > blocked(numbblocks);
for(unsigned i=0; (i < numbblocks); i++)
{
blocked[i].resize(N);
for(int j=0; (j < N); j++)
{
blocked[i][j] = signal[i*M+j];
}
}
return blocked;
}
I wrote this function, thinking that it did the above, however, it will just store:
X[0] = 1, 2, 3, 4
x[1] = 3, 4, 5, 6
.....
Could anyone please explain how I would go about modifying the above function to allow for skips by overlap to take place?
This function is similar to this: Rolling window
EDIT:
I have the following vector:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
I want to split this vector, into sub-blocks (thus creating a 2D vector), with an overlap of the parameter overlap so in this case, the parameters would be: size=4 overlap=2, this would then create the following 2D vector:
`block0 = [ 1 3 5 7 9 11]
block1 = [ 2 4 6 8 10 12]
block2 = [ 3 5 7 9 11 13]
block3 = [ 4 6 8 10 12 14]`
So essentially, 4 blocks have been created, each block contains a value where the element is skipped by the overlap
EDIT 2:
This is where I need to get to:
The value of overlap will overlap the results of x in terms of placements inside the vector:
block1 = [1, 3, 5, 7, 9, 11]
Notice from the actual vector block:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
Value: 1 -> This is pushed into block "1"
Value 2 -> This is not pushed into block "1" (overlap is skip 2 places in the vector)
Value 3 -> This is pushed into block "1"
value 4 -> This is not pushed into block "1" (overlap is skip to places in the vector)
value 5 -> This is pushed into block "1"
value 6 -> "This is not pushed into block "1" (overlap is skip 2 places in the vector)
value 7 -> "This value is pushed into block "1"
value 8 -> "This is not pushed into block "1" (overlap is skip 2 places in the vector)"
value 9 -> "This value is pushed into block "1"
value 10 -> This value is not pushed into block "1" (overlap is skip 2 places in the
vector)
value 11 -> This value is pushed into block "1"
BLOCK 2
Overlap = 2;
value 2 - > Pushed back into block "2"
value 4 -> Pushed back into block "2"
value 6, 8, 10 etc..
So each time, the place in the vector is skipped by the "overlap" in this case, it is the value of 2..
This is what the expected output would be:
[[ 1 3 5 7 9 11]
[ 2 4 6 8 10 12]
[ 3 5 7 9 11 13]
[ 4 6 8 10 12 14]]
If I understand you correctly, you're pretty close. You need something like the following. I used int because frankly its easier to type than double =P
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
#include <iterator>
std::vector<std::vector<int>>
split(const std::vector<int>& data, size_t blocksize, size_t overlap)
{
// compute maximum block size
std::vector<std::vector<int>> res;
size_t minlen = (data.size() - blocksize)/overlap + 1;
auto start = data.begin();
for (size_t i=0; i<blocksize; ++i)
{
res.emplace_back(std::vector<int>());
std::vector<int>& block = res.back();
auto it = start++;
for (size_t j=0; j<minlen; ++j)
{
block.push_back(*it);
std::advance(it,overlap);
}
}
return res;
}
int main()
{
std::vector<int> data { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
for (size_t i=2; i<6; ++i)
{
for (size_t j=2; j<6; ++j)
{
std::vector<std::vector<int>> blocks = split(data, i, j);
std::cout << "Blocksize = " << i << ", Overlap = " << j << std::endl;
for (auto const& obj : blocks)
{
std::copy(obj.begin(), obj.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
std::cout << std::endl;
}
}
return 0;
}
Output
Blocksize = 2, Overlap = 2
1 3 5 7 9 11 13
2 4 6 8 10 12 14
Blocksize = 2, Overlap = 3
1 4 7 10 13
2 5 8 11 14
Blocksize = 2, Overlap = 4
1 5 9 13
2 6 10 14
Blocksize = 2, Overlap = 5
1 6 11
2 7 12
Blocksize = 3, Overlap = 2
1 3 5 7 9 11
2 4 6 8 10 12
3 5 7 9 11 13
Blocksize = 3, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
Blocksize = 3, Overlap = 4
1 5 9
2 6 10
3 7 11
Blocksize = 3, Overlap = 5
1 6 11
2 7 12
3 8 13
Blocksize = 4, Overlap = 2
1 3 5 7 9 11
2 4 6 8 10 12
3 5 7 9 11 13
4 6 8 10 12 14
Blocksize = 4, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
4 7 10 13
Blocksize = 4, Overlap = 4
1 5 9
2 6 10
3 7 11
4 8 12
Blocksize = 4, Overlap = 5
1 6 11
2 7 12
3 8 13
4 9 14
Blocksize = 5, Overlap = 2
1 3 5 7 9
2 4 6 8 10
3 5 7 9 11
4 6 8 10 12
5 7 9 11 13
Blocksize = 5, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
4 7 10 13
5 8 11 14
Blocksize = 5, Overlap = 4
1 5 9
2 6 10
3 7 11
4 8 12
5 9 13
Blocksize = 5, Overlap = 5
1 6
2 7
3 8
4 9
5 10
Here is a code snippet below.
Input to program is
dimension d[] = {{4, 6, 7}, {1, 2, 3}, {4, 5, 6}, {10, 12, 32}};
PVecDim vecdim(new VecDim());
for (int i=0;i<sizeof(d)/sizeof(d[0]); ++i) {
vecdim->push_back(&d[i]);
}
getModList(vecdim);
Program:
class dimension;
typedef shared_ptr<vector<dimension*> > PVecDim;
typedef vector<dimension*> VecDim;
typedef vector<dimension*>::iterator VecDimIter;
struct dimension {
int height, width, length;
dimension(int h, int w, int l) : height(h), width(w), length(l) {
}
};
PVecDim getModList(PVecDim inList) {
PVecDim modList(new VecDim());
VecDimIter it;
for(it = inList->begin(); it!=inList->end(); ++it) {
dimension rot1((*it)->length, (*it)->width, (*it)->height);
dimension rot2((*it)->width, (*it)->height, (*it)->length);
cout<<"rot1 "<<rot1.height<<" "<<rot1.length<<" "<<rot1.width<<endl;
cout<<"rot2 "<<rot2.height<<" "<<rot2.length<<" "<<rot2.width<<endl;
modList->push_back(*it);
modList->push_back(&rot1);
modList->push_back(&rot2);
for(int i=0;i < 3;++i) {
cout<<(*modList)[i]->height<<" "<<(*modList)[i]->length<<" "<<(*modList)[i]->width<<" "<<endl;
}
}
return modList;
}
What I see is that the values rot1 and rot2 actually overwrite previous values.
For example that cout statement prints as below for input values defined at top. Can someone tell me why are these values being overwritten?
rot1 7 4 6
rot2 6 7 4
4 7 6
7 4 6
6 7 4
rot1 3 1 2
rot2 2 3 1
4 7 6
3 1 2
2 3 1
You are storing pointers to local variables when you do this kind of thing:
modList->push_back(&rot1);
These get invalidated every loop cycle. You could save yourself a lot of trouble by not storing pointers in the first place.