C C THIS SET OF PROGRAM AND SUBROUTINE UNITS IS TO SUPPORT C C 'AN OPTIMIZED MASS STORAGE FFT', BY DONALD FRASER C C REVISION DATE: JULY 1978 (MINOR REV JUNE 79). C C THE SET INCLUDES A UNIVERSAL TEST DRIVER PROGRAM, WHICH SIMULATES C MASS STORE THROUGH A FORTRAN ARRAY, SAMPLE PROGRAMS AND I/O C SUBROUTINES FOR CONTROL DATA 6000 AND CYBER COMPUTERS AND FOR C DEC PDP 11 MINICOMPUTERS. C C I/O SUBROUTINES FOR OTHER SYSTEMS SHOULD BE EASILY CONSTRUCTED C FROM THE EXAMPLES AND WITH REFERENCE TO THE FORMAL PAPER. C BUT CARE SHOULD BE TAKEN WITH SOME FUSSY COMPILERS SINCE FFT C SUBROUTINES ASSIGN EITHER TYPE REAL OR TYPE COMPLEX TO THE SAME C ARRAY AS IT IS PASSED AS A FORMAL PARAMETER. NOTE THAT COMPLEX C DATA IS ASSUMED TO BE STORED REAL/IMAG/REAL/IMAG... IN BOTH C MASS STORE AND CORE STORE. C C THE PROGRAM UNITS APPEAR IN THE FOLLOWING ORDER: C C FIRST, THE FFT SUBROUTINE SET: C 1 RMFFT OPTIMIZED MASS STORAGE FFT (REAL DATA OR REAL RESULT) C 2 CMFFT CALLED BY 1, OR MASS STORAGE FFT (ALL COMPLEX DATA) C 3 MFCOMP IN-CORE FFT C 4 MFSORT MASS STORE SORTING C 5 MFREV IN-CORE SORTING OR WHOLE BLOCK SORTING C 6 MFLOAD LOADING/UNLOADING CORE STORE C 7 MFINDX BLOCK INDEXING ALGORITHM (VIRTUAL PERMUTATION) C 8 MFSUM MEXA() EXPONENT SUMMATIONS C 9 MFRCMP REAL-COMPLEX UNSCRAMBLING/SCRAMBLING C 10 MFRLOD LOADING/UNLOADING CORE STORE FOR MFRCMP C 11 MFPAR HELPER ROUTINE (NOT ESSENTIAL, BUT RECOMMENDED) C 12 DMPERM MASS STORE DIMENSION SHIFTING (BONUS SUBROUTINE) C C THEN, TEST PROGRAMS AND SAMPLE I/O SUBROUTINES C C 13 UNIVERSAL TEST PROGRAM (SIMULATED MASS STORE, NEEDS 14 TO 17 ALSO) C 14 RANMF RANDOM NUMBER GENERATOR C 15 NAIVE DISCRETE FOURIER TRANSFORM COMPUTED NAIVELY C 16 MFREAD DUMMY I/O ROUTINE USING SIMULATED MASS STORE C 17 MFWRIT AS ABOVE C C 18 CYBER MASS STORE SAMPLE PROGRAM C 19 MFREAD/MFWRIT CYBER MASS STORE I/O ROUTINE C C 20 CYBER EXTENDED CORE/LCM SAMPLE PROGRAM C 21 MFREAD/MFWRIT CYBER EXTENDED CORE/LCM I/O ROUTINES C C 22 PDP 11 MASS STORE SAMPLE PROGRAM C 23 MFREAD PDP 11 STANDARD FORTRAN MASS STORE I/O ROUTINES C 24 MFWRIT AS ABOVE C C 25 PDP 11 FAST MACRO I/O SAMPLE PROGRAM (NEEDS MACRO OPEN SUBRTN) C 26 MFREAD/MFWRIT PDP 11 FAST MACRO I/O ROUTINE FOR RSX11M/RT11. C END SUBROUTINE RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C C REAL-TO-COMPLEX FFT (OR VICE-VERSA) OF MULTI-DIMENSD MASS STORE ARRAY C (FRASER, ACM TOMS - 1978/79, AND J.ACM, V.23,N.2, APRIL 76, PP. 298-3 C MASS STORE ARRAY IS EITHER REAL OR COMPLEX DATA (SEE NOTE BELOW) C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C C MEXA(J) LIST OF DIMENSION SIZE EXPONS (BASE 2), ADJACENT VARIABLES FIR C NDIM IS NUMBER OF EXPONENTS IN LIST AND THUS THE NUMBER OF DIMENSIONS C SUM TO NDIM OF MEXA(J) = M, WHERE 2**M IS EFFECT SIZE OF MASS STORE A C THUS, 2**M PACKED REAL VALUES, C OR, 2**M COMPLEX VALUES, IF COMPLEX RESULT WITH IPAK=1 (SEE BELO C RMFFT ALWAYS REVERSES DIMENSION ORDER AND MEXA LIST (TRANSPOSED, IF 2 C C ISGN GIVES SIGN OF COMPLEX EXPONENT OF TRANSFORM (+ OR -), AND C IDIR DETERMINES DIRECTION OF TRANSFORM, THUS: C IDIR=-1, REAL-TO-COMPLEX C IDIR=+1, COMPLEX-TO-REAL C SCAL IS REAL MULTIPLIER OF RESULT (EG. SET SCAL=1. FWD, 1./2**M INV) C C BUFA IS CORE STORE WORKING ARRAY BASE ADDRESS (SEE NOTE ABOVE) C IBEX, ICEX ARE BLOCK AND CORE SIZE EXPONENTS, THUS C 2**IBEX IS NUMBER OF REAL ELEMENTS IN MASS STORE BLOCK C 2**ICEX IS NUMBER OF REAL ELEMENTS IN CORE STORE BUFA C C IPAK IS ARRAY PACKING DETERMINATOR, THUS: C IPAK=+1 EXPANDS COMPLEX ARRAY TO FULL REDUNDANCY (SAME AS SUBRTN CMFF C IPAK=0 COMPUTES COMPLEX ARRAY OF JUST OVER HALF SIZE (COMMON METHOD) C IPAK=-1 HOLDS COMPLEX ARRAY AT EXACTLY HALF SIZE (2**(M-1) CMPLX ELMT C C MASS STORE ARRAY MUST BE OPEN FOR ACCESS BY USER SUBRTNS MFREAD/MFWRIT C EG. SUBRTN MFREAD(BUFA,NB,JB) AND MFWRIT(BUFA,NB,JB) TRANSFER ONE C BLOCK, INDEX JB, BETWEEN MASS STORE AND CORE STORE BUFA, NB REALS C (1.LE.JB.LE.2**(M-IBEX) IF REAL, OR 2**(M-IBEX+1) IF CMPLX AND IPAK=1 C COMPLEX BUFA(1) INTEGER B,MEXA(1) C MH=MFSUM(MEXA,NDIM,99)-1 B=IBEX-1 IF(IDIR.GT.0)GO TO 10 C C BELOW, REAL-TO-COMPLEX TRANSFORM MEXA(1)=MEXA(1)-1 CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) CALL MFRCMP (MEXA,NDIM,ISGN,IDIR,IPAK, BUFA,B,MH) MEXA(NDIM)=MEXA(NDIM)+1 RETURN C C BELOW, COMPLEX-TO-REAL TRANSFORM 10 MEXA(NDIM)=MEXA(NDIM)-1 CALL MFRCMP (MEXA,NDIM,ISGN,IDIR,IPAK, BUFA,B,MH) CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) MEXA(1)=MEXA(1)+1 RETURN C END SUBROUTINE CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C C COMPLEX FFT OF MULTI-DIMENSD MASS STORE ARRAY, CALLED BY USER OR RMFFT C FOR COMMENTS, SEE SUBRTN RMFFT; ARGUMNTS HAVE SAME MEANING EXCEPT FOR C IDIR=+1 OR -1, ARRAY ALWAYS COMPLEX, DIMENSION ORDER REVERSED C WHILE IDIR=0, DIMENSION ORDER (AND MEXA LIST) ARE NOT REVERSED C COMPLEX BUFA(1) INTEGER B,C,MEXA(1) DATA LSET/1/,LREAD/1/,LWRIT/2/ C M=MFSUM(MEXA,NDIM,99) MREAL=M+1 B=IBEX-1 C=ICEX-1 NC=2**C IPAS=0 MPAS=M-C NPAS=C-B C MOST EFFICIENT USE OF CORE STORE - TRIES TO DO C-B PASSES PER LOAD IDUM=MFINDX(LSET,B,M,M,NPAS) C DUMMY CALL TO MFINDX TO SPECIFY VIRTUAL (B.'S'.M)**(C-B) PERMUTATION C C FIRST, PIECE-MEAL ATTACK ON FFT COMPUTATION FOLLOWS 10 IF(MPAS.LE.0) GO TO 40 IF(MPAS.LT.NPAS)NPAS=MPAS 20 CALL MFLOAD(LREAD,BUFA,IBEX,ICEX,IFLG) C LOAD CORE WORKING SPACE WITH 2**(C-B) BLOCKS ACCORDING TO MFINDX IF(IFLG.LT.0) GO TO 30 CALL MFCOMP (MEXA,NDIM,ISGN, BUFA,B,C,M, NPAS,IPAS) C DO MODIFIED IN-CORE FFT, REQUIRING NPAS PASSES STARTING WITH IPAS CALL MFLOAD(LWRIT,BUFA,IBEX,ICEX,IFLG) C UNLOAD CORE AREA, WRITING BLOCKS BACK IN-PLACE TO MASS STORE GO TO 20 30 IPAS=IPAS+NPAS MPAS=MPAS-NPAS GO TO 10 C END OF FIRST PART C C SPECIFY BLOCKS TO BE READ IN NEXT PART IN TRUE ORDER (NO PERM) 40 IDUM=MFINDX(LSET,B,M,M,0) C FINAL, CONCLUDING ATTACK ON FFT COMPUTATION FOLLOWS 50 CALL MFLOAD(LREAD,BUFA,IBEX,ICEX,IFLG) IF(IFLG.LT.0)GO TO 80 CALL MFCOMP (MEXA,NDIM,ISGN, BUFA,C,C,M, C,IPAS) C DO FINAL, C-PASS IN-CORE FFT OF EACH CORE-LOAD IF(SCAL.EQ.1.)GO TO 70 DO 60 J=1,NC 60 BUFA(J)=BUFA(J)*SCAL 70 CALL MFLOAD(LWRIT,BUFA,IBEX,ICEX,IFLG) GO TO 50 C C BELOW, SORT ARRAY (FULL BIT-REVERSAL AND DIMEN REVERSAL IF IDIR.NE.0) 80 IF(IDIR.EQ.0)GO TO 90 CALL MFSORT(BUFA,IBEX,ICEX,1,MREAL,MREAL) M=MFSUM(MEXA,NDIM,-1) C DO FULL BIT-REVERSAL OF M BITS (AND REVERSE MEXA LIST) RETURN C C BELOW, REVERSE BITS OF EACH DIMEN SEPARATELY (NO DIMEN REVERSAL) 90 IH=1 DO 100 J=1,NDIM IG=IH IH=IH+MEXA(J) 100 CALL MFSORT(BUFA,IBEX,ICEX,IG,IH,MREAL) RETURN C END SUBROUTINE MFCOMP (MEXA,NDIM,ISGN, BUFA,B,C,M, NPAS,IPAS) C C MODIFIED, IN-CORE FFT OF 2**C ELEMENTS, NPAS PASSES STARTING WITH IPAS C MEXA, NDIM, ISGN ,BUFA AND M HAVE SAME MEANING AS IN RMFFT COMMENTS C B,C EQUIVALENT TO IBEX,ICEX EXCEPT HERE REFER TO NUM COMPLEX ELMTS C (2**C CMPLX ELMTS IN CORE STORE BUFA, IN BLOCKS OF 2**B CMPLX ELMTS) C C FFT W PHASE FACTOR COMPUTED RECURSIVELY EXCEPT ON BLOCK BOUNDS C MULTIDIMEN FFT ACHIEVED BY REPEATING W SEQUENCES C INTEGER B,C,SPAN,STEP,MEXA(1) COMPLEX TEMP,W,D,BUFA(1) DATA LINDX/0/,LREST/4/ C DATA PI/3.141592653589793/ PIMOD=PI*2.0**(1-M) IF(ISGN.LT.0)PIMOD=-PIMOD NC=2**C C C BELOW, NPAS COMPUTATION PASSES WHILE DATA IN-CORE DO 50 JPAS=1,NPAS KPAS=IPAS+JPAS-1 C KPAS IS GLOBAL COMPUTING PASS NUMBER (JPAS-1 IS LOCAL) KDIFF=M-MFSUM(MEXA,NDIM,KPAS) KPEFF=KPAS+KDIFF C KPEFF IS EFFECTIVE GLOBAL PASS FOR MULTIDIMEN. FFT W GENERATION D=CEXP(CMPLX(0.,PIMOD*2.0**KPEFF)) C D IS USED FOR RECURSIVE MODIFICATION OF W PHASE FACTOR C ITEM=C-JPAS SPAN=2**ITEM STEP=2*SPAN C SPAN SEPARATES VALUES IN FFT KERNEL, STEP TO NEXT PAIR, SAME W C IF(B.LT.ITEM)ITEM=B NB=2**ITEM IF(ITEM.GT.KDIFF)ITEM=KDIFF NRPT=2**ITEM C NRPT COUNTS REPETITION OF W FOR MULTIDIMEN. FFT C IMOD=2**(M-B-KPAS-1) IF(IMOD.LE.1)GO TO 20 IDUM=MFINDX(LREST,0,0,0,0) MEXP=KPEFF ITEM=KDIFF-B IF(ITEM.GT.0)GO TO 10 MEXP=B+KPAS ITEM=0 10 NCLR=2**ITEM PIMOD2=PIMOD*2.0**MEXP C IMOD AND NCLR ARE USED TO COMPUTE W WITHOUT EXCEEDING SMALL INTEGER C C BELOW, START OF ONE PASS THROUGH CORE, NOTING BLOCK BOUNDARIES 20 DO 50 I1=1,SPAN,NB W=(1.,0.) IF(IMOD.LE.1)GO TO 30 INDWM=MOD(MFINDX(LINDX,0,0,0,0)-1,IMOD)/NCLR ANDWM=INDWM W=CEXP(CMPLX(0.,PIMOD2*ANDWM)) C NEW W COMPUTED DIRECTLY AT BEGINNING OF NEW BLOCK AREA C C BELOW, COMPUTATIONS WITHIN EACH BLOCK OF 2**B CMPLX ELMTS 30 DO 50 I2=1,NB,NRPT C C BELOW, REPETITION OF SAME W DUE TO MULTIDIMEN FFT DO 40 I3=1,NRPT I4=I1+I2+I3-2 C C BELOW, STEPPING THOUGH INDICES HAVING SAME W IN ONE DIMEN FFT DO 40 J=I4,NC,STEP K=J+SPAN TEMP=(BUFA(J)-BUFA(K))*W BUFA(J)=BUFA(J)+BUFA(K) 40 BUFA(K)=TEMP C FFT 2-POINT KERNEL ARITHMETIC (ALGORITHM BIT-REVERSAL FOLLOWS COMPUT) C W=W*D C RECURSIVE MODIFICATION OF W WITHIN BLOCK BOUNDARIES 50 CONTINUE RETURN C END SUBROUTINE MFSORT(BUFA,IBEX,ICEX,IG,IH,M) C C BIT-REVERSED PERMUTATION (IG.'R'.IH) OF MASS STORE REAL ARRAY C REVERSES IH-IG BITS IN INDEX (M-1,...,IH-1,...,IG,...,0) C NOTE THAT THIS IS MORE GENERAL THAN THE FULL M-BIT REVERSAL C OF REFERENCE (FRASER, J.ACM, V.23, N.2, APR. 76, P. 306), C BUT ALGORITHM IS LOGICALLY THE SAME, WITH ALTERED BIT LIMITS. C BUFA,IBEX,ICEX AND M HAVE SAME MEANING AS IN COMMENTS IN RMFFT C (BLOCKS 2**IBEX, CORE BUFA 2**ICEX, TOTAL 2**M, ALL REAL) C REAL BUFA(1) DATA LSET/1/,LPERM/2/,LREAD/1/,LWRIT/2/ C IDUM=MFINDX(LSET,IBEX,M,M,0) C DUMMY CALL TO INITIALISE MFINDX (INITIALLY UNPERMUTED ARRAY) IF(IH-IG.LE.1)RETURN IF(IG.GE.IBEX)GO TO 50 IF(IH.LE.ICEX)GO TO 60 C CHECK FOR SPECIAL CASES, REQUIRING SIMPLER TREATMENT C C BELOW, MIXED PERMUTATION OF BOTH ELEMENTS AND BLOCKS IPAS=0 NPAS=ICEX-IBEX C MOST EFFIENT USE OF CORE STORE - TRIES TO DO ICEX-IBEX PASSES PER LOAD MPAS=IH-IBEX IF(IBEX-IG.LT.MPAS)MPAS=IBEX-IG C C BELOW, FIRST VIRTUAL 'S' PERMUTATIONS 10 IF(MPAS.LE.0)GO TO 40 IF(MPAS.LT.NPAS) NPAS=MPAS IGCOR=IG+IPAS IF((IGCOR.GT.IBEX-1).AND.(IGCOR.GT.IBEX+NPAS-1))GO TO 30 IF((IPAS.EQ.0).AND.(IGCOR.GT.IBEX+NPAS-1))GO TO 30 C BYPASS UNNECESSARY CORE LOAD IF TRIVIAL CASES IDUM=MFINDX(LPERM,IBEX,IH,M,NPAS) C DUMMY CALL TO MFINDX TO SPECIFY VIRTUAL (IBEX.S.IH)**NPAS PERM C C BELOW, LOAD CORE ACCORDING TO VIRTUAL PERMUTATION AND PERM ELMTS 20 CALL MFLOAD(LREAD,BUFA,IBEX,ICEX,IFLG) IF(IFLG.LT.0)GO TO 30 IF(IPAS.NE.0) CALL MFREV(BUFA,IGCOR,IBEX,ICEX,-1) CALL MFREV(BUFA,IGCOR,IBEX+NPAS,ICEX,-1) C CARRY OUT IN-CORE, SYMMETRIC R PERMS. (ONE ONLY ON FIRST PASS) CALL MFLOAD(LWRIT,BUFA,IBEX,ICEX,IFLG) C UNLOAD CORE AREA, WRITING BLOCKS BACK IN-PLACE TO MASS STORE GO TO 20 C 30 IPAS=IPAS+NPAS MPAS=MPAS-NPAS GO TO 10 C END OF FIRST PART C C BELOW, FINAL 'R' PERM. OF BLOCKS IN MASS STORE, IF (IH-2*IBEX+IG).GT.1 40 CALL MFREV(BUFA,0,IH-2*IBEX+IG,M-IBEX,IBEX) RETURN C C BELOW, PERMUTATION OF BLOCKS ONLY REQUIRED 50 CALL MFREV(BUFA,IG-IBEX,IH-IBEX,M-IBEX,IBEX) RETURN C C BELOW, PERMUTATION OF ELEMENTS IN CORE ONLY REQUIRED 60 CALL MFLOAD(LREAD,BUFA,IBEX,ICEX,IFLG) IF(IFLG.LT.0)RETURN CALL MFREV(BUFA,IG,IH,ICEX,-1) CALL MFLOAD(LWRIT,BUFA,IBEX,ICEX,IFLG) GO TO 60 C END SUBROUTINE MFREV(BUFA,IG,IH,M,IBEX) C C BIT-REVERSED PERMUTATION OF RANDOMLY ADDRESSABLE ELEMENTS C REVERSES IH-IG BITS IN INDEX (M-1,...,IH-1,...,IG,...,0) C (GENERAL PERM IG.'R'.IH, FRASER, J.ACM, V.23, N.2, APR 1976, P. 300) C IF IBEX.LT.0, SORTS 2**M REAL ELMTS IN CORE BUFA, C IF IBEX.GE.0, SORTS BLOCKS IN MASS STORE C (2**IBEX REAL ELMTS PER BLOCK AND 2**M BLOCKS IN SECOND CASE) C C THE ALGORITHM MAINTAINS A SET OF 'REVERSED' INTEGERS IN ARRAY IRA() C OF INCREASING NUMBER OF BITS, UP TO 2 LESS THAN (IH-IG) BITS. C INCREMENTING A REVERSED INTEGER THEN REQUIRES THE ALTERNATE C ADDITION OF NRA() TO IRA(), OR REPLACEMENT BY THE NEXT LOWER C INCREMENTED REVERSED INTEGER IN THE HIERARCHY, RECURSIVELY. C THIS IN ITSELF IS FAST, AS RECURSION DEPTHS ARE ON AVERAGE SMALL. C BUT, IN ADDITION, ONLY QUARTER LENGTH SERIES ARE GENERATED (-2 BITS) C AND THE FULL LENGTH DERIVED BY SCALING BY 2 AND ADDING OFFSETS. C IN THIS FINAL STAGE, ONLY VALID SWAP PAIRS ARE GENERATED (1 OR 3 EACH C C WITHIN THE INNER LOOPS, GROUPS OF 2**IG ELMTS ARE MOVED TOGETHER C WHILE THIS IS REPEATED OVER 2**(M-IH) PARTS OF THE ARRAY, C CORRESPONDING TO THE UNPERMUTED BITS M TO IH AND IG-1 TO 0. C REAL BUFA(1),TEMP INTEGER IRA(16),NRA(16),IFOFA(3),IROFA(3) C IHG=IH-IG-3 IF(IHG.LE.-2)RETURN C NO PERMUTATION REQUIRED C NB=2**IBEX NB1=NB+1 NG=2**IG NGDB=NG*2 NH=2**IH NHHF=NH/2 C NG IS MOVEMENT GROUP SIZE, NH IS PERMUTATION REPLICATION SIZE NM=2**M NPARS=NM-NH+1 NREV=NH/4 C DO 10 J=1,IHG IRA(J)=0 NREV=NREV/2 10 NRA(J)=NREV C REVERSED INTEGER RECURSION SETS INITIALISED C NREV=NH/4 IFOFA(1)=NG-1 IROFA(1)=NH/2-1 IFOFA(2)=-1 IROFA(2)=-1 IFOFA(3)=NH/2+NG-1 IROFA(3)=NH/2+NG-1 C THREE PAIRS OF OFFSETS TO CONVERT QUARTER TO FULL LENGTH SERIES C IFOR=0 IREV=0 C C BELOW, GENERATE INDEX PAIRS AND SWAP (IREV IS 'TOP' OF IRA() SET) 20 NOF=3 IF(IFOR.GE.IREV)NOF=1 C SELECTS ONCE-ONLY SWAP PAIRS (EITHER 1 OR 3 PAIRS) DO 40 JOF=1,NOF IFOF=IFOFA(JOF) IROF=IROFA(JOF) DO 40 I1=1,NG C REPETITION OVER GROUP OR SUPER ELEMENT OF NG ACTUAL ELEMENTS IN2F=IFOR+IFOF+I1 IN2R=IREV+IROF+I1 DO 40 I2=1,NPARS,NH C REPETITION OF SAME PERMUTATION OVER ARRAY PARTS IN3F=IN2F+I2 IN3R=IN2R+I2 IF(IBEX.GE.0)GO TO 30 C C BELOW, IN-CORE ELEMENT SORTING TEMP=BUFA(IN3R) BUFA(IN3R)=BUFA(IN3F) BUFA(IN3F)=TEMP GO TO 40 C C BELOW, SORTING WHOLE BLOCKS IN MASS STORE 30 CALL MFREAD(BUFA,NB,IN3F) CALL MFREAD(BUFA(NB1),NB,IN3R) CALL MFWRIT(BUFA,NB,IN3R) CALL MFWRIT(BUFA(NB1),NB,IN3F) C 40 CONTINUE C END OF INNER, REPETITION LOOPS C IFOR=IFOR+NGDB C INCREMENT FORWARD QUARTER-LENGTH INTEGER (ALREADY SCALED BY NG*2) IF(IFOR.GE.NHHF)RETURN C RETURN FORM SUBROUTINE C IF(IREV.GE.NREV)GO TO 50 C TEST FOR ALTERNATE METHODS OF REVERSE-INCREMENTING (SIMPLE BELOW) C NOTE THAT REVERSE QUARTER-LENGTH INTEGER IS ALREADY SCALED BY NG*2 C IREV=IREV+NREV GO TO 20 C C ALTERNATE RECURSIVE ALTERATION TO QUARTER-LENGTH REVERSED SERIES 50 DO 60 J=1,IHG IF(IRA(J).LT.NRA(J))GO TO 70 60 CONTINUE C C BELOW, SIMPLE INCREMENT OF REVERSE INTEGER, LOWER IN HIERARCHY 70 IRA(J)=IRA(J)+NRA(J) IREV=IRA(J) 80 IF(J.EQ.1)GO TO 20 J=J-1 IRA(J)=IREV GO TO 80 C END SUBROUTINE MFLOAD(LOAD,BUFA,IBEX,ICEX,IFLG) C C LOADS, UNLOADS CORE STORE ARRAY BUFA, 2**ICEX REALS, 2**IBEX PER BLOCK C RETURNS IFLG=+1 NORMALLY, IFLG=-1 WHEN FINISHED ONE PASS OF MASS STOR C BLOCKS INDEXED ACCORDING TO VIRTUAL PERMUTATION FUNCTION MFINDX C LOAD=1 (LREAD) READS BLOCKS FROM MASS STORE INTO CORE STORE BUFA C LOAD=2 (LWRIT) WRITES BLOCKS BACK IN-PLACE TO MASS STORE C REAL BUFA(1) DATA LINDX/0/,LHOLD/3/,LREST/4/ C NB=2**IBEX NCB=2**(ICEX-IBEX) IF(LOAD.EQ.2)GO TO 30 IFLG=+1 IDUM=MFINDX(LHOLD,0,0,0,0) C HOLDS CURRENT MFINDX VALUE FOR ENTRY 2 AND SUBRTN MFCOMP DO 10 J=1,NCB K=(J-1)*NB JB=MFINDX(LINDX,0,0,0,0) IF(JB.LT.0)GO TO 20 CALL MFREAD(BUFA(K+1),NB,JB) C READS BLOCK WITH NEXT VIRTUAL MFINDX INDEX 10 CONTINUE RETURN 20 IFLG=-1 RETURN C 30 IDUM=MFINDX(LREST,0,0,0,0) C RESETS MFINDX TO START OF IN-PLACE BLOCK DO 40 J=1,NCB K=(J-1)*NB JB=MFINDX(LINDX,0,0,0,0) CALL MFWRIT(BUFA(K+1),NB,JB) C WRITES BLOCK WITH NEXT VIRTUAL MFINDX INDEX (REPEAT MFREAD SEQUENCE) 40 CONTINUE RETURN C END FUNCTION MFINDX(LSPEC,B,H,M,N) C C VIRTUAL 'S' PERMUTATION (FRASER, J.ACM, V.23, N.2, APR. 76, P.303) C CYCLIC SHIFTS H-B BITS IN INDEX (M-1,...,H-1,...,B,...,0) C COMPUTES NEXT INDEX FOR SEQUENTIAL CORE LOAD, PERM (B.'S'.H)**N C BLOCK SIZE EXPON B, MASS STORE EXPON M (0.LE.B.LE.H.LE.M) C N IS EFFECTIVE NUMBER OF LEFT SHIFTS PER I/O PASS (-N RIGHT SHIFTS) C C NOTE VARIABLE NAMES AS FOLLOWS: C IPERM IS 'P' OF ALGORITHM C NPERM=N (ARGUMENT) IS 'N' OF ALGORITHM C ISTEP IS 'Q**P' OF ALGORITHM C JAY AND KAY ARE 'J' AND 'K' OF ALGORITHM C NOTE UPPER BOUND H INSTEAD OF M, REQUIRING 2**(M-H) REPEATS C C LSPEC=0 (LINDX) RETURNS MFINDX FOR INDEX (B,H,M,N DUMMIES HERE) C LSPEC=1 (LSET) SETS IPERM=0 (UNPERMED), ENTERS B,H,M,N PARAMS C LSPEC=2 (LPERM) CHANGES THE B,H,M,N PARAMETERS C LSPEC=3 (LHOLD) HOLDS CURRENT INDEXING STATE (B,H,M,N DUMMIES HERE) C LSPEC=4 (LREST) RESTORES STATE TO LAST LHOLD (B,H,M,N DUMMIES HERE) C INTEGER B,H C IF(LSPEC.EQ.1)GO TO 100 IF(LSPEC.EQ.2)GO TO 200 IF(LSPEC.EQ.3)GO TO 300 IF(LSPEC.EQ.4)GO TO 400 C 10 IF(ISTEP.NE.0)GO TO 20 C BELOW, PRECEDES FIRST MFINDX OF A PASS IF(NPERM.GT.0)IPERM=MOD(IPERM-NPERM,IHB) IF(IPERM.LT.0)IPERM=IHB+IPERM ISTEP=2**IPERM C C 20 BELOW, NORMAL GENERATION OF NEXT MFINDX 20 MFINDX=JAY+JOFF IF(MFINDX.GT.NMB)GO TO 40 KAY=JAY+ISTEP JAY=MOD(KAY,NHB) IF(KAY.GE.NHB)JAY=JAY+1 NRPT=NRPT-1 IF(NRPT.GT.0)RETURN C C NRPT,JOFF REQUIRED TO REPEAT SEQUENCE ON 2**(M-H) PARTS OF ARRAY JOFF=JOFF+NHB 30 NRPT=NHB JAY=0 RETURN C C 40 BELOW, END OF ONE PASS, PARS RESET, IPERM ALTERED IF INVERSE 40 IF(NPERM.LT.0)IPERM=MOD(IPERM-NPERM,IHB) MFINDX=-1 50 JOFF=1 ISTEP=0 GO TO 30 C C LSPEC=1 (LSET) SETS IPERM=0 (UNPERMED), ENTERS B,H,M,N PARAMS 100 IPERM=0 C C LSPEC=2 (LPERM) CHANGES THE B,H,M,N PARAMETERS (DUMMIES ELSEWHERE) 200 IHB=H-B NPERM=N NHB=2**IHB NMB=2**(M-B) MFINDX=IPERM GO TO 50 C C LSPEC=3 (LHOLD) HOLDS CURRENT MFINDX INDEXING PARAMETERS 300 JAYH=JAY JOFH=JOFF NRPTH=NRPT 310 MFINDX=IPERM RETURN C C LSPEC=4 (LREST) RESTORES PARAMETERS TO INDEX MFINDX AT LAST LHOLD 400 JAY=JAYH JOFF=JOFH NRPT=NRPTH GO TO 310 C END FUNCTION MFSUM(MEXA,NDIM,MLIM) C C SCANS MEXA LIST IN REVERSE ORDER, RETURNING (MFSUM.JUST GT.MLIM) C (IF MLIM LARGE ENOUGH, RETURNS M TOTAL FOR NDIM VALUES) C (IF MLIM NEGATIVE, RETURNS M TOTAL, REVERSES ORDER OF MEXA LIST) C INTEGER MEXA(1) C MFSUM=0 IF(NDIM.LE.0)RETURN C DO 10 J=1,NDIM I=NDIM+1-J MFSUM=MFSUM+MEXA(I) IF((MLIM.GE.0).AND.(MLIM.LT.MFSUM))RETURN 10 CONTINUE IF(MLIM.GE.0)RETURN C C BELOW, REVERSE ORDER OF MEXA LIST NDIMH=NDIM/2 DO 20 J=1,NDIMH K=NDIM+1-J MTEM=MEXA(J) MEXA(J)=MEXA(K) 20 MEXA(K)=MTEM RETURN C END SUBROUTINE MFRCMP (MEXA,NDIM,ISGN,IDIR,IPAK, BUFA,B,M) C C UNSCRAMBLES REAL-TO-COMPLEX FFT OR VICE-VERSA, CALLED BY SUBRTN RMFFT C MOST ARGUMENTS HAVE SAME MEANING AS IN RMFFT COMMENTS C BUT 2**B COMPLEX ELMTS IN MASS STORE BLOCK, C USES (2**B)*4 CMPLX IN BUFA, 'LOWER', 'UPPER' PLUS EXPANSION AREAS C TOTAL MASS STORE ARRAY SIZE OF 2**M COMPLEX ELMTS. C COMPLEX ATEM,BTEM,TEMP,W,D,BUFA(1) INTEGER B,JAYA(4),KAYA(4),JWKA(4),KWKA(4),MEXA(1) C JAYA,KAYA,JWKA,KWKA ALLOW UP TO 4 DIMENSIONS - INCREASE IF REQUIRED DATA PI/3.141592653589793/ DATA LOWER/1/,LUPPR/2/,LCLR/-1/ C DO 10 IDIM=1,NDIM JAYA(IDIM)=0 KAYA(IDIM)=0 10 CONTINUE C MULTIDIMEN. CONJUGATE-SYMMETRIC INDICES ZEROED C IEXPND=1 NB=2**B NBDB=NB*2 JBOF=2**(M-B) MAX=M-B-MEXA(NDIM) IF(IDIR*IPAK.LT.0)MAX=M-B JBMAX=2**MAX IF(MAX.LT.0)JBMAX=1 IF(IPAK.LT.0)JBMAX=0 C JBMAX IS MAXIMUM BLOCK INDEX REQUIRED (DEPENDS ON IPAK) C IWFG=0 W=(1.,0.) D=CEXP(CMPLX(0.,PI*2.0**(-MEXA(NDIM)))) IF(ISGN.LT.0)D=CONJG(D) C W IS COMPLEX PHASE FACTOR, D IS RECURSIVE MODIFIER OF W C 20 JAY=0 KAY=0 IDIM=NDIM 30 IF(IDIM.EQ.1)GO TO 40 NUMD=2**MEXA(IDIM) JWKA(IDIM)=JAY KWKA(IDIM)=KAY JAY=JAY*NUMD+JAYA(IDIM) KAY=KAY*NUMD+KAYA(IDIM) IDIM=IDIM-1 GO TO 30 C CONJUGATE-SYMMETRIC BASE INDICES COMPUTED FROM MULTIDIMEN. SET C 40 MEX1=MEXA(1) C 2**MEX1 IS NUMBER OF VALUES ADJACENT IN FIRST DIMENSION IFLG=-1 IF(MEX1.LE.B)GO TO 140 C C BELOW, FIRST DIMEN. GREATER THAN BLOCK SIZE, MULTIPLE BLOCKS NBPD1=2**(MEX1-B) NBLCNT=NBPD1 KINC=NB KBINC=NBLCNT-1 IF(JAY.EQ.KAY)NBLCNT=NBLCNT/2 JB=JAY*NBPD1+1 KB=KAY*NBPD1+1 C JB AND KB ARE BLOCK INDEX PAIRS CONTAINING CONJUGATE ELEMENTS J1=0 K1=0 C 50 NCNT=NB+1 60 CALL MFRLOD(LOWER,IOF,BUFA,NB,JB,JBMAX,JBOF,IDIR,NCNT) C LOWER BLOCK LOADED IF(JB.GT.JBMAX)IEXPND=-1 J2=J1+IOF JB=JB+1 J3=0 K3=0 NEWBLK=NCNT-NB IF(IFLG.GE.0)GO TO 80 C 70 CALL MFRLOD(LUPPR,IOF,BUFA,NB,KB,JBMAX,JBOF,IDIR,IFLG) C UPPER BLOCK LOADED IFLG=IFLG+1 K2=K1+IOF KB=KB+KBINC C FIRST TIME, UPPER BLOCK STEPS HIGH, FOLLOWING STEPS SMALL NEGATIVE KBINC=-1 C 80 J=J2+J3 K=K2+K3 C J AND K INDEX CONJUGATE-SYMMETRIC PAIRS IN CORE JJ=J+NBDB KK=K+NBDB IF(IDIR.GT.0)GO TO 180 C C BELOW, UNSCRAMBLING FOR REAL-TO-COMPLEX FFT TEMP=(BUFA(J)+CONJG(BUFA(K)))*0.5 BTEM=BUFA(K)-CONJG(BUFA(J)) BTEM=(CMPLX(AIMAG(BTEM),REAL(BTEM)))*0.5*W ATEM=TEMP+BTEM BTEM=TEMP-BTEM BUFA(J)=ATEM IF(IEXPND.GT.0)BUFA(JJ)=BTEM IF(IWFG.EQ.0)GO TO 150 BUFA(K)=CONJG(BTEM) IF(IEXPND.GT.0)BUFA(KK)=CONJG(ATEM) C 90 J3=J3+1 K3=KINC-J3 C IN-CORE INDEX PAIRS STEPPED IN OPPOSING DIRECTIONS IF(IDIM.NE.NDIM)GO TO 95 IWFG=1 W=W*D C RECURSIVE MODIFICATION OF W IF UNIDIMEN. TRANSFORM 95 NCNT=NCNT-1 IF(NCNT.LE.0)GO TO 100 C ENTER RECURSION ROUTINE IF OPERATION COMPLETE IN CURRENT DIMEN IF(J3.EQ.1)GO TO 70 IF(NCNT.GT.NEWBLK)GO TO 80 C END OF INNER LOOP (NOTE SPECIAL CASE WHEN J3=1 ABOVE) C C BELOW, MAY REQUIRE TO READ NEW BLOCKS NBLCNT=NBLCNT-1 IF(NBLCNT.GT.0)GO TO 50 IF(JAY.EQ.KAY)GO TO 60 C JAY.EQ.KAY NEEDS SYMMETRICAL MIDDLE, OTHERWISE CURRENT DIMEN COMPLT C C 100 BELOW, RECURSION TO COMPUTE MULTIDIMEN. CONJUGATE-SYMMETRY 100 JAYA(IDIM)=0 KAYA(IDIM)=0 IDIM=IDIM+1 IF(IDIM.GT.NDIM)GO TO 120 NUMD=2**MEXA(IDIM) IF(NUMD.LE.1)GO TO 120 IF(IDIM.NE.NDIM)GO TO 105 IWFG=1 W=W*D C RECURSIVE MODIFICATION OF W IF MULTIDIMEN. FFT 105 IF(JAYA(IDIM).EQ.0)GO TO 110 IF((JWKA(IDIM)*NUMD+JAYA(IDIM)).EQ. X (KWKA(IDIM)*NUMD+KAYA(IDIM)))GO TO 100 IF(KAYA(IDIM).EQ.1)GO TO 100 C 110 JAYA(IDIM)=JAYA(IDIM)+1 KAYA(IDIM)=NUMD-JAYA(IDIM) C RECURSIVE STEPPING OF MULTIDIMEN. CONJUGATE-SYMMETRIC INDEX PAIRS GO TO 20 C C BELOW, OPERATION COMPLETE, TIDY UP AND RETURN FROM SUBROUTINE 120 DO 130 IAREA=1,2 CALL MFRLOD(IAREA,IOF,BUFA,NB,LCLR,JBMAX,JBOF,IDIR,IFLG) C DUMMY CALL TO MFRLOD TO WRITE ANY UNWRITTEN BLOCKS TO MASS STORE 130 CONTINUE RETURN C RETURN FROM SUBROUTINE C C C 140 BELOW, FIRST DIMEN. LESS THAN BLOCK SIZE, INDEX PAIRS ALL IN-CORE 140 NUMD1=2**MEX1 NBPD1=NB/NUMD1 NCNT=NUMD1 KINC=NCNT KBINC=0 IF(JAY.EQ.KAY)NCNT=NCNT/2+1 JB=JAY/NBPD1+1 KB=KAY/NBPD1+1 C JB AND KB ARE BLOCK INDEX PAIRS CONTAINING CONJUGATE ELEMENTS J1=(JAY-(JB-1)*NBPD1)*NUMD1 K1=(KAY-(KB-1)*NBPD1)*NUMD1 GO TO 60 C C 150 BELOW, UNSCRAMBLING WITH W0 (IWFG=0) MUST BE TREATED DIFFERENTLY 150 IF(IEXPND.LT.0)GO TO 160 C BELOW, ARRAY EXPANSION (EITHER IPAK=+1 OR IPAK=0 AND STILL REDUNDANT) BUFA(K)=CONJG(ATEM) BUFA(KK)=CONJG(BTEM) GO TO 90 C 160 BELOW, NO ARRAY EXPANSION (EITHER IPAK=-1 OR IPAK=0 NOT REDUNDANT) 160 IF(J.EQ.K)GO TO 170 BUFA(K)=CONJG(BTEM) GO TO 90 C 170 BELOW, SPECIAL CASE IF IPAK=-1 AND ELEMENTS ARE SAME 170 BUFA(J)=CMPLX(REAL(ATEM),REAL(BTEM)) GO TO 90 C C 180 BELOW, SCRAMBLING FOR COMPLEX-TO-REAL FFT 180 IF(IWFG.EQ.0)GO TO 200 BTEM=CONJG(BUFA(K)) 190 ATEM=(BUFA(J)+BTEM) BTEM=(BUFA(J)-BTEM)*W BTEM=CMPLX(AIMAG(BTEM),REAL(BTEM)) BUFA(J)=ATEM-CONJG(BTEM) BUFA(K)=CONJG(ATEM)+BTEM GO TO 90 C C 200 BELOW, SCRAMBLING WITH W0 (IWFG=0) MUST BE TREATED DIFFERENTLY 200 IF(IEXPND.LT.0)GO TO 210 BTEM=BUFA(JJ) GO TO 190 C C 210 BELOW, NO REDUNDANCY (EITHER IPAK=-1 OR IPAK=0 OR 1 NOT REDUND) 210 IF(J.EQ.K)GO TO 220 BTEM=CONJG(BUFA(K)) GO TO 190 C C 220 BELOW, SPECIAL CASE IF IPAK=-1 AND ELEMENTS ARE SAME 220 BTEM=CMPLX(AIMAG(BUFA(J)),0.) BUFA(J)=CMPLX(REAL(BUFA(J)),0.) GO TO 190 C END SUBROUTINE MFRLOD(IAREA,IOF,BUFA,NB,JB,JBMAX,JBOF,IDIR,NCNT) C C LOADS, UNLOADS CORE STORE ARRAY BUFA, FOR REAL FFT UNSCRAMBLING ROUTIN C BLOCK SIZE NB CMPLX, BLOCK NUMBER JB (JB=-1 DOES FINAL TIDY O/P) C JBMAX IS MAX BLOCK INDX FOR EXPANSN, JBOF OFFSET TO EXPANDING BLOCKS C IDIR=-1 DIRECTION REAL/CMPLX, +1 CMPLX/REAL C IAREA=1 (LOWER) OR 2 (UPPER) OF TWO AREAS IN LOGICAL UNSCRAMBLING C NOTE THAT BLOCK NORMALLY PHYSICALLY LOADED IN THESE AREAS, C BUT, IF BLOCK ALREADY RESIDENT, MAY BE IN DIFFERENT AREA, SO C IOF RETURNED AS ACTUAL OFFSET IN BUFA TO LOADED BLOCK. C USES (2**B)*4 CMPLX IN BUFA, 'LOWER', 'UPPER' PLUS EXPANSION AREAS C RETURNS IOF AS BUFFER OFFSET TO AREA (MAY NOT BE SAME, IF BLOCK RESID C C NCNT IS COUNT OF ELEMENTS TO BE ACCESSED IN THIS LOAD, TO ALLOW C NOTE TO BE TAKEN OF ANY PARTLY FILLED BLOCKS DURING EXPANSION, C PREVENTING THE READING OF 'NON-EXISTENT' BLOCKS. C LISTS JBPFA(), NCPFA() OF SIZE NPARF HOLD THIS INFORMATION, DEFAULTS C TO ALL-READ IF EXCEEDED, BUT INCREASE NPARF ETC, IF PROBLEM. C COMPLEX BUFA(1) INTEGER JBAREA(2),NCAREA(2),JBPFA(5),NCPFA(5) DATA JBAREA(1)/-1/,JBAREA(2)/-1/,NPARF/5/ C IF(JBAREA(1).GE.0)GO TO 20 C JBAREA() HOLDS INDEX OF BLOCK LOADED IN AREA 1 OR 2 (FIRST TIME -1 BEL C IEXIST=-1 DO 10 I=1,NPARF 10 JBPFA(I)=-1 C PRE-CLEARS PARTLY FILLED BLOCK LIST (ONCE BLOCK FILLED, ALSO CLEARED) C 20 NBDB=NB*2 IF(JB.LT.0)GO TO 50 IF(IAREA.EQ.2)GO TO 30 NCLOW=NCNT IF(MOD(NCNT,2).NE.0)NCLOW=(NCLOW-1)*2 30 NCHLD=NCLOW IF(IAREA.EQ.2)NCHLD=NCLOW-1 IF(NCNT.LT.0)NCHLD=1 C NCHLD IS THE NUMBER OF ELEMENTS TO BE ACCESSED IN CURRENT READ C DO 40 I=1,2 IF(JB.EQ.JBAREA(I))GO TO 140 40 CONTINUE C TEST DONE TO SEE IF REQUIRED BLOCK ALREADY IN CORE (TRIVIAL IF SO) C C OTHERWISE BELOW, FIRST WRITE OUT RESIDENT BLOCK, THEN READ IN NEW 50 IOF=(IAREA-1)*NB+1 C IOF IS BASE OFFSET OF CORE AREA WHERE BLOCK IS TO BE FOUND IOFDB=IOF+NBDB IF(JBAREA(IAREA).LT.0)GO TO 90 CALL MFWRIT(BUFA(IOF),NBDB,JBAREA(IAREA)) C WRITE OUT BLOCK BEFORE READING NEW BLOCK IF(IDIR.GT.0)GO TO 90 IF(JBAREA(IAREA).GT.JBMAX)GO TO 90 IF(NCAREA(IAREA).GE.NB)GO TO 80 C C BELOW, IF LAST BLOCK ONLY PART-FILLED, INDEX, ELMTS ACCESSED NOTED DO 60 I=1,NPARF IF(JBPFA(I).LT.0)GO TO 70 60 CONTINUE C NO ROOM IN LISTS, DEFAULTS TO ALL READ I=NPARF IEXIST=I 70 JBPFA(I)=JBAREA(IAREA) NCPFA(I)=NCAREA(IAREA) C 80 CALL MFWRIT(BUFA(IOFDB),NBDB,JBOF+JBAREA(IAREA)) C SIMILARLY, WRITE OUT BLOCK PAIR IF EXPANDING C C BELOW, READ BLOCK NOTING BLOCK INDX (READ EXPANDED, IF PART FILLED) 90 JBAREA(IAREA)=JB IF(JB.LT.0)GO TO 130 CALL MFREAD(BUFA(IOF),NBDB,JB) C READ REQUIRED BLOCK AND NOTE ACCESS COUNT NCAREA(IAREA)=NCHLD IF(JB.GT.JBMAX)GO TO 130 IF(IDIR.GT.0)GO TO 120 C C BELOW, EXPANSION - DOES BLOCK EXIST TO READ DO 100 I=1,NPARF IF(JB.EQ.JBPFA(I))GO TO 110 100 CONTINUE IF(IEXIST.LT.0)GO TO 130 110 JBPFA(I)=-1 NCAREA(IAREA)=NCPFA(I)+NCHLD C IF BLOCK TO BE READ WAS ONLY PART FILLED, THEN IT EXISTS TO READ 120 CALL MFREAD(BUFA(IOFDB),NBDB,JBOF+JB) C READ EXPANDED BLOCK IF REQUIRED C 130 RETURN C RETURN FROM SUBROUTINE C C BELOW, TRIVIAL CASE - BLOCK ALREADY LOADED 140 IOF=(I-1)*NB+1 C IOF IS BASE OFFSET OF CORE AREA WHERE BLOCK IS TO BE FOUND IF(I.NE.IAREA)GO TO 150 NCAREA(I)=NCAREA(I)+NCHLD C INCREASE ACCESS COUNT IF CURRENT IAREA MATCHES ORIGINAL IAREA 150 RETURN C END FUNCTION MFPAR(IRMF,ICOMP) C C HELPER ROUTINE TO CROSS-COMPUTE MASS STORE FFT FILE PARAMETERS C PARAMETERS ARE HELD AND COMPUTED IN 3 COMMON AREAS (SEE BELOW) C MFPAR RETURNS 0 NORMALLY, -1 IF NOT ALL MFINT CORRECT, +1 IBEX ERROR C C COMMON/MFARG/ HOLDS ARGUMENTS AS USED IN FFT CALLS, AS FOLLOWS: C VARIABLE NAMES HAVE SAME MEANING AS COMMENTS, SUBROUTINE RMFFT C MEXA() HOLDS EXPONENTS FOR UP TO 4 DIMENSIONS (R/T ZEROS EXCESS) C NDIM NUM DIMENS, IBEX,ICEX BLOCK AND CORE EXPONS, IPAK RMFFT PACKI C ISGN,IDIR,SCAL ARE IGNORED HERE, BUT INCLUDED FOR COMPLETENESS C C COMMON/MFVAL/,/MFINT/ RETURN COMPUTED VALUES, USEFUL FOR FILE ACCESS C NDMA(4),DIMA(4) HOLD DIMENSION SIZES CORRESPONDING TO MEXA() C (EG. NDMA(1)=DIMA(1)=2.**MEXA(1), ETC. AND =1. BEYOND NDIM) C C NTD1,TDM1 IS CURRENT TOTAL NUM OF 'RECDS' OF SIZE NRD1,RDM1 C NRD1,RDM1 IS NUM OF REALS IN CURRENT FIRST DIMENSION C (USEFUL FOR ACCESSING DATA BY MFREAD/MFWRIT, NRD1,RDM1 REALS, C ASSUMING THAT MFREAD/MFWRIT CAN HANDLE 'RECDS' OF DIFFERENT SIZES C C NFBK,FBLK IS MAXIMUM FILE SIZE OF 'RECDS' OF SIZE NRBK,RBLK C NTBK,TBLK IS CURRENT TOTAL NUM OF 'RECDS' OF SIZE NRBK,RBLK C NRBK,RBLK IS NUM OF REALS IN FFT WORKING BLOCK (2**IBEX REALS) C (GIVES MAX AND CURRENT FILE SIZE AND ACCESS BY FFT ROUTINES, C NFBK.GT.NTBK ONLY WITH PACKED REAL DATA WHEN EXPANDING, IPAK=0 OR 1) C C NRCR,RCOR IS NUM OF REALS IN FFT WORKING CORE (2**ICEX REALS) C NSZE=SIZE=2.**M, WHICH IS THE EFFECTIVE TOTAL SIZE OF TRANSFORM, C WHERE M IS SUM TO NDIM OF MEXA() (SEE RMFFT COMMENTS) C C NOTE THAT ALL /MFARG/ ARE INTGS (EXCEPT SCAL), ALL /MFVAL/ REALS C (/MFINT/ IS INTEGER CONVERSION OF /MFVAL/, ANY VALUE OF MFINT C IS SET -1 IF TOO LARGE, BY FIXMAX, AND MFPAR RETURNED -1 AS FLAG, C FIXMAX SET BY DATA STATEMENT TO 32767. HERE, BUT ALTER TO SUIT) C C ROUTINE ARGUMENTS HAVE THE FOLLOWING EFFECT: C IRMF=-1, DATA IS PACKED REAL, +1 DATA IS COMPLEX, ROUTINE RMFFT, C IRMF=0, DATA IS COMPLEX, ROUTINE CMFFT C C ICOMP=0, COMPUTES VALUES IN /MFVAL/ FROM VALUES GIVEN IN /MFARG/ C ICOMP=1 , REVERSE COMPUTES EXPONENTS IN /MFARG/ FROM /MFVAL/ C (DIMA(),RBLK,RCOR GIVEN INSTEAD OF MEXA(),IBEX,ICEX) C C NOTE, ROUTINE FORCES ICEX, IBEX TO CORRECT RANGE, MFPAR=+1 IF CANNOT C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE REAL VAL(11) INTEGER INT(11) EQUIVALENCE (VAL(1),DIMA(1)),(INT(1),NDMA(1)) C DATA FIXMAX/32767./,NMAX/4/ C MFPAR=0 IF(ICOMP.EQ.0)GO TO 20 ALG2=ALOG(2.) IBEX=IFIX(ALOG(RBLK)/ALG2+0.5) ICEX=IFIX(ALOG(RCOR)/ALG2+0.5) C DO 10 I=1,NDIM 10 MEXA(I)=IFIX(ALOG(DIMA(I))/ALG2+0.5) C 20 M=0 DO 30 I=1,NMAX IF(I.GT.NDIM)MEXA(I)=0 M=M+MEXA(I) 30 DIMA(I)=2.**MEXA(I) SIZE=2.**M C IF(IRMF.EQ.0)GO TO 90 IF(ICEX.GT.M)ICEX=M IF(IBEX.GT.ICEX-2)IBEX=ICEX-2 IF(IBEX.LT.2)MFPAR=1 C FORCES ICEX.NGT.M AND IBEX.NGT.ICEX-2, OR MFPAR=1 (IRMF=+/- 1) C 40 RBLK=2.**IBEX RCOR=2.**ICEX C FADD=SIZE IF(IRMF.EQ.0.OR.IPAK.GT.0)GO TO 50 C FADD IS ADDITIONAL FILE SIZE IN REALS, 'SIZE' IF CMFFT OR IPAK=1 C FADD=0. IF(IPAK.LT.0)GO TO 50 C IPAK=-1 REQUIRES NO FILE EXPANSION C IDIM=NDIM IF(IRMF.LT.0)IDIM=1 FADD=SIZE*2./DIMA(IDIM) C FADD COMPUTED FOR PARTICULAR CASE OF IPAK=0, WHEN COMPLX C 50 FSIZ=SIZE+FADD ITEM=IFIX(FSIZ/RBLK+0.5) IF(FLOAT(ITEM)*RBLK+0.5 .LT.FSIZ)ITEM=ITEM+1 FBLK=FLOAT(ITEM) C FBLK IS MAXIMUM NUMBER OF 'RECDS', SIZE RBLK, POSSIBLE TBLK=FBLK IF(IRMF.GE.0)GO TO 60 C GENERALLY TBLK=FBLK, BUT FOR PACKED REAL NOT SO, BELOW FSIZ=SIZE TBLK=FSIZ/RBLK C 60 TDM1=1. RDM1=FSIZ IF(NDIM.EQ.1)GO TO 70 C JOB COMPLETED IF NDIM=1 C RDM1=DIMA(1) IF(IRMF.GE.0)RDM1=RDM1*2. TDM1=FSIZ/RDM1 C OTHERWISE COMPUTE TDM1 AS NUMBER OF 'RECDS', SIZE RDM1 REALS C 70 DO 80 I=1,11 INT(I)=-1 IF(VAL(I).LE.FIXMAX)INT(I)=IFIX(VAL(I)+0.5) IF(INT(I).LT.0.AND.MFPAR.EQ.0)MFPAR=-1 80 CONTINUE C CONVERT VALUES IN /MFVAL/ TO INTEGERS IN /MFINT/ (-1 IF TOO LARGE) RETURN C 90 IF(ICEX.GT.M+1)ICEX=M+1 IF(IBEX.GT.ICEX-1)IBEX=ICEX-1 IF(IBEX.LT.1)MFPAR=1 GO TO 40 C FORCES ICEX.NGT.M+1 AND IBEX.NGT.ICEX-1, OR MFPAR=1 (IRMF=0) C END SUBROUTINE DMPERM (MEXA,NDIM,NSHFT,IREX, BUFA,IBEX,ICEX) C C SHIFTS ORDER OF DIMENSIONS OF REAL OR COMPLEX MASS STORE ARRAY C NOTE, THIS IS NOT USED BY FFT SUBRTNS BUT IS INCLUDED FOR COMPLETENESS C (FRASER, ACM TOMS - 1978/79, AND J.ACM, V.23,N.2, APRIL 76, PP. 298-3 C C MEXA(J) LIST OF DIMENSION SIZE EXPONS (BASE 2), ADJACENT VARIABLES FIR C NDIM IS NUMBER OF EXPONENTS IN LIST AND THUS THE NUMBER OF DIMENSIONS C SUM TO NDIM: MEXA(J)=M, WHERE 2**M IS SIZE OF MASS STORE ARRAY (SEE B C NSHFT IS DIMENSION SHIFT COUNT, THUS: C NSHFT=0, NO SHIFT OR CHANGE OCCURS C NSHFT=1,2 ETC., FIRST TO NEXT DIMENSION, CIRC NSHFT PLACE SHIFT (MOD C NSHFT=-1, REVERSES THE ORDER OF DIMENSIONS C IREX=0 REAL, 1 COMPLEX (THAT IS, MOVEMENT GROUP IS 2**IREX REALS, C AND TOTAL MASS STORE SIZE IS 2**(M+IREX) REAL ELEMENTS) C REAL BUFA(1) INTEGER MEXA(1) C NS=MOD(NSHFT,NDIM) IF(NS.EQ.0)RETURN M=MFSUM(MEXA,NDIM,-1)+IREX C FINDS M TOTAL AND REVERSES MEXA LIST CALL MFSORT(BUFA,IBEX,ICEX,IREX,M,M) C INITIAL OVERALL BIT-REVERSAL M BITS ABOVE IREX BITS IF(NSHFT.LT.0)GO TO 10 C C BELOW, REVERSAL OF TWO PARTS, TO FORM REQUIRED SHIFT IH=MFSUM(MEXA,NS,-1)+IREX CALL MFSORT(BUFA,IBEX,ICEX,IREX,IH,M) C REVERSE LOWER PART OF MEXA LIST AND LOWER PART OF ARRAY BITS CALL MFSORT(BUFA,IBEX,ICEX,IH,M,M) C SEPARATELY REVERSE UPPER PART OF ARRAY BITS IH=MFSUM(MEXA(NSHFT+1),NDIM-NS,-1) C REVERSE UPPER PART OF MEXA LIST RETURN C RETURN FROM SUBROUTINE AFTER CYCLIC SHIFTS C C BELOW, SEPARATELY REVERSE OVER EACH DIMENSION (DIMEN REVERSAL) 10 IH=IREX DO 20 J=1,NDIM IG=IH IH=IH+MEXA(J) 20 CALL MFSORT(BUFA,IBEX,ICEX,IG,IH,M) RETURN C END C C THIS PROGRAM TESTS THE MASS STORE FFT BY COMPARISON WITH NAIVE DFT C FFT PARAMETERS MAY BE ALTERED AT WILL (SEE COMMENTS) C MASS STORE IS SIMULATED BY FORTRAN ARRAYS (SEE DUMMY I/O SUBROUTINES) C PRINTING MAY BE COPIOUS, OR ONLY MAX DIFFERENCES (SEE COMMENTS) C TEST OK IF MAX DIFFERENCES ARE NEAR ORDER OF MACHINE ROUND-OFF C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE C C COMMON AREAS /MFARG/,/MFVAL/,/MFINT/ USEFUL FOR RUNNING MASS STORE FFT C /MFARG/ HOLDS ARGUMENTS USED IN FFT CALLES, MOSTLY EXPONENTS C HELPER ROUTINE MFPAR COMPUTES VALUES FROM /MFARG/ INTO C /MFVAL/ (REALS AS SOME LARGE), /MFINT/ (INTEGER EQUIVALENTS IF POSS) C OR CAN REVERSE-COMPUTE SOME /MFARG/ FROM /MFVAL/ C SEE COMMENTS, ROUTINE MFPAR. C COMMON/MASS/RMAS(1024) COMPLEX ANAIV(512),BNAIV(512),CBUFA(512),CDIF REAL RANDA(1024),BUFA(1024) EQUIVALENCE (CBUFA(1),BUFA(1)) C C COMMON/MASS/RMAS() USED BY ROUTINES MFREAD/MFWRIT TO SIMULATE MASS STORE C ANAIV(), BNAIV() HOLD RESULT OF NAIVE DFT FOR COMPARISON C BUFA()=CBUFA() IS WORKING AREA IN CORE STORE FOR FFT AND PROGRAM C RANDA HOLDS PSEUDO RANDOM DATA USED IN TEST C LP=5 IPRINT=0 C LP IS PRINTER LOGICAL UNIT, IPRINT=+1 FOR COPIOUS PRINT, C IPRINT=0 FOR MAX DIFFERENCES ONLY, -1 OVERALL MAX DIFFERENCE ONLY C M=5 C M SETS THE OVERALL ARRAY SIZE FOR AUTO IBEX,ICEX,MEXA,NDIM STEPPING C FIXED VALUES CAN BE USED (SEE COMMENTS BELOW DO 100 STATEMENTS) C IRMF=-1 C IRMF=-1 REAL ROUTINE RMFFT TEST, 0 COMPLEX ROUTINE CMFFT TEST C ISGN=-1 IDIR=-1 IPAK=1 C FFT ARGS, ISGN=+/- 1, IDIR=-1 (RMFFT), IDIR=1 OR 0 (CMFFT) C IPAK=1 OR 0 (RMFFT), -1 GIVES APPARENT FAILURES DUE TO SQUEESED RESULT C C BELOW, PRINT HEADINGS FOR TEST OUTPUT IF(IPRINT.LE.0)WRITE(LP,910)IPRINT,IRMF 910 FORMAT(31H1MASS STORE FFT TEST - IPRINT =,I3, X 36H (1=COPIOUS,0=MAX DIFFS,-1=OVERALL),, X 9H IRMF =,I3,28H (0=CMFFT TEST,1=RMFFT TEST) /) DIFMG=0. C C BELOW, DO 100 COMPUTES ALL POSSIBLE MEXA FOR 1,2 AND 3 DIMENSIONS DO 100 NDIM=1,3 M2M=M-NDIM+1 IF(NDIM.EQ.1)M2M=1 DO 100 M2=1,M2M M3M=M2M-M2+1 IF(NDIM.NE.3)M3M=1 DO 100 M3=1,M3M IF(NDIM.EQ.1)MEXA(1)=M IF(NDIM.EQ.2)MEXA(1)=M-M2 IF(NDIM.EQ.3)MEXA(1)=M-M2-M3 MEXA(2)=M2 MEXA(3)=M3 C REPLACE DO 100 SET BY FIXED MEXA LIST, IF DESIRED C IBEX=2 ICEX=4 C DUMMY IBEX, ICEX SO NO ERROR IN MFPAR BELOW IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 C CALL HELPER ROUTINE TO COMPUTE SIZES USED BY NAIVE DFT SUBRTN C M=MFSUM(MEXA,NDIM,99) AR=RANMF(1) C RESET RANDOM NUMBER GENERATOR AND COMPUTE M IN CASE NOT GIVEN DO 10 J=1,NSZE RANDA(J)=RANMF(-1) 10 ANAIV(J)=CMPLX(RANDA(J),0.) C LOAD RANDOM NUMBERS FOR FFT AND FOR NAIVE SUBROUTINE C CALL NAIVE(ANAIV,BNAIV,NDMA(1),NDMA(2),NDMA(3),ISGN) C NAIVE DFT SUBROUTINE CALLED TO COMPUTE 'SLOW' FOURIER TRANSFORM C C IF(IRMF.EQ.0)GO TO 20 C BELOW, SET LIMTS FOR STEPPING IBEX, ICEX, WHEN CALLING RMFFT IBEXL=2 ICEXL=4 ICEXM=M GO TO 30 C C SETS DIFFERENT LIMITS FOR IBEX, ICEX FOR CMFFT BELOW (IRMF.EQ.0) 20 IBEXL=1 ICEXL=2 ICEXM=M+1 C 30 IF(ICEXL.GT.ICEXM)GO TO 1000 DO 100 ICEX=ICEXL,ICEXM IBEXM=ICEX-2 IF(IRMF.EQ.0)IBEXM=ICEX-1 DO 100 IBEX=IBEXL,IBEXM C IBEX AND ICEX COMPUTED; REPLACE DO 100 ABOVE BY FIXED IBEX,ICEX IF REQUD. C IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1 C HELPER ROUTN, NTD1 TOTAL NUMB OF NRD1 REALS IN FIRST DIMENSION C (NCNT IS NUMBER OF REAL ELMTS IN FIRST DIMENSION) SCAL=1. IF(IRMF.EQ.0)GO TO 50 C SWITCH FOR COMPLEX ROUTINE CMFFT AT 50, REAL RMFFT BELOW C DO 40 JB=1,NTD1 K=(JB-1)*NCNT DO 35 I=1,NCNT J=K+I 35 BUFA(I)=RANDA(J) CALL MFWRIT(BUFA,NRD1,JB) 40 CONTINUE C LOAD RANDOM NUMBERS IN REAL ARRAY IN 'RECDS' OF FIRST DIMEN LENGTH C (NOTE, THIS REQUIRES MFREAD/MFWRIT TO BE ABLE TO ACCEPT 'RECORDS' C OF DIFFERENT LENGTH; OTHERWISE MUST USE NTBK AND NRBK HERE) C CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C REAL MASS STORE ROUTINE RMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT GO TO 70 C C BELOW, USE COMPLEX ROUTINE CMFFT, NCNT NUM OF CMPLX ELMTS IN FIRST DIMEN 50 NCNT=NCNT/2 DO 60 JB=1,NTD1 K=(JB-1)*NCNT DO 55 I=1,NCNT J=K+I 55 CBUFA(I)=CMPLX(RANDA(J),0.) CALL MFWRIT(BUFA,NRD1,JB) 60 CONTINUE C LOAD REAL VALUES IN CMPLX ARRAY IN 'RECDS' OF FIRST DIMEN LENGTH C (NOTE, THIS REQUIRES MFREAD/MFWRIT TO BE ABLE TO ACCEPT 'RECORDS' C OF DIFFERENT LENGTH; OTHERWISE MUST USE NTBK AND NRBK HERE) C CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C COMPLEX MASS STORE ROUTINE CMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT C 70 IF(IPRINT.LE.0)GO TO 75 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 920 FORMAT(8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) WRITE(LP,930) 930 FORMAT(8H INDEX,12X,3HFFT,24X,5HNAIVE,24X,4HDIFF) C 75 IERR=MFPAR(-IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1/2 C HELPER ROUTN, NTD1 TOTAL NUMB OF NRD1 REALS IN FIRST DIMENSION C (NOTE IRMF=+1 FOR DATA IN COMPLEX STATE, NCNT ELMTS) C C BELOW, COMPARES FFT COMPLEX RESULT WITH NAIVE RESULT DIFM=0. DO 80 JB=1,NTD1 K=(JB-1)*NCNT CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF FIRST DIMEN LENGTH (RECOMPUTED ABOVE BY MFPAR) C (NOTE, THIS REQUIRES MFREAD/MFWRIT TO BE ABLE TO ACCEPT 'RECORDS' C OF DIFFERENT LENGTH; OTHERWISE MUST USE NTBK AND NRBK HERE) C DO 80 I=1,NCNT J=K+I INDEX=J-1 IF(IDIR.NE.0)CDIF=CBUFA(I)-BNAIV(J) IF(IDIR.EQ.0)CDIF=CBUFA(I)-ANAIV(J) DIF=ABS(REAL(CDIF)) IF(DIF.GT.DIFM)DIFM=DIF DIF=ABS(AIMAG(CDIF)) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.LE.0)GO TO 80 IF(IDIR.NE.0)WRITE(LP,940)INDEX,CBUFA(I),BNAIV(J),CDIF IF(IDIR.EQ.0)WRITE(LP,940)INDEX,CBUFA(I),ANAIV(J),CDIF 940 FORMAT(1X,I5,3(2X,2E13.4)) 80 CONTINUE C BELOW, PRINT INTERMEDIATE DIFFERENCES C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 950 FORMAT(10H MAX DIFF ,E11.4,1X, X 8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) IF(DIFM.GT.DIFMG)DIFMG=DIFM C C BELOW, INVERT ISGN AND IDIR FOR INVERSE TRANSFORM (COMPLEX-TO-REAL) ISGN=-ISGN IDIR=-IDIR SCAL=1./SIZE IF(IRMF.NE.0) X CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C EITHER ROUTINE RMFFT INVERSE TRANSFORMS ARRAY TO PACKED REAL C IF(IRMF.EQ.0) X CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C OR ROUTINE CMFFT INVERSE TRANSFORMS ARRAY C IF(IPRINT.LE.0)GO TO 85 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) WRITE(LP,960) 960 FORMAT(8H INDEX,4X,8HFFT/2**M,6X,5HINPUT,10X,4HDIFF) C 85 IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1 IF(IRMF.EQ.0)NCNT=NCNT/2 C HELPER ROUTN, NTD1 TOTAL NUMB OF NRD1 REALS IN FIRST DIMENSION C (NCNT IS NUMBER OF ELMTS IN FIRST DIMENSION, REAL OR CMPLX) C C BELOW, COMPARES FFT INVERSE RESULT WITH INITIAL RANDOM INPUT DIFM=0. DO 90 JB=1,NTD1 K=(JB-1)*NCNT CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF FIRST DIMEN LENGTH (RECOMPUTED ABOVE BY MFPAR) C (NOTE, THIS REQUIRES MFREAD/MFWRIT TO BE ABLE TO ACCEPT 'RECORDS' C OF DIFFERENT LENGTH; OTHERWISE MUST USE NTBK AND NRBK HERE) C DO 90 I=1,NCNT J=K+I INDEX=J-1 IF(IRMF.NE.0)RM=BUFA(I) IF(IRMF.EQ.0)RM=REAL(CBUFA(I)) DIF=ABS(RM-RANDA(J)) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.GT.0)WRITE(LP,940)INDEX,RM,RANDA(J),DIF 90 CONTINUE C PRINT INVERSE RESULTS (SHOULD BE SAME AS INITIAL RANDOM SET) C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) IF(DIFM.GT.DIFMG)DIFMG=DIFM ISGN=-ISGN IDIR=-IDIR C RESTORE ISGN AND IDIR FOR FORWARD TRANSFORM 100 CONTINUE C C BELOW, PRINT OVERALL MAXIMUM DIFFERENCE WRITE(LP,970)DIFMG,M,ISGN,IDIR,IPAK 970 FORMAT(18H OVERALL MAX DIFF ,E11.4,3X, X 48H FOR ALL MEXA(1 TO 3 DIM),IBEX,ICEX,MEXA FOR M =,I3, X 19H, ISGN,IDIR(+/-) =,2I4,8H IPAK =,I4) STOP C 1000 WRITE(LP,980)IERR 980 FORMAT(25H IBEX FORCED TOO SMALL OR, X 30H NOT ALL /MFINT/ CORRECT, IERR,I4) STOP END FUNCTION RANMF(J) C C RANDOM NUMBER GENERATOR FOR MASS STORE FFT TEST C IF(J.GE.0)GO TO 20 C POSITIVE J CAUSES RESET OF INITIAL K C NEGATIVE J MUST BE USED NORMALLY C MODULO=2048 FLMOD=2048.0 DO 10 I=1,15 10 K=MOD(5*K,MODULO) Z=FLOAT(K)/FLMOD RANMF=Z RETURN C 20 K=J RANMF=J RETURN C END SUBROUTINE NAIVE(ANAIV,BNAIV,NJ,NK,NL,ISGN) C C NAIVE DISCRETE FOURIER TRANSFORM - 1 TO 3 DIMENSIONS C USED TO TEST MASS STORE FFT, INPUT ARRAY ANAIV(NJ,NK,NL) C RESULT RETURNED IN BOTH ARRAYS ANAIV AND BNAIV C ANAIV DIMENSIONS IN INITIAL ORDER, BNAIV REVERSED ORDER C NJ,NK,NL DIMENSIONING, ISGN SIGN OF COMPLEX EXPONENT OF FOURIER C COMPLEX TEMP,ANAIV(NJ,NK,NL),BNAIV(NL,NK,NJ) DATA PI/3.141592653589793/ C PI2=PI*2.0 IF(ISGN.LT.0)PI2=-PI2 C DO 20 JB=1,NJ AJB=FLOAT(JB-1)/FLOAT(NJ) DO 20 KB=1,NK AKB=FLOAT(KB-1)/FLOAT(NK) DO 20 LB=1,NL ALB=FLOAT(LB-1)/FLOAT(NL) C TEMP=(0.,0.) DO 10 JA=1,NJ AJA=FLOAT(JA-1)*AJB DO 10 KA=1,NK AKA=FLOAT(KA-1)*AKB DO 10 LA=1,NL ALA=FLOAT(LA-1)*ALB 10 TEMP=TEMP+ANAIV(JA,KA,LA)*CEXP(CMPLX(0.,PI2*(AJA+AKA+ALA))) C 20 BNAIV(LB,KB,JB)=TEMP C DO 30 JA=1,NJ DO 30 KA=1,NK DO 30 LA=1,NL 30 ANAIV(JA,KA,LA)=BNAIV(LA,KA,JA) RETURN C END SUBROUTINE MFREAD(BUFA,NB,JB) C C DUMMY SUBROUTINE TO SIMULATE RANDOM ACCESS MASS STORE READ C READ BLOCK, INDEX JB, FROM MASS STORE TO BUFA, NB REAL VALUES C COMMON ARRAY RMAS SIMULATES MASS STORE ARRAY C COMMON/MASS/RMAS(1024) REAL BUFA(NB) C IOF=(JB-1)*NB DO 10 I=1,NB K=IOF+I 10 BUFA(I)=RMAS(K) RETURN C END SUBROUTINE MFWRIT(BUFA,NB,JB) C C DUMMY SUBROUTINE TO SIMULATE RANDOM ACCESS MASS STORE WRITE C WRITE BLOCK, INDEX JB, FORM BUFA TO MASS STORE, NB REAL VALUES C COMMON ARRAY RMAS SIMULATES MASS STORE ARRAY C COMMON/MASS/RMAS(1024) REAL BUFA(NB) C IOF=(JB-1)*NB DO 10 I=1,NB K=IOF+I 10 RMAS(K)=BUFA(I) RETURN C END C PROGRAM MASTOM(TAPE1,INPUT,OUTPUT,TAPE60=INPUT,TAPE5=OUTPUT) C C CONTROL DATA 6000 AND CYBER MASS STORE I/O FFT TEST PROGRAM C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C C COMMON/FFTCOM/LUN,MINDX(512) C C COMMON /FFTCOM/ HOLDS LOGICAL UNIT NUMBER FOR MASS STORE I/O C ARRAY MINDX HOLDS RECORD INDICES FOR CYBER MASS STORE I/O C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE C C COMMON AREAS /MFARG/,/MFVAL/,/MFINT/ USEFUL FOR RUNNING MASS STORE FFT C /MFARG/ HOLDS ARGUMENTS USED IN FFT CALLES, MOSTLY EXPONENTS C HELPER ROUTINE MFPAR COMPUTES VALUES FROM /MFARG/ INTO C /MFVAL/ (REALS AS SOME LARGE), /MFINT/ (INTEGER EQUIVALENTS IF POSS) C OR CAN REVERSE-COMPUTE SOME /MFARG/ FROM /MFVAL/ C SEE COMMENTS, ROUTINE MFPAR. C COMPLEX CBUFA(4096) REAL BUFA(8192) EQUIVALENCE (CBUFA(1),BUFA(1)) C C BUFA()=CBUFA() IS WORKING AREA IN CORE STORE FOR FFT AND PROGRAM C LUN=1 C LUN IS LOGICAL UNIT FOR CYBER MASS STORE I/O C LP=5 IPRINT=0 C LP IS PRINTER LOGICAL UNIT, IPRINT=+1 COPIOUS, 0 MAX DIFFERENCES ONLY C IRMF=-1 C IRMF=-1 REAL ROUTINE RMFFT TEST, 0 COMPLEX ROUTINE CMFFT TEST C ISGN=-1 IDIR=-1 IPAK=1 C FFT ARGS, ISGN=+/- 1, IDIR=-1 (RMFFT), IDIR=1 OR 0 (CMFFT) C IPAK=1, 0 OR -1 (RMFFT), NOT USED (CMFFT) C C BELOW, PRINT HEADINGS FOR TEST OUTPUT IF(IPRINT.LE.0)WRITE(LP,910)IPRINT,IRMF 910 FORMAT(31H1MASS STORE FFT TEST - IPRINT =,I3, X 25H (1=COPIOUS,0=MAX DIFFS),, X 9H IRMF =,I3,28H (0=CMFFT TEST,1=RMFFT TEST) /) DIFMG=0. C MEXA(1)=8 MEXA(2)=6 NDIM=2 IBEX=9 ICEX=13 C MORE FFT ARGS, 2**8 ROWS OF 2**6 ELMTS, 2 DIMEN, C FFT MASS STORE BLOCKS 2**IBEX REALS, BUFA 2**ICEX REALS C IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 CALL OPENMS(LUN,MINDX,NFBK+1,0) C CYBER 'READMS/WRITMS' MASS STORE OPENED WITH 'NUM REC'+1=NFBK+1 C (NOTE HELPER ROUTN MFPAR RETURNS NFBK AS MAXIMUM FILE SIZE) C NCNT=NRBK C HELPER ROUTINE, NCNT NUM OF ELMTS IN FFT BLOCK, NTBK TOTAL BLOCKS C M=MFSUM(MEXA,NDIM,99) SCAL=1. VALU=0. VINC=1./SIZE IF(IRMF.EQ.0)GO TO 50 C SWITCH FOR COMPLEX ROUTINE CMFFT AT 50, REAL RMFFT BELOW C DO 40 JB=1,NTBK DO 35 I=1,NCNT BUFA(I)=VALU 35 VALU=VALU+VINC CALL MFWRIT(BUFA,NRBK,JB) 40 CONTINUE C LOAD RAMP FUNCTN IN REAL ARRAY IN 'RECDS' OF NRBK LENGTH C (NOTE, CYBER MFREAD/MFWRIT (USING READMS/WRITMS) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C REAL MASS STORE ROUTINE RMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT GO TO 70 C C BELOW, USE COMPLEX ROUTINE CMFFT, NCNT NUM OF CMPLX ELMTS IN FFT BLOCK 50 NCNT=NCNT/2 DO 60 JB=1,NTBK DO 55 I=1,NCNT CBUFA(I)=CMPLX(VALU,0.) 55 VALU=VALU+VINC CALL MFWRIT(BUFA,NRBK,JB) 60 CONTINUE C LOAD RAMP FUNCTN IN COMPLEX ARRAY IN 'RECDS' OF NRBK LENGTH C (NOTE, CYBER MFREAD/MFWRIT (USING READMS/WRITMS) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C COMPLEX MASS STORE ROUTINE CMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT C 70 IF(IPRINT.LE.0)GO TO 75 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 920 FORMAT(8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) WRITE(LP,930) 930 FORMAT(8H INDEX,12X,3HFFT) C IERR=MFPAR(-IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRBK/2 C HELPER ROUTN, NTBK TOTAL NUMB OF NRBK REALS IN FFT BLOCK C (NOTE IRMF=+1 FOR DATA IN COMPLEX STATE, NCNT ELMTS) C C BELOW, PROGRAM CAN ACCESS FFT COMPLEX RESULT (AND FORM COMPARISON, IF KNOWN) DO 80 JB=1,NTBK K=(JB-1)*NCNT CALL MFREAD(BUFA,NRBK,JB) C READ 'RECDS' OF NRBK LENGTH, TOTALLING NTBK (RECOMPUTED BY MFPAR) C (NOTE, CYBER MFREAD/MFWRIT (USING READMS/WRITMS) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C DO 80 I=1,NCNT INDEX=J-1 IF(IPRINT.LE.0)GO TO 80 WRITE(LP,940)INDEX,CBUFA(I) 940 FORMAT(1X,I5,2X,2E13.4) 80 CONTINUE C C BELOW, INVERT ISGN AND IDIR FOR INVERSE TRANSFORM (COMPLEX-TO-REAL) 75 ISGN=-ISGN IDIR=-IDIR SCAL=1./SIZE IF(IRMF.NE.0) X CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C EITHER ROUTINE RMFFT INVERSE TRANSFORMS ARRAY TO PACKED REAL C IF(IRMF.EQ.0) X CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C OR ROUTINE CMFFT INVERSE TRANSFORMS ARRAY C IF(IPRINT.LE.0)GO TO 85 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) WRITE(LP,960) 960 FORMAT(8H INDEX,4X,8HFFT/2**M,6X,5HINPUT,10X,4HDIFF) C 85 IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRBK IF(IRMF.EQ.0)NCNT=NCNT/2 C HELPER ROUTN, NTBK TOTAL NUMB OF NRBK REALS IN FFT BLOCK C (NCNT IS NUMBER OF ELMTS IN FFT BLOCK, REAL OR CMPLX) C C BELOW, COMPARES FFT INVERSE RESULT WITH INITIAL RANDOM INPUT DIFM=0. VALU=0. DO 90 JB=1,NTBK CALL MFREAD(BUFA,NRBK,JB) C READ 'RECDS' OF NRBK LENGTH, TOTALLING NTBK (RECOMPUTED BY MFPAR) C (NOTE, CYBER MFREAD/MFWRIT (USING READMS/WRITMS) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C DO 90 I=1,NCNT IF(IRMF.NE.0)RM=BUFA(I) IF(IRMF.EQ.0)RM=REAL(CBUFA(I)) DIF=ABS(RM-VALU) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.GT.0)WRITE(LP,990)I,RM,VALU,DIF 990 FORMAT(1X,I5,3(2X,E13.4)) VALU=VALU+VINC 90 CONTINUE C PRINT INVERSE RESULTS (SHOULD BE SAME AS INITIAL RAMP) C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 950 FORMAT(10H MAX DIFF ,E11.4,1X, X 8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) IF(DIFM.GT.DIFMG)DIFMG=DIFM C STOP C 1000 WRITE(LP,980)IERR 980 FORMAT(25H IBEX FORCED TOO SMALL OR, X 30H NOT ALL /MFINT/ CORRECT, IERR,I4) STOP END SUBROUTINE MFREAD(BUFA,NB,JB) C C CONTROL DATA 6000 AND CYBER MASS STORE I/O ROUTINES FOR FFT C C (LOGICAL UNIT LUN IN COMMON/FFTCOM/ MUST HAVE BEEN OPENED C PREVIOUSLY; EG. CALL OPENMS(LUN,INDXARRAY,NREC+1,0) C WHERE NREC=2**(M-IBEX+1) IF IPAK=1 OR LESS IF IPAK=0 OR -1) C C SEE ALSO ALTERNATIVE SUBROUTINES USING EXTENDED CORE OR LCM C (IN ADDITION, GETW, PUTW OR READM, WRITEM MACROS CAN BE USED) C C READ BLOCK, INDEX JB, FROM MASS STORE TO BUFA, NB REAL VALUES C COMMON/FFTCOM/LUN,MINDX(512) REAL BUFA(NB) C CALL READMS(LUN,BUFA,NB,JB) RETURN C ENTRY MFWRIT C WRITE BLOCK, INDEX JB, FROM BUFA TO MASS STORE, NB REAL VALUES C CALL WRITMS(LUN,BUFA,NB,JB,-1,0) RETURN C END C PROGRAM LCMTOM(INPUT,OUTPUT,TAPE60=INPUT,TAPE5=OUTPUT) C C CONTROL DATA 6000 AND CYBER EXTENDED CORE/LCM FFT TEST PROGRAM C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C C LEVEL 3, LBUFA COMMON/FFTCOM/LBUFA(32768) C C LBUFA IN EXTENDED CORE/LCM SIMULATES FAST MASS STORE C DIMENSION LBUFA AS LARGE AS NECESSARY FOR RESULTANT ARRAY C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE C C COMMON AREAS /MFARG/,/MFVAL/,/MFINT/ USEFUL FOR RUNNING MASS STORE FFT C /MFARG/ HOLDS ARGUMENTS USED IN FFT CALLES, MOSTLY EXPONENTS C HELPER ROUTINE MFPAR COMPUTES VALUES FROM /MFARG/ INTO C /MFVAL/ (REALS AS SOME LARGE), /MFINT/ (INTEGER EQUIVALENTS IF POSS) C OR CAN REVERSE-COMPUTE SOME /MFARG/ FROM /MFVAL/ C SEE COMMENTS, ROUTINE MFPAR. C COMPLEX CBUFA(4096) REAL BUFA(8192) EQUIVALENCE (CBUFA(1),BUFA(1)) C C BUFA()=CBUFA() IS WORKING AREA IN CORE STORE FOR FFT AND PROGRAM C LP=5 IPRINT=0 C LP IS PRINTER LOGICAL UNIT, IPRINT=+1 COPIOUS, 0 MAX DIFFERENCES ONLY C IRMF=-1 C IRMF=-1 REAL ROUTINE RMFFT TEST, 0 COMPLEX ROUTINE CMFFT TEST C ISGN=-1 IDIR=-1 IPAK=1 C FFT ARGS, ISGN=+/- 1, IDIR=-1 (RMFFT), IDIR=1 OR 0 (CMFFT) C IPAK=1, 0 OR -1 (RMFFT), NOT USED (CMFFT) C C BELOW, PRINT HEADINGS FOR TEST OUTPUT IF(IPRINT.LE.0)WRITE(LP,910)IPRINT,IRMF 910 FORMAT(31H1MASS STORE FFT TEST - IPRINT =,I3, X 25H (1=COPIOUS,0=MAX DIFFS),, X 9H IRMF =,I3,28H (0=CMFFT TEST,1=RMFFT TEST) /) DIFMG=0. C MEXA(1)=8 MEXA(2)=6 NDIM=2 IBEX=7 ICEX=13 C MORE FFT ARGS, 2**8 ROWS OF 2**6 ELMTS, 2 DIMEN, C FFT MASS STORE BLOCKS 2**IBEX REALS, BUFA 2**ICEX REALS C IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1 C HELPER ROUTINE, NCNT NUM OF ELMTS IN FIRST DIMEN, NTD1 TOTAL C M=MFSUM(MEXA,NDIM,99) SCAL=1. VALU=0. VINC=1./SIZE IF(IRMF.EQ.0)GO TO 50 C SWITCH FOR COMPLEX ROUTINE CMFFT AT 50, REAL RMFFT BELOW C DO 40 JB=1,NTD1 DO 35 I=1,NCNT BUFA(I)=VALU 35 VALU=VALU+VINC CALL MFWRIT(BUFA,NRD1,JB) 40 CONTINUE C LOAD RAMP FUNCTN IN REAL ARRAY IN 'RECDS' OF NRD1 LENGTH C (NOTE, 'LCM' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN CYBER MASS STORE) C CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C REAL MASS STORE ROUTINE RMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT GO TO 70 C C BELOW, USE COMPLEX ROUTINE CMFFT, NCNT NUM OF CMPLX ELMTS IN FFT BLOCK 50 NCNT=NCNT/2 DO 60 JB=1,NTD1 DO 55 I=1,NCNT CBUFA(I)=CMPLX(VALU,0.) 55 VALU=VALU+VINC CALL MFWRIT(BUFA,NRD1,JB) 60 CONTINUE C LOAD RAMP FUNCTN IN COMPLEX ARRAY IN 'RECDS' OF NRD1 LENGTH C (NOTE, 'LCM' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN CYBER MASS STORE) C CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C COMPLEX MASS STORE ROUTINE CMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT C 70 IF(IPRINT.LE.0)GO TO 75 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 920 FORMAT(8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) WRITE(LP,930) 930 FORMAT(8H INDEX,12X,3HFFT) C IERR=MFPAR(-IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1/2 C HELPER ROUTINE, NCNT NUM OF ELMTS IN FIRST DIMEN, NTD1 TOTAL C (NOTE IRMF=+1 FOR DATA IN COMPLEX STATE, NCNT ELMTS) C C BELOW, PROGRAM CAN ACCESS FFT COMPLEX RESULT (AND FORM COMPARISON, IF KNOWN) DO 80 JB=1,NTD1 K=(JB-1)*NCNT CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF NRD1 LENGTH, TOTALLING NTD1 (RECOMPUTED BY MFPAR) C (NOTE, 'LCM' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN CYBER MASS STORE) C DO 80 I=1,NCNT INDEX=J-1 IF(IPRINT.LE.0)GO TO 80 WRITE(LP,940)INDEX,CBUFA(I) 940 FORMAT(1X,I5,2X,2E13.4) 80 CONTINUE C C BELOW, INVERT ISGN AND IDIR FOR INVERSE TRANSFORM (COMPLEX-TO-REAL) 75 ISGN=-ISGN IDIR=-IDIR SCAL=1./SIZE IF(IRMF.NE.0) X CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C EITHER ROUTINE RMFFT INVERSE TRANSFORMS ARRAY TO PACKED REAL C IF(IRMF.EQ.0) X CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C OR ROUTINE CMFFT INVERSE TRANSFORMS ARRAY C IF(IPRINT.LE.0)GO TO 85 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) WRITE(LP,960) 960 FORMAT(8H INDEX,4X,8HFFT/2**M,6X,5HINPUT,10X,4HDIFF) C 85 IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1 IF(IRMF.EQ.0)NCNT=NCNT/2 C HELPER ROUTINE, NCNT NUM OF ELMTS IN FIRST DIMEN, NTD1 TOTAL C (NCNT IS NUMBER OF ELMTS IN FFT BLOCK, REAL OR CMPLX) C C BELOW, COMPARES FFT INVERSE RESULT WITH INITIAL RANDOM INPUT DIFM=0. VALU=0. DO 90 JB=1,NTD1 CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF NRD1 LENGTH, TOTALLING NTD1 (RECOMPUTED BY MFPAR) C (NOTE, 'LCM' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN CYBER MASS STORE) C DO 90 I=1,NCNT IF(IRMF.NE.0)RM=BUFA(I) IF(IRMF.EQ.0)RM=REAL(CBUFA(I)) DIF=ABS(RM-VALU) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.GT.0)WRITE(LP,990)I,RM,VALU,DIF 990 FORMAT(1X,I5,3(2X,E13.4)) VALU=VALU+VINC 90 CONTINUE C PRINT INVERSE RESULTS (SHOULD BE SAME AS INITIAL RAMP) C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 950 FORMAT(10H MAX DIFF ,E11.4,1X, X 8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) IF(DIFM.GT.DIFMG)DIFMG=DIFM C STOP C 1000 WRITE(LP,980)IERR 980 FORMAT(25H IBEX FORCED TOO SMALL OR, X 30H NOT ALL /MFINT/ CORRECT, IERR,I4) STOP END SUBROUTINE MFREAD(BUFA,NB,JB) C C CONTROL DATA 6000 AND CYBER EXTENDED CORE STORE I/O ROUTINES FOR FFT C C (EXTENDED CORE OR LCM TAKES PLACE OF MASS STORE - C DIMENSION LBUFA AS LARGE AS NECESSARY FOR LARGE ARRAYS) C C ALTERNATIVELY, EXTENDED CORE USE COULD BE COMBINED WITH C READM/WRITEM MACROS TO ACCESS LARGER FILE WHEN NECESSARY C (USE VIRTUAL MEMORY ALGORITHM - MANY SECTORS HELD IN C EXTENDED CORE AND ONLY ACCESSED FROM DISC IF NOT PRESENT). C C READ BLOCK, INDEX JB, FROM EXTENDED CORE TO BUFA, NB REAL VALUES C LEVEL 3, LBUFA COMMON/FFTCOM/LBUFA(32768) REAL BUFA(NB) C CALL MOVLEV(LBUFA((JB-1)*NB+1),BUFA,NB) RETURN C ENTRY MFWRIT C WRITE BLOCK, INDEX JB, FROM BUFA TO EXTENDED CORE, NB REAL VALUES C CALL MOVLEV(BUFA,LBUFA((JB-1)*NB+1),NB) RETURN C END C C PDP 11 MASS STORE I/O FFT SAMPLE TEST PROGRAM C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C C COMMON/FFTCOM/LUN C C COMMON /FFTCOM/ HOLDS LOGICAL UNIT NUMBER FOR MASS STORE I/O C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE C C COMMON AREAS /MFARG/,/MFVAL/,/MFINT/ USEFUL FOR RUNNING MASS STORE FFT C /MFARG/ HOLDS ARGUMENTS USED IN FFT CALLES, MOSTLY EXPONENTS C HELPER ROUTINE MFPAR COMPUTES VALUES FROM /MFARG/ INTO C /MFVAL/ (REALS AS SOME LARGE), /MFINT/ (INTEGER EQUIVALENTS IF POSS) C OR CAN REVERSE-COMPUTE SOME /MFARG/ FROM /MFVAL/ C SEE COMMENTS, ROUTINE MFPAR. C COMPLEX CBUFA(1024) REAL BUFA(2048) EQUIVALENCE (CBUFA(1),BUFA(1)) C C BUFA()=CBUFA() IS WORKING AREA IN CORE STORE FOR FFT AND PROGRAM C LUN=1 C LUN IS LOGICAL UNIT FOR PDP 11 MASS STORE I/O C LP=5 IPRINT=0 C LP IS PRINTER LOGICAL UNIT, IPRINT=+1 COPIOUS, 0 MAX DIFFERENCES ONLY C IRMF=-1 C IRMF=-1 REAL ROUTINE RMFFT TEST, 0 COMPLEX ROUTINE CMFFT TEST C ISGN=-1 IDIR=-1 IPAK=1 C FFT ARGS, ISGN=+/- 1, IDIR=-1 (RMFFT), IDIR=1 OR 0 (CMFFT) C IPAK=1, 0 OR -1 (RMFFT), NOT USED (CMFFT) C C BELOW, PRINT HEADINGS FOR TEST OUTPUT IF(IPRINT.LE.0)WRITE(LP,910)IPRINT,IRMF 910 FORMAT(31H1MASS STORE FFT TEST - IPRINT =,I3, X 25H (1=COPIOUS,0=MAX DIFFS),, X 9H IRMF =,I3,28H (0=CMFFT TEST,1=RMFFT TEST) /) DIFMG=0. C MEXA(1)=8 MEXA(2)=6 NDIM=2 IBEX=7 ICEX=11 C MORE FFT ARGS, 2**8 ROWS OF 2**6 ELMTS, 2 DIMEN, C FFT MASS STORE BLOCKS 2**IBEX REALS, BUFA 2**ICEX REALS C IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 CALL ASSIGN(LUN,'FFTEST.DAT',0) NWD=NRBK*2 DEFINE FILE LUN(NFBK,NWD,U,INDX) C PDP 11 MASS STORE OPENED WITH NUM REC=NFBK, NRBK*2 WORDS PER REC C (NOTE HELPER ROUTN MFPAR RETURNS NFBK AS MAXIMUM FILE SIZE) C NCNT=NRBK C HELPER ROUTINE, NCNT NUM OF ELMTS IN FFT BLOCK, NTBK TOTAL BLOCKS C M=MFSUM(MEXA,NDIM,99) SCAL=1. VALU=0. VINC=1./SIZE IF(IRMF.EQ.0)GO TO 50 C SWITCH FOR COMPLEX ROUTINE CMFFT AT 50, REAL RMFFT BELOW C DO 40 JB=1,NTBK DO 35 I=1,NCNT BUFA(I)=VALU 35 VALU=VALU+VINC CALL MFWRIT(BUFA,NRBK,JB) 40 CONTINUE C LOAD RAMP FUNCTN IN REAL ARRAY IN 'RECDS' OF NRBK LENGTH C (NOTE, PDP 11 MFREAD/MFWRIT (USING FORTRAN I/O) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C REAL MASS STORE ROUTINE RMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT GO TO 70 C C BELOW, USE COMPLEX ROUTINE CMFFT, NCNT NUM OF CMPLX ELMTS IN FFT BLOCK 50 NCNT=NCNT/2 DO 60 JB=1,NTBK DO 55 I=1,NCNT CBUFA(I)=CMPLX(VALU,0.) 55 VALU=VALU+VINC CALL MFWRIT(BUFA,NRBK,JB) 60 CONTINUE C LOAD RAMP FUNCTN IN COMPLEX ARRAY IN 'RECDS' OF NRBK LENGTH C (NOTE, PDP 11 MFREAD/MFWRIT (USING FORTRAN I/O) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C COMPLEX MASS STORE ROUTINE CMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT C 70 IF(IPRINT.LE.0)GO TO 75 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 920 FORMAT(8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) WRITE(LP,930) 930 FORMAT(8H INDEX,12X,3HFFT) C IERR=MFPAR(-IRMF,0) IF(IERR.NE.0)GO TO 1000 IF(IERR.NE.0)GO TO 1000 NCNT=NRBK/2 C HELPER ROUTN, NTBK TOTAL NUMB OF NRBK REALS IN FFT BLOCK C (NOTE IRMF=+1 FOR DATA IN COMPLEX STATE, NCNT ELMTS) C C BELOW, PROGRAM CAN ACCESS FFT COMPLEX RESULT (AND FORM COMPARISON, IF KNOWN) DO 80 JB=1,NTBK K=(JB-1)*NCNT CALL MFREAD(BUFA,NRBK,JB) C READ 'RECDS' OF NRBK LENGTH, TOTALLING NTBK (RECOMPUTED BY MFPAR) C (NOTE, PDP 11 MFREAD/MFWRIT (USING FORTRAN I/O) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C DO 80 I=1,NCNT INDEX=J-1 IF(IPRINT.LE.0)GO TO 80 WRITE(LP,940)INDEX,CBUFA(I) 940 FORMAT(1X,I5,2X,2E13.4) 80 CONTINUE C C BELOW, INVERT ISGN AND IDIR FOR INVERSE TRANSFORM (COMPLEX-TO-REAL) 75 ISGN=-ISGN IDIR=-IDIR SCAL=1./SIZE IF(IRMF.NE.0) X CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C EITHER ROUTINE RMFFT INVERSE TRANSFORMS ARRAY TO PACKED REAL C IF(IRMF.EQ.0) X CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C OR ROUTINE CMFFT INVERSE TRANSFORMS ARRAY C IF(IPRINT.LE.0)GO TO 85 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) WRITE(LP,960) 960 FORMAT(8H INDEX,4X,8HFFT/2**M,6X,5HINPUT,10X,4HDIFF) C 85 IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRBK IF(IRMF.EQ.0)NCNT=NCNT/2 C HELPER ROUTN, NTBK TOTAL NUMB OF NRBK REALS IN FFT BLOCK C (NCNT IS NUMBER OF ELMTS IN FFT BLOCK, REAL OR CMPLX) C C BELOW, COMPARES FFT INVERSE RESULT WITH INITIAL RANDOM INPUT DIFM=0. VALU=0. DO 90 JB=1,NTBK CALL MFREAD(BUFA,NRBK,JB) C READ 'RECDS' OF NRBK LENGTH, TOTALLING NTBK (RECOMPUTED BY MFPAR) C (NOTE, PDP 11 MFREAD/MFWRIT (USING FORTRAN I/O) CANNOT ACCEPT 'RECDS' C OF DIFFERENT LENGTH; OTHERWISE COULD USE NTD1 'RECDS' OF NRD1 HERE) C DO 90 I=1,NCNT IF(IRMF.NE.0)RM=BUFA(I) IF(IRMF.EQ.0)RM=REAL(CBUFA(I)) DIF=ABS(RM-VALU) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.GT.0)WRITE(LP,990)I,RM,VALU,DIF 990 FORMAT(1X,I5,3(2X,E13.4)) VALU=VALU+VINC 90 CONTINUE C PRINT INVERSE RESULTS (SHOULD BE SAME AS INITIAL RAMP) C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 950 FORMAT(10H MAX DIFF ,E11.4,1X, X 8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) IF(DIFM.GT.DIFMG)DIFMG=DIFM C STOP C 1000 WRITE(LP,980)IERR 980 FORMAT(25H IBEX FORCED TOO SMALL OR, X 30H NOT ALL /MFINT/ CORRECT, IERR,I4) STOP END SUBROUTINE MFREAD(BUFA,NB,JB) C C PDP 11 FORTRAN DIRECT ACCESS READ ROUTINE FOR FFT C C (LOGICAL UNIT LUN IN COMMON/FFTCOM/ MUST HAVE BEEN OPENED C PREVIOUSLY; EG. CALL ASSIGN(LUN,'FILENAME',0) C AND DEFINE FILE LUN(NREC,NWD,U,INDX) C WHERE NWD=2**(IBEX+1) AND NREC=2**(M-IBEX+1) OR LESS IF IPAK=0 OR -1) C C SEE ALSO ALTERNATIVE, FAST MACRO I/O SUBROUTINES C (THESE ARE TO BE PREFERRED, SINCE SPEED 2 TO 10 TIMES BETTER) C C READ BLOCK, INDEX JB, FROM MASS STORE TO BUFA, NB REAL VALUES C COMMON/FFTCOM/LUN REAL BUFA(NB) C READ(LUN'JB)BUFA RETURN C END SUBROUTINE MFWRIT(BUFA,NB,JB) C C PDP 11 FORTRAN DIRECT ACCESS WRITE ROUTINE FOR FFT C C (LOGICAL UNIT LUN IN COMMON/FFTCOM/ MUST HAVE BEEN OPENED C PREVIOUSLY; EG. CALL ASSIGN(LUN,'FILENAME',0) C AND DEFINE FILE LUN(NREC,NWD,U,INDX) C WHERE NWD=2**(IBEX+1) AND NREC=2**(M-IBEX+1) OR LESS IF IPAK=0 OR -1) C C SEE ALSO ALTERNATIVE, FAST MACRO I/O SUBROUTINES C (THESE ARE TO BE PREFERRED, SINCE SPEED 2 TO 10 TIMES BETTER) C C WRITE BLOCK, INDEX JB, FROM BUFA TO MASS STORE, NB REAL VALUES C COMMON/FFTCOM/LUN REAL BUFA(NB) C WRITE(LUN'JB)BUFA RETURN C END C C PDP 11 FAST MACRO I/O FFT SAMPLE TEST PROGRAM C (REQUIRES CALL TO SYSTEM MACRO TO OPEN FILE FOR I/O - SEE LINE 70) C C NOTE THAT FAST MACRO I/O IS MORE EFFEICIENT THAN STANDARD FORTRAN I/O C C NOTE WELL THAT TYPE COMPLEX DATA MUST EXIST AS ALTERNATING C REAL/IMAG/REAL/IMAG... ELEMENTS, BOTH IN MASS STORE AND IN FORTRAN C WORKING ARRAY BUFA; IN THIS FFT, DIFFERENT SUBROUTINES WILL SET C DIFFERENT TYPE (REAL OR COMPLEX) FOR ARRAY BUFA. C C COMMON/FFTCOM/IFDB,IOERR C C COMMON /FFTCOM/ HOLDS FDB ADDRESS FOR MACRO I/O (RSX11M), CHANNEL (RT11) C (SEE COMMENTS IN FAST MACRO ROUTINE MFREAD/MFWRIT) C COMMON/MFARG/MEXA(4),NDIM,ISGN,IDIR,SCAL,IBEX,ICEX,IPAK COMMON/MFVAL/DIMA(4),TDM1,RDM1,FBLK,TBLK,RBLK,RCOR,SIZE COMMON/MFINT/NDMA(4),NTD1,NRD1,NFBK,NTBK,NRBK,NRCR,NSZE C C COMMON AREAS /MFARG/,/MFVAL/,/MFINT/ USEFUL FOR RUNNING MASS STORE FFT C /MFARG/ HOLDS ARGUMENTS USED IN FFT CALLES, MOSTLY EXPONENTS C HELPER ROUTINE MFPAR COMPUTES VALUES FROM /MFARG/ INTO C /MFVAL/ (REALS AS SOME LARGE), /MFINT/ (INTEGER EQUIVALENTS IF POSS) C OR CAN REVERSE-COMPUTE SOME /MFARG/ FROM /MFVAL/ C SEE COMMENTS, ROUTINE MFPAR. C COMPLEX CBUFA(1024) REAL BUFA(2048) EQUIVALENCE (CBUFA(1),BUFA(1)) C C BUFA()=CBUFA() IS WORKING AREA IN CORE STORE FOR FFT AND PROGRAM C LUN=1 C LUN IS LOGICAL UNIT FOR PDP 11 MASS STORE I/O C LP=5 IPRINT=0 C LP IS PRINTER LOGICAL UNIT, IPRINT=+1 COPIOUS, 0 MAX DIFFERENCES ONLY C IRMF=-1 C IRMF=-1 REAL ROUTINE RMFFT TEST, 0 COMPLEX ROUTINE CMFFT TEST C ISGN=-1 IDIR=-1 IPAK=1 C FFT ARGS, ISGN=+/- 1, IDIR=-1 (RMFFT), IDIR=1 OR 0 (CMFFT) C IPAK=1, 0 OR -1 (RMFFT), NOT USED (CMFFT) C C BELOW, PRINT HEADINGS FOR TEST OUTPUT IF(IPRINT.LE.0)WRITE(LP,910)IPRINT,IRMF 910 FORMAT(31H1MASS STORE FFT TEST - IPRINT =,I3, X 25H (1=COPIOUS,0=MAX DIFFS),, X 9H IRMF =,I3,28H (0=CMFFT TEST,1=RMFFT TEST) /) DIFMG=0. C MEXA(1)=8 MEXA(2)=6 NDIM=2 IBEX=7 ICEX=11 C MORE FFT ARGS, 2**8 ROWS OF 2**6 ELMTS, 2 DIMEN, C FFT MASS STORE BLOCKS 2**IBEX REALS, BUFA 2**ICEX REALS C IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 C (NOTE HELPER ROUTN MFPAR RETURNS NFBK AS MAXIMUM FILE SIZE) C STOP 'ASSIGN AND OPEN FILE HERE' C DELETE ABOVE LINE AND INVOKE SYSTEM MACRO 'OPEN$' (RSX) OR '.OPEN (RT11) C C FOR EXAMPLE, A FORTRAN CALLABLE SUBROUTINE 'MFOPEN' COULD OPEN FILE C 'FFTTEST.DAT', RETURNING IFDB=FDB ADDRESS (RSX11M) IN COMMON/FFTCOM/ C OF CHANNEL NUMBER (RT11), FOR USE BY MACRO MFREAD/MFWRIT, THUS: C C CALL MFOPEN(LUN,'FFTTEST.DAT',IFDB) C IOERR=0 C PRESET IOERR IN /FFTCOM/; ZERO IF NO ERRORS IN I/O C NCNT=NRD1 C HELPER ROUTINE, NCNT NUM OF ELMTS IN 'FIRST' DIMEN, NTD1 TOTAL BLOCKS C M=MFSUM(MEXA,NDIM,99) SCAL=1. VALU=0. VINC=1./SIZE IF(IRMF.EQ.0)GO TO 50 C SWITCH FOR COMPLEX ROUTINE CMFFT AT 50, REAL RMFFT BELOW C DO 40 JB=1,NTD1 DO 35 I=1,NCNT BUFA(I)=VALU 35 VALU=VALU+VINC CALL MFWRIT(BUFA,NRD1,JB) 40 CONTINUE C LOAD RAMP FUNCTN IN REAL ARRAY IN 'RECDS' OF NRD1 LENGTH C (NOTE, 'MACRO' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN FORTRAN MASS STORE) C CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C REAL MASS STORE ROUTINE RMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT GO TO 70 C C BELOW, USE COMPLEX ROUTINE CMFFT, NCNT NUM OF CMPLX ELMTS IN 'FIRST' DIMEN 50 NCNT=NCNT/2 DO 60 JB=1,NTD1 DO 55 I=1,NCNT CBUFA(I)=CMPLX(VALU,0.) 55 VALU=VALU+VINC CALL MFWRIT(BUFA,NRD1,JB) 60 CONTINUE C LOAD RAMP FUNCTN IN COMPLEX ARRAY IN 'RECDS' OF NRD1 LENGTH C (NOTE, 'MACRO' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN FORTRAN MASS STORE) C CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C COMPLEX MASS STORE ROUTINE CMFFT TO TRANSFORM ARRAY TO COMPLEX RESULT C 70 IF(IPRINT.LE.0)GO TO 75 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 920 FORMAT(8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) WRITE(LP,930) 930 FORMAT(8H INDEX,12X,3HFFT) C IERR=MFPAR(-IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1/2 C HELPER ROUTN, NTD1 TOTAL NUMB OF NRD1 REALS IN 'FIRST' DIMEN C (NOTE IRMF=+1 FOR DATA IN COMPLEX STATE, NCNT ELMTS) C C BELOW, PROGRAM CAN ACCESS FFT COMPLEX RESULT (AND FORM COMPARISON, IF KNOWN) DO 80 JB=1,NTD1 K=(JB-1)*NCNT CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF NRD1 LENGTH, TOTALLING NTD1 (RECOMPUTED BY MFPAR) C (NOTE, 'MACRO' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN FORTRAN MASS STORE) C DO 80 I=1,NCNT INDEX=J-1 IF(IPRINT.LE.0)GO TO 80 WRITE(LP,940)INDEX,CBUFA(I) 940 FORMAT(1X,I5,2X,2E13.4) 80 CONTINUE C C BELOW, INVERT ISGN AND IDIR FOR INVERSE TRANSFORM (COMPLEX-TO-REAL) 75 ISGN=-ISGN IDIR=-IDIR SCAL=1./SIZE IF(IRMF.NE.0) X CALL RMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX, IPAK) C EITHER ROUTINE RMFFT INVERSE TRANSFORMS ARRAY TO PACKED REAL C IF(IRMF.EQ.0) X CALL CMFFT (MEXA,NDIM,ISGN,IDIR,SCAL, BUFA,IBEX,ICEX) C OR ROUTINE CMFFT INVERSE TRANSFORMS ARRAY C IF(IPRINT.LE.0)GO TO 85 C BELOW, PRINT HEADINGS FOR TEST OUTPUT WRITE(LP,910)IPRINT,IRMF WRITE(LP,920)NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) WRITE(LP,960) 960 FORMAT(8H INDEX,4X,8HFFT/2**M,6X,5HINPUT,10X,4HDIFF) C 85 IERR=MFPAR(IRMF,0) IF(IERR.NE.0)GO TO 1000 NCNT=NRD1 IF(IRMF.EQ.0)NCNT=NCNT/2 C HELPER ROUTN, NTD1 TOTAL NUMB OF NRD1 REALS IN 'FIRST' DIMEN C (NCNT IS NUMBER OF ELMTS IN 'FIRST' DIMEN, REAL OR CMPLX) C C BELOW, COMPARES FFT INVERSE RESULT WITH INITIAL RANDOM INPUT DIFM=0. VALU=0. DO 90 JB=1,NTD1 CALL MFREAD(BUFA,NRD1,JB) C READ 'RECDS' OF NRD1 LENGTH, TOTALLING NTD1 (RECOMPUTED BY MFPAR) C (NOTE, 'MACRO' MFREAD/MFWRIT CAN ACCEPT 'RECORDS' OF DIFFERENT LENGTH; C SO CAN USE NTD1,NRD1 HERE INSTEAD OF NTBK,NRBK AS IN FORTRAN MASS STORE) C DO 90 I=1,NCNT IF(IRMF.NE.0)RM=BUFA(I) IF(IRMF.EQ.0)RM=REAL(CBUFA(I)) DIF=ABS(RM-VALU) IF(DIF.GT.DIFM)DIFM=DIF IF(IPRINT.GT.0)WRITE(LP,990)I,RM,VALU,DIF 990 FORMAT(1X,I5,3(2X,E13.4)) VALU=VALU+VINC 90 CONTINUE C PRINT INVERSE RESULTS (SHOULD BE SAME AS INITIAL RAMP) C IF(IPRINT.GE.0)WRITE(LP,950)DIFM,NDIM,ISGN,IDIR,IBEX,ICEX,IPAK, X (MEXA(J),J=1,NDIM) 950 FORMAT(10H MAX DIFF ,E11.4,1X, X 8H NDIM =,I3,8H ISGN =,I3,8H IDIR =,I3, X 8H IBEX =,I3,8H ICEX =,I3,8H IPAK =,I3, X 10H MEXA() =,3I5) IF(DIFM.GT.DIFMG)DIFMG=DIFM C STOP C 1000 WRITE(LP,980)IERR 980 FORMAT(25H IBEX FORCED TOO SMALL OR, X 30H NOT ALL /MFINT/ CORRECT, IERR,I4) STOP END ; ; PDP11 RSX11M OR RT11 FAST MACRO I/O ROUTINES FOR FFT ; ; SUBROUTINE MFREAD(BUFA,NB,JB) ; SUBROUTINE MFWRIT(BUFA,NB,JB) ; ;C READ BLOCK, INDEX JB, FROM MASS STORE TO BUFA, NB REAL VALUES ;C WRITE BLOCK, INDEX JB, FROM BUFA TO MASS STORE, NB REAL VALUES ; ; COMMON/FFTCOM/IFDB,IOERR (RSX11 FDB ADDRESS, ERROR) ;OR COMMON/FFTCOM/ICHAN,IOERR (RT11 CHANNEL NUM, ERROR) ; ;NOTE1: FILE MUST BE PROPERLY OPEN FOR READ/WRITE ACCESS AND WITH ; RSX11M FDB ADDRESS OR RT11 CHANNEL NUMBER IN FIRST WORD ; OF COMMON/FFTCOM/ (IE. INVOKE RSX11M OR RT11 OPEN MACROS). ; ;NOTE2: I/O ERRORS, IF THEY OCCUR, ARE RETURNED IN SECOND WORD ; OF COMMON/FFTCOM/. THIS WORD (IOERR) REMAINS UNCHANGED ; IF NO ERROR OCCURS - THUS, IF PRESET TO 0 BEFORE CALLING ; MFREAD/MFWRIT (OR MASS STORE FFT), WILL FINALLY BE ; 0 IF NO ERRORS, OR NON ZERO=LAST ERROR (SEE FOLLOWING LABEL L4:). ; ;NOTE3: NB MUST BE AN INTEGRAL POWER OF 2; 128 OR MORE MOST EFFICIENT ; (NB.LE.64 USES LOCAL 256 WORD JBUF TO HOLD SECTOR; ; WRITE ALWAYS WRITES THIS SECTOR TO FILE; SLOW BUT SAFE). ; ;NOTE4: READY TO ASSEMBLE FOR RSX11M. FOR RT11, ERASE FOLLOWING LINE: RSX=0 ; .IF DF,RSX ; CONDITIONAL SECTION FOR RSX11M (V3) .TITLE MFREAD(RSX11M) .MCALL READ$,WRITE$,WAIT$ .PSECT FFTCOM,RW,D,GBL,REL,OVR IFDB: .WORD 0 ;FDB ADDRESS IOERR: .WORD 0 ;ERROR FLAG (UNCHANGED IF NO ERROR) .PSECT .ENDC ; .IF NDF,RSX ; CONDITIONAL SECTION FOR RT11 (V3) .TITLE MFREAD(RT11) .MCALL .READW,.WRITW ERRBYT=52 .PSECT FFTCOM,RW,D,GBL,REL,OVR ICHAN: .WORD 0 ;CHANNEL NUMBER IOERR: .WORD 0 ;ERROR FLAG (UNCHANGED IF NO ERROR) .PSECT MFREAD,RW,I,LCL,REL,OVR .ENDC ; .GLOBL MFREAD,MFWRIT ; MFREAD: MOV #1,R0 ;MFREAD SETS JSW=1 BR L1 ; MFWRIT: MOV #-1,R0 ;MFWRIT SETS JSW=-1 ; L1: MOV R0,JSW ;HOLD JSW TST (R5)+ ;IGNORE ARGUMENT COUNT MOV (R5)+,R3 ;R3=ADDRESS OF 'BUFA' MOV @(R5)+,R2 ;R2='NB' MOV @(R5)+,R1 ;R1='JB' ; FINISH ACCESSING SUBROUTINE ARGUMENTS ; DEC R1 ;R1=JB-1 ASL R2 ;R2=WORD COUNT, NB*2 MOV R2,R5 ;COPY TO R5 BEQ L6 ;FINISH IF COUNT ZERO CLR R0 ;CLEAR R0 FOR WORD OFFSET CMP R5,#256. ;CHECK WHETHER WHOLE SECTORS BLT L12 ;GO TO L12 IF NOT (MORE COMPLEX) ; ; BELOW, SCALE R1 TO SECTOR OFFSET (ASSUMES NWD POWER OF 2) L10: BIT #256.,R5 ;LOOK FOR BIT AT 256. BNE L11 ;R1 COMPLETE WHEN FOUND ASL R1 ;SCALE R1 ACCORDING TO R5 ASR R5 BR L10 ; ; NOW HAVE R1=SECTOR START (FIRST=0) ; R2=WORD COUNT ; R3=BUFA ADDRESS ; L11: MOV JSW,JSWIO ;SET UP FOR READ/WRITE BGT L13 MOV #-1,SECHLD ;DIRECT WRITE, ENSURE JBUF LOOKS EMPTY L13: JSR PC,INOUT ;CALL DIRECT INPUT/OUTPUT L6: RTS PC ;RETURN FROM SUBROUTINE ; END OF SIMPLE DIRECT INPUT/OUTPUT ; .IF DF,RSX ; CONDITIONAL SECTION FOR RSX11M INOUT: ASL R2 ;RSX11M NEEDS BYTE COUNT=NB*4 INC R1 ;RSX11M SECTOR STARTS WITH 1 MOV R1,SECTL ;HOLD AS LOWER SECTOR VALUE MOV IFDB,R4 ;R4=FDB ADDRESS MOVB F.LUN(R4),R1 ;USE LUN FOR EVENT FLAG ; TST JSWIO BLT L5 ;BRANCH IF WRITE ; MOV F.EFBK+2(R4),R0 ;GET LOW SECTOR OF EOF DEC R0 ;ALLOW FOR HEADER SECTOR CMP R0,SECTL ;TEST IF SECTOR EXISTS YET BLT L7 ;NO READ IF DOES NOT EXIST ; READ$ R4,R3,R2,#SECT,R1 ;FDB,BUF,BYTCNT,SECT,EVFLG ; L4: MOV IFDB,R4 ;R4=FDB ADDRESS MOVB F.LUN(R4),R1 ;USE LUN FOR EVENT FLAG WAIT$ R4,R1 ;WAIT FOR I/O FINISH BCC L7 ;NO ERROR IF CARRY CLEAR ; MOV IFDB,R4 ;R4=FDB ADDRESS MOVB F.ERR(R4),R4 ;HOLD NEGATIVE ERROR CODE MOV R4,IOERR ;IN IOERR IN COMMON/FFTCOM/ L7: RTS PC ; L5: WRITE$ R4,R3,R2,#SECT,R1 ;FDB,BUF,BYTCNT,SECT,EVFLG BR L4 ; SECT: .WORD 0 ;HOLDS SECTOR VALUE (HIGHER, ALWAYS 0) SECTL: .WORD 0 ;(LOWER, COMPUTED) .ENDC ; .IF NDF,RSX ;CONDITIONAL SECTION FOR RT11 INOUT: MOV ICHAN,R4 ;R4=CHANNEL NUMBER ; TST JSWIO BLT L5 ;BRANCH IF WRITE ; .READW #AREA,R4,R3,R2,R1 ;AREA,CHAN,BUF,WDCNT,SECT ; L4: BCC L7 ;NO ERROR IF CARRY CLEAR ; MOVB ERRBYT,R4 ;HOLD ERROR CODE + 1 (TO MAKE NON ZERO) INC R4 ;ERRORS 0,1,2 GO TO 1,2,3 MOV R4,IOERR ;IN IOERR IN COMMON/FFTCOM/ L7: RTS PC ; L5: .WRITW #AREA,R4,R3,R2,R1 ;AREA,CHAN,BUF,WDCNT,SECT BR L4 AREA: .BLKW 10 ;AREA FOR RT11 I/O MACROS USE .ENDC ; ; BELOW, MORE COMPLEX HANDLING OF NWD.LT.256 (PART SECTORS) L12: CLC ROR R1 ;SCALE R1/R0 RIGHT ACCORDING TO R5 ROR R0 ;R0 HOLDS FLOW OUT OF R1 ASL R5 BIT #256.,R5 ;LOOK FOR BIT 256 BNE L20 ;R1/R0 COMPLETE IF FOUND BR L12 ; L20: SWAB R0 ASL R0 ; ; NOW HAVE R0=BYTE OFFSET IN LOCAL BUFFER ; R1=SECTOR REQUIRED ; R2=WORD COUNT ; R3=USER BUFA ADDRESS ; ; BELOW, TRANSFER BETWEEN LOCAL AND USER BUFFER ADD #JBUF,R0 ;R0=JBUF ADDRESS + OFFSET CMP SECHLD,R1 ;CHECK CURRENT SECTOR LOADED BNE L24 ;MUST FIRST LOAD SECTO AT L24 IF NEC L21: TST JSW ;TEST WHETHER READ/WRITE BLT L23 ; ; BELOW, 'READ' PART SECTOR L22: MOV (R0)+,(R3)+ ;COPY LOCAL TO USER BUFA DEC R2 BGT L22 JMP L6 ;FINISH ; ; BELOW, 'WRITE' PART SECTOR L23: MOV (R3)+,(R0)+ ;COPY USER TO LOCAL BUF DEC R2 BGT L23 MOV #-1,JSWIO ;SET UP I/O FOR WRITE JSR PC,LINOUT ;WRITE FROM LOCAL JBUF (SLOW BUT SAFE) JMP L6 ;FINISH ; ; BELOW, LOAD LOCAL JBUF, IF POSSIBLE L24: MOV R1,SECHLD ;HOLD CURRENT SECTOR NUM MOV #1,JSWIO ;SET UP FOR READ JSR PC,LINOUT ;DO LOCAL READ TO JBUF BR L21 ; ; BELOW, LOCAL INPUT/OUTPUT ROUTINE LINOUT: MOV R0,-(SP) ;SAVE REGISTERS R0 TO R3 MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #256.,R2 ;R2=256. FOR WHOLE SECTOR MOV #JBUF,R3 ;R3 IS LOCAL JBUF ADDRESS JSR PC,INOUT ;CALL INOUT ROUTINE MOV (SP)+,R3 ;RESTORE REGISTERS R0 TO R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RTS PC ; ; BELOW, LOCAL VARIABLES JSW: .WORD 0 ;JSW=+1 MFREAD, -1 MFWRIT JSWIO: .WORD 0 ;ACTUAL JSW USED FOR INOUT ROUTINE SECHLD: .WORD -1 ;CURRENT SECTOR LOADED IN JBUF JBUF: .BLKW 256. ;JBUF 256 WORD LOCAL BUFFER FOR NWD.LT.256 ; .END