gf2matrix *invert_matrix(gf2matrix *dest, const gf2matrix *m) { if (!m) return NULL; mzd_t *temp = mzd_inv_m4ri(NULL, (mzd_t*) m, 0); if(!temp) { dest = NULL; } else { mzd_t *I = make_identity_matrix(m->nrows); mzd_t *prod = mul_matrices(NULL, m, temp); if(comp_matrices(prod, I) == 0) { // inversion was successful if (dest) { mzd_copy(dest, temp); mzd_free(temp); } else { dest = temp; } } else { dest = NULL; } mzd_free(prod); mzd_free(I); } return dest; }
int test_pluq_structured(rci_t m, rci_t n) { printf("pluq: testing structured m: %5d, n: %5d", m, n); mzd_t* A = mzd_init(m, n); mzd_t* L = mzd_init(m, m); mzd_t* U = mzd_init(m, n); for(rci_t i = 0; i < m; i += 2) for (rci_t j = i; j < n; ++j) mzd_write_bit(A, i, j, 1); mzd_t* Acopy = mzd_copy (NULL,A); mzp_t* P = mzp_init(m); mzp_t* Q = mzp_init(n); rci_t r = mzd_pluq(A, P, Q, 0); printf(", rank: %5d ",r); for (rci_t i = 0; i < r; ++i){ for (rci_t j = 0; j < i; ++j) mzd_write_bit(L, i, j, mzd_read_bit(A,i,j)); for (rci_t j = i + 1; j < n; ++j) mzd_write_bit(U, i, j, mzd_read_bit(A,i,j)); } for (rci_t i = r; i < m; ++i) for (rci_t j = 0; j < r; ++j) mzd_write_bit(L, i, j, mzd_read_bit(A,i,j)); for (rci_t i = 0; i < r; ++i){ mzd_write_bit(L,i,i, 1); mzd_write_bit(U,i,i, 1); } mzd_apply_p_left(Acopy, P); mzd_apply_p_right_trans(Acopy, Q); mzd_addmul(Acopy, L, U, 0); int status = 0; for (rci_t i = 0; i < m; ++i) for (rci_t j = 0; j < n; ++j){ if (mzd_read_bit (Acopy,i,j)){ status = 1; break; } } if (status) { printf("\n"); printf(" ... FAILED\n"); } else printf (" ... passed\n"); mzd_free(U); mzd_free(L); mzd_free(A); mzd_free(Acopy); mzp_free(P); mzp_free(Q); return status; }
int test_trsm_upper_right (int m, int n, int offset, const char* description){ printf("upper_right: %s m: %4d n: %4d offset: %4d ... ",description, m, n, offset); mzd_t* Ubase = mzd_init (2048,2048); mzd_t* Bbase = mzd_init (2048,2048); mzd_randomize (Ubase); mzd_randomize (Bbase); mzd_t* Bbasecopy = mzd_copy (NULL, Bbase); mzd_t* U = mzd_init_window (Ubase, 0, offset, n, offset + n); mzd_t* B = mzd_init_window (Bbase, 0, offset, m, offset + n); mzd_t* W = mzd_copy (NULL, B); size_t i,j; for (i=0; i<n; ++i){ for (j=0; j<i;++j) mzd_write_bit(U,i,j, 0); mzd_write_bit(U,i,i, 1); } mzd_trsm_upper_right (U, B, 2048); mzd_addmul(W, B, U, 2048); int status = 0; for ( i=0; i<m; ++i) for ( j=0; j<n; ++j){ if (mzd_read_bit (W,i,j)){ status = 1; } } // Verifiying that nothing has been changed around the submatrices mzd_addmul(W, B, U, 2048); mzd_copy (B, W); for ( i=0; i<2048; ++i) for ( j=0; j<2048/RADIX; ++j){ if (Bbase->rows[i][j] != Bbasecopy->rows[i][j]){ status = 1; } } mzd_free_window (U); mzd_free_window (B); mzd_free (W); mzd_free(Ubase); mzd_free(Bbase); mzd_free(Bbasecopy); if (!status) printf("passed\n"); else printf("FAILED\n"); return status; }
int test_trsm_lower_left (int m, int n, int offsetL, int offsetB){ mzd_t* Lbase = mzd_init (2048,2048); mzd_t* Bbase = mzd_init (2048,2048); mzd_randomize (Lbase); mzd_randomize (Bbase); mzd_t* Bbasecopy = mzd_copy (NULL, Bbase); mzd_t* L = mzd_init_window (Lbase, 0, offsetL, m, offsetL + m); mzd_t* B = mzd_init_window (Bbase, 0, offsetB, m, offsetB + n); mzd_t* W = mzd_copy (NULL, B); size_t i,j; for (i=0; i<m; ++i){ for (j=i+1; j<m;++j) mzd_write_bit(L,i,j, 0); mzd_write_bit(L,i,i, 1); } mzd_trsm_lower_left(L, B, 2048); mzd_addmul(W, L, B, 2048); int status = 0; for ( i=0; i<m; ++i) for ( j=0; j<n; ++j){ if (mzd_read_bit (W,i,j)){ status = 1; } } // Verifiying that nothing has been changed around the submatrices mzd_addmul(W, L, B, 2048); mzd_copy (B, W); for ( i=0; i<2048; ++i) for ( j=0; j<2048/RADIX; ++j){ if (Bbase->rows[i][j] != Bbasecopy->rows[i][j]){ status = 1; } } mzd_free_window (L); mzd_free_window (B); mzd_free_window (W); mzd_free(Lbase); mzd_free(Bbase); mzd_free(Bbasecopy); if (!status) printf(" ... passed\n"); else printf(" ... FAILED\n"); return status; }
/** * Check that the results of all implemented multiplication algorithms * match up. * * \param m Number of rows of A * \param l Number of columns of A/number of rows of B * \param n Number of columns of B * \param k Parameter k of M4RM algorithm, may be 0 for automatic choice. * \param cutoff Cut off parameter at which dimension to switch from * Strassen to M4RM */ int mul_test_equality(rci_t m, rci_t l, rci_t n, int k, int cutoff) { int ret = 0; mzd_t *A, *B, *C, *D, *E; printf(" mul: m: %4d, l: %4d, n: %4d, k: %2d, cutoff: %4d", m, l, n, k, cutoff); /* we create two random matrices */ A = mzd_init(m, l); B = mzd_init(l, n); mzd_randomize(A); mzd_randomize(B); /* C = A*B via Strassen */ C = mzd_mul(NULL, A, B, cutoff); /* D = A*B via M4RM, temporary buffers are managed internally */ D = mzd_mul_m4rm( NULL, A, B, k); /* E = A*B via naive cubic multiplication */ E = mzd_mul_naive( NULL, A, B); mzd_free(A); mzd_free(B); if (mzd_equal(C, D) != TRUE) { printf(" Strassen != M4RM"); ret -=1; } if (mzd_equal(D, E) != TRUE) { printf(" M4RM != Naiv"); ret -= 1; } if (mzd_equal(C, E) != TRUE) { printf(" Strassen != Naiv"); ret -= 1; } mzd_free(C); mzd_free(D); mzd_free(E); if(ret==0) { printf(" ... passed\n"); } else { printf(" ... FAILED\n"); } return ret; }
int addsqr_test_equality(rci_t m, int k, int cutoff) { int ret = 0; mzd_t *A, *C, *D, *E, *F; printf("addsqr: m: %4d, k: %2d, cutoff: %4d", m, k, cutoff); /* we create two random matrices */ A = mzd_init(m, m); C = mzd_init(m, m); mzd_randomize(A); mzd_randomize(C); /* D = C + A*B via M4RM, temporary buffers are managed internally */ D = mzd_copy(NULL, C); D = mzd_addmul_m4rm(D, A, A, k); /* E = C + A*B via naive cubic multiplication */ E = mzd_mul_m4rm(NULL, A, A, k); mzd_add(E, E, C); /* F = C + A*B via naive cubic multiplication */ F = mzd_copy(NULL, C); F = mzd_addmul(F, A, A, cutoff); mzd_free(A); mzd_free(C); if (mzd_equal(D, E) != TRUE) { printf(" M4RM != add,mul"); ret -=1; } if (mzd_equal(E, F) != TRUE) { printf(" add,mul = addmul"); ret -=1; } if (mzd_equal(F, D) != TRUE) { printf(" M4RM != addmul"); ret -=1; } if (ret==0) printf(" ... passed\n"); else printf(" ... FAILED\n"); mzd_free(D); mzd_free(E); mzd_free(F); return ret; }
int test_pluq_solve_left(rci_t m, rci_t n, int offsetA, int offsetB) { mzd_t* Abase = mzd_init(2048, 2048); mzd_t* Bbase = mzd_init(2048, 2048); mzd_randomize(Abase); mzd_randomize(Bbase); mzd_t* A = mzd_init_window(Abase, 0, offsetA, m, m + offsetA); mzd_t* B = mzd_init_window(Bbase, 0, offsetB, m, n + offsetB); // copy B mzd_t* Bcopy = mzd_init(B->nrows, B->ncols); for (rci_t i = 0; i < B->nrows; ++i) for (rci_t j = 0; j < B->ncols; ++j) mzd_write_bit(Bcopy,i,j, mzd_read_bit (B,i,j)); for (rci_t i = 0; i < m; ++i) { mzd_write_bit(A,i,i, 1); } mzd_t *Acopy = mzd_copy(NULL, A); rci_t r = mzd_echelonize(Acopy,1); printf("solve_left m: %4d, n: %4d, r: %4d da: %4d db: %4d ", m, n, r, offsetA, offsetB); mzd_free(Acopy); Acopy = mzd_copy(NULL, A); int consistency = mzd_solve_left(A, B, 0, 1); //copy B mzd_t *X = mzd_init(B->nrows,B->ncols); for (rci_t i = 0; i < B->nrows; ++i) for (rci_t j = 0; j < B->ncols; ++j) mzd_write_bit(X,i,j, mzd_read_bit (B,i,j)); mzd_t *B1 = mzd_mul(NULL, Acopy, X, 0); mzd_t *Z = mzd_add(NULL, Bcopy, B1); int status = 0; if(consistency == 0) { status = 1 - mzd_is_zero(Z); if (status == 0) { printf("passed\n"); } else { printf("FAILED\n"); } } else { printf("skipped (no solution)\n"); } mzd_free(Bcopy); mzd_free(B1); mzd_free(Z); mzd_free_window(A); mzd_free_window(B); mzd_free(Acopy); mzd_free(Abase); mzd_free(Bbase); mzd_free(X); return status; }
int test_kernel_left_pluq(size_t m, size_t n) { mzd_t* A = mzd_init(m, n); mzd_randomize(A); mzd_t *Acopy = mzd_copy(NULL, A); size_t r = mzd_echelonize_m4ri(A, 0, 0); printf("kernel_left m: %4zu, n: %4zu, r: %4zu ",m, n, r); mzd_free(Acopy); Acopy = mzd_copy(NULL, A); mzd_t *X = mzd_kernel_left_pluq(A, 0); if (X == NULL) { printf("passed\n"); mzd_free(A); mzd_free(Acopy); return 0; } mzd_t *Z = mzd_mul(NULL, Acopy, X, 0); int status = 1 - mzd_is_zero(Z); if (!status) printf("passed\n"); else printf("FAILED\n"); mzd_free(A); mzd_free(Acopy); mzd_free(X); mzd_free(Z); return status; }
int run(void *_p, unsigned long long *data, int *data_len) { struct trsm_params *p = (struct trsm_params *)_p; *data_len = 2; mzd_t *B = mzd_init(p->m, p->n); mzd_t *L = mzd_init(p->n, p->n); mzd_randomize(B); mzd_randomize(L); for (rci_t i = 0; i < p->n; ++i){ for (rci_t j = i + 1; j < p->n; ++j) mzd_write_bit(L,i,j, 0); mzd_write_bit(L,i,i, 1); } data[0] = walltime(0); data[1] = cpucycles(); mzd_trsm_lower_right(L, B, 2048); data[0] = walltime(data[0]); data[1] = cpucycles() - data[1]; mzd_free(B); mzd_free(L); return 0; }
mzd_slice_t *_mzd_slice_addmul_naive(mzd_slice_t *C, const mzd_slice_t *A, const mzd_slice_t *B) { if (C == NULL) C = mzd_slice_init(A->finite_field, A->nrows, B->ncols); const unsigned int e = A->finite_field->degree; mzd_t *t0 = mzd_init(A->nrows, B->ncols); for(unsigned int i=0; i<e; i++) { for(unsigned int j=0; j<e; j++) { mzd_mul(t0, A->x[i], B->x[j], 0); _mzd_ptr_add_modred(A->finite_field, t0, C->x, i+j); } } mzd_free(t0); return C; }
MatrixF2::~MatrixF2() { mzd_free(matrix); }
/* * Class: m4rjni_Mzd * Method: mzd_destroy * Signature: (J)V */ JNIEXPORT void JNICALL Java_m4rjni_Mzd_mzd_1destroy(JNIEnv *env, jobject obj, jlong ptr) { mzd_t *M = (mzd_t*)ptr; mzd_free(M); }
/** * Implements both apply_p_right and apply_p_right_trans. */ void _mzd_apply_p_right_even(mzd_t *A, mzp_t *P, size_t start_row, size_t start_col, int notrans) { assert(A->offset == 0); if(A->nrows - start_row == 0) return; const size_t length = MIN(P->length,A->ncols); const size_t width = A->width; size_t step_size = MIN(A->nrows-start_row, MAX((CPU_L1_CACHE>>3)/A->width,1)); /* our temporary where we store the columns we want to swap around */ mzd_t *B = mzd_init(step_size, A->ncols); word *Arow; word *Brow; /* setup mathematical permutation */ size_t *permutation = (size_t *)m4ri_mm_calloc(sizeof(size_t),A->ncols); for(size_t i=0; i<A->ncols; i++) permutation[i] = i; if (!notrans) { for(size_t i=start_col; i<length; i++) { size_t t = permutation[i]; permutation[i] = permutation[P->values[i]]; permutation[P->values[i]] = t; } } else { for(size_t i=start_col; i<length; i++) { size_t t = permutation[length-i-1]; permutation[length-i-1] = permutation[P->values[length-i-1]]; permutation[P->values[length-i-1]] = t; } } /* we have a bitmask to encode where to write to */ word *write_mask = (word*)m4ri_mm_calloc(sizeof(word), length); for(size_t i=0; i<A->ncols; i+=RADIX) { const size_t todo = MIN(RADIX,A->ncols-i); for(size_t k=0; k<todo; k++) { if(permutation[i+k] == i+k) { write_mask[i/RADIX] |= ONE<<(RADIX - k - 1); } } } for(size_t i=start_row; i<A->nrows; i+=step_size) { step_size = MIN(step_size, A->nrows-i); for(size_t k=0; k<step_size; k++) { Arow = A->rows[i+k]; Brow = B->rows[k]; /*copy row & clear those values which will be overwritten */ for(size_t j=0; j<width; j++) { Brow[j] = Arow[j]; Arow[j] = Arow[j] & write_mask[j]; } } /* here we actually write out the permutation */ mzd_write_col_to_rows_blockd(A, B, permutation, write_mask, i, i+step_size, length); } m4ri_mm_free(permutation); m4ri_mm_free(write_mask); mzd_free(B); }
int test_lqup_full_rank (size_t m, size_t n){ printf("pluq: testing full rank m: %5zu, n: %5zu",m,n); mzd_t* U = mzd_init (m,n); mzd_t* L = mzd_init (m,m); mzd_t* U2 = mzd_init (m,n); mzd_t* L2 = mzd_init (m,m); mzd_t* A = mzd_init (m,n); mzd_randomize (U); mzd_randomize (L); size_t i,j; for (i=0; i<m; ++i){ for (j=0; j<i && j<n;++j) mzd_write_bit(U,i,j, 0); for (j=i+1; j<m;++j) mzd_write_bit(L,i,j, 0); if(i<n) mzd_write_bit(U,i,i, 1); mzd_write_bit(L,i,i, 1); } mzd_mul(A, L, U, 2048); mzd_t* Acopy = mzd_copy (NULL,A); mzp_t* P = mzp_init(m); mzp_t* Q = mzp_init(n); mzd_pluq(A, P, Q, 2048); for (i=0; i<m; ++i){ for (j=0; j<i && j <n;++j) mzd_write_bit (L2, i, j, mzd_read_bit(A,i,j)); for (j=i+1; j<n;++j) mzd_write_bit (U2, i, j, mzd_read_bit(A,i,j)); } for (i=0; i<n && i<m; ++i){ mzd_write_bit(L2,i,i, 1); mzd_write_bit(U2,i,i, 1); } mzd_addmul(Acopy,L2,U2,0); int status = 0; for ( i=0; i<m; ++i) for ( j=0; j<n; ++j){ if (mzd_read_bit (Acopy,i,j)){ status = 1; } } if (status){ printf(" ... FAILED\n"); } else printf (" ... passed\n"); mzd_free(U); mzd_free(L); mzd_free(U2); mzd_free(L2); mzd_free(A); mzd_free(Acopy); mzp_free(P); mzp_free(Q); return status; }
int run(void *_p, unsigned long long *data, int *data_len) { struct elim_params *p = (struct elim_params *)_p; #ifndef HAVE_LIBPAPI *data_len = 2; #else *data_len = MIN(papi_array_len + 1, *data_len); #endif int papi_res; mzd_t *A = mzd_init(p->m, p->n); if(p->r != 0) { mzd_t *L, *U; L = mzd_init(p->m, p->m); U = mzd_init(p->m, p->n); mzd_randomize(U); mzd_randomize(L); for (rci_t i = 0; i < p->m; ++i) { for (rci_t j = i + 1; j < p->m; j+=m4ri_radix) { int const length = MIN(m4ri_radix, p->m - j); mzd_clear_bits(L, i, j, length); } mzd_write_bit(L,i,i, 1); for (rci_t j = 0; j < i && j < p->n; j+=m4ri_radix) { int const length = MIN(m4ri_radix, i - j); mzd_clear_bits(U, i, j, length); } if(i < p->r) { mzd_write_bit(U, i, i, 1); } else { for (rci_t j = i; j < p->n; j+=m4ri_radix) { int const length = MIN(m4ri_radix, p->n - i); mzd_clear_bits(U, i, j, length); } } } mzd_mul(A,L,U,0); mzd_free(L); mzd_free(U); } else { mzd_randomize(A); } mzp_t *P = mzp_init(A->nrows); mzp_t *Q = mzp_init(A->ncols); #ifndef HAVE_LIBPAPI data[0] = walltime(0); data[1] = cpucycles(); #else int array_len = *data_len - 1; unsigned long long t0 = PAPI_get_virt_usec(); papi_res = PAPI_start_counters((int*)papi_events, array_len); if (papi_res) m4ri_die(""); #endif if(strcmp(p->algorithm, "m4ri") == 0) p->r = mzd_echelonize_m4ri(A, 0, 0); else if(strcmp(p->algorithm, "ple") == 0) p->r = mzd_ple(A, P, Q, 0); else if(strcmp(p->algorithm, "mmpf") == 0) p->r = _mzd_ple_russian(A, P, Q, 0); else m4ri_die("unknown algorithm %s",p->algorithm); #ifndef HAVE_LIBPAPI data[1] = cpucycles() - data[1]; data[0] = walltime(data[0]); #else mzp_free(P); mzp_free(Q); PAPI_stop_counters((long long*)&data[1], array_len); t0 = PAPI_get_virt_usec() - t0; data[0] = t0; for (int nv = 0; nv <= array_len; ++nv) { data[nv] -= loop_calibration[nv]; } #endif mzd_free(A); return 0; }
int run_nothing(void *_p, unsigned long long *data, int *data_len) { struct elim_params *p = (struct elim_params *)_p; mzd_t *A = mzd_init(p->m, p->n); if(p->r != 0) { mzd_t *L, *U; L = mzd_init(p->m, p->m); U = mzd_init(p->m, p->n); mzd_randomize(U); mzd_randomize(L); for (rci_t i = 0; i < p->m; ++i) { for (rci_t j = i + 1; j < p->m; j+=m4ri_radix) { int const length = MIN(m4ri_radix, p->m - j); mzd_clear_bits(L, i, j, length); } mzd_write_bit(L,i,i, 1); for (rci_t j = 0; j < i && j <p->n; j+=m4ri_radix) { int const length = MIN(m4ri_radix, i - j); mzd_clear_bits(U, i, j, length); } if(i < p->r) { mzd_write_bit(U, i, i, 1); } else { for (rci_t j = i; j < p->n; j+=m4ri_radix) { int const length = MIN(m4ri_radix, p->n - j); mzd_clear_bits(U, i, j, length); } } } mzd_mul(A,L,U,0); mzd_free(L); mzd_free(U); } else { mzd_randomize(A); } #ifndef HAVE_LIBPAPI *data_len = 2; #else *data_len = MIN(papi_array_len + 1, *data_len); #endif int papi_res; #ifndef HAVE_LIBPAPI data[0] = walltime(0); data[1] = cpucycles(); #else int array_len = *data_len - 1; unsigned long long t0 = PAPI_get_virt_usec(); papi_res = PAPI_start_counters((int*)papi_events, array_len); if(papi_res) m4ri_die(""); #endif #ifndef HAVE_LIBPAPI data[1] = cpucycles() - data[1]; data[0] = walltime(data[0]); #else PAPI_stop_counters((long long*)&data[1], array_len); t0 = PAPI_get_virt_usec() - t0; data[0] = t0; for (int nv = 0; nv <= array_len; ++nv) { if (data[nv] < loop_calibration[nv]) loop_calibration[nv] = data[nv]; } #endif mzd_free(A); return (0); }
void _qseive(const mp_limb_t n, const mp_limb_t B) { nmod_sparse_mat_t M; mp_limb_t quad, *quads, *xs, x, i = 0, j, piB = n_prime_pi(B); const mp_limb_t * ps = n_primes_arr_readonly(piB + 2); const double * pinvs = n_prime_inverses_arr_readonly(piB + 2); mzd_t *K; /* init */ quads = (mp_limb_t *)malloc((piB + 1)*sizeof(mp_limb_t *)); xs = (mp_limb_t *)malloc((piB + 1)*sizeof(mp_limb_t *)); K = mzd_init(piB + 1, 1); nmod_sparse_mat_init(M, piB + 1, piB + 1, 2); printf("init done\n"); printf("using %ld primes\n", piB); /* seive */ for (x = n_sqrt(n), i = 0; i <= piB; x++) { quad = x*x - n; if (quad == 0) continue; for (j = 0; j < piB; j++) n_remove2_precomp(&quad, ps[j], pinvs[j]); if (quad == 1) /* was B-smooth */ { quads[i] = x*x - n; quad = x*x - n; for (j = 0; j < piB; j++) { if (n_remove2_precomp(&quad, ps[j], pinvs[j]) % 2) _nmod_sparse_mat_set_entry(M, j, i, M->row_supports[j], 1); } xs[i] = x; i++; } } printf("data collection done\n"); n_cleanup_primes(); _bw(K, M, 1, 2, 7, 7); printf("procesing complete\n"); mzd_print(K); int done = 0; for (j = 0; !done; j++) { fmpz_t a, b, diff, N; fmpz_init_set_ui(a, 1); fmpz_init_set_ui(b, 1); fmpz_init_set_ui(N, n); fmpz_init(diff); for (i = 0; i < piB; i++) { if (mzd_read_bit(K, i, j)) { fmpz_mul_ui(a, a, xs[i]); fmpz_mul_ui(b, b, quads[i]); } } assert(fmpz_is_square(b)); fmpz_sqrt(b, b); if (fmpz_mod_ui(a, a, n) != fmpz_mod_ui(b, b, n) && fmpz_mod_ui(a, a, n) != n - fmpz_mod_ui(b, b, n)) { done = 1; fmpz_print(a); printf("\n"); fmpz_print(b); printf("\n"); fmpz_sub(diff, a, b); fmpz_gcd(a, diff, N); fmpz_divexact(b, N, a); fmpz_print(a); printf("\n"); fmpz_print(b); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(N); fmpz_clear(diff); } /* cleanup */ free(quads); free(xs); mzd_free(K); nmod_sparse_mat_clear(M); return; }
void free_matrix(gf2matrix *m) { if(!m) return; mzd_free(m); }
int test_lqup_half_rank(size_t m, size_t n) { printf("pluq: testing half rank m: %5zd, n: %5zd",m,n); mzd_t* U = mzd_init(m, n); mzd_t* L = mzd_init(m, m); mzd_t* U2 = mzd_init(m, n); mzd_t* L2 = mzd_init(m, m); mzd_t* A = mzd_init(m, n); mzd_randomize (U); mzd_randomize (L); size_t i,j; for (i=0; i<m && i<n; ++i){ mzd_write_bit(U,i,i, 1); for (j=0; j<i;++j) mzd_write_bit(U,i,j, 0); if (i%2) for (j=i; j<n;++j) mzd_write_bit(U,i,j, 0); for (j=i+1; j<m;++j) mzd_write_bit(L,i,j, 0); mzd_write_bit(L,i,i, 1); } mzd_mul(A, L, U, 0); mzd_t* Acopy = mzd_copy (NULL,A); mzp_t* Pt = mzp_init(m); mzp_t* Q = mzp_init(n); int r = mzd_pluq(A, Pt, Q, 0); for (i=0; i<r; ++i){ for (j=0; j<i;++j) mzd_write_bit (L2, i, j, mzd_read_bit(A,i,j)); for (j=i+1; j<n;++j) mzd_write_bit (U2, i, j, mzd_read_bit(A,i,j)); } for (i=r; i<m; i++) for (j=0; j<r;++j) mzd_write_bit (L2, i, j, mzd_read_bit(A,i,j)); for (i=0; i<r; ++i){ mzd_write_bit(L2,i,i, 1); mzd_write_bit(U2,i,i, 1); } mzd_apply_p_left(Acopy, Pt); mzd_apply_p_right_trans(Acopy, Q); mzd_addmul(Acopy,L2,U2,0); int status = 0; for ( i=0; i<m; ++i) { for ( j=0; j<n; ++j){ if (mzd_read_bit(Acopy,i,j)){ status = 1; } } if(status) break; } if (status) printf(" ... FAILED\n"); else printf (" ... passed\n"); mzd_free(U); mzd_free(L); mzd_free(U2); mzd_free(L2); mzd_free(A); mzd_free(Acopy); mzp_free(Pt); mzp_free(Q); return status; }