How to assign real and imaginary parts of complex variables in C - c

Using the complex number type of the C99 standard, how does one assign the real and imaginary parts of a variable individually? I found the GNU extension __real__ and __imag__ will do it, as in the following example program. But this isn't portable or standard. How can one do this portably?
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int
main()
{
complex double z;
__real__ z = 3.0;
__imag__ z = 2.0;
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}

C 2018 6.2.5 13 implies we can treat complex number as an array of two elements:
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.
This is crude wording, at odds with the explicitly stated aliasing rules in 6.5 7, but the standard is imperfect, and footnotes 41 and 49, about integers and pointers, suggest such statements about representation and alignment are supposed to allow some use of one view of the object for another in spite of the rules in 6.5 7. If so, we can define macros:
#define Re(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[0])
#define Im(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[1])
after which Re(x) and Im(x), when given a complex object, produce an lvalue for the real or imaginary part. So we can assign them:
Re(x) = 3;
Im(x) = 4;

How can one do this portably?
It's just... addition:
z = 3.0;
z += I * 2.0;
You could first zero the imaginary part, if you want to:
z = creal(z) + I * 2.0;
how does one assign the real and imaginary parts of a variable
individually?
// assign real
z = new_value + I * cimag(z);
// assign imaginary
z = creal(z) + I * new_value;
One could prefer _Imaginary_I or CMPLXF macros over I.

I found another possible solution. The code below assumes that complex double is bit-equivalent to double[2] (which I think is correct but would appreciate a verification!). I think the solution below may be more efficient since it doesn't involve an extra addition operation for each assignment (as does KamilCuk's solution).
If anyone can verify this is will be portable to all platforms, I would appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#define SET_REAL(z, x) ( *((double *) &(z)) = (x) )
#define SET_IMAG(z, x) ( *(((double *) &(z)) + 1) = (x) )
int
main()
{
complex double z;
SET_REAL(z, 3.0);
SET_IMAG(z, 2.0);
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}

Related

How to compare two complex numbers?

