Add your own alternative version
Stats
192.4K views 3.1K downloads 39 bookmarked
Posted
15 Dec 2002

Comments and Discussions



"The .NET platform doesn't have complex numbers built in."
is false since .Net v4.0 which introduced System.Numerics.Complex






Thanks for the library. I have updated it a bit and added a couple extensions. Here is the code:
complex.h:
#pragma once
using namespace System;
#include <complex>
namespace ComplexMath
{
public value class Complex
{
private:
double _real;
double _imag;
static Complex Convert(std::complex<double> c); public:
Complex(double real, double imag);
Complex(double real):_real(real),_imag(0)
{
}
Complex(std::complex<double>& Other);
virtual System::String^ ToString() override;
virtual System::String^ ToString(System::String^ Format);
static Complex operator +(Complex cLeft);
static Complex operator (Complex cLeft);
static Complex Plus(Complex cLeft)
{return operator +(cLeft);}
static Complex Negative(Complex cLeft)
{return operator (cLeft);}
static bool operator ==( Complex cLeft, Complex cRight);
static bool operator ==( Complex cLeft, double right);
static bool operator ==( double left, Complex cRight);
bool Equals( double number)
{return operator ==( *this,number);}
bool Equals( Complex c)
{return operator ==( *this,c);}
static bool Equals( Complex cLeft, Complex cRight)
{return operator ==( cLeft, cRight);}
static bool Equals( Complex cLeft, double right)
{return operator ==( cLeft, right);}
static bool Equals( double left, Complex cRight)
{return operator ==( left, cRight);}
static bool operator != ( Complex cLeft, Complex cRight)
{ return !operator ==(cLeft,cRight); }
static bool operator !=( Complex cLeft, double right)
{ return !operator ==(cLeft,right); }
static bool operator !=( double left, Complex cRight)
{ return !operator ==(left,cRight); }
static bool NotEqual( Complex cLeft, Complex cRight)
{ return !operator ==(cLeft,cRight); }
static bool NotEqual( Complex cLeft, double right)
{ return !operator ==(cLeft,right); }
static bool NotEqual( double left, Complex cRight)
{ return !operator ==(left,cRight); }
static Complex operator *( Complex cLeft, Complex cRight);
static Complex operator *( Complex cLeft, double right);
static Complex operator *( double left , Complex cRight);
static Complex Multiply( Complex cLeft, Complex cRight)
{ return operator *( cLeft, cRight); }
static Complex Multiply( Complex cLeft, double right)
{ return operator *( cLeft, right);}
static Complex Multiply( double left , Complex cRight)
{ return operator *( left , cRight); }
static Complex operator /( Complex cLeft , Complex cRight);
static Complex operator /( Complex cLeft , double right);
static Complex operator /( double left , Complex cRight);
static Complex Divide( Complex cLeft, Complex cRight)
{ return operator /( cLeft, cRight); }
static Complex Divide( Complex cLeft, double right)
{ return operator /( cLeft, right);}
static Complex Divide( double left , Complex cRight)
{ return operator /( left , cRight); }
static Complex operator +( Complex cLeft, Complex cRight);
static Complex operator +( Complex cLeft, double right);
static Complex operator +( double left, Complex cRight);
static Complex Add( Complex cLeft, Complex cRight)
{ return operator +( cLeft, cRight); }
static Complex Add( Complex cLeft, double right)
{ return operator +( cLeft, right);}
static Complex Add( double left , Complex cRight)
{ return operator +( left , cRight); }
static Complex operator ( Complex cLeft, Complex cRight);
static Complex operator ( Complex cLeft, double right);
static Complex operator ( double left, Complex cRight);
static Complex Subtract( Complex cLeft, Complex cRight)
{ return operator ( cLeft, cRight); }
static Complex Subtract( Complex cLeft, double right)
{ return operator ( cLeft, right);}
static Complex Subtract( double left , Complex cRight)
{ return operator ( left , cRight); }
property double x
{
double get()
{
return _real;
}
void set(double value)
{
_real=value;
}
}
property double y
{
double get()
{
return _imag;
}
void set(double value)
{
_imag=value;
}
}
property double Magnitude
{
double get()
{
return _real*_real+_imag*_imag;
}
void set(double value)
{
double arg = Complex::Arg(*this);
std::complex<double> c = std::polar(value,arg);
_real=c.real();
_imag=c.imag();
}
}
static double Abs(Complex c);
static double Arg(Complex c);
static Complex Conj(Complex c);
static double Imag(Complex c)
{ return c._imag;}
static double Real(Complex c)
{ return c._real;}
static Complex Polar(double r, double theta);
static Complex Polar(double r); static Complex Cos(Complex c);
static Complex Cosh(Complex c);
static Complex Exp(Complex c);
static Complex Log(Complex c);
static Complex Log10(Complex c);
static double Norm(Complex c);
static Complex Pow(Complex base, double power);
static Complex Pow(Complex base, Complex power);
static Complex Pow(double base, Complex power);
static Complex Sin(Complex c);
static Complex Sinh(Complex c);
static Complex Sqrt(Complex c);
static Complex Tan(Complex c);
static Complex Tanh(Complex c);
static Complex Parse(String^ Text);
};
}
complex.cpp:
#include "stdafx.h"
#include "complex.h"
using namespace System;
using namespace std;
namespace ComplexMath
{
Complex::Complex(double real, double imag):_real(real),_imag(imag)
{
}
Complex::Complex(std::complex<double>& Other):_real(Other.real()),_imag(Other.imag())
{
}
System::String^ Complex::ToString()
{ return String::Format("({0:g6},{1:g6})",_real,_imag);
}
System::String^ Complex::ToString(System::String^ Format)
{ return String::Format(Format,_real,_imag);
}
Complex Complex::operator +(Complex cLeft)
{
return cLeft;
}
Complex Complex::operator (Complex cLeft)
{
cLeft._imag=cLeft._imag;
cLeft._real=cLeft._real;
return cLeft;
}
bool Complex::operator ==( Complex cLeft, Complex cRight)
{
return (cLeft._imag == cRight._imag) && (cLeft._real == cRight._real);
}
bool Complex::operator ==( Complex cLeft, double right)
{
return (cLeft._real == right) && (cLeft._imag == 0);
}
bool Complex::operator ==( double left, Complex cRight)
{
return (left == cRight._real) && (cRight._imag == 0);
}
Complex Complex::operator +(Complex cLeft, Complex cRight)
{
cLeft._real+=cRight._real;
cLeft._imag+=cRight._imag;
return cLeft;
}
Complex Complex::operator +( Complex cLeft, double right)
{
cLeft._real+=right;
return cLeft;
}
Complex Complex::operator +( double left, Complex cRight)
{
cRight._real+=left;
return cRight;
}
Complex Complex::operator ( Complex cLeft, Complex cRight)
{
cLeft._real=cRight._real;
cLeft._imag=cRight._imag;
return cLeft;
}
Complex Complex::operator ( Complex cLeft, double right)
{
cLeft._real=right;
return cLeft;
}
Complex Complex::operator ( double left, Complex cRight)
{
return cRight+left;
}
Complex Complex::operator *(Complex c1, Complex c2)
{
return Complex(c1._real*c2._realc1._imag*c2._imag,c1._real*c2._imag+c2._real*c1._imag);
}
Complex Complex::operator *(Complex cLeft, double right)
{
return Complex(right*cLeft._real,right*cLeft._imag);
}
Complex Complex::operator *( double left , Complex cRight)
{
complex<double> C1(cRight._real,cRight._imag);
return Complex(left*C1);
}
Complex Complex::operator /(Complex c1, Complex c2)
{
complex<double> C1(c1._real,c1._imag);
complex<double> C2(c2._real,c2._imag);
return Convert(C1/C2);
}
Complex Complex::operator /( Complex cLeft, double right)
{
complex<double> C1(cLeft._real,cLeft._imag);
return Convert(C1/right);
}
Complex Complex::operator /( double left , Complex cRight)
{
complex<double> C1(cRight._real,cRight._imag);
return Convert(left/C1);
}
double Complex::Abs(Complex c)
{
std::complex<double> c1(c._real,c._imag);
double rval = abs(c1);
return rval;
}
double Complex::Arg(Complex c)
{
std::complex<double> c1(c._real,c._imag);
double rval = arg(c1);
return rval;
}
Complex Complex::Conj(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = conj(c1);
return Convert(c2);
}
Complex Complex::Cos(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = cos(c1);
return Convert(c2);
}
Complex Complex::Cosh(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = cosh(c1);
return Convert(c2);
}
Complex Complex::Exp(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = exp(c1);
return Convert(c2);
}
Complex Complex::Log(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = log(c1);
return Convert(c2);
}
Complex Complex::Log10(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = std::log10(c1);
return Convert(c2);
}
double Complex::Norm(Complex c)
{
std::complex<double> c1(c._real,c._imag);
return std::norm(c1);
}
Complex Complex::Polar(double r)
{
return Polar(r,0);
}
Complex Complex::Polar(double r, double theta)
{
std::complex <double> c1 ( polar (r,theta ) );
return Convert(c1);
}
Complex Complex::Pow(Complex base, double power)
{
std::complex<double> c1(base._real,base._imag);
return Convert(std::pow(c1,power));
}
Complex Complex::Pow(Complex base, Complex power)
{
std::complex<double> c1(base._real,base._imag);
std::complex<double> c2(power._real,power._imag);
return Convert(std::pow(c1,c2));
}
Complex Complex::Pow(double base, Complex power)
{
std::complex<double> c1(power._real,power._imag);
return Convert(std::pow(base,c1));
}
Complex Complex::Sin(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = sin(c1);
return Convert(c2);
}
Complex Complex::Sinh(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = sinh(c1);
return Convert(c2);
}
Complex Complex::Sqrt(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = sqrt(c1);
return Convert(c2);
}
Complex Complex::Tan(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = tan(c1);
return Convert(c2);
}
Complex Complex::Tanh(Complex c)
{
std::complex<double> c1(c._real,c._imag);
std::complex<double> c2 = tanh(c1);
return Convert(c2);
}
Complex Complex::Parse(String^ Text)
{
String^ txt = Text>Replace("(","");
txt=txt>Replace(")","");
array<String^>^ parts = txt>Split(',');
return Complex(Double::Parse(parts[0]),Double::Parse(parts[1]));
}
Complex Complex::Convert(complex<double> c)
{
Complex rval = Complex(real(c),imag(c));
return rval;
}
}






