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.

4
  • 2
    Is there any particular reason why you insist on using macros instead of, say, functions? Commented Apr 13, 2012 at 11:38
  • Yes, because we are doing supercomputing and (in our case) functions cannot be optimized as good as "direct code". Commented Apr 13, 2012 at 11:44
  • 4
    `functions cannot be optimized as good as "direct code". ' I do supercomputing too, and this statement is just silly. Commented Apr 13, 2012 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... Commented Apr 13, 2012 at 12:48

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I had tried '#define d_dx(A,s) PASTE(s,d_dx(A))'. Why did that not work?
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.
gfortran docs say cpp is invoked in traditional mode. Maybe one of the two options discussed here will help: c-faq.com/cpp/oldpaste.html.
If so, use conditional compilation to choose the old versus new versions. #ifdef __STDC__ is a start.
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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.