472,780 Members | 1,139 Online

# Complex question

hi

I am trying to use the complex data type.

Consider this code, taken from the cclib library:

struct complex csqrt(Cpx z)
{ double r;
r=sqrt(z.re*z.re+z.im*z.im);
r=sqrt(ldexp(r+fabs(z.re),-1));
if(r==0.) z.re=z.im=0.;
else{
if(z.re>=0.){ z.re=r; z.im=ldexp(z.im/r,-1);}
else{ z.re=ldexp(fabs(z.im)/r,-1);
if(z.im>=0.) z.im=r; else z.im= -r;
}
}
return z;
}

Now, this works in lcc-win easily because lcc-win
data type easily, using
z.re (real part)
and
ze.im

for the imaginary part.

I do not see how can be this written in standard C.
Has anyone an idea?

Thanks
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 24 '08 #1
11 2313
On Jan 24, 2:03*pm, jacob navia <ja...@nospam.comwrote:
hi

I am trying to use the complex data type.

Consider this code, taken from the cclib library:

struct complex csqrt(Cpx z)
{ double r;
* *r=sqrt(z.re*z.re+z.im*z.im);
* *r=sqrt(ldexp(r+fabs(z.re),-1));
* *if(r==0.) z.re=z.im=0.;
* *else{
* * *if(z.re>=0.){ z.re=r; z.im=ldexp(z.im/r,-1);}
* * *else{ z.re=ldexp(fabs(z.im)/r,-1);
* * * *if(z.im>=0.) z.im=r; else z.im= -r;
* * * }
* * }
* *return z;

}

Now, this works in lcc-win easily because lcc-win
data type easily, using
z.re (real part)
and
ze.im

for the imaginary part.

I do not see how can be this written in standard C.
Has anyone an idea?
To get the imaginary part:

#include <complex.h>
double cimag(double complex z);
float cimagf(float complex z);
long double cimagl(long double complex z);

But then again, to get the square root, you would just call the
function:

#include <complex.h>
double complex csqrt(double complex z);
float complex csqrtf(float complex z);
long double complex csqrtl(long double complex z);

So I guess you do not have the header complex.h?
In such a case, maybe this is helpful:
http://www.moshier.net/#Complex_variables
Jan 24 '08 #2
On Jan 24, 2:03*pm, jacob navia <ja...@nospam.comwrote:
hi

I am trying to use the complex data type.

Consider this code, taken from the cclib library:

struct complex csqrt(Cpx z)
{ double r;
* *r=sqrt(z.re*z.re+z.im*z.im);
* *r=sqrt(ldexp(r+fabs(z.re),-1));
* *if(r==0.) z.re=z.im=0.;
* *else{
* * *if(z.re>=0.){ z.re=r; z.im=ldexp(z.im/r,-1);}
* * *else{ z.re=ldexp(fabs(z.im)/r,-1);
* * * *if(z.im>=0.) z.im=r; else z.im= -r;
* * * }
* * }
* *return z;

}

Now, this works in lcc-win easily because lcc-win
data type easily, using
z.re (real part)
and
ze.im

for the imaginary part.

I do not see how can be this written in standard C.
Has anyone an idea?
Just guessing, since I do not have a C99 compiler handy right now, but
I would say:

