I am a Java developer, but now I need a C++ library and I am not so experienced in this language. In particular, I always get confused about pointers, references and memory allocation. This I think is the reason why I am getting an error at a matrix class I am developing.
The main code:
#include "stdafx.h"
#include "matrix.cpp"
void matrixtest();
int main()
{
matrixtest();
system("pause");
return 0;
}
void matrixtest()
{
// let's try 3x3 matrices
static const int arr1[] = {1, 2, 1, -1, 1, 2, 2, 3, -4};
static const int arr2[] = {0, 2, 2, 1, -1, 0, 3, 2, -2};
vector<int> values1(arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
vector<int> values2(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
matrix A(values1, 3);
matrix B(values2, 3);
matrix sum = A + B;
sum.show();
matrix diff = A - B;
diff.show();
matrix prod = A * B;
prod.show();
}
matrix.cpp interesting code:
matrix::matrix(vector<int> v, int r) : values(v), rows(r) {
values = v;
rows = r;
}
// [...]
matrix& matrix::operator += (const matrix& rhs) {
matrix result = (*this) + rhs;
(*this) = result;
return *this;
}
matrix matrix::operator + (const matrix& rhs) {
if (rows != rhs.rows || values.size() != rhs.values.size()) {
throw std::length_error("Matrices shapes mismatch");
}
matrix result(values, rows);
for (auto& i : values) {
result.values[i] = this->values[i] + rhs.values[i];
}
return result;
}
// [...]
void matrix::show() {
string delimiter = "";
for (auto& i : values) {
delimiter = "";
for (auto j = 0; j < values.size()/rows; j++) {
cout << delimiter << values[i * values.size()/rows + j]; // this is the line giving the error
delimiter = ",";
}
std::cout << std::endl;
}
}
full matrix.hpp file:
#ifndef matrix_hpp
#define matrix_hpp
class matrix {
private:
std::vector<int> values; // size is found by values.size()
int rows; // columns is values.size()/rows
public:
matrix(vector<int>, int); // base ctor.
matrix(const matrix& rhs); // copy ctor.
matrix& operator=(const matrix& rhs); // assign. ctor.
~matrix(); // dtor.
int& operator () (int row, int column);
const int& operator () (int row, int column) const;
matrix operator + (int scalar) const;
matrix operator - (int scalar) const;
matrix operator * (int scalar) const;
matrix& operator += (int scalar);
matrix& operator -= (int scalar);
matrix& operator *= (int scalar);
matrix operator + (const matrix&);
matrix operator - (const matrix&);
matrix operator * (const matrix&);
matrix& operator += (const matrix&);
matrix& operator *= (const matrix&);
// should be private ??
void reshape(int newRows, int newColumns);
void show(); //used for dev. only
void range(int start, int defaultStep = 1);
void fill(int value);
void randint(int lowerBound, int upperBound);
};
#endif /* CMatrix_hpp */
This class is based on an example given at matrix example.
The error says '0xC0000005: Access violation reading location 0x5820A694.'
So I am guessing the memory allocation is wrong and/or there is an out of bounds array and/or I am messing with the '&' operators.
Edit: I get the following trace:
this 0x00dffe24 {values={ size=9 } rows=3 } matrix *
So, the matrix does exist, but for some reason I am getting the error.
The for loop that you are using, before the one causing the error
for (auto& i : values)
is a range-based for loop.
With this you will get the values present in vector(values).
But based on the logic you have written what you want here is an index that represents the row you are working with.
You should go for the normal for loop.
for(int i =0; i<rows; ++i)
Related
I am implementing this class from https://isocpp.org/wiki/faq/operator-overloading
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double& operator() (unsigned row, unsigned col); // Subscript operators often come in pairs
double operator() (unsigned row, unsigned col) const; // Subscript operators often come in pairs
// ...
~Matrix(); // Destructor
Matrix(const Matrix& m); // Copy constructor
Matrix& operator= (const Matrix& m); // Assignment operator
// ...
private:
unsigned rows_, cols_;
double* data_;
};
inline
Matrix::Matrix(unsigned rows, unsigned cols)
: rows_ (rows)
, cols_ (cols)
//, data_ ← initialized below after the if...throw statement
{
if (rows == 0 || cols == 0)
throw BadIndex("Matrix constructor has 0 size");
data_ = new double[rows * cols];
}
inline
Matrix::~Matrix()
{
delete[] data_;
}
inline
double& Matrix::operator() (unsigned row, unsigned col)
{
if (row >= rows_ || col >= cols_)
throw BadIndex("Matrix subscript out of bounds");
return data_[cols_*row + col];
}
inline
double Matrix::operator() (unsigned row, unsigned col) const
{
if (row >= rows_ || col >= cols_)
throw BadIndex("const Matrix subscript out of bounds");
return data_[cols_*row + col];
}
In my main program I am declaring
Matrix *m = new Matrix(20,20)
Now how to access the elements ?
Normally
Matrix m(20,20)
will do the job.
But how to access in the other case ?
I tried
*m(i,j) - didn't work
m->operator()(i,j) - didn't work
(*m)(i,j) should do the trick. But then you might as well implement an equivalent at method so you can write m->at(i,j).
I have a Matrix3 class which has an overloaded * operator so i should be able to go:
Matrix3 m1, m2, m3
m2.setRotateX(3.98f); //values are not important just setting a value.
m3.setRotateZ(9.62f);
m1 = m2 * m3
Expected result:
m1 is assigned the result of m2 * m3 calculation. Instead it appears to be still assigned whatever was in memory when it was created.
I have looked at it in the debugger and the result code at the end of the operator * method is assigned to the correct values but it never is assigned for some reason.
I am running Visual Studio 2017 (I tried updating to latest version) and currently running with the Debug x86 profile.
I should also point out I am not using a pre-made maths library because this is part of an assignment.
Here is the full code for the class:
matrix3.h
#pragma once
#include "vector3.h"
class Matrix3
{
public:
union
{
struct
{
Vector3 xAxis;
Vector3 yAxis;
union {
Vector3 zAxis;
Vector3 translation;
};
};
Vector3 axis[3];
float data[3][3];
};
static const Matrix3 identity;
Matrix3(Vector3 x, Vector3 y, Vector3 z) : xAxis{ x }, yAxis{ y }, zAxis{ z } { }
Matrix3(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9) : data{ f1, f2, f3, f4, f5, f6, f7, f8, f9 } {}
Matrix3() : Matrix3{ identity } {}
Matrix3(const Matrix3 &other)
{
for (int i = 0; i > 3; i++)
axis[i] = other.axis[i];
}
Matrix3& operator= (const Matrix3& other);
Vector3& operator[] (int index);
const Vector3& operator[] (int index) const;
Matrix3 operator * (const Matrix3& other) const;
Vector3 operator * (const Vector3& v) const;
Matrix3 operator + (const Matrix3& other) const;
Matrix3 operator - (const Matrix3& other) const;
operator float*() { return reinterpret_cast<float*>(data); }
Matrix3 transpose() const;
void setScaled(float x, float y, float z);
void setScaled(const Vector3& v);
void scale(float x, float y, float z);
void scale(const Vector3 v);
void setRotateX(float radians);
void setRotateY(float radians);
void setRotateZ(float radians);
void rotateX(float radians);
void rotateY(float radians);
void rotateZ(float radians);
void setEuler(float pitch, float yaw, float roll);
operator std::string() const;
friend std::ostream& operator<< (std::ostream& os, const Matrix3& matrix);
};
matrix3.cpp
#include "Matrix3.h"
const Matrix3 Matrix3::identity = Matrix3({ 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 });
static const int MATRIX_DIMS = 3;
Vector3& Matrix3::operator[] (int index)
{
return axis[index];
}
const Vector3& Matrix3::operator[] (int index) const
{
return axis[index];
}
Matrix3& Matrix3::operator=(const Matrix3& other)
{
xAxis = other.xAxis;
yAxis = other.yAxis;
zAxis = other.zAxis;
return *this;
}
Matrix3 Matrix3::operator * (const Matrix3& other) const
{
Matrix3 result;
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
result.data[c][r] = data[0][r] * other.data[c][0] +
data[1][r] * other.data[c][1] +
data[2][r] * other.data[c][2];
return result;
}
Vector3 Matrix3::operator * (const Vector3& v) const
{
Vector3 result;
for (int r = 0; r < 3; ++r)
{
result[r] = 0;
for (int i = 0; i < MATRIX_DIMS; ++i)
result[r] += data[i][r] * v[i];
}
return result;
}
Matrix3 Matrix3::operator+(const Matrix3& other) const
{
Matrix3 result;
for (int x = 0; x < MATRIX_DIMS; x++)
for (int y = 0; y < MATRIX_DIMS; y++)
result[x][y] = data[x][y] + other[x][y];
return result;
}
Matrix3 Matrix3::operator-(const Matrix3& other) const
{
Matrix3 result;
for (int x = 0; x < MATRIX_DIMS; x++)
for (int y = 0; y < MATRIX_DIMS; y++)
result[x][y] = data[x][y] - other[x][y];
return result;
}
Matrix3 Matrix3::transpose() const
{
Matrix3 result;
for (int r = 0; r < MATRIX_DIMS; ++r)
for (int c = 0; c < MATRIX_DIMS; ++c)
result.data[r][c] = data[c][r];
return result;
}
void Matrix3::setScaled(const Vector3& v)
{
// set scale of each axis
xAxis = { v.x, 0, 0 };
yAxis = { 0, v.y, 0 };
zAxis = { 0, 0, v.z };
}
void Matrix3::setScaled(float x, float y, float z)
{
// set scale of each axis
xAxis = { x, 0, 0 };
yAxis = { 0, y, 0 };
zAxis = { 0, 0, z };
}
void Matrix3::scale(const Vector3 v)
{
Matrix3 m;
m.setScaled(v.x, v.y, v.z);
*this = *this * m;
}
void Matrix3::scale(float x, float y, float z)
{
Matrix3 m;
m.setScaled(x, y, z);
*this = *this * m;
}
void Matrix3::rotateX(float radians)
{
Matrix3 m;
m.setRotateX(radians);
*this = *this * m;
}
void Matrix3::rotateY(float radians)
{
Matrix3 m;
m.setRotateY(radians);
*this = *this * m;
}
void Matrix3::rotateZ(float radians)
{
Matrix3 m;
m.setRotateZ(radians);
*this = *this * m;
}
void Matrix3::setRotateX(float radians)
{
xAxis = { 1, 0, 0 };
yAxis = { 0, cosf(radians), sinf(radians) };
zAxis = { 0, -sinf(radians), cosf(radians) };
}
void Matrix3::setRotateY(float radians)
{
xAxis = { cosf(radians), 0, -sinf(radians) };
yAxis = { 0, 1, 0 };
zAxis = { sinf(radians), 0, cosf(radians) };
}
void Matrix3::setRotateZ(float radians)
{
xAxis = { cosf(radians), sinf(radians), 0 };
yAxis = { -sinf(radians), cosf(radians), 0 };
zAxis = { 0, 0, 1 };
}
void Matrix3::setEuler(float pitch, float yaw, float roll)
{
Matrix3 x, y, z;
x.setRotateX(pitch);
y.setRotateY(yaw);
z.setRotateZ(roll);
*this = z * y * x;
}
Matrix3::operator std::string() const
{
std::string result = "";
for (int r = 0; r < MATRIX_DIMS; ++r)
{
result += "{";
for (int c = 0; c < MATRIX_DIMS; ++c)
{
result += std::to_string(data[r][c]);
if (r != MATRIX_DIMS - 1 || c != MATRIX_DIMS - 1)
result += ",";
}
result += "}";
}
return result;
}
std::ostream& operator<< (std::ostream& os, const Matrix3& matrix)
{
os << static_cast<std::string>(matrix);
return os;
}
The supplied code exhibits undefined behavior. In c++ only up to one member of a union is active at any time. Only a union's active member can be read from. Assigning to a union member makes it active and makes all other members inactive. For example, if you assign a value to identity.data it's undefined behavior to try to read from identity.axis until you assign a value to identity.axis, after which you can no longer read from identity.data. This is different from how it works in c.
By calling void Matrix3::setRotateX(float radians) you assign values to the union's xAxis, yAxis and zAxis members, making the struct component of the union active. Then, when you multiply m2 with m3 you call Matrix3 Matrix3::operator * (const Matrix3& other) const which reads from the union's data member which is not active, which leads to undefined behavior.
The easiest solution would likely to be to dispose of the union all together and use only one of the representations.
I am trying to use the Sundials ODE solver libraries in order to approximate the dynamics of an extension to the multi species Lotka-Volterra competition equations. E.g. in the case of two species
dx1/dt = r1 * x1 * (1 - (x1 + a12 * x2))
dx2/dt = r2 * x2 * (1 - (x2 + a21 * x1))
or...
dx/dt = r * x * (1 - A * x)
(where K = a11 = a22 = 1)
From what I understand the Sundials ODE solver expects an object of class ODE_vector, the elements of which represent the various state variables of the system, in this case x1 and x2 and I have no problem getting the solver to approximate the trajectories of the two species' populations if I program each parameter (r1, r2, a12, a21) as unique objects as in the following code:
int community::dynamics(ODE_vector const & state, ODE_vector & time_derivative) {
double r1 = 0.5;
double r2 = 0.2;
double a12 = 0.2;
double a21 = 0.2;
time_derivative[0] = r1 * state[0] * (1 - (state[0] + a12 * state[1]));
time_derivative[1] = r2 * state[1] * (1 - (state[1] + a21 * state[0]));
return 0;
};
... where time_derivative and state are members of the Sundials class ODE.
Can anyone show me how to adapt the code to get the system of ODEs into matrix form, i.e. so that r1, r2, a12 and a21 are in the form r and A? I've been told to convert from ODE_vector to armadillo vector/matrix objects using "Advanced constructors" (e.g. 1) but it's one thing to know that and another to successfully implement it!!
Thanks!
Where you thinking of something like this? I implemented that naively in 30 min. There is a lot of optimisation, but it will never be as performant as your stripped down code. Even if you used Armadillo, Blitz++ etc.
#include <algorithm>
#include <iostream>
#include <vector>
template<class T> class Matrix {
public:
Matrix() {}
Matrix(size_t m, size_t n) : m_(m), n_(n) { v_.resize(m*n); }
Matrix& operator*= (const Matrix& other) {
if (other.m_ != n_) {
throw std::length_error("dimesions don't match");
}
Matrix<T> nv(m_,other.n_);
for (size_t j = 0; j < other.n_; ++j) {
for (size_t i = 0; i < m_; ++i) {
for (size_t k = 0; k < n_; ++k)
nv(i,j) += operator()(i,k) * other(k,j);
}
}
*this = nv;
return *this;
}
Matrix operator* (const Matrix& other) const {
Matrix ret = *this;
return ret *= other;
}
Matrix& operator+= (const Matrix& other) {
if (other.m_ != m_ || other.n_ != n_) {
throw std::length_error("dimesions don't match");
}
std::transform(v_.begin(), v_.end(), other.v_.begin(), v_.begin(), std::plus<T>());
return *this;
}
Matrix operator+ (const Matrix& other) const {
Matrix ret = *this;
return ret += other;
}
Matrix operator- () const {
Matrix<T> res (m_,n_);
std::transform (v_.begin(), v_.end(), res.v_.begin(), std::negate<T>());
return res;
}
Matrix& operator-= (const Matrix& other) {
return *this += -other;
}
Matrix operator- (const Matrix& other) const {
Matrix ret = *this;
return ret -= other;
}
Matrix operator->* (const Matrix& other) const {
if (other.m_ != m_ || other.n_ != n_) {
throw std::length_error("dimesions don't match");
}
Matrix res = *this;
std::transform(res.v_.begin(), res.v_.end(), other.v_.begin(),
res.v_.begin(), std::multiplies<T>());
return res;
}
Matrix operator=(std::vector<std::initializer_list<T>> const& other) {
n_ = other.size();
if (n_ == 0) {
throw std::bad_alloc();
}
m_ = other.front().size();
if (m_ == 0) {
throw std::bad_alloc();
}
for (auto const& i : other) {
if (i.size() != m_) {
throw std::bad_alloc();
}
}
v_.resize(m_*n_);
size_t j = 0;
for (const auto& i : other) {
std::copy(i.begin(), i.end(), v_.begin()+j);
j+=m_;
}
return *this;
}
T& operator() (size_t m, size_t n) {
return v_[n*m_+m];
}
const T& operator() (size_t m, size_t n) const {
return v_[n*m_+m];
}
size_t m() const {return m_;}
size_t n() const {return n_;}
private:
size_t m_, n_;
std::vector<T> v_;
};
template<class T> inline std::ostream&
operator<< (std::ostream& os, const Matrix<T>& v) {
size_t i,j;
for (i = 0; i < v.m(); ++i) {
for (j = 0; j < v.n(); ++j) {
os << v(i,j);
os << " ";
}
if (i<v.m()-1)
os << std::endl;
}
return os;
}
int main() {
Matrix<double> A, r, x, one, dxdt;
A = {{1,.2},
{.2,1}};
r = {{0.5,0.2}};
x = {{0.1,-0.1}};
one = {{1,1}};
dxdt = (r ->* x ->* (one - A * r));
std::cout << dxdt << std::endl;
return 0;
}
I am trying to use a symMatrixBlock representation for the cloth simulation.
The following class stores a symmetric matrix nxn who's each element is a 3x3 matrix (represented as Mat33 class)
class SymMatrixBlocks
{
public:
int size;
int *rowstart;
std::vector<int> col_lookup;
std::vector<Mat33 *> matBlock;
bool bAllZero;
public:
SymMatrixBlocks(int size);
SymMatrixBlocks(const SymMatrixBlocks &src);
~SymMatrixBlocks();
void Zero(void);
SymMatrixBlocks& operator=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator+=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator-=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator*=(double con);
Mat33* getMatBlock(int row, int col);
void SetDiag(DiagonalMatrix &src, DiagonalMatrix &ret);
void print();
Mat33* operator() (int row, int col);
};
inline const SymMatrixBlocks operator +(const SymMatrixBlocks &lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(lhs) += rhs;
}
inline const SymMatrixBlocks operator -(const SymMatrixBlocks &lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(lhs) -= rhs;
}
inline const SymMatrixBlocks operator *(const SymMatrixBlocks &lhs, double rhs)
{
return SymMatrixBlocks(lhs) *= rhs;
}
inline const SymMatrixBlocks operator *(double lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(rhs) *= lhs;
}
}
SymMatrixBlocks& SymMatrixBlocks::operator+=(const SymMatrixBlocks &src)
{
if (size != src.size)
return *this;
if (src.bAllZero)
return *this;
int i, j, start, length;
for (i = 0; i<src.size; i++)
{
start = src.rowstart[i];
length = src.rowstart[i + 1] - start;
for (j = 0; j<length; j++)
(*((*this)(i, src.col_lookup[start + j]))) += (*(src.matBlock[start + j]));
}
return *this;
}
Mat33* SymMatrixBlocks::operator() (int row, int col)
{
int i, start, l, length;
bAllZero = false;
if (row > col)
{
start = row;
row = col;
col = start;
}
start = rowstart[row];
length = rowstart[row + 1] - start;
for (l = 0; l<length; l++)
if (col_lookup[start + l] == col)
break;
if ((length != 0) && (l != length))
{
return matBlock[start + l];
}
else
{
for (l = 0; l<length; l++)
if (col_lookup[start + l] >= col)
break;
col_lookup.insert(col_lookup.begin() + start + l, col);
Mat33 *tempmat = new Mat33();
matBlock.insert(matBlock.begin() + start + l, tempmat);
for (i = row + 1; i <= size; i++)
rowstart[i]++;
return matBlock[start + l];
}
}
when I run the following line it gives memory leakage. Can anyone spot it out?
*tm1 = *df_dx * h; // all these are object of the SymMtrixBlocks class.
Beginner at C++ here. I specifically need help trying to figure out what is wrong with my overloaded * operator which is supposed to multiply two polynomials of a class Poly I made. My other overloaded operators appear to work just fine. Here is the original question:
P(x) = 2x4 + 3x3 – 12x2 + x – 19 (4th order polynomial)
or
P(x) = 2x7 + 5x5 – 7x2 + x – 19 (7th order polynomial)
Where the coefficients for the first and second equations can be described by the following array of integers
'Coeff1[ ] = {-19, 1, -12, 3, 2}'
'Coeff2[[ ] = {-19, 1, -7, 0, 0, 5, 0, 2}'
Design and code a polynomial class in C++ that has the following properties:
class Poly{
private:
int order; //order of the polynomial
int *coeff; // pointer to array of coeff on the heap
// size of coeff array predicated on (order + 1)
public:
Poly( ); //default constructor – order=0 & coeff[0] =1
Poly(int Order , int Default = 1) ;// creates Nth order poly
// and inits all coeffs
Poly(int Order, int *Coeff); //creates an Nth polynomial & inits
~Poly( ); // destructor
::::::: // copy constructor
//mutators & accessors
void set( ){// Query user for coefficient values);
void set(int coeff[ ], int size); // input coeffs via external coeff vector
int getOrder( )const; // get order of polynomial
int * get( ); //returns pointer to coeff array
//overloaded operators
Poly operator+( const Poly &rhs); // add two polynomials
Poly operator-( const Poly &rhs); // subt two polynomials
Poly operator*( const int scale); // scale a polynomial
Poly operator*(const Poly &rhs); // mult two polynomials
bool operator==(const Poly &rhs); // equality operator
const int & operator[ ](int I)const; // return the Ith coefficient
int & operator[ ](int I); // return the Ith coefficient
int operator( )(int X); // evaluate P(x) according
Poly & operator=(const Poly & rhs);
friend ostream & operator<<(ostream & Out, const Poly &rhs);
//other member functions
};
Demonstrate the following operations for the following Polynomials:
P1(x) = 2x4 + 3x3 – 12x2 + x – 19 (4th order polynomial)
P2(x) = 2x7 + 7x5 – 6x2 + x – 19 (7th order polynomial)
//display the following results for the polynomials defined above
o P3 = P1 + P2;
o P3 = P2 – P1;
o P3 = P1*10;
o P3 = 10*P1;
o P3 = P1*P2;
o bool flag = (P1==P2);
o P1[3] = P2[5]; // assign the 5th coefficient of P2 to 3rd coefficient of P1
o int Z = P1(int X = 5); // evaluate Polynomial for input X
// suggest using Horner’s method
o The displayed polynomial for P2 should be printed as follows
2X^7 + 7X^5 – 6X^2 + 1X – 1
Heres my code so far:
#include <iostream>
#include <cmath>
using namespace std;
class Poly
{
private:
int order;
int *coeff;
public:
Poly();
Poly(int Order, int Default=1);
Poly(int Order, int *Coeff);
Poly(const Poly ©);
~Poly();
void set(); //ask the user for the coefficient values
void set(int *Coeff, int size); //put the coefficient values in a external coeff vector
int getOrder() const; //gets the order of the polynomial
int* get() const; //returns pointer to coeff array
Poly operator +(const Poly &rhs);
Poly operator -(const Poly &rhs);
Poly operator *(const int scale);
Poly operator *(const Poly &rhs);
bool operator ==(const Poly &rhs);
const int & operator [](int access) const;
int & operator [](int access);
int operator ()(int X);
Poly & operator =(const Poly &rhs);
friend ostream & operator <<(ostream &Out, const Poly &rhs);
};
int main() {
int coeff1[] = {-19,1,-12,3,2};
int coeff2[] = {-19,1,-7,0,0,5,0,2};
Poly P1(4,coeff1);
Poly P2(7, coeff2);
Poly P3;
cout << "P1: " << P1 << endl;
cout << "P2: " << P2 << endl;
P3 = P1 * P2;
cout << "P1 * P2: " << P3 << endl;
return 0;
}
Poly::Poly() : order(0)
{
coeff = new int[1];
coeff[0] = 1;
}
Poly::Poly(int Order, int Default) : order(Order)
{
coeff = new int[order+1];
for (int i = 0; i < order+1; i++){
coeff[i] = Default;
}
}
Poly::Poly(int Order, int *Coeff) : order(Order), coeff(Coeff)
{
}
Poly::Poly(const Poly & copy)
{
order = copy.getOrder();
coeff = new int[order+1];
for (int i = 0; i < order+1; i++){
coeff[i] = copy.get()[i];
}
}
Poly::~Poly()
{
//if(coeff){
//delete [] coeff;
//}
}
void Poly::set()
{
cout << "Enter your coefficients:\n";
for (int i = 0; i < order+1; i++){
cin >> coeff[i];
}
}
void Poly::set(int *Coeff, int size)
{
delete [] coeff;
coeff = new int[size];
order = size;
for (int i = 0; i < order+1; i++){
coeff[i] = Coeff[i];
}
}
int Poly::getOrder() const
{
return order;
}
int* Poly::get() const
{
return coeff;
}
Poly Poly::operator +(const Poly &rhs)
{
int length = max(order+1, rhs.getOrder()+1);
int *answer = new int[length];
for (int i = 0; i < length + 1; i++){
answer[i] = coeff[i] + rhs.get()[i];
}
if (order > rhs.getOrder()){
for (int i = order+1 - rhs.getOrder()+1 ; i < order+1; i++){
answer[i] = coeff[i];
}
}
else if (order < rhs.getOrder()){
for (int i = rhs.getOrder()+1 - order+1; i < rhs.getOrder()+1; i++){
answer[i] = rhs.get()[i];
}
}
return Poly(length-1, answer);
}
Poly Poly::operator -(const Poly &rhs)
{
int length = max(order+1, rhs.getOrder()+1);
int *answer = new int[length];
for (int i = 0; i < order+1 && i < rhs.getOrder() + 1; i++){
answer[i] = coeff[i] - rhs.get()[i];
}
if (order > rhs.getOrder()){
for (int i = order+1-rhs.getOrder()+1; i < order+1; i++){
answer[i] = coeff[i];
}
}
else if (order < rhs.getOrder()){
for (int i = rhs.getOrder()+1 - order+1; i < rhs.getOrder()+1; i++){
answer[i] = 0 - rhs.get()[i];
}
}
return Poly(length-1, answer);
}
Poly Poly::operator *(const int scale)
{
int *answer = new int[order+1];
for (int i = 0; i < order+1; i++){
answer[i] = coeff[i] * scale;
}
return Poly(order, answer);
}
Poly Poly::operator *(const Poly &rhs)
{
int *shorter = NULL;
int *longer = NULL;
int s = 0;
int l = 0;
if(order < rhs.getOrder()){
shorter = coeff;
s = order;
longer = rhs.coeff;
l = rhs.order;
} else {
shorter = rhs.coeff;
s = rhs.order;
longer = coeff;
l = order;
}
Poly sum = Poly(l, longer) * shorter[0];
int *prod;
int nl;
for (int i = 1; i <= s; i++){
nl = l + i;
prod = new int[nl + 1];
for(int j = 0; j < i; j++){
prod[j] = 0;
}
for(int k = 0; k <= l; k++){
prod[k+i] = shorter[i] * longer[k];
}
sum = sum + Poly(nl, prod);
}
return sum;
}
bool Poly::operator ==(const Poly &rhs)
{
bool result;
if (order == rhs.order){
result = true;
for(int i = 0; i<order+1; i++){
if (coeff[i] != rhs.get()[i]){
result = false;
}
}
}else result = false;
return result;
}
const int& Poly::operator[](int access) const
{
return coeff[order + 1 - access];
}
int& Poly::operator [](int access)
{
return coeff[order + 1 - access];
}
int Poly::operator ()(int x)
{
int total = 0;
for(int i = 0; i < order + 1; i++){
total += coeff[i] * pow(x, i);
}
return total;
}
Poly &Poly::operator =(const Poly &rhs)
{
order = rhs.getOrder();
coeff = rhs.get();
return *this;
}
ostream& operator <<(ostream & Out, const Poly &rhs)
{
Out << rhs.get()[rhs.getOrder()] << "x^" << rhs.getOrder(); //first
for (int i = rhs.getOrder()-1; i > 0; i--){
if (rhs.get()[i] < 0 || rhs.get()[i] > 1) {
if(rhs.get()[i] > 0){
Out << " + ";
}
Out << rhs.get()[i] << "x^" << i << " ";
}else if (rhs.get()[i] == 1){
Out << "+ x ";
}else if (rhs.get()[i] == 1){
Out << "- x";
}
}
if (rhs.get()[rhs.getOrder() - rhs.getOrder()] > 0) {
Out << " + " << rhs.get()[rhs.getOrder() - rhs.getOrder()]; //last
}else Out << rhs.get()[rhs.getOrder() - rhs.getOrder()]; //last
Out << endl;
return Out;
}
`
Here is my current output. The answer I keep getting is half of the correct answer but I can't seem to get the first half.
P1: 2x^4 + 3x^3 -12x^2 + x -19
P2: 2x^7 + 5x^5 -7x^2 + x -19
P1 * P2: -114x^5 + 49x^4 -76x^3 + 362x^2 -38x^1 + 361
Any help is appreciated. Thank you
First, stop manually managing memory. Replace order and coeff with std::vector<int> values;. This bundles size() for order, and handles memory management for you.
If you don't know how to use std::vector yet, learn: it is far easier than learning how to write your own Poly class.
The next step in implementing Poly * Poly is to implement Poly& operator*=( Poly const& rhs );
The final step is friend Poly operator*( Poly lhs, Poly const& rhs ) { return std::move(lhs*=rhs); } There is little reason to use more than one line, and it can be inline.
That leaves operator*=.
The first step in implementing *= it so implement operator+(Poly const&, Poly const&), again via Poly& operator+=(Poly const&). As addition is easy, I will leave that to you.
The next step is scalar multiplication. Implement Poly& operator*=(int), and from it friend Poly operator*(Poly lhs, int x) { return std::move( lhs*=x ); } and friend Poly operator*(int x, Poly rhs) { return std::move( rhs*= x ); }. This is called 'scalar multiplication'.
Once we have those, *= becomes easy.
Store a copy of our initial value. (Poly init = std::move(*this);)
Create a return value (empty).
For each coefficient on the right hand side, do retval += coeff * init;
return *this = std::move(retval);
This is a sketch of the solution. To solve it really, you'll want to implement tests at each phase. Because I implemented *= in terms of other operations, testing each of those operations to make sure they work is key to having a debuggable *=. Then you test *=, then you test *, and then you are done.
If you are compiling in a compliant C++ compiler, a nice thing about using std::vector is that your default copy, move, assign and move-assign operations do the right thing, as does your default destructor. Seek to manage resources with specialized resource management classes, and follow The Rule of Zero, and you will have less pain.
Note that the above *= is not much easier to write than *, but in general *= is easier, so you should get into the habit anyhow.
Finally, note that this allocates more memory than is required, and is not optimal. It is, however, easy to get correct. After you have something like the above implemented, you can make it more optimal a number of ways. You can use karatsuba multiplication, you could use expression templates to avoid intermediate multiplication on the result += coeff * init; lines, you could reserve the right amount of space in result, or you could start playing with indexes manually.
The first step should be correctness, because if you have a correct algorithm you can at the very least use it to test your more optimal (trickier) algorithms.
Your code (for the polynomial multiplication) contains no comments and is rather opaque and hard to read/understand. So, I refuse to compile it (mentally) and can only guess, but it seems you don't know how multiplication of polynomials is defined, since your product polynomial is set to have order = min(order(A), order(B)) + 1, while correct is order(A)+order(B).
I suggest, you
1 make sure you understand polynomial multiplication before starting to code
2 write clear code with minimal instructions and useful comments (or better: useful variable names)
3 manage memory via the C++ standard library (using std::vector<>)
4 structure your code (write polynomial& polynomial::operator+=(polynomial const&) and then define the product as a standalone (can be a friend) via
polynomial operator*(polynomial const&a,polynomial const&b)
{
auto c=a;
c*=b;
return std::move(c);
}
though you may want to improve on this particular design (avoiding the re-allocation the is necessary in the above code in the c*=b operation).
I think this:
sum = sum + Poly(length, prod);
should be
sum = sum + Poly(length + i - 1, prod);
Also, the loop on i should stop at the shortest coeff array length.
Here's a modified version of the function:
Poly Poly::operator *(const Poly &rhs)
{
int *shorter = NULL;
int *longer = NULL;
int s = 0;
int l = 0;
if(order < rhs.order){
shorter = coeff;
s = order;
longer = rhs.coeff;
l = rhs.order;
} else {
shorter = rhs.coeff;
s = rhs.order;
longer = coeff;
l = order;
}
Poly sum = Poly(l, longer) * shorter[0];
int *prod;
int nl;
for (int i = 1; i <= s; i++){
nl = l + i;
prod = new int[nl + 1];
for(int j = 0; j < i; j++){
prod[j] = 0;
}
for(int k = 0; k <= l; k++){
prod[k+i] = shorter[i] * longer[k];
}
sum = sum + Poly(nl, prod);
}
return sum;
}
Note how it is based on order values rather than coeff array lengths (contrarily to the fix I indicated at the top of this answer).
If it doesn't work for you, then you may have other bugs in the code you didn't provide, or your algorithms work with array lengths, so you might have to adjust either to get things working.
Finally, as it has been said in other answers, you should use the tools provided by the standard library instead of handling array allocation by hand.