matrix blocking gives a segmentation fault - c++

I am trying to implement the Strassen algorithm in C++. I want to partition the square matrix 'hA' into 4 equal blocks.
// Initialize matrices on the host
float hA[N][N],ha11[N / 2][N / 2], ha12[N / 2][N / 2], ha21[N / 2][N / 2],
ha22[N / 2][N / 2];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
hA[i][j] = i;
//hB[i][j] = i;
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("\n%d,%d\n", i, j);
if (i < N / 2 & j < N / 2) {
ha11[i][j] = hA[i][j];
} else if (i < N / 2 & j >= N / 2) {
ha12[i][j] = hA[i][j];
} else if (i >= N / 2 & j < N / 2) {
ha21[i][j] = hA[i][j];
} else if (i >= N / 2 & j >= N / 2) {
ha22[i][j] = hA[i][j]; //faulty!
}
}
}
I used above method for partitioning and it gets faulty as shown in the output below. But it works fine when I remove the last comparison in the 'if else' ladder.
Why does 'i' have a wrong value that is even outside the loop condition? Is there a more convenient way to do the partitioning than this way?

To work with code as written, your sub arrays need to be NxN each, not N/2 by N/2, but I dont think this is actually the "error".
You are chopping the array into 4 equal parts, so they should be able to be smaller than the original. That leaves with two issues.
Your assignments are wrong, h11 is fine, but h12, h21 and h22 all need adjusting like this:
ha12[i-N/2][j-N/2] = hA[i][j];
ha21[i-N/2][j] = hA[i][j];
ha22[i-N/2][j-N/2] = hA[i][j];
instead of what you have, (though keep them where that are).
btw, it may be easier to read if you removes the if statements altogether, iterating over just one quarter, but doing 4 assignments per quarter.
A second, potential issue is of course what happens when N isn't divisible by 2. You code seems to ignore this, which maybe it can. I expect you need to think about where you want the odd values to go, and make the sub arrays each large enough for teh rounded up parts.

Your arrays should be N x N, not N/2 x N/2.
Your use of the bitwise operator & is unusual but works. I mistakenly thought you need a logical and ( && ) instead. Still, for readability I'd suggest the &&. You get the short circuiting with too.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("\n%d,%d\n", i, j);
if (i < N / 2 & j < N / 2) {
ha11[i][j] = hA[i][j];
} else if (i < N / 2 & j >= N / 2) {
ha12[i][j] = hA[i][j];
} else if (i >= N / 2 & j < N / 2) {
ha21[i][j] = hA[i][j];
} else if (i >= N / 2 & j >= N / 2) {
ha22[i][j] = hA[i][j]; //faulty!
}
}
}

Related

Symmetric matrix, value into c++ vector

I am trying to solve the following problem. Let's say I have a symmetric matrix with size n. I want to take all the "important values", and store them into a vector. Let me give an example to explain it better.
Let's say I have the following matrix A = [1, 2, 3 // 2, 5, 6 // 3, 6, 9]. I want to define vector of size n*(n+1)/2 such that:
V = [A(0,0), A(0,1), A(0,2), A(1,1), A(1,2), A(2,2) ]
I want to find a function that receives as input two integer i and j, and outputs the corresponding value of the matrix. The catch is that I do not want to access the matrix directly, instead I want to access the vector.
This is my reasoning so far. If I have an input with j < i, I just swap them since the matrix is symmetric. If I have that i == 0, the position in the array is just j. If that is not the case, I think I need to do something like this. (n is the dimension of the matrix, and position is the integer that I need when for the array.)
int position = 0;
for(int k = 0; k < i; k++){
position = position + (n-k);
}
position = position + j % i;
However, this code fails. I think I'm close to the solution but I am missing something. Any help?
The last j % i should be j - i.
In addition, the loop is essentially doing
position = n + (n - 1) + ... + (n - i + 1);
which can be simplified to
position = (n * 2 - i + 1) * i / 2;
So you can simply write
position = (n * 2 - i + 1) * i / 2 + j - i;
or
position = (n * 2 - i - 1) * i / 2 + j;
You can do simply this:
int myvector[matrix.size()];
int pos = 0;
for(int i = 0; i < matrix.size(); i++){
for(int j = 0; j < matrix.size(); j++){
if(j > i) myvector[pos++] = matrix[i][j];
else myvector[pos++] = matrix[j][i];
}
}

General formula for pairing members of array?

