I would like to make matrices and use them using the Eigen3 library, with my number type being Boost.Multiprecision's mpfr_float wrapper. I can make the matrices just fine, but working with them fails for everything I've tried except matrix addition. Merely multiplication of two identity matrices produces garbage results!
Here's a MWE:
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/LU>
#include <boost/multiprecision/mpfr.hpp>
#include <iostream>
namespace Eigen{
using boost::multiprecision::mpfr_float;
template<> struct NumTraits<boost::multiprecision::mpfr_float>
{
typedef boost::multiprecision::mpfr_float Real;
typedef boost::multiprecision::mpfr_float NonInteger;
typedef boost::multiprecision::mpfr_float Nested;
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 20, //these have no impact
AddCost = 30,
MulCost = 40
};
inline static Real highest() { // these seem to have no impact
return (mpfr_float(1) - epsilon()) * pow(mpfr_float(2),mpfr_get_emax()-1);
}
inline static Real lowest() {
return -highest();
}
inline static Real dummy_precision(){
return pow(mpfr_float(10),-int(mpfr_float::default_precision()-3));
}
inline static Real epsilon(){
return pow(mpfr_float(10),-int( mpfr_float::default_precision()));
}
//http://www.manpagez.com/info/mpfr/mpfr-2.3.2/mpfr_31.php
};
} // namespace eigen
int main()
{
int size = 10;
typedef Eigen::Matrix<boost::multiprecision::mpfr_float, Eigen::Dynamic, Eigen::Dynamic> mp_matrix;
mp_matrix A = mp_matrix::Identity(size, size);
std::cout << A * A << std::endl; // produces nan's every other row!!!
return 0;
}
It produces the identity matrix just fine, but on my machine, using the latest homebrew-distributed versions (and others) of the dependencies for this code (Boost 1.57, Eigen 3.2.4), my program produces NaN's every other row in the matrix:
1 0 0 0 0 0 0 0 0 0
nan nan nan nan nan nan nan nan nan nan
0 0 1 0 0 0 0 0 0 0
nan nan nan nan nan nan nan nan nan nan
0 0 0 0 1 0 0 0 0 0
nan nan nan nan nan nan nan nan nan nan
0 0 0 0 0 0 1 0 0 0
nan nan nan nan nan nan nan nan nan nan
0 0 0 0 0 0 0 0 1 0
nan nan nan nan nan nan nan nan nan nan
Odd matrix sizes produce two rows of nan's at the bottom...
This does not seem to depend on the default precision, or the details of the NumTraits struct I define, or even whether I define one. I can inherit from GenericTraits<mpfr_float>, or not; I can say RequireInitialization = 1, or 0. I get NaN's. If I try to LU invert to solve a system, the returned matrix is entirely NaN. If the size of the matrix is 1x1, I even get a single NaN from matrix multiplication. Changing the various static functions has no impact either.
I feel like the strangest part is that if I define a custom complex class (not std::complex, for data loss reasons), with mpfr_float's as the underlying type for real and imaginary parts, I DO get functional matrices.
edit : Here is the complex type's NumTraits:
/**
\brief this templated struct permits us to use the Float type in Eigen matrices.
*/
template<> struct NumTraits<mynamespace::complex> : NumTraits<boost::multiprecision::mpfr_float> // permits to get the epsilon, dummy_precision, lowest, highest functions
{
typedef boost::multiprecision::mpfr_float Real;
typedef boost::multiprecision::mpfr_float NonInteger;
typedef mynamespace::complex Nested;
enum {
IsComplex = 1,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1, // yes, require initialization, otherwise get crashes
ReadCost = 2 * NumTraits<Real>::ReadCost,
AddCost = 2 * NumTraits<Real>::AddCost,
MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
};
};
Here is the complex class I wrote:
#include <boost/multiprecision/mpfr.hpp>
#include <boost/multiprecision/random.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/split_member.hpp>
#include <eigen3/Eigen/Core>
#include <assert.h>
namespace mynamespace {
using boost::multiprecision::mpfr_float;
class complex {
private:
mpfr_float real_, imag_; ///< the real and imaginary parts of the complex number
// let the boost serialization library have access to the private members of this class.
friend class boost::serialization::access;
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
// note, version is always the latest when saving
ar & real_;
ar & imag_;
}
/**
\brief load method for archiving a bertini::complex
*/
template<class Archive>
void load(Archive & ar, const unsigned int version) {
ar & real_;
ar & imag_;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
public:
complex():real_(), imag_(){}
complex(double re) : real_(re), imag_("0.0"){}
complex(const mpfr_float & re) : real_(re), imag_("0.0"){}
complex(const std::string & re) : real_(re), imag_("0.0"){}
complex(const mpfr_float & re, const mpfr_float & im) : real_(re), imag_(im) {}
complex(double re, double im) : real_(re), imag_(im) {}
complex(const std::string & re, const std::string & im) : real_(re), imag_(im) {}
complex(const mpfr_float & re, const std::string & im) : real_(re), imag_(im) {}
complex(const std::string & re, const mpfr_float & im) : real_(re), imag_(im) {}
complex(complex&& other) : complex() {
swap(*this, other);
}
complex(const complex & other) : real_(other.real_), imag_(other.imag_) {}
friend void swap(complex& first, complex& second) {
using std::swap;
swap(first.real_,second.real_);
swap(first.imag_,second.imag_);
}
complex& operator=(complex other) {
swap(*this, other);
return *this;
}
mpfr_float real() const {return real_;}
mpfr_float imag() const {return imag_;}
void real(const mpfr_float & new_real){real_ = new_real;}
void imag(const mpfr_float & new_imag){imag_ = new_imag;}
void real(const std::string & new_real){real_ = mpfr_float(new_real);}
void imag(const std::string & new_imag){imag_ = mpfr_float(new_imag);}
complex& operator+=(const complex & rhs) {
real_+=rhs.real_;
imag_+=rhs.imag_;
return *this;
}
complex& operator-=(const complex & rhs) {
real_-=rhs.real_;
imag_-=rhs.imag_;
return *this;
}
complex& operator*=(const complex & rhs) {
mpfr_float a = real_*rhs.real_ - imag_*rhs.imag_; // cache the real part of the result
imag_ = real_*rhs.imag_ + imag_*rhs.real_;
real_ = a;
return *this;
}
complex& operator/=(const complex & rhs) {
mpfr_float d = rhs.abs2();
mpfr_float a = real_*rhs.real_ + imag_*rhs.imag_; // cache the numerator of the real part of the result
imag_ = imag_*rhs.real_ - real_*rhs.imag_/d;
real_ = a/d;
return *this;
}
complex operator-() const
return complex(-real(), -imag());
}
mpfr_float abs2() const {
return pow(real(),2)+pow(imag(),2);
}
mpfr_float abs() const {
return sqrt(abs2());
}
mpfr_float arg() const {
return boost::multiprecision::atan2(imag(),real());
}
mpfr_float norm() const {
return abs2();
}
complex conj() const {
return complex(real(), -imag());
}
void precision(unsigned int prec) {
real_.precision(prec);
imag_.precision(prec);
}
unsigned int precision() const {
assert(real_.precision()==imag_.precision());
return real_.precision();
}
friend std::ostream& operator<<(std::ostream& out, const complex & z) {
out << "(" << z.real() << "," << z.imag() << ")";
return out;
}
friend std::istream& operator>>(std::istream& in, complex & z) {
std::string gotten;
in >> gotten;
if (gotten[0]=='(') {
if (*(gotten.end()-1)!=')') {
in.setstate(std::ios::failbit);
z.real("NaN");
z.imag("NaN");
return in;
}
else{
// try to find a comma in the string.
size_t comma_pos = gotten.find(",");
// if the second character, have no numbers in the real part.
// if the second to last character, have no numbers in the imag part.
if (comma_pos!=std::string::npos){
if (comma_pos==1 || comma_pos==gotten.size()-2) {
in.setstate(std::ios::failbit);
z.real("NaN");
z.imag("NaN");
return in;
}
else{
z.real(gotten.substr(1, comma_pos-1));
z.imag(gotten.substr(comma_pos+1, gotten.size()-2 - (comma_pos)));
return in;
}
}
// did not find a comma
else{
z.real(gotten.substr(1,gotten.size()-2));
z.imag("0.0");
return in;
}
}
}
else{
z.real(gotten);
z.imag("0.0");
return in;
}
}
}; // end declaration of the mynamespace::complex number class
inline complex operator+(complex lhs, const complex & rhs){
lhs += rhs;
return lhs;
}
inline complex operator+(complex lhs, const mpfr_float & rhs) {
lhs.real(lhs.real()+rhs);
return lhs;
}
inline complex operator+(const mpfr_float & lhs, complex rhs) {
return rhs+lhs;
}
inline complex operator-(complex lhs, const complex & rhs){
lhs -= rhs;
return lhs;
}
inline complex operator-(complex lhs, const mpfr_float & rhs) {
lhs.real(lhs.real()-rhs);
return lhs;
}
inline complex operator-(const mpfr_float & lhs, complex rhs) {
rhs.real(lhs - rhs.real());
return rhs;
}
inline complex operator*(complex lhs, const complex & rhs){
lhs *= rhs;
return lhs;
}
inline complex operator*(complex lhs, const mpfr_float & rhs) {
lhs.real(lhs.real()*rhs);
lhs.imag(lhs.imag()*rhs);
return lhs;
}
inline complex operator*(const mpfr_float & lhs, complex rhs) {
return rhs*lhs; // it commutes!
}
inline complex operator/(complex lhs, const complex & rhs){
lhs /= rhs;
return lhs;
}
inline complex operator/(complex lhs, const mpfr_float & rhs) {
lhs.real(lhs.real()/rhs);
lhs.imag(lhs.imag()/rhs);
return lhs;
}
inline complex operator/(const mpfr_float & lhs, const complex & rhs) {
mpfr_float d = rhs.abs2();
return complex(lhs*rhs.real()/d, -lhs*rhs.imag()/d);
}
inline mpfr_float real(const complex & z) {
return z.real();
}
inline mpfr_float imag(const complex & z) {
return z.imag();
}
inline complex conj(const complex & z) {
return z.conj();
}
inline mpfr_float abs2(const complex & z) {
return z.abs2();
}
inline mpfr_float abs(const complex & z) {
return boost::multiprecision::sqrt(abs2(z));
}
inline mpfr_float arg(const complex & z) {
return boost::multiprecision::atan2(z.imag(),z.real());
}
inline complex inverse(const complex & z) {
mpfr_float d = z.abs2();
return complex(z.real()/d, -z.imag()/d);
}
inline complex square(const complex & z) {
return complex(z.real()*z.real() - z.imag()*z.imag(), mpfr_float("2.0")*z.real()*z.imag());
}
inline complex pow(const complex & z, int power) {
if (power < 0) {
return pow(inverse(z), -power);
}
else if (power==0)
return complex("1.0","0.0");
else if(power==1)
return z;
else if(power==2)
return z*z;
else if(power==3)
return z*z*z;
else {
unsigned int p(power);
complex result("1.0","0.0"), z_to_the_current_power_of_two = z;
// have copy of p in memory, can freely modify it.
do {
if ( (p & 1) == 1 ) { // get the lowest bit of the number
result *= z_to_the_current_power_of_two;
}
z_to_the_current_power_of_two *= z_to_the_current_power_of_two; // square z_to_the_current_power_of_two
} while (p >>= 1);
return result;
}
}
inline complex polar(const mpfr_float & rho, const mpfr_float & theta) {
return complex(rho*cos(theta), rho*sin(theta));
}
inline complex sqrt(const complex & z) {
return polar(sqrt(abs(z)), arg(z)/2);
}
} // re: namespace
What am I doing wrong? What can I do to Eigen / NumTraits / etc to get matrix operations to work correctly?
This strange nan behavior was caused be a bug in the boost/multiprecision/mpfr.hpp file, appearing in Boost versions 1.56, 1.57 and presumably earlier. The assignment operator did not test for self-assignment -- so the number was set to nan.
Why this happened every other row, and on the last row if the matrix size was odd, is still unclear to me. However, adding a test for self-assignment, à la the commit on GitHub here, fixes the problem. An official patch from the maintainer is forthcoming, but will/did not make it into 1.58. I give thanks to John on the Boost user's mailing list for finding the bug.
If you want to fix this bug in your installation of Boost, in boost/multiprecision/mpfr.hpp, simply wrap the contents (not including return) of the reference assignment operator in if(this != &o){...}.
One lingering question I have regards the Eigen implementation -- what is causing the self-assignment? Is it a problem in general?
Related
Having trouble with the overloaded IOstream in my C++ class, the code below is my header file, so there is no main(). The overloaded iostream seems to work with simple cin and cout calls, but when put into more complex ones, it throws no match for operato<< and operator>>.
/*
Provide three constructors Complex(a, b), Complex(a), and Complex(). Complex()
creates a Complex object for number 0 and Complex(a) creates a Complex object with 0 for b.
Also provide the getRealPart() and getImaginaryPart() functions for returning
the real and imaginary part of the complex number, respectively.
*/
/*
Overload the operators +, -, *, /, +=, -=, *=, /=, [ ], unary + and -, prefix ++ and --,
postfix ++ and --, <<, >>. Overload the operators +, -, *, / as nonmember functions.
*/
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
using namespace std;
class Complex{
public:
Complex();
Complex(double a);
Complex(double a, double b);
void set_I(double input);
void set_R(double input);
double get_I_comp() const; //I accessor
double get_R_comp() const; // double accessor
double getRealPart();
double getImaginaryPart();
Complex operator+(Complex other);
Complex operator+(double other);
Complex operator-(Complex other);
Complex operator-(double other);
Complex operator*(Complex other);
Complex operator*(double other);
Complex operator/(Complex other);
Complex operator/(double other);
void operator++();
Complex& operator++(int dummy);
void operator+=(Complex other);
void operator+=(double other);
void operator-=(Complex other);
void operator-=(double other);
void operator*=(double other);
void operator*=(const Complex& other);
void operator/=(double other);
void operator/=(const Complex& other);
void operator- ();
void operator+ ();
double& operator[](int index);
Complex& operator<<(const int& intput);
Complex& operator>>(const string& output);
friend ostream& operator<<(ostream& out, Complex& target);
friend istream& operator>>(const istream& input, Complex& target);
std::string toString() //temporary solution right now
{
if (this->c_I != 0){
string ret = std::to_string(c_R);
ret = ret + " + ";
ret = ret + std::to_string(c_I);
ret = ret + " i \n";
return ret;
}
else{
string ret = std::to_string(c_R);
return ret;
}
}
Complex& add(double num);
Complex& add(Complex other);
Complex& subtract(double num);
Complex& subtract(Complex other);
Complex& multiply(double num);
Complex& multiply(Complex other);
Complex& divide(double num);
Complex& divide(Complex other);
Complex& abs();
private:
double c_I;
double c_R;
};
Complex::Complex() : c_I(0),c_R(0){ //works
}
Complex::Complex(double a) :c_I(0),c_R(a){ //works
}
Complex::Complex(double a, double b){ //works // at first I have the i as a and r as b, so thats why is fliped
this->c_I = b;
this->c_R = a;
}
double Complex::get_I_comp() const{
return c_I;
}
double Complex::get_R_comp() const{
return c_R;
}
double Complex::getImaginaryPart(){
return c_I;
}
double Complex::getRealPart(){
return c_R;
}
void Complex::set_I(double input){
c_I = input;
}
void Complex::set_R(double input){
c_R = input;
}
Complex Complex::operator+(Complex other){
Complex ret( (this->c_R + other.get_R_comp() ),(this->c_I + other.get_I_comp()));
return (ret);
}
Complex Complex::operator+(double other){
Complex ret(this->c_R + other,this->c_I);
return ret;
}
Complex Complex::operator-(Complex other){
Complex ret(this->c_R - other.get_R_comp(),this->c_I - other.get_I_comp());
return ret;
}
Complex Complex::operator-(double other){
Complex ret(this->c_R - other,this->c_I);
return ret;
}
Complex Complex::operator*(double other){
Complex ret(this->c_R * other ,this->c_I *other);
return ret;
}
Complex Complex::operator*(Complex other){
if((other.get_I_comp() != 0) && (other.get_R_comp() != 0) ){
Complex ret = other * (this->c_R);
Complex neu(-(other.get_I_comp()*this->c_I),other.get_R_comp()*this->c_I);
return (ret + neu);
}
if((other.get_I_comp() == 0 ) && (other.get_R_comp() != 0)){
Complex ret(this->c_R,this->c_I);
ret = ret * other.get_R_comp();
return ret;
}
else{
Complex ret((-((this->c_I)*other.get_I_comp())),(this->c_R)*other.get_I_comp());
return ret;
}
}
Complex Complex::operator/(double other){
if (other == 0) { // zero division error handler
throw runtime_error("Math error: Can't div by zero\n");
return 1;
}
if(other != 0){
Complex ret(this->c_R/other,this->c_I/other);
return ret;
}
}
//To divide a+bi by c+id we will perform the operation (ac+bd)/(c^2 + d^2) + (bc-ad)/(c^2 + d^2)i.
Complex Complex::operator/(Complex other){
if ((other.get_I_comp() != 0) && (other.get_R_comp() != 0)){
double first = ((this->c_R)*other.get_R_comp() + (this->c_I)*other.get_I_comp())/(other.get_R_comp()*other.get_R_comp() + other.get_R_comp()*other.get_R_comp());
double second = (this->c_I*other.get_R_comp() + c_R*other.get_I_comp())/(other.get_R_comp()*other.get_R_comp() + other.get_I_comp()*other.get_I_comp());
Complex ret(first,second);
return ret;
}
if((other.get_I_comp() == 0 ) && (other.get_R_comp() != 0)){
Complex ret(this->c_R,this->c_I);
ret = ret *(1/other.get_R_comp());
return ret;
}
else{
Complex ret(this->c_R,this->c_I);
Complex neu(1/other.get_I_comp());
ret = ret * neu;
return ret;
}
}
void Complex::operator++(){
c_R++;
}
Complex& Complex::operator++(int dummy){
Complex temp = *this;
++temp;
c_R++;
return temp;
}
void Complex::operator+=(double other){
c_R += other;
}
void Complex::operator+=(Complex other){
c_R += other.get_R_comp();
c_I += other.get_I_comp();
}
void Complex::operator-=(double other){
c_R +=(-1*other);
}
void Complex::operator-=(Complex other){
c_R -= other.get_R_comp();
c_I -= other.get_I_comp();
}
void Complex::operator*=(double other){
Complex& reference = *this; //pass by reference editing
reference = reference* other;
}
void Complex::operator*=(const Complex& rhs){
Complex& reference = *this;
reference = reference * rhs;
}
void Complex::operator/=(double other){
Complex& reference = *this;
reference = reference / other;
}
void Complex::operator/=(const Complex& rhs){
Complex& reference = *this;
reference = reference / rhs;
}
double& Complex::operator[](int index){
if(index <= 1){
return(index == 0 ? c_R : c_I);
}
else{
throw std::out_of_range ("index outta bound");
}
}
void Complex::operator-(){
c_R*=(-1);
c_I*=(-1);
}
void Complex::operator+(){
if(c_R<0){
c_R*=(-1);
}
if(c_I<0){
c_I*=(-1);
}
}
Complex& Complex::add(double num){
Complex& reference = *this;
reference = reference + num;
return reference;
}
Complex& Complex::add(Complex other){
Complex& reference = *this;
reference = reference + other;
return reference;
}
Complex& Complex::subtract(double num){
Complex& reference = *this;
reference = reference - num;
return reference;
}
Complex& Complex::subtract(Complex other){
Complex& reference = *this;
reference = reference - other;
return reference;
}
Complex& Complex::multiply(double num){
Complex& reference = *this;
reference = reference*num;
return reference;
}
Complex& Complex::multiply(Complex other){
Complex& reference = *this;
reference = reference * other;
return reference;
}
Complex& Complex::divide(double num){
Complex& reference = *this;
reference = reference/num;
return reference;
}
Complex& Complex::divide(Complex other){
Complex& reference = *this;
reference = reference/other;
return reference;
}
Complex& Complex::abs(){
Complex& reference = *this;
+reference;
return reference;
}
ostream& operator<<(ostream& out, Complex& target){
out << "Real : ";
out << " " << target.getRealPart();
out << " imaginary :";
out <<target.getImaginaryPart();
return out;
}
istream& operator>>(const istream& input, Complex& target) {
string use;
input>>use;
stringstream convert(use);
int x = 0;
convert>>x;
target.set_R(x);
return input;
}
when doing calls such as
cout << "(" << number1 << ")" << " + " << "(" << number2 << ") = " << (number1 + number2) << endl;
it throws the following exception:
main.cpp:19:69: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream’ and ‘Complex’)
cout << "(" << number1 << ")" << " + " << "(" << number2 << ") = " << (number1 + number2) << endl;
In file included from main.cpp:1:0:
Complex.h:276:10: note: candidate: std::ostream& operator<<(std::ostream&, Complex&)
ostream& operator<<(ostream& out, Complex& target){
You have to overload the following function too!.
ostream& operator<<(ostream& out, Complex&& target){
out << "Real : ";
out << " " << target.getRealPart();
out << " imaginary :";
out <<target.getImaginaryPart();
return out;
}
Non-const references don't bind to temporaries.
So ostream& operator<<(ostream& out, Complex& target) can't be used in code that looks like cout << Complex{1.0} or cout << (complex1 + complex2), because in both cases the second argument is a temporary Complex instance.
A possible fix is to use const references when you don't plan to modify the argument:
ostream& operator<<(ostream& out, Complex const& target)
Another solution (for small objects) is to accept it by-value:
ostream& operator<<(ostream& out, Complex target)
I'm trying to create a set of classes in order to handle complex numbers. I've seen that there is already a set of classes for the complex numbers, but because I'm learning C++ I thought it was a good idea to create a basic implementation. The problem comes up when I tried to overload the operator "/". I got a segfault and I can't understand if the problem is my implementation of the division:
complex.hpp :
#include <iostream>
#include <cstdlib>
class Complex {
float real;
float imm;
public:
Complex(float new_real = 0,float new_imm = 0) {this->real = new_real;this->imm = new_imm;}
void set(float new_real,float new_imm) {this->real = new_real; this->imm = new_imm;}
float get_real(void) const { return this->real;}
float get_imm(void) const { return this->imm;}
Complex conj(void) const {Complex tmp; tmp.set(this->real,-1.0 * this->imm); return tmp;}
friend std::ostream& operator<<(std::ostream& os, const Complex& cpx) {os << "Real: " << cpx.real << " Imm: " << cpx.imm << std::endl; return os; }
friend Complex operator*(const Complex& lhs,const Complex& rhs);
friend Complex operator+(const Complex& lhs,const Complex& rhs);
friend Complex operator+(const Complex& lhs,const float& rhs);
};
complex.cpp:
#include "complex.hpp"
Complex operator*(const Complex& lhs,const Complex& rhs)
{
float real_part = (lhs.real * rhs.real) - ( lhs.imm * rhs.imm);
float imm_part = (lhs.real * rhs.imm) + ( lhs.imm * rhs.real);
Complex result;
result.set(real_part,imm_part);
return result;
}
Complex operator+(const Complex& lhs,const Complex& rhs)
{
float real_part = lhs.real + rhs.real;
float imm_part = lhs.imm + rhs.imm;
Complex result;
result.set(real_part,imm_part);
return result;
}
Complex operator+(const Complex& lhs,const float& rhs)
{
float real_part = lhs.real + rhs;
float imm_part = lhs.imm;
Complex result;
result.set(real_part,imm_part);
return result;
}
Complex operator/(const Complex& lhs,const Complex& rhs)
{
Complex numerator(0,0);
numerator = rhs * rhs.conj();
Complex denominator(0,0);
denominator = lhs * rhs.conj();
Complex result;
float real_numerator = numerator.get_real();
result = denominator / real_numerator;
return result;
}
Complex operator/(const Complex& lhs,const float& rhs)
{
float real_part = lhs.get_real() / rhs;
float imm_part = lhs.get_imm() / rhs;
Complex result;
result.set(real_part,imm_part);
return result;
}
The whole idea of the division between 2 complex is to multiply the numerator and denominator for the conjugate of the numerator in order to have only a real number on the numerator. Just to make it clear :
(a + ib) / (c + id) = ((a + ib) / (c + id)) * ((c - id) / (c - id)) = ((a + ib) * (c - id)) / (c^2 + d^2)
Now when I try to do this:
main.cpp :
int main(int argc, char *argv[])
{
Complex x(4,8);
Complex y(3,7);
Complex result = x / y;
result = x / 6;
return 0;
}
I got this segfault, which I don't understand:
(gdb) break main
Breakpoint 2 at 0x401c56: file equalization_main.cpp, line 49.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
`/home/campiets/workspace/frontend/dfe_equalizer_fe/dev/view/src_c/test' has changed; re-reading symbols.
Starting program: /home/campiets/workspace/frontend/dfe_equalizer_fe/dev/view/src_c/test
Breakpoint 2, main (argc=1, argv=0x7fffffffbf08) at equalization_main.cpp:49
49 Complex x(4,8);
(gdb) n
50 Complex y(3,7);
(gdb) n
51 Complex result = x / y;
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401e64 in Complex::Complex (this=<error reading variable: Cannot access memory at address 0x7fffff3feff8>, new_real=<error reading variable: Cannot access memory at address 0x7fffff3feff4>,
new_imm=<error reading variable: Cannot access memory at address 0x7fffff3feff0>) at complex.hpp:38
38 Complex(float new_real = 0,float new_imm = 0) {this->real = new_real; this->imm = new_imm;}
Any ideas ?
Complex operator/(const Complex& lhs,const Complex& rhs)
{
...
Complex denominator...;
...
float real_numerator = ...;
result = denominator / real_numerator;
...
}
That's infinite recursion.
Since the compiler hasn't seen operator/(const Complex &lhs, const float &rhs), it converts the float argument to Complex and hence you get recursion.
The simplest solution is to declare or define operator/(const Complex &lhs, const float &rhs) before operator/(const Complex &lhs, const Complex &rhs).
My preference would be to implement the operators as class members, though. That yields simpler source code and solves the problem too.
The function
Complex operator/(const Complex& lhs,const Complex& rhs) { ... }
causes stack overflow since the line
result = denominator / real_numerator;
ends up being interpreted as:
result = denominator / Complex(real_numerator);
You can resolve that problem by defining or declaring
Complex operator/(const Complex& lhs, const float& rhs)
before it.
If you change your code to use:
Complex operator/(const Complex& lhs,const float& rhs)
{
return Complex(lhs.get_real()/rhs, lhs.get_imm()/rhs);
}
Complex operator/(const Complex& lhs,const Complex& rhs)
{
...
}
your program will work ok.
A suggestion for simplifying the above operator/ function.
If you add the following member function
float magnitude_square() const { return (real*real + imm*imm); }
then you can use
Complex operator/(const Complex& lhs,const Complex& rhs)
{
return (lhs * rhs.conj())/rhs.magnitude_square());
}
I have this formatted string in an istream.
(5, -4)
Let say :
open parenthesis
an integer number
comma and space
another integer number
close parenthesis
I would like to know what is the best approach to extract both integers and validate the string formatting.
This is in a class like this :
class MyPoint
{
public:
MyPoint() = default;
~MyPoint() = default;
...
friend ostream & operator>>(ostream & lhs, MyPoint const & rhs);
...
private:
int x, y;
};
ostream & operator>>(ostream & lhs, MyPoint const & rhs) {
// ???
}
Many thanks to all.
Here is my header file
#ifndef MYPOINT_H
#define MYPOINT_H
#include <iostream>
using namespace std;
class MyPoint
{
public:
MyPoint() : mX{ 0 }, mY{ 0 } { ; }
MyPoint(int x, int y) : mX{ x }, mY{ y } { ; }
~MyPoint() = default;
int x() const { return mX; }
int y() const { return mY; }
void setX(int x) { mX = x; }
void setY(int y) { mY = y; }
MyPoint operator-() const { return MyPoint(-mX, mY); }
MyPoint operator+(MyPoint rhs) const { rhs.mX += mX; rhs.mY += mY; return rhs; }
MyPoint operator-(MyPoint rhs) const { rhs.mX = mX - rhs.mX; rhs.mY = mY - rhs.mY; return rhs; }
MyPoint operator*(MyPoint rhs) const { rhs.mX *= mX; rhs.mY *= mY; return rhs; }
MyPoint operator/(MyPoint rhs) const { rhs.mX = mX / rhs.mX; rhs.mY = mY / rhs.mY; return rhs; }
MyPoint operator%(MyPoint rhs) const { rhs.mX = mX % rhs.mX; rhs.mY = mY % rhs.mY; return rhs; }
friend MyPoint operator+(int lhs, MyPoint const & rhs);
friend MyPoint operator-(int lhs, MyPoint const & rhs);
friend MyPoint operator*(int lhs, MyPoint const & rhs);
friend MyPoint operator/(int lhs, MyPoint const & rhs);
friend MyPoint operator%(int lhs, MyPoint const & rhs);
friend ostream & operator<<(ostream & lhs, MyPoint const & rhs);
friend istream & operator>>(istream & lhs, MyPoint & rhs);
private:
int mX, mY;
};
#endif //MYPOINT_H
And here my source file
#include "MyPoint.h"
MyPoint operator+(int lhs, MyPoint const & rhs) {
return MyPoint(lhs + rhs.mX, lhs + rhs.mY);
}
MyPoint operator-(int lhs, MyPoint const & rhs) {
return MyPoint(lhs - rhs.mX, lhs - rhs.mY);
}
MyPoint operator*(int lhs, MyPoint const & rhs) {
return MyPoint(lhs * rhs.mX, lhs * rhs.mY);
}
MyPoint operator/(int lhs, MyPoint const & rhs) {
return MyPoint(lhs / rhs.mX, lhs / rhs.mY);
}
MyPoint operator%(int lhs, MyPoint const & rhs) {
return MyPoint(lhs % rhs.mX, lhs % rhs.mY);
}
ostream & operator<<(ostream & lhs, MyPoint const & rhs) {
return lhs << "(" << rhs.mX << "," << rhs.mY << ")";
}
istream & operator >> (istream & lhs, MyPoint & rhs) {
return lhs >> "(" >> rhs.mX >> "," >> rhs.mY >> ")"; // HERE is the compiling error
}
And finally, the tests in the main
MyPoint p1, p2(2, -2);
cout << p1 << endl;
cout << p2 << endl;
With this file, I got this error :
Error C2679 binary '>>': no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
For situations like this, I've often found it handy to define an overload of operator>> to read a predefined string from a stream:
std::istream &operator>>(std::istream &is, char const *pat) {
char ch;
while (isspace(static_cast<unsigned char>(is.peek())))
is.get(ch);
while (*pat && is && *pat == is.peek() && is.get(ch)) {
++pat;
}
// if we didn't reach the end of the pattern, matching failed (mismatch, premature EOF, etc.)
if (*pat) {
is.setstate(std::ios::failbit);
}
return is;
}
With this, reading your format might look something like this:
istream & operator>>(istream & lhs, MyPoint & rhs) {
return lhs >> "(" >> rhs.x >> "," >> rhs.y >> ")";
}
This will do like most typical overloads and set the stream's fail bit if the pattern you've given isn't matched. As it stands now, each string in the input can be preceded by arbitrary white space (just like conversions for numbers and such).
There is technically a minor bug here: as it stands right now, this uses the global locale's definition of whitespace. To be really correct, it should probably use the definition provided in the locale associated with the input stream.
Also note that I had to change your definition of operator>> bit; in the question it looks like an overload of operator<<, with just those two characters changed to get operator>> instead.
For a quick example:
#include <iostream>
std::istream &operator>>(std::istream &is, char const *pat) {
// implementation above
}
class Point {
int x, y;
friend std::istream &operator>>(std::istream &is, Point &p) {
return is >> "(" >> p.x >>"," >> p.y >> ")";
}
friend std::ostream &operator<<(std::ostream &os, Point const &p) {
return os << "(" << p.x <<", " << p.y << ")";
}
};
int main() {
Point p;
std::cout << "Please enter a point: ";
std::cin >> p;
std::cout << "Thanks. Point: " << p << '\n';
}
Tested with VC++ 2013, VC++ 2015, and g++ 6.1 (but this isn't pushing the limits of compilers at all, so I'd expect it to work fine even with compilers so old they're horribly broken in general (e.g., gcc 2.x or VC++ 6.0).
This question already has an answer here:
About c++11 range for loops and iterators
(1 answer)
Closed 7 years ago.
OH! I found the problem. As I said at end, it was a simple problem.
In for loop, i iterated wiht copy of "Particle"s. I updated them but the operation does not affect the original values that stored in vector.
For requests about solution one can access the particle objects using 3 major ways.
lvalue-ref object way:
for (auto& p: particles)
...
Or by iterators:
for (auto it=particles.begin(); i<particles.end();++it)
...
Or by plain indexes:
for (size_t i=0; i<particles.size(); ++i)
...
For ones that curious about code, you may look below:
If I am not missing something very obvious, I encountered with a really strange problem.
To simplify the problem, I have a class named "Particle", which has a function called "update". Particle class has some private variables like position, velocity etc. And update function is supposed to make some calculations and add proper values to that private variables. But, that simply does not work.
Actually, I am sceptical about the type of that variables which is a class written by me, "Vector2".
To add values to variables, I've used the "+=" operator, and I think I implemented them correctly(?) in my Vector2 class.
To clarify situation, IMHO, it is better to give some code:
This is my Vector2.h :
namespace sim {
#include <ostream>
#include <cmath>
using namespace std;
struct Vector2 {
double x, y;
Vector2& operator+=(const Vector2& rhs) {
this->x += rhs.x;
this->y += rhs.y;
cout << "op+=" << endl;
return *this;
}
Vector2& operator*=(double k) {
x *= k;
y *= k;
cout << "op*=" << endl;
return *this;
}
friend ostream& operator<<(ostream& os, const Vector2& v2);
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);
};
ostream& operator<<(ostream& os, const Vector2& v2) {
os << "[ " << v2.x << "; " << v2.y << " ]";
return os;
}
Vector2 operator+(Vector2 lhs, const Vector2& rhs) {
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) {
lhs *= k;
cout << "op*" << endl;
return lhs;
}
(removed some unrelated parts like constructor)
And this is Particle class:
class Particle {
private:
Vector2 pos;
Vector2 vel;
Vector2 acc;
double rad;
SDL_Color clr;
public:
Particle(
Vector2 _p,
Vector2 _v,
Vector2 _a,
double _r = 10.0,
SDL_Color _c = { 255, 255, 255, 255 }) {
pos = _p;
vel = _v;
acc = _a;
rad = _r;
clr = _c;
}
Vector2& move_particle(Vector2 move_by) {
return (pos += move_by);
}
void update(double dt) {
this->vel += acc * dt;
this->pos += vel * dt;
cout << "update " << pos << vel << acc << endl;
}
void render(SDL_Renderer* renderer) {
// TODO: this was supposed to be a circle, but, who cares? ;)
SDL_Rect r = { int(pos.x), int(pos.y), int(rad), int(rad) };
SDL_RenderFillRect(renderer, &r);
cout << "render" << endl;
}
};
And the result: update does not update.
How do I know (guess) my overloads DOES work?
For 3 Vector2 objects, I can do any kind of operation I defined correctly.
And the results are just what they supposed to be. (Or, maybe not?)
But debugging update function roughly brings me to the point that actually += operator works for one time, and not again BUT this behaviour is showing itself only in update function.
And I know, this will be such a simple mistake that I possibly feel ashamed (just kidding).
Oh, and the main code of course:
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
auto window = SDL_CreateWindow("My Very First Particle Simulation", -1, -1,
1024, 768, SDL_WINDOW_SHOWN);
auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
const Vector2 g(0.0, 9.8);
double dt = 0.1;
std::vector<Particle> particles;
bool quit = false;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONUP:
particles.emplace_back(Vector2(event.button.x, event.button.y), Vector2(1.0, 0.0), g);
break;
default:
break;
}
SDL_RenderClear(renderer);
for (auto p : particles) {
p.update(dt);
p.render(renderer);
}
SDL_RenderPresent(renderer);
}
}
}
Some comments on your code,
you can just change these to be member functions
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 lhs);
as in
Vector2 operator+(const Vector2& rhs);
Vector2 operator-(const Vector2& rhs);
Vector2 operator*(const double k);
friend Vector2 operator*(const double k, Vector2 lhs);
In them copy this to a new Vector2 and then update the value and return. The fourth function is kept as friend so that you can have something like double*Vector2 while the third one takes care of Vector2*double
Any operation that has Vector2 as the left operand can be done as a member function.
I can see that these two operators are taking their first args by value. Change them so the take their args by reference.
Vector2 operator+(Vector2 lhs, const Vector2& rhs) { // lhs should be a const reference
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) { // lhs should be a const reference
lhs *= k;
cout << "op*" << endl;
return lhs;
}
EDIT:
Also these functions should take their class args as const referenecs:
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);
I am working on an assignment for my c++ class. We are having to overload several operators such as +, -, !=, =, etc. Well, I have all of them figured out except the multiplication. Everything I have tried gives an overflow or just doesn't compile. Not sure what I need for it.
Here is the header file that holds my overloads.
#ifndef COMPLEXNUMBER_H
#define COMPLEXNUMBER_H
#include<iostream>
using namespace std;
class ComplexNumber{
public:
double real, imaginary;
ComplexNumber(){
real = 0;
imaginary = 0;
}
ComplexNumber(double a, double b){
real = a;
imaginary = b;
}
ComplexNumber(double a){
real = a;
imaginary = 0;
}
ComplexNumber & operator= (const ComplexNumber & rhs){
if(this == &rhs){
return *this;
}
else{
real = rhs.imaginary;
imaginary = rhs.imaginary;
}
return *this;
}
ComplexNumber & operator+= (const ComplexNumber &rhs){
real += rhs.real;
imaginary += rhs.imaginary;
return *this;
}
ComplexNumber & operator-= (const ComplexNumber &rhs){
real -= rhs.real;
imaginary -= rhs.imaginary;
return *this;
}
const ComplexNumber operator+ (const ComplexNumber &rhs){
ComplexNumber result = *this;
result += rhs;
return result;
}
const ComplexNumber operator- (const ComplexNumber &rhs){
ComplexNumber result = *this;
result -= rhs;
return result;
}
const ComplexNumber operator* (const ComplexNumber &rhs){
return *this * rhs;
}
friend ostream & operator<< (ostream &out, const ComplexNumber &c){
out << "(" << c.real << (c.imaginary<0?" - ":" + ") << abs(c.imaginary) << " i)";
return out;
}
friend istream & operator>> (istream & in, ComplexNumber &c){
in >> c.real >> c.imaginary;
return in;
}
operator double(){
return real;
}
bool operator== (const ComplexNumber & rhs) const {
bool result = (this->real == rhs.real) && (this->imaginary == rhs.imaginary);
return result;
}
bool operator!= (const ComplexNumber &rhs) const{
return !(*this == rhs);
}
};
#endif
I know that multiplication operator is way off, but its just what I have at the moment. Here it is on its own. Any ideas would be greatly appreciated!!
const ComplexNumber operator* (const ComplexNumber &rhs){
return *this * rhs;
}
It gives you an overflow because of the way you call it. With your call, you are multiplying a complex number with a complex number, and it just keeps calling the same operator without doing anything. You could try to use some basic math and derive the formula for complex number multiplication. Specifically, let's say we have two complex numbers Z1 and Z2. Let Z1 = a + bi, where a is the real part, and b is the imaginary part, and Z2 = c + di, where c is the real part, and d is the imaginary part. We have Z1 * Z2 = (a + bi)(c + di) = ( ac + adi + cbi - bd ). Now, we separate the real and the imaginary part, the real part here is everything without i, so ac - bd, and the imaginary part would be ad + cb. Now, use that in the terms of your class members, and you would get something like this:
const ComplexNumber operator* (const ComplexNumber &rhs)
{
ComplexNumber result;
result.real = real * rhs.real - imaginary * rhs.imaginary;
result.imaginary = real * rhs.imaginary + imaginary * rhs.real;
return result;
}