#include <complex.h>
double complex my_csqrt(double complex z)
{
double r;
r = sqrt(creal(z) * creal(z) + (cimag(z) * cimag(z)) * I;
r = sqrt(ldexp(r + fabs(creal(z)), -1));
if (r == 0.)
z= 0.0 + 0.0 * I;
else {
if (creal(z) >= 0.) {
z = r + ldexp(cimag(z) / r, -1) * I;
} else {
z = ldexp(fabs(cimag(z)) / r, -1) + cimag(z) >= 0 ? r *
I : -r * I;
}
}
return z;
}
Jan 24 '08 #3
jacob navia wrote:
hi

I am trying to use the complex data type.

Consider this code, taken from the cclib library:

struct complex csqrt(Cpx z)
{ double r;
r=sqrt(z.re*z.re+z.im*z.im);
r=sqrt(ldexp(r+fabs(z.re),-1));
if(r==0.) z.re=z.im=0.;
else{
if(z.re>=0.){ z.re=r; z.im=ldexp(z.im/r,-1);}
else{ z.re=ldexp(fabs(z.im)/r,-1);
if(z.im>=0.) z.im=r; else z.im= -r;
}
}
return z;
}

Now, this works in lcc-win easily because lcc-win
data type easily, using
z.re (real part)
and
ze.im

for the imaginary part.

I do not see how can be this written in standard C.
Has anyone an idea?
Your function works just fine in standard C. Check the following:
#include <math.h>
#include <stdio.h>

/* if you don't have <complex.h>, remove or comment out the line below */
#define USE_COMPLEX_H

typedef struct cmplx
{
double re, im;
} Cpx;
/* 'cmplx' chosen for the name of the struct since 'complex' should be
<complex.h*/

Cpx Csqrt
/* renamed because csqrt should be in <complex.h*/
(Cpx z)
{
double r;
r = sqrt(z.re * z.re + z.im * z.im);
r = sqrt(ldexp(r + fabs(z.re), -1));
if (r == 0.)
z.re = z.im = 0.;
else {
if (z.re >= 0.) {
z.re = r;
z.im = ldexp(z.im / r, -1);
}
else {
z.re = ldexp(fabs(z.im) / r, -1);
if (z.im >= 0.)
z.im = r;
else
z.im = -r;
}
}
return z;
}

Cpx Csquare(Cpx z)
{
Cpx r;
r.re = z.re * z.re - z.im * z.im;
r.im = 2 * z.re * z.im;
return r;
}

#if defined(USE_COMPLEX_H)
#include <complex.h>

double complex Csqrt2(double complex z)
{
double r;
r = sqrt(creal(z) * creal(z) + cimag(z) * cimag(z));
r = sqrt(ldexp(r + fabs(creal(z)), -1));
if (r == 0.)
z = 0.;
else {
if (creal(z) >= 0.) {
z = r + ldexp(cimag(z) / r, -1) * I;
}
else {
z = ldexp(fabs(cimag(z)) / r,
-1) + (cimag(z) >= 0. ? r : -r) * I;
}
}
return z;
}
#endif

int main(void)
{
Cpx x, y, z;
#if defined(USE_COMPLEX_H)
double complex cx, cy, cz;
#endif
int i, j;
printf("Using the function Jacob Navia provided,\n"
"with a struct for complex types.\n\n");
for (i = -2; i < 3; i++)
for (j = -2; j < 3; j++) {
x.re = i;
x.im = j;
y = Csqrt(x);
z = Csquare(y);
printf("y = Csqrt(%g+%gi)) = %g+%gi, y*y=%g+%gi\n",
x.re, x.im, y.re, y.im, z.re, z.im);
}

#if defined(USE_COMPLEX_H)
printf("\nUsing the function Jacob Navia provided,\n"
"rewritten to use complex types.\n\n");
for (i = -2; i < 3; i++)
for (j = -2; j < 3; j++) {
cx = i + j * I;
cy = Csqrt2(cx);
cz = cy * cy;
printf("y = Csqrt2(%g+%gi)) = %g+%gi, y*y=%g+%gi\n",
creal(cx), cimag(cx),
creal(cy), cimag(cy),
creal(cz), cimag(cz));
}

#endif

return 0;
}

[Output]

Using the function Jacob Navia provided,
with a struct for complex types.

y = Csqrt(-2+-2i)) = 0.643594+-1.55377i, y*y=-2+-2i
y = Csqrt(-2+-1i)) = 0.343561+-1.45535i, y*y=-2+-1i
y = Csqrt(-2+0i)) = 0+1.41421i, y*y=-2+0i
y = Csqrt(-2+1i)) = 0.343561+1.45535i, y*y=-2+1i
y = Csqrt(-2+2i)) = 0.643594+1.55377i, y*y=-2+2i
y = Csqrt(-1+-2i)) = 0.786151+-1.27202i, y*y=-1+-2i
y = Csqrt(-1+-1i)) = 0.45509+-1.09868i, y*y=-1+-1i
y = Csqrt(-1+0i)) = 0+1i, y*y=-1+0i
y = Csqrt(-1+1i)) = 0.45509+1.09868i, y*y=-1+1i
y = Csqrt(-1+2i)) = 0.786151+1.27202i, y*y=-1+2i
y = Csqrt(0+-2i)) = 1+-1i, y*y=0+-2i
y = Csqrt(0+-1i)) = 0.707107+-0.707107i, y*y=1.5702e-16+-1i
y = Csqrt(0+0i)) = 0+0i, y*y=0+0i
y = Csqrt(0+1i)) = 0.707107+0.707107i, y*y=1.5702e-16+1i
y = Csqrt(0+2i)) = 1+1i, y*y=0+2i
y = Csqrt(1+-2i)) = 1.27202+-0.786151i, y*y=1+-2i
y = Csqrt(1+-1i)) = 1.09868+-0.45509i, y*y=1+-1i
y = Csqrt(1+0i)) = 1+0i, y*y=1+0i
y = Csqrt(1+1i)) = 1.09868+0.45509i, y*y=1+1i
y = Csqrt(1+2i)) = 1.27202+0.786151i, y*y=1+2i
y = Csqrt(2+-2i)) = 1.55377+-0.643594i, y*y=2+-2i
y = Csqrt(2+-1i)) = 1.45535+-0.343561i, y*y=2+-1i
y = Csqrt(2+0i)) = 1.41421+0i, y*y=2+0i
y = Csqrt(2+1i)) = 1.45535+0.343561i, y*y=2+1i
y = Csqrt(2+2i)) = 1.55377+0.643594i, y*y=2+2i