Hello guys I am having the following problem:
I have an array with a lenght that is a multiple of 4 e.g:
{1,2,3,4,5,6,7,8}
I want to know how can i get the numbers in the following pairs: {1,4},{2,3},{5,8},{6,7}.....(etc)
Suppose i loop through them and i want to get the index of the pair member from my current index
int myarr[8]={1,2,3,4,5,6,7,8};
for(int i=0;i<8;i++)
**j= func(i)**
I have thought of something like this:
f(1)=4
f(4)=1
and i would be taking: **f(i)=a * i + b** (i think a linear function is enough) It would result: f(i)=j=-i+5 .How can i generalise this for more then 4 members? What do you do in cases where you need a general formula for pairing elements?
Basically, if i is odd j would be i+3, otherwise j = i+1;
int func(int i) {
if(i%2 != 0)
return i+3;
else
return i+1;
}
This will generate
func(1) = 4, func(2) = 3, func(5) = 8, func(6) = 7 // {1,4},{2,3},{5,8},{6,7}.
You could do it as follows by keeping the incremental iteration but use a function depending on the current block and the remainder as follows.
int myarr[8]={1,2,3,4,5,6,7,8};
int Successor(int i)
{
int BlockStart = i / 4;
int Remainder = i % 4;
int j = 0;
if ( Remainder == 0 )
j = 0;
else if ( Remainder == 1 )
j = 3;
else if ( Remainder == 2 )
j = 1;
else if ( Remainder == 3 )
j = 2
return BlockStart + j;
}
for(int i = 0; i < 8; i++)
{
j = f(i);
// usage of the index
}
About the generalization, this should do it:
auto pairs(const vector<int>& in, int groupLength = 4) {
vector<pair<int, int>> result;
int groups = in.size() / groupLength;
for (int group = 0; group < groups; ++group) {
int i = group * groupLength;
int j = i + groupLength - 1;
while (i < j) {
result.emplace_back(in[i++], in[j--]);
}
}
return result;
}
You can run this code online.
If you are just looking for a formula to calculate the indices, then in general case it's:
int f(int i, int k = 4) {
return i + k - 2 * (i % k) - 1;
}
Turns out your special case (size 4) is sequence A004444 in OEIS.
In general you have "nimsum n + (size-1)".

How to turn equation with decrementing indexing into math equation with summation?

