Thread overview
complex numbers not explicite different types
Nov 26, 2003
davepermen
Nov 26, 2003
Sean L. Palmer
Nov 26, 2003
davepermen
Nov 26, 2003
Sean L. Palmer
Nov 26, 2003
davepermen
November 26, 2003
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?


November 26, 2003
"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


November 26, 2003
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


November 26, 2003
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..


November 26, 2003
"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 sticks onto some other type.  In C# this is called an attribute, and you can 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 to the next level.  Like with C, there are Java, C#, and D all competing to 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