Using the function Jacob Navia provided,
rewritten to use __complex__ types.

y = Csqrt2(-2+-2i)) = 0.643594+-1.55377i, y*y=-2+-2i
y = Csqrt2(-2+-1i)) = 0.343561+-1.45535i, y*y=-2+-1i
y = Csqrt2(-2+0i)) = 0+1.41421i, y*y=-2+0i
y = Csqrt2(-2+1i)) = 0.343561+1.45535i, y*y=-2+1i
y = Csqrt2(-2+2i)) = 0.643594+1.55377i, y*y=-2+2i
y = Csqrt2(-1+-2i)) = 0.786151+-1.27202i, y*y=-1+-2i
y = Csqrt2(-1+-1i)) = 0.45509+-1.09868i, y*y=-1+-1i
y = Csqrt2(-1+0i)) = 0+1i, y*y=-1+0i
y = Csqrt2(-1+1i)) = 0.45509+1.09868i, y*y=-1+1i
y = Csqrt2(-1+2i)) = 0.786151+1.27202i, y*y=-1+2i
y = Csqrt2(0+-2i)) = 1+-1i, y*y=0+-2i
y = Csqrt2(0+-1i)) = 0.707107+-0.707107i, y*y=1.5702e-16+-1i
y = Csqrt2(0+0i)) = 0+0i, y*y=0+0i
y = Csqrt2(0+1i)) = 0.707107+0.707107i, y*y=1.5702e-16+1i
y = Csqrt2(0+2i)) = 1+1i, y*y=0+2i
y = Csqrt2(1+-2i)) = 1.27202+-0.786151i, y*y=1+-2i
y = Csqrt2(1+-1i)) = 1.09868+-0.45509i, y*y=1+-1i
y = Csqrt2(1+0i)) = 1+0i, y*y=1+0i
y = Csqrt2(1+1i)) = 1.09868+0.45509i, y*y=1+1i
y = Csqrt2(1+2i)) = 1.27202+0.786151i, y*y=1+2i
y = Csqrt2(2+-2i)) = 1.55377+-0.643594i, y*y=2+-2i
y = Csqrt2(2+-1i)) = 1.45535+-0.343561i, y*y=2+-1i
y = Csqrt2(2+0i)) = 1.41421+0i, y*y=2+0i
y = Csqrt2(2+1i)) = 1.45535+0.343561i, y*y=2+1i
y = Csqrt2(2+2i)) = 1.55377+0.643594i, y*y=2+2i
Jan 25 '08 #4
jacob navia <ja***@nospam.comwrote:
In lcc-win it works since lcc-win defines
#define creal(z) z.re
Nitpick: you need
#define creal(z) ((z).re)

