Jump to page: 1 2 3
Thread overview
No more implicit conversion real->complex?!
Mar 20, 2006
Norbert Nemec
Mar 20, 2006
Walter Bright
Mar 21, 2006
Don Clugston
Mar 21, 2006
kris
Mar 21, 2006
Regan Heath
Mar 21, 2006
Don Clugston
Mar 21, 2006
Don Clugston
Mar 21, 2006
kris
Mar 21, 2006
Sean Kelly
Mar 21, 2006
kris
Mar 22, 2006
Don Clugston
Mar 22, 2006
Sean Kelly
Mar 22, 2006
kris
Mar 24, 2006
Walter Bright
Mar 24, 2006
kris
Mar 21, 2006
Rioshin an'Harthen
Mar 21, 2006
Don Clugston
Mar 21, 2006
Rioshin an'Harthen
Mar 21, 2006
Don Clugston
Mar 21, 2006
Rioshin an'Harthen
Mar 21, 2006
Don Clugston
Mar 21, 2006
Rioshin an'Harthen
March 20, 2006
I just notice that as of D 0.150, implicit conversion from real/imaginary to complex does not work any more. I could not make out the message containing the suggestion by Don Clugston, so I'm not sure about the rationale.

In any case: if this conversion does not work implicitely any more, I wonder whether I understand the rule which conversions do? real->complex is possible without ambiguities or loss of information. Why not make it implicit?

I think this is an important issue: in numerics, mixing of real and complex values happens all the time, therefore it should be as simple as possible.
March 20, 2006
"Norbert Nemec" <Norbert@Nemec-online.de> wrote in message news:dvn3vm$qpu$1@digitaldaemon.com...
>I just notice that as of D 0.150, implicit conversion from
> real/imaginary to complex does not work any more. I could not make out the message containing the suggestion by Don Clugston, so I'm not sure about the rationale.
>
> In any case: if this conversion does not work implicitely any more, I wonder whether I understand the rule which conversions do? real->complex is possible without ambiguities or loss of information. Why not make it implicit?
>
> I think this is an important issue: in numerics, mixing of real and complex values happens all the time, therefore it should be as simple as possible.

The issue Don brought up was the problem of overload resolution between functions taking real args and those taking complex args.


March 21, 2006
Norbert Nemec wrote:
> I just notice that as of D 0.150, implicit conversion from
> real/imaginary to complex does not work any more. I could not make out
> the message containing the suggestion by Don Clugston, so I'm not sure
> about the rationale.
> 
> In any case: if this conversion does not work implicitely any more, I
> wonder whether I understand the rule which conversions do? real->complex
> is possible without ambiguities or loss of information. Why not make it
> implicit?

It's not 100% unambiguous, there are two possible conversions
    7.2 -> 7.2 + 0i
and 7.2 -> 7.2 - 0i.

OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.

Consider
creal sin(creal c);
real sin(real x);

writefln( sin(3.2) );

Now, 3.2 is a double, so it tries to find sin(double).
This fails, so it tries implicit conversions.
Both sin(creal) and sin(real) are possible, so it's ambiguous, and
compilation will fail.
Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.

> I think this is an important issue: in numerics, mixing of real and
> complex values happens all the time, therefore it should be as simple as
> possible.

I agree. But the implicit conversions were actually making mixing of real and complex functions much more difficult. It would be good to have someone other than me seriously thinking about these issues, and gaining some experience with numerics in D.

March 21, 2006
Don Clugston wrote:
> Norbert Nemec wrote:
> 
>> I just notice that as of D 0.150, implicit conversion from
>> real/imaginary to complex does not work any more. I could not make out
>> the message containing the suggestion by Don Clugston, so I'm not sure
>> about the rationale.
>>
>> In any case: if this conversion does not work implicitely any more, I
>> wonder whether I understand the rule which conversions do? real->complex
>> is possible without ambiguities or loss of information. Why not make it
>> implicit?
> 
> 
> It's not 100% unambiguous, there are two possible conversions
>     7.2 -> 7.2 + 0i
> and 7.2 -> 7.2 - 0i.
> 
> OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
> 
> Consider
> creal sin(creal c);
> real sin(real x);
> 
> writefln( sin(3.2) );
> 
> Now, 3.2 is a double, so it tries to find sin(double).
> This fails, so it tries implicit conversions.
> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
> compilation will fail.
> Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.
> 
>> I think this is an important issue: in numerics, mixing of real and
>> complex values happens all the time, therefore it should be as simple as
>> possible.
> 
> 
> I agree. But the implicit conversions were actually making mixing of real and complex functions much more difficult. It would be good to have someone other than me seriously thinking about these issues, and gaining some experience with numerics in D.
> 

