I need to implement a matrix transpose procedure in C++.
The problem is the signature, the function has to be called like this:
transpose(in_mat[0][0], n, m, out_mat[0][0])
where n and m are the dimensions.
All values are doubles, both the matrices and the dimensions.
Since the code is automatically generated, I can't fix this.
My workaround looks like this:
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer= &in_mat;
double* out_pointer= &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
It works fine.
I've constructed a test case with two matrices of different width and height. One is filled with random numbers, the other is filled with zeros. Then the transpose procedure is called and the two matrices are compared.
The functionality is correct.
But it corrupts the stack. When run in Visual Studio 2015 there is a warning
Run-Time Check Failure #2 - Stack around the variable 'in_mat' was corrupted.
What did I do wrong ? Why is the stack corrupted ?
Code after the invocation of transpose works correctly.
EDIT:
Here is the complete setup:
#include <random>
#include <iostream>
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer = &in_mat;
double* out_pointer = &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
int main()
{
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
double n = 5;
double m = 4;
transpose(in_mat[0][0], n, m, out_mat[0][0]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (in_mat[i][j] - out_mat[j][i]>0.0001) {
std::cout << "code is broken" << std::endl; //never reached
}
}
}
std::cout << "finished" << std::endl;
}
Your subscripts (or loop limits) were backwards where you initialized the matrices.
You have
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
When j==4 you are writing beyond the end of out_mat
Related
First of all, I made this class.
class Matrix
{
public:
double ele[4][4];
int numOfRow;
int numOfColumns;
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = 0;
}
Matrix(double mat[][4], int Row, int Col) {
numOfRow = Row;
numOfColumns = Col;
for (int i = 0; i < numOfRow; i++) {
for (int j = 0; i < numOfColumns; j++) {
ele[i][j] = mat[i][j];
}
}
}
Matrix Add(Matrix m) {
Matrix output;
for (int i = 0; i < numOfRow; i++) {
for (int j = 0; j < numOfColumns; j++) {
output.ele[i][j] = ele[i][j] + m.ele[i][j];
}
}
return output;
}
Matrix Subtract(Matrix m);
Matrix Multiply(Matrix m);
Matrix Transpose(void);
};
This is part of the main function. In this way, I'm going to bring up the values of the txt files that I've already made in matA and matB and replace them. It's just a process of putting numbers in.
double matA[4][4];
for (int i = 0; i < RowA; i++) {
for (int j = 0; j < ColA; j++) {
fscanf(fpInput, "%lf", &matA[i][j]);
}
}
double matB[4][4];
for (int i = 0; i < RowB; i++) {
for (int j = 0; j < ColB; j++) {
fscanf(fpInput, "%lf", &matB[i][j]);
}
}
And we substitute matrixA and matrixB class objects, respectively.
Matrix matrixA(matA, RowA, ColA);
Matrix matrixB(matB, RowB, ColB);
I tried substitute Value obtained by 'Add' function into class object called matrixO. but, The substituted values did not work smoothly. For example, if matrixA contains (1, 2, 3) in order and matrixB has (4, 5, 6), then the 'add function' requires that the array of matrixO contains (5, 7, 9), but it does not. The value of the matrixO.ele is not output at all.
Matrix matrixO = matrixA.Add(matrixB);
for (int i = 0; i < RowA; i++) {
for (int j = 0; j < ColA; j++) {
fprintf(fpOutput, "%lf ", matrixO.ele[i][j]);
printf("%lf", matrixO.ele[i][j]);
}
fprintf(fpOutput, "\n");
}
In the Matrix constructor section, I changed it like this.
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = ele[0][0];
}
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = {};
}
But both of these cases are wrong. How do we solve this issue?
You are assigning a value to your matrix out-of-bounds:
ele[4][4] = 0;
The last element of double ele[4][4]; is ele[3][3];
This is undefined behavior, so it makes no sense to analyze what happens after it.
You can 0-initialize your Matrix in its constructor like this:
Matrix(): ele(), numOfRow(), numOfColumns() {}
I am trying to copy a matrix from an old matrix class to an armadillo matrix. Unfortunately when attempting to do this with a for loop the armadillo matrix will copy the value from the old matrix to the ENTIRE column when the lowest-most element is non-zero (I am using sparse matrices). I have attached the code that is being used below. This is very simplified because I need to figure out why it is doing this first. According to the documentation this should work.
main()
{
OldMatrixClass MatrixA(size, size);
FillMatrix(MatrixA, size);
for (auto i = 0; i < size; i++)
{
for (auto j = 0; j < size; j++)
{
file << MatrixA[i][j] << "\t";
}
file << "\n";
}
arma::Mat<double> ArmaA(size, size);
ArmaA.zeros();
CopyMatrix(MatrixA, ArmaA, size);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
file << ArmaA[i,j] << "\t";
}
file << "\n";
}
}
void FillMatrix(OldMatrixClass &A, int size)
{
double num = 0.15;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (rand() % 101 < 26)
{
A[i][j] = num;
}
else
{
A[i][j] = 0;
}
}
}
}
void CopyMatrix(OldMatrixClass A, arma::Mat<double> &B, int size)
{
for (int k = 0; k < size; k++)
{
for (int j = 0; j < size; j++)
{
B[j, k] = A[j][k];
}
}
}
This is the output when I run this code... As you can see only the entire columns are altered if the last element in MatrixA column is non-zero.
Output
Is there something I'm doing wrong? Is my syntax messed up somewhere?
See the documentation:
Caveat: accessing elements via [i,j] and [i,j,k] does not work correctly in C++; instead use (i,j) and (i,j,k)
I need a function that multiply a matrix and a vector (Matrix*vector)
It takes in a matrix A and a vector B, with int describing the dimensions. Somehow it isn't running correctly. Any help??
void Multiply(double *res, double **A, double *B, int ARows, int ACols, int BRows)
{
if (ACols !=BRows)
{
return;
}
for (int i = 0; i < ACols; i++)
{
res[i] = 0;
for (int j = 0; j < BRows; j++)
{
res[i] += A[i][j]*B[j];
}
}
}
It seems you mean
for (int i = 0; i < ARows; i++)
{
res[i] = 0;
for (int j = 0; j < ACols; j++)
{
res[i] += A[i][j]*B[j];
}
}
It would be better if the function returns a boolean value that signals whether the function execution was successful for example
bool Multiply(double *res, double **A, double *B, int ARows, int ACols, int BRows)
{
bool success = ACols == BRows;
if ( success )
{
for (int i = 0; i < ARows; i++)
{
res[i] = 0;
for (int j = 0; j < ACols; j++)
{
res[i] += A[i][j]*B[j];
}
}
}
return success;
}
Instead of the manually written loops you could use the standard algorithm std::inner_product declared in the header <numeric>.
The task is as follows: Describe the class "matrix of numbers" with component data: the dimensions of the matrix, a pointer to the elements. Overload operations: << (matrix output to the screen), + (addition of matrices), unary ¬– (change the sign of each element), / = (divide each element by a number). I performed it, and performed it correctly, but you need to set the matrix dimension from the keyboard, and as you can see, it is set in advance for me [3] [3]. It sounds pretty simple, but something I'm really dumb. Thanks in advance for your help. Here is the code:
#include "pch.h"
#include <iostream>
using namespace std;
class Matrix
{
public:
Matrix()
{
int Table[3][3];
}
int Table[3][3];
void Create()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
Table[i][j] = 10;
}
};
ostream& operator <<(ostream& t, Matrix a)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
t << a.Table[i][j] << " ";
t << "\n";
}
return t;
}
Matrix& operator /=(Matrix& a, int num)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] /= num;
return a;
}
Matrix& operator -(Matrix& a, int empty)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] = -a.Table[i][j];
return a;
}
Matrix& operator +(Matrix& a, Matrix b)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
int main()
{
int u;
setlocale(LC_ALL, "Russian");
Matrix Example;
Example.Create();
Matrix Example1;
Example1.Create();
cout << Example;
cout << Example1;
cout << "Сумма матриц: "<<endl;
cout << Example + Example1;
Example - 1;
Example1 - 1;
cout<< Example + Example1;
cout << "На сколько вы хотите её поделить?\n";
cin >> u;
Example /= u;
Example1 /= u;
cout << Example;
cout << Example1;
}`
You need to dynamically create the matrix.
In order to this you need to use pointers(*). Change int table[3][3]
double table**;
An example of how it could be implemented (note that I use matrix instead of table)
class Matrix {
private:
double** matrix;
int col;
int row;
public:
Matrix(){};
void Create(int row, int col);
};
void Matrix::Create(int row_, int col_){
double val = 0.0;
col = col_; // initalize private members
row = row_;
matrix = new double*[row]; // Create a new array of size row_
for(int i = 0; i < row; i++)
{
matrix[i] = new double[col]; // Create new cols of size col (inside array of row)
}
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
matrix[i][j] = val;
val = val + 1.0;
}
}
}
I tried to reuse your design for simplicity, but I really suggest that you try to specify the dimensions of the matrix in a constructor instead and maybe even construct the matrix in it as well.
Something like this:
Matrix(int row_, int col_) : row(row_), col(col_) {*/ create matrix here /*};
You can skip the "create matrix here" part and use your own Create() if you want to.
You need dynamic memory allocation for that. I won't fiddle around with pointers (new / delete) unless you are explicitly told to. As a beginner you should probably use the standard template library (STL) tools:
#include <vector> and use std::vector<std::vector<int>> Table instead of int Table[3][3]. Then write a constructor like this:
Matrix(std::size_t rows, std::size_t cols)
{
Table.resize(rows);
for (unsigned int i = 0; i < Table.size(); ++i)
Table[i].resize(cols);
}
You can additionally store the dimension of the matrix, but there is no need to do it since you can get the information from the vectors. Replace the hardcoded dimensions in all loops by the corresponding dynamic sizes (stored or extracted from the vectors). For example:
Matrix& operator +(Matrix& a, Matrix b)
{
unsigned int rows = a.Table.size();
unsigned int cols = a.Table[0].size();
for (unsigned int i = 0; i < rows; i++)
for (unsigned int j = 0; j < cols; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
However, this vector of vectors is not really effective. Better would be a single vector but I guess for a beginner it is okay.
Greetings
I put in my program two loops - one fills 2D array with one value N0, and next loop is generating random number. And my program does not work when I have loop for array. I get "Unhandled exception... (parameters: 0x00000003)". But without first loop it works correctly. Thanks for help.
#include <iostream>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
using namespace std;
const double czas = 1E9;
int main()
{
//Declaration of variables
const int k = 20;
const int L = 30;
double N0 = 7.9E9;
int t,i,j, WalkerAmount;
double excitation, ExcitationAmount;
double slab[30][600];
//Random number generator
boost::random::mt19937 gen;
boost::random::uniform_int_distribution<> numberGenerator(1, 4);
//Filling slab with excitation
for (int i = 0; i <= L; i++)
{
for (int j = 0; j <= k*L; j++) { slab[i][j] = N0; }
}
//Time loop
for (t = 0; t < czas; t++) {
WalkerAmount = 0;
ExcitationAmount = 0;
for (int i = 0; i <= L; i++)
{
for (int j = 0; j <= k*L; j++)
{
int r = numberGenerator(gen);
cout << r << endl;
}
}
}
system("pause");
return 0;
}
Arrays in C++ are indexed from 0 to n-1 where n is the capacity of the array. Then, the code following code is wrong.
int main()
{
//Declaration of variables
const int k = 20;
const int L = 30;
double N0 = 7.9E9;
double slab[30][600];
// [...]
for (int i = 0; i <= L; i++)
{
for (int j = 0; j <= k*L; j++) { slab[i][j] = N0; }
}
}
When you initialize your array, you always go one steep too far. As you consider the case where i == L and j == k*L you reach an area in the memory that out of your array.
The loop you want to execute is
for (int i = 0; i < L; i++)
for (int j = 0; j < k*L; j++)
// Initialize