コード例 #1
0
ファイル: cpu-rs-log-exp-2.c プロジェクト: yszheda/GPU-RSCode
// normalize the column by the pivot value
void normalize_pivot_col(uint8_t *matrix, uint8_t *result, int col, int size)
{
    int row;
    uint8_t pivotValue;

    pivotValue = matrix[ IDC2D(col, col, size) ];
    for(row=0; row<size; row++)
    {
        matrix[ IDC2D(row, col, size)] = gf_div(matrix[ IDC2D(row, col, size) ], pivotValue);
        result[ IDC2D(row, col, size)] = gf_div(result[ IDC2D(row, col, size) ], pivotValue);
    }
}
コード例 #2
0
ファイル: cpu-rs-log-exp-2.c プロジェクト: yszheda/GPU-RSCode
// normalize the row by the pivot value
void normalize_pivot_row(uint8_t *matrix, uint8_t *result, int row, int size)
{
    int col;
    uint8_t pivotValue;

    pivotValue = matrix[ IDC2D(row, row, size) ];
    for(col=0; col<size; col++)
    {
        matrix[ IDC2D(row, col, size)] = gf_div(matrix[ IDC2D(row, col, size) ], pivotValue);
        result[ IDC2D(row, col, size)] = gf_div(result[ IDC2D(row, col, size) ], pivotValue);
    }
}
コード例 #3
0
ファイル: rs.c プロジェクト: chubbymaggie/cb-multios
int cgc_rs_decode(uint8_t *encoded, int n_parity)
{
    poly_t tmp, synd, sigma, pos;
    cgc_memcpy(tmp.terms, encoded, 255);
    tmp.degree = 255;
    rs_calc_synd(&synd, &tmp, n_parity);

    // synd.degree must equal n_parity, e.g. don't eliminate zero terms
    rs_calc_sigma(&sigma, &synd);
    rs_calc_pos(&pos, &sigma);
    rs_calc_omega(&tmp, &synd, &sigma);
    rs_calc_sigma_deriv(&sigma);
    for (int i = 0; i < pos.degree; i++)
    {
        uint8_t x_inv = gf_inverse(gf_exp[(255 - 1 - pos.terms[i]) % 255]);
        uint8_t mag = gf_div(gf_poly_eval(&tmp, x_inv), gf_mul(x_inv, gf_poly_eval(&sigma, x_inv)));
        encoded[255 - 1 - pos.terms[i]] ^= mag;
    }

    // test result for errors
    cgc_memcpy(tmp.terms, encoded, 255);
    tmp.degree = 255;
    rs_calc_synd(&synd, &tmp, n_parity);
    gf_poly_reduce(&synd);
    // if no errors, then we succesfully decoded
    return synd.degree == 0;
}
コード例 #4
0
ファイル: poly.c プロジェクト: enascimento/supercop
poly_t * poly_syndrome_init(poly_t generator, gf_t *support, int n)
{
    int i,j,t;
    gf_t a;
    poly_t * F;

    F = malloc(n * sizeof (poly_t));
    t = poly_deg(generator);

    //g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0
    //f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0

    for(j=0; j<n; j++)
    {
        F[j] = poly_alloc(t-1);
        poly_set_coeff(F[j],t-1,gf_unit());
        for(i=t-2; i>=0; i--)
        {
            poly_set_coeff(F[j],i,gf_add(poly_coeff(generator,i+1),
                                         gf_mul(support[j],poly_coeff(F[j],i+1))));
        }
        a = gf_add(poly_coeff(generator,0),gf_mul(support[j],poly_coeff(F[j],0)));
        for(i=0; i<t; i++)
        {
            poly_set_coeff(F[j],i, gf_div(poly_coeff(F[j],i),a));
        }
    }

    return F;
}
コード例 #5
0
ファイル: poly.c プロジェクト: enascimento/supercop
// p = p * x mod g
// p de degré <= deg(g)-1
void poly_shiftmod(poly_t p, poly_t g) {
    int i, t;
    gf_t a;

    t = poly_deg(g);
    a = gf_div(p->coeff[t-1], g->coeff[t]);
    for (i = t - 1; i > 0; --i)
        p->coeff[i] = gf_add(p->coeff[i - 1], gf_mul(a, g->coeff[i]));
    p->coeff[0] = gf_mul(a, g->coeff[0]);
}
コード例 #6
0
void test_division_inverse() {
    suite("division has nonequal inverse");
    ALL1(
            switch ( a ) {
                case 0:
                case 1:
                    break;

                default:
                    test(gf_div(1,a) != a);
            }
        )
}
コード例 #7
0
ファイル: gf-bench.c プロジェクト: Moseco/rnccdn
// Main
int
main(int argc, char **argv)
{
	// Variables
	int		i;
	struct timeval	start, end;
	// Change # of repeats according to the processing bits
	int		repeat = REPEAT / 1; // 8bits
	//int		repeat = REPEAT / 2; // 16bits
	//int		repeat = REPEAT / 4; // 32bits
	//int		repeat = REPEAT / 8; // 64bits
	uint8_t		a, b; // Change type of these according to the processing bits
	//uint16_t	a, b; // 16bits
	//uint32_t	a, b; // 32bits
	//uint64_t	a, b; // 64bits


	// Initialize GF
	//GFinit(); // Some libraries need initialization

	// Start measuring elapsed time
	gettimeofday(&start, NULL); // Get start time

	// Repeat mul and div in GF
	for (i = 0; i < repeat; i++) {
		// Note change these according to the bits,
		// random() must be 64bits
		a = (uint8_t)(random() & 0xff);
		b = (uint8_t)(random() & 0xff);
		// a = (uint16_t)(random() & 0xffff); // In case of 16bits

		// Calculate in GF
		gf_mul(a, b); // You may need to change this function according to the bits like GF8mul(), GF64mul()
		gf_div(a, b);
	}

	// Get end time
	gettimeofday(&end, NULL);

	// Print result
	printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec)));
}
コード例 #8
0
ファイル: raid6_test.c プロジェクト: wdskuki/NCFS
//test raid6 algorithm
int main(int argc, char *argv[])
{

	char disk_data[DISKNUM][BLOCKSIZE];
	char read_data[DISKNUM-2][BLOCKSIZE];
	int disk_id;
	char temp_char;
	int i, j;
	int code_disk_id, parity_disk_id;
	int data_disk_coeff;

	int disk_failed_no = DISK_FAILED_NUM;
	int disk_first_id = FIRST_FAIL_ID;
	int disk_second_id = SECOND_FAIL_ID;
	int disk_another_failed_id;	

	int g1, g2, g12;
	char P_temp[BLOCKSIZE], Q_temp[BLOCKSIZE];

	gen_tables(8);

	printf("\nPrint gflog(x)\n");
	for (i=0; i<256; i++){
		printf("%d(%d) ",i,gflog[i]);
	}
	printf("\n");

        printf("\nPrint gfilog(x)\n");
        for (i=0; i<256; i++){
                printf("%d(%d) ",i,gfilog[i]);
        }
        printf("\n");


	for (i=0; i<DISKNUM; i++){
		if (i < DISKNUM-2){
			temp_char = TEST_DATA_BEGIN + i;
		}
		else{
			temp_char = 0;
		}

		for (j=0; j<BLOCKSIZE; j++){
			disk_data[i][j] = temp_char;
		}
	}

	printf("\n****** PRINT DISK DATA ******\n");
        for (i=0; i<DISKNUM; i++){
                printf("Disk id: %d\n",i);
                for (j=0; j<BLOCKSIZE; j++){
                        printf("%c(%d) ",disk_data[i][j],disk_data[i][j]);
                }
                printf("\n");
        }


	//write P and Q

	code_disk_id = DISKNUM -1;
	parity_disk_id = DISKNUM - 2;

	for (i=0; i<DISKNUM; i++){
		if ( (i != parity_disk_id) && (i != code_disk_id) ){
			
			for (j=0; j<BLOCKSIZE; j++){

				//calculate P
				disk_data[parity_disk_id][j] = 
					disk_data[parity_disk_id][j] ^ disk_data[i][j];
			

                                //calculate the coefficient of the data block
                                data_disk_coeff = i;

                                if (i > code_disk_id){   
                                        (data_disk_coeff)--;                  
                                }
                                if (i > parity_disk_id){
                                        (data_disk_coeff)--;
                                }        
                                data_disk_coeff = DISKNUM - 3 - data_disk_coeff;
                                data_disk_coeff = get_coefficient(data_disk_coeff);

                                printf("\ndata disk coefficient = %d\n",data_disk_coeff);

				//calculate Q
				temp_char = disk_data[code_disk_id][j];
				disk_data[code_disk_id][j] = temp_char ^ 
					(char)gf_mul((unsigned char)disk_data[i][j],data_disk_coeff,FIELDSIZE);

				printf(" newQ=%c(%d) \n",disk_data[code_disk_id][j],
					(unsigned int)disk_data[code_disk_id][j]);
			}

		}
	}


        printf("\n****** PRINT DISK DATA ******\n");
        for (i=0; i<DISKNUM; i++){
                printf("Disk id: %d\n",i);
                for (j=0; j<BLOCKSIZE; j++){
                        printf("%c(%d) ",disk_data[i][j],disk_data[i][j]);
                }
                printf("\n");
        }


	//read data

	for (i=0; i<DISKNUM-2; i++){
		for (j=0; j<BLOCKSIZE; j++){
			read_data[i][j] = 0;
		}
	}


	for (disk_id=0; disk_id<DISKNUM-2; disk_id++){

		disk_another_failed_id = disk_second_id;

		if (disk_id == disk_first_id){
			disk_another_failed_id = disk_second_id;
		}
		else if (disk_id == disk_second_id){
			disk_another_failed_id = disk_first_id;
		}

		printf("\nDisk ID: %d, another failed disk ID: %d\n",disk_id, disk_another_failed_id);

		//case of the disk is not failed
		if ( (disk_failed_no == 0) || 
				((disk_id != disk_first_id) && (disk_id != disk_second_id)) ){
			printf("NO DISK FAIL\n");
			for (j=0; j<BLOCKSIZE; j++){
				read_data[disk_id][j] = disk_data[disk_id][j];
			}
		}
		//cases of single disk fail
		else if ( (disk_failed_no == 1) ||
		((disk_failed_no == 2) && (disk_another_failed_id == code_disk_id)) ){
			printf("One disk fail, or 1 data plus Q disk fail\n");
			for (i = 0; i < DISKNUM; i++){
				if ( (i != disk_id) && (i != code_disk_id) ){
					for (j=0; j<BLOCKSIZE; j++){
						read_data[disk_id][j] =
							read_data[disk_id][j] ^ disk_data[i][j];
					}
				}
			}
		}
		else if (disk_failed_no == 2){
			if (disk_another_failed_id == parity_disk_id){
				printf("1 data plus P disk fail\n");

				//calculate Q'
				for (i=0; i<DISKNUM; i++){
                                        if ( ((i != disk_first_id) && (i != disk_second_id)) 
					&& (i != parity_disk_id) && (i != code_disk_id) ){
                                                for (j=0; j < BLOCKSIZE; j++){

                                			//calculate the coefficient of the data block
                                			data_disk_coeff = i;

                                			if (i > code_disk_id){
                                        			(data_disk_coeff)--;
                                			}
                                			if (i > parity_disk_id){
                                        			(data_disk_coeff)--;
                                			}
                                			data_disk_coeff = DISKNUM - 3 - data_disk_coeff;              
                                			data_disk_coeff = get_coefficient(data_disk_coeff);

                                			printf("\ndata disk coefficient = %d\n",data_disk_coeff);       

                                                        temp_char = read_data[disk_id][j];
                                                        read_data[disk_id][j] = read_data[disk_id][j] ^
								(char)gf_mul((unsigned char)disk_data[i][j],data_disk_coeff,FIELDSIZE);
                                                }
                                        }

                                	for (j=0; j<BLOCKSIZE; j++){
                                        	printf("Q'=%c(%d) ",read_data[disk_id][j],read_data[disk_id][j]);
                                	}

				}


                                //calculate Q xor Q'
                                for (j=0; j < BLOCKSIZE; j++){
                                	read_data[disk_id][j] = read_data[disk_id][j] ^ disk_data[code_disk_id][j];
                                }
        
                                for (j=0; j<BLOCKSIZE; j++){
                                        printf("Q'+Q=%c(%d) ",read_data[disk_id][j],read_data[disk_id][j]);
                                }

                                //calculate the coefficient of the data block
                                data_disk_coeff = disk_id;

                                if (disk_id > code_disk_id){
                                        (data_disk_coeff)--;
                                }
                                if (disk_id > parity_disk_id){
                                        (data_disk_coeff)--;
                                }
                                data_disk_coeff = DISKNUM - 3 - data_disk_coeff;
				data_disk_coeff = get_coefficient(data_disk_coeff);

				printf("\ndata disk coefficient = %d\n",data_disk_coeff);

                                //decode the origianl data block
                                for (j=0; j < BLOCKSIZE; j++){
					temp_char = read_data[disk_id][j];
                                        read_data[disk_id][j] = (char)gf_div((unsigned char)temp_char,data_disk_coeff,FIELDSIZE);
                                }
			}
			else{
			//case of two data disk fail
				printf("2 data disk fail\n");

				//calculate g1
				g1 = disk_id;
                                if (g1 > code_disk_id){
                                        (g1)--;
                                }
                                if (g1 > parity_disk_id){
                                        (g1)--;
                                }
                                g1 = DISKNUM - 3 - g1;
                                g1 = get_coefficient(g1);
				printf("g1=%d \n",g1);

				//calculate g2
                                g2 = disk_another_failed_id;
                                if (g2 > code_disk_id){     
                                        (g2)--;             
                                }
                                if (g2 > parity_disk_id){     
                                        (g2)--;             
                                }
                                g2 = DISKNUM - 3 - g2;                          
                                g2 = get_coefficient(g2);   
				printf("g2=%d \n",g2);

				//calculate g12
				g12 = g1 ^ g2;

				//calculate P'
				for (j=0; j<BLOCKSIZE; j++){
					P_temp[j] = 0;
				}

				for (i=0; i<DISKNUM; i++){
					if ( (i != disk_first_id) && (i != disk_second_id) &&
						(i != parity_disk_id) && (i != code_disk_id) )
					{
						for (j=0; j<BLOCKSIZE; j++){
							P_temp[j] = P_temp[j] ^ disk_data[i][j];
						}
					}
				}

				for (j=0; j<BLOCKSIZE; j++){
					P_temp[j] = P_temp[j] ^ disk_data[parity_disk_id][j];
					//P_temp = P' xor P
				}


				//calculate Q'
				for (j=0; j<BLOCKSIZE; j++){
					Q_temp[j] = 0;
				}

                                for (i=0; i<DISKNUM; i++){
                                        if ( ((i != disk_first_id) && (i != disk_second_id)) 
                                        && (i != parity_disk_id) && (i != code_disk_id) ){

                                                //calculate the coefficient of the data block
                                                data_disk_coeff = i;

                                                if (i > code_disk_id){
                                                        (data_disk_coeff)--;
                                                }
                                                if (i > parity_disk_id){
                                                        (data_disk_coeff)--;
                                                }
                                                data_disk_coeff = DISKNUM - 3 - data_disk_coeff;              
                                                data_disk_coeff = get_coefficient(data_disk_coeff);

                                                printf("\ndata disk coefficient = %d\n",data_disk_coeff);       

                                                for (j=0; j < BLOCKSIZE; j++){
                                                        temp_char = Q_temp[j];
                                                        Q_temp[j] = temp_char ^ 
							(char)gf_mul((unsigned char)disk_data[i][j],data_disk_coeff,FIELDSIZE);
                                                }
                                        }

                                        for (j=0; j<BLOCKSIZE; j++){
                                                printf("Q'=%c(%d) ",Q_temp[j],Q_temp[j]);
                                        }
                                }

				//calculate D
				for (j=0; j<BLOCKSIZE; j++){
					temp_char = (char)(gf_mul(g2,(unsigned char)P_temp[j],FIELDSIZE) 
								^ Q_temp[j] ^ disk_data[code_disk_id][j]);
					read_data[disk_id][j] = (char)gf_div((unsigned char)temp_char, g12, FIELDSIZE);
				}
			}
		}
	}


	//print data read
	printf("\n****** PRINT READ DATA ******\n");
        for (i=0; i<DISKNUM-2; i++){
                printf("Read disk id: %d\n",i);
                for (j=0; j<BLOCKSIZE; j++){
                        printf("%c(%d) ",read_data[i][j],read_data[i][j]);
                }
                printf("\n");
        }

	return 0;
}
コード例 #9
0
ファイル: poly.c プロジェクト: enascimento/supercop
// On suppose deg(g) >= deg(p)
void poly_eeaux(poly_t * u, poly_t * v, poly_t p, poly_t g, int t) {
    int i, j, dr, du, delta;
    gf_t a;
    poly_t aux, r0, r1, u0, u1;

    // initialisation des variables locales
    // r0 <- g, r1 <- p, u0 <- 0, u1 <- 1
    dr = poly_deg(g);

    r0 = poly_alloc(dr);
    r1 = poly_alloc(dr - 1);
    u0 = poly_alloc(dr - 1);
    u1 = poly_alloc(dr - 1);
    poly_set(r0, g);
    poly_set(r1, p);
    poly_set_to_zero(u0);
    poly_set_to_zero(u1);
    poly_set_coeff(u1, 0, gf_unit());
    poly_set_deg(u1, 0);

    // invariants:
    // r1 = u1 * p + v1 * g
    // r0 = u0 * p + v0 * g
    // et deg(u1) = deg(g) - deg(r0)
    // on s'arrête lorsque deg(r1) < t (et deg(r0) >= t)
    // et donc deg(u1) = deg(g) - deg(r0) < deg(g) - t
    du = 0;
    dr = poly_deg(r1);
    delta = poly_deg(r0) - dr;

    while (dr >= t) {
        for (j = delta; j >= 0; --j) {
            a = gf_div(poly_coeff(r0, dr + j), poly_coeff(r1, dr));
            if (a != gf_zero()) {
                // u0(z) <- u0(z) + a * u1(z) * z^j
                for (i = 0; i <= du; ++i) {
                    poly_addto_coeff(u0, i + j, gf_mul_fast(a, poly_coeff(u1, i)));
                }
                // r0(z) <- r0(z) + a * r1(z) * z^j
                for (i = 0; i <= dr; ++i)
                    poly_addto_coeff(r0, i + j, gf_mul_fast(a, poly_coeff(r1, i)));
            }
        }
        // échanges
        aux = r0;
        r0 = r1;
        r1 = aux;
        aux = u0;
        u0 = u1;
        u1 = aux;

        du = du + delta;
        delta = 1;
        while (poly_coeff(r1, dr - delta) == gf_zero())
            delta++;
        dr -= delta;
    }

    poly_set_deg(u1, du);
    poly_set_deg(r1, dr);
    //return u1 and r1;
    *u=u1;
    *v=r1;

    poly_free(r0);
    poly_free(u0);
}
コード例 #10
0
ファイル: msr_test.c プロジェクト: wdskuki/NCFS
//test msr algorithm
int main(int argc, char *argv[])
{
	char write_data[MSR_M * MSR_SEGMENT_NUM][BLOCKSIZE];
	char disk_data[DISKNUM][MSR_SEGMENT_SIZE * MSR_SEGMENT_NUM][BLOCKSIZE];
	char read_data[MSR_M * MSR_SEGMENT_NUM][BLOCKSIZE];
	char temp_buf[BLOCKSIZE];
	int i, j, k, p;
	int temp;
	char temp_char;

	int msr_segment_id;
	int msr_block_id;
	int disk_id, block_no;
	int code_disk_id, code_block_no;
	int temp_msr_block_id, temp_disk_id, temp_block_no;
	char encoded_data;
	int coefficient;
	int decode_block_id, decode_disk_id, decode_block_no;

        int disk_failed_num = DISK_FAILED_NUM;
        int disk_first_id = FIRST_FAIL_ID;
        int disk_second_id = SECOND_FAIL_ID;
        int disk_another_failed_id;            

	//Generate GF table
	gen_tables(8);

	//Generate coding matrix
	msr_gen_coding_matrix(MSR_N, MSR_K, MSR_M, MSR_C);

	//Print the coding matrix
	printf("\nCoding matrix\n");
	for (i=0; i<MSR_C; i++){
		printf("M'%d = ",i);
		for (j=0; j<MSR_M; j++){
			temp = msr_coding_matrix[i][j];
			if (temp != 0){
				if (temp == 1){
					printf("M%d + ",j);
				}
				else{
					printf("%dM%d + ",temp,j);
				}
			}
		}
		printf("\n");
	}
	printf("\n");


	//Generate write buffer
	for (i=0; i<MSR_M * MSR_SEGMENT_NUM; i++){
		temp_char = TEST_DATA_BEGIN + i;
		for (j=0; j<BLOCKSIZE; j++){
			write_data[i][j] = temp_char;
		}
	}

	//PRINT Write Buffer
	printf("\n******PRINT Write Buffer******\n");
	for (i=0; i <MSR_M * MSR_SEGMENT_NUM; i++){
		printf("%d Data block: ",i);
		for (j=0; j<BLOCKSIZE; j++){
			printf("%c(%d) ",write_data[i][j],write_data[i][j]); 
		}
		printf("\n");
	}


	//Nullify disk data
        for (i=0; i <DISKNUM; i++){
                for (j=0; j<MSR_SEGMENT_SIZE * MSR_SEGMENT_NUM; j++){
                        for (k=0; k<BLOCKSIZE; k++){
                                disk_data[i][j][k] = 0;
                        }
                }           
        }

	//Write data to disk
        printf("\n******Writing data to disk******\n");
	
	for (i=0; i<MSR_M * MSR_SEGMENT_NUM; i++){
		//find data block location
		msr_segment_id = (int)(i / MSR_M);  //find msr_segment_id;
		msr_block_id = i % MSR_M;
		disk_id = msr_get_disk_id(msr_block_id, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
		block_no = msr_get_block_no(msr_block_id, MSR_SEGMENT_SIZE);
		block_no = block_no + msr_segment_id * MSR_SEGMENT_SIZE;
                printf("M%d disk_id=%d block_no=%d\n",msr_block_id,disk_id,block_no);

		//write data block
		for (k=0; k<BLOCKSIZE; k++){
			disk_data[disk_id][block_no][k] = write_data[msr_block_id + msr_segment_id * MSR_M][k];
		}

		//find coded block location
		for (p=0; p<MSR_C; p++){
		   	if (msr_coding_matrix[p][msr_block_id] != 0){

				code_disk_id = msr_get_code_disk_id(p, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
				code_block_no = msr_get_code_block_no(p, MSR_SEGMENT_SIZE);
				code_block_no = code_block_no + msr_segment_id * MSR_SEGMENT_SIZE;

				//generate encoded data
				for (k=0; k<BLOCKSIZE; k++){
					temp_buf[k] = 0;
				}

				for (j=0; j<MSR_M; j++){
					coefficient = msr_coding_matrix[p][j];
					if (coefficient != 0){
						temp_msr_block_id = j;
						temp_disk_id = msr_get_disk_id(temp_msr_block_id, MSR_SEGMENT_SIZE, 
										MSR_N, MSR_K);
						temp_block_no = msr_get_block_no(temp_msr_block_id, MSR_SEGMENT_SIZE);
						temp_block_no = temp_block_no + msr_segment_id * MSR_SEGMENT_SIZE;

						for (k=0; k<BLOCKSIZE; k++){
							temp_char = disk_data[temp_disk_id][temp_block_no][k];
							encoded_data = (char)gf_mul((unsigned char)coefficient, 
									(unsigned char)temp_char,  FIELDSIZE);
							temp_buf[k] = temp_buf[k] ^ encoded_data;
						}
					}
				}

				//write coded block
                		for (k=0; k<BLOCKSIZE; k++){
                        		disk_data[code_disk_id][code_block_no][k] = temp_buf[k];
                		}
			}
		}
	}

        //PRINT Disk Data
        printf("\n******PRINT Disk Data******\n");
        for (i=0; i <DISKNUM; i++){
                printf("###Disk id: %d\n",i);
                for (j=0; j<MSR_SEGMENT_SIZE * MSR_SEGMENT_NUM; j++){
			msr_block_id = msr_find_block_id(i,j,MSR_SEGMENT_SIZE,MSR_N,MSR_K);
			if (msr_block_id == -1){
				msr_block_id = msr_find_code_block_id(i,j,MSR_SEGMENT_SIZE,MSR_N,MSR_K);
				msr_block_id = msr_block_id + 100;
			}
                        printf("##Relative block number: %d. MSR ID: {%d}, Data: ",j,msr_block_id); 
			for (k=0; k<BLOCKSIZE; k++){
				printf("%c(%d) ",disk_data[i][j][k],disk_data[i][j][k]);
			}
			printf("\n");
                }           
                printf("\n");
        }


        //Read data from disk to read buffer        

	for (i=0; i<MSR_M * MSR_SEGMENT_NUM; i++){

		msr_block_id = i % MSR_M;
		msr_segment_id = i / MSR_M;
                disk_id = msr_get_disk_id(msr_block_id, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
                block_no = msr_get_block_no(msr_block_id, MSR_SEGMENT_SIZE);		
		block_no = block_no + msr_segment_id * MSR_SEGMENT_SIZE;				

                disk_another_failed_id = disk_second_id; 
                if (disk_id == disk_first_id){
                        disk_another_failed_id = disk_second_id;              
                }
                else if (disk_id == disk_second_id){
                        disk_another_failed_id = disk_first_id;
                }


                disk_another_failed_id = disk_second_id; 

                if (disk_id == disk_first_id){
                        disk_another_failed_id = disk_second_id;              
                }
                else if (disk_id == disk_second_id){
                        disk_another_failed_id = disk_first_id;
                }

		if ((disk_id != FIRST_FAIL_ID) && (disk_id != SECOND_FAIL_ID)){
		//Case of no disk failure
			printf("\nBlock is accessible\n");
			for (k=0; k<BLOCKSIZE; k++){
				read_data[i][k] = disk_data[disk_id][block_no][k];
			}
		}
		else{
		//Cases of disk failure

                        //Find the single coded block for handling one-node failure
                        decode_block_id = msr_find_single_decode_block_id(msr_block_id, MSR_SEGMENT_SIZE);
                        decode_disk_id = msr_get_code_disk_id(decode_block_id, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
                        decode_block_no = msr_get_code_block_no(decode_block_id, MSR_SEGMENT_SIZE);
                        decode_block_no = decode_block_no + msr_segment_id * MSR_SEGMENT_SIZE;


			if ( (disk_failed_num == 1) ||
				((disk_failed_num == 2) && (disk_another_failed_id >= (int)(MSR_N/2)) && 
				(disk_another_failed_id != decode_disk_id)) ){
			//Case of single disk failure
				printf("\nSingle disk failure. msr_block_id: %d. disk_id: %d. block_no: %d\n",
						msr_block_id, disk_id, block_no);

				for (k=0; k<BLOCKSIZE; k++){
					temp_buf[k] = disk_data[decode_disk_id][decode_block_no][k];
				}

				//Calculate the requested data
				for (j=0; j<MSR_M; j++){
					coefficient = msr_coding_matrix[decode_block_id][j];
					if ((j != msr_block_id) && (coefficient != 0)){
						temp_disk_id = msr_get_disk_id(j, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
						temp_block_no = msr_get_block_no(j, MSR_SEGMENT_SIZE);
						temp_block_no = temp_block_no + msr_segment_id * MSR_SEGMENT_SIZE;
						for (k=0; k<BLOCKSIZE; k++){
							temp_char = (char)gf_mul((unsigned char)coefficient, 
								(unsigned char)disk_data[temp_disk_id][temp_block_no][k], 
								FIELDSIZE);
							temp_buf[k] = temp_buf[k] ^ temp_char;
						}
					}
				}

				for (k=0; k<BLOCKSIZE; k++){
					read_data[i][k] = (char)gf_div((unsigned char)temp_buf[k], 
							(unsigned char)msr_coding_matrix[decode_block_id][msr_block_id], 
							FIELDSIZE);
				}
			}
                        else if ((disk_failed_num == 2) && (disk_another_failed_id == decode_disk_id)){
                                printf("\nTwo-disk failure (D + primary parity). msr_block_id: %d. disk_id: %d. block_no: %d\n",  
                                                msr_block_id, disk_id, block_no);


				//generate block status array
				int block_status[MSR_M];   //0 for healthy; 1 for failed
				int code_block_status[MSR_C];
				int sec_code_block_id, sec_code_disk_id, sec_code_block_no;
				int sec_code_block_coeff[MSR_M];
				char sec_code_block_value[BLOCKSIZE];
				int temp_block_coeff[MSR_M];
				char temp_block_value[BLOCKSIZE];
				int count_failed_blocks;
				int temp_coeff1, temp_coeff2;

				for (j=0; j<MSR_M; j++){
					temp_disk_id = msr_get_disk_id(j, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
					if ((temp_disk_id == disk_id) || (temp_disk_id == disk_another_failed_id)){
						block_status[j] = 1;
					}
					else{
						block_status[j] = 0;
					}
				}

				for (j=0; j<MSR_C; j++){
                                        temp_disk_id = msr_get_code_disk_id(j, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
                                        if ((temp_disk_id == disk_id) || (temp_disk_id == disk_another_failed_id)){
                                                code_block_status[j] = 1;
                                        }
                                        else{
                                                code_block_status[j] = 0;
                                        }
				}

				//get secondary decode block
				sec_code_block_id = 0;
				for (j=0; j<MSR_C; j++){
					count_failed_blocks = MSR_M;
					//find code block having target block and fewest failed blocks
					if ((code_block_status[j] == 0) && (msr_coding_matrix[j][msr_block_id] != 0)){
						temp = 0;
						for (k=0; k<MSR_M; k++){
							if ((k != msr_block_id) && (msr_coding_matrix[j][k] != 0)
							&& (block_status[k] == 1)){
								temp++;
							}
						}
						if (temp < count_failed_blocks){
							sec_code_block_id = j;
							count_failed_blocks = temp;
						}						
					}
				}
				sec_code_disk_id = msr_get_code_disk_id(sec_code_block_id, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
                        	sec_code_block_no = msr_get_code_block_no(sec_code_block_id, MSR_SEGMENT_SIZE);
                        	sec_code_block_no = sec_code_block_no + msr_segment_id * MSR_SEGMENT_SIZE;
				printf("\n***get sec_decode_block. block_id=%d, sec_code_block_id=%d\n",
										msr_block_id,sec_code_block_id);

				//generate temporary coefficient array
				for (k=0; k<MSR_M; k++){
					sec_code_block_coeff[k] = msr_coding_matrix[sec_code_block_id][k];
				}

				for (k=0; k<BLOCKSIZE; k++){
					sec_code_block_value[k] = disk_data[sec_code_disk_id][sec_code_block_no][k];
				}
				
				//eliminate non-target values (failed blocks)
				for (j=0; j<MSR_M; j++){
					if ((j != msr_block_id) && (sec_code_block_coeff[j] != 0)
					&& (block_status[j] != 0)){
printf("\n****eliminate %d\n",j);
						//find decode block, eliminate the failed block
						temp_msr_block_id = msr_find_single_decode_block_id(j, MSR_SEGMENT_SIZE);
						temp_disk_id = msr_get_code_disk_id(temp_msr_block_id, 
									MSR_SEGMENT_SIZE, MSR_N, MSR_K);
						temp_block_no = msr_get_code_block_no(temp_msr_block_id, MSR_SEGMENT_SIZE);
						temp_block_no = temp_block_no + msr_segment_id * MSR_SEGMENT_SIZE;
printf("****code bock id: %d\n",temp_msr_block_id);
						for (k=0; k<MSR_M; k++){
							temp_block_coeff[k] = msr_coding_matrix[temp_msr_block_id][k];
						}

						if ((temp_disk_id != disk_id) || (temp_disk_id != disk_another_failed_id)){
							for (k=0; k<BLOCKSIZE; k++){
								temp_block_value[k] = disk_data[temp_disk_id][temp_block_no][k];
							}
						}else{
							printf("\nError: Attempt to access failed disk\n");
						}

						temp_coeff1 = sec_code_block_coeff[j];
						temp_coeff2 = temp_block_coeff[j];

printf("\n");
						for (k=0; k<MSR_M; k++){
							//temp = temp_coeff1 * temp_block_coeff[k]
							//	^ temp_coeff2 * sec_code_block_coeff[k];

							temp = (int)((char)gf_mul((unsigned char)temp_coeff1, 
									(unsigned char)temp_block_coeff[k], FIELDSIZE)
								^ (char)gf_mul((unsigned char)temp_coeff2,
									(unsigned char)sec_code_block_coeff[k], FIELDSIZE));

							sec_code_block_coeff[k] = temp;
printf("%d:%d ",k,temp);
						}
printf("\n");

						for (k=0; k<BLOCKSIZE; k++){
							sec_code_block_value[k] = 
								(char)gf_mul((unsigned char)sec_code_block_value[k],
										(unsigned char)temp_coeff2, FIELDSIZE);
                                                        temp_char = (char)gf_mul((unsigned char)temp_block_value[k], 
                                                                          (unsigned char)temp_coeff1, FIELDSIZE);
							sec_code_block_value[k] ^= temp_char;
						}
					}
				}

				//eliminate non-target values (healthy blocks)
				for (j=0; j < MSR_M; j++){
					if ((j != msr_block_id) && (sec_code_block_coeff[j] != 0)){
						temp_msr_block_id = j;
						temp_disk_id = msr_get_disk_id(temp_msr_block_id, MSR_SEGMENT_SIZE, MSR_N, MSR_K);
						temp_block_no = msr_get_code_block_no(temp_msr_block_id, MSR_SEGMENT_SIZE);
						temp_block_no = temp_block_no + msr_segment_id * MSR_SEGMENT_SIZE;

						for (k=0; k<BLOCKSIZE; k++){
							temp_block_value[k] = disk_data[temp_disk_id][temp_block_no][k];
						}

						temp = sec_code_block_coeff[temp_msr_block_id];
						for (k=0; k<BLOCKSIZE; k++){
							temp_char = (char)gf_mul((unsigned char)temp,
								(unsigned char)temp_block_value[k], FIELDSIZE);
							sec_code_block_value[k] ^= temp_char;
						}
						sec_code_block_coeff[temp_msr_block_id] = 0;
					}
				}


				//find target value
				temp = sec_code_block_coeff[msr_block_id];
				for (k=0; k<BLOCKSIZE; k++){
                                        read_data[i][k] = (char)gf_div((unsigned char)sec_code_block_value[k], 
                                                        (unsigned char)temp, FIELDSIZE);
				}
                        }
			else{
                                printf("\nTwo data-disk failure, or more than two disk failure. Non-supported failure."); 
				printf("msr_block_id: %d. disk_id: %d. block_no: %d\n",
                                                msr_block_id, disk_id, block_no);
			}
		}
	}


        //PRINT Read Buffer
        printf("\n******PRINT Read Buffer******\n");
        for (i=0; i <MSR_M * MSR_SEGMENT_NUM; i++){
                printf("%d data block: ",i);
                for (j=0; j<BLOCKSIZE; j++){
                        printf("%c(%d) ",read_data[i][j],read_data[i][j]); 
                }
                printf("\n");
        }

	return 0;
}