By this argument, if the overloaded types were char and long (instead of creal & real) then D should not allow implicit conversion there?
March 21, 2006
On Tue, 21 Mar 2006 00:15:37 -0800, kris <foo@bar.com> wrote:
> Don Clugston wrote:
>> Norbert Nemec wrote:
>>
>>> I just notice that as of D 0.150, implicit conversion from
>>> real/imaginary to complex does not work any more. I could not make out
>>> the message containing the suggestion by Don Clugston, so I'm not sure
>>> about the rationale.
>>>
>>> In any case: if this conversion does not work implicitely any more, I
>>> wonder whether I understand the rule which conversions do? real->complex
>>> is possible without ambiguities or loss of information. Why not make it
>>> implicit?
>>   It's not 100% unambiguous, there are two possible conversions
>>     7.2 -> 7.2 + 0i
>> and 7.2 -> 7.2 - 0i.
>>  OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
>>  Consider
>> creal sin(creal c);
>> real sin(real x);
>>  writefln( sin(3.2) );
>>  Now, 3.2 is a double, so it tries to find sin(double).
>> This fails, so it tries implicit conversions.
>> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
>> compilation will fail.
>> Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.
>>
>>> I think this is an important issue: in numerics, mixing of real and
>>> complex values happens all the time, therefore it should be as simple as
>>> possible.
>>   I agree. But the implicit conversions were actually making mixing of real and complex functions much more difficult. It would be good to have someone other than me seriously thinking about these issues, and gaining some experience with numerics in D.
>>
>
> By this argument, if the overloaded types were char and long (instead of creal & real) then D should not allow implicit conversion there?

You can disambiguate char and long by using an "IntegerSuffix" eg.

void foo(char c) {}
void foo(long c) {}

void main()
{
	foo(5L);
}

Is the same true for real and creal?

