C     Fx compiler version 2.1
CC    TEMPLATE t(1024)
CC    ALIGN a(I,J) WITH t(J)
CC    ALIGN b(I,J) WITH t(J)
CC    ALIGN x(I) WITH t(I)
CC    ALIGN y(I) WITH t(I)
CC    DISTRIBUTE t(BLOCK_CYCLIC(16,64))
C     PDO (j = 1:1024)
C     POUT a(:,j),x(j)
C     LOCAL
C     fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
C     fxlmidx0 = ifxlm(fxxdesc,0,fxloopstart0)
C     DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     a(:,j) = real(j)
C     x(j) = 1.
C     fxlmidx0 = (fxlmidx0 + 1)
C     ENDDO
C     ENDLOCAL
C     ENDPDO
C     y = 0.
C     CALL timer_start()
C     PDO (j = 1:1024)
C     PIN a(:,j),x(j)
C     POUT b(:,j)
C     LOCAL
C     fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
C     fxlmidx0 = ifxlm(fxbdesc,1,fxloopstart0)
C     DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     b(:,j) = a(:,j) * x(j)
C     fxlmidx0 = (fxlmidx0 + 1)
C     ENDDO
C     ENDLOCAL
C     ENDPDO
C     PDO (j = 1:1024)
C     PIN b(:,j)
C     PMERGEVARS result
C     LOCAL
C     PINIT
C     result = 0.
C     fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
C     fxlmidx0 = ifxlm(fxbdesc,1,fxloopstart0)
C     DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     PBODY
C     result = (result + b(:,j))
C     fxlmidx0 = (fxlmidx0 + 1)
C     ENDDO
C     ENDLOCAL
C     PMERGE
C     DO fxp2_mergedepth = 5, 0, (-1)
C     fxp2_idle = fxmerge_step(result,fxp2_rt_result,1024,
C    $fxp2_mergedepth)
C     IF (fxp2_idle.NE.0) THEN
C     result = (result + fxp2_rt_result)
C     ENDIF
C     ENDDO
C     CALL fxmerge_broadcast(result,1024)
C     ENDPDO
C     y = (y + result)
C     forall_clocks = timer_stop()
C     CALL verify(result)
C     y = 0.
C     CALL timer_start()
C     PDO (j = 1:1024)
C     PIN a(:,j),x(j)
C     PMERGEVARS result
C     LOCAL
C     PINIT
C     result = 0.
C     fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
C     fxlmidx0 = ifxlm(fxxdesc,0,fxloopstart0)
C     DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     PBODY
C     result = (result + (a(:,j) * x(j)))
C     fxlmidx0 = (fxlmidx0 + 1)
C     ENDDO
C     ENDLOCAL
C     PMERGE
C     DO fxp3_mergedepth = 5, 0, (-1)
C     fxp3_idle = fxmerge_step(result,fxp3_rt_result,1024,
C    $fxp3_mergedepth)
C     IF (fxp3_idle.NE.0) THEN
C     result = (result + fxp3_rt_result)
C     ENDIF
C     ENDDO
C     CALL fxmerge_broadcast(result,1024)
C     ENDPDO
C     y = (y + result)
C     pdo_clocks = timer_stop()
C     CALL verify(result)
C     CALL prperf(1024,1024,forall_clocks,pdo_clocks)
C     END
      PROGRAM main
      INTEGER fxindex1
      INTEGER fxlmidx0
      INTRINSIC real
      REAL real
      INTEGER fxfirst0
      EXTERNAL left
      REAL left
      INTEGER fxcellid
      INTEGER fxloopstart0
      INTEGER fxcc0
      EXTERNAL fxmerge_step
      INTEGER fxmerge_step
      INTEGER fxp2_idle
      INTEGER fxp3_idle
      INTEGER j
      EXTERNAL fx_procstart
      INTEGER fxstride0
      INTEGER fxlmlast0
      INTRINSIC float
      REAL float
      EXTERNAL right
      REAL right
      EXTERNAL ifxlm
      INTEGER ifxlm
      INTEGER fxindex1_1
      EXTERNAL fx_deinit
      INTEGER fxdistarg
      INTEGER forall_clocks
      EXTERNAL fxmerge_broadcast
      INTEGER fxlmfirst0
      EXTERNAL net_reduce
      EXTERNAL prperf
      INTEGER pdo_clocks
      EXTERNAL fxcl_inita
      EXTERNAL verify
      EXTERNAL fxinitdesc
      EXTERNAL timer_stop
      INTEGER timer_stop
      INTEGER fxlast0
      INTEGER fxlmstride0
      INTEGER fxp2_mergedepth
      INTEGER fxp3_mergedepth
      EXTERNAL ifxceil
      INTEGER ifxceil
      EXTERNAL fx_init
      EXTERNAL fx_set_module_geometry
      EXTERNAL timer_start
      REAL a(1024,16)
      REAL b(1024,16)
      REAL x(16)
      REAL y(16)
      REAL result(1024)
      REAL fxp2_rt_result(1024)
      REAL fxp3_rt_result(1024)
      INTEGER fxadesc(71,2)
      INTEGER fxbdesc(71,2)
      INTEGER fxxdesc(71,1)
      INTEGER fxydesc(71,1)
      INTEGER fxdistarray(6,20)
      COMMON /fxcommon/ fxcellid,fxdistarg
      CALL fx_init(fxcellid,1,1,0,0)
      CALL fx_set_module_geometry(0,0,0,8,8)
      fxdistarg = 0
      fxdistarray(1,1) = 1
      fxdistarray(2,1) = 0
      fxdistarray(3,1) = 16
      fxdistarray(4,1) = 64
      fxdistarray(5,1) = 0
      fxdistarray(6,1) = 0
      CALL fxinitdesc(1,1,fxdistarray,fxydesc)
      fxdistarray(1,1) = 1
      fxdistarray(2,1) = 0
      fxdistarray(3,1) = 16
      fxdistarray(4,1) = 64
      fxdistarray(5,1) = 0
      fxdistarray(6,1) = 0
      CALL fxinitdesc(1,1,fxdistarray,fxxdesc)
      fxdistarray(1,1) = 2
      fxdistarray(2,1) = 0
      fxdistarray(3,1) = 16
      fxdistarray(4,1) = 64
      fxdistarray(5,1) = 0
      fxdistarray(6,1) = 0
      fxdistarray(3,2) = 1024
      CALL fxinitdesc(1,2,fxdistarray,fxbdesc)
      fxdistarray(1,1) = 2
      fxdistarray(2,1) = 0
      fxdistarray(3,1) = 16
      fxdistarray(4,1) = 64
      fxdistarray(5,1) = 0
      fxdistarray(6,1) = 0
      fxdistarray(3,2) = 1024
      CALL fxinitdesc(1,2,fxdistarray,fxadesc)
