0

I am stuck with the following problem:

I have the two following correct working macros (expanding to Fortran90 code):

#define ld_dx(A)   (  (A(ixp1)-A(ix  ))/(dx)  )
#define rd_dx(A)   (  (A(ix  )-A(ixm1))/(dx)  )

(Note: these macros depend on the following additional macros:

#define ix    2:nx-1
#define ixp1  1+ix+1
#define ixm1 -1+ix-1

And they depend also the declarations:

integer, parameter :: nx = 100, dx = 1

)

In my code I can use these macros by a call as for example

X = X + ld_dx(Y)

or:

X = X + rd_dx(Y)

Now I would like to be able to call ld_dx(A) by writing d_dx(A,l) instead and rd_dx(A) by writing d_dx(A,r). The example would therefore look like this:

X = X + d_dx(Y,l)

or

X = X + d_dx(Y,r)

=> I am looking for a CPP macro that can provide this syntactic sugar (to get as close as possible to the mathematical notation). <=

The most straightforward thing to do would be:

#define d_dx(A,s)  s ## d_dx(A)

Unfortunately this does not work. CPP transforms

d_dx(Y,l)

into:

l ## Y)

I tried many things by studying the other CPP concatenation related questions, but I could not figure it out. Thank you very much in advance for some help!

Sam

PS: Note it would also be fine for me to rename the macros 'ld_dx(A)' and 'rd_dx(A)' into 'dl_dx(A)' and 'dr_dx(A)' This regarding, the most straightforward thing to do would be:

#define d_dx(A,s)  d ## s ## _dx(A)

Unfortunately this does not work neither: CPP transforms

d_dx(Y,l)

into:

d ## l ## _dx(Y) 
  1

Error: Expected a right parenthesis in expression at (1)

I.e. the concatenation is simply not performed.

Sam
  • 27
  • 6
  • 2
    Is there any particular reason why you insist on using macros instead of, say, _functions_? – pmcs Apr 13 '12 at 11:38
  • Yes, because we are doing supercomputing and (in our case) functions cannot be optimized as good as "direct code". – Sam Apr 13 '12 at 11:44
  • 4
    `functions cannot be optimized as good as "direct code". ' I do supercomputing too, and this statement is just silly. – Jonathan Dursi Apr 13 '12 at 12:40
  • Well, I admit it is not well formulated my statement. I simply did not want to discuss this issue, so I put a quick approximate explanation. Nevertheless, we have our reasons to do what we do... – Sam Apr 13 '12 at 12:48

2 Answers2

2
#define PASTE(x,y) x##y
#define d_dx(A,s) PASTE(s,d_dx)(A)

Token pasting (## operator) and stringizing (# operator) suppress substitution of adjoining arguments, so you have to do it in two steps.

fizzer
  • 13,551
  • 9
  • 39
  • 61
  • I had tried '#define d_dx(A,s) PASTE(s,d_dx(A))'. Why did that not work? – Sam Apr 13 '12 at 12:39
  • This solution works fine with the IMB XL compiler and with the intel compiler. Unfortunately, I now had to find out that this solution, however, does not work with the c-preprocessor called by gfortran (I tried: gcc version 4.6.2 (GCC), gcc version 4.4.4 (GCC), gcc version 4.1.2 20070115 (SUSE Linux)). The problem remains the same as described above in the "PS": the actual concatenation is simply not performed. We are aiming for code working with any common compiler. I would be very grateful, if we could find a solution that works with the gcc compiler too. Thank you very much in advance. – Sam Apr 17 '12 at 09:16
  • gfortran docs say cpp is invoked in traditional mode. Maybe one of the two options discussed here will help: http://c-faq.com/cpp/oldpaste.html. – fizzer Apr 17 '12 at 12:36
  • If so, use conditional compilation to choose the old versus new versions. `#ifdef __STDC__` is a start. – fizzer Apr 17 '12 at 12:38
0

Try without spaces. Some preprocessors ignore spaces on either side of the ##, others do not.

#define d_dx(A,s)  d##s##_dx(A)
cup
  • 11
  • 1