In C, complex numbers are float or double and have same problem as canonical types:
#include <stdio.h>
#include <complex.h>
int main(void)
{
double complex a = 0 + I * 0;
double complex b = 1 + I * 1;
for (int i = 0; i < 10; i++) {
a += .1 + I * .1;
}
if (a == b) {
puts("Ok");
}
else {
printf("Fail: %f + i%f != %f + i%f\n", creal(a), cimag(a), creal(b), cimag(b));
}
return 0;
}
The result:
$ clang main.c
$ ./a.out
Fail: 1.000000 + i1.000000 != 1.000000 + i1.000000
I try this syntax:
a - b < DBL_EPSILON + I * DBL_EPSILON
But the compiler hate it:
main.c:24:15: error: invalid operands to binary expression ('_Complex double' and '_Complex double')
if (a - b < DBL_EPSILON + I * DBL_EPSILON) {
~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This last works fine but it’s a little fastidious:
fabs(creal(a) - creal(b)) < DBL_EPSILON && fabs(cimag(a) - cimag(b)) < DBL_EPSILON
Comparing 2 complex floating point numbers is much like comparing 2 real floating point numbers.
Comparing for exact equivalences often is insufficient as the numbers involved contain small computational errors.
So rather than if (a == b) code needs to be if (nearlyequal(a,b))
The usual approach is double diff = cabs(a - b) and then comparing diff to some small constant value like DBL_EPSILON.
This fails when a,b are large numbers as their difference may many orders of magnitude larger than DBL_EPSILON, even though a,b differ only by their least significant bit.
This fails for small numbers too as the difference between a,b may be relatively great, but many orders of magnitude smaller than DBL_EPSILON and so return true when the value are relatively quite different.
Complex numbers literally add another dimensional problem to the issue as the real and imaginary components themselves may be greatly different. Thus the best answer for nearlyequal(a,b) is highly dependent on the code's goals.
For simplicity, let us use the magnitude of the difference as compared to the average magnitude of a,b. A control constant ULP_N approximates the number of binary digits of least significance that a,b are allowed to differ.
#define ULP_N 4
bool nearlyequal(complex double a, complex double b) {
double diff = cabs(a - b);
double mag = (cabs(a) + cabs(b))/2;
return diff <= (mag * DBL_EPSILON * (1ull << ULP_N));
}
Instead of comparing the complex number components, you can compute the complex absolute value (also known as norm, modulus or magnitude) of their difference, which is the distance between the two on the complex plane:
if (cabs(a - b) < DBL_EPSILON) {
// complex numbers are close
}
Small complex numbers will appear to be close to zero even if there is no precision issue, a separate issue that is also present for real numbers.
Since complex numbers are represented as floating point numbers, you have to deal with their inherent imprecision. Floating point numbers are "close enough" if they're within the machine epsilon.
The usual way is to subtract them, take the absolute value, and see if it's close enough.
#include <complex.h>
#include <stdbool.h>
#include <float.h>
static inline bool ceq(double complex a, double complex b) {
return cabs(a-b) < DBL_EPSILON;
}

Is it possible to have variable inputs in C functions

I'm making a simple function to calculate the difference between two inputs. Just for convenience really. Something to refer to in personal header files.
I wish to input either:
two integers : output one integer
two doubles : output one double
I've tried searching online for some kind of global input declaration but can't find it.
I prefer not to have two functions, just one simple one.
Example code headers:
int diff(int a, int b);
double diff(double a, double b);
Thanks for the help!
No, this is called overloading and it's not a feature C has. You are best off creating distinct functions to handle this.
You can do it with all sorts of C wizardry (you can just about do anything with enough C wizardry), but the resulting code may be so ugly as to be unmaintainable :-)
For example, C11 introduced generic selections, with the _Generic primary expression, and this allows you to call different functions based on the input argument type. It actually does a little more than that, but that's the aspect you're interested in, based on your question.
For example, let's say you define two functions thus:
int diffi (int a, int b) { return a - b; }
double diffd (double a, double b) { return a - b; }
Normally, you would have to decide which to call based on what your input types were. The C11 generic selection feature allows you to do this:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
int: diffi, \
default: diffX \
)(a,b)
And what this does is basically, on finding the macro diff(x,y) in the source code:
determine the type of the expression (a), without evaluating it;
inject into the source stream the token matching that type (or default if no match found);
inject into the source stream the (a,b) text at the end.
So, if your source file contains the lines:
x = diff (1, 2);
y = diff (1.0, 2);
this will be translated into:
x = diffi (1 , 2);
y = diffd (1.0, 2);
giving you your effective overloading.
Now that's a moderately easy case since it relies on only the first argument type - you'll see a hole there if you try to do:
z = diff (1, 2.0);
in that the type of the first argument is an int so you'll get:
z = diffi (1, 2.0);
which won't be what you actually want to do. This is where the complexities come in since you have to cover four possibilities: {int/int, int/double, double/int, double/double} and it gets more complex based on the number of arguments and the possible types for each argument.
That full case of yours, however, can be done with judicious use of defaults and nested generic selections, something like:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
and this can be read as:
if the type of a is double, use diffd;
otherwise, if the type of b is double, use diffd;
otherwise, use diffi.
don't forget to inject the arguments as well.
The following complete program (compiled with clang 3.0) shows this feature in action:
#include <stdio.h>
int diffi (int a, int b) {
printf ("diffi %d %d", a, b);
return a - b;
}
double diffd (double a, double b) {
printf ("diffd %f %f", a, b);
return a - b;
}
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
int main (void) {
int i; double d;
i = diff (1 , 2 ); printf (" --> %d\n", i);
d = diff (1.0, 2 ); printf (" --> %f\n", d);
d = diff (1 , 2.0); printf (" --> %f\n", d);
d = diff (1.0, 2.0); printf (" --> %f\n", d);
return 0;
}
The output of that program is:
diffi 1 2 --> -1
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
showing that the correct function is being called for the four possibilities.
And, in fact, as rici points out in a comment, you can rely on the promotion rules of C, where adding a double and int (in any order) gives you a double while adding two int variables gives you an int:
#define diff(a,b) _Generic((a+b), double:diffd, default:diffi)(a,b)
Function overloading is not available in C.
Some possible workarounds
Use two functions with different names for ex: diff_i and diff_d
(Recommended)
Use varargs (not recommended) This will make code difficult to maintain with time.
Use _Generic
An IEEE754 double has more than 32bits of precision, so just write the double version and let automatic conversion take care of the rest.
Of course if you're using a system where sizeof(int)>4 or a char has more than 8 bits, it may be best to write variants for each type, and adopt some kind of Hungarian-naming-convension for them. You could then write, maybe:
int diffi(int, int);
double diffd(double, double);
ssize_t diffz(size_t, size_t);
etc. Essentially, this is manually name-mangling, the same technique the C++ compiler uses to generate distinct symbolic-names for the object-file's export table.

