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());
}
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 have a vector3 class which i need to implement different multiplication options ( so i overloaded the operator *) depending of the types that im multiplying.
The problem is that in the last one i get the error:
Description Resource Path Location Type
ambiguating new declaration of 'Pang::vector3 Pang::operator*(const Pang::vector3&, const Pang::vector3&)' vector3.h /PangGame/src line 130
C/C++ Problem
But i have only one operator overloaded that returns vector and muyltiplies two vectors.
Hope you can help ( just to clarify the class vector 3 has threee double numbers ) ex: vector3(double x, double y, double z); )
friend vector3 operator* (const double& number, const vector3& vector)
{
vector3 result;
result.x = number*vector.x;
result.y = number*vector.y;
result.z = number*vector.z;
return result;
}
friend vector3 operator* (const vector3& vector, const double& number)
{
vector3 result;
result.x = number*vector.x;
result.y = number*vector.y;
result.z = number*vector.z;
return result;
}
//Scalar product: If a = a1i + a2j + a3k and b = b1i + b2j + b3k then
// a · b = a1*b1 + a2*b2 + a3*b3
friend double operator* (const vector3& vector1, const vector3& vector2)
{
double result;
result= (vector1.x)*(vector2.x)+(vector1.y)*(vector2.y) + (vector1.z)*(vector2.z);
return result;
}
/* Product: Vector x Vector
* Example: The cross product of a = (2,3,4) and b = (5,6,7)
cx = aybz - azby = 3×7 - 4×6 = -3
cy = azbx - axbz = 4×5 - 2×7 = 6
cz = axby - aybx = 2×6 - 3×5 = -3
Answer: a × b = (-3,6,-3)*/
friend vector3 operator* (const vector3& vector,const vector3& vector2)
{
vector3 result;
result.x = (vector.y)*(vector2.z) - (vector.z)*(vector2.y);
result.y = (vector.z)*(vector2.x) - (vector.x)*(vector2.z);
result.z = (vector.x)*(vector2.y) - (vector.y)*(vector2.x);
return result;
}
The problem is that you are trying to overload operator* based on the return type:
double operator* (const vector3& vector1, const vector3& vector2)
vector3 operator* (const vector3& vector1, const vector3& vector2)
This is not allowed because overload resolution takes into account the function signature, which does not include the return type:
3.19 signature [defns.signature]
⟨function⟩ name, parameter-type-list, and enclosing namespace (if any)
One possible solution, if you do want your operator* to possibly yield either a double or another vector3, you can return a proxy type that is convertible to these types:
struct vector3_multiplication_proxy {
vector3 lhs, rhs;
operator double() { return 0; /* Your inner product calculation here */ }
operator vector3() { return {}; /* Your cross product calculation here */ }
};
vector3_multiplication_proxy operator* (const vector3& lhs, const vector3& rhs) {
return {lhs, rhs};
}
This does have lifetime pitfalls and may delay calculation depending on how you use it, so it may or may not be a good idea. In your particular case, it's probably a bad idea, because the inner and cross products are different things and should probably be denoted by different syntax.
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?
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;
}
I am implementing a complex number using operator overloading. In the program, the user enters a complex number ALWAYS in the form:
a + bi
So, in example...
25.0 + 3.6i
Assume that the user will always enter both the real and the imaginary parts of the complex number, e.g., the user will enter "5 + 0i" (and not "5") or "0 - 6.2i" (and not "-6.2i").
My problem is that in main() I have the following code:
ComplexNumber c1;
cin >> c1;
cout << c1;
and the code prints:
0 + 0i
...when I entered "4.2 + 8.3i" into the prompt during runtime.
Here is my implementation of my operator>> class:
istream & operator>>(istream & in, ComplexNumber & n) {
string real;
string imag;
bool done = false;
int sign = 1;
string num;
in >> num;
int length;
for (int i = 0; i < num.length(); i++) {
if (num.at(i) == 'i') {
imag = num.substr((i - length), i);
}
else if (num.at(i) == '-') {
sign = -1;
}
else if (num.at(i) == ' ') {
if (!done) {
real = num.substr(i);
done = true;
}
length = 0;
}
length++;
}
n = ComplexNumber(atof(real.c_str()), atof(imag.c_str()) * sign);
return in;
}
Here is my implementation of operator<< class:
ostream & operator<<(ostream & out, const ComplexNumber & n) {
n.print(out);
return out;
}
Here is my implementation of the ComplexNumber member class print():
void ComplexNumber::print(ostream & out) const {
if (imag >= 0)
out << real << " + " << imag << "i";
else
out << real << " - " << (-1 * imag) << "i";
}
This is my ComplexNumber header file for further details:
#ifndef COMPLEXNUMBER_H
#define COMPLEXNUMBER_H
#include <iostream>
using namespace std;
class ComplexNumber {
public:
// constructors
ComplexNumber();
ComplexNumber(double real_part, double imaginary_part);
ComplexNumber(const ComplexNumber & rhs);
// named member functions
void print(ostream & out = cout) const;
bool equals(const ComplexNumber & rhs) const;
// assignment operators
const ComplexNumber & operator=(const ComplexNumber & rhs);
const ComplexNumber & operator+=(const ComplexNumber & rhs);
const ComplexNumber & operator-=(const ComplexNumber & rhs);
const ComplexNumber & operator*=(const ComplexNumber & rhs);
private:
double real;
double imag;
};
// arithmetic operators
ComplexNumber operator+(const ComplexNumber & lhs, const ComplexNumber & rhs);
ComplexNumber operator-(const ComplexNumber & lhs, const ComplexNumber & rhs);
ComplexNumber operator*(const ComplexNumber & lhs, const ComplexNumber & rhs);
// relational operators
bool operator==(const ComplexNumber & lhs, const ComplexNumber & rhs);
bool operator!=(const ComplexNumber & lhs, const ComplexNumber & rhs);
// I/O operators
ostream & operator<<(ostream & out, const ComplexNumber & n);
istream & operator>>(istream & in, ComplexNumber & n);
#endif
Any help with my implementations would be great.
Essentially your operator >> is way too complex, and doesn’t even handle errors properly. You shouldn’t read the value into a string to begin with – read it directly into a number. Furthermore, after each read operation you need to check (and potentially set) the stream’s state.
istream& operator >>(istream& in, ComplexNumber& value) {
int re;
if (not (in >> re)) {
return in;
char pm;
if (not (in >> pm) or (pm != '+' and pm != '-') {
in.setstate(ios::failbit);
return in;
}
int im;
if (not (in >> im))
return in;
char i;
if (not (in >> i) or i != 'i') {
in.setstate(ios::failbit);
return in;
}
value = ComplexNumber {re, (pm == '-' ? -im : im)};
return in;
}
(I used C++11 initialisers because I’m lazy ….)
And, yes, this can be written even shorter by pulling the whole reading into a single chainged expression:
istream& operator >>(istream& in, ComplexNumber& value) {
int re;
int im;
char pm;
char i;
if (not (in >> re >> pm) or
(pm != '+' and pm != '-') or
not (in >> im >> i) or
i != 'i')
{
in.setstate(ios::failbit);
return in;
}
value = ComplexNumber {re, (pm == '-' ? -im : im)};
return in;
}
Whether this is better depends on the audience. Personally, I do find it more (!) readable than the first version. A more structured alternative (which would be overkill for such a simple case) is Boost.Qi which allows very elegant parser construction.
This part:
string num;
in >> num;
It reads only one word from input. You would need to call it several times to read something like 4.2 + 8.3i, which has three words.