Writing MATLAB arrays in C/C++ - c++

The MATLAB code samples part of background of an grayscale image by creating a cell array that is backgroundSample{1}, backgroundSample{2}, ... , backgroundSample{9}. Here halfRows and halfCols is the half size of the image.
Since backgroundSample is an array that contains nine 2-D matrices. It confused me that how to write this code in C/C++. Can I get the elements of backgroundSample{i} using something like backgroundSample[i].elements[m][n]?
MATLAB code:
offset = [-60, -20, 20, 60];
for i = 1: 1: 3
for j = 1: 1: 3
backgroundSample{(i - 1) * 3 + j} =
background(halfRows + offset(i): halfRows + offset(i + 1), ...
halfCols + offset(j): halfCols + offset(j + 1));
end;
end;
EDIT:
As we can assign a matrix simply by A = B in MATLAB. For an example, backgroundSample{1} = background(60: 100, 60: 100) in my question and this assignment is in the loops of i: 1→3 and j: 1→3. However, when assigning a matrix in C/C++, it should assign every element one by one. Maybe like this:
for(int i = 0; i < 3; i++)
for(int j = 0; n < 3; j++)
// to get every elements
for(int m = 0 ...)
for(int n = 0 ...)
// not sure whether there is such usage of "->" in array
backgroundSample[(i - 1) * 3 + j]->elements[m][n] = background[i iteration][j iteration]
So there are conflicts between indices of matrix backgroundSample[m][n] and background[i][j]. How to resolve the issue?

The simplest way to implement what you're describing is to declare a multidimensional array:
int backgroundSample[9][3][3];
where the dimensions of each 2-D matrix is assumed to be 3×3. To access the (m, n) element in the k-th matrix, you write backgroundSample[k][m][n], e.g:
for (int m = 0; m < 3; ++m)
{
for(int n = 0; n < 3; ++n)
{
backgroundSample[(i - 1) * 3 + j][m][n] = background[i][j];
}
}
Alternatively, if each sample in this array stores more information, you can declare a structure:
typedef struct
{
int elements[3][3];
// More fields...
} TSample;
and then create an array of these:
TSample backgroundSample[9];
To access an element you would write backgroundSample[k].elements[m][n].
There's also the possibility of allocating the memory dynamically (during runtime, meaning that you don't know how much of these structures you have in advance):
TSample* backgroundSample;
In C++ the actual process of memory allocation would look like this:
backgroundSample = new TSample[9];
Accessing an element would be done by writing backgroundSample[k]->elements[m][n]. Notice the array operator -> which accesses the field elements by dereferencing the pointer backgroundSample[k].
Note: each call to new needs to be accompanied by a matching call to delete when done in order to release the memory, i.e:
delete[] backgroundSample;
Hope that helps!

Related

Construct mirror vector around the centre element in c++

