/*******Test ranks of 100,000 6x8 binary matrices**************
*******Each row a byte from a RNG, overlapping rows*************/
#include "header.h"
#include "macro.h"
/* define a binary matrix */
typedef struct binmatrix {
uniform *row;
int no_row, no_col;
unsigned long mask;
} binmatrix;
/*print the title*/
void rnk_ttl(char *fn, char *test)
{
if( test[0]=='6' ){
puts("\n\t|-------------------------------------------------------------|");
puts("\t|This is the BINARY RANK TEST for 6x8 matrices. From each of |");
puts("\t|six random 32-bit integers from the generator under test, a |");
puts("\t|specified byte is chosen, and the resulting six bytes form a |");
puts("\t|6x8 binary matrix whose rank is determined. That rank can be|");
puts("\t|from 0 to 6, but ranks 0,1,2,3 are rare; their counts are |");
puts("\t|pooled with those for rank 4. Ranks are found for 100,000 |");
puts("\t|random matrices, and a chi-square test is performed on |");
puts("\t|counts for ranks 6,5 and (0,...,4) (pooled together). |");
puts("\t|-------------------------------------------------------------|\n");
}
if( test[1]=='1' ){
puts("\n\t|-------------------------------------------------------------|");
puts("\t|This is the BINARY RANK TEST for 31x31 matrices. The leftmost|");
puts("\t|31 bits of 31 random integers from the test sequence are used|");
puts("\t|to form a 31x31 binary matrix over the field {0,1}. The rank |");
puts("\t|is determined. That rank can be from 0 to 31, but ranks< 28 |");
puts("\t|are rare, and their counts are pooled with those for rank 28.|");
puts("\t|Ranks are found for 40,000 such random matrices and a chisqu-|");
puts("\t|are test is performed on counts for ranks 31,30,28 and <=28. |");
puts("\t|-------------------------------------------------------------|");
}
if( test[1]=='2' ){
puts("\n\t|-------------------------------------------------------------|");
puts("\t|This is the BINARY RANK TEST for 32x32 matrices. A random 32x|");
puts("\t|32 binary matrix is formed, each row a 32-bit random integer.|");
puts("\t|The rank is determined. That rank can be from 0 to 32, ranks |");
puts("\t|less than 29 are rare, and their counts are pooled with those|");
puts("\t|for rank 29. Ranks are found for 40,000 such random matrices|");
puts("\t|and a chisquare test is performed on counts for ranks 32,31,|");
puts("\t|30 and <=29. |");
puts("\t|-------------------------------------------------------------|");
}
printf("\t\tRank test for binary matrices (%s) from %s\n", test, fn);
return;
}
/*compute the rank of a binary matrix*/
int rkbm(binmatrix bm)
{
register int i, j, k, rt=0;
int rank=0;
uniform tmp;
for(k=0; k<bm.no_row; ++k){
i=k;
while( ( (bm.row[i]>>rt)&1 ) == 0 ){
++i;
if( i<bm.no_row ){
continue;
}
else {
++rt;
if( rt<bm.no_col ){
i=k;
continue;
}
}
return rank;
}
++rank;
if( i!=k ){
tmp=bm.row[i];
bm.row[i]=bm.row[k];
bm.row[k]=tmp;
}
for(j=i+1; j<bm.no_row; ++j){
if( ( (bm.row[j] >> rt) & 1 ) == 0 ) continue;
else bm.row[j] ^= bm.row[k];
}
++rt;
}
return rank;
}
/* perform the test and calculate test-stat */
real rnk_stat(char *fn, counter no_mtr, char *test, int rt)
{
real p6[]={.009443, 0.217439, 0.773118};
real p30[]={.0052854502, .1283502644, .5775761902, .2887880952};
binmatrix bm;
register counter i, j;
register int cls, llim;
char cat[2][4]={ {"r<="}, {"r="} };
counter *f;
short df=3;
real pvalue, *p;
real Ef, chsq=0, tmp;
switch(test[1]){
case '1': bm.no_row=bm.no_col=31;bm.mask=pow(2,31)-1;llim=28;p=p30;break;
case '2': bm.no_row=bm.no_col=32;bm.mask=pow(2,32)-1;llim=29; p=p30; break;
default: {
df=2;
bm.no_row=6;
bm.no_col=8;
bm.mask=pow(2,8)-1;
llim=4;
p=p6;
printf("\n\t\t\t bits %2d to %2d\n", 25-rt, 32-rt);
break;
}
}
bm.row=(uniform*)malloc(bm.no_row*sizeof(uniform));
f=(counter*)calloc( (df+1), sizeof(counter));
puts("\n\tRANK\tOBSERVED\tEXPECTED\t(O-E)^2/E\tSUM\n");
for( i=1; i<=no_mtr; ++i ){
/* get the rows of a matrix */
for(j=0; j<bm.no_row; ++j){
switch(test[1]){
case '1': bm.row[j]=( uni(fn)>>1 ); break;
case '2': bm.row[j]=uni(fn); break;
default: bm.row[j]=( uni(fn)>>rt ); break;
}
bm.row[j] &= bm.mask;
}
cls=rkbm(bm);
cls=MAX(llim,cls)-llim;
++f[cls];
}
/* compute chi-square */
for(i=0; i<=df; ++i){
Ef=no_mtr* ( *(p+i) );
tmp=(f[i]-Ef)*(f[i]-Ef)/Ef;
chsq+=tmp;
printf("\t%s%d\t%-12d\t%-12.1f", cat[MIN(1,i)], i+llim, f[i], Ef);
printf("\t%-12.3f\t%-12.3f\n", tmp, chsq);
}
uni("close");
/* cfree(f, (df+1), sizeof(counter));*/
free(bm.row);
pvalue=1-Chisq( df, chsq );
printf("\n\t\tchi-square = %.3f with df = %d;", chsq, df);
printf(" p-value = %.3f\n", pvalue);
printf("\t--------------------------------------------------------------\n");
return pvalue;
}
/* type "6x8", "31x31" or "32x32" (including the quotation mark) to call
each test.*/
void binrnk(char *filename, char *test)
{
counter no_matrices=100000;
short rt=24, not6x8=strncmp(test, "6 x 8", 1);
real *p;
if( not6x8 ){
rt=0;
no_matrices=40000;
}
rnk_ttl(filename, test);
p=(real*)malloc( (rt+1)*sizeof(real) );
do{
p[rt]=rnk_stat(filename, no_matrices, test, rt);
--rt;
}while(rt>=0);
if( not6x8 ) return;
puts("\t TEST SUMMARY, 25 tests on 100,000 random 6x8 matrices");
puts("\t These should be 25 uniform [0,1] random variates:");
for(rt=24; rt>=0; --rt){
if( (rt+1)%5==0 ) puts(" ");
printf("\t%-12.6f", p[rt]);
}
printf("\n\t\tThe KS test for those 25 supposed UNI's yields\n");
printf("\t\t\tKS p-value = %.6f\n", KStest(p,25));
free(p);
return;
}
/*main()
{
binrnk("binc", "6 x 8");
binrnk("binc", "32 x 32");
return;
}*/
syntax highlighted by Code2HTML, v. 0.9.1