Matrix vector multiplication CCS c++ - c++

I am trying to multiply a matrix and a vector with the matrix in Compressed Column Storage. The matrix is :
0 3 0
4 0 0
2 0 0
here is the CCS form:
[ 4 2 3 ]
[ 2 3 1 ]
[ 1 3 4 4 ]
The vector is:
[ 1 3 4 ]
So the product should be
[ 9 4 2 ]
Here is the function I am trying to create
vector<int> multiply(vector<int> val,vector<int> col,vector<int> row,vector<int> v, int r){
vector<int> x(v.size());
for (int j=0; j<r; j++) {
for (int i=col[j]-1; i<col[j+1]-1; i++) {
cout<<"\n"<<val[i]<<"*"<<v[j]<<"\n";
x[j]+= val[i]*v[j];
}
}
return x;
}
But this returns
[ 6 9 0 ]
This is the closest I've gotten to the real solution, how can I fix this?

I would think about this as driven by the col_ptr vector.
1.) I wasn't sure what value(s) r could take, so I removed it, as we don't need that information to solve the problem
2.) I should note that I have not compiled this, but I believe the algorithm is correct
3.) There are some obvious ways to optimize the memory usage of this code, but I left those variables in to help explain the process.
4.) The main problem with the code you posted is that it doesn't seem to use the row array to tell us which row the value is in!
vector<int> multiply(vector<int> val,vector<int> col,vector<int> row,vector<int> v) {
vector<int> x(v.size());
//we may need to initialize x as all zeroes, I forget
int col_size = col.size();
int column_idx = 0;
for (int j=0; j<col_size-1; j++) {
//j indicates where the columns start going!
//columns end prior to the next column start
//val_index is where we need to start in the val array, for this column
int val_index_start = col[j]-1; //this is redunda
//we keep traversing forward until the next column starts
int next_column_start = col[j+1]-1;
for (int k=val_index_start; k < next_column_start && k < v.size(); k++) {
int row_of_cell = row[k] - 1;
int column_of_cell = column_idx;
int product = v[column_idx]*val[k];
x[row_of_cell] += product;
}
column_idx++;
}
return x;
}

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());

