QuantumDot
QuantumDot

Reputation: 435

Converting std::complex between array of two elements.

"WolframLibrary.h" represents complex numbers using the struct:

typedef struct {double ri[2];} mcomplex;
#define mcreal(mc)  (((mc).ri)[0])
#define mcimag(mc)  (((mc).ri)[1])

which is just an array of two elements. The standard library header <complex> defines it differently. I want to make the compiler automatically convert between the two using the = operator, but I don't know how. Suppose

mcomplex z1 = {3.2, 1.1};   //  <-- this is z1 = 3.2 + 1.1 I
std::complex<double> z2(-4.0, 0.5); // <-- this is z2 = -4.0 + 0.5 I

How do I tell the compiler that z1 = z2 in my program means mcreal(z1) = real(z2); mcimag(z1) = imag(z2);, and vice versa?

Upvotes: 2

Views: 354

Answers (1)

R Sahu
R Sahu

Reputation: 206577

The simplest way to be able to use

z1 = z2;

is to provide a converting constructor from std::complex<double> to mcomplex.

Then, you can use:

std::complex<double> z2(-4.0, 0.5);
mcomplex z1 = z2;

or

mcomplex z1 = {3.2, 1.1}; 
std::complex<double> z2(-4.0, 0.5);
z1 = z2;

In order to be able to use the operations the other way, you need to provide a user defined conversion operator from mcomplex to std::complex<double>.

Finally, there is no need to use typedef struct {...} mcomplex;. Just use struct mcomplex { ... };

Here's program that builds successfully for me. Please note that main is empty on purpose. It just demonstrates the legal operations between mcomplex and std::complex<double>.

#include <complex>

struct mcomplex
{
   mcomplex(double re = 0, double im = 0)
   {
      ri[0] = re;
      ri[1] = im;
   }

   // Converting constructor.
   mcomplex(std::complex<double> const& c) : mcomplex(c.real(), c.imag()) {}

   // User defined conversion operator
   operator std::complex<double> () const
   {
      return {ri[0], ri[1]};
   }

   double ri[2];
};

void test1()
{
   std::complex<double> z2(-4.0, 0.5);
   mcomplex z1 = z2;
   (void)z1; // Shut up the compiler
}

void test2()
{
   mcomplex z1 = {3.2, 1.1}; 
   std::complex<double> z2(-4.0, 0.5);
   z1 = z2;
}

void test3()
{
   mcomplex z1 = {3.2, 1.1}; 
   std::complex<double> z2 = z1;
   (void)z2; // Shut up the compiler
}

void test4()
{
   mcomplex z1 = {3.2, 1.1}; 
   std::complex<double> z2(-4.0, 0.5);
   z2 = z1;
}

int main()
{
}

If you don't have the option of modifying the definition of mcomplex, your best option is to provide couple of non-member functions to do the conversions.

namespace MyApp
{
   mcomplex to_mcomplex(std::complex<double> const& c )
   {
      return mcomplex{c.real(), c.imag()};
   }

   std::complex<double> to_std_complex(mcomplex const& c)
   {
       return {c.re[0], c.re[1]};
   }
}

and then use

std::complex<double> z1(-4.0, 0.5);
mcomplex z2 = MyApp::to_mcomplex(z1);

and

mcomplex z1 = {3.2, 1.1}; 
std::complex<double> z2 = MyApp::to_std_complex(z1);

Upvotes: 2

Related Questions