CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC C C Following are software versions of the leading zero and popcount C functions needed for those architectures without these features. C It also contains versions of the timing routines. The timing C routines most likely will need to be modified for each C architecture. C C Contents: C INITPC - Popcount table initialization C POPCNT - Popcount function C INITLZ - Leading zero table initialization C LEADZ - Leading zero function C WALL - Wall Clock timer function C CPUTIME - CPU timer function C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC #ifdef SW_POPCNT SUBROUTINE INITPC c Uncomment this routine for machines without popcnt hardware. c This routine initializes a 2^16 array to contain the popcount c of each index. Then the popcount of a 64 bit number can be c performed with four table look-ups. IMPLICIT NONE INTEGER POPS, I, J COMMON /POPS/POPS(0:65535) INTEGER POPS2(0:255) INTEGER POPS3(0:15) c POPS3 contains the popcount of 4 bit indices DATA POPS3/0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4/ c Generate array POPS2 to contain the popcount of 8 bit indices DO 10 I = 0,15 DO 10 J = 0,15 POPS2(I*16+J) = POPS3(I) + POPS3(J) 10 CONTINUE c Finally, generate array POPS to contain the popcount of 16 bit indices DO 20 I = 0,255 DO 20 J = 0,255 POPS(I*256+J) = POPS2(I) + POPS2(J) 20 CONTINUE RETURN END FUNCTION POPCNT(IVAL) c Uncomment this routine for machines without popcnt hardware. c This routine uses the array initialized in INITPC to find the c popcount of a 64-bit number. IMPLICIT NONE INTEGER (kind=8) IVAL INTEGER POPS, POPCNT COMMON /POPS/POPS(0:65535) POPCNT = POPS(IAND(65535_8, IVAL)) + & POPS(IAND(65535_8, ISHFT(IVAL,-16_8))) + & POPS(IAND(65535_8, ISHFT(IVAL,-32_8))) + & POPS(IAND(65535_8, ISHFT(IVAL,-48_8))) RETURN END #endif SW_POPCNT #ifdef SW_LEADZ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c For machines without leadz hardware, define SW_LEADZ 1 at top of file. c 'INITLZ' initializes a 2^16 array to contain the position of c the leading zero of each index. c 'LEADZ' uses the table to handle 64-bit ints cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc SUBROUTINE INITLZ IMPLICIT NONE INTEGER (kind=8) IVAL, BITS48, BITS32, BITS16 INTEGER LZCNT, I, J COMMON / LZCNT / LZCNT(0:65535) COMMON / BITTS / BITS48, BITS32, BITS16 LZCNT(0) = 16 LZCNT(1) = 15 DO 20 I = 2,16 DO 10 J = 2**(I-1),2**I-1 LZCNT(J) = 16-I 10 CONTINUE 20 CONTINUE BITS48 = Z'FFFFFFFFFFFF' BITS32 = Z'FFFFFFFF' BITS16 = Z'FFFF' RETURN END FUNCTION LEADZ(IVAL) c This routine uses the array initialized in INITLZ to find the c leading zero in the first non-zero double byte. IMPLICIT NONE INTEGER (kind=8) IVAL, BITS48, BITS32, BITS16 INTEGER LZCNT, LEADZ COMMON / LZCNT / LZCNT(0:65535) COMMON / BITTS / BITS48, BITS32, BITS16 IF (IVAL .GT. BITS48) THEN LEADZ = LZCNT( IAND(BITS16, ISHFT(IVAL,-48)) ) ELSE IF (IVAL .GT. BITS32) THEN LEADZ = 16 + LZCNT( IAND(BITS16, ISHFT(IVAL,-32)) ) ELSE IF (IVAL .GT. BITS16) THEN LEADZ = 32 + LZCNT( IAND(BITS16, ISHFT(IVAL,-16)) ) ELSE LEADZ = 48 + LZCNT( IAND(BITS16, IVAL) ) END IF RETURN END #endif SW_LEADZ FUNCTION WALL() cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Computes the amount of wall clock time that has elapsed. c c Make suitable changes to provide access to wall clock time c on architecture being used. c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc REAL (kind=8) WALL #ifdef CRAY REAL SECONDR WALL = SECONDR() #else REAL (kind=8) MPI_WTIME WALL = MPI_WTIME() #endif RETURN END FUNCTION CPUTIME() cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Computes the amount of cpu time that has elapsed. c c Make suitable changes to provide access to cpu time on c architecture being used. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc REAL (kind=8) CPUTIME #ifdef CRAY REAL TSECND CPUTIME = TSECND( ) C CPUTIME = RTC() #else REAL*4 ETIME, TARRAY(2) EXTERNAL ETIME CPUTIME = ETIME ( TARRAY ) #endif RETURN END