-1

I'm trying to printf a 1D array of complex numbers (c_double_complex)that is filled in the Fortran90 code and allocated in C code.

However, when printing the array in C (using %f) after passing it from the Fortran code, only the first complex number of the array is printed and the rest is zero.

I've tried it with integer and double and it worked fine.

subroutine F_sub ( a, array ) bind (C, name="F_sub")
   use, intrinsic :: iso_c_binding
   implicit none
   integer (c_int) :: a
   complex (c_double_complex), dimension (a) :: array

  array = [ 2.5 , 4.4 ]
   a = 18
end subroutine F_sub
#include <stdio.h>
#include <stdlib.h>

void F_sub ( int *a, double _Complex * array_ptr );

int main ( void ) {

   double _Complex * array_ptr;
   int a;
    a=2;
   array_ptr = malloc (8* sizeof(double _Complex));

   F_sub (&a, array_ptr);

   printf ( "Values are: %f %f and a= %d\n", array_ptr [0], array_ptr [1] , a);
   free(array_ptr);
   return 0;
}
output: Values are: 2.500000 0.000000 and a= 18

Could anyone please tell me where is the problem in above codes?

francescalus
  • 30,576
  • 16
  • 61
  • 96
dev.robi
  • 19
  • 5
  • `%f` is the format specifier for `double` but you pass a `double _Complex`. [See here](https://stackoverflow.com/questions/4099433/c-complex-number-and-printf) for some suggestion about printing complex numbers – M.M Apr 25 '19 at 22:37

1 Answers1

0

Put simply, neither the POSIX specification of printf() nor the Standard C specification includes any conversion formats for printing complex numbers. You'll have to pass the real and imaginary parts of a complex number separately to printf(), and provide 2 conversion specifiers. For example, you could use cimag() and creal() from <complex.h> and the generic format %g (the + ensures there's always a sign, + or -):

printf("%g%+gi", creal(array_ptr[0]), cimag(array_ptr[0]));

I would probably create myself a function to handle the formatting of complex numbers, and use that everywhere, rather than repeatedly writing the code out.


From a comment:

… my concern is not related to the printing part of the complex number; it is about why the C code can not print the second number (4.4) in the array and only the first one is printed (2.5).

See §6.2.5 Types ¶11ff:

¶11 There are three complex types, designated as float _Complex, double _Complex, and long double _Complex.43) (Complex types are a conditional feature that implementations need not support; see 6.10.8.3.) The real floating and complex types are collectively called the floating types.

¶12 For each floating type there is a corresponding real type, which is always a real floating type. For real floating types, it is the same type. For complex types, it is the type given by deleting the keyword _Complex from the type name.

¶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.

So, the C complex numbers are treated as an array of two values. In the C code, array_ptr[0] is one complex number. You are supposed to use creal() and cimag() or similar functions to get the two parts out of the one number. AFAICS, your Fortran function (I only know Fortran 77 — I never got to play with Fortran 90, and the code shown is radically different from F77!) is only setting a single complex number. So I don't believe there is an array_ptr[1] for you to access; you get undefined behaviour. I'm not sure I have a good explanation of why you're getting anything sensible. I'd expect that array_ptr[0] is equivalent to a pointer, and the code wouldn't print the number it points at.

I do have gfortran (from GCC 8.3.0); I can try your code later.

I'm having nasty thoughts about what's going wrong — I suspect that you need a minor variant of this:

double _Complex value;

F_sub(&a, &value);

printf("Values are: %f %f and a= %d\n", creal(value), cimag(value), a);

If this is correct, then you're getting away with blue murder (or undefined behaviour), and are unlucky that the code isn't crashing. There is also a chance that you don't need the & in &value in the call to F_sub().

I also suspect that the free(array_ptr) in your code is erroneous — I don't see why Fortran would allocate space.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I understand what you are talking bout. But actually my concern is not related to the printing part of the complex number, it is about why the C code can not print the second number (4.4) in the array and only the first one is printed (2.5). – dev.robi Apr 25 '19 at 22:49
  • I've added some non-definitive thoughts to my answer — I'm not sure that you get notified that I edited it. I may need to undo the 'duplicate' too. – Jonathan Leffler Apr 25 '19 at 23:34
  • Yes. I have tried and it is working with me. – dev.robi Apr 28 '19 at 11:17