How to sort elements from a 2D array above the main diagonal [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Without any use of in-built functions, libraries or pointers how can I sort elements from an 2D array above the main diagonal.
I really couldn't find any explanation or on other sites. I tried to change the 2D array into a 1D array and then sort but couldn't find the logic behind the code.
For example in a 4x4 array:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
To print:
1 12 8 7
5 6 4 3
9 10 11 2
13 14 15 16
Without getting into the details of actually writing the algorithm, here's an example of an approach to breaking down and solving this problem:
Iterate through the 2D array and figure out which values are 'above' the main diagonal. Store these values in a data structure (probably a 1D array)
Sort that resulting array (I'm assuming you have learned how to sort an array, but let me know if this step is a problem)
Build a new 2D array using these sorted elements, and find a way to put the sorted elements back into the correct spot, with everything on and below the main diagonal maintaining their old spots. (hint: is there a map from sorted element index to where on the upper diagonal of the 2D array it would go?)
Hopefully this will help you writing this algorithm! Let me know if I misunderstood something about the problem or if you have questions.
I have used 4 loops. The inner 2 loops find max element, the outer 2 loops place the maximum element to the convenient cell.
#include <stdio.h>
typedef enum {
false = 0,
true = 1
}bool;
int x[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
bool change = false;
int main()
{
int a , b;
for(int k = 0 ; k < 4; k++){
for(int l = k + 1; l < 4 ; l++){
int max = x[k][l];
for(int m = k; m < 4; m++){
for(int n = l; n < 4; n++){
if(x[m][n] > max){
max = x[m][n];
a = m;
b = n;
change = true;
}
}
}
if(change)
{
x[a][b] = x[k][l];
x[k][l] = max;
change = false;
}
}
}
for (int o = 0; o < 4 ; o++){
for(int u = 0; u < 4; u++){
printf("%d ",x[o][u]);
}
printf("\n");
}
return 0;
}

C++ errors and questions

Pictures of the code and errors:
https://puu.sh/sPat1/da5b011ac6.png
https://puu.sh/sPavZ/ad81dc6386.png
Questions : This is a program that generates 600 numbers from 1 to 49 , 3 times. 1800 numbers total. How can I check through all the numbers I mean how many times 1 is included, 2 ,3 ,4 ,5 ,6 . . . 48, 49.. <- IN ONLY ONE OF THE ARRAYS a[100][6] for example. Please help.
You can create another array/vector with indexes from [0..49] and increment the desired index every time you meet a value in an original array:
int arr[100][6];
//fill it
int check[50];
for(int i = 0; i < 50; i++)
check[i] = 0;
for(int i = 0; i < 100; i++)
for(int j = 0; j < 6; j++)
check[arr[i][j]]++;
//now check has a list of occurences for 0, 1, 2, ..., 49
As for code style, I would suggest to go away from magic constants like 100, 50, and use something like
const int max_random = 50;
const int mat_width = 100;
const int mat_height = 6;
Also, for C++ the usage of std::vector is encouraged instead of usual arrays - STL is created just for the purpose of leaving most of the pointers/low-level operations under the hood.

Interesting algorithm to compare two matrices?

I have a problem, basically, I have two matrices (vectors), one massive matrix and a smaller matrix. I have an algorithm that splits the massive matrix into blocks (of the size of the small block)
So for example (I am using test data here) so the massive matrix size is: 4x4 and the small matrix is 2x2 and then I pass the particular block (at the current position) to a function that checks to see if the small matrix is equal to the massive block (at that particular position) if it is, then returns true otherwise returns false.
I can output each block like this:
bool compareMatrix(vector<double> &theMatrix1, vector<double> &theMatrix2, int startRow, int startCol)
{
// I can output the matrix blocks like this:
cout << theMatrix1[startRow*2+startCol] << endl;
}
But I don't quite understand how I would compare the block (at the startingRow/Col) to the small matrix..
How it would is this:
Matrix 1: (4x4)
0 1 0 1
1 1 0 1
0 0 1 1
0 1 1 1
Matrix 2: (2x2)
0 1
0 1
I then split the blocks into 2x2:
B1 =
0 1
1 1
is B1 equal to theMatrix2 - No so return false
B2 =
0 1
0 1
is B2 equal to theMatrix2 - Yes so return true
I have really tried to explain things to the best of detail as I possibly can and hope someone can give me some advice because I've been working on it for so long now!
Thanks
If the size of the big matrix is known you can compare small parts of it with your 2x2 matrix like so
int bigMatrixSize=4;
bool compare(...)
{
for (int i=0; i<2; ++i)
for (int k=0; k<2; ++k)
if(bigMatrix[k+startX+(i+staryY)*bigMatrixSize] != smallMatrix[k][i])
return false;
return true;
}
I left out bounds checking and some other stuff, but It should give you an idea.
bool compareMatrix(vector<double> &theMatrix1, int nRow1, int nCol1, vector<double> &theMatrix2, int nRow2, int nCol2, int startRow, int startCol)
{
int p1 = startRow * nCol1 + startCol, p2 = 0;
for (int y = 0; y < nRow2; ++y)
{
for (int x = 0; x < nCol2; ++x)
{
if (theMatrix1[p1 + x] != theMattrix2[p2 + x]) // You can use memcmp here, but it's safer let compiler do the optimization.
{
return false;
}
}
p1 += nCol1;
p2 += nCol2;
}
return true;
}
You want something like this? You can add the columns count to the position to reach the next row.

diagonally reflect a matrix

I'm not sure if this question has been either asked
or quite possibly already answered. If I start with
an original 3x3 matrix:
1 2 3
4 5 6
7 8 9
, how would I produce the following 3x3 matrix:
9 6 3
8 5 2
7 4 1
??
For an N*N square matrix :
for(int i=0;i<n-1;i++)
for(int j=0;j<n-1-i;j++) //Swap elements above anti-diagonal
std::swap(mat[i][j],mat[n-1-j][n-1-i]); //with elements below it
Since you're trying to reflect about the secondary diagonal (that's NOT transposition), here's the code, a slightly modified copy of Peter's:
for (int i = 0; i < n; i++)
{
for (int j = 0; j < i; j++)
{
int temp = a[i][j];
a[i][j] = a[n - 1 - j][n - 1 - i];
a[n - 1 - j][n - 1 - i] = temp;
}
}
For a reflection, pairs of items in the matrix are swapped, so the "do something" (within the loops) will be a swap operation. Loops will be used to pick an item to swap, and some basic arithmetic is used to choose which item to swap it with. The loops should iterate over the triangle of items that are one side of the axis to reflect around, excluding those on the reflection axis and on the other side of it. To visualise that...
0 1 2
0 * * /
1 * / .
2 / . .
The asterisks are the items to use as first parameters for the swap. The dots are the items to use as second parameters to the swap. The slashes are on the reflection axis.
Therefore...
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < (n-1)-i; j++) // Thanks to Bugaboo for bugfix
{
std::swap (a[i][j], a[2-j][2-i]);
}
}
With a 3x3 matrix, the loops are a bit excessive - they are shown here for the principle, and to show how to extend it. There are only three asterisks in that visualisation, and only three swap operations needed...
std::swap (a[0][0], a[2][2]);
std::swap (a[0][1], a[1][2]);
std::swap (a[1][0], a[2][1]);
I think I found a way in the MatLab that combines a series of other existing flipping method.
fliplr (flip left and right)
transpose
fliplr
Ham is the target then the code is the following.
Maybe it is wrong, but let me know.
fliplr(fliplr(Ham)')