Пример #1
0
/* Simple convenience wrapper for conjugate gradient solver */
static void
solve_cg_bem2d(matrixtype type, void *A, pavector b, pavector x,
	       real accuracy, uint steps)
{
  addeval_t addevalA;
  pavector  r, p, a;
  uint      i, n;
  real      norm;

  switch (type) {
  case AMATRIX:
    addevalA = (addeval_t) addeval_amatrix_avector;
    break;
  case HMATRIX:
    addevalA = (addeval_t) addeval_hmatrix_avector;
    break;
  case H2MATRIX:
    addevalA = (addeval_t) addeval_h2matrix_avector;
    break;
  default:
    printf("ERROR: unknown matrix type!\n");
    abort();
    break;
  }

  n = b->dim;
  assert(x->dim == n);

  r = new_avector(n);
  p = new_avector(n);
  a = new_avector(n);
  random_avector(x);

  init_cg(addevalA, A, b, x, r, p, a);

  for (i = 1; i < steps; i++) {
    step_cg(addevalA, A, b, x, r, p, a);
    norm = norm2_avector(r);
#ifndef NDEBUG
    printf("  Residual: %.5e\t Iterations: %u\r", norm, i);
    fflush(stdout);
#endif
    if (norm <= accuracy) {
      break;
    }
  }
#ifndef NDEBUG
  printf("  Residual: %.5e\t Iterations: %u\n", norm2_avector(r), i);
#endif

  del_avector(r);
  del_avector(p);
  del_avector(a);

}
Пример #2
0
real
norm2chol_sparsematrix(pchmatrix LU, pcsparsematrix sp)
{
  avector   tmp1, tmp2;
  uint      rows = LU->rc->size;
  uint      cols = LU->cc->size;
  pavector  x, y;
  real      norm;
  uint      j;

  assert(sp->rows == rows);
  assert(sp->cols == cols);

  x = init_avector(&tmp1, cols);
  y = init_avector(&tmp2, rows);

  random_avector(x);
  norm = norm2_avector(x);
  scale_avector(1.0 / norm, x);

  for (j = 0; j < NORM_STEPS; j++) {
    // printf("norm = %g \n", sqrt( norm));
    clear_avector(y);
    mvm_sparsematrix_avector(1.0, false, sp, x, y);
    triangularsolve_hmatrix_avector(true, false, false, LU, y);
    triangularsolve_hmatrix_avector(true, false, true, LU, y);
    add_avector(-1.0, y, x);
    copy_avector(x, y);
    triangularsolve_hmatrix_avector(true, false, false, LU, y);
    triangularsolve_hmatrix_avector(true, false, true, LU, y);
    mvm_sparsematrix_avector(-1.0, true, sp, y, x);
    norm = norm2_avector(x);
    scale_avector(1.0 / norm, x);
  }

  uninit_avector(y);
  uninit_avector(x);

  return REAL_SQRT(norm);
}
Пример #3
0
int
main()
{
    pamatrix  a, acopy, l, ld, r, q, qr;
    pavector  x, b, tau;
    uint      rows, cols;
    real      error;

    rows = 8;
    cols = 5;

    (void) printf("----------------------------------------\n"
                  "Check random %u x %u Cholesky factorization\n", rows, rows);

    (void) printf("Creating random self-adjoint positive definite matrix\n");
    a = new_amatrix(rows, rows);
    random_spd_amatrix(a, 1.0);

    (void) printf("Creating random solution and right-hand side\n");
    x = new_avector(rows);
    random_avector(x);
    b = new_avector(rows);
    clear_avector(b);
    mvm_amatrix_avector(1.0, false, a, x, b);

    (void) printf("Copying matrix\n");
    acopy = new_amatrix(rows, rows);
    copy_amatrix(false, a, acopy);

    (void) printf("Computing Cholesky factorization\n");
    choldecomp_amatrix(a);

    (void) printf("Solving\n");
    cholsolve_amatrix_avector(a, b);
    add_avector(-1.0, x, b);
    error = norm2_avector(b);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    (void) printf("Building triangular factor\n");
    l = new_amatrix(rows, rows);
    copy_lower_amatrix(a, false, l);

    (void) printf("Checking factorization\n");
    copy_amatrix(false, acopy, a);
    addmul_amatrix(-1.0, false, l, true, l, a);
    error = normfrob_amatrix(a);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    del_amatrix(l);
    del_amatrix(acopy);
    del_avector(b);
    del_avector(x);
    del_amatrix(a);

    (void) printf("----------------------------------------\n"
                  "Check random %u x %u LDL^T factorization\n", rows, rows);

    (void) printf("Creating random self-adjoint positive definite matrix\n");
    a = new_amatrix(rows, rows);
    random_spd_amatrix(a, 1.0);

    (void) printf("Creating random solution and right-hand side\n");
    x = new_avector(rows);
    random_avector(x);
    b = new_avector(rows);
    clear_avector(b);
    mvm_amatrix_avector(1.0, false, a, x, b);

    (void) printf("Copying matrix\n");
    acopy = new_amatrix(rows, rows);
    copy_amatrix(false, a, acopy);

    (void) printf("Computing LDL^T factorization\n");
    ldltdecomp_amatrix(a);

    (void) printf("Solving\n");
    ldltsolve_amatrix_avector(a, b);
    add_avector(-1.0, x, b);
    error = norm2_avector(b);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    (void) printf("Building triangular factor\n");
    l = new_amatrix(rows, rows);
    copy_lower_amatrix(a, true, l);

    (void) printf("Multiplying by diagonal\n");
    ld = new_amatrix(rows, rows);
    copy_amatrix(false, l, ld);
    diageval_amatrix(true, a, true, ld);

    (void) printf("Checking factorization\n");
    copy_amatrix(false, acopy, a);
    addmul_amatrix(-1.0, false, ld, true, l, a);
    error = normfrob_amatrix(a);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    del_amatrix(ld);
    del_amatrix(l);
    del_amatrix(acopy);
    del_avector(b);
    del_avector(x);
    del_amatrix(a);

    (void) printf("----------------------------------------\n"
                  "Check random %u x %u LR factorization\n", rows, rows);

    (void) printf("Creating random invertible matrix\n");
    a = new_amatrix(rows, rows);
    random_invertible_amatrix(a, 1.0);

    (void) printf("Creating random solution and right-hand side\n");
    x = new_avector(rows);
    random_avector(x);
    b = new_avector(rows);
    clear_avector(b);
    mvm_amatrix_avector(1.0, false, a, x, b);

    (void) printf("Copying matrix\n");
    acopy = new_amatrix(rows, rows);
    copy_amatrix(false, a, acopy);

    (void) printf("Computing LR factorization\n");
    lrdecomp_amatrix(a);

    (void) printf("Solving\n");
    lrsolve_amatrix_avector(a, b);
    add_avector(-1.0, x, b);
    error = norm2_avector(b);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    (void) printf("Building triangular factors\n");
    l = new_amatrix(rows, rows);
    r = new_amatrix(rows, rows);
    copy_lower_amatrix(a, true, l);
    copy_upper_amatrix(a, false, r);

    (void) printf("Checking factorization\n");
    copy_amatrix(false, acopy, a);
    addmul_amatrix(-1.0, false, l, false, r, a);
    error = normfrob_amatrix(a);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    /* Check forward/backward substitution */
    (void) printf("----------------------------------------\n");
    check_triangularsolve(true, true, false, l, false);
    check_triangularsolve(true, true, false, l, true);
    check_triangularsolve(true, true, true, l, false);
    check_triangularsolve(true, true, true, l, true);
    check_triangularsolve(true, false, false, l, false);
    check_triangularsolve(true, false, false, l, true);
    check_triangularsolve(true, false, true, l, false);
    check_triangularsolve(true, false, true, l, true);

    check_triangularsolve(false, false, false, r, false);
    check_triangularsolve(false, false, false, r, true);
    check_triangularsolve(false, false, true, r, false);
    check_triangularsolve(false, false, true, r, true);
    set_unit(r);
    check_triangularsolve(false, true, false, r, false);
    check_triangularsolve(false, true, false, r, true);
    check_triangularsolve(false, true, true, r, false);
    check_triangularsolve(false, true, true, r, true);

    /* Intermediate clean-up */
    (void) printf("Cleaning up\n");
    del_amatrix(r);
    del_amatrix(l);

    /* Check triangular matrix multiplication */
    (void) printf("----------------------------------------\n");
    check_triangularaddmul(false, false, false, false);
    check_triangularaddmul(true, false, false, false);
    check_triangularaddmul(false, true, false, false);
    check_triangularaddmul(true, true, false, false);

    check_triangularaddmul(false, false, true, false);
    check_triangularaddmul(true, false, true, false);
    check_triangularaddmul(false, true, true, false);
    check_triangularaddmul(true, true, true, false);

    check_triangularaddmul(false, false, false, true);
    check_triangularaddmul(true, false, false, true);
    check_triangularaddmul(false, true, false, true);
    check_triangularaddmul(true, true, false, true);

    check_triangularaddmul(false, false, true, true);
    check_triangularaddmul(true, false, true, true);
    check_triangularaddmul(false, true, true, true);
    check_triangularaddmul(true, true, true, true);

    /* Checking QR factorization */
    (void) printf("----------------------------------------\n"
                  "Check square QR factorization\n");
    copy_amatrix(false, acopy, a);
    random_avector(x);
    clear_avector(b);
    mvm_amatrix_avector(1.0, false, a, x, b);

    tau = new_avector(rows);
    qrdecomp_amatrix(a, tau);

    (void) printf("Solving\n");
    qrsolve_amatrix_avector(a, tau, b);
    add_avector(-1.0, x, b);
    error = norm2_avector(b);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    q = new_amatrix(rows, rows);
    qrexpand_amatrix(a, tau, q);

    (void) printf("Checking factorization\n");
    r = new_amatrix(rows, rows);
    copy_upper_amatrix(a, false, r);
    qr = new_amatrix(rows, rows);
    copy_amatrix(false, acopy, qr);
    addmul_amatrix(-1.0, false, q, false, r, qr);
    error = normfrob_amatrix(qr);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    (void) printf("Checking inverse\n");
    copy_amatrix(false, acopy, a);
    qrinvert_amatrix(a);

    identity_amatrix(qr);
    addmul_amatrix(-1.0, false, acopy, false, a, qr);
    error = normfrob_amatrix(qr);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    /* Intermediate clean-up */
    (void) printf("Cleaning up\n");

    del_amatrix(qr);
    del_amatrix(r);
    del_amatrix(q);
    del_avector(tau);
    del_avector(b);
    del_avector(x);
    del_amatrix(acopy);
    del_amatrix(a);

    /* Check forward/backward evaluation */
    (void) printf("----------------------------------------\n");
    a = new_amatrix(rows, cols);
    random_amatrix(a);
    check_lowereval(false, false, a, false);
    check_lowereval(false, false, a, true);
    check_lowereval(false, true, a, false);
    check_lowereval(false, true, a, true);
    check_uppereval(false, false, a, false);
    check_uppereval(false, false, a, true);
    check_uppereval(false, true, a, false);
    check_uppereval(false, true, a, true);
    set_unit(a);
    check_lowereval(true, false, a, false);
    check_lowereval(true, false, a, true);
    check_lowereval(true, true, a, false);
    check_lowereval(true, true, a, true);
    check_uppereval(true, false, a, false);
    check_uppereval(true, false, a, true);
    check_uppereval(true, true, a, false);
    check_uppereval(true, true, a, true);
    (void) printf("Cleaning up\n");
    del_amatrix(a);
    a = new_amatrix(cols, rows);
    random_amatrix(a);
    check_lowereval(false, false, a, false);
    check_lowereval(false, false, a, true);
    check_lowereval(false, true, a, false);
    check_lowereval(false, true, a, true);
    check_uppereval(false, false, a, false);
    check_uppereval(false, false, a, true);
    check_uppereval(false, true, a, false);
    check_uppereval(false, true, a, true);
    set_unit(a);
    check_lowereval(true, false, a, false);
    check_lowereval(true, false, a, true);
    check_lowereval(true, true, a, false);
    check_lowereval(true, true, a, true);
    check_uppereval(true, false, a, false);
    check_uppereval(true, false, a, true);
    check_uppereval(true, true, a, false);
    check_uppereval(true, true, a, true);
    (void) printf("Cleaning up\n");
    del_amatrix(a);

    /* Test random QR factorizations */
    (void) printf("----------------------------------------\n"
                  "Check full rectangular QR factorization\n");
    a = new_amatrix(rows, cols);
    random_amatrix(a);
    acopy = new_amatrix(rows, cols);
    copy_amatrix(false, a, acopy);

    tau = new_avector(rows);
    qrdecomp_amatrix(a, tau);
    q = new_amatrix(rows, rows);
    r = new_amatrix(rows, cols);
    qrexpand_amatrix(a, tau, q);
    copy_upper_amatrix(a, false, r);
    qr = new_amatrix(rows, cols);
    copy_amatrix(false, acopy, qr);
    addmul_amatrix(-1.0, false, q, false, r, qr);
    error = normfrob_amatrix(qr);
    printf("  Accuracy %g, %sokay\n", error,
           (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    del_amatrix(r);
    del_amatrix(q);

    (void) printf("Check skinny QR factorization\n");
    q = new_amatrix(rows, cols);
    r = new_amatrix(cols, cols);
    qrexpand_amatrix(a, tau, q);
    copy_upper_amatrix(a, false, r);
    copy_amatrix(false, acopy, qr);
    addmul_amatrix(-1.0, false, q, false, r, qr);
    error = normfrob_amatrix(qr);
    printf("  Accuracy %g, %sokay\n", error,
           (error < tolerance ? "" : "    NOT "));
    if (error >= tolerance)
        problems++;

    /* Final clean-up */
    (void) printf("Cleaning up\n");
    del_amatrix(qr);
    del_amatrix(r);
    del_amatrix(q);
    del_avector(tau);
    del_amatrix(acopy);
    del_amatrix(a);

    (void) printf("----------------------------------------\n"
                  "  %u matrices and\n"
                  "  %u vectors still active\n"
                  "  %u errors found\n", getactives_amatrix(),
                  getactives_avector(), problems);

    return problems;
}
Пример #4
0
static void
check_triangularsolve(bool lower, bool unit, bool atrans,
                      pcamatrix a, bool xtrans)
{
    uint      n = a->rows;
    amatrix   xtmp, btmp;
    pamatrix  x, b;
    avector   xvtmp, bvtmp;
    pavector  xv, bv;
    real      error;

    assert(n == a->cols);

    /*
     * amatrix
     */

    x = init_amatrix(&xtmp, n, n);
    random_amatrix(x);

    b = init_zero_amatrix(&btmp, n, n);

    if (xtrans)
        addmul_amatrix(1.0, false, x, !atrans, a, b);
    else
        addmul_amatrix(1.0, atrans, a, false, x, b);

    triangularsolve_amatrix(lower, unit, atrans, a, xtrans, b);

    add_amatrix(-1.0, false, x, b);
    error = norm2_amatrix(b) / norm2_amatrix(x);

    (void) printf("Checking amatrix triangularsolve\n"
                  "  (lower=%s, unit=%s, atrans=%s, xtrans=%s)\n"
                  "  Accuracy %g, %sokay\n", (lower ? "tr" : "fl"),
                  (unit ? "tr" : "fl"), (atrans ? "tr" : "fl"),
                  (xtrans ? "tr" : "fl"), error,
                  (IS_IN_RANGE(0.0, error, 1.0e-14) ? "" : "    NOT "));
    if (!IS_IN_RANGE(0.0, error, 1.0e-14))
        problems++;

    copy_amatrix(false, x, b);
    triangulareval_amatrix(lower, unit, atrans, a, xtrans, b);

    triangularsolve_amatrix(lower, unit, atrans, a, xtrans, b);

    add_amatrix(-1.0, false, x, b);
    error = norm2_amatrix(b) / norm2_amatrix(x);

    (void) printf("Checking amatrix triangulareval/triangularsolve\n"
                  "  (lower=%s, unit=%s, atrans=%s, xtrans=%s):\n"
                  "  Accuracy %g, %sokay\n", (lower ? "tr" : "fl"),
                  (unit ? "tr" : "fl"), (atrans ? "tr" : "fl"),
                  (xtrans ? "tr" : "fl"), error,
                  (IS_IN_RANGE(0.0, error, 1.0e-14) ? "" : "    NOT "));
    if (!IS_IN_RANGE(0.0, error, 1.0e-14))
        problems++;

    /*
     * avector
     */

    xv = init_avector(&xvtmp, n);
    random_avector(xv);

    bv = init_avector(&bvtmp, n);
    clear_avector(bv);

    if (atrans) {
        addevaltrans_amatrix_avector(1.0, a, xv, bv);
    }
    else {
        addeval_amatrix_avector(1.0, a, xv, bv);
    }

    triangularsolve_amatrix_avector(lower, unit, atrans, a, bv);

    add_avector(-1.0, xv, bv);
    error = norm2_avector(bv) / norm2_avector(xv);

    (void) printf("Checking avector triangularsolve\n"
                  "  (lower=%s, unit=%s, atrans=%s)\n"
                  "  Accuracy %g, %sokay\n", (lower ? "tr" : "fl"),
                  (unit ? "tr" : "fl"), (atrans ? "tr" : "fl"), error,
                  (IS_IN_RANGE(0.0, error, 1.0e-14) ? "" : "    NOT "));
    if (!IS_IN_RANGE(0.0, error, 1.0e-14))
        problems++;

    copy_avector(xv, bv);
    triangulareval_amatrix_avector(lower, unit, atrans, a, bv);

    triangularsolve_amatrix_avector(lower, unit, atrans, a, bv);

    add_avector(-1.0, xv, bv);
    error = norm2_avector(bv) / norm2_avector(xv);

    (void) printf("Checking avector triangulareval/triangularsolve\n"
                  "  (lower=%s, unit=%s, atrans=%s):\n"
                  "  Accuracy %g, %sokay\n", (lower ? "tr" : "fl"),
                  (unit ? "tr" : "fl"), (atrans ? "tr" : "fl"), error,
                  (IS_IN_RANGE(0.0, error, 1.0e-14) ? "" : "    NOT "));
    if (!IS_IN_RANGE(0.0, error, 1.0e-14))
        problems++;

    uninit_amatrix(b);
    uninit_amatrix(x);
    uninit_avector(bv);
    uninit_avector(xv);
}
Пример #5
0
int
main()
{
    ph2matrix h2, h2copy, L, R;
    pclusterbasis rb, cb, rbcopy, cbcopy, rblow, cblow, rbup, cbup;
    pclusteroperator rwf, cwf, rwflow, cwflow, rwfup, cwfup, rwfh2, cwfh2;
    ptruncmode tm;

    pavector  x, b;
    uint      n;
    real      error;
    pcurve2d  gr2;
    pbem2d    bem2;
    pcluster  root2;
    pblock    block2;
    uint      clf, m;
    real      tol, eta, delta, eps_aca;

    n = 579;
    tol = 1.0e-13;

    clf = 16;
    eta = 1.0;
    m = 4;
    delta = 1.0;
    eps_aca = 1.0e-13;

    gr2 = new_circle_curve2d(n, 0.333);
    bem2 = new_slp_laplace_bem2d(gr2, 2, BASIS_CONSTANT_BEM2D);
    root2 = build_bem2d_cluster(bem2, clf, BASIS_CONSTANT_BEM2D);
    block2 = build_strict_block(root2, root2, &eta, admissible_max_cluster);

    rb = build_from_cluster_clusterbasis(root2);
    cb = build_from_cluster_clusterbasis(root2);
    setup_h2matrix_aprx_greenhybrid_bem2d(bem2, rb, cb, block2, m, 1, delta,
                                          eps_aca, build_bem2d_rect_quadpoints);

    (void) printf("----------------------------------------\n"
                  "Check %u x %u Cholesky factorization\n", n, n);

    (void) printf("Creating laplacebem2d SLP matrix\n");
    assemble_bem2d_h2matrix_row_clusterbasis(bem2, rb);
    assemble_bem2d_h2matrix_col_clusterbasis(bem2, cb);
    h2 = build_from_block_h2matrix(block2, rb, cb);
    assemble_bem2d_h2matrix(bem2, block2, h2);

    (void) printf("Creating random solution and right-hand side\n");
    x = new_avector(n);
    random_avector(x);
    b = new_avector(n);
    clear_avector(b);
    mvm_h2matrix_avector(1.0, false, h2, x, b);

    (void) printf("Copying matrix\n");

    rbcopy = clone_clusterbasis(h2->rb);
    cbcopy = clone_clusterbasis(h2->cb);
    h2copy = clone_h2matrix(h2, rbcopy, cbcopy);


    (void) printf("Computing Cholesky factorization\n");

    tm = new_releucl_truncmode();
    rblow = build_from_cluster_clusterbasis(root2);
    cblow = build_from_cluster_clusterbasis(root2);
    L = build_from_block_lower_h2matrix(block2, rblow, cblow);

    rwflow = prepare_row_clusteroperator(L->rb, L->cb, tm);
    cwflow = prepare_col_clusteroperator(L->rb, L->cb, tm);
    rwf = NULL;
    cwf = NULL;
    init_cholesky_h2matrix(h2, &rwf, &cwf, tm);
    choldecomp_h2matrix(h2, rwf, cwf, L, rwflow, cwflow, tm, tol);

    (void) printf("Solving\n");

    cholsolve_h2matrix_avector(L, b);

    add_avector(-1.0, x, b);
    error = norm2_avector(b) / norm2_avector(x);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  IS_IN_RANGE(2.0e-13, error, 3.0e-12) ? "" : "    NOT ");
    if (!IS_IN_RANGE(2.0e-13, error, 3.0e-12))
        problems++;

    rwfh2 = prepare_row_clusteroperator(h2copy->rb, h2copy->cb, tm);
    cwfh2 = prepare_col_clusteroperator(h2copy->rb, h2copy->cb, tm);

    (void) printf("Checking factorization\n");
    error = norm2_h2matrix(h2copy);
    addmul_h2matrix(-1.0, L, true, L, h2copy, rwfh2, cwfh2, tm, tol);
    error = norm2_h2matrix(h2copy) / error;
    (void) printf("  Accuracy %g, %sokay\n", error,
                  IS_IN_RANGE(4.0e-15, error, 4.0e-14) ? "" : "    NOT ");
    if (!IS_IN_RANGE(4.0e-15, error, 4.0e-14))
        problems++;




    del_h2matrix(h2copy);
    del_h2matrix(h2);
    del_h2matrix(L);
    del_avector(b);
    del_avector(x);
    del_truncmode(tm);

    del_clusteroperator(rwflow);
    del_clusteroperator(cwflow);
    del_clusteroperator(rwf);
    del_clusteroperator(cwf);
    del_clusteroperator(rwfh2);
    del_clusteroperator(cwfh2);


    rb = build_from_cluster_clusterbasis(root2);
    cb = build_from_cluster_clusterbasis(root2);
    setup_h2matrix_aprx_greenhybrid_bem2d(bem2, rb, cb, block2, m, 1, delta,
                                          eps_aca, build_bem2d_rect_quadpoints);

    (void) printf("----------------------------------------\n"
                  "Check %u x %u LR factorization\n", n, n);

    (void) printf("Creating laplacebem2d SLP matrix\n");
    assemble_bem2d_h2matrix_row_clusterbasis(bem2, rb);
    assemble_bem2d_h2matrix_col_clusterbasis(bem2, cb);
    h2 = build_from_block_h2matrix(block2, rb, cb);
    assemble_bem2d_h2matrix(bem2, block2, h2);

    (void) printf("Creating random solution and right-hand side\n");
    x = new_avector(n);
    random_avector(x);
    b = new_avector(n);
    clear_avector(b);
    mvm_h2matrix_avector(1.0, false, h2, x, b);

    (void) printf("Copying matrix\n");
    rbcopy = clone_clusterbasis(h2->rb);
    cbcopy = clone_clusterbasis(h2->cb);
    h2copy = clone_h2matrix(h2, rbcopy, cbcopy);

    (void) printf("Computing LR factorization\n");
    rblow = build_from_cluster_clusterbasis(root2);
    cblow = build_from_cluster_clusterbasis(root2);
    L = build_from_block_lower_h2matrix(block2, rblow, cblow);

    rbup = build_from_cluster_clusterbasis(root2);
    cbup = build_from_cluster_clusterbasis(root2);
    R = build_from_block_upper_h2matrix(block2, rbup, cbup);

    tm = new_releucl_truncmode();
    rwf = prepare_row_clusteroperator(h2->rb, h2->cb, tm);
    cwf = prepare_col_clusteroperator(h2->rb, h2->cb, tm);
    rwflow = prepare_row_clusteroperator(L->rb, L->cb, tm);
    cwflow = prepare_col_clusteroperator(L->rb, L->cb, tm);
    rwfup = prepare_row_clusteroperator(R->rb, R->cb, tm);
    cwfup = prepare_col_clusteroperator(R->rb, R->cb, tm);

    lrdecomp_h2matrix(h2, rwf, cwf, L, rwflow, cwflow, R, rwfup, cwfup, tm,
                      tol);

    (void) printf("Solving\n");
    lrsolve_h2matrix_avector(L, R, b);

    add_avector(-1.0, x, b);
    error = norm2_avector(b) / norm2_avector(x);
    (void) printf("  Accuracy %g, %sokay\n", error,
                  IS_IN_RANGE(2e-13, error, 2e-12) ? "" : "    NOT ");
    if (!IS_IN_RANGE(2e-13, error, 2e-12))
        problems++;


    rwfh2 = prepare_row_clusteroperator(h2copy->rb, h2copy->cb, tm);
    cwfh2 = prepare_col_clusteroperator(h2copy->rb, h2copy->cb, tm);

    (void) printf("Checking factorization\n");
    error = norm2_h2matrix(h2copy);
    addmul_h2matrix(-1.0, L, false, R, h2copy, rwfh2, cwfh2, tm, tol);
    error = norm2_h2matrix(h2copy) / error;
    (void) printf("  Accuracy %g, %sokay\n", error,
                  IS_IN_RANGE(4.0e-15, error, 5.0e-14) ? "" : "    NOT ");
    if (!IS_IN_RANGE(4.0e-15, error, 5.0e-14))
        problems++;


    /* Final clean-up */
    (void) printf("Cleaning up\n");

    del_h2matrix(h2);
    del_h2matrix(h2copy);
    del_h2matrix(L);
    del_h2matrix(R);
    del_clusteroperator(rwf);
    del_clusteroperator(cwf);
    del_clusteroperator(rwflow);
    del_clusteroperator(cwflow);
    del_clusteroperator(rwfup);
    del_clusteroperator(cwfup);
    del_clusteroperator(rwfh2);
    del_clusteroperator(cwfh2);

    del_avector(b);
    del_avector(x);
    del_truncmode(tm);

    freemem(root2->idx);
    del_bem2d(bem2);
    del_block(block2);
    del_cluster(root2);
    del_curve2d(gr2);

    (void) printf("----------------------------------------\n"
                  "  %u matrices and\n"
                  "  %u vectors still active\n"
                  "  %u errors found\n", getactives_amatrix(),
                  getactives_avector(), problems);

    return problems;
}