I'm making a 2D dynamic Matrix class. Problem arises in my copy constructor and =operator. Kindly tell me what am I doing wrong. Here is the code: (The cout's are for checking.
private:
int rows;
int coloumns;
float **ptr;
Matrix(const Matrix & M)
{ cout << "copy const called"<<endl;
cout << "1 "<< endl;
if(rows < 0 || column < 0) // To check if its a garbage value or not
{
rows = 0, col = 0;
ptr = NULL;
cout << "2 "<< endl;
}
else if(ptr!=NULL)
{
cout << "3 "<< endl;
for(int i = 0 ; i < col; i++)
{
delete [] ptr[i];
}
cout << "4 "<< endl;
delete [] ptr;
ptr = NULL;
cout << "5 "<< endl;
}
cout << "6 "<< endl;
*this = M;
cout << "7 "<< endl;
}
Matrix operator= (const Matrix &M)
{
if(this == &M)
{
return *this;
}
if(row!=0 && columns != 0)
{
for(int i = 0 ; i < columns; i++)
{
delete [] ptr[i];
}
delete [] ptr;
ptr = NULL;
}
rows = M.rows; col = M.columns;
ptr = new float *[rows];
for(int i = 0; i < rows; i++)
{
ptr[i] = new float [col];
}
for(int i = 0; i< rows ; i++)
{
for( int j=0 ; j< columns ;j++)
{
ptr[i][j] = M.ptr[i][j];
}
}
return *this;
}
int main()
{
Matrix M1(2,3);
Matrix M2(M1);
M2(0, 0) = 1;
}
It stops at the " *this = M " in the copy constructor. Moreover, I wanted to confirm that when I return something in the = operator, does it take the place of the whole " *this = M" , or just replaces M?
Note:
Not allowed to use vectors.
You have infinite recursion going on. In you copy constructor you have
*this = M;
This calls your class's operator= which you have declared as
Matrix operator= (const Matrix &M)
You can see that you are returning by value. When you return by value a copy is made. To make that copy we need to call the copy construct. This in turn calls the assignment operator again which call the copy constructor and the cycle just keeps going.
Your copy constructor can be corrected and simplified to be
Matrix(const Matrix & m) : rows(m.rows), columns(m.columns)
{
ptr = new float*[rows];
for (int i = 0; i < rows; i++)
ptr[i] = new float[columns];
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
ptr[i][j] = m.ptr[i][j]
}
Notice how I didn't have to check the state of the new class as we know what it is since we are initializing it. Everything is uninitialized and all we have to do is initialize everything and then copy the values from the one matrix into the new one.
In regards to you assignment operator you should have it return a reference to the object instead of returning by value. This avoids unnecessary copies and allows you to chain the operator with other operators.
Your code looks complicated to me.
I do not understand why you have chosen float** instead of plain float*. This looks better to me:
int rc, cc; // row count, column count
float* d; // data (rc * cc floats)
Memory allocation became a simpler operation:
d = new float[ rc * cc ];
Copying is also simpler:
memcpy( d, source.d, rc * cc * sizeof( *d ) );
The "hard" part is to retrieve a matrix element. You have to convert a row and column to an index:
index = row * column_count + column;
The whole class:
#include <iostream>
class matrix_type
{
int rc, cc; // row count, column count
float* d; // data
void allocate( const int arc, const int acc ) // a prefix in arc and acc stands for Argument
{
if ( arc * acc == rc * cc )
return; // nothing to do: already allocated
delete[] d;
rc = arc;
cc = acc;
d = new float[rc * cc];
}
void copy( const matrix_type& s )
{
allocate( s.rc, s.cc );
memcpy( d, s.d, rc * cc * sizeof( *d ) );
}
int as_idx( const int ar, const int ac ) const
{
return ar * cc + ac;
}
public:
matrix_type( const int arc, const int acc ) : rc( 0 ), cc( 0 ), d( 0 )
{
allocate( arc, acc );
memset( d, 0, rc * cc * sizeof( *d ) );
}
matrix_type()
{
delete[] d;
}
matrix_type( const matrix_type& s ) : rc( 0 ), cc( 0 ), d( 0 )
{
copy( s );
}
matrix_type& operator=(const matrix_type& s)
{
copy( s );
return *this;
}
float& at( const int ar, const int ac )
{
if ( ar < rc && ac < cc )
return d[as_idx( ar, ac )];
else
throw "out of range";
}
const float& at( const int ar, const int ac ) const
{
return const_cast<matrix_type*>(this)->at( ar, ac );
}
void print( std::ostream& os ) const
{
for ( int r = 0; r < rc; ++r )
{
for ( int c = 0; c < cc; ++c )
os << at( r, c ) << ' ';
os << '\n';
}
}
};
int main()
{
matrix_type m1( 3, 5 );
m1.at( 0, 0 ) = 1.f;
m1.at( 2, 4 ) = 15.f;
matrix_type m2( m1 );
matrix_type m3( 0, 0 );
m3 = m2;
m3.print( std::cout );
return 0;
}
Related
I'm writing code for a project in my class, and it is producing incredibly unusual results. Row and column values end up with random numbers in the millions and it eventually throws exceptions and I can't understand why.
#include <iostream>
using namespace std;
class SparseRow {
protected:
int row;
int col;
int value;
public:
SparseRow();
SparseRow(int inRow, int inCol, int inVal);
SparseRow(const SparseRow& newRow);
SparseRow& operator=(const SparseRow& newRow);
~SparseRow();
void display();
int getRow();
int getCol();
int getValue();
void setRow(int inRow);
void setCol(int inCol);
void setValue(int inVal);
};
class SparseMatrix {
protected:
int noRows;
int noCols;
int commonValue;
int noSparseValues;
SparseRow *myMatrix;
void setNoSparseValues(int noSV);
public:
SparseMatrix();
SparseMatrix(int rows, int cols, int cv, int noSV);
SparseMatrix(const SparseMatrix& matrix);
SparseMatrix& operator=(const SparseMatrix& matrix);
~SparseMatrix();
void readMatrix();
SparseMatrix* transpose();
SparseMatrix* multiply(SparseMatrix& M);
SparseMatrix* add(SparseMatrix& M);
void display();
void displayMatrix();
int getNoRows();
int getNoCols();
int getCommonValue();
int getNoSparseValues();
int getValue(int row, int col);
void setValue(int row, int col, int val);
};
SparseRow::SparseRow() {
row = -1;
col = -1;
value = 0;
}
SparseRow::SparseRow(int inRow, int inCol, int inVal) {
row = inRow;
col = inCol;
value = inVal;
}
SparseRow::SparseRow(const SparseRow& newRow) {
row = newRow.row;
col = newRow.col;
value = newRow.value;
}
SparseRow& SparseRow::operator=(const SparseRow& newRow) {
if (this != &newRow) {
row = newRow.row;
col = newRow.col;
value = newRow.value;
}
return *this;
}
SparseRow::~SparseRow() {
cout << "Deleting SparseRow with values: " << endl;
display();
}
void SparseRow::display() {
cout << "Row: " << row << ", Column: " << col << ", Value: " << value << endl;
}
int SparseRow::getRow() {
return row;
}
int SparseRow::getCol() {
return col;
}
int SparseRow::getValue() {
return value;
}
void SparseRow::setRow(int inRow) {
row = inRow;
}
void SparseRow::setCol(int inCol) {
col = inCol;
}
void SparseRow::setValue(int inVal) {
value = inVal;
}
SparseMatrix::SparseMatrix() {
noRows = 0;
noCols = 0;
commonValue = 0;
noSparseValues = 0;
}
SparseMatrix::SparseMatrix(int rows, int cols, int cv, int noSV) {
noRows = rows;
noCols = cols;
commonValue = cv;
noSparseValues = noSV;
myMatrix = new SparseRow[rows * cols];
}
SparseMatrix::SparseMatrix(const SparseMatrix& matrix) {
noRows = matrix.noRows;
noCols = matrix.noCols;
commonValue = matrix.commonValue;
noSparseValues = matrix.noSparseValues;
myMatrix = matrix.myMatrix;
}
SparseMatrix& SparseMatrix::operator=(const SparseMatrix& matrix) {
if (this != &matrix) {
delete[] myMatrix;
noRows = matrix.noRows;
noCols = matrix.noCols;
commonValue = matrix.commonValue;
noSparseValues = matrix.noSparseValues;
myMatrix = matrix.myMatrix;
}
return *this;
}
SparseMatrix::~SparseMatrix() {
cout << "Deleting SparseMatrix with values: " << endl;
display();
delete[] myMatrix;
}
void SparseMatrix::readMatrix() {
int count = 0;
int val;
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < noCols; j++) {
cin >> val;
if (val != commonValue) {
myMatrix[count].setRow(i);
myMatrix[count].setCol(j);
myMatrix[count].setValue(val);
// Why does C++ prevent me from calling a constructor on objects in an array? It doesn't make sense.
count++;
}
}
}
if (count != noSparseValues) {
cout << "ERROR: Incorrect number of sparse values! Changing to correct number." << endl;
noSparseValues = count;
}
}
SparseMatrix* SparseMatrix::transpose() {
SparseMatrix *newMatrix = new SparseMatrix(noCols, noRows, commonValue, noSparseValues);
for (int i = 0; i < noSparseValues; i++) {
newMatrix->setValue(myMatrix[i].getCol(), myMatrix[i].getRow(), myMatrix[i].getValue());
}
return newMatrix;
}
SparseMatrix* SparseMatrix::multiply(SparseMatrix& M) {
if (noCols != M.getNoRows()) {
cout << "ERROR: Matrices cannot be multiplied!" << endl;
return NULL;
}
SparseMatrix *newMatrix = new SparseMatrix(noRows, M.getNoCols(), commonValue, noRows * M.getNoCols());
// Why does C++ prevent me from creating an array to store this information? It doesn't make sense.
int SVCount = 0;
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < M.getNoCols(); j++) {
int sum = 0;
for (int k = 0; k < noCols; k++) {
sum += getValue(i, k) * M.getValue(k, j);
}
if (sum != newMatrix->getCommonValue()) {
SVCount++;
}
newMatrix->setValue(i, j, sum);
}
}
newMatrix->setNoSparseValues(SVCount);
return newMatrix;
}
SparseMatrix* SparseMatrix::add(SparseMatrix& M) {
if (noRows != M.getNoRows() || noCols != M.getNoCols()) {
cout << "ERROR: Matrices cannot be added!" << endl;
return NULL;
}
SparseMatrix *newMatrix = new SparseMatrix(noRows, noCols, commonValue + M.getCommonValue(), noRows * noCols);
int SVCount = 0;
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < noCols; j++) {
int sum = getValue(i, j) + M.getValue(i, j);
if (sum != newMatrix->getCommonValue()) {
SVCount++;
}
newMatrix->setValue(i, j, sum);
}
}
newMatrix->setNoSparseValues(SVCount);
return newMatrix;
}
void SparseMatrix::display() {
for (int i = 0; i < noSparseValues; i++) {
myMatrix[i].display();
}
}
void SparseMatrix::displayMatrix() {
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < noCols; j++) {
cout << getValue(i, j) << " ";
}
cout << endl;
}
}
int SparseMatrix::getNoRows() {
return noRows;
}
int SparseMatrix::getNoCols() {
return noCols;
}
int SparseMatrix::getCommonValue() {
return commonValue;
}
int SparseMatrix::getNoSparseValues() {
return noSparseValues;
}
void SparseMatrix::setNoSparseValues(int noSV) {
noSparseValues = noSV;
}
int SparseMatrix::getValue(int row, int col) {
for (int i = 0; i < noSparseValues; i++) {
if (myMatrix[i].getRow() == row && myMatrix[i].getCol() == col) {
return myMatrix[i].getValue();
}
}
return commonValue;
}
void SparseMatrix::setValue(int row, int col, int val) {
bool replacingSparse = (getValue(row, col) != commonValue);
bool replacingWithSparse = (val != commonValue);
int index = -1;
if (replacingSparse) {
for (int i = 0; i < noSparseValues; i++) {
if (myMatrix[i].getRow() == row && myMatrix[i].getCol() == col) {
index = i;
break;
}
}
if (replacingWithSparse) {
myMatrix[index].setValue(val);
}
else {
for (int i = index; i < noSparseValues; i++) {
myMatrix[i] = myMatrix[i + 1];
}
noSparseValues--;
}
}
else {
if (replacingWithSparse) {
for (int i = 0; i < noSparseValues; i++) {
if (myMatrix[i].getRow() > row || (myMatrix[i].getRow() >= row && myMatrix[i].getCol() > col)) {
index = i;
break;
}
}
for (int i = noSparseValues; i > index; i--) {
myMatrix[i] = myMatrix[i - 1];
}
myMatrix[index].setRow(row);
myMatrix[index].setCol(col);
myMatrix[index].setValue(val);
noSparseValues++;
}
}
}
int main() {
int n, m, cv, noNSV;
SparseMatrix* temp;
cin >> n >> m >> cv >> noNSV;
SparseMatrix* firstOne = new SparseMatrix(n, m, cv, noNSV);
firstOne->readMatrix();
cin >> n >> m >> cv >> noNSV;
SparseMatrix* secondOne = new SparseMatrix(n, m, cv, noNSV);
secondOne->readMatrix();
cout << "First one in sparse matrix format" << endl;
firstOne->display();
cout << "First one in normal matrix format" << endl;
firstOne->displayMatrix();
cout << "Second one in sparse matrix format" << endl;
secondOne->display();
cout << "Second one in normal matrix format" << endl;
secondOne->displayMatrix();
cout << "After Transpose first one in normal format" << endl;
temp = firstOne->transpose();
temp->displayMatrix();
cout << "After Transpose second one in normal format" << endl;
temp = secondOne->transpose();
temp->displayMatrix();
cout << "Multiplication of matrices in sparse matrix form:" << endl;
temp = secondOne->multiply(*firstOne);
temp->display();
cout << "Addition of matrices in sparse matrix form:" << endl;
temp = secondOne->add(*firstOne);
temp->display();
}
Input:
3 3 0 3
2 2 2
0 0 0
0 0 0
3 3 0 3
2 2 2
0 0 0
0 0 0
Expected output: (not formatted exactly the same, but the numbers should be identical)
First one in sparse matrix format
0, 0, 2
0, 1, 2
0, 2, 2
First one in normal matrix format
2 2 2
0 0 0
0 0 0
Second one in sparse matrix format
0, 0, 2
0, 1, 2
0, 2, 2
Second one in normal matrix format
2 2 2
0 0 0
0 0 0
After Transpose first one
2 0 0
2 0 0
2 0 0
After Transpose second one
2 0 0
2 0 0
2 0 0
Multiplication of matrices in sparse matrix form:
0, 0, 4
0, 1, 4
0, 2, 4
Addition of matrices in sparse matrix form:
0, 0, 4
0, 1, 4
0, 2, 4
Actual output:
First one in sparse matrix format
Row: 0, Column: 0, Value: 2
Row: 0, Column: 1, Value: 2
Row: 0, Column: 2, Value: 2
First one in normal matrix format
2 2 2
0 0 0
0 0 0
Second one in sparse matrix format
Row: 0, Column: 0, Value: 2
Row: 0, Column: 1, Value: 2
Row: 0, Column: 2, Value: 2
Second one in normal matrix format
2 2 2
0 0 0
0 0 0
After Transpose first one in normal format
0 0 0
2 0 0
2 0 0
After Transpose second one in normal format
0 0 0
2 0 0
2 0 0
Multiplication of matrices in sparse matrix form:
Row: 0, Column: 1, Value: 4
Row: 0, Column: 2, Value: 4
Row: 369, Column: -33686019, Value: 9
Addition of matrices in sparse matrix form:
(Exceptions thrown here, line 222 in code)
Exceptions thrown:
Project1.exe has triggered a breakpoint.
Unhandled exception at 0x777E8499 (ntdll.dll) in Project1.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77825890).
I'll address only some of the issues in the posted code.
pointers
Their explict use is always prone to error and it's increasingly discouraged at every new version of the standard.
In OP's code they own the responsability of managing memory resources, but in C++ they don't automatically call the destructor of an object when it goes out of scope.
That's what a smart pointer like std::unique_ptr can do.
Let's see what happens in main:
int n, m, cv, noNSV;
SparseMatrix* temp; // <- Declaration far from initialization
cin >> n >> m >> cv >> noNSV;
SparseMatrix* firstOne = new SparseMatrix(n, m, cv, noNSV);
// ^^^^^^^^^^^^^^^^ Why?
// ...
temp = firstOne->transpose(); // <- Here the pointer is initialized
// ...
temp = secondOne->transpose(); // <- Here the pointer is overwritten, but the allocated memory
// isn't released, it leaks.
// ...
temp = secondOne->multiply(*firstOne); // <- Again...
// ...
temp = secondOne->add(*firstOne); // <- ...and again
// ...
// No 'delete' calls at the end, so no destructor is called for the previously allocated objects
The only reason to use pointers here, is that SparseMatrix::transpose() is designed to return one, but it could easily retrun a SparseMatrix instead (Return Value Optimization would avoid unnecessary copies).
To every call of new should correspond a delete and since functions like transpose return a pointer to a newly allocated objects, delete temp; should be called before overwriting temp, to make sure that the proper destructor is called.
In C++, though, we should take advantage of RAII (Resource Acquisition Is Initialization, also named Scope-Bound Resource Management):
{ // <- Start of a scope
int n, m, cv, noNSV;
std::cin >> n >> m >> cv >> noNSV;
// Declare a variable using the constructor. Its lifetime begins here.
SparseMatrix firstOne(n, m, cv, noNSV);
// The same for 'secondOne'
// ...
// SparseSparse::transpose() here should return a SparseMatrix, not a pointer
SparseMatrix temp = firstOne.transpose();
// ...
// Here the matrix is reassigned (which can be cheap if move semantic is implemented)
temp = secondOne.transpose();
// ...
temp = secondOne.multiply(firstOne); // <- Again...
// ...
} // <- End of scope, all the destructors are called. No leaks.
special member functions
That's actually related to previous point, looking at how e.g. the copy assignment operator is implemented in the posted snippet:
SparseMatrix& SparseMatrix::operator=(const SparseMatrix& matrix) {
if (this != &matrix) { // <- debatable, see copy-and-swap idiom
delete[] myMatrix; // <- putted here makes this function not exception safe ^^
noRows = matrix.noRows;
noCols = matrix.noCols;
commonValue = matrix.commonValue;
noSparseValues = matrix.noSparseValues;
myMatrix = matrix.myMatrix; // <- The pointer is overwritten, but this is shallow copy
// what you need is a deep copy of the array
}
return *this;
}
A proper implementation of this and the other special functions would take advantage of the copy-and-swap idiom, which is masterfully described here:
What is the copy-and-swap idiom?
Also, regarding this comment in OP's reading function:
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < noCols; j++) {
cin >> val;
if (val != commonValue) {
myMatrix[count].setRow(i);
myMatrix[count].setCol(j);
myMatrix[count].setValue(val);
// Why does C++ prevent me from calling a constructor on objects in an array? It doesn't make sense.
count++;
}
}
}
The asker could use the placement parameter of new (placement new), there:
for (int i = 0; i < noRows; i++) {
for (int j = 0; j < noCols; j++) {
cin >> val;
if (val != commonValue) {
new (myMatrix + count) SparseRow(i, j, val);
count++;
}
}
}
Many other issues are left to the OP to solve.
I just don't know what to do with it...
The functions runs well in debug, but not in release.
I am trying to learn about artificial neural networks and C++ vectors.
Here is the code (in Python 2.7) that I'm writing in C++:
http://neuralnetworksanddeeplearning.com/chap1.html#exercise_852508
(just scroll a little to reach it)
I'm using MinGW 7.2.0 from MSYS2 (C++11).
There are some "teste" prints inside the backpropagation method, that is where the problem is comming from (I guess). I also overloaded operators +, - and * to make things easier.
I know that there are some libs like Armadillo that could make things easier, but I really wanna use this problem to learn better.
And here is the files:
neuralnetwork.h
(I made everything public to make things easier to look at)
#define MIN_NUMBER_TOLERANCE 1e-8
namespace nn
{
class neuralnetwork
{
//private:
public:
//total number of weights. useful to reserve memory
int numWeights;
//total number of biases. useful to reserve memory
int numBiases;
//total number of layers: 1 for input, n hidden layers and 1 for output
int numLayers;
//a vector to store the number of neurons in each layer: 0 index is about the input layer, last index is about the output layer
std::vector<int> sizes;
//stores all biases: num of neurons of layer 1 + ... + num of neurons of layer (numLayers - 1) (input layer has no bias)
std::vector<std::vector<double>> biases;
//stores all weights: (num of neurons of layer 1) x (num of neurons of layer ) + ... + ( num of neurons of layer (numLayers - 1) ) x ( num of neurons of layer (numLayers - 2) ) (input layer has no bias)
std::vector<std::vector<std::vector<double>>> weights;
//stores the output of each neuron of each layer
std::vector<std::vector<double>> layersOutput;
std::vector<std::vector<std::vector<double>>> derivativeWeights;
std::vector<std::vector<double>> derivativeBiases;
std::default_random_engine generator;
std::normal_distribution<double> distribution;
double randomNormalNumber(void);
double costDerivatives(const double&, const double&);
std::vector<double> costDerivatives(const std::vector<double> &, const std::vector<double> &);
void backPropagation(const std::vector<double>& neuralNetworkInputs, const std::vector<double>& expectedOutputs, // inputs
std::vector<std::vector<std::vector<double>>>& derivativeWeights, std::vector<std::vector<double>>& derivativeBiases); // outputs
void update_mini_batch( const std::vector<std::pair<std::vector<double>,std::vector<double>>> & mini_batch, double eta);
//public:
neuralnetwork(const std::vector<int>& sizes);
std::vector<double> feedforward(const std::vector<double>&);
};
std::vector<double> sigmoid(const std::vector<double> &);
double sigmoid(double);
std::vector<double> sigmoid_prime(const std::vector<double> &);
//double sigmoid_prime(double);
}
neuralnetwork.cpp
#include "neuralnetwork.h"
#include <iostream>
#include <assert.h>
#include <algorithm>
namespace nn
{
int counter = 0;
neuralnetwork::neuralnetwork(const std::vector<int> &sizes)
{
this->distribution = std::normal_distribution<double>( 0.0 , 1.0 );
this->numLayers = sizes.size();
this->sizes = sizes;
this->numWeights = 0;
this->numBiases = 0;
for ( int i = 1 ; i < this->numLayers ; i++ )
{
numWeights += this->sizes[ i ] * this->sizes[ i - 1 ];
numBiases += this->sizes[ i ];
}
this->weights.reserve( numWeights );
this->biases.reserve( numBiases );
this->derivativeWeights.reserve( numWeights );
this->derivativeBiases.reserve( numBiases );
this->layersOutput.reserve( this->sizes[ 0 ] + numBiases );
std::vector<double> auxVectorWeights;
std::vector<std::vector<double> > auxMatrixWeights;
std::vector<double> auxVectorBiases;
#ifdef DEBUG_BUILD
std::cout << "debugging!\n";
#endif
//just to accommodate the input layer with null biases and inputs (makes things easier to iterate and reading :D).
this->layersOutput.push_back( std::vector<double>( this->sizes[ 0 ] ) );
std::vector<std::vector<double>> matrixNothing( 0 );
this->weights.push_back( matrixNothing );
this->biases.push_back( std::vector<double>( 0 ) );
//since the second layer (index 1) because there is no weights (nor biases) for the neurons of the first layer
for ( int layer = 1 ; layer < this->numLayers ; layer++ )
{
//preallocate memory for the output of each layer.
layersOutput.push_back( std::vector<double>( this->sizes[ layer ] ) );
//-----------weights begin--------------
//auxMatrixWeights will store the weights connections between one layer (number of columns) and its subsequent layer (number of rows)
//auxMatrixWeights = new std::vector(this->sizes[layer], std::vector<double>( this->sizes[layer - 1] )); // it is not working...
//size[layer] stores the number of neurons on the layer
for ( int i = 0 ; i < this->sizes[ layer ] ; i++ )
{
//auxVectorWeights will have the size of the amount of wights necessary to connect the neuron i (from this layer) to neuron j (from next layer)
auxVectorWeights = std::vector<double>( this->sizes[ layer - 1 ] );
for ( int j = 0 ; j < auxVectorWeights.size() ; j++ )
{
auxVectorWeights[ j ] = this->randomNormalNumber();
}
auxMatrixWeights.push_back( auxVectorWeights );
}
this->weights.push_back( auxMatrixWeights );
auxMatrixWeights.clear();
//-----------weights end----------------
//-----------biases begin---------------
auxVectorBiases = std::vector<double>( this->sizes[ layer ] );
for ( int i = 0 ; i < auxVectorBiases.size() ; i++ )
{
auxVectorBiases[ i ] = this->randomNormalNumber();
}
this->biases.push_back( auxVectorBiases );
//-----------biases end-----------------
}
#ifdef _DEBUG
for ( int i = 0 ; i < this->weights.size() ; i++ )
{
std::cout << "layer " << i << "\n";
for ( int j = 0 ; j < this->weights[ i ].size() ; j++ )
{
std::cout << "neuron" << j << std::endl;
for ( const auto k : this->weights[ i ][ j ] )
{
std::cout << '\t' << k << ' ';
}
std::cout << std::endl;
}
}
#endif
}
template <class T>
inline int lastIndex(std::vector<T> vector , int tail)
{
return (vector.size() - tail);
}
double neuralnetwork::randomNormalNumber(void)
{
return this->distribution( this->generator );
}
double sigmoid(double z)
{
return 1.0 / ( 1.0 + exp( -z ) );
}
std::vector<double> sigmoid(const std::vector<double> & z)
{
int max = z.size();
std::vector<double> output;
output.reserve(max);
for(int i=0;i<max;i++)
{
output.push_back(0);
output[i] = 1.0 / ( 1.0 + exp( -z[i] ) );
}
return output;
}
/*double sigmoid_prime(double z)
{
return sigmoid( z ) * ( 1 - sigmoid( z ) );
}*/
std::vector<double> sigmoid_prime(const std::vector<double>& z)
{
int max = z.size();
std::vector<double> output;
output.reserve(max);
for(int i=0;i<max;i++)
{
output.push_back(sigmoid( z[i] ) * ( 1 - sigmoid( z[i] ) ) );
}
return output;
}
//scalar times vector
std::vector<double> operator* (double a , const std::vector<double> & b)
{
int size = b.size();
std::vector<double> result(size);
for ( int i = 0 ; i < size ; i++ )
{
result[i] = a * b[ i ];
}
return result;
}
// inner product
std::vector<double> operator* (const std::vector<double> & a , const std::vector<double> & b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size(); // or b.size(). they should have the same size.
std::vector<double> result;
result.reserve(size); // or b.size(). they should have the same size.
for ( int i = 0 ; i < size ; i++ )
{
result.push_back( a[ i ] * b[ i ] );
}
return result;
}
//matrix times columns vector
std::vector<double> operator* (const std::vector<std::vector<double>> & a , const std::vector<double> & b)
{
#ifdef _DEBUG
assert(a[0].size() == b.size());
for(int i = 0 ; i < ( lastIndex( a , 1 )) ; i++)
{
assert(a[i].size() == a[i+1].size());
}
#endif
int lines = a.size();
int columns = a[0].size();
std::vector<double> result;
result.reserve(lines);
int j = 0;
for ( int i = 0 ; i < lines ; i++ )
{
result.push_back(0);
for(j = 0 ; j < columns ; j++)
{
result[i] += a[ i ][ j ] * b[ j ];
}
}
return result;
}
//scalar times matrix (calls scalar times vector)
std::vector<std::vector<double>> operator* (double a , const std::vector<std::vector<double>> & b)
{
#ifdef _DEBUG
for(int i = 0 ; i < b.size()-1 ; i++)
{
assert(b[i].size() == b[i+1].size());
}
#endif
int lines = b.size();
int columns = b[0].size();
std::vector<std::vector<double>> result;
int j = 0;
for ( int i = 0 ; i < lines ; i++ )
{
result.push_back(a * b[ j ]);
}
return result;
}
std::vector<double> operator+(const std::vector<double>& a, const std::vector<double>& b)
{
assert(a.size() == b.size());
int size = a.size();
std::vector<double> result;
result.reserve(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(0);
result[i] = a[i] + b[i];
}
return result;
}
//sum of matrices
std::vector<std::vector<double>> operator+(const std::vector<std::vector<double>>& a, const std::vector<std::vector<double>>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
#ifdef _DEBUG
for(int i = 0 ; i < size ; i++)
{
assert(a[i].size() == b[i].size());
}
#endif
std::vector<std::vector<double>> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(a[i] + b[i]);
}
return result;
}
//subtraction of vectors
std::vector<double> operator-(const std::vector<double>& a, const std::vector<double>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
std::vector<double> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result[i] = a[i] - b[i];
}
return result;
}
//subtraction of matrices (calls subtraction of vectors)
std::vector<std::vector<double>> operator-(const std::vector<std::vector<double>>& a, const std::vector<std::vector<double>>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
#ifdef _DEBUG
for(int i = 0 ; i < size ; i++)
{
assert(a[i].size() == b[i].size());
}
#endif
std::vector<std::vector<double>> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(a[i] - b[i]);
}
return result;
}
//elementwise division
std::vector<double> operator/(const std::vector<double>& a, const std::vector<double>& b)
{
assert(a.size() == b.size());
int size = a.size();
std::vector<double> result;
result.reserve(size);
for(int i = 0 ; i < size ; i++)
{
if(b[i] < MIN_NUMBER_TOLERANCE)
{
throw std::runtime_error("Can't divide by zero!");
}
result[i] = a[i] / b[i];
}
return result;
}
double neuralnetwork::costDerivatives(const double &networkOutput , const double &expectedOutput)
{
return expectedOutput - networkOutput;
}
std::vector<double> neuralnetwork::costDerivatives(const std::vector<double> &networkOutput , const std::vector<double> &expectedOutput)
{
assert(expectedOutput.size() == networkOutput.size());
int size = networkOutput.size();
std::vector<double> output;
output.reserve(size);
for(int i = 0 ; i < size ; i++)
{
output.push_back(networkOutput[i] - expectedOutput[i]);
}
return output;
}
void neuralnetwork::backPropagation(const std::vector<double> &neuralNetworkInputs , const std::vector<double> &expectedOutputs, // inputs
std::vector<std::vector<std::vector<double>>>& derivativeWeights , std::vector<std::vector<double>>& derivativeBiases) // outputs
{
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
derivativeWeights.reserve( sizes.size() - 1 );
derivativeBiases.reserve( sizes.size() - 1 );
//to store one activation layer
std::vector<double> activation = neuralNetworkInputs;
//to store each one of the activation layers
std::vector<std::vector<double>> activations;
activations.reserve(sizes.size()); // numBiases is the same as the number of neurons (except 1st layer)
activations.push_back(activation);
int maxLayerSize = 0;
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
for ( int i = 1 ; i < numBiases ; i++ )
{
maxLayerSize = std::max(sizes[i], maxLayerSize);
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
// to store one weighted sum
std::vector<double> z;
z.reserve(maxLayerSize);
// to store each one of the weighted sums
std::vector<std::vector<double>> zs;
zs.reserve(sizes.size());
// layer and neuron counter
int layer, neuron;
for ( layer = 1 ; layer < numLayers ; layer++ )
{
z = (weights[layer] * activation) + biases[layer];
zs.push_back(z);
activation = sigmoid(z);
activations.push_back(activation);
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
std::vector<double> delta = costDerivatives(activations[ lastIndex( activations , 1 )] , expectedOutputs) * sigmoid_prime(z);
delta.reserve(maxLayerSize);
derivativeBiases.push_back(delta);
int j;
std::vector<std::vector<double>> dummyMatrix;
dummyMatrix.reserve(maxLayerSize);
for (neuron = 0; neuron < sizes[ lastIndex( sizes , 1 )]; neuron++)
{
dummyMatrix.push_back(std::vector<double>(activations[ lastIndex( activations , 2 )].size()));
for (j = 0; j < activations[ lastIndex( activations , 2 )].size(); j++)
{
dummyMatrix[neuron][j] = delta[neuron] * activations[ lastIndex( activations , 2 )][j];
}
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
derivativeWeights.push_back(dummyMatrix);
dummyMatrix.clear();
std::vector<double> sp;
sp.reserve(maxLayerSize);
std::vector<double> dummyVector;
dummyVector.reserve(maxLayerSize);
double dummyDouble = 0;
for(layer = 2 ; layer < numLayers ; layer++)
{
z = zs[ lastIndex( zs , layer )];
sp = sigmoid_prime(z);
for(j = 0 ; j < sizes[ lastIndex( weights , layer )] ; j++)
{
for (neuron = 0; neuron < sizes[ lastIndex( sizes , layer - 1 )]; neuron++)
{
dummyDouble += weights[ lastIndex( weights , layer - 1 )][neuron][j] * delta[neuron];
}
dummyVector.push_back(dummyDouble * sp[j]);
dummyDouble = 0;
}
delta = dummyVector;
dummyVector.clear();
derivativeBiases.push_back(delta);
for (neuron = 0; neuron < sizes[ lastIndex( sizes , layer )]; neuron++)
{
dummyMatrix.push_back(std::vector<double>(sizes[ lastIndex( sizes , layer + 1 )]));
for (j = 0; j < sizes[ lastIndex( sizes , layer + 1 )]; j++)
{
dummyMatrix[neuron][j] = activations[ lastIndex( activations , layer + 1 )][j] * delta[neuron];
}
}
derivativeWeights.push_back(dummyMatrix);
dummyMatrix.clear();
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
//both derivativeWeights and derivativeBiases are reversed. so let's reverse it.
std::reverse(derivativeWeights.begin(),derivativeWeights.end());
std::reverse(derivativeBiases.begin(),derivativeBiases.end());
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
}
}
main.cpp
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "neuralnetwork.h"
#include <string>
void printAll(const std::vector<double> & v, const std::string & name)
{
int size = v.size();
std::cout << "\t" << name << ":\t";
for(int i = 0 ; i < size ; i++)
{
std::cout << v[i] << "\t";
}
std::cout << std::endl;
}
template<class T>
void printAll(const std::vector<T> & v, const std::string & name)
{
int size = v.size();
std::cout << name << ":" << std::endl;
for(int i = 0 ; i < size ; i++)
{
printAll(v[i], "\t" + ("[" + std::to_string(i)) + "]");
}
}
int main(int argc, char** argv )
{
nn::neuralnetwork n({2,4,3});
n.weights = {{},{{1,2},{3,4},{5,6},{7,8}} , {{9,8,7,6},{5,4,3,2},{1,2,3,4}}};
n.biases = {{},{1, 4, 6, 8} , {9, 2, 4}};
printAll(n.weights,"weights");
printAll(n.biases,"biases");
std::vector<std::vector<std::vector<double>>> derivativeWeights;
std::vector<std::vector<double>> derivativeBiases;
n.backPropagation({1,2},{1,2,3},derivativeWeights,derivativeBiases);
printAll(n.derivativeWeights,"derivativeWeights");
printAll(n.derivativeBiases,"derivativeBiases");
system("PAUSE");
return 0;
}
It looks like your problem is that you are only reserving memory for the vectors in the constructor, not allocating it.
The reserve method does not resize the vector, it is a performance optimization in cases where you know you will resize the vector in the future, but an optimizing compiler is free to ignore it.
This isn't causing a problem for 'weights' and 'biases' in this particular code becuase you are initializing them with vectors of the proper size, which does set them to the correct size. The problems are with derivativeWeights and derivativeBiases, where you reserve memory for the vectors, but they are never actually resized. This makes this memory potentially invalid if you try to dereference it. You could use resize instead of reserve, or push back the elements one by one, which will also resize the vector.
Another comment is that you don't have to use this-> for every member of the class, the 'this->' is assumed for members of the class if you don't use it.
I didn't found the problem, but I realised that, for this problem (artificial neural network), I can initialize each property of the class with each right sizes without loss of generality. So this is what I'm going to do.
I feel a little ashamed that I am not finding it... :/
I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading.
In other words:
void MyMatrix::ReturnValue()
{
int row = 0, col = 0;
cout << "Return Value From the last Matrix" << endl;
cout << "----------------------------------" << endl;
cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}
The operation ((*this).matrix)[row][col] should return an int.
I have no idea how to build the operator [][].
Alternatively, I could concatenate a couple of calls to the operator [], but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int, and it compel to build another operator, and I dont want to do that.
The data matrix is defined like
int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
matrix[i] = new int[col];
if (matrix[i] == NULL)
{
cout << "Allocation memory - Failed";
return;
}
}
What can I do?
Thank you,
Simply, such an operator does not exist, so you can not overload it.
A possible solution is to define two classes: the Matrix and the Row.
You can define the operator[] of a Matrix so that it returns a Row, then define the same operator for the Row so that it returns an actual value (int or whatever you want, your Matrix could be also a template).
This way, the statement myMatrix[row][col] will be legal and meaningful.
The same can be done in order to assign a new Row to a Matrix or to change a value in a Row.
* EDIT *
As suggested in the comments, also you should take in consideration to use operator() instead of operator[] for such a case.
This way, there wouldn't be anymore the need for a Row class too.
You can define your own operator [] for the class. A straightforward approach can look the following way
#include <iostream>
#include <iomanip>
struct A
{
enum { Rows = 3, Cols = 4 };
int matrix[Rows][Cols];
int ( & operator []( size_t i ) )[Cols]
{
return matrix[i];
}
};
int main()
{
A a;
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
}
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
std::cout << std::endl;
}
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11
I have no idea how to build the operator [][].
Sometimes it is fine to use a different operator, namely ():
int& Matrix::operator () (int x, int y)
{
return matrix[x][y];
}
const int& Matrix::operator () (int x, int y) const
{
return matrix[x][y];
}
int diagonal (const Matrix& m, int x)
{
return m (x, x); // Usage.
}
Advantage:
No need to use "intermediate" class like Row or Column.
Better control than with Row& Matrix operator (int); where someone could use the Row reference to drop in a row of, say, illegal length. If Matrix should represent a rectangular thing (image, matrix in Algebra) that's a potential source of error.
Might be less tedious in higher dimensions, because operator[] needs classes for all lower dimensions.
Disadvantage:
Uncommon, different syntax.
No more easy replacement of complete rows / columns, if that's desired. However, replacing columns is not easy, anyway, provided you used rows to model (and vice versa).
In either case, there are pros and cons if the number of dimensions are not known at runtime.
I was looking for self-tested array replacement...
Improved version returns reference or NULL reference and checks boundaries inside.
#include <iostream>
#include <iomanip>
template<typename T, int cols>
class Arr1
{
public:
Arr1(T (&place)[cols]) : me(place) {};
const size_t &Cols = cols;
T &operator [](size_t i)
{
if (i < cols && this != NULL) return me[i];
else {
printf("Out of bounds !\n");
T *crash = NULL;
return *crash;
}
}
private:
T (&me)[cols];
};
template<typename T, int rows, int cols>
class Arr2
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
Arr2() {
ret = NULL;
for (size_t i = 0; i < rows; i++) // demo - fill member array
{
for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
}
}
~Arr2() {
if (ret) delete ret;
}
Arr1<T, cols>(&operator [](size_t i))
{
if (ret != NULL) delete ret;
if (i < rows) {
ret = new Arr1<T, cols>(matrix[i]);
return *ret;
}
else {
ret = NULL;
printf("Out of bounds !\n");
return *ret;
}
}
//T(&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
Arr1<T, cols> *ret;
};
template<typename T,int rows, int cols>
class Arr
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
T(&operator [](size_t i))[cols]
{
if (i < rows) return matrix[i];
else {
printf("Out of bounds !\n");
T(*crash)[cols] = NULL;
return *crash;
}
}
T (&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
};
void main2()
{
std::cout << "Single object version:" << endl;
Arr<int, 3, 4> a;
for (size_t i = 0; i <= a.Rows; i++)
{
int *x = &a[i][0];
if (!x) printf("Fill loop - %i out of bounds...\n", i);
else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
}
for (size_t i = 0; i < a.Rows; i++)
{
for (size_t j = 0; j <= a.Cols; j++) {
std::cout << std::setw(2) << a[i][j] << ' ';
if (a.MemberCheck[i][j] != a[i][j])
printf("Internal error !");
}
std::cout << std::endl;
}
std::cout << endl << "Double object version:" << endl;
Arr2<int, 3, 4> a2;
for (size_t i = 0; i < a2.Rows; i++)
{
for (size_t j = 0; j <= a2.Cols; j++) {
int &x = a2[i][j];
if (&x)
{
x++;
std::cout << std::setw(2) << a2[i][j] << ' ';
//if (&a2.MemberCheck[i][j] != &a2[i][j])
// printf("Internal error !");
}
}
}
}
Output
Single object version:
Out of bounds !
Fill loop - 3 out of bounds...
0 1 2 3 4
4 5 6 7 8
8 9 10 11 -858993460
Double object version:
1 2 3 4 Out of bounds !
5 6 7 8 Out of bounds !
9 10 11 12 Out of bounds !
it works fine in the program below
#include<iostream>
using namespace std;
class A{
public:
int r,c;
int** val;
A()
{
r=0;c=0;val=NULL;
}
A(int row,int col)
{
r=row;c=col;
int count=0;
val=new int*[row];
for(int i=0;i<r;i++){
val[i]=new int[col];
for(int j=0;j<c;j++){
count++;
val[i][j]=count;
}
}
}
int* &operator[](int index){
return val[index];
}
};
int main(void){
A a(3,3);
cout<<a[1][2];
return 0;
}
here, a[1][2] first computes a[1]-->which returns 2nd row as (int*) type
then it's read as (int*)[2] which returns 3rd element of that row.In short,
a[1][2]------>(a[1])[2]------>(val[1])[2]------>val[1][2].
I'm working on a polynomial class that basically does +,-,*,/, and evaluates polynomials. I keep running into bugs (specifically output is incorrect) and I think it's because of one of my operation methods (maybe addition??).
EDIT: Narrowed down problem to +() operator. It cannot add polynomials and a double.
Any help would be appreciated, please!
Polynomial Class CPP:
#include <iostream>
#include "polynomial.h"
using namespace std;
/*
=======================
Constructors
=======================
*/
Polynomial::Polynomial() //default constructor
{
for ( int i = 0; i < 20; i++ )
{
coefs[i] = 0;
}
}
Polynomial::~Polynomial() {}
void Polynomial::set(int coef, int pwr){
coefs[pwr] = coef;
pwrs = degree();
}
int Polynomial::degree()
{
int d = 0;
for ( int i = 0; i < 20; i++ )
if ( coefs[i] != 0 ) d = i;
return d;
}
/*
=======================
operator=
=======================
*/
Polynomial& Polynomial::operator= ( const Polynomial& poly )
{
if ( this == &poly ) return ( *this ) ;
else{
for (int i = 0; i < 20; i++)
coefs[i] = poly.coefs[i];
}
return ( *this );
}
/*
=======================
operator+
=======================
*/
Polynomial operator+(const Polynomial& a, const Polynomial& b )
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ) c.coefs[i] += a.coefs[i];
for ( int i = 0; i <= b.pwrs; i++ ) c.coefs[i] += b.coefs[i];
c.pwrs = c.degree();
return c;
}
Polynomial operator+(const Polynomial& a, const double& d)
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ){
if(i == a.pwrs) {
i=i+1;
c.coefs[i] = d;
}
c.coefs[i] += a.coefs[i];
}
c.pwrs = c.degree();
return c;
}
/*
=======================
Operator-
=======================
*/
Polynomial operator- (const Polynomial& a,const Polynomial& b )
{
//Polynomial a = *this; //a is the poly on the L.H.S
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ ) c.coefs[i] += a.coefs[i];
for ( int i = 0; i <= b.pwrs; i++ ) c.coefs[i] -= b.coefs[i];
c.pwrs = c.degree();
return c;
}
/*
=======================
Operator*
=======================
*/
Polynomial operator* (const Polynomial& a, const Polynomial& b)
{
//Polynomial a = *this; //a is the poly on the L.H.S
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ )
for ( int j = 0; j <= b.pwrs; j++ )
c.coefs[i+j] += ( a.coefs[i] * b.coefs[j] );
c.pwrs = c.degree();
return c;
}
Polynomial operator*(const Polynomial& poly1, const double& d)
{
Polynomial poly;
for(int i = 0; i < 20; i++)
poly.coefs[i] = poly1.coefs[i] * d;
poly.pwrs = poly1.pwrs;
return poly;
}
Polynomial operator*(const double& d, const Polynomial& poly1)
{
Polynomial poly;
for(int i = 0; i < 20; i++)
poly.coefs[i] = d * poly1.coefs[i];
poly.pwrs = poly1.pwrs;
return poly;
}
/*
=======================
Operator/
=======================
*/
Polynomial operator/ (const Polynomial& a, const Polynomial& b)
{
Polynomial c;
for ( int i = 0; i <= a.pwrs; i++ )
for ( int j = 0; j <= b.pwrs; j++ )
c.coefs[i+j] += ( a.coefs[i] / b.coefs[j] );
c.pwrs = c.degree();
return c;
}
ostream& operator<<(ostream& out, const Polynomial& p) {
for ( int i = 19; i >= 0; i-- ) {
if(p.pwrs > 1){
if ( p.coefs[i] != 0 ) {
cout << p.coefs[i] << "x^" << i << " ";
if(p.coefs[i-1] > 0)
cout << "+";
else if(p.coefs[i-1] < 0)
cout << "";
}
}
else if (p.pwrs == 1)
cout << p.coefs[i] << "x ";
else if(p.pwrs == 0)
cout << p.coefs[i];
}
cout << endl;
}
Main:
#include <iostream>
#include "polynomial.h"
#include "monomial.h"
using namespace std;
int main(){
Polynomial a, b, c, d, e,result;
a.set(1,3); //x^3
b.set(1,2); //x^2
c.set(6,1); //6x
d.set(0.01,10); //(1/100)x^10
e.set(2,5); //2x^5
result = 4*(a+b)*(c+1)*(d-e); // 4 * (x^3+x^2) * (6x+1) * ((1/100)x^10 - 2x^5)
}
You probably need to set pwrs = degree(); in operator =.
Also, as #6502 pointed out, your operator + is incorrect. You could change it like this:
Polynomial operator+(const Polynomial& a, const double& d)
{
Polynomial c;
c.coefs[0] = d;
for ( int i = 0; i <= a.pwrs; i++ ){
c.coefs[i] += a.coefs[i];
}
c.pwrs = c.degree();
return c;
}
Still inefficient, but at least it should give the correct result.
There is a logic problem with addition of a double. In that case you only want to add to coefs[0], not to all of them.
Why are you defining an assignment operator? Isn't the default one correct for this class?
Besides the problem that Henrink pointed out, assigning 0.01 to coef is meaningless. As only int is accepted here.
void Polynomial::set(int coef, int pwr){
coefs[pwr] = coef;
pwrs = degree();
}
Hey there, this is turning out to really be a tricky one for me.
main.cpp
#include <stdlib.h>
#include <iostream>
#include "Matrix.h"
int main(int argc, char** argv) {
// Dummy matrix
double row1[3] = {3, -1, -2};
double col1[3] = {4, 3, 1};
// Initialize matrix with 4 x 2 dimensions
Matrix<double> *m = new Matrix<double>(1, 3);
Matrix<double> *n = new Matrix<double>(3, 1);
Matrix<double> *mn;
// Set each row or column
m->set_row(row1, 0);
n->set_col(col1, 0);
std::cout << "Matrix M: \n";
m->print();
std::cout << "Matrix N: \n";
n->print();
std::cout << "Matrix MN: \n";
mn = m->mult(n);
mn->print();
return (EXIT_SUCCESS);
}
matrix.h
/*
* File: Matrix.h
* Author: charles
*
* Created on March 16, 2011, 12:45 AM
*/
#ifndef _MATRIX_H_
#define _MATRIX_H_
template <typename T>
class Matrix {
public:
Matrix(int _r, int _c){
// Set row and column size, then initialize matrix
_rows = _r;
_cols = _c;
_matrix = new T * [_rows];
for(int i = 0; i < _rows; ++i){
_matrix[i] = new T [_cols];
}
}
virtual ~Matrix(){
// Delete everything
for(int i = 0; i < _cols; ++i){
delete[] _matrix[i];
}
delete[] _matrix;
}
// Get number of rows
unsigned int get_rows(){
return _rows;
}
// Get number of columns
unsigned int get_cols(){
return _cols;
}
// Returns the row from _matrix as an array
T* get_row(int _r){
T* _t = new T [_cols];
for(int i = 0; i < _cols; ++i){
_t[i] = _matrix[_r][i];
}
return _t;
}
// Returns the column from _matrix as an array
T* get_col(int _c){
T* _t = new T [_rows];
for(int i = 0; i < _rows; ++i){
_t[i] = _matrix[i][_c];
}
return _t;
}
T get_elem(int _r, int _c){
return _matrix[_r][_c];
}
// Set a specific row with an array of type T
void set_row( T _t[], int _r ){
for(int i = 0; i < _cols; ++i){
_matrix[_r][i] = _t[i];
}
}
// Set a specific column with an array of type T
void set_col( T _t[], int _c){
for(int i = 0; i < _rows; ++i){
_matrix[i][_c] = _t[i];
}
}
// Set a specific index in the matrix with value T
void set_elem(T _t, int _r, int _c){
_matrix[_r][_c] = _t;
}
// Test to see if matrix is square
bool is_square(){
return (_rows == _cols);
}
// Print contents of matrix for debugging purposes
void print(){
for(int i = 0; i < _rows; ++i){
for(int j = 0; j < _cols; ++j){
std::cout << _matrix[i][j] << " ";
}
std::cout << "\n";
}
}
T comp_mult(int _r, T* _c){
T temp;
for(int i = 0; i < _cols; ++i){
std::cout << "Comp " << i << "\n";
if(i == 0) temp = _matrix[_r][i] * _c[i];
else temp += _matrix[_r][i] * _c[i];
}
return temp;
}
// Add one matrix to another and return new matrix
Matrix* add(Matrix* _m){
// Cannot add matrices if they do not have the same dimensions
if(!(_rows == _m->get_rows() && _cols == _m->get_cols())){
std::cout << "Not equal!";
return NULL;
}
else{
Matrix<T>* _t = new Matrix<T>(_rows, _cols);
for(int i = 0; i < _rows; ++i){
for(int j = 0; j < _cols; ++j){
_t->set_elem(_matrix[i][j] + _m->get_elem(i, j), i, j);
}
}
return _t;
}
}
// Multiply two matrices and return new matrix
Matrix* mult(Matrix* _m){
// If dimensions are not compatible return NULL
if(_cols != _m->get_rows()){
return NULL;
}
else{
Matrix<T>* _t = new Matrix<T>(_rows, _m->get_cols());
// Print out dimensions
// std::cout << "Dimensions: r = " << _t->get_rows() << " c = " << _t->get_cols() << "\n";
// Each row of _t
for(int i = 0; i < _t->get_rows(); ++i){
// Each value in each row of _t
for(int j = 0; j < _t->get_cols(); ++j){
T temp; // Temp variable to hold value for _t[i][j]
// Each row in _matrix
std::cout << "Loop i:" << i << "\n";
temp = this->comp_mult(i, _m->get_col(j));
std::cout << "loop j: " << j << "\n";
std::cout << "TEMP = " << temp << "\n";
_t->set_elem(temp, i, j); // this is where i segfault
}
}
}
}
// Multiply entire matrix by number and return new matrix
Matrix* scalar(T _n){
Matrix<T>* _t = new Matrix<T>(_rows, _cols);
for(int i = 0; i < _rows; ++i){
for(int j = 0; j < _cols; ++j){
_t->set_elem(_matrix[i][j] * _n, i, j);
}
}
return _t;
}
private:
unsigned int _rows; // Number of rows
unsigned int _cols; // Number of columns
T** _matrix; // Actual matrix data
};
#endif /* _MATRIX_H_ */
Sample Output
Matrix M:
3 -1 -2
Matrix N:
4
3
1
Matrix MN:
Loop i:0
Comp 0
Comp 1
Comp 2
loop j: 0
TEMP = 7
Segmentation fault
So the problem I'm having is that I am getting a segmentation fault when trying to assign a new matrix a value. It does not make sense to me because I have initialized the new matrix that I am trying to assign a value, I know its size, I'm not trying to access memory outside the matrix, and I know that my temp variable has a value. Anyone with a suggestion?
You forgot to return _t from mult() - The debugger likely gives you an incorrect location for the crash you get when calling mn->print()
Also, get_col and get_row leaks memory, and you need to make a copy constructor and an assignment operator.
_t->set_elem(temp, i, j); // this is where i segfault
My sixth sense tells me that you're going out of index. Check out your index values! Are they within limit?
Implement set_elem() as:
void set_elem(T _t, int _r, int _c){
if ( _ r >= _rows || _c >= _cols )
throw std::out_of_range("index out of range");
_matrix[_r][_c] = _t;
}