Search code examples
cc99complex-numbers

How to efficiently work with complex numbers in C language?


How to efficiently work with complex numbers in C language?

We have 3 options:

  1. Using structures and passing them to functions by value:
struct complex_double
{
   double data[2];
}

typedef struct complex_double ComplexDouble;

ComplexDouble complex_double_add(ComplexDouble z_1, ComplexDouble z_2)
{
   ComplexDouble result;

   result.data[0] = z_1.data[0] + z_2.data[0];
   result.data[1] = z_1.data[1] + z_2.data[1];

   return result;
}

But in this way we have 3 times copying of values of structures (two arguments and one return). The size of ComplexDouble is 16 bytes, so we need to copy 3 * 16 bytes = 48 bytes, which maybe is unefficiently.

  1. Passing pointers to structures:
struct complex_double
{
   double data[2];
}

typedef struct complex_double ComplexDouble;

ComplexDouble * complex_double_initialize(double x, double y)
{
   ComplexDouble *z;
   
   z = (ComplexDouble *)malloc( sizeof(ComplexDouble) );

   if(z == NULL)
   {
     fprintf(stderr, "complex_double_initialize: Error! Failed to allocate memory for ComplexDouble\n");
     exit(EXIT_FAILURE);
   }

   z->data[0] = x;
   z->data[1] = y;

   return z;
}

void complex_double_add(ComplexDouble *result, ComplexDouble *z_1, ComplexDouble *z_2)
{
   result->data[0] = z_1->data[0] + z_2->data[0];
   result->data[1] = z_1->data[1] + z_2->data[1];
}

In this variant we are passing 3 pointers to structures, which is 3 * 8 bytes = 24 bytes. Maybe this is more efficiently.

  1. Using complex type from C99 standard library:
double complex z_1, z_2, z_3;

z_3 = z_1 + z_2;

double complex double_complex_add(double complex z_1, double complex z_2)
{
   return (z_1 + z_2);
}

But there are something i don't understand about C99 complex type. How is double complex actually passed into function and returned from function? Is it copyed by value as in the first variant with structures?

Which variant should i use?


Solution

  • Use the standard version of it. It is nowadays integrated into compilers and is the best you can get.

    How is double complex actually passed into function and returned from function?
    

    They are accessible by value as the specification of your function indicates, and as would be the case for any other function parameters, unless they have an array type.

    Complex numbers are guaranteed to have the same representation (= memory layout) as a vector of two reals, but they are proper types:

    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.
    

    Although their byte pattern is the same as a two element vector of floating point values, they are considered as arithmetic types like any other number.