to avoid bad interactions with operators when z is an expression
and creal(z) is part of a larger expression.

(this apart from whether creal() can be implemented as a macro,
and whether the standard should provide direct accessors to the
members of a complex.)
--
pa at panix dot com
Jan 25 '08 #5
jacob navia wrote:
Army1987 wrote:
>z = creal(z) + I * new_imag_part;
z = new_real_part + I * cimag(z);

Well in the chapter "Awful syntax anyone?" that would
take the first prize...

Or maybe that's too harsh.

fn = (int *(*)(int))foo;

is maybe better
Afwulness is in the eye of the beholder.
I think I will keep my "extensions"

z.im = new_imag_part;

Easy isn't it?
I think that you're allowed to do that, as that couldn't break any strictly
conforming program.
Why do we have creal()z) (a "getter" function) and not setreal(z) (the
"setter" part)?
Yes, maybe that'be useful. (Of course that'd not be setreal(z)...)
--
Army1987 (Replace "NOSPAM" with "email")
Jan 25 '08 #6
Army1987 wrote:
jacob navia wrote:
>I think I will keep my "extensions"

z.im = new_imag_part;

Easy isn't it?
I think that you're allowed to do that, as that couldn't break any strictly
conforming program.
Not breaking strictly conforming programs is only one requirement of a
conforming implementation. Jacob's extension violates a constraint,
according to n1256 6.5.2.3p1. He's only allowed to do it provided he
issues a diagnostic in conforming mode.
>Why do we have creal()z) (a "getter" function) and not setreal(z) (the
"setter" part)?
Yes, maybe that'be useful. (Of course that'd not be setreal(z)...)
I can see the argument for it, though it's purely syntactic since

setreal(&z,real); /* or z = setreal(z,real); */

would be equivalent to

z = real + cimag(z)*I;

In fact I prefer the current version of doing things, because C's syntax
does not lend itself to setter functions (ie z.setreal(real) or
setreal(z,real) would not be possible.)
Jan 25 '08 #7
Philip Potter wrote:
Army1987 wrote:
>jacob navia wrote:
>>I think I will keep my "extensions"

z.im = new_imag_part;

Easy isn't it?
I think that you're allowed to do that, as that couldn't break any
strictly
conforming program.

Not breaking strictly conforming programs is only one requirement of a
conforming implementation. Jacob's extension violates a constraint,
according to n1256 6.5.2.3p1. He's only allowed to do it provided he
issues a diagnostic in conforming mode.
>>Why do we have creal()z) (a "getter" function) and not setreal(z) (the
"setter" part)?
Yes, maybe that'be useful. (Of course that'd not be setreal(z)...)

I can see the argument for it, though it's purely syntactic since

setreal(&z,real); /* or z = setreal(z,real); */

would be equivalent to

z = real + cimag(z)*I;

In fact I prefer the current version of doing things, because C's syntax
does not lend itself to setter functions (ie z.setreal(real) or
setreal(z,real) would not be possible.)
But why z.real and z.imaginary would be forbidden?

It is clear that complex are built from float/double/long double PAIRS.
Why couldn't we agree in the name of those elemnts of the pairs
and be done with it?

Writing

z.real = 5.887;

is Much clearer than

z = creal(z) + 5.887*I;

Besides, it requires a lot LESS implementation effort
than to recognize the first thing as its equivalent.

For a compiler is harder to recognize ALL the possible forms of the
first statement as equivalent

z = 5.887*I+creal(z);
z = (6.887-1.0)*I+creal(z);

etc etc etc!

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 25 '08 #8
Army1987 <ar******@nospam.itwrote:
Any function can be implemented as a macro, but it ought to be
#define creal(z) (((double _Complex)(z)).re)
as it should have the right type regardless of the type of z.
But then you lose the lvalue-preserving property. It looks like
there is no way to do what Jacob wanted without breaking the

Come to think of it, how is it done in Fortran ? The same way
as in C99, I think.
complex z
z= cmplx(new_real_val, imag(z))
z= cmplx(real(z), new_imag_val)

No direct accessors there either. To change one of the components
you have to synthesize a new complex number.

