SUBROUTINE S11 ( A, B, MODULUS, N, Q, M, NUMSIZE, MODBITS ) c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c CVS Info c $Date: 2005/01/10 21:56:21 $ c $Revision: 1.2 $ c $RCSfile: s11.F,v $ c $Name: rel_5 $ c c This subroutine builds the "random" matrices A and B. c c Parameters: c c Provided by calling routine: c MODULUS = A large integer modulus, stored as an array of integers. c N = The size of the data to be multiplied c Q = The size of the grid of PEs, Q x Q c M = The size of the sub-matrices on each PE c NUMSIZE = The number of words used to store an MP integer c (passed in so S11 can declare arrays with exact dimensions) c MODBITS = The number of bits in MODULUS c c Returned by this routine: c A = Matrix of multiple precision numbers c B = Matrix of multiple precision numbers c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Modified for non-shared-memory systems c Each PE fills its own resident sub-matrices of A, B c They are of size M x M, where M = Ceiling(N/Q) c c A(i,j) is bigA(rM+i, cM+j) where this PE is logically row r, col c c so we have the (r,c)-th sub-matrix c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c IMPLICIT NONE c #include "bench11.h" #include C C--CVS variable declaration TYPE CVS sequence character( 160 ) string integer stringend END TYPE CVS C--CVS initilaize variables TYPE( CVS ),save :: CVS_INFO = $ CVS("BMARKGRP $Date: 2005/01/10 21:56:21 $ $Revision: 1.2 $" // $ "$RCSfile: s11.F,v $ $Name: rel_5 $", 0) c INTEGER N, Q, M, NUMSIZE, ABCNUMSIZE, MODBITS c INTEGER MODSIZE, FULLWORDS, EXTRABITS, EXTRABITMASK, NUMRANDS INTEGER FULLWORDS, EXTRABITS, NUMRANDS INTEGER SKIPBITS, BITCTR, WORDCTR INTEGER*8 MODSIZE, ASIZE, BSIZE, EXTRABITMASK c c Arrays to hold the matrices c These are allocated in main M11 at max size, we resize here c MPLONG A ( NUMSIZE, M, M ) MPLONG B ( NUMSIZE, M, M ) MPLONG MODULUS ( NUMSIZE ) c c Array to hold enough bits for one row (N long) of A and B c 2 matrices, N may be 2*MAXMATSIZE c c INTEGER*8 on DEC c INTEGER*8 TEMPBITS ( 0 : (4*MAXMATSIZE*MAXBITSIZE)/64 ) c c Other variables c INTEGER IROW, MYFIRST, MYLAST, RANWDS INTEGER I, J, K INTEGER ROW, COL, Q0, M0, MI, MJ c ABCNUMSIZE = NUMSIZE - MPHL c cccccccccccccc VERBOSE Output ccccccccccccccc IF(VERBOSE .GT. 0) THEN PRINT*, "CALL S11(",N,", modulus, -, -)" PRINT*, " (Set up the matrices)" ENDIF ccccccccccccccccccccccccccccccccccccccccccccccc c MODSIZE = NUMSIZE - MPHL c c Set up counters and mask needed to fill A and B c FULLWORDS = MODBITS / BITSPERWORD EXTRABITS = MOD ( MODBITS, BITSPERWORD ) IF (EXTRABITS .GT. 0) THEN EXTRABITMASK = ISHFT(BITMASK, EXTRABITS - BITSPERWORD) ENDIF c IF(VERBOSE .GT. 0) THEN PRINT*," Modulus has ",MODBITS," bits" PRINT*," Fill the matrices" ENDIF c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Use the random number generator to fill the matrices A and B. c c Place the random bits into the multiple precision numbers which c make up A and B. c c Each PE fills the M x M submatrix of A and of B that resides on that PE. c For each row in its block, the PE generates all the random bits c for that row, and then fills only the appropriate columns of A and B. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c If N < M * Q, be careful to random-fill only the data cells. c Some PEs have some zero rows or cols or both, some may be all zero. c ROW, COL are zero-based indices of this PE in the Q x Q array of PEs. c ROW = MYPE / Q COL = MOD(MYPE, Q) Q0 = N / M M0 = N - M * Q0 c c MI, MJ are loop bounds for I and J c They may be < M for PE on right or bottom edge c MI = M MJ = M c c Initialize the structures for the multi-precision integers c Just the local submatrices c DO 250, I = 1, M DO 250, J = 1, M #if (GMP32 == 0) A(MPALLOC,I,J) = ABCNUMSIZE A(MPSIZE, I,J) = MODSIZE #else A(MPALLOC,I,J) = ABCNUMSIZE + ISHFT( MODSIZE, 32 ) #endif #ifdef GMP A(MPPTR, I,J) = LOC( A(MPDATA,I,J) ) #endif #if (GMP32 == 0) B(MPALLOC,I,J) = ABCNUMSIZE B(MPSIZE, I,J) = MODSIZE #else B(MPALLOC,I,J) = ABCNUMSIZE + ISHFT( MODSIZE, 32 ) #endif #ifdef GMP B(MPPTR, I,J) = LOC( B(MPDATA,I,J) ) #endif 250 CONTINUE c c If N < M * Q, zeroize edges c IF (ROW. EQ. Q0) THEN DO 270, I = M0 + 1, M DO 270, J = 1, M #if (GMP32 == 0) A(MPSIZE,I,J) = 0 B(MPSIZE,I,J) = 0 #else c erase mpsize in upper 32 bits A(MPALLOC,I,J) = IAND ( A(MPALLOC,I,J), BITMASK32 ) B(MPALLOC,I,J) = IAND ( B(MPALLOC,I,J), BITMASK32 ) #endif A(MPDATA,I,J) = 0 B(MPDATA,I,J) = 0 270 CONTINUE MI = M0 END IF c IF (COL. EQ. Q0) THEN DO 280, I = 1, M DO 280, J = M0 + 1, M #if (GMP32 == 0) A(MPSIZE,I,J) = 0 B(MPSIZE,I,J) = 0 #else c erase mpsize in upper 32 bits A(MPALLOC,I,J) = IAND ( A(MPALLOC,I,J), BITMASK32 ) B(MPALLOC,I,J) = IAND ( B(MPALLOC,I,J), BITMASK32 ) #endif A(MPDATA,I,J) = 0 B(MPDATA,I,J) = 0 280 CONTINUE MJ = M0 END IF c IF (ROW. GT. Q0 .OR. COL .GT. Q0) THEN DO 290, I = 1, M DO 290, J = 1, M #if (GMP32 == 0) A(MPSIZE,I,J) = 0 B(MPSIZE,I,J) = 0 #else c erase mpsize in upper 32 bits A(MPALLOC,I,J) = IAND ( A(MPALLOC,I,J), BITMASK32 ) B(MPALLOC,I,J) = IAND ( B(MPALLOC,I,J), BITMASK32 ) #endif A(MPDATA,I,J) = 0 B(MPDATA,I,J) = 0 290 CONTINUE RETURN END IF c c RANWDS 64-bit random binary words will fill a row of A and B c RANWDS = ( (2*N*MODBITS) + 63 ) / 64 c DO 450, I = 1, MI c c Generate random bits for this (global) row # of A and B c in the array TEMPBITS c IROW = I + M * ROW c CALL GET_MY_BDATA64(IROW, 1, 1, RANWDS, 1, -99911, TEMPBITS, * MYFIRST, MYLAST) c c skip bits in TEMPBITS until the ones that go in my subblock c SKIPBITS = (2 * MODBITS) * (COL * M) c c These counters keep track of position in TEMPBITS c WORDCTR = SKIPBITS/64 BITCTR = MOD(SKIPBITS, 64) c DO 400, J = 1, MJ c c Fill the low order words of A(I,J) c DO 300, K = MPDATA, MPDATA + FULLWORDS - 1 #if (BITSPERWORD==64) A(K,I,J) = IOR ( * ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ) WORDCTR = WORDCTR + 1 #else A(K,I,J) = IAND ( * IOR ( ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ), * BITMASK ) BITCTR = BITCTR + BITSPERWORD IF (BITCTR .GE. 64) THEN WORDCTR = WORDCTR + 1 BITCTR = BITCTR - 64 ENDIF #endif 300 CONTINUE c c Partially fill the last word of A(I,J) with EXTRABITS bits c IF (EXTRABITS .NE. 0) THEN K = MPDATA + FULLWORDS c A(K,I,J) = IAND ( * IOR ( ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ), * EXTRABITMASK ) c BITCTR = BITCTR + EXTRABITS IF (BITCTR .GE. 64) THEN WORDCTR = WORDCTR + 1 BITCTR = BITCTR - 64 ENDIF ENDIF c c Fill the low order words of B(I,J) c DO 350, K = MPDATA, MPDATA + FULLWORDS - 1 #if (BITSPERWORD==64) B(K,I,J) = IOR ( * ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ) WORDCTR = WORDCTR + 1 #else B(K,I,J) = IAND ( * IOR ( ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ), * BITMASK ) BITCTR = BITCTR + BITSPERWORD IF (BITCTR .GE. 64) THEN WORDCTR = WORDCTR + 1 BITCTR = BITCTR - 64 ENDIF #endif 350 CONTINUE c c Partially fill the last word of B(I,J) with EXTRABITS bits c IF (EXTRABITS .NE. 0) THEN K = MPDATA + FULLWORDS c B(K,I,J) = IAND ( * IOR ( ISHFT(TEMPBITS(WORDCTR), -BITCTR), * ISHFT(TEMPBITS(WORDCTR+1),64-BITCTR) ), * EXTRABITMASK ) c BITCTR = BITCTR + EXTRABITS IF (BITCTR .GE. 64) THEN WORDCTR = WORDCTR + 1 BITCTR = BITCTR - 64 ENDIF ENDIF 400 CONTINUE ! loop on J c 450 CONTINUE ! loop on I c c Go through the entries of A and B. c If the top order word(s) is zero, reset the usage counter. c This normalizes the form of the multiple precision number. c DO 600, I = 1, M DO 610, J = 1, M c c Skip words in the border of zeros c and work backwards from highest-order limb c #if (GMP32 == 0) ASIZE = A(MPSIZE,I,J) #else ASIZE = ISHFT( A(1,I,J), -32 ) #endif IF (ASIZE .NE. 0) THEN DO 650 K = NUMSIZE, MPDATA, -1 IF (A(K,I,J) .EQ. 0) THEN ASIZE = ASIZE - 1 ELSE GOTO 660 ENDIF 650 CONTINUE 660 CONTINUE #if (GMP32 == 0) A(MPSIZE,I,J) = ASIZE #else A(1,I,J) = IAND(A(1,I,J),BITMASK32) + ISHFT(ASIZE,32) #endif ENDIF c #if (GMP32 == 0) BSIZE = B(MPSIZE,I,J) #else BSIZE = ISHFT( B(1,I,J), -32 ) #endif IF (BSIZE .NE. 0) THEN DO 670 K = NUMSIZE, MPDATA, -1 IF (B(K,I,J) .EQ. 0) THEN BSIZE = BSIZE - 1 ELSE GOTO 680 ENDIF 670 CONTINUE 680 CONTINUE #if (GMP32 == 0) B(MPSIZE,I,J) = BSIZE #else B(1,I,J) = IAND(B(1,I,J),BITMASK32) + ISHFT(BSIZE,32) #endif ENDIF 610 CONTINUE 600 CONTINUE c cccccccccccccc VERBOSE Output ccccccccccccccc c c IF(VERBOSE .GT. 1) THEN IF((VERBOSE .GT. 1) .AND. (MYPE .EQ. 0)) THEN c c Test for consistency by printing out the filled matrices c PRINT*, "S11 Consistency Check - Matrix A:" DO 700, I = 1, M PRINT*, "Row ", I DO 700, J = 1, M CALL MPWRITE(A(1,I,J)) c print* 700 CONTINUE c PRINT*, "S11 Consistency Check - Matrix B:" DO 750, I = 1, M PRINT*, "Row ", I DO 750, J = 1, M CALL MPWRITE(B(1,I,J)) c print* 750 CONTINUE c c STOP ENDIF c cccccccccccccccccccccccccccccccccccccccccccccccc c RETURN END