C     TEMPLATE t(1024)
C     ALIGN a(I,J) WITH t(J)
C     ALIGN b(I,J) WITH t(J)
C     ALIGN x(I) WITH t(I)
C     ALIGN y(I) WITH t(I)
C     DISTRIBUTE t(BLOCK_CYCLIC(16,64))
C     PDO (j = 1:1024)
C     POUT a(:,j),x(j)
C     LOCAL
      fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
      fxlmidx0 = ifxlm(fxxdesc,0,fxloopstart0)
      DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
        DO fxindex1 = 1, 1024, 1
          a(fxindex1,fxlmidx0) = real(j)
        ENDDO
        x(fxlmidx0) = 1.
        fxlmidx0 = (fxlmidx0 + 1)
      ENDDO
C     ENDLOCAL
C     ENDPDO
      CALL fxcl_inita(0,1,1,fxlast0,fxlmlast0,fxcc0,1,fxydesc((
     $fxcellid + 8),1),1024,1,16,fxfirst0,fxlmfirst0)
      DO fxindex1 = fxlmfirst0, fxlmlast0, 1
        y(fxindex1) = 0.
      ENDDO
      CALL timer_start()
C     PDO (j = 1:1024)
C     PIN a(:,j),x(j)
C     POUT b(:,j)
C     LOCAL
      fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
      fxlmidx0 = ifxlm(fxbdesc,1,fxloopstart0)
      DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
        DO fxindex1 = 1, 1024, 1
          b(fxindex1,fxlmidx0) = (a(fxindex1,fxlmidx0) * x(fxlmidx0))
        ENDDO
        fxlmidx0 = (fxlmidx0 + 1)
      ENDDO