Similar to this question: Turn while loop into math equation?, I have the following nested loop that I am trying to convert into a math equation as I need to write this up in a format that doesn't look like code. I believe I am going to need some type of summation equation.
Here is the code:
int num = 0;
for (int i = nr - 1; i >= 0; i--) {
for (int j = nc - 1; j >= 0; j--) {
ela[i][j] = num;
eha[i][j] = num + ea[i][j] - 1;
num += ea[i][j];
}
}
I know that summations start from a lower bound and continue to a higher bound, so I'm not quite sure how to apply a summation here since I start from a higher index and continue to a lower index.
I'm not sure why I'm getting downvoted, as the question I referenced is very similar to mine, has the same tags and is upvoted 14 times. Please comment below if I can improve my question somehow.
Update:
I was able to update the formula as follows:
nr = 50;
nc = 10;
num = sum[ea[i,j],i=0,nr-1,j=0,nc-1]; // correct based upon nr, nc and ea
for (int i = 0; i < nr; i) {
for (int j = 0; j < nc; j++) {
num = num - ea[i,j];
ela[i][j] = num;
eha[i][j] = num + ea[i,j] - 1;
}
}
If I am right, you can transcribe the effect as
You can describe this as the matrix ela being a 2D suffix sum of the matrix ea (for every element, sum of the elements that follow in the lexicographical ordering), while eha is the sum of matrices ela and ea minus all ones.
If the problem is just with how to express the sum when you're looping the other direction, you can change your code to:
int num = 0;
for (int i = 0; i < nr; i++) {
for (int j = 0; j < nc; j++) {
ela[nr - i][nc - j] = num;
eha[nr - i][nc - i] = num + ea[nr - i][nc - j] - 1;
num += ea[nr - i][nc - j];
}
}
I'm not saying you have to change your code to this, but from here it should be more obvious how to change this to use summation notation.
It's hard to tell without any context, but the code in question becomes more intelligible if you think of the arrays as vectors enumerating the elements in reverse order, row-major. The code below is functionally equivalent to the original one posted, but arguably easier to follow.
// n.b. ela[nr - 1 - i][nc - 1 - j] == rela(nc * i + j);
int &rela(int k) { return ela[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &reha(int k) { return elh[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &rea(int k) { return ea[nr - 1 - k / nc][nc - 1 - k % nc]; }
for (int k = 0, sum = 0; k < nr * nc - 1; k++) {
rela(k) = sum;
sum += rea(k);
reha(k) = sum - 1;
}
In plain English, rela(k) is the partial sum of rea elements 0 ... k-1 and reha(k) is one less than the partial sum of rea elements 0 ... k (also, rela(k) == reha(k - 1) + 1 for k > 0).
Technically, this description could be translated back in terms of the 2d arrays, but it becomes rather messy quickly.

Why is this Segfault Occuring?

So I've traced the segfault to the line, but I don't understand why this is a segfault. Can someone elaborate on the error of my ways?
Here are the variable declarations.
size_t i, j, n, m, chunk_size, pixel_size;
i = j = n = m = 0;
chunk_size = 256;
pixel_size = 4;
Here are the array declarations.
uint8_t** values = new uint8_t*[chunk_size];
for (i = 0; i < chunk_size; ++ i)
values[i] = new uint8_t[chunk_size];
float** a1 = new float*[chunk_size];
for (i = 0; i < chunk_size; ++i)
a1[i] = new float[chunk_size];
And here is where the segfault occurs.
float delta, d;
for (i = 0; i < 256; ++i) {
for (j = n = m = d = 0; j < 256; j = m) {
while (i == 0 || d != 0) {
d = a1[i][m]; <------SEGFAULT per GDB
++m;
}
delta = (d - a1[i][j]) / m;
n = j + 1;
while (n < j + m) {
a1[i][n] = a1[i][n - 1] + delta;
++n;
}
}
}
I'm fairly new to C++ and can't figure out why this would be a segfault. Is this not the proper way to set a variables value to a variable in an array? Is that the source of my segfault?
Note: The point of this whole thing is too expand a 4x4 array to a 256x256 array with my simpleton interpolation formula.
while (i == 0 || d != 0) {
d = a1[i][m]; <------SEGFAULT per GDB
++m;
}
This is an endless while loop, in some cases (e.g. in the first iteration of the outer loop).
Your outer loop starts out with i = 0 and the inner loops starts with d = 0 and the logic controlling the while loop is not sufficient (see code comment).
for (i = 0; i < 256; ++i) {
for (j = n = m = d = 0; j < 256; j = m) {
// Here i == 0 is ALWAYS true (so d != 0 is ignored due to
// short-circuit evaluation) and then 'm' is continuously incremented
// until it goes out of bounds
while (i == 0 || d != 0) {
d = a1[i][m]; <------SEGFAULT per GDB
++m;
}
delta = (d - a1[i][j]) / m;
n = j + 1;
while (n < j + m) {
a1[i][n] = a1[i][n - 1] + delta;
++n;
}
}
The problem is in the following lines :
while (i == 0 || d != 0) {
d = a1[i][m]; <------SEGFAULT per GDB
++m;
}
Your while loop will keep on going while i equals 0. Since you never increment i in your while loop, m keeps on incrementing forever until arriving out of bounds, causing the segfault issue that you are having.
Make sure you check the values of i and m, so that they are in the allocated memory range and your code will work.

Divide array integer 2 even sums

I am finding hard to solve this programming problem. I am required to take an array of integers that can be of size N, anywhere from 2 <= N <= 30. I need to divide the array into two smaller arrays whose sums are equal, and if they are not equal, they need to be as close as possible to the same value. I would guess that using some sort of recursive function would be ideal in this situation, but if not, a dynamically programmed solution would work just as well.
I guess you can review wikipedia article on Partition problem. It provides a pseudocode of pseudopolynomial algorithm in c# which you can rather easily convert into c++:
public static bool BalancePartition(int[] S)
{
int n = S.Length;
int N = S.Sum();
bool[,] P = new bool[N / 2 + 1, n + 1];
for (int i = 0; i < n + 1; i++)
P[0, i] = true;
for (int i = 1; i <= N / 2; i++)
for (int j = 1; j <= n; j++)
if (S[j - 1] <= i)
P[i, j] = P[i, j - 1] || P[i - S[j - 1], j - 1];
else
P[i, j] = P[i, j - 1];
return P[N / 2, n];
}