# ZEBRA and HBOOK benchmark

          Program zevent
    c.....................................................................
    c          This program has been developed to compare the relative
    c          performance of ZEBRA FZ Input/Output versus ROOT.
    c          It creates a data structure (one event) identical to
    c          the ROOT object Event described in root/test/Event.h.
    c
    c          Each Event top level bank has 3 substructures:
    c            lHeader = lq(lEvent-1) : Event header
    c            lTracks = lq(lEvent-2) : Support bank for all tracks
    c            lHist   = lq(lEvent-3) : pointer to histogram bank
    c          The track number itrack is described by:
    c            lTrack = lq(lTracks-itrack)
    c
    c          The program is invoked with
    c              zEvent  nevent  mode
    c          where:
    c             nevent is the number of events to be processed.
    c             mode   can be:
    c             mode = 'create'  create only the Zebra structures
    c                  = 'fzwrite' create + write FZ file
    c                  = 'rzwrite' create + write RZ file
    c                  = 'fzread'  read FZ file
    c                  = 'rzread'  read RZ file
    c                  = 'hfill'   create + fill hbook histograms
    c
    c              Author: Rene Brun
    c.....................................................................
          include "zEvent.h"

          integer npar, nevent, ievent, nuh, iuhead,istat,icycle, lrec
          character *80 gname
          character *8 mode, chtop
          integer isl,iquest,idate,itime,tstart,tend,realtime
          common/slate/isl(40)
          common/quest/iquest(100)

          call hlimit(nwpaw)

          call datime(idate,itime)
          tstart = 3600*isl(4) + 60*isl(5) + isl(6)
          npar = iargc()
          nevent = 1000
          mode = 'create'
          if (npar.gt.0) then
             call getarg(1,gname)
             read(gname,*) nevent
          endif
          if (npar.gt.1) then
             call getarg(2,gname)
             read(gname,*) mode
          endif
          call vzero(lEvent,5)
          lrec = 8000
    c
    c                 Create the Event division and a link area
    c                 Declare bank formats
    c
          call mzdiv(0,EventDiv,'EventDiv',100000,200000,' ')
          call mzlink(0,'/cevent/',lEvent,lHeader,lEvent)
          call mzform('Trak','15F 2I',ioTrack)
          call mzform('Head','3I',ioHeader)
          call mzform('Even','4I 1F',ioEvent)

          if (mode.eq.'fzwrite') then
    c......         Open the Zebra FZoutput file (using C I/O)
             call cfopen(iquest(1),0,lrec,'w',0,'Event.fz',istat)
             call fzfile(1,lrec,'LO')
    c
    c                loop on events (write)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call NewEvent(ievent)
                call fzout(1,EventDiv,lEvent,0,'L',0,0,0)
                call mzwipe(EventDiv)
             enddo
             call fzendo(1,' ')
          elseif (mode.eq.'rzwrite') then
    c......           Open the Zebra RZ output file
             call rzopen(1,chtop,'Event.rz','NWX',lrec,istat)
             call rzmake(1,chtop,1,'I','EVENT',64000,'NX')
    c
    c                loop on events (write)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call NewEvent(ievent)
                call rzout(EventDiv,lEvent,ievent,icycle,' ')
                call mzwipe(EventDiv)
             enddo
             call rzend(chtop)
          elseif (mode.eq.'create') then
    c......           Only create structures
    c                loop on events (create Zebra structures only)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call NewEvent(ievent)
                call mzwipe(EventDiv)
             enddo
          elseif (mode.eq.'fzread') then
    c......           Open the Zebra FZ input file
             call cfopen(iquest(1),0,lrec,'r',0,'Event.fz',istat)
             call fzfile(1,lrec,'L')
    c
    c                loop on events (read)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call fzin(1,EventDiv,lEvent,1,' ',nuh, iuhead)
                call mzwipe(EventDiv)
             enddo
             call fzendi(1,' ')
          elseif (mode.eq.'rzread') then
    c......           Open the Zebra RZ input file
             call rzopen(1,'//LUN1','Event.rz','X',lrec,istat)
             call rzfile(1,'//LUN1','X')
    c
    c                loop on events (rz read)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call rzin(EventDiv,lEvent,1,ievent,1,' ')
                call mzwipe(EventDiv)
             enddo
             call rzend('//LUN1')
          elseif (mode.eq.'hfill') then
    c......           Create and Fill histograms only
             call EventHbook
    c                loop on events (create Zebra structures and fill histograms)
    c
             do ievent = 1,nevent
                if (mod(ievent,50).eq.0) print *, mode,' event=',ievent
                call NewEvent(ievent)
                call EventHfill
                call mzwipe(EventDiv)
             enddo
          else
             print*,' Invalid mode'
          endif
          call datime(idate,itime)
          tend = 3600*isl(4) + 60*isl(5) + isl(6)
          realtime = tend - tstart
          print 1000, mode, realtime, realtime/float(nevent)
    1000  format(a,' total real time= ',i5,' seconds',
         +' realtime/event = ',f8.4,' seconds')
          end

    c___________________________________________________________________________
          subroutine EventHbook
    c
    c           create histograms
    c
          include "zEvent.h"

          call hbook1(hNtrack,    'Ntrack',100,575.,625.,0)
          call hbook1(hNseg,      'Nseg',100,5800.,6200.,0)
          call hbook1(hTemperature,'Temperature',100,19.5,20.5,0)
          call hbook1(hPx,        'Px',100,-4.,4.,0)
          call hbook1(hPy,        'Py',100,-4.,4.,0)
          call hbook1(hPz,        'Pz',100,0.,5.,0)
          call hbook1(hRandom,    'Random',100,0.,1000.,0)
          call hbook1(hMass2,     'Mass2',100,0.,12.,0)
          call hbook1(hBx,        'Bx',100,-0.5,0.5,0)
          call hbook1(hBy,        'By',100,-0.5,0.5,0)
          call hbook1(hMeanCharge,'MeanCharge',100,0.,0.01,0)
          call hbook1(hXfirst,    'Xfirst',100,-40.,40.,0)
          call hbook1(hXlast,     'Xlast',100,-40.,40.,0)
          call hbook1(hYfirst,    'Yfirst',100,-40.,40.,0)
          call hbook1(hYlast,     'Ylast',100,-40.,40.,0)
          call hbook1(hZfirst,    'Zfirst',100,0.,80.,0)
          call hbook1(hZlast,     'Zlast',100,0.,250.,0)
          call hbook1(hCharge,    'Charge',100,-1.5,1.5,0)
          call hbook1(hNpoint,    'Npoint',100,50.,80.,0)
          call hbook1(hValid,     'Valid',100,0.,1.2,0)
          end

    c___________________________________________________________________________
          subroutine EventHfill
    c
    c           fill histograms
    c
          include "zEvent.h"
          integer ntrack, itrack

          ntrack = iq(lEvent+kNtrack)
          call hf1(hNtrack,      float(iq(lEvent+kNtrack)),1.)
          call hf1(hNseg  ,      float(iq(lEvent+kNseg)),1.)
          call hf1(hTemperature ,q(lEvent+kTemperature),1.)

    c            Generate and fill the ntrack track banks
          do itrack = 1,ntrack
             lTrack = lq(lTracks-itrack)
             call hf1(hPx,        q(lTrack+kPx),1.)
             call hf1(hPy,        q(lTrack+kPy),1.)
             call hf1(hPz,        q(lTrack+kPz),1.)
             call hf1(hRandom,    q(lTrack+kRandom),1.)
             call hf1(hMass2,     q(lTrack+kMass2),1.)
             call hf1(hBx,        q(lTrack+kBx),1.)
             call hf1(hBy,        q(lTrack+kBy),1.)
             call hf1(hMeanCharge,q(lTrack+kMeanCharge),1.)
             call hf1(hXfirst,    q(lTrack+kXfirst),1.)
             call hf1(hXlast,     q(lTrack+kXlast),1.)
             call hf1(hYfirst,    q(lTrack+kYfirst),1.)
             call hf1(hYlast,     q(lTrack+kYlast),1.)
             call hf1(hZfirst,    q(lTrack+kZfirst),1.)
             call hf1(hZlast,     q(lTrack+kZlast),1.)
             call hf1(hCharge,    q(lTrack+kCharge),1.)
             call hf1(hNpoint,    float(iq(lTrack+kNpoint)),1.)
             call hf1(hValid,     float(iq(lTrack+kValid)),1.)
          enddo
          end
    c___________________________________________________________________________
          Subroutine NewEvent(ievent)
    c
    c             Create and fill one event
          include "zEvent.h"

          integer hbook,lcid
          common/hcbook/hbook(51)

          integer ievent, ntrack, itrack
          real*4 sigmat,sigmas,random,Rndm

    c           Create the top level Event bank with 3 down links and 3 data words
          call mzbook(EventDiv,lEvent,lEvent,1,'Even',3,3,3,ioEvent,0)
          call rannor(sigmat,sigmas)
          random = Rndm(1)
          ntrack = 600+5*sigmat
          iq(lEvent+kNtrack)     = ntrack
          iq(lEvent+kNseg)       = 10*ntrack + 20*sigmas
          iq(lEvent+kNvertex)    = 1
          iq(lEvent+kFlag)       = random+0.5
          q(lEvent+kTemperature) = random+20

    c            Create the EventHeader bank
          call mzbook(EventDiv,lHeader,lEvent,-1,'Head',0,0,3,ioHeader,0)
          iq (lHeader+kEvtNum) = ievent
          iq(lHeader+kRun)     = 1
          iq(lHeader+kDate)    = 970125

    c            Create the top level bank to support ntrack tracks
          call mzbook(EventDiv,lTracks,lEvent,-2,'Trks',ntrack,ntrack,0,0,0)

    c            Generate and fill the ntrack track banks
          do itrack = 1,ntrack
             call NewTrack(itrack,random)
          enddo

    c          Create histogram at first event. Fill histogram
          if (ievent.eq.1) call hbook1(1000,'hstat',100,0.,1.,0.)
          call hf1(1000,random,1.)
    c
    c          Copy histogram bank pointed by lcid=hbook(11) in lEvent structure
    c
          lcid = hbook(11)
          call mzcopy(0,lcid,EventDiv,lEvent,-3,' ')
          end

    c___________________________________________________________________________
          Subroutine NewTrack(itrack,random)
    c
    c              Create and fill one track
    c
          include "zEvent.h"

          integer itrack, icharge
          real*4 a,b,px,py,random,fRandom,fMass2, Rndm

          call mzbook(EventDiv,lTrack,lTracks,-itrack,'TRAK',0,0,17
         +           ,ioTrack,0)

          call rannor(px,py)
          q(lTrack+kPx) = px
          q(lTrack+kPy) = py
          q(lTrack+kPz) = sqrt(px*px+py*py)
          fRandom = 1000*random
          q(lTrack+kRandom) = fRandom
          if (fRandom .lt. 10) then
             fMass2 = 0.08
          elseif (fRandom .lt. 100) then
             fMass2 = 0.8
          elseif (fRandom .lt. 500) then
             fMass2 = 4.5
          elseif (fRandom .lt. 900) then
             fMass2 = 8.9
          else
             fMass2 = 9.8
          endif
          call Rannor(a,b)
          q(lTrack+kBx) = 0.1*a
          q(lTrack+kBy) = 0.1*b
          q(lTrack+kMeanCharge) = 0.01*Rndm(1)
          call Rannor(a,b)
          q(lTrack+kXfirst) = a*10
          q(lTrack+kXlast)  = b*10
          call Rannor(a,b)
          q(lTrack+kYfirst) = a*12
          q(lTrack+kYlast)  = b*16
          call Rannor(a,b)
          q(lTrack+kZfirst) = 50 + 5*a
          q(lTrack+kZlast)  = 200 + 10*b
          icharge = 3*Rndm(1) -1
          q(lTrack+kCharge)  = icharge
          iq(lTrack+kNpoint) = 60+10*Rndm(1)
          iq(lTrack+kValid)  = 0.6+Rndm(1)
          end