www.digitalmars.com         C & C++   DMDScript  

D - complex numbers not explicite different types

reply davepermen <davepermen_member pathlink.com> writes:
i found out the math module doesn't contain much useful complex number
functions, so i wanted to write my own ones.

but this:

cfloat exp(cfloat z) {
return exp(z.re)*exp(z.im);
}

cfloat exp(ifloat i) {
return cos(cast(float)i) + sin(cast(float)i)*1i;
}

results in

Main.d(26): function exp overloads cfloat(cfloat z) and cfloat(ifloat i) both
match argument list for exp


i'm interested why. this should work, shouldn't it?

btw, once operator overloading gets doable with functions, too, we don't need
ifloat and cfloat to remain basetypes..

typedef float ifloat;
struct cfloat {
float re;
ifloat im;
}
and the proper operators would be enough..
// float operator+(float a,float b);
// ifloat operator+(ifloat a,ifloat b);
cfloat operator+(float a,ifloat b);
cfloat operator+(float a,cfloat b);
cfloat operator+(ifloat a,float b);
cfloat operator+(ifloat a,cfloat b);
cfloat operator+(cfloat a,float b);
cfloat operator+(cfloat a,ifloat b);
cfloat operator+(cfloat a,cfloat b);

and this for all sort of ops, of course..

and then, sin(ifloat) sin(cfloat) etc would be doable, too...




or have i missed something?
Nov 26 2003
parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
"davepermen" <davepermen_member pathlink.com> wrote in message
news:bq1qsg$29iq$1 digitaldaemon.com...
 i found out the math module doesn't contain much useful complex number
 functions, so i wanted to write my own ones.

 but this:

 cfloat exp(cfloat z) {
 return exp(z.re)*exp(z.im);
 }

 cfloat exp(ifloat i) {
 return cos(cast(float)i) + sin(cast(float)i)*1i;
 }

 results in

 Main.d(26): function exp overloads cfloat(cfloat z) and cfloat(ifloat i)
both
 match argument list for exp


 i'm interested why. this should work, shouldn't it?
I have no idea why that doesn't work. It might be the calling of exp from inside complex exp is hiding the other global exp overloads?
 btw, once operator overloading gets doable with functions, too, we don't
need
 ifloat and cfloat to remain basetypes..

 typedef float ifloat;
 struct cfloat {
 float re;
 ifloat im;
 }
 and the proper operators would be enough..
 // float operator+(float a,float b);
 // ifloat operator+(ifloat a,ifloat b);
 cfloat operator+(float a,ifloat b);
 cfloat operator+(float a,cfloat b);
 cfloat operator+(ifloat a,float b);
 cfloat operator+(ifloat a,cfloat b);
 cfloat operator+(cfloat a,float b);
 cfloat operator+(cfloat a,ifloat b);
 cfloat operator+(cfloat a,cfloat b);

 and this for all sort of ops, of course..

 and then, sin(ifloat) sin(cfloat) etc would be doable, too...

 or have i missed something?
That will work since typedef makes a new distinct type in D. "typedef A B;" in D is roughly equivalent to "struct B : A {};" in C++, except it brings all the members (C++ loses the ctors) and also it works on basic types such as float, that you can't "inherit" from. Sean
Nov 26 2003
next sibling parent reply davepermen <davepermen_member pathlink.com> writes:
In article <bq1ris$2agf$1 digitaldaemon.com>, Sean L. Palmer says...
I have no idea why that doesn't work.  It might be the calling of exp from
inside complex exp is hiding the other global exp overloads?
can we say BUG?! :D no clue eighter.. i'll dive more into it..
That will work since typedef makes a new distinct type in D.