--
pa at panix dot com
Jan 26 '08 #9
user923005 wrote:
It could be implemented (for instance) as:

complex {
double parts[2];
};

or
complex {
double re;
double im;
};

or whatever underneath the covers, since that bit is not specified
clearly.
Of course it might be implemented as the standard specifies:
"Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements of the
corresponding real type; the first element is equal to the real part,
and the second element to the imaginary part, of the complex
number."
When you think about that, then I'm sure you will realize that there are
a number of ways to accomplish what you want.
Jan 26 '08 #10
On Jan 25, 9:01*pm, Martin Ambuhl <mamb...@earthlink.netwrote:
user923005 wrote:
It could be implemented (for instance) as:
complex {
double parts[2];
};
or
complex {
double re;
double im;
};
or whatever underneath the covers, since that bit is not specified
clearly.

Of course it might be implemented as the standard specifies:
"Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements of the
corresponding real type; the first element is equal to the real part,
and the second element to the imaginary part, of the complex
number."
When you think about that, then I'm sure you will realize that there are
a number of ways to accomplish what you want.
It's kind of sad if you are forced to do it in an underhanded way by
Jan 28 '08 #11
user923005 wrote:
On Jan 25, 9:01 pm, Martin Ambuhl <mamb...@earthlink.netwrote:
>user923005 wrote:
>>It could be implemented (for instance) as:
complex {
double parts[2];
};
or
complex {
double re;
double im;
};
or whatever underneath the covers, since that bit is not specified
clearly.
Of course it might be implemented as the standard specifies:
"Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements of the
corresponding real type; the first element is equal to the real part,
and the second element to the imaginary part, of the complex
number."
When you think about that, then I'm sure you will realize that there are
a number of ways to accomplish what you want.

It's kind of sad if you are forced to do it in an underhanded way by
Specially if it could have been so easy to specify a couple of "setter"
functions:

// For double _Complex
double sreal(complex,double); // Returns the old value
double simag(complex,double); // Returns the old value

that would do this!

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jan 28 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

### Similar topics

 34 by: Pmb | last post by: I've been working on creating a Complex class for my own learning purpose (learn through doing etc.). I'm once again puzzled about something. I can't figure out how to overload the assignment... 3 by: Arthur | last post by: Spending the morning avoiding responsibilities, and seeing what it would take to color some complex numbers. class color_complex(complex): def __init__(self,*args,**kws):... 7 by: Schüle Daniel | last post by: Hello I am trying to customize the handling of complex numbers what I am missing is a builtin possibility to create complex numbers in polar coordinates so first I wrote a standalone function... 12 by: Russ | last post by: I tried the following: >>> x = complex(4) >>> y = x >>> y *= 2 >>> print x, y (4+0j) (8+0j) But when I tried the same thing with my own class in place of "complex" above, I found that both... 2 by: jccorreu | last post by: I'm taking in data from multiple files that represents complex numbers for charateristics of different elements. I begin with arrays of doubles and interpolate to get standard values in real and... 3 by: Klaas Vantournhout | last post by: Hi, I am using CLAPACK to do lots of matrix operations, but this is done on complex matrices. There I also need to work with normal complex operators, I use also the standard complex library. ... 2 by: jraul | last post by: Suppose you have a complex number class, and you overload conversions to double by only taking the real part. You also overload operator* to do complex multiplication. You then write: ... 3 by: katis | last post by: Hi all :) Is it posible in xsd to change only minOccurs value of element in complex type by extending this type? The problem I'm trying to solve is this: I have two complex types -... 2 by: =?Utf-8?B?c2lwcHl1Y29ubg==?= | last post by: Have a complex process where I need to Import a large amount of data then run some transformations on this data then import into DataBase. The transformation involves multiple fields and multiple... 0 by: Rina0 | last post by: Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and... 0 by: erikbower65 | last post by: Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to... 0 by: linyimin | last post by: Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for... 0 by: kcodez | last post by: As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it... 0 by: Taofi | last post by: I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ... 0 by: lllomh | last post by: Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{ 0 by: lllomh | last post by: How does React native implement an English player? 0 by: Mushico | last post by: How to calculate date of retirement from date of birth 2 by: DJRhino | last post by: Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...