コード例 #1
0
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;
}
コード例 #2
0
ファイル: test_trsm.c プロジェクト: yp/Heu-MCHC
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;
}
コード例 #3
0
int addmul_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, *F;
  
  printf("addmul: 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);
  C = mzd_init(m, n);
  mzd_randomize(A);
  mzd_randomize(B);
  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, B, k);

  /* E = C + A*B via naiv cubic multiplication */
  E = mzd_mul_m4rm(NULL, A, B, k);
  mzd_add(E, E, C);

  /* F = C + A*B via naiv cubic multiplication */
  F = mzd_copy(NULL, C);
  F = mzd_addmul(F, A, B, cutoff);

  mzd_free(A);
  mzd_free(B);
  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;
}
コード例 #4
0
ファイル: test_trsm.c プロジェクト: yp/Heu-MCHC
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;
}
コード例 #5
0
/**
 * 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;

}
コード例 #6
0
ファイル: test_kernel.c プロジェクト: yp/Heu-MCHC
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;
}
コード例 #7
0
ファイル: test_lqup.c プロジェクト: yp/Heu-MCHC
int test_lqup_random(size_t m, size_t n) {
  printf("pluq: testing random m: %5zd, n: %5zd",m,n);

  size_t i,j;
  mzd_t* U = mzd_init(m, n);
  mzd_t* L = mzd_init(m, m);
  mzd_t* A = mzd_init(m, n);
  mzd_randomize(A);

  mzd_t* Acopy = mzd_copy (NULL,A);

  mzp_t* P = mzp_init(m);
  mzp_t* Q = mzp_init(n);
  int r;
  r=mzd_pluq(A, P, Q, 0);
  printf(", rank: %5d ",r);

  for (i=0; i<r; ++i){
    for (j=0; j<i;++j)
      mzd_write_bit(L, i, j, mzd_read_bit(A,i,j));
    for (j=i+1; j<n;++j)
      mzd_write_bit(U, i, j, mzd_read_bit(A,i,j));
  }
  for (i=r; i<m; i++)
    for (j=0; j<r;++j)
      mzd_write_bit(L, i, j, mzd_read_bit(A,i,j));
  for (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 ( i=0; i<m; ++i)
    for ( j=0; j<n; ++j){
      if (mzd_read_bit (Acopy,i,j)){
	status = 1;
        break;
      }
    }
  if (status) {
    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;
}
コード例 #8
0
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;
}
コード例 #9
0
ファイル: m4rjni.c プロジェクト: brentondwalker/m4rjni
/*
 * Class:     m4rjni_Mzd
 * Method:    mzd_randomize
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_m4rjni_Mzd_mzd_1randomize(JNIEnv *env, jobject obj, jlong ptr) {
  mzd_t *M = (mzd_t*)ptr;
  if (M==NULL) return;
  mzd_randomize(M);
}
コード例 #10
0
ファイル: bench_rank.c プロジェクト: jpflori/m4ri
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;
}
コード例 #11
0
ファイル: bench_rank.c プロジェクト: jpflori/m4ri
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);
}
コード例 #12
0
void randomize_matrix(gf2matrix *m)
{
	mzd_randomize(m);
}
コード例 #13
0
ファイル: test_lqup.c プロジェクト: yp/Heu-MCHC
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;
}
コード例 #14
0
ファイル: test_lqup.c プロジェクト: yp/Heu-MCHC
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;
}
コード例 #15
0
int smallops_test_add(rci_t M, rci_t N, rci_t m, rci_t n, rci_t offset, word pattern) {
  int ret = 0; 

  printf("      mzd_add: M: %4d, N: %4d, m: %4d, n: %4d, offset: %4d, pattern: 0x%" PRIx64 " ", M, N, m, n, offset, pattern);

  mzd_t *AA;
  mzd_t *A = mzd_init_test_matrix_random(M, N, m, n, offset, pattern, &AA);

  mzd_t *BB;
  mzd_t *B = mzd_init_test_matrix_random(M, N, m, n, offset, pattern, &BB);

  mzd_t *CC;
  mzd_t *C = mzd_init_test_matrix_random(M, N, m, n, offset, pattern, &CC);

  mzd_t *DD;
  mzd_t *D = mzd_init_test_matrix_random(M, N, m, n, offset, pattern, &DD);

  /* Creation went okay? */

  ret += mzd_check_pattern(AA, m, n, offset, pattern);
  ret += mzd_check_pattern(BB, m, n, offset, pattern);
  ret += mzd_check_pattern(CC, m, n, offset, pattern);
  ret += mzd_check_pattern(DD, m, n, offset, pattern);

  /* Testing equality A+A == 0 */

  mzd_add(C, A, A);

  if(!mzd_is_zero(C)) {
    ret +=1;
  }

  ret += mzd_check_pattern(AA, m, n, offset, pattern);
  ret += mzd_check_pattern(BB, m, n, offset, pattern);
  ret += mzd_check_pattern(CC, m, n, offset, pattern);

  /* Testing equality A+A == 0 but this time C is already zero */

  mzd_add(C, B, B);

  if(!mzd_is_zero(C)) {
    ret +=1;
  }

  ret += mzd_check_pattern(AA, m, n, offset, pattern);
  ret += mzd_check_pattern(BB, m, n, offset, pattern);
  ret += mzd_check_pattern(CC, m, n, offset, pattern);

  /* Testing in place add. C is zero, so afterwards C == A */

  mzd_add(C, C, A);

  if(!mzd_equal(C,A)) {
    ret +=1;
  }

  ret += mzd_check_pattern(AA, m, n, offset, pattern);
  ret += mzd_check_pattern(BB, m, n, offset, pattern);
  ret += mzd_check_pattern(CC, m, n, offset, pattern);

  /* Testing equality C (== A) + A == 0 */

  mzd_add(B, C, A);

  if(!mzd_is_zero(B)) {
    ret +=1;
  }


  if(m == n) {
    /* Testing equality (A + B)^2 == A^2 + BA + AB + B^2 */

    mzd_randomize(A);
    mzd_randomize(B);
    
    mzd_add(C,A,B);
    
    mzd_mul(D,C,C, 0); // (A+B)^2
    
    mzd_mul(C,A,A, 0); 
    mzd_addmul(C, B, A, 0);
    mzd_addmul(C, A, B, 0);
    mzd_addmul(C, B, B, 0);
    
    if(!mzd_equal(C,D)) {
      ret += 1;
    }

    ret += mzd_check_pattern(AA, m, n, offset, pattern);
    ret += mzd_check_pattern(BB, m, n, offset, pattern);
    ret += mzd_check_pattern(CC, m, n, offset, pattern);
    ret += mzd_check_pattern(DD, m, n, offset, pattern);
  }

  mzd_free_test_matrix_random(AA, A);
  mzd_free_test_matrix_random(BB, B);
  mzd_free_test_matrix_random(CC, C);
  mzd_free_test_matrix_random(DD, D);

  if(ret == 0) {
    printf(" ... passed\n");
  } else {
    printf(" ... FAILED\n");
  }
#ifdef ABORT_ON_FAIL
  if (ret) abort();
#endif

  return ret;
}