我想在C ++代码中调用Fortran函数,所以我将一段C ++代码编写为fllow
:
#include <cstdio>
#include <math.h>
extern "C" {
double dcadre_(double(*f)(double*), double *a, double *b, double *aerr, double *rerr, double *error, int *ier);
}
double fun(double *x) {
return log(*x);
}
int main() {
int ier = 500;
double a = 0.0, b = 10.0, aerr = 0.01, rerr = 0.0001, error = 1.0;
printf("%f\n", dcadre_(fun, &a, &b, &aerr, &rerr, &error, &ier));
return 0;
}
这是fortran77代码:
REAL FUNCTION DCADRE(F,A,B,AERR,RERR,ERROR,IER)
implicit none
EXTERNAL F
DIMENSION T(10,10),R(10),AIT(10),DIF(10),RN(4),TS(2049)
DIMENSION IBEGS(30),BEGIN(30),FINIS(30),EST(30)
DIMENSION REGLSV(30)
LOGICAL H2CONV,AITKEN,RIGHT,REGLAR,REGLSV
REAL T,R,AIT,DIF,RN,TS,BEGIN,FINIS,EST,AITLOW
REAL H2TOL,AITTOL,LENGTH,JUMPTL,ZERO,P1,HALF,ONE
REAL TWO,FOUR,FOURP5,TEN,HUN,CADRE,ERROR,A,B
REAL AERR,RERR,STEPMN,STEPNM,STAGE,CUREST,FNSIZE
REAL PREVER,BEG,FBEG,END,FEND,STEP,ASTEP,TABS,HOVN
REAL FN,SUM,SUMABS,ABSI,VINT,TABTLM,ERGL,ERGOAL
REAL ERRA,ERRR,FEXTRP,ERRER,DIFF,SING,FEXTM1,ALG4O2
REAL H2NXT,SINGNX,SLOPE,FBEG2,ALPHA
REAL ERRET,H2TFEX,FI
REAL RVAL,F
integer*4 IBEGS,IER,ISTAGE,IBEG,IEND,L,N,LM1,N2,ISTEP,II,III,I,IST
*EP2,IT,NNLEFT
integer*4 MAXTS,MAXTBL,MXSTGE
DATA AITLOW,H2TOL,AITTOL,JUMPTL,MAXTS,MAXTBL,MXSTGE/1.1E0,.15E0, .
*1E0,.01E0,2049,10,30/
DATA RN(1),RN(2),RN(3),RN(4)/.7142005E0,.3466282E0,.843751E0, .126
*3305E0/
DATA ZERO,P1,HALF,ONE,TWO,FOUR,FOURP5,TEN,HUN/0.0E0,0.1E0,0.5E0, 1
*.0E0,2.0E0,4.0E0,4.5E0,10.0E0,100.0E0/
save MAXTS,MAXTBL,MXSTGE
ALG4O2=ALOG10(TWO)
CADRE=ZERO
ERROR=ZERO
CUREST=ZERO
VINT=ZERO
IER=0
LENGTH=ABS(B-A)
IF((LENGTH.EQ.ZERO))GO TO 215
IF((RERR.GT.P1.OR.RERR.LT.ZERO))GO TO 210
IF((AERR.EQ.ZERO.AND.(RERR+HUN).LE.HUN))GO TO 210
ERRR=RERR
ERRA=ABS(AERR)
STEPMN=(LENGTH/FLOAT(2**MXSTGE))
STEPNM=AMAX1(LENGTH,ABS(A),ABS(B))*TEN
STAGE=HALF
ISTAGE=1
FNSIZE=ZERO
PREVER=ZERO
REGLAR=.FALSE.
BEG=A
RVAL=BEG
FBEG=F(RVAL)*HALF
TS(1)=FBEG
IBEG=1
END=B
RVAL=END
FEND=F(RVAL)*HALF
TS(2)=FEND
IEND=2
5 RIGHT=.FALSE.
10 STEP=END - BEG
ASTEP=ABS(STEP)
IF((ASTEP.LT.STEPMN))GO TO 205
IF((STEPNM+ASTEP.EQ.STEPNM))GO TO 205
T(1,1)=FBEG + FEND
TABS=ABS(FBEG) + ABS(FEND)
L=1
N=1
H2CONV=.FALSE.
AITKEN=.FALSE.
15 LM1=L
L=L + 1
N2=N + N
FN=N2
ISTEP=(IEND - IBEG)/N
IF((ISTEP.GT.1))GO TO 25
II=IEND
IEND=IEND + N
IF((IEND.GT.MAXTS))GO TO 200
HOVN=STEP/FN
III=IEND
FI=ONE
DO 10011 I=1,N2,2
TS(III)=TS(II)
RVAL=END-FI*HOVN
TS(III-1)=F(RVAL)
FI=FI+TWO
III=III-2
II=II-1
10011 CONTINUE
10012 CONTINUE
ISTEP=2
25 ISTEP2=IBEG + ISTEP/2
SUM=ZERO
SUMABS=ZERO
DO 10021 I=ISTEP2,IEND,ISTEP
SUM=SUM + TS(I)
SUMABS=SUMABS + ABS(TS(I))
10021 CONTINUE
10022 CONTINUE
T(L,1)=T(L-1,1)*HALF+SUM/FN
TABS=TABS*HALF+SUMABS/FN
ABSI=ASTEP*TABS
N=N2
IT=1
VINT=STEP*T(L,1)
TABTLM=TABS*TEN
FNSIZE=AMAX1(FNSIZE,ABS(T(L,1)))
ERGL=ASTEP*FNSIZE*TEN
ERGOAL=STAGE*AMAX1(ERRA,ERRR*ABS(CUREST+VINT))
FEXTRP=ONE
DO 10031 I=1,LM1
FEXTRP=FEXTRP*FOUR
T(I,L)=T(L,I) - T(L-1,I)
T(L,I+1)=T(L,I) + T(I,L)/(FEXTRP-ONE)
10031 CONTINUE
10032 CONTINUE
ERRER=ASTEP*ABS(T(1,L))
IF((L.GT.2))GO TO 40
IF((TABS+P1*ABS(T(1,2)).EQ.TABS))GO TO 135
GO TO 15
40 DO 45 I=2,LM1
DIFF=ZERO
IF((TABTLM+ABS(T(I-1,L)).NE.TABTLM))DIFF=T(I-1,LM1)/T(I-1,L)
T(I-1,LM1)=DIFF
45 CONTINUE
IF((ABS(FOUR-T(1,LM1)).LE.H2TOL))GO TO 60
IF((T(1,LM1).EQ.ZERO))GO TO 55
IF((ABS(TWO-ABS(T(1,LM1))).LT.JUMPTL))GO TO 130
IF((L.EQ.3))GO TO 15
H2CONV=.FALSE.
IF((ABS((T(1,LM1)-T(1,L-2))/T(1,LM1)).LE.AITTOL))GO TO 75
50 IF(REGLAR) GO TO 55
IF((L.EQ.4))GO TO 15
55 IF(ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL) GO TO 175
GO TO 145
60 IF(H2CONV) GO TO 65
AITKEN=.FALSE.
H2CONV=.TRUE.
65 FEXTRP=FOUR
70 IT=IT + 1
VINT=STEP*T(L,IT)
ERRER=ABS(STEP/(FEXTRP-ONE)*T(IT-1,L))
IF((ERRER.LE.ERGOAL))GO TO 160
IF((ERGL+ERRER.EQ.ERGL))GO TO 160
IF((IT.EQ.LM1))GO TO 125
IF((T(IT,LM1).EQ.ZERO))GO TO 70
IF((T(IT,LM1).LE.FEXTRP))GO TO 125
IF((ABS(T(IT,LM1)/FOUR-FEXTRP)/FEXTRP.LT.AITTOL))FEXTRP=FEXTRP*FOU
*R
GO TO 70
75 IF(T(1,LM1).LT.AITLOW) GO TO 175
IF((AITKEN))GO TO 80
H2CONV=.FALSE.
AITKEN=.TRUE.
80 FEXTRP=T(L-2,LM1)
IF((FEXTRP.GT.FOURP5))GO TO 65
IF((FEXTRP.LT.AITLOW))GO TO 175
IF((ABS(FEXTRP-T(L-3,LM1))/T(1,LM1).GT.H2TOL))GO TO 175
SING=FEXTRP
FEXTM1=ONE/(FEXTRP - ONE)
AIT(1)=ZERO
DO 85 I=2,L
AIT(I)=T(I,1) + (T(I,1)-T(I-1,1))*FEXTM1
R(I)=T(1,I-1)
DIF(I)=AIT(I) - AIT(I-1)
85 CONTINUE
IT=2
90 VINT=STEP*AIT(L)
ERRER=ERRER*FEXTM1
IF((ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL))GO TO 95
ALPHA=ALOG10(SING)/ALG4O2 - ONE
IER=MAX0(IER,65)
GO TO 160
95 IT=IT + 1
IF((IT.EQ.LM1))GO TO 125
IF((IT.GT.3))GO TO 100
H2NXT=FOUR
SINGNX=SING+SING
100 IF(H2NXT.LT.SINGNX) GO TO 105
FEXTRP=SINGNX
SINGNX=SINGNX+SINGNX
GO TO 110
105 FEXTRP=H2NXT
H2NXT=FOUR*H2NXT
110 DO 115 I=IT,LM1
R(I+1)=ZERO
IF((TABTLM+ABS(DIF(I+1)).NE.TABTLM))R(I+1)=DIF(I)/DIF(I+1)
115 CONTINUE
H2TFEX=-H2TOL*FEXTRP
IF((R(L)-FEXTRP.LT.H2TFEX))GO TO 125
IF((R(L-1)-FEXTRP.LT.H2TFEX))GO TO 125
ERRER=ASTEP*ABS(DIF(L))
FEXTM1=ONE/(FEXTRP - ONE)
DO 120 I=IT,L
AIT(I)=AIT(I) + DIF(I)*FEXTM1
DIF(I)=AIT(I) - AIT(I-1)
120 CONTINUE
GO TO 90
125 FEXTRP=AMAX1(PREVER/ERRER,AITLOW)
PREVER=ERRER
IF((L.LT.5))GO TO 15
IF((L-IT.GT.2.AND.ISTAGE.LT.MXSTGE))GO TO 170
ERRET=ERRER/(FEXTRP**(MAXTBL-L))
IF((ERRET.GT.ERGOAL.AND.(ERGL+ERRET).NE.ERGL))GO TO 170
GO TO 15
130 IF(ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL) GO TO 170
DIFF=ABS(T(1,L))*(FN+FN)
GO TO 160
135 SLOPE=(FEND-FBEG)*TWO
FBEG2=FBEG+FBEG
DO 140 I=1,4
RVAL=BEG+RN(I)*STEP
DIFF=ABS(F(RVAL) - FBEG2-RN(I)*SLOPE)
IF((TABTLM+DIFF.NE.TABTLM))GO TO 155
140 CONTINUE
GO TO 160
145 SLOPE=(FEND-FBEG)*TWO
FBEG2=FBEG+FBEG
I=1
150 RVAL=BEG+RN(I)*STEP
DIFF=ABS(F(RVAL) - FBEG2-RN(I)*SLOPE)
155 ERRER=AMAX1(ERRER,ASTEP*DIFF)
IF((ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL))GO TO 175
I=I+1
IF((I.LE.4))GO TO 150
IER=66
160 CADRE=CADRE + VINT
ERROR=ERROR + ERRER
IF((RIGHT))GO TO 165
ISTAGE=ISTAGE - 1
IF((ISTAGE.EQ.0))GO TO 220
REGLAR=REGLSV(ISTAGE)
BEG=BEGIN(ISTAGE)
END=FINIS(ISTAGE)
CUREST=CUREST - EST(ISTAGE+1) + VINT
IEND=IBEG - 1
FEND=TS(IEND)
IBEG=IBEGS(ISTAGE)
GO TO 180
165 CUREST=CUREST + VINT
STAGE=STAGE+STAGE
IEND=IBEG
IBEG=IBEGS(ISTAGE)
END=BEG
BEG=BEGIN(ISTAGE)
FEND=FBEG
FBEG=TS(IBEG)
GO TO 5
170 REGLAR=.TRUE.
175 IF(ISTAGE.EQ.MXSTGE) GO TO 205
IF((RIGHT))GO TO 185
REGLSV(ISTAGE+1)=REGLAR
BEGIN(ISTAGE)=BEG
IBEGS(ISTAGE)=IBEG
STAGE=STAGE*HALF
180 RIGHT=.TRUE.
BEG=(BEG+END)*HALF
IBEG=(IBEG+IEND)/2
TS(IBEG)=TS(IBEG)*HALF
FBEG=TS(IBEG)
GO TO 10
185 NNLEFT=IBEG - IBEGS(ISTAGE)
IF((IEND+NNLEFT.GE.MAXTS))GO TO 200
III=IBEGS(ISTAGE)
II=IEND
DO 190 I=III,IBEG
II=II + 1
TS(II)=TS(I)
190 CONTINUE
DO 195 I=IBEG,II
TS(III)=TS(I)
III=III + 1
195 CONTINUE
IEND=IEND + 1
IBEG=IEND - NNLEFT
FEND=FBEG
FBEG=TS(IBEG)
FINIS(ISTAGE)=END
END=BEG
BEG=BEGIN(ISTAGE)
BEGIN(ISTAGE)=END
REGLSV(ISTAGE)=REGLAR
ISTAGE=ISTAGE + 1
REGLAR=REGLSV(ISTAGE)
EST(ISTAGE)=VINT
CUREST=CUREST + EST(ISTAGE)
GO TO 5
200 IER=131
GO TO 215
205 IER=132
GO TO 215
210 IER=133
215 CADRE=CUREST + VINT
220 DCADRE=CADRE
9000 CONTINUE
9005 RETURN
END
然后我编译了它们:
gfortran -c DCADRE.f
g++ -c test.cc
g++ -o test test.o DCADRE.o
发生了问题:
DCADRE.o: In function `dcadre_':
DCADRE.f:(.text+0x1ac): undefined reference to `_gfortran_pow_i4_i4'
collect2: error: ld returned 1 exit status
也许我忘了链接一些Fortran库,但我不知道如何修复它。