please how can i write codes to set up maths test for 5 people and save their results in a database?





The norm of 3 and 4 won`t be 25. It will be equal 5.





The norm is the square of the modulus, so 25 is correct.





Hi,
I have a Fortran program which I have to convert into Java originally. I have converted the code completely but can't get appropriate resutls. The code contains lot of arithmetic calculations using double precision data type of Fortran.
I believe the data types of C++ and Java are based on same whereas of Fortran double precision is based on IEEE756. I want to know how to convert these double precision calculations into C++ normally. For example:
double precision d1 = 0.3648564D0;
d1**2 // ** indicates exponent
DSIN(d1) // sin of double precision
DCOS(d1) // cos of double precision
The above are my main concerns which I find very difficult to convert. I use sin & cos for DSIN & DCOS. But Fortran 77 deals somthing differntly with double precision. How to convert/translate that into our normal C++ application is what I am looking for.
If you can provide the same for Java that would be a plus for me, otherwise I will use the code accordingly of C++ in my Java application. I hope help from you.
Please help me out. Am stuck up very badly.
Thanks
Terry





This command don't work in Command Window in VS 2008.
Command "c:\>vbc" is not valid.
What I am doing wrong ?





Use the visual studio command prompt.
Start > All Programs > Visual Studio 2008 >Visual Studio Tools > Visual Studio command prompt.






//======================================================================== // Copyright (c) 20052006, Boxing Wang. All rights reserved. //========================================================================
using System; using System.Diagnostics;
namespace Wbx.Math { [DebuggerDisplay("{Real} + {Imag}i")] public struct Complex { public double Real;
public double Imag;
[DebuggerStepThrough()] public Complex(double real, double imag) { this.Real = real; this.Imag = imag; }
[DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public Complex Conjugate { [DebuggerStepThrough()] get { return new Complex(Real, Imag); } }
[DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public double Norm { [DebuggerStepThrough()] get { return Real * Real + Imag * Imag; } }
[DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public double Modulus { [DebuggerStepThrough()] get { return System.Math.Sqrt(Real * Real + Imag * Imag); } }
[DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public double Argument { [DebuggerStepThrough()] get { return System.Math.Atan2(Imag, Real); } }
[DebuggerStepThrough()] public static Complex Polar(double modulus, double argument) { return new Complex( modulus * System.Math.Cos(argument), modulus * System.Math.Sin(argument)); }
public static Complex operator +(Complex z1, Complex z2) { return new Complex(z1.Real + z2.Real, z1.Imag + z2.Imag); }
public static Complex operator (Complex z1, Complex z2) { return new Complex(z1.Real  z2.Real, z1.Imag  z2.Imag); }
public static Complex operator *(Complex z1, Complex z2) { return new Complex( z1.Real * z2.Real  z1.Imag * z2.Imag, z1.Real * z2.Imag + z1.Imag * z2.Real); }
public static Complex operator /(Complex z1, Complex z2) { double value = z2.Real * z2.Real + z2.Imag * z2.Imag;
return new Complex( (z1.Real * z2.Real + z1.Imag * z2.Imag) / value, (z1.Imag * z2.Real  z1.Real * z2.Imag) / value); }
public static bool operator ==(Complex z1, Complex z2) { return (z1.Real == z2.Real && z1.Imag == z2.Imag); }
public static bool operator !=(Complex z1, Complex z2) { return (z1.Real != z2.Real  z1.Imag == z2.Imag); }
public static Complex Cos(Complex z) { Complex z1 = Exp(new Complex(z.Imag, z.Real)); Complex z2 = Exp(new Complex(z.Imag, z.Real));
return new Complex(0.5 * (z1.Real + z2.Real), 0.5 * (z1.Imag + z2.Imag)); }
public static Complex Cosh(Complex z) { Complex z1 = Exp(z); Complex z2 = Exp(new Complex(z.Real, z.Imag));
return new Complex(0.5 * (z1.Real + z2.Real), 0.5 * (z1.Imag + z2.Imag)); }
public static Complex Sin(Complex z) { Complex z1 = Exp(new Complex(z.Imag, z.Real)); Complex z2 = Exp(new Complex(z.Imag, z.Real));
return new Complex(0.5 * (z1.Imag  z2.Imag), 0.5 * (z2.Real  z1.Real)); }
public static Complex Sinh(Complex z) { Complex z1 = Exp(z); Complex z2 = Exp(new Complex(z.Real, z.Imag));
return new Complex(0.5 * (z1.Real  z2.Real), 0.5 * (z1.Imag  z2.Imag)); }
public static Complex Tan(Complex z) { return Sin(z) / Cos(z); }
public static Complex Tanh(Complex z) { return Sinh(z) / Cosh(z); }
public static Complex Exp(Complex z) { double value = System.Math.Exp(z.Real);
return new Complex( value * System.Math.Cos(z.Imag), value * System.Math.Sin(z.Imag)); }
public static Complex Log(Complex z) { return new Complex(System.Math.Log(z.Modulus), z.Argument); }
public static Complex Log10(Complex z) { const double log10 = 2.3025850929940459;
Complex value = Log(z);
value.Real /= log10; value.Imag /= log10;
return value; }
public static Complex Pow(Complex baseNumber, Complex index) { return Exp(index * Log(baseNumber)); }
public static Complex Sqrt(Complex z) { double value = System.Math.Sqrt(z.Real * z.Real + z.Imag * z.Imag) + z.Real;
return new Complex( System.Math.Sqrt(0.5 * value), System.Math.Sqrt(0.5 / value) * z.Imag); }
public override string ToString() { return (String.Format("{0} + {1}i", Real, Imag)); }
public override bool Equals(object obj) { return base.Equals(obj); }
public override int GetHashCode() { return Real.GetHashCode() ^ Imag.GetHashCode(); } } }





Very nice.
Note the error in the != operator:
should be:
public static bool operator !=(Complex z1, Complex z2)
{
return (z1.Real != z2.Real  z1.Imag != z2.Imag);
}





Your sqrt function is also wrong, but thanks for the rest, proved very helpful
Correct sqrt:
public static Complex Sqrt(Complex z)
{
return Polar(System.Math.Sqrt(z.Modulus), z.Argument * 0.5);
}





You should either mark the Real and Imag fields as readonly, or make them public properties with private setters. You can append " : this()" to the constructor's signature to make C# allow property assignments in the constructor.





Can this run with Windows Forms instead of console? I tried adding complex.dll as a reference (in Visual Studio 2005) but got the following error ar runtime:
LoaderLock was detected
DLL 'C:\Documents and Settings\Bill\My Documents\Visual Studio 2005\Projects\TestComplex\TestComplex\bin\Release\complex.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.





Bill,
I recompiled with VS 2005, and it fixes the problems.
The version on codeproject was compiled with the old VS 2002.
You might want to try the Nmath library. It is pure managd code and can be downloaded from nmath.sourceforge.net It has a good complex math library, see the file src\Complex.cs (MathNet.Numericsv0.3)
 modified at 10:18 Monday 2nd January, 2006





Looks very promising however:
I tried the test app in Visual Studio 2005 console mode and while no errors were generated it did not display the line of output at all.
Is it supposed to work with Visual Studio 2005?
Thanks
Bill.





Sorry this library has not been tested with visual studio 2005.
I will test and make a new version for 2005 if needed. VB now supports operator overloading so that should eliminate the need for the methods Add() Subract(), Multiply(), And Divide().
Thanks,
Karl





Thank you Karl, appreciated. I'm using C# and Windows Forms.
 Bill.





I have been writing NUMERICAL METHOD algorithm ( finding roots of polynomials ) and your dll saved my from rewriting program into C++
Gratz





You don't have to write this to allow vb to use this.






I'm having serious trouble getting the standard





First of all, it's managed C++. This could be written entirely using straight C#.
Secondly, why are you using std::complex? . You're instantiated the template using a double in the C++ section, so the C# and VB side doesn't benefit from the point of a template, which is to instantiate whatever type you want. Therefore, this supports the previous point that this should have been written in C# to begin with.
BTW, C++ doesn't inherently support complex types (last time I checked). This is provided by STL.
You might want to look at this link for some simplistic examples:
http://www.csharphelp.com/archives/archive135.html[^]
As this article discusses, you might also want to overload the equality operators so we can compare complex numbers.
Finally, as you say, there's a major performance hit using complex numbers with managed C++. If I were writing a complicated math function with lots of complex number calculations, I really wouldn't want to incur these performance hits.
Marc
Help! I'm an AI running around in someone's f*cked up universe simulator.
sensitivity and ethnic diversity means celebrating difference, not hiding from it.  Christian Graus





Thanks for the comment.
You are right it could be in straight C# and that would be nice.
My goal was full functionality, which is where managed C++ is great. C# and VB get to use the STL indirectly to get full functionality. The tradeoff is losing some flexibility and performance in non trivial cases. For the easy cases I am NOT using STL!
I use STL to handle nontrivial cases letting it worry about significant bits, as needed. With time more functions could be converted away from the STL wrapper. At that point it would be an easy port to C# if desired.
I HAVE overloaded the equality and other operators. I was hoping for feedback on why I needed to create redundant functions like Equals() to make it work in VB. The overloaded stuff works great in C++ and C#, but not everything maps to VB.
Ok STL is not “built” into the language but any good C++ compiler has STL, hence you can do complex math with C++ and FORTRAN.
Karl





I HAVE overloaded the equality and other operators.
Oops, sorry!
Not to be nitpicky:
Ok STL is not “built” into the language but any good C++ compiler has STL, hence you can do complex math with C++ and FORTRAN.
Any good C++ compiler supports templates, which therefore allows you to use STL.
And not to be sarcastic:
I was hoping for feedback on why I needed to create redundant functions like Equals() to make it work in VB. The overloaded stuff works great in C++ and C#, but not everything maps to VB.
Another reason why VB is pathetic (Marc tones it down from a vast selection of words beginning with the letter 's').
Marc
Help! I'm an AI running around in someone's f*cked up universe simulator. Sensitivity and ethnic diversity means celebrating difference, not hiding from it.  Christian Graus Every line of code is a liability  Taka Muraoka







General News Suggestion Question Bug Answer Joke Praise Rant Admin Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

