WSJT-X/lib/downsam9.f90
Bill Somerville f416a52def Make Fortran profiling timer function a callback with a default null implementation
Groundwork for calling the decoders directly from C/C++ threads.

To  access   the  timer   module  timer_module   must  now   be  used.
Instrumented code need  only use the module function  'timer' which is
now a  procedure pointer that  is guaranteed to be  associated (unless
null()  is assigned  to it,  which should  not be  done). The  default
behaviour of 'timer' is to do nothing.

If a  Fortran program  wishes to  profile code it  should now  use the
timer_impl module  which contains a default  timer implementation. The
main program should call 'init_timer([filename])' before using 'timer'
or     calling     routines     that     are     instrumented.      If
'init_timer([filename])'.  If it is called  then an optional file name
may  be  provided  with  'timer.out'  being used  as  a  default.  The
procedure 'fini_timer()' may be called to close the file.

The default  timer implementation is  thread safe if used  with OpenMP
multi-threaded code  so long as  the OpenMP  thread team is  given the
copyin(/timer_private/) attribute  for correct operation.   The common
block /timer_private/ should  be included for OpenMP  use by including
the file 'timer_common.inc'.

The module 'lib/timer_C_wrapper.f90' provides  a Fortran wrapper along
with 'init' and 'fini' subroutines  which allow a C/C++ application to
call timer instrumented  Fortran code and for it  to receive callbacks
of 'timer()' subroutine invocations.  No C/C++ timer implementation is
provided at this stage.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6320 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
2015-12-27 15:40:57 +00:00

88 lines
2.2 KiB
Fortran

subroutine downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2)
!Downsample from id2() into c2() so as to yield nspsd samples per symbol,
!mixing from fpk down to zero frequency. The downsample factor is 432.
use, intrinsic :: iso_c_binding
use FFTW3
use timer_module, only: timer
include 'constants.f90'
integer(C_SIZE_T) NMAX1
parameter (NMAX1=653184)
parameter (NFFT1=653184,NFFT2=1512)
type(C_PTR) :: plan !Pointers plan for big FFT
integer*2 id2(0:8*npts8-1)
real*4, pointer :: x1(:)
complex c1(0:NFFT1/2)
complex c2(0:NFFT2-1)
real s(5000)
logical first
common/patience/npatience,nthreads
data first/.true./
save plan,first,c1,s,x1
df1=12000.0/NFFT1
npts=8*npts8
if(npts.gt.NFFT1) npts=NFFT1 !### Fix! ###
if(first) then
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
! Plan the FFTs just once
!$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
plan=fftwf_alloc_real(NMAX1)
call c_f_pointer(plan,x1,[NMAX1])
x1(0:NMAX1-1) => x1 !remap bounds
call fftwf_plan_with_nthreads(nthreads)
plan=fftwf_plan_dft_r2c_1d(NFFT1,x1,c1,nflags)
call fftwf_plan_with_nthreads(1)
!$omp end critical(fftw)
first=.false.
endif
if(newdat.eq.1) then
x1(0:npts-1)=id2(0:npts-1)
x1(npts:NFFT1-1)=0. !Zero the rest of x1
call timer('FFTbig9 ',0)
call fftwf_execute_dft_r2c(plan,x1,c1)
call timer('FFTbig9 ',1)
nadd=int(1.0/df1)
s=0.
do i=1,5000
j=int((i-1)/df1)
do n=1,nadd
j=j+1
s(i)=s(i)+real(c1(j))**2 + aimag(c1(j))**2
enddo
enddo
newdat=0
endif
ndown=8*nsps8/nspsd !Downsample factor = 432
nh2=NFFT2/2
nf=nint(fpk)
i0=int(fpk/df1)
nw=100
ia=max(1,nf-nw)
ib=min(5000,nf+nw)
call pctile(s(ia),ib-ia+1,40,avenoise)
fac=sqrt(1.0/avenoise)
do i=0,NFFT2-1
j=i0+i
if(i.gt.nh2) j=j-NFFT2
c2(i)=fac*c1(j)
enddo
call four2a(c2,NFFT2,1,1,1) !FFT back to time domain
return
end subroutine downsam9