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 #include "bench7.h" #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 INTEGER (A-Z) 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 INTEGER (A-Z) c INTEGER (kind=8) IVAL, MASK16 c c Version for 64-bit words COMMON /POPS/POPS(0:65535) c MASK16 = 65535_8 c POPCNT = POPS(IAND(MASK16,IVAL)) + & POPS(IAND(MASK16,ISHFT(IVAL,16))) + & POPS(IAND(MASK16,ISHFT(IVAL,32))) + & POPS(IAND(MASK16,ISHFT(IVAL,48))) RETURN END #endif CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC #ifdef SW_LEADZ SUBROUTINE INITLZ c Uncomment this routine for machines without leadz hardware. c This routine initializes a 2^16 array to contain the position of c the leading zero of each index. This is used in the LEADZ c subroutine which follows. IMPLICIT INTEGER (A-Z) COMMON /LZCNT/LZCNT(0:65535) 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 RETURN END FUNCTION LEADZ(IVAL) c Uncomment this routine for machines without leadz hardware. c This routine uses the array initialized in INITLZ to find the c leading zero in the first non-zero double byte. IMPLICIT INTEGER (A-Z) INTEGER (kind=8) IVAL, MASK16 c c Version for 64-bit words COMMON /LZCNT/LZCNT(0:65535) MASK16 = 65535_8 c IF (IVAL .GE. ISHFT(1_8,49)) THEN LEADZ = LZCNT(ISHFT(IVAL,-48)) ELSE IF (IVAL .GE. ISHFT(1_8,33)) THEN LEADZ = 16 + LZCNT(IAND(MASK16,ISHFT(IVAL,-32))) ELSE IF (IVAL .GT. 65535) THEN LEADZ = 32 + LZCNT(IAND(MASK16,ISHFT(IVAL,-16))) ELSE LEADZ = 48 + LZCNT(IAND(MASK16,IVAL)) END IF RETURN END #endif 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 #ifdef CRAY WALL = SECONDR() #else WALL = SECNDS(0.0) #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 DOUBLE PRECISION CPUTIME #ifdef CRAY REAL TSECND CPUTIME = TSECND( ) C CPUTIME = RTC() #else REAL*4 ETIME, TARRAY(2) EXTERNAL ETIME CPUTIME = ETIME ( TARRAY ) #endif RETURN END