multiplication of complex times a float

F

foice

Hello to everybody
I am dealing with a rather long mathematical expression generated by a
CAS and this contains products of real numbers and complex numbers.
Of course the real numbers can be thought as complex and
multiplication between complex numbers would not be a problem.
Unfortunately the CAS gives output where a real is put in real form
and apparently a multiplication between a float and complex like this
amp = 2. * complex<float> (1.,1.);
cannot be digested by the compiler.
Mathematically the operation makes perfectly sense ... why is not
defined the multiplication of reals and complex?
Any idea how to simply get this multiplication done without writing
complex<float> (2.,0)*complex<float>(1.,1.) ??

Thanks a lot
Roberto
 
F

Francesco S. Carta

If you really need to define the multiplication in that order, just
define a custom operator*():

//-------
#include <iostream>
#include <complex>

using namespace std;

complex<float> operator*(const float& f, const complex<float>& fc) {
return fc * f;
}

int main() {
complex<float> amp = 2. * complex<float>(1.,1.);
cout << amp << endl;
return 0;
}
//-------

Although I would simply swap the factors' order in the original line.

Sorry, I overlooked the fact that you're dealing with automatically
generated code... never mind, the above could solve the issue faster
than modifying the code generator, so ;-)
 
F

Francesco S. Carta

Sorry, I overlooked the fact that you're dealing with automatically
generated code... never mind, the above could solve the issue faster
than modifying the code generator, so ;-)

Ouch! There was a reason for not defining it in first place! Beware that
adding such an operator will make ambiguous the resolution of
multiplications in the inverse order (which were fine)! I think you're
forced to explicitly convert the float or to change the code generator...
 
F

foice

True 2. can be multiplied both left and right times the complex.
Integers still suffer the problem... however.
 
F

Francesco S. Carta

so ... 2. * complex<float> works or 2 * complex<float> works
but it does not works if I write the other way around.

If you use my operator*(), yes.
that's weired as I see that the writing in right other way was used to
define the operator* which makes the trick.

The instruction in my operator*() works because by the time we are into
the function, the 2. is already converted to a float, hence the call is
not ambiguous anymore.
however my CAS writes always float*complex. This is is because my
comlpex are actually funciotns and there is this convention to write
numbers in front of functions.

so ... now it compiles with the code autmatically wrote by the CAS.
i'll go for some numerical check.

If it compiles, that's all right. The problem here is only about call
resolution ambiguity, the calculations will be fine - but do your checks
in any case.
 
S

SG

I am dealing with a rather long mathematical expression generated by a
CAS and this contains products of real numbers and complex numbers.
Of course the real numbers can be thought as complex and
multiplication between complex numbers would not be a problem.
Unfortunately the CAS gives output where a real is put in real form
and apparently a multiplication between a float and complex like this
        amp = 2. * complex<float> (1.,1.);
cannot be digested by the compiler.
Mathematically the operation makes perfectly sense ... why is not
defined the multiplication of reals and complex?

The problem here is that template argument deduction fails. The C++
standard states that by including the <complex> header you get the
following function template among others:

template<class T>
complex<T> operator*(const T&, const complex<T>&);

We have two contexts where T can be deduced. Since you use a double
integral in combination with a complex<float> you'll have T=double for
the first parameter and T=float for the second parameter which is a
contradiction. This is a deduction failure and the function template
is ignored.

If you use 2.f instead of 2. it'll work.

There are a couple of tricks one could use if you have the chance to
write your own complex class. For example, you can define operator* in
class as a friend. This way, it's not a template so T doesn't have to
be deduced:

template<class T>
class mycomplex
{
T real_, imag_;
public:
mycomplex(T r=0, T i=0) : real_(r), imag_(i) {}
...
friend mycomplex operator*(T s, mycomplex const& c)
{
return mycomplex(s*c.real,s*c.imag);
}
...
};

Another way of handling the template parameter deduction problem is to
disable deduction for one parameter:

template<class T>
struct identity {typedef T type;};

template<class T>
complex<T> operator*(const typename identity<T>::type&,
const complex<T>&);

Here, identity<T>::type is not a deducible context with respect to the
template parameter T. So, given your example, T will be deduced to be
float and the double value would be converted to float.

But as soon as you make mycomplex<U> convertible to mycomplex<T> with
this

template<class U>
mycomplex(mycomplex<U> const& c)
: real(c.real()), imag(c.imag())
{}

you will probably get ambiguities in a situation like yours:

2.0 * mycomplex<float>(1,0)

operator*(double,mycomplex<double>) or
operator*(float, mycomplex<float>) ??

To emulate "the usual arithmetic conversions" one probably has to use
two template parameters:

template<class T, class U>
mycomplex<Z> operator*(T s, mycomplex<U> const&);

where picking Z is not that easy if you can't use the decltype
operator of C++0x. The BOOST_TYPEOF macro could help here.

Cheers!
SG
 
F

Francesco S. Carta

[..] this works:

complex<float> amp = float(2.) * complex<float>(1.,1.);

And there is a way to have a float literal: 2.f, so this should work as
well:

complex<float> amp = 2.f * complex<float>(1.,1.);

It will, indeed. Another of those damn simple solutions that slip out of
sight when one gridlocks on less trivial stuff :-/

Float caf... ehrm... double caffeine dose tomorrow!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top