## D - complex numbers not explicite different types

• davepermen (33/33) Nov 26 2003 i found out the math module doesn't contain much useful complex number
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
"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
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
"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

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
```
Nov 26 2003
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