(I've not done very much in the way of numerics and I've never used creal, so I honestly don't know)

Regan
March 21, 2006
"Don Clugston" <dac@nospam.com.au> wrote in message news:dvobhe$2cm6$1@digitaldaemon.com...
> Norbert Nemec wrote:
>> I just notice that as of D 0.150, implicit conversion from real/imaginary to complex does not work any more. I could not make out the message containing the suggestion by Don Clugston, so I'm not sure about the rationale.
>>
>> In any case: if this conversion does not work implicitely any more, I wonder whether I understand the rule which conversions do? real->complex is possible without ambiguities or loss of information. Why not make it implicit?
>
> It's not 100% unambiguous, there are two possible conversions
>     7.2 -> 7.2 + 0i
> and 7.2 -> 7.2 - 0i.
>
> OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
>
> Consider
> creal sin(creal c);
> real sin(real x);
>
> writefln( sin(3.2) );
>
> Now, 3.2 is a double, so it tries to find sin(double).
> This fails, so it tries implicit conversions.
> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
> compilation will fail.
> Up to now, the only way of overcoming this was to supply seperate
> functions for float, double, real, and creal arguments. This is clumsy,
> and becomes impractical once multiple arguments are used.

version(delurk)
{

I've been thinking about this ever since the last discussion about this, and believe there might be a better solution to the problem at hand than disabling real -> creal implicit conversions.

Since the compiler knows the storage requirements of the different types, and if multiple implicit conversions are possible (e.g. the above mentioned sin( creal ) and sin( real )), why not make the compiler choose the one with the least storage requirement (i.e. changing the original number the least).

So if we have

creal sin( creal c );
real sin( real r );

writefln( sin( 3.2 ) );

as above, the 3.2 is according to specs a double, and we don't find double sin( double d ) anywhere, we try implicit conversions. Now, we have two options: creal sin( creal c ) and real sin( real r ). The storage requirement of creal is larger than that of real, so conversion to real changes the original double less than conversion to creal. Thus, the compiler chooses to convert it into real.

Naturally, we can help the compiler make the choice:

writefln( sin( cast( creal ) 3.2 ) );

would naturally pick the creal version (since 3.2 has been cast to it).

What are your thoughts about this? Could this work? And if this could, should this be added to the D specifications?

}


March 21, 2006
kris wrote:
> Don Clugston wrote:
>> Norbert Nemec wrote:
>>
>>> I just notice that as of D 0.150, implicit conversion from
>>> real/imaginary to complex does not work any more. I could not make out
>>> the message containing the suggestion by Don Clugston, so I'm not sure
>>> about the rationale.
>>>
>>> In any case: if this conversion does not work implicitely any more, I
>>> wonder whether I understand the rule which conversions do? real->complex
>>> is possible without ambiguities or loss of information. Why not make it
>>> implicit?
>>
>>
>> It's not 100% unambiguous, there are two possible conversions
>>     7.2 -> 7.2 + 0i
>> and 7.2 -> 7.2 - 0i.
>>
>> OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
>>
>> Consider
>> creal sin(creal c);
>> real sin(real x);
>>
>> writefln( sin(3.2) );
>>
>> Now, 3.2 is a double, so it tries to find sin(double).
>> This fails, so it tries implicit conversions.
>> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
>> compilation will fail.
>> Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.
>>
>>> I think this is an important issue: in numerics, mixing of real and
>>> complex values happens all the time, therefore it should be as simple as
>>> possible.
>>
>>
>> I agree. But the implicit conversions were actually making mixing of real and complex functions much more difficult. It would be good to have someone other than me seriously thinking about these issues, and gaining some experience with numerics in D.
> 
> By this argument, if the overloaded types were char and long (instead of creal & real) then D should not allow implicit conversion there?

I can't think of many examples where you have overloads of both char and long. But it's _extremely_ common for complex functions to be overloads of real functions. Let's not forget that the purpose of implicit conversions is for convenience. IMHO, real->creal fails to be convenient, given the D's simple lookup rules.

March 21, 2006
Rioshin an'Harthen wrote:
> "Don Clugston" <dac@nospam.com.au> wrote in message news:dvobhe$2cm6$1@digitaldaemon.com...
>> Norbert Nemec wrote:
>>> I just notice that as of D 0.150, implicit conversion from
>>> real/imaginary to complex does not work any more. I could not make out
>>> the message containing the suggestion by Don Clugston, so I'm not sure
>>> about the rationale.
>>>
>>> In any case: if this conversion does not work implicitely any more, I
>>> wonder whether I understand the rule which conversions do? real->complex
>>> is possible without ambiguities or loss of information. Why not make it
>>> implicit?
>> It's not 100% unambiguous, there are two possible conversions
>>     7.2 -> 7.2 + 0i
>> and 7.2 -> 7.2 - 0i.
>>
>> OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
>>
>> Consider
>> creal sin(creal c);
>> real sin(real x);
>>
>> writefln( sin(3.2) );
>>
>> Now, 3.2 is a double, so it tries to find sin(double).
>> This fails, so it tries implicit conversions.
>> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
>> compilation will fail.
>> Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.
> 
> version(delurk)
> {
> 
> I've been thinking about this ever since the last discussion about this, and believe there might be a better solution to the problem at hand than disabling real -> creal implicit conversions.
> 
> Since the compiler knows the storage requirements of the different types, and if multiple implicit conversions are possible (e.g. the above mentioned sin( creal ) and sin( real )), why not make the compiler choose the one with the least storage requirement (i.e. changing the original number the least).
> 
> So if we have
> 
> creal sin( creal c );
> real sin( real r );
> 
> writefln( sin( 3.2 ) );
> 
> as above, the 3.2 is according to specs a double, and we don't find double sin( double d ) anywhere, we try implicit conversions. Now, we have two options: creal sin( creal c ) and real sin( real r ). The storage requirement of creal is larger than that of real, so conversion to real changes the original double less than conversion to creal. Thus, the compiler chooses to convert it into real.
> 
> Naturally, we can help the compiler make the choice:
> 
> writefln( sin( cast( creal ) 3.2 ) );
> 
> would naturally pick the creal version (since 3.2 has been cast to it).
> 
> What are your thoughts about this? Could this work? And if this could, should this be added to the D specifications?
> 
> }

This would mean the lookup rules become more complicated. I think Walter was very keen to keep them simple.
March 21, 2006
Regan Heath wrote:
> On Tue, 21 Mar 2006 00:15:37 -0800, kris <foo@bar.com> wrote:
>> Don Clugston wrote:
>>> Norbert Nemec wrote:
>>>
>>>> I just notice that as of D 0.150, implicit conversion from
>>>> real/imaginary to complex does not work any more. I could not make out
>>>> the message containing the suggestion by Don Clugston, so I'm not sure
>>>> about the rationale.
>>>>
>>>> In any case: if this conversion does not work implicitely any more, I
>>>> wonder whether I understand the rule which conversions do? real->complex
>>>> is possible without ambiguities or loss of information. Why not make it
>>>> implicit?
>>>   It's not 100% unambiguous, there are two possible conversions
>>>     7.2 -> 7.2 + 0i
>>> and 7.2 -> 7.2 - 0i.
>>>  OK, it's not a big deal. But the real problem is that with that implicit conversion in place, overload resolution is a real nuisance.
>>>  Consider
>>> creal sin(creal c);
>>> real sin(real x);
>>>  writefln( sin(3.2) );
>>>  Now, 3.2 is a double, so it tries to find sin(double).
>>> This fails, so it tries implicit conversions.
>>> Both sin(creal) and sin(real) are possible, so it's ambiguous, and
>>> compilation will fail.
>>> Up to now, the only way of overcoming this was to supply seperate functions for float, double, real, and creal arguments. This is clumsy, and becomes impractical once multiple arguments are used.
>>>
>>>> I think this is an important issue: in numerics, mixing of real and
>>>> complex values happens all the time, therefore it should be as simple as
>>>> possible.
>>>   I agree. But the implicit conversions were actually making mixing of real and complex functions much more difficult. It would be good to have someone other than me seriously thinking about these issues, and gaining some experience with numerics in D.
>>>
>>
>> By this argument, if the overloaded types were char and long (instead of creal & real) then D should not allow implicit conversion there?
> 
> You can disambiguate char and long by using an "IntegerSuffix" eg.
> 
> void foo(char c) {}
> void foo(long c) {}
> 
> void main()
> {
>     foo(5L);
> }
> 
> Is the same true for real and creal?

Yes. But IMHO, it is ridiculous to expect user code to write

sin(2L);
instead of sin(2);
just because std.math includes sin(creal).
(It could be a high school student, who's never heard of complex numbers!).
March 21, 2006
"Don Clugston" <dac@nospam.com.au> wrote in message news:dvoklp$2pmq$2@digitaldaemon.com...
> Rioshin an'Harthen wrote:
>> "Don Clugston" <dac@nospam.com.au> wrote in message news:dvobhe$2cm6$1@digitaldaemon.com...
>>
>> I've been thinking about this ever since the last discussion about this, and believe there might be a better solution to the problem at hand than disabling real -> creal implicit conversions.
>>
>> Since the compiler knows the storage requirements of the different types, and if multiple implicit conversions are possible (e.g. the above mentioned sin( creal ) and sin( real )), why not make the compiler choose the one with the least storage requirement (i.e. changing the original number the least).
>>
>> So if we have
>>
>> creal sin( creal c );
>> real sin( real r );
>>
>> writefln( sin( 3.2 ) );
>>
>> as above, the 3.2 is according to specs a double, and we don't find double sin( double d ) anywhere, we try implicit conversions. Now, we have two options: creal sin( creal c ) and real sin( real r ). The storage requirement of creal is larger than that of real, so conversion to real changes the original double less than conversion to creal. Thus, the compiler chooses to convert it into real.
>>
>> Naturally, we can help the compiler make the choice:
>>
>> writefln( sin( cast( creal ) 3.2 ) );
>>
>> would naturally pick the creal version (since 3.2 has been cast to it).
>>
>> What are your thoughts about this? Could this work? And if this could, should this be added to the D specifications?
>
> This would mean the lookup rules become more complicated. I think Walter was very keen to keep them simple.

I doubt they'd become that much more complicated. Currently, the DMD compiler has to look up all the possible implicit conversions, and if there's more than one possible conversion, error out because it can't know which one.

Now, since it knows the types in question - and the type of the value being passed to the function, it's not that much more to do, IMHO. Basically, if it would error with an amiguous implicit conversion, do a search of the minimum of the possible types that are larger than the current type. If this doesn't match any type, do the error, otherwise select the type. A simple search during compile time is all that's required if we encounter more than one possible implicit conversion, to select the one that is the smallest of the possible ones.

Approximately (in some kind of pseudo-code):

type tryImplicitConversion( type intype, type[] implicit_conversion )
{
    least_type = illegal_type; // illegal type, if we can't find any other -
size is defined as
                                          // maximum
    foreach( type in implicit_conversion )
    {
        if( intype.sizeof > type.sizeof )
            continue; // we're not interested in types that are *less* in
size than our
                          // input type

        if( least_type.sizeof < type.sizeof )
            continue; // nor are we interested in larger types than
necessary

        least_type = type; // ok, this is the smallest type we can convert
to
                                    // (we've found so far)
    }

    return least_type;
}


« First   ‹ Prev
1 2 3