"typedef A B;" in D is roughly equivalent to "struct B : A {};" in C++,
except it brings all the members (C++ loses the ctors) and also it works on
basic types such as float, that you can't "inherit" from.
i know. and i'm currently toying around with it.. and it works great so far.. if only operator overloads could be based on functions.. i've made it like this: typedev float val; alias val rval; typedev val ival; struct cval { rval re; ival im; } and then added operators for cval.. the only thing that does NOT work now is rval op ival ... :( else, it all would work great, and would allow to implement complex math and even more completely based on a library. except, of course, the postfix i for numbers.. while we're at it.. i'd like to get a typedef val xval; typedef val yval; and typedef val zval; and typedef val wval; with postfix x,y,z,w to do struct v3val { xval x; yval y; zval z; } and struct qval { wval w; xval x; yval y; zval z; } etc.. and having then 35x, 23y, 46z as possible values.. so v3val pos = 12x + 14y + 64z; we could extend this thought quite a bit.. i think we need an overloadable postfix :D then it could all be done with libraries:D
Nov 26 2003
parent "Sean L. Palmer" <palmer.sean verizon.net> writes:
"davepermen" <davepermen_member pathlink.com> wrote in message
news:bq1tm7$2dil$1 digitaldaemon.com...
That will work since typedef makes a new distinct type in D.

"typedef A B;" in D is roughly equivalent to "struct B : A {};" in C++,
except it brings all the members (C++ loses the ctors) and also it works
on
basic types such as float, that you can't "inherit" from.
i know. and i'm currently toying around with it.. and it works great so
far.. if
 only operator overloads could be based on functions..

 i've made it like this:
 typedev float val;
 alias val rval;
 typedev val ival;
 struct cval {
 rval re;
 ival im;
 }

 and then added operators for cval..

 the only thing that does NOT work now is rval op ival ... :( else, it all
would
 work great, and would allow to implement complex math and even more
completely
 based on a library. except, of course, the postfix i for numbers..
The postfix units are just convention. It would be nice, but it's not crucial. It's the same as having to use * instead of juxtaposition for multiply. Personally I like juxtaposition, I think it's a great operator. It is just unruly, hard to tame.
 while we're at it.. i'd like to get a typedef val xval; typedef val yval;
and
 typedef val zval; and typedef val wval; with postfix x,y,z,w to do struct
v3val
 { xval x; yval y; zval z; } and struct qval { wval w; xval x; yval y; zval
z; }
 etc.. and having then 35x, 23y, 46z as possible values..

 so

 v3val pos = 12x + 14y + 64z;

 we could extend this thought quite a bit.. i think we need an overloadable
 postfix :D then it could all be done with libraries:D
You mean make your own numeric literal suffix? like f is to float, and u is to unsigned? That could be nice I guess. But v3val pos = x(12) + y(14) + z(64); wouldn't be that bad. However you've hit on a nugget of gold here. A way to automatically create new struct types out of combinations of different unique types is a great idea. In fact that is the very definition of addition of incompatible values, it just aggregates them. 1 x + 2 x = 3 x 1 x + 2 y = 1 x + 2 y // can't simplify, no operator has been defined to add type x to type y You could pull out (select) values from an additive combination using dot: (1 x + 2 y).x = 1x (1 x + 2 y).y = 2y To do this in C, D, Java, etc now, you'd have to define a struct to hold every permutation of possible combinations of types, as well as operator + for each combination. This should be automatic. Car car = new Porsche; Television tv = new FlatscreenTV; mobile_entertainment = car + tv; // this possesses a union of the functionality of car and tv. If there are conflicts, you have to manually specify which one to use. mobile_entertainment.car.turn_on(); Multiplication is different... it *always* works, and produces a value which is a combination of the two inputs 2 x * 3 x = 6 x 2 x * 3 y = 6 xy // no operator has been defined to multiply type x to type y, so by default it makes a new "xy" type to represent the mix Would need somehow to represent the concept of square units and reciprocal units. 24 mile / 4 hour = 6 mile/hour 9.8 m / s / s = 9.8 m / s**2 With this in mind, you may be able to make a language that doesn't possess the concept of struct, only addition. Similarly multiplication is closely related to the concept of tuple. Tagged unions can effectively replace many forms of polymorphism, you'd set that up on binary |. I think that sets could tie in here somehow, but haven't thought it thru yet. Similarly these don't require a new type in many cases, just a "tag" that define your own. They work much like const and volatile in C++. You can combine them implicitly, but to get rid of one needs a typecast. Haskell is very close to this now. It may be worth looking into. I've also run into a bunch of languages recently that have splintered off of Haskell. It means people recognize the shortcomings of Haskell. That indicates to me that a new language is about to come into existence, one that pushes Haskell be the Next Big Thing... we shall see which prevails. ;) I've been thinking recently that it might have been a mistake on C's part to eliminate Pascal's concept of Procedure being distinct from Function. Function: Cannot modify parameters, cannot change any state (even globals), cannot have static locals, and must return one value. Always "const" Procedure: Can modify parameters, can change state, cannot return a value except maybe an error code. Not "const" Sean
Nov 26 2003
prev sibling parent davepermen <davepermen_member pathlink.com> writes:
private import std.math;

float exp(float x) {
return std.math.exp(x);
}

cfloat exp(ifloat x) {
return std.math.cos(x) + 1i*std.math.sin(x);
}

cfloat exp(cfloat z) {
return exp(z.re)*exp(z.im);
}


that way works.. as a solution to my original problem..
Nov 26 2003