# # fftl02.rb # # $Id: fftl02.rb,v 1.2 2000/11/27 01:53:56 keiko Exp $ # require "narray" require "numru/dcl" include NumRu include Math #----------------------------------------------------------------------- module Tfftp # # # PURPOSE TO DEMONSTRATE THE USE OF FFTPACK, AND TO # TEST THE PERFORMANCE OF FFTPACK ON ONE # WELL-CONDITIONED PROBLEM. # # USAGE CALL TFFTPK (IERROR) # # ARGUMENTS # # ON OUTPUT IERROR # INTEGER VARIABLE SET TO ZERO IF FFTPACK # CORRECTLY SOLVED THE TEST PROBLEM, AND # ONE IF FFTPACK FAILED. # # I/O IF THE TEST SUCCEEDS(FAILS), THE MESSAGE # # FFTPACK TEST SUCCESSFUL (UNSUCCESSFUL) # # IS WRITTEN ON UNIT 6. IN THE CASE OF FAILURE, # ADDITIONAL MESSAGES ARE WRITTEN IDENTIFYING THE # FAILURE MORE EXPLICITLY. # # PRECISION SINGLE # # REQUIRED LIBRARY NONE # FILES # # LANGUAGE FORTRAN # # HISTORY WRITTEN BY MEMBERS OF THE SCIENTIFIC # COMPUTING DIVISION OF NCAR, # BOULDER COLORADO. # # ALGORITHM FOR EACH OF THE ROUTINES, RFFTF, RFFTB, EZFFTF, # AND EZFFTB IN THE FFTPACK PACKAGE A SIMILAR # TEST IS RUN. AN APPROPIATE VECTOR, FOR WHICH # THE EXACT TRANSFORM IS KNOWN IS USED AS THE # INPUT VECTOR. THE ROUTINE IS CALLED TO PERFORM # THE TRANSFORM. THE CALCULATED TRANSFORM VECTOR # IS COMPARED WITH THE EXACT TRANSFORM TO SEE # WHETHER THE PERFORMANCE CRITERION IS MET WITHIN # THE SPECIFED TOLERANCE. # # FOR RFFTF AND EZFFTF, A REAL VECTOR, THE ELEMEN # WHICH ARE EQUAL TO ONE, IS USED AS INPUT. THE # TRANSFORMED VECTOR HAS THE FIRST ELEMENT EQUAL # TO THE LENGTH OF THE INPUT VECTOR. ALL OTHER # ELEMENTS ARE EQUAL TO ZERO. # # FOR RFFTB AND EZFFTB, THE INPUT VECTOR HAS FIRS # ELEMENT EQUAL TO ONE AND ALL THE OTHER ELEMENTS # EQUAL TO ZERO. THE TRANSFORMED VECTOR HAS ALL # COMPONENTS EQUAL TO ONE. # # PORTABILITY ANSI STANDARD # # N = 36 DIM1 = 2*N+15 DIM2 = 3*N+15 ND2 = N/2 TOL = 0.01 M998 = " FFTPACK TEST SUCCESSFUL\n" M999 = " FFTPACK TEST UNSUCCESSFUL\n" M1001 = " IN FFTPACK, ENTRY RFFTF RESULTS IN ERROR\n" M1002 = " IN FFTPACK, ENTRY RFFTB RESULTS IN ERROR\n" M1003 = " IN FFTPACK, ENTRY EZFFTF RESULTS IN ERROR\n" M1004 = " IN FFTPACK, ENTRY EZFFTB RESULTS IN ERROR\n" # def stores(x) # # FORCES THE ARGUMENT VALUE X TO BE STORED IN MEMORY LOCATION V. # # common /value/ v # v=x # end def trunc(x) # # TRUNC IS A PORTABLE FORTRAN FUNCTION WHICH TRUNCATES A VALUE TO THE # MACHINE SINGLE PRECISION WORD SIZE, REGARDLESS OF WHETHER LONGER # PRECISION INTERNAL REGISTERS ARE USED FOR FLOATING POINT ARITHMETIC IN # COMPUTING THE VALUE INPUT TO TRUNC. THE METHOD USED IS TO FORCE A # STORE INTO MEMORY BY USING A COMMON BLOCK IN ANOTHER SUBROUTINE. # # common /value/ v # stores(x) # trunc=v x.to_f #???? end # # STATEMENT FUNCTION SMALL(EX) IS FOR TESTING WHETHER X IS CLOSE TO ZERO # INDEPENDENTLY OF MACHINE WORD SIZE. SMALL(EX) IS EXACTLY ZERO ONLY IF # ABS(X) .LT. EPS/TOL, WHERE EPS IS THE MACHINE PRECESION AND TOL IS A # TOLERANCE FACTOR USED TO CONTROL THE STRICTNESS OF THE TEST. # def small(ex) trunc(1.0+TOL*ex.abs)-1.0 end def fft_test rldat = NArray.sfloat(N) # # CALL INITIALIZATION ROUTINE FOR RFFTF AND RFFTB. # wrfft = DCL::rffti(N) # # TEST OF RFFTF. # rldat.fill!(1.0) # result = DCL::rfftf(rldat, wrfft) # # TEST RESULTS OF RFFTF # error = (N.to_f - result[0]).abs for i in 1..N-1 error = [error, (result[i]).abs].max end if (small(error) == 0) ier1 = 0 else ier1 = 1 print M1001 end # # TEST OF RFFTB. # rldat.fill!(0.0) rldat[0] = 1.0 # result = DCL::rfftb(rldat, wrfft) # # TEST RESULTS OF RFFTB # error = 0.0 for i in 0..N-1 error = [error, (1.0 - result[i]).abs].max end if (small(error) == 0) ier2 = 0 else ier2 = 1 print M1002 end # # CALL INITIALIZATION ROUTINE EZFFTI FOR EZFFTF AND EZFFTB # wezfft = DCL::ezffti(N) # # TEST OF EZFFTF. # rldat.fill!(1.0) # # azero, a, b = DCL::ezfftf(rldat, wezfft) # # TEST RESULTS OF EZFFTF # error = (azero - 1.0).abs for i in 0..ND2-1 error = [(a[i]).abs + (b[i]).abs, error].max end if (small(error) == 0) ier3 = 0 else ier3 = 1 print M1003 end # # TEST OF EZFFTB. # azero = 1.0 a[0..ND2-1] = 0.0 b[0..ND2-1] = 0.0 # result = DCL::ezfftb(azero, a, b, wezfft) # # TEST RESULTS OF EZFFTB # error = 0.0 for i in 0..N-1 error = [(1.0 - result[i]).abs, error].max end if (small(error) == 0) ier4 = 0 else ier4 = 1 print M1004 end # # ierror = ier1 + ier2 + ier3 + ier4 if (ierror == 0) print M998 else ierror = 1 print M999 end ierror end end include Tfftp ier = Tfftp::fft_test