Scientific Programming in C X. More features & Fortran interface Susi Lehtola 20 November 2012
typedef typedefs are a way to make shorthand for data types, and possibly also make the code more general (e.g., make a single-precision and double-precision version from the same code). / D e c l a r e r e a l to be the same as double / typedef double r e a l ; r e a l x, y, z ; You can t use modifiers with typedef d data types, e.g. long real would give a compiler error. Scientific Programming in C, fall 2012 Susi Lehtola More features 2/58
typedef typedefs are most often used for structs. Instead of s t r u c t v e c t o r { double x, y, z ; } ; s t r u c t v e c t o r r ; one can write typedef s t r u c t { double x, y, z ; } v e c t o r ; v e c t o r r ; Scientific Programming in C, fall 2012 Susi Lehtola More features 3/58
switch Now that we have a working knowledge of C, we can discuss some more features of C. The switch statement is an alternative to using many if statements, when an expression is only evaluated once. The wanted possibilities are identified in the switch statement, and the execution proceeds to the relevant branch if one exists. The default branch (if it exists) is executed if no other branch is matched. The execution continues until the end of the switch statement or until a break statement is encountered. Scientific Programming in C, fall 2012 Susi Lehtola More features 4/58
switch example #i n c l u d e <s t d i o. h> i n t main ( v o i d ) { / Amount o f c h a r a c t e r s, t a b s and l i n e s / s i z e t nc =0, n l =0; i n t c ; } w h i l e ( ( c=g e t c h a r ( ) )! =EOF) s w i t c h ( c ) { / I f c i s a n e w l i n e c h a r a c t e r / case ( \n ) : / I n c r e m e n t number o f l i n e s / n l ++; / Any o t h e r c h a r a c t e r than t h e one ( s ) s p e c i f i e d above / d e f a u l t : nc++; break ; } p r i n t f ( %u c h a r a c t e r s on %u l i n e s. \ n, nc, n l ) ; r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola More features 5/58
switch example, cont d In the preceding example, if c is a newline character, the number of lines is incremented. However, because there is no break statement, the program continues to the default case, and the number of characters is also incremented for the newline character. Scientific Programming in C, fall 2012 Susi Lehtola More features 6/58
2nd switch example i n t i s w h i t e ( i n t c ) { / Check f o r w h i t e s p a c e c h a r a c t e r / s w i t c h ( c ) { } / c i s w h i t e s p a c e / case ( ) : case ( \ f ) : case ( \n ) : case ( \ t ) : case ( \ v ) : r e t u r n 1 ; / Normally, you s h o u l d have t h i s h e r e. However, i n t h i s c a s e i t i s v o l u n t a r y s i n c e t h e r e t u r n s t a t e m e n t ends t h e f u n c t i o n. / break ; / c i s not w h i t e s p a c e / d e f a u l t : r e t u r n 0 ; } Scientific Programming in C, fall 2012 Susi Lehtola More features 7/58
2nd switch example, cont d The iswhite function returns 1 for white space characters and 0 for non-white space characters, analogously to the isspace() function. Scientific Programming in C, fall 2012 Susi Lehtola More features 8/58
Duff s device What does the following code fragment do? (Taken from learn C the hard way) v o i d d u f f s d e v i c e ( char from, char to, s i z e t count ) { s i z e t n = ( count + 7) / 8 ; } s w i t c h ( count % 8) { case 0 : do { to++ = from++; case 7 : to++ = from++; case 6 : to++ = from++; case 5 : to++ = from++; case 4 : to++ = from++; case 3 : to++ = from++; case 2 : to++ = from++; case 1 : to++ = from++; } w h i l e( n > 0 ) ; } Scientific Programming in C, fall 2012 Susi Lehtola More features 9/58
Duff s device What does the following code fragment do? (Taken from learn C the hard way) v o i d d u f f s d e v i c e ( char from, char to, s i z e t count ) { s i z e t n = ( count + 7) / 8 ; } s w i t c h ( count % 8) { case 0 : do { to++ = from++; case 7 : to++ = from++; case 6 : to++ = from++; case 5 : to++ = from++; case 4 : to++ = from++; case 3 : to++ = from++; case 2 : to++ = from++; case 1 : to++ = from++; } w h i l e( n > 0 ) ; } Don t write this at home. Scientific Programming in C, fall 2012 Susi Lehtola More features 10/58
Duff s device, cont d copies data from char *from to char *to copying is done byte by byte, up to 8 bytes at a time n is the number of iterations necessary in the nasty construct the execution hops within the while loop if count is not divisible by 8, only the remainder is copied in the first iteration otherwise the copy does 8 bytes Scientific Programming in C, fall 2012 Susi Lehtola More features 11/58
Duff s device, cont d copies data from char *from to char *to copying is done byte by byte, up to 8 bytes at a time n is the number of iterations necessary in the nasty construct the execution hops within the while loop if count is not divisible by 8, only the remainder is copied in the first iteration otherwise the copy does 8 bytes Don t write code like this. Scientific Programming in C, fall 2012 Susi Lehtola More features 12/58
enum enums are a way to declare constant integer values. By default the numbering starts from 0. / NO i s 0, YES i s 1 / enum t r u t h {NO, YES } ; You can also change the starting point enum weekday {MON=1, TUE, WED, THU, FRI, SAT, SUN} ; enum month {JAN=1, FEB, MAR, APR, MAY, JUN, \ JUL, AUG, SEP, OCT, NOV, DEC} ; or specify all of the values manually enum e s c a p e s { BELL= \a, BACKSPACE= \b, TAB= \ t, NEWLINE= \n, VTAB= \ v, RETURN= \ r } ; Scientific Programming in C, fall 2012 Susi Lehtola More features 13/58
Using enums The typical case where you want to use enums is when your program has many different runmodes. Using enums instead of a manually constructed list using #defines makes programming less error-prone. Scientific Programming in C, fall 2012 Susi Lehtola More features 14/58
enum example The following example is from the Casida TDDFT routines of ERKALE: / What k i n d o f c o u p l i n g i s used / enum c o u p l i n g m o d e { / I n d e p e n d e n t P a r t i c l e A p p r o x i m a t i o n / IPA, / Random Phase A p p r o x i m a t i o n / RPA, / Time Dependent L o c a l D e n s i t y A p p r o x i m a t i o n / TDLDA } ; Calculations can be made within different levels of theory, IPA being the simplest, RPA being much more sophisticated and TDLDA furthermore adding some minor corrections. Scientific Programming in C, fall 2012 Susi Lehtola More features 15/58
enum example, cont d In the code enum c o u p l i n g m o d e c o u p l i n g ; When the input is parsed, coupling is then set to IPA, RPA or TDLDA, depending on the input arguments. In the code comparisons can be then made using the symbolic values, e.g. s w i t c h ( c o u p l i n g ) { case (TDLDA ) : / Code c a l c u l a t i n g l o c a l d e n s i t y c o r r e c t i o n s / case (RPA ) : / Code c a l c u l a t i n g e f f e c t o f Coulomb i n t e r a c t i o n / case ( IPA ) : / No c o r r e c t i o n s / } Here TDLDA RPA IPA. Scientific Programming in C, fall 2012 Susi Lehtola More features 16/58
Another alternative to multidimensional arrays As it was mentioned in the pointer lecture, there are many ways to handle multidimensional arrays in C. The recommended way is to use dynamic memory allocation with manual indexing, as then one can be sure that the memory is allocated continguously and no memory trashing occurs. Scientific Programming in C, fall 2012 Susi Lehtola More features 17/58
Another alternative to multidimensional arrays As it was mentioned in the pointer lecture, there are many ways to handle multidimensional arrays in C. The recommended way is to use dynamic memory allocation with manual indexing, as then one can be sure that the memory is allocated continguously and no memory trashing occurs. However, there is also another alternative. Remember that arrays are pointers to the start of the array. Scientific Programming in C, fall 2012 Susi Lehtola More features 18/58
Another alternative to multidimensional arrays, cont d #i n c l u d e < s t d l i b. h> i n t main ( v o i d ) { / S i z e o f t h e a r r a y / s i z e t M=20, N=10; s i z e t i ; / P o i n t e r to t h e a r r a y o f p o i n t e r s / double p=null ; / A l l o c a t e memory f o r t h e p o i n t e r a r r a y / p=m a l l o c (M s i z e o f ( double ) ) ; / A l l o c a t e memory f o r t h e e l e m e n t s o f t h e a r r a y / p [0]= m a l l o c (M N s i z e o f ( double ) ) ; / I n i t i a l i z e t h e r e s t o f t h e a r r a y / f o r ( i =1; i <M; i ++) p [ i ]=p [0]+ i M s i z e o f ( double ) ; / Now e l e m e n t s o f t h e a r r a y can be a c c e s s e d w i t h p [ i ] [ j ] as w i t h t h e normal p o i n t e r a r r a y / } / F r e e t h e memory / f r e e ( p [ 0 ] ) ; f r e e ( p ) ; r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola More features 19/58
Another alternative to multidimensional arrays, cont d This is completely analogous to using static multidimensional arrays double t[2][3]; t t[0][0] t[0][1] t[0][2] t[1][0] t[1][1] t[1][2] t[0] t[1] the difference being that now the arrays are allocated dynamically. In contrast to the manual indexing scheme where you can decide what kind of ordering to use, here you always end up using the normal C ordering (last index runs fastest). Scientific Programming in C, fall 2012 Susi Lehtola More features 20/58
Pointers to functions Also functions can be handled as pointers in C. Note the difference in syntax / A f u n c t i o n t h a t r e t u r n s a p o i n t e r to i n t / i n t f ( ) ; / A p o i n t e r to a f u n c t i o n t h a t r e t u r n s i n t / i n t ( p f ) ( ) ; Scientific Programming in C, fall 2012 Susi Lehtola More features 21/58
Pointers to functions, cont d You can use function pointers to write generalized code, e.g. double e v a l ( double ( f ) ( double ), double x ) { / E v a l u a t e f u n c t i o n at x / return f ( x ) ; } which you can call with e v a l ( s i n, 1. 0 ) ; Scientific Programming in C, fall 2012 Susi Lehtola More features 22/58
Pointers to functions, cont d You can also use arrays of functions: #i n c l u d e <math. h> #i n c l u d e <s t d i o. h> #i n c l u d e < s t d l i b. h> i n t main ( v o i d ) { / P o i n t e r to p o i n t e r to f u n c t i o n f ( x ) / double ( f ) ( double x ) ; / H e l p e r / i n t i ; / A l l o c a t e memory f o r a r r a y / f=m a l l o c (3 s i z e o f ( double ( ) ( double ) ) ) ; / and s e t e l e m e n t s / f [0]= s i n ; / f ( x ) = s i n ( x ) / f [1]= l o g ; / f ( x ) = l o g ( x ) / f [2]= s q r t ; / f ( x ) = s q r t ( x ) / / P r i n t v a l u e s a t x =1.0 / f o r ( i =0; i <3; i ++) p r i n t f ( ( f )[% i ](1.0)=% e \n, i, f [ i ] ( 1. 0 ) ) ; f r e e ( f ) ; r e t u r n 0 ; } Scientific Programming in C, fall 2012 Susi Lehtola More features 23/58
Pointers to functions, cont d Running the code results in $. / a. out ( f ) [ 0 ] ( 1. 0 ) = 8. 4 1 4 7 1 0 e 01 ( f ) [ 1 ] ( 1. 0 ) = 0. 0 0 0 0 0 0 e+00 ( f ) [ 2 ] ( 1. 0 ) = 1. 0 0 0 0 0 0 e+00 which you can compare to the accurate values sin 1 = 0.8414709848078965 log 1 = 0 1 = 1 Scientific Programming in C, fall 2012 Susi Lehtola More features 24/58
Pointers to functions, cont d Running the code results in $. / a. out ( f ) [ 0 ] ( 1. 0 ) = 8. 4 1 4 7 1 0 e 01 ( f ) [ 1 ] ( 1. 0 ) = 0. 0 0 0 0 0 0 e+00 ( f ) [ 2 ] ( 1. 0 ) = 1. 0 0 0 0 0 0 e+00 which you can compare to the accurate values sin 1 = 0.8414709848078965 log 1 = 0 1 = 1 Remember that you could use qsort() to sort even this kind of an array, if you just come up with a comparison operator (e.g., wrt the value at x = 1) Scientific Programming in C, fall 2012 Susi Lehtola More features 25/58
Interfacing C with Fortran As you recall, there are some fundamental differences between C and Fortran. the size of an array is known a priori in Fortran, in C it isn t Fortran arrays are stored in column order (first index runs fastest), C arrays are stored in row order Fortran passes arguments by reference, whereas C passes them by value Scientific Programming in C, fall 2012 Susi Lehtola More features 26/58
Interfacing C with Fortran As you recall, there are some fundamental differences between C and Fortran. the size of an array is known a priori in Fortran, in C it isn t Fortran arrays are stored in column order (first index runs fastest), C arrays are stored in row order Fortran passes arguments by reference, whereas C passes them by value When you use Fortran functions or subroutines from C, you need to use pointer arguments. Scientific Programming in C, fall 2012 Susi Lehtola More features 27/58
Interfacing C with Fortran, cont d Conventionally it has been the case that people have wanted to use Fortran routines from C, mainly LAPACK (linear algebra such as matrix diagonalization). Scientific Programming in C, fall 2012 Susi Lehtola More features 28/58
Interfacing C with Fortran, cont d Conventionally it has been the case that people have wanted to use Fortran routines from C, mainly LAPACK (linear algebra such as matrix diagonalization). Nowadays also many Fortran users want to interface to C, as there are many extremely useful libraries available that have been written in C (or C++), such as the GNU Scientific Library (GSL) or FFTW. Scientific Programming in C, fall 2012 Susi Lehtola More features 29/58
Interfacing C with Fortran, cont d Although compiler-dependent interfacing has been around for a long time, the C interface has been only recently standardized in Fortran 2003. I will use the Fortran data types introduced in the 2003 standard in order to avoid defining the sizes manually. This has no effect on code portability, as if you don t have Fortran 2003 features you can just write a dummy ISO C BINDING module which defines the sizes of the datatypes in Fortran 90 code. Scientific Programming in C, fall 2012 Susi Lehtola More features 30/58
Interfacing C with Fortran, cont d In order to prevent unwanted mixed-language programming, the Fortran function names are usually suffixed with an underscore. However, this is dependent on the compiler: it might not be added it might be added two might be added You can adjust these with compiler flags, e.g. -fno-underscoring and -fsecond-underscore in gfortran. Scientific Programming in C, fall 2012 Susi Lehtola More features 31/58
Interfacing C with Fortran, cont d In order to prevent unwanted mixed-language programming, the Fortran function names are usually suffixed with an underscore. However, this is dependent on the compiler: it might not be added it might be added two might be added You can adjust these with compiler flags, e.g. -fno-underscoring and -fsecond-underscore in gfortran. Fortran 2003 added the BIND(C) attribute which eliminates the need to handle underscoring. Scientific Programming in C, fall 2012 Susi Lehtola More features 32/58
C to Fortran interface A simple example: using the Fortran intrinsic function nint(x), which returns the nearest integer to the floating point number x equivalent to ((int) round(x)) in C Fortran wrapper code wnint.f90 f u n c t i o n wnint ( x ) r e s u l t ( i ) use ISO C BINDING i m p l i c i t none r e a l (C DOUBLE), i n t e n t ( i n ) : : x i n t e g e r ( C INT ) : : i i=n i n t ( x ) end f u n c t i o n wnint Scientific Programming in C, fall 2012 Susi Lehtola More features 33/58
C to Fortran interface, cont d #i n c l u d e <s t d i o. h> #i n c l u d e < s t d l i b. h> / F o r t r a n f u n c t i o n / i n t w n i n t ( c o n s t double x ) ; i n t main ( i n t argc, char a r g v ) { double d ; i f ( a r g c!=2) { p r i n t f ( Usage : %s v a l u e \n, a r g v [ 0 ] ) ; r e t u r n 1 ; } d=a t o f ( a r g v [ 1 ] ) ; } p r i n t f ( %e rounded to t h e c l o s e s t i n t e g e r i s %i. \ n,\ d, w n i n t (&d ) ) ; r e t u r n 0 ; Note that you have to declare the prototypes for the Fortran functions you use in the C code. Scientific Programming in C, fall 2012 Susi Lehtola More features 34/58
C to Fortran interface using BIND(C) If you add bind(c) to the attributes of the Fortran function f u n c t i o n wnint ( x ) r e s u l t ( i ) b i n d ( c ) use ISO C BINDING i m p l i c i t none r e a l (C DOUBLE), i n t e n t ( i n ) : : x i n t e g e r ( C INT ) : : i i=n i n t ( x ) end f u n c t i o n wnint it will be available to C as / F o r t r a n f u n c t i o n / i n t wnint ( c o n s t double x ) ; and you would call it with p r i n t f ( %e rounded to t h e c l o s e s t i n t e g e r i s %i. \ n,\ d, wnint (&d ) ) ; Scientific Programming in C, fall 2012 Susi Lehtola More features 35/58
C to Fortran interface, compiling When you mix C with Fortran, you naturally have to use different compilers for the different parts of the program. Compile C part with gcc -c (and other flags) Compile Fortran part with gfortran -c (and other flags) Link module files together Scientific Programming in C, fall 2012 Susi Lehtola More features 36/58
C to Fortran interface, compile example Example: # Compile main program gcc g c n i n t. c # Compile F o r t r a n wrapper g f o r t r a n g c wnint. c # L i n k t h e s e t o g e t h e r gcc o n i n t. x n i n t. o wnint. o l g f o r t r a n Note that if you use gcc to perform the linking, you need to add -lgfortran so that the Fortran runtime libraries that are needed by wnint.o are linked in. You can also use gfortran to perform the linking, then you don t need the -lgfortran argument. $. / i n t. x 1.54 1.540000 e+00 rounded to the c l o s e s t i n t e g e r i s 2. $. / i n t. x 1. 2 1.200000 e+00 rounded to the c l o s e s t i n t e g e r i s 1. Scientific Programming in C, fall 2012 Susi Lehtola More features 37/58
C to Fortran interface, strings Unlike C strings, Fortran strings are not terminated. Instead, their size is always known since Fortran includes array metadata. Fortran functions with string arguments are appended with the length of the string. Scientific Programming in C, fall 2012 Susi Lehtola More features 38/58
C to Fortran interface, strings cont d For example, you would call the Fortran subroutine s u b r o u t i n e f p r i n t s t r ( s t r ) use i s o c b i n d i n g i m p l i c i t none c h a r a c t e r ( k i n d=c c h a r, l e n = ), i n t e n t ( i n ) : : s t r w r i t e (, (A) ) F o r t r a n code w r i t e (, (AAA) ), s t r, end s u b r o u t i n e f p r i n t s t r in C code as v o i d f p r i n t s t r ( c o n s t char, i n t l e n ) ; N.B. len is here not a pointer. Scientific Programming in C, fall 2012 Susi Lehtola More features 39/58
C to Fortran interface, strings cont d The analogous C code is #i n c l u d e <s t d i o. h> v o i d c p r i n t s t r ( c o n s t char s t r ) { p r i n t f ( C code \n ) ; p r i n t f ( \ %s \ \n, s t r ) ; } and the calling main program in C is #i n c l u d e < s t r i n g. h> v o i d c p r i n t s t r ( c o n s t char ) ; v o i d f p r i n t s t r ( c o n s t char, i n t l e n ) ; i n t main ( v o i d ) { char s t r [80]= This i s a t e s t s t r i n g. ; } c p r i n t s t r ( s t r ) ; f p r i n t s t r ( s t r, s t r l e n ( s t r ) ) ; r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola More features 40/58
C to Fortran interface, strings cont d... and the main program in Fortran is program t e s t use ISO C BINDING i m p l i c i t none c h a r a c t e r ( k i n d=c c h a r, l e n =80) : : s t r! Set s t r, use e x p l i c i t t y p e s t r=c c h a r This i s a t e s t s t r i n g.! P r i n t u s i n g F o r t r a n r o u t i n e. Remember t h a t you need! to remove t h e padded s p a c e s i n F o r t r a n c a l l f p r i n t s t r ( t r i m ( s t r ) )! P r i n t u s i n g C r o u t i n e, t e r m i n a t e s t r i n g c a l l c p r i n t s t r ( t r i m ( s t r ) // C NULL CHAR) end program t e s t Scientific Programming in C, fall 2012 Susi Lehtola More features 41/58
C to Fortran interface, strings example Running the programs gives $. / c t o f. x C code This i s a t e s t s t r i n g. F o r t r a n code This i s a t e s t s t r i n g. $. / f t o c. x F o r t r a n code This i s a t e s t s t r i n g. C code This i s a t e s t s t r i n g. Scientific Programming in C, fall 2012 Susi Lehtola More features 42/58
C to Fortran interface, vectors Let s begin with using a Fortran routine from C. s u b r o u t i n e f p r i n t a r r ( n, a r r ) use ISO C BINDING i m p l i c i t none i n t e g e r ( C INT ), i n t e n t ( i n ) : : n r e a l (C DOUBLE), i n t e n t ( i n ), dimension ( n ) : : a r r i n t e g e r ( C INT ) : : i w r i t e (, (A) ) F o r t r a n a r r a y do i =1,n w r i t e (, ( AF8. 3 ), advance= no ), a r r ( i ) end do w r i t e (, ) end s u b r o u t i n e f p r i n t a r r The routine prints out the elements of the vector it is given. Note that the array size needs to be given explicitly, since Fortran arrays contain metadata not available in the C version. Scientific Programming in C, fall 2012 Susi Lehtola More features 43/58
C to Fortran interface, vectors cont d The corresponding C code is #i n c l u d e <s t d i o. h> v o i d c p r i n t a r r ( c o n s t i n t N, c o n s t double a r r ) { i n t i ; p r i n t f ( C a r r a y \n ) ; f o r ( i =0; i < N; i ++) p r i n t f ( %8.3 f, i, a r r [ i ] ) ; p r i n t f ( \n ) ; } Scientific Programming in C, fall 2012 Susi Lehtola More features 44/58
C to Fortran interface, vectors cont d A Fortran test program program t e s t use ISO C BINDING i m p l i c i t none r e a l (C DOUBLE), dimension ( : ), a l l o c a t a b l e : : a r r i n t e g e r ( C INT ), parameter : : N=9 i n t e g e r ( C INT ) : : i a l l o c a t e ( a r r (N) ) do i =1,N a r r ( i )= i 1 end do c a l l f p r i n t a r r ( n, a r r ) c a l l c p r i n t a r r ( n, a r r ) d e a l l o c a t e ( a r r ) end program t e s t Scientific Programming in C, fall 2012 Susi Lehtola More features 45/58
C to Fortran interface, vectors cont d.. and the corresponding C test program #i n c l u d e < s t d l i b. h> v o i d c p r i n t a r r ( c o n s t i n t N, c o n s t double a r r ) ; v o i d f p r i n t a r r ( c o n s t i n t N, c o n s t double a r r ) ; i n t main ( v o i d ) { c o n s t i n t N=9; double a r r ; i n t i ; a r r=m a l l o c (N s i z e o f ( double ) ) ; f o r ( i =0; i <N; i ++) a r r [ i ]= i ; } c p r i n t a r r (&N, a r r ) ; f p r i n t a r r (&N, a r r ) ; f r e e ( a r r ) ; r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola More features 46/58
C to Fortran interface, vectors cont d Running the programs gives the expected result $. / c t o f. x C a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 F o r t r a n a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 $. / f t o c. x F o r t r a n a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 C a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 so the Fortran routine has correct access to the array allocated and initialized in C, and vice versa. Scientific Programming in C, fall 2012 Susi Lehtola More features 47/58
C to Fortran interface, matrices The same can be applied to multidimensional arrays. Scientific Programming in C, fall 2012 Susi Lehtola More features 48/58
C to Fortran interface, matrices The same can be applied to multidimensional arrays. Some points to take into account: in the Fortran interface, you cannot use arrays of pointers. The memory region must be continguous! can use static arrays or multidimensional arrays with the manual indexing or the multidimensional arrays allocated as mentioned at the beginning of this lecture indices in Fortran run from 1 to N, whereas in C they run from 0 to N-1 Fortran storage order is the opposite of C Scientific Programming in C, fall 2012 Susi Lehtola More features 49/58
C to Fortran interface, matrices cont d s u b r o u t i n e f p r i n t a r r (m, n, a r r ) use ISO C BINDING i m p l i c i t none i n t e g e r ( C INT ), i n t e n t ( i n ) : : m, n r e a l (C DOUBLE), i n t e n t ( i n ), dimension (m, n ) : : a r r i n t e g e r ( C INT ) : : i, j w r i t e (, (A) ) F o r t r a n a r r a y do i =1,m do j =1,n w r i t e (, ( AF8. 3 ), advance= no ), a r r ( i, j ) end do w r i t e (, ) end do end s u b r o u t i n e f p r i n t a r r Scientific Programming in C, fall 2012 Susi Lehtola More features 50/58
C to Fortran interface, matrices cont d #i n c l u d e <s t d i o. h> v o i d c p r i n t a r r ( c o n s t i n t M, c o n s t i n t N, \ c o n s t double a r r [ ] [ N ] ) { / Need to d e f i n e t h e l e n g t h o f t h e l a s t d i m e n s i o n ( s )! } Other o p t i o n would be to use a p o i n t e r and manual i n d e x i n g. / i n t i, j ; p r i n t f ( C a r r a y \n ) ; f o r ( i =0; i < M; i ++) { f o r ( j =0; j < N; j ++) p r i n t f ( %8.3 f, i, a r r [ i ] [ j ] ) ; p r i n t f ( \n ) ; } Scientific Programming in C, fall 2012 Susi Lehtola More features 51/58
C to Fortran interface, matrices cont d program t e s t use ISO C BINDING i m p l i c i t none r e a l (C DOUBLE), dimension ( :, : ), a l l o c a t a b l e : : a r r i n t e g e r ( C INT ), parameter : : M=3, N=4 i n t e g e r ( C INT ) : : i, j a l l o c a t e ( a r r (M,N) ) do i =1,M do j =1,N a r r ( i, j )=( i 1) N+j 1 end do end do c a l l f p r i n t a r r (m, n, a r r ) c a l l c p r i n t a r r (m, n, a r r ) d e a l l o c a t e ( a r r ) end program t e s t Scientific Programming in C, fall 2012 Susi Lehtola More features 52/58
C to Fortran interface, matrices cont d #i n c l u d e <s t d l i b. h> v o i d c p r i n t a r r ( c o n s t i n t M, c o n s t i n t N, c o n s t double a r r ) ; v o i d f p r i n t a r r ( c o n s t i n t M, c o n s t i n t N, double a r r ) ; i n t main ( v o i d ) { const i n t M=3, N=4; i n t i, j ; } double a r r ; a r r=m a l l o c (M s i z e o f ( double ) ) ; a r r [0]= m a l l o c (M N s i z e o f ( double ) ) ; f o r ( i =1; i<m; i ++) a r r [ i ]= a r r [0]+ i N; f o r ( i =0; i<m; i ++) f o r ( j =0; j<n; j ++) a r r [ i ] [ j ]= i N+j ; c p r i n t a r r (&M, &N, a r r [ 0 ] ) ; / Fortran function i s given the s t a r t of the array a r r i s h e r e t h e s t a r t o f t h e p o i n t e r a r r a y whereas a r r [ 0 ] i s t h e s t a r t o f t h e a c t u a l a r r a y, i f you use s t a t i c a l l o c a t i o n t h i s would be j u s t a r r / f p r i n t a r r (&M, &N, a r r [ 0 ] ) ; f r e e ( a r r [ 0 ] ) ; f r e e ( a r r ) ; r e t u r n 0 ; Scientific Programming in C, fall 2012 Susi Lehtola More features 53/58
C to Fortran interface, matrices cont d $. / c t o f. x C a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 9. 0 0 0 1 0.000 1 1.000 F o r t r a n a r r a y 0. 0 0 0 3. 0 0 0 6. 0 0 0 9. 0 0 0 1. 0 0 0 4. 0 0 0 7. 0 0 0 1 0. 0 00 2. 0 0 0 5. 0 0 0 8. 0 0 0 1 1. 0 00 $. / f t o c. x F o r t r a n a r r a y 0. 0 0 0 1. 0 0 0 2. 0 0 0 3. 0 0 0 4. 0 0 0 5. 0 0 0 6. 0 0 0 7. 0 0 0 8. 0 0 0 9. 0 0 0 1 0.000 1 1.000 C a r r a y 0. 0 0 0 4. 0 0 0 8. 0 0 0 1. 0 0 0 5. 0 0 0 9. 0 0 0 2. 0 0 0 6. 0 0 0 1 0.000 3. 0 0 0 7. 0 0 0 11.000 As you can see, the elements end up in the transpose ordering. If you use manual indexing in C, you can use the Fortran ordering in the C code as well. Scientific Programming in C, fall 2012 Susi Lehtola More features 54/58
C to Fortran interface, matrices cont d Fortran also has the intrinsic transpose function, which you can use to convert the indexing when you mix code. Scientific Programming in C, fall 2012 Susi Lehtola More features 55/58
C to Fortran interface, matrices cont d Fortran also has the intrinsic transpose function, which you can use to convert the indexing when you mix code. This will result in some computational overhead. If your matrices are very large, this is a thing you really want to avoid. Scientific Programming in C, fall 2012 Susi Lehtola More features 56/58
C to Fortran interface, matrices cont d Fortran also has the intrinsic transpose function, which you can use to convert the indexing when you mix code. This will result in some computational overhead. If your matrices are very large, this is a thing you really want to avoid.... but if the matrices are not very big, the overhead is probably acceptable wrt to the cleaner code. Scientific Programming in C, fall 2012 Susi Lehtola More features 57/58
Loop optimizations Remember that the memory ordering in C is row major, and column major in Fortran. When writing loops you should keep this in mind. double f ( s i z e t i, s i z e t j ) ; c o n s t s i z e t M=1000, N=200; double mat [M] [ N ] ; s i z e t i, j ; f o r ( j =0; j <N; j ++) f o r ( i =0; i <M; i ++) mat [ i ] [ j ]= f ( i, j ) ; Here the loops are in wrong order. Changing to the correct memory order is beneficial. Scientific Programming in C, fall 2012 Susi Lehtola More features 58/58