How to create a complex type of a existing function?

I am just beginning C programming (not C++) and I have to convert the quadratic formula for adressing complex roots, and for printing these. The normal quadratic equation is as follows (for discriminant > 0):
else {
/* */
x1 = ((-b) + sqrt(discr)) / (2 * a);
x2 = ((-b) - sqrt(discr)) / (2 * a);
printf("%s%.4lf%s%.4lf\n\n", "x1: ", x1, "\tx2: ", x2);
}
When I try to convert this into its complex values I have used the following strategies:
Creating a new version of the result of the sqrt(discr), the complex part in the equation, by creating a variable _Complex double discr_complex = discr * I.
-> OR discr_complex = discr + discr * I.
Making x1 and x2 complex by 'complex x1' or '_Complex c1' or 'complex x1 = ..formula.. * I' or '_Complex x1 = ...formula * I'.
Making every part complex by using the keyword complex.
For all these versions it does not print the correct complex output (#+#i). I tried printing the normal values, which works, but not for the complex part. I tried using the methods creal(x1) and cimag(x1) which do not work (undeclared reference to creal / cimag), or x1.real() / x1.imag(), which also doesn't work ('imag' in something not a structure or union).
Does anybody maybe know how to convert my x1 and x2 values into complex numbers, with maybe a clear explanation how to return each seperate part of the complex equation (real/imaginary) and how this conversion takes place taken my 'normal' formula?
The reason that calling creal does not work is that either you have not included the proper header complex.h or you are calling it with an argument x1 that is not of the correct type double complex. The second error, when you call x1.real() is because the . notation tries to access a member of a struct but x1 is a double.
I suggest using complex.h that enables working with complex numbers and define a new abc-formula that deals with complex numbers. Also note that you can not use 'regular' math functions like sqrt on variables of complex type but need to use the complex.h analogs e.g. csqrt()
#include <complex.h>
int main(void)
{
double complex z = 1.0 + 0.5 * I;
printf("The real part of z = %f\n", creal(z));
printf("The iamginary part of z = %f\n", cimag(z));
return 0;
}
Edit:
completely redefine your function, try something like this:
void complex_abc() {
double complex a = 1;
double complex b = 2;
double complex c = 3;
double complex x1;
double complex x2;
double complex d;
d = b*b - 4 * a * c;
x1 = ( -b + csqrt(d) ) / 2*a;
x2 = ( -b - csqrt(d) ) / 2*a;
printf("x1 = %f + i %f\n", creal(x1), cimag(x1));
printf("x2 = %f + i %f\n", creal(x2), cimag(x2));
return;
}
And as correctly noted by #Lutzl in the comments you need to link the math library with the flag -lm during compiling

C99 complex casting

I have some C99 code where I need to convert an array of 2n double to an array of n double complex. I do this with
static void real_to_complex(const double *r, size_t n, double complex *z)
{
size_t i;
for (i=0 ; i<n ; i++)
z[i] = r[2*i] + r[2*i + 1]*I;
}
This is a performance critical part of the code, and I'd really rather not have to create a new storage area z and have the expense of the copying, instead I'd like to replace these function calls by
z = (double complex*)r;
Is there any way to do this and remain standard conforming? I understand that a double complex is guaranteed to have the same layout as an array of two doubles -- perhaps I could get away with a compiler check as to whether this layout is (real,imaginary) or (imaginary,real)?
You are guaranteed the first element of the complex array corresponds to the real part and the second element corresponds to the imaginary part.
Quote from the publicly available draft of C11 Standard
6.2.5/13 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.
Example program
#include <complex.h>
#include <stdio.h>
int main(void) {
double x[] = {42, 2, 41, 1, 0, 0};
_Complex double *y = (void*)x;
while (creal(*y) > 0) {
printf("%f + %fi\n", creal(*y), cimag(*y));
y++;
}
return 0;
}

How to work with complex numbers in C?

How can I work with complex numbers in C? I see there is a complex.h header file, but it doesn't give me much information about how to use it. How to access real and imaginary parts in an efficient way? Is there native functions to get module and phase?
This code will help you, and it's fairly self-explanatory:
#include <stdio.h> /* Standard Library of Input and Output */
#include <complex.h> /* Standard Library of Complex Numbers */
int main() {
double complex z1 = 1.0 + 3.0 * I;
double complex z2 = 1.0 - 4.0 * I;
printf("Working with complex numbers:\n\v");
printf("Starting values: Z1 = %.2f + %.2fi\tZ2 = %.2f %+.2fi\n", creal(z1), cimag(z1), creal(z2), cimag(z2));
double complex sum = z1 + z2;
printf("The sum: Z1 + Z2 = %.2f %+.2fi\n", creal(sum), cimag(sum));
double complex difference = z1 - z2;
printf("The difference: Z1 - Z2 = %.2f %+.2fi\n", creal(difference), cimag(difference));
double complex product = z1 * z2;
printf("The product: Z1 x Z2 = %.2f %+.2fi\n", creal(product), cimag(product));
double complex quotient = z1 / z2;
printf("The quotient: Z1 / Z2 = %.2f %+.2fi\n", creal(quotient), cimag(quotient));
double complex conjugate = conj(z1);
printf("The conjugate of Z1 = %.2f %+.2fi\n", creal(conjugate), cimag(conjugate));
return 0;
}
with:
creal(z1): get the real part (for float crealf(z1), for long double creall(z1))
cimag(z1): get the imaginary part (for float cimagf(z1), for long double cimagl(z1))
Another important point to remember when working with complex numbers is that functions like cos(), exp() and sqrt() must be replaced with their complex forms, e.g. ccos(), cexp(), csqrt().
Complex types are in the C language since C99 standard (-std=c99 option of GCC). Some compilers may implement complex types even in more earlier modes, but this is non-standard and non-portable extension (e.g. IBM XL, GCC, may be intel,... ).
You can start from http://en.wikipedia.org/wiki/Complex.h - it gives a description of functions from complex.h
This manual http://pubs.opengroup.org/onlinepubs/009604499/basedefs/complex.h.html also gives some info about macros.
To declare a complex variable, use
double _Complex a; // use c* functions without suffix
or
float _Complex b; // use c*f functions - with f suffix
long double _Complex c; // use c*l functions - with l suffix
To give a value into complex, use _Complex_I macro from complex.h:
float _Complex d = 2.0f + 2.0f*_Complex_I;
(actually there can be some problems here with (0,-0i) numbers and NaNs in single half of complex)
Module is cabs(a)/cabsl(c)/cabsf(b); Real part is creal(a), Imaginary is cimag(a). carg(a) is for complex argument.
To directly access (read/write) real an imag part you may use this unportable GCC-extension:
__real__ a = 1.4;
__imag__ a = 2.0;
float b = __real__ a;
For convenience, one may include tgmath.h library for the type generate macros. It creates the same function name as the double version for all type of variable. For example, For example, it defines a sqrt() macro that expands to the sqrtf() , sqrt() , or sqrtl() function, depending on the type of argument provided.
So one don't need to remember the corresponding function name for different type of variables!
#include <stdio.h>
#include <tgmath.h>//for the type generate macros.
#include <complex.h>//for easier declare complex variables and complex unit I
int main(void)
{
double complex z1=1./4.*M_PI+1./4.*M_PI*I;//M_PI is just pi=3.1415...
double complex z2, z3, z4, z5;
z2=exp(z1);
z3=sin(z1);
z4=sqrt(z1);
z5=log(z1);
printf("exp(z1)=%lf + %lf I\n", creal(z2),cimag(z2));
printf("sin(z1)=%lf + %lf I\n", creal(z3),cimag(z3));
printf("sqrt(z1)=%lf + %lf I\n", creal(z4),cimag(z4));
printf("log(z1)=%lf + %lf I\n", creal(z5),cimag(z5));
return 0;
}
The notion of complex numbers was introduced in mathematics, from the need of calculating negative quadratic roots. Complex number concept was taken by a variety of engineering fields.
Today that complex numbers are widely used in advanced engineering domains such as physics, electronics, mechanics, astronomy, etc...
Real and imaginary part, of a negative square root example:
#include <stdio.h>
#include <complex.h>
int main()
{
int negNum;
printf("Calculate negative square roots:\n"
"Enter negative number:");
scanf("%d", &negNum);
double complex negSqrt = csqrt(negNum);
double pReal = creal(negSqrt);
double pImag = cimag(negSqrt);
printf("\nReal part %f, imaginary part %f"
", for negative square root.(%d)",
pReal, pImag, negNum);
return 0;
}
To extract the real part of a complex-valued expression z, use the notation as __real__ z.
Similarly, use __imag__ attribute on the z to extract the imaginary part.
For example;
__complex__ float z;
float r;
float i;
r = __real__ z;
i = __imag__ z;
r is the real part of the complex number "z"
i is the imaginary part of the complex number "z"

Resources