I have a for-loop that is constructing a vector with 101 elements, using (let's call it equation 1) for the first half of the vector, with the centre element using equation 2, and the latter half being a mirror of the first half.
Like so,
double fc = 0.25
const double PI = 3.1415926
// initialise vectors
int M = 50;
int N = 101;
std::vector<double> fltr;
fltr.resize(N);
std::vector<int> mArr;
mArr.resize(N);
// Creating vector mArr of 101 elements, going from -50 to +50
int count;
for(count = 0; count < N; count++)
mArr[count] = count - M;
// using these elements, enter in to equations to form vector 'fltr'
int n;
for(n = 0; n < M+1; n++)
// for elements 0 to 50 --> use equation 1
fltr[n] = (sin((fc*mArr[n])-M))/((mArr[n]-M)*PI);
// for element 51 --> use equation 2
fltr[M] = fc/PI;
This part of the code works fine and does what I expect, but for elements 52 to 101, I would like to mirror around element 51 (the output value using equation)
For a basic example;
1 2 3 4 5 6 0.2 6 5 4 3 2 1
This is what I have so far, but it just outputs 0's as the elements:
for(n = N; n > M; n--){
for(i = 0; n < M+1; i++)
fltr[n] = fltr[i];
}
I feel like there is an easier way to mirror part of a vector but I'm not sure how.
I would expect the values to plot like this:
After you have inserted the middle element, you can get a reverse iterator to the mid point and copy that range back into the vector through std::back_inserter. The vector is named vec in the example.
auto rbeg = vec.rbegin(), rend = vec.rend();
++rbeg;
copy(rbeg, rend, back_inserter(vec));
Lets look at your code:
for(n = N; n > M; n--)
for(i = 0; n < M+1; i++)
fltr[n] = fltr[i];
And lets make things shorter, N = 5, M = 3,
array is 1 2 3 0 0 and should become 1 2 3 2 1
We start your first outer loop with n = 3, pointing us to the first zero. Then, in the inner loop, we set i to 0 and call fltr[3] = fltr[0], leaving us with the array as
1 2 3 1 0
We could now continue, but it should be obvious that this first assignment was useless.
With this I want to give you a simple way how to go through your code and see what it actually does. You clearly had something different in mind. What should be clear is that we do need to assign every part of the second half once.
What your code does is for each value of n to change the value of fltr[n] M times, ending with setting it to fltr[M] in any case, regardless of what value n has. The result should be that all values in the second half of the array are now the same as the center, in my example it ends with
1 2 3 3 3
Note that there is also a direct error: starting with n = N and then accessing fltr[n]. N is out of bounds for an arry of size N.
To give you a very simple working solution:
for(int i=0; i<M; i++)
{
fltr[N-i-1] = fltr[i];
}
N-i-1 is the mirrored address of i (i = 0 -> N-i-1 = 101-0-1 = 100, last valid address in an array with 101 entries).
Now, I saw several guys answering with a more elaborate code, but I thought that as a beginner, it might be beneficial for you to do this in a very simple manner.
Other than that, as #Pzc already said in the comments, you could do this assignment in the loop where the data is generated.
Another thing, with your code
for(n = 0; n < M+1; n++)
// for elements 0 to 50 --> use equation 1
fltr[n] = (sin((fc*mArr[n])-M))/((mArr[n]-M)*PI);
// for element 51 --> use equation 2
fltr[M] = fc/PI;
I have two issues:
First, the indentation makes it look like fltr[M]=.. would be in the loop. Don't do that, not even if this should have been a mistake when you wrote the question and is not like this in the code. This will lead to errors in the future. Indentation is important. Using the auto-indentation of your IDE is an easy way to go. And try to use brackets, even if it is only one command.
Second, n < M+1 as a condition includes the center. The center is located at adress 50, and 50 < 50+1. You haven't seen any problem as after the loop you overwrite it, but in a different situation, this can easily produce errors.
There are other small things I'd change, and I recommend that, when your code works, you post it on CodeReview.
Let's use std::iota, std::transform, and std::copy instead of raw loops:
const double fc = 0.25;
constexpr double PI = 3.1415926;
const std::size_t M = 50;
const std::size_t N = 2 * M + 1;
std::vector<double> mArr(M);
std::iota(mArr.rbegin(), mArr.rend(), 1.); // = [M, M - 1, ..., 1]
const auto fn = [=](double m) { return std::sin((fc * m) + M) / ((m + M) * PI); };
std::vector<double> fltr(N);
std::transform(mArr.begin(), mArr.end(), fltr.begin(), fn);
fltr[M] = fc / PI;
std::copy(fltr.begin(), fltr.begin() + M, fltr.rbegin());

Void value not ignored as it ought to be (Trying to assign void to non-void variable?)

vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
int row = nums.size();
int col = nums[0].size();
vector<vector<int>> newNums;
if((row*col) < (r*c)){
return nums;
}
else{
deque<int> storage;
for(int i = 0; i < row; i++){
for(int k = 0; k < col; k++){
storage.push_back(nums[i][k]);
}
}
for(int j = 0; j < r; j++){
for(int l = 0; l < c; l++){
newNums[j][l] = storage.pop_front();
}
}
}
return newNums;
}
Hey guys, I am having a problem where I am getting the said error of the title above 'Void value not ignored as it ought to be'. When I looked up the error message, the tips stated "This is a GCC error message that means the return-value of a function is 'void', but that you are trying to assign it to a non-void variable. You aren't allowed to assign void to integers, or any other type." After reading this, I assumed my deque was not being populated; however, I can not find out why my deque is not being populated. If you guys would like to know the problem I am trying to solve, I will be posting it below. Also, I cannot run this through a debugger since it will not compile :(. Thanks in advance.
In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new one with different size but keep its original data.
You're given a matrix represented by a two-dimensional array, and two positive integers r and c representing the row number and column number of the wanted reshaped matrix, respectively.
The reshaped matrix need to be filled with all the elements of the original matrix in the same row-traversing order as they were.
If the 'reshape' operation with given parameters is possible and legal, output the new reshaped matrix; Otherwise, output the original matrix.
Example 1:
Input:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
Output:
[[1,2,3,4]]
Explanation:
The row-traversing of nums is [1,2,3,4]. The new reshaped matrix is a 1 * 4 matrix, fill it row by row by using the previous list.
This line has two problems:
newNums[j][l] = storage.pop_front();
First, pop_front() doesn't return the element that was popped. To get the first element of the deque, use storage[0]. Then call pop_front() to remove it.
You also can't assign to newNums[j][i], because you haven't allocated those elements of the vectors. You can pre-allocate all the memory by declaring it like this.
vector<vector<int>> newNums(r, vector<int>(c));
So the above line should be replaced with:
newNums[j][l] = storage[0];
storage.pop_front();

Efficiently inserting column/row into a matrix stored in row/col-major vector in-place

It's not hard to efficiently insert row or column into a matrix stored in a row-
or col-major (respectively) vector. The problem of inserting row into a col-major vector or column into a row-major vector is slightly more interesting.
For example, given a 2x3 matrix stored in row-major in vector:
1 2 3 <=> 1 2 3 4 5 6
4 5 6
and a column 7 8 that is inserted before after column 1 in the original matrix, we get:
1 7 2 3 <=> 1 7 2 3 4 8 5 6
4 8 5 6
[Inserting a row into a col-major vector is similar.]
The sample setup in C++:
auto m = 2; // #rows
auto n = 3; // #cols
// row-major vector
auto x = std::vector<double>{1,2,3,4,5,6};
auto const colIndex = 1;
auto const col = std::vector<double>{7,8};
// insert column {7,8} into the 2nd position
// =>{1,7,2,3,4,8,5,6}
There could be various options to achieve this algorithmically and in C++, but we're looking for the efficiency and scalability to large matrices and multiple inserts.
The first obvious option that I can think of is to use std::vector<double>::insert to insert new elements to the correct positions:
//option 1: insert in-place
x.reserve(m*(n+1));
for(auto i = 0; i < col.size(); i++)
x.insert(begin(x) + colIndex + i * (n + 1), col[i]);
, which is valid but extremely slow even for moderate data sizes because of the resizing and shifting on each iteration.
Another, more direct option is to create another vector, populate all the columns in the ranges [0,colIndex),colIndex,(colIndex,n+1], and swap it with the original vector:
// option 2: temp vec and swap
{
auto tmp = std::vector<double>(m*(n+1));
for(auto i = 0; i < m; i++)
{
for(auto j = 0; j < colIndex; j++)
tmp[j + i * (n + 1)] = x[j + i * n];
tmp[colIndex + i * (n + 1)] = col[i];
for(auto j = colIndex + 1; j < n + 1; j++)
tmp[j + i * (n + 1)] = x[(j - 1) + i * n];
}
std::swap(tmp, x);
};
This is much faster than the option 1, but requires extra space for the matrix copy and iterating over all elements.
Are there any other ways to achieve this that would beat the above in speed/space or both?
Example code on ideone: https://ideone.com/iXrPfF
This version is likely to be much faster, especially at scale, and could be the basis for further micro-optimization (if [and only if] really necessary):
// one-time reallocation of the vector to get space for the new column
x.resize(x.size() + col.size());
// we'll start shifting elements over from the right
double *from = &x[m * n];
const double *src = &col[m];
double *to = from + m;
size_t R = n - colIndex; // number of cols left of the insert
size_t L = colIndex; // number of cols right of the insert
while (to != &x[0]) {
for (size_t i = 0; i < R; ++i) *(--to) = *(--from);
*(--to) = *(--src); // insert value from new column
for (size_t i = 0; i < L; ++i) *(--to) = *(--from);
}
ideone
This doesn't require any temporary allocation and aside from possible micro-optimizations of the loop it's probably about as fast as it gets. To understand how it works, we can start by observing that the bottom-right element of the original matrix is being shifted m elements to the right in the source vector. Working backwards from the last element, at some point a value from the inserted column vector gets inserted, and subsequent elements from the source vector are now shifted m - 1 only elements to the right. Using that logic we simply construct a 3-phase loop that works from right to left on the source array. The loop iterates m times, once for each row. The three phases of the loop, corresponding to its three lines of code, are:
Shift row elements that are "to the right" of the insertion point.
Insert the row value from the new column.
Shift row elements that are "to the left" of the insertion point (shifting one less place than in phase 1).
There's also serious room for improvement in the naming of the variables, and the algorithm should certainly be encapsulated in its own function with proper input parameters. One possible signature would be:
void insert_column(std::vector<double>& matrix,
size_t rows, size_t columns, size_t insertBefore,
const std::vector<double>& column);
From here there's further room for improvement in making it generic using templates.
And from there, you might observe that the algorithm has possible application beyond matrices. What's really happening is that you're "zippering" two vectors together with a skip and an offset (i.e., starting at element i, insert an element from B into A after every n'th element).
so what I would go with is something like (completely untested (tm))
x.resize(x.size() + col.size());
for (size_t processed = 0; processed < col.size(); ++processed) {
// shift the elements for row n (starting at the end)
// to their new location
auto start = x.end()-(processed+1) * rowSize;
auto end = start + rowSize;
auto middle = end - (col.size()-processed);
std::rotate(start, middle, end);
// replace one of the default value items to be the new value
x[x.size()- rowSize*(1+processed)] = col[col.size()-processed-1];
}
The idea being that you go from
[1,2,3,4,5,6] & adding [a,b,c]
Resize:
[1,2,3,4,5,6,x,x,x]
First loop shift:
[1,2,3,4,x,x,x,5,6]
First loop replace
[1,2,3,4,x,x,c,5,6]
Second loop shift
[1,2,x,x,3,4,c,5,6]
and so on.
Since std::rotate is linear, and each item only ever gets moved once; this should also be linear.
This differs to your option #1 in that every time you inserted, you have to move everything afterwards; meaning that the last x elements are shifted col.size() times.
An alternate solution can be transpose followed by insertion and transpose again. However, the in-place transpose in non-trivial (https://en.wikipedia.org/wiki/In-place_matrix_transposition). See the implementation here https://stackoverflow.com/a/9320349

Implementing iterative autocorrelation process in C++ using for loops

I am implementing pitch tracking using an autocorrelation method in C++ but I am struggling to write the actual line of code which performs the autocorrelation.
I have an array containing a certain number ('values') of amplitude values of a pre-recorded signal, and I am performing the autocorrelation function on a set number (N) of these values.
In order to perform the autocorrelation I have taken the original array and reversed it so that point 0 = point N, point 1 = point N-1 etc, this array is called revarray
Here is what I want to do mathematically:
(array[0] * revarray[0])
(array[0] * revarray[1]) + (array[1] * revarray[0])
(array[0] * revarray[2]) + (array[1] * revarray[1]) + (array[2] * revarray[0])
(array[0] * revarray[3]) + (array[1] * revarray[2]) + (array[2] * revarray[1]) + (array[3] * revarray[0])
...and so on. This will be repeated for array[900]->array[1799] etc until autocorrelation has been performed on all of the samples in the array.
The number of times the autocorrelation is carried out is:
values / N = measurements
Here is the relevent section of my code so far
for (k = 0; k = measurements; ++k){
for (i = k*(N - 1), j = k*N; i >= 0; i--, j++){
revarray[j] = array[i];
for (a = k*N; a = k*(N - 1); ++a){
autocor[a]=0;
for (b = k*N; b = k*(N - 1); ++b){
autocor[a] += //**Here is where I'm confused**//
}
}
}
}
I know that I want to keep iteratively adding new values to autocor[a], but my problem is that the value that needs to be added to will keep changing. I've tried using an increasing count like so:
for (i = (k*N); i = k*(N-1); ++i){
autocor[i] += array[i] * revarray[i-1]
}
But I clearly know this won't work as when the new value is added to the previous autocor[i] this previous value will be incorrect, and when i=0 it will be impossible to calculate using revarray[i-1]
Any suggestions? Been struggling with this for a while now. I managed to get it working on just a single array (not taking N samples at a time) as seen here but I think using the inverted array is a much more efficient approach, I'm just struggling to implement the autocorrelation by taking sections of the entire signal.
It is not very clear to me, but I'll assume that you need to perform your iterations as many times as there are elements in that array (if it is indeed only half that much - adjust the code accordingly).
Also the N is assumed to mean the size of the array, so the index of the last element is N-1.
The loops would looks like that:
for(size_t i = 0; i < N; ++i){
autocorr[i] = 0;
for(size_t j = 0; j <= i; ++j){
const size_t idxA = j
, idxR = i - j; // direct and reverse indices in the array
autocorr[i] += array[idxA] * array[idxR];
}
}
Basically you run the outer loop as many times as there are elements in your array and for each of those iterations you run a shorter loop up to the current last index of the outer array.
All that is left to be done now is to properly calculate the indices of the array and revarray to perform the calculations and accummulate a running sum in the current outer loop's index.

Converting MatLab code - Confused

Basically, I have this final piece of code to convert from MatLab to C++.
The function takes in a 2D vector and then checks the elements of the 2D vector against 2 criteria and if not matched, it removes the blocks. But I'm confused to what the code in MatLab wants to be returned, a 2D or a 1D vector? Here is the code:
function f = strip(blocks, sumthresh, zerocrossthresh)
% This function removes leading and trailing blocks that do
% not contain sufficient energy or frequency to warrent consideration.
% Total energy is measured by summing the entire vector.
% Frequency is measured by counting the number of times 0 is crossed.
% The parameters sumthresh and zerocrossthrech are the thresholds,
% averaged across each sample, above which consideration is warrented.
% A good sumthresh would be 0.035
% A good zerocrossthresh would be 0.060
len = length(blocks);
n = sum(size(blocks)) - len;
min = n+1;
max = 0;
sumthreshtotal = len * sumthresh;
zerocrossthreshtotal = len * zerocrossthresh;
for i = 1:n
currsum = sum(abs(blocks(i,1:len)));
currzerocross = zerocross(blocks(i,1:len));
if or((currsum > sumthreshtotal),(currzerocross > zerocrossthreshtotal))
if i < min
min = i;
end
if i > max;
max = i;
end
end
end
% Uncomment these lines to see the min and max selected
% max
% min
if max > min
f = blocks(min:max,1:len);
else
f = zeros(0,0);
end
Alternatively, instead of returning another vector (whether it be 1D or 2D) might it be better to actually send the memory location of the vector and remove the blocks from it? So for example..
for(unsigned i=0; (i < theBlocks.size()); i++)
{
for(unsigned j=0; (j < theBlocks[i].size()); j++)
{
// handle theBlocks[i][kj] ....
}
}
Also, I do not understand this line:
currsum = sum(abs(blocks(i,1:len)));
Basically the: (i,1:len)
Any ideas? Thanks :)
blocks(i,1:len) is telling the array that it wants to go from blocks[i][1 to the end]. So if it was a 3x3 array it's doing something like:
blocks[i][1]
blocks[i][2]
blocks[i][3]
.
.
.
blocks[i][end]
Then it's taking the absolute value of the contents of the matrix and adding them together. It's returning a [x][x] matrix but the length is either going to be a 0x0 or of (max)X(len).