C     ENDLOCAL
C     ENDPDO
C     PDO (j = 1:1024)
C     PIN b(:,j)
C     PMERGEVARS result
C     LOCAL
C     PINIT
      DO fxindex1 = 1, 1024, 1
        result(fxindex1) = 0.
      ENDDO
      fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
      fxlmidx0 = ifxlm(fxbdesc,1,fxloopstart0)
      DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     PBODY
        DO fxindex1 = 1, 1024, 1
          result(fxindex1) = (result(fxindex1) + b(fxindex1,fxlmidx0)
     $)
        ENDDO
        fxlmidx0 = (fxlmidx0 + 1)
      ENDDO
C     ENDLOCAL
C     PMERGE
      DO fxp2_mergedepth = 5, 0, (-1)
        fxp2_idle = fxmerge_step(result,fxp2_rt_result,1024,
     $fxp2_mergedepth)
        IF (fxp2_idle.NE.0) THEN
          DO fxindex1 = 1, 1024, 1
            result(fxindex1) = (result(fxindex1) + fxp2_rt_result(
     $fxindex1))
          ENDDO
        ENDIF
      ENDDO
      CALL fxmerge_broadcast(result,1024)
C     ENDPDO
      CALL fxcl_inita(0,1,1,fxlast0,fxlmlast0,fxcc0,1,fxydesc((
     $fxcellid + 8),1),1024,1,16,fxfirst0,fxlmfirst0)
      fxindex1_1 = fxfirst0
      DO fxindex1 = fxlmfirst0, fxlmlast0, 1
        y(fxindex1) = (y(fxindex1) + result(fxindex1_1))
        fxindex1_1 = (fxindex1_1 + 1)
      ENDDO
      forall_clocks = timer_stop()
      CALL verify(result)
      CALL fxcl_inita(0,1,1,fxlast0,fxlmlast0,fxcc0,1,fxydesc((
     $fxcellid + 8),1),1024,1,16,fxfirst0,fxlmfirst0)
      DO fxindex1 = fxlmfirst0, fxlmlast0, 1
        y(fxindex1) = 0.
      ENDDO
      CALL timer_start()
C     PDO (j = 1:1024)
C     PIN a(:,j),x(j)
C     PMERGEVARS result
C     LOCAL
C     PINIT
      DO fxindex1 = 1, 1024, 1
        result(fxindex1) = 0.
      ENDDO
      fxloopstart0 = (MAX(((fxcellid * 16) + 1),1))
      fxlmidx0 = ifxlm(fxxdesc,0,fxloopstart0)
      DO j = fxloopstart0, MIN(((fxcellid * 16) + 16),1024), 1
C     PBODY
        DO fxindex1 = 1, 1024, 1
          result(fxindex1) = (result(fxindex1) + (a(fxindex1,fxlmidx0
     $) * x(fxlmidx0)))
        ENDDO
        fxlmidx0 = (fxlmidx0 + 1)
      ENDDO
C     ENDLOCAL
C     PMERGE
      DO fxp3_mergedepth = 5, 0, (-1)
        fxp3_idle = fxmerge_step(result,fxp3_rt_result,1024,
     $fxp3_mergedepth)
        IF (fxp3_idle.NE.0) THEN
          DO fxindex1 = 1, 1024, 1
            result(fxindex1) = (result(fxindex1) + fxp3_rt_result(
     $fxindex1))
          ENDDO
        ENDIF
      ENDDO
      CALL fxmerge_broadcast(result,1024)
C     ENDPDO
      CALL fxcl_inita(0,1,1,fxlast0,fxlmlast0,fxcc0,1,fxydesc((
     $fxcellid + 8),1),1024,1,16,fxfirst0,fxlmfirst0)
      fxindex1_1 = fxfirst0
      DO fxindex1 = fxlmfirst0, fxlmlast0, 1
        y(fxindex1) = (y(fxindex1) + result(fxindex1_1))
        fxindex1_1 = (fxindex1_1 + 1)
      ENDDO
      pdo_clocks = timer_stop()
      CALL verify(result)
      CALL prperf(1024,1024,forall_clocks,pdo_clocks)
      CALL fx_deinit()
      END
C     errors = 0
C     DO i = 1, 1024, 1
C     IF (result(i).NE.524800.) errors = (errors + 1)
C     ENDDO
C     IF (errors.GT.0) WRITE (unit=6,fmt=*) 'errors=',errors
C     END
      SUBROUTINE verify(result)
      INTEGER fxcellid
      INTEGER i
      EXTERNAL fx_procstart
      INTEGER fxdistarg
      EXTERNAL fxdblcheck
      EXTERNAL net_reduce
      INTEGER errors
      REAL result(1024)
      COMMON /fxcommon/ fxcellid,fxdistarg
      CALL fxdblcheck(fxdistarg,0,'verify')
      errors = 0
      DO i = 1, 1024, 1
        IF (result(i).NE.524800.) THEN
          errors = (errors + 1)
        ENDIF
      ENDDO
      IF (errors.GT.0) THEN
        IF (fxcellid.EQ.0) THEN
          WRITE (unit=6,fmt=*) 'errors=',errors
        ENDIF
      ENDIF
      END
C     pdo_msecs = (real(pdo_clocks) / 2e4)
C     forall_msecs = (real(forall_clocks) / 2e4)
C     flops = ((m * n) * 2.)
C     pdo_mflops = ((flops / pdo_msecs) / 1e3)
C     forall_mflops = ((flops / forall_msecs) / 1e3)
C     WRITE (unit=6,fmt=*) m,n,pdo_clocks,pdo_msecs,pdo_mflops,
C    $forall_clocks,forall_msecs,forall_mflops
C     END
      SUBROUTINE prperf(m,n,forall_clocks,pdo_clocks)
      INTRINSIC real
      REAL real
      INTEGER fxcellid
      REAL forall_msecs
      EXTERNAL fx_procstart
      INTEGER m
      INTEGER n
      REAL flops
      REAL pdo_msecs
      INTEGER fxdistarg
      INTEGER forall_clocks
      REAL forall_mflops
      EXTERNAL fxdblcheck
      EXTERNAL net_reduce
      INTEGER pdo_clocks
      REAL pdo_mflops
      COMMON /fxcommon/ fxcellid,fxdistarg
      CALL fxdblcheck(fxdistarg,0,'prperf')
      pdo_msecs = (real(pdo_clocks) / 2e4)
      forall_msecs = (real(forall_clocks) / 2e4)
      flops = ((m * n) * 2.)
      pdo_mflops = ((flops / pdo_msecs) / 1e3)
      forall_mflops = ((flops / forall_msecs) / 1e3)
      IF (fxcellid.EQ.0) THEN
        WRITE (unit=6,fmt=*) m,n,pdo_clocks,pdo_msecs,pdo_mflops,
     $forall_clocks,forall_msecs,forall_mflops
      ENDIF
      END
