quinlan@physics.utoronto.ca (Gerald Quinlan) (07/07/90)
I have a question about using the C preprocessor to perform macro substitutions in a Fortran program. The problem is the following. I have a short subroutine which adds two numbers (a,b) in extended precision, returning their sum (sum) and the error made in the addition (error). This routine gets called about 8 times in a heavily-used do loop in my program, so I thought I could speed things up by eliminating the subroutine call and doing the add in-line. I tried to get the preprocessor cpp to do the in-line substitution automatically for me, as shown below in the sample program adtest.F. --------------------------- adtest.F ---------------------------------- #define CALL_ADD(a,b,sum,error)\ dum=a+b \ if(abs(a).gt.abs(b)) then \ error=a-dum \ error=error+b \ else \ error=b-dum \ error=error+a \ endif \ sum=dum program adtest double precision dum,err,resid,rn,sum integer n sum=0.d0 resid=0.d0 do 10 n=1,500000 rn=sqrt(dble(n)) CALL_ADD(sum,rn,sum,err) resid=resid+err 10 continue sum=sum+resid write(6,*) 'addt:',sum,resid stop end When I run this through cpp (on a Sun) to get adtest.f I get the result shown below. --------------------------- adtest.f ---------------------------------- program adtest double precision dum,err,resid,rn,sum integer n sum=0.d0 resid=0.d0 do 10 n=1,500000 rn=sqrt(dble(n)) dum=sum+rn if(abs(sum).gt.abs(rn)) then err=sum-dum err=err+rn else err=rn-dum err=err+sum endif sum=dum resid=resid+err 10 continue sum=sum+resid write(6,*) 'addt:',sum,resid stop end Note how cpp has combined all the statements of the macro into one long line. I suppose this isn't a problem in C, where the statements end with ";" and more than one statement per line is allowed. But in Fortran this doesn't work; the compiler won't accept adtest.f. Does anyone know how to get around this? I've tried various tricks to get the macro inserted properly, but can't seem to find anything that works.
worley@compass.com (Dale Worley) (07/09/90)
quinlan@physics.utoronto.ca (Gerald Quinlan) writes: > I have a question about using the C preprocessor to perform macro > substitutions in a Fortran program. > #define CALL_ADD(a,b,sum,error)\ > dum=a+b \ > [etc.] > Note how cpp has combined all the statements of the macro into one long line. There is no way to get around this with CPP. The problem is that CPP macro definitions are exactly one line long. (CPP is line-oriented like Fortran, despite that C is not!) The backslashes at the ends of lines are really escape characters that mean "delete the newline that follows me". Since the deletion of the newline is in a (logical) processing pass before CPP's macro processing, it is impossible to get one outputed. Thus, it is impossible to have the output of a macro span more than one line. Oddly, a macro *call* is allowed to span more than one line. Dale Worley Compass, Inc. worley@compass.com -- It is easier to get forgiveness than permission.
ted@hasvcr.UUCP (Ted Powell) (07/11/90)
In article <1990Jul6.162153.17644@helios.physics.utoronto.ca> quinlan@physics.utoronto.ca (Gerald Quinlan) writes: >I have a question about using the C preprocessor to perform macro >substitutions in a Fortran program. ... [example omitted] >Note how cpp has combined all the statements of the macro into one long line. >I suppose this isn't a problem in C, where the statements end with ";" and >more than one statement per line is allowed. But in Fortran this doesn't >work; the compiler won't accept adtest.f. Does anyone know how to get >around this? I've tried various tricks to get the macro inserted properly, >but can't seem to find anything that works. Your problem is that you want to get characters into the macro expansion that cpp considers special. An unescaped newline terminates the macro definition, rather than being included in it, and consecutive spaces are reduced to a single space. Pick a couple of characters that do not otherwise occur in your source files, for example percent to represent newline and underscore to represent space. Then (assuming you are in a Unix environment; you'll have to use an intermediate file otherwise) pipe the output of cpp through: tr '_%' ' \012' ^note space This translates underscores into spaces and percent signs into newlines (\012 is interpreted by tr as a newline character). Note that some versions of the tr program require their arguments in a slightly different form--check your manual if necessary. Your macros now look something like: #define qqsv(a,b,c) line one\ %______line two\ %______line three\ %______last line ^column 1 The remainder of your program is of course unchanged, since actual spaces and newlines are unaffected by their trip through tr. All this takes much less time to do than to describe, of course. M4 is a nice language. I used a similar language called UMIST heavily for many years as a Fortran preprocessor, and as an MVTAB (multivariate contingency tabulator) preprocessor. But in your circumstances I think M4 is overkill. -- ted@hasvcr.wimsey.bc.ca ...!ubc-cs!van-bc!hasvcr!ted (Ted Powell)