static VALUE rb_gsl_blas_zdotc(int argc, VALUE *argv, VALUE obj) { gsl_complex *r; int status; gsl_vector_complex *x = NULL, *y = NULL; get_vector_complex2(argc, argv, obj, &x, &y); r = ALLOC(gsl_complex); status = gsl_blas_zdotc(x, y, r); return Data_Wrap_Struct(cgsl_complex, 0, free, r); }
int lls_complex_solve(const double lambda, gsl_vector_complex *c, lls_complex_workspace *w) { if (c->size != w->p) { fprintf(stderr, "lls_complex_solve: coefficient vector has wrong size\n"); return GSL_EBADLEN; } else { int s = 0; /* solve (AHA + lambda^2 I) c = AHb and estimate condition number */ s = lls_lapack_zposv(lambda, c, w); /* compute residual || AHA c - AHb || */ gsl_vector_complex_memcpy(w->work_b, w->AHb); gsl_blas_zhemv(CblasUpper, GSL_COMPLEX_ONE, w->AHA, c, GSL_COMPLEX_NEGONE, w->work_b); w->residual = gsl_blas_dznrm2(w->work_b); /* compute chi^2 = b^H b - 2 c^H A^H b + c^H A^H A c */ { gsl_complex negtwo = gsl_complex_rect(-2.0, 0.0); gsl_complex val; /* compute: AHA c - 2 AHb */ gsl_vector_complex_memcpy(w->work_b, w->AHb); gsl_blas_zhemv(CblasUpper, GSL_COMPLEX_ONE, w->AHA, c, negtwo, w->work_b); /* compute: c^H ( AHA c - 2 AHb ) */ gsl_blas_zdotc(c, w->work_b, &val); w->chisq = w->bHb + GSL_REAL(val); } /* save coefficient vector for future robust iterations */ gsl_vector_complex_memcpy(w->c, c); ++(w->niter); return s; } } /* lls_complex_solve() */
/** * C++ version of gsl_blas_zdotc(). * @param X First vector * @param Y Second vector * @param dotc Vector product * @return Error code on failure */ int zdotc( vector_complex const& X, vector_complex const& Y, complex* dotc ){ return gsl_blas_zdotc( X.get(), Y.get(), &dotc->get() ); }
void test_eigen_herm_results (const gsl_matrix_complex * A, const gsl_vector * eval, const gsl_matrix_complex * evec, size_t count, const char * desc, const char * desc2) { const size_t N = A->size1; size_t i, j; gsl_vector_complex * x = gsl_vector_complex_alloc(N); gsl_vector_complex * y = gsl_vector_complex_alloc(N); /* check eigenvalues */ for (i = 0; i < N; i++) { double ei = gsl_vector_get (eval, i); gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i); gsl_vector_complex_memcpy(x, &vi.vector); /* compute y = m x (should = lambda v) */ gsl_blas_zgemv (CblasNoTrans, GSL_COMPLEX_ONE, A, x, GSL_COMPLEX_ZERO, y); for (j = 0; j < N; j++) { gsl_complex xj = gsl_vector_complex_get (x, j); gsl_complex yj = gsl_vector_complex_get (y, j); gsl_test_rel(GSL_REAL(yj), ei * GSL_REAL(xj), 1e8*GSL_DBL_EPSILON, "%s, eigenvalue(%d,%d), real, %s", desc, i, j, desc2); gsl_test_rel(GSL_IMAG(yj), ei * GSL_IMAG(xj), 1e8*GSL_DBL_EPSILON, "%s, eigenvalue(%d,%d), imag, %s", desc, i, j, desc2); } } /* check eigenvectors are orthonormal */ for (i = 0; i < N; i++) { gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i); double nrm_v = gsl_blas_dznrm2(&vi.vector); gsl_test_rel (nrm_v, 1.0, N * GSL_DBL_EPSILON, "%s, normalized(%d), %s", desc, i, desc2); } for (i = 0; i < N; i++) { gsl_vector_complex_const_view vi = gsl_matrix_complex_const_column(evec, i); for (j = i + 1; j < N; j++) { gsl_vector_complex_const_view vj = gsl_matrix_complex_const_column(evec, j); gsl_complex vivj; gsl_blas_zdotc (&vi.vector, &vj.vector, &vivj); gsl_test_abs (gsl_complex_abs(vivj), 0.0, 10.0 * N * GSL_DBL_EPSILON, "%s, orthogonal(%d,%d), %s", desc, i, j, desc2); } } gsl_vector_complex_free(x); gsl_vector_complex_free(y); } /* test_eigen_herm_results() */
int gsl_linalg_complex_cholesky_decomp(gsl_matrix_complex *A) { const size_t N = A->size1; if (N != A->size2) { GSL_ERROR("cholesky decomposition requires square matrix", GSL_ENOTSQR); } else { size_t i, j; gsl_complex z; double ajj; for (j = 0; j < N; ++j) { z = gsl_matrix_complex_get(A, j, j); ajj = GSL_REAL(z); if (j > 0) { gsl_vector_complex_const_view aj = gsl_matrix_complex_const_subrow(A, j, 0, j); gsl_blas_zdotc(&aj.vector, &aj.vector, &z); ajj -= GSL_REAL(z); } if (ajj <= 0.0) { GSL_ERROR("matrix is not positive definite", GSL_EDOM); } ajj = sqrt(ajj); GSL_SET_COMPLEX(&z, ajj, 0.0); gsl_matrix_complex_set(A, j, j, z); if (j < N - 1) { gsl_vector_complex_view av = gsl_matrix_complex_subcolumn(A, j, j + 1, N - j - 1); if (j > 0) { gsl_vector_complex_view aj = gsl_matrix_complex_subrow(A, j, 0, j); gsl_matrix_complex_view am = gsl_matrix_complex_submatrix(A, j + 1, 0, N - j - 1, j); cholesky_complex_conj_vector(&aj.vector); gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_NEGONE, &am.matrix, &aj.vector, GSL_COMPLEX_ONE, &av.vector); cholesky_complex_conj_vector(&aj.vector); } gsl_blas_zdscal(1.0 / ajj, &av.vector); } } /* Now store L^H in upper triangle */ for (i = 1; i < N; ++i) { for (j = 0; j < i; ++j) { z = gsl_matrix_complex_get(A, i, j); gsl_matrix_complex_set(A, j, i, gsl_complex_conjugate(z)); } } return GSL_SUCCESS; } } /* gsl_linalg_complex_cholesky_decomp() */
int gsl_linalg_complex_cholesky_invert(gsl_matrix_complex * LLT) { if (LLT->size1 != LLT->size2) { GSL_ERROR ("cholesky matrix must be square", GSL_ENOTSQR); } else { size_t N = LLT->size1; size_t i, j; gsl_vector_complex_view v1; /* invert the lower triangle of LLT */ for (i = 0; i < N; ++i) { double ajj; gsl_complex z; j = N - i - 1; { gsl_complex z0 = gsl_matrix_complex_get(LLT, j, j); ajj = 1.0 / GSL_REAL(z0); } GSL_SET_COMPLEX(&z, ajj, 0.0); gsl_matrix_complex_set(LLT, j, j, z); { gsl_complex z1 = gsl_matrix_complex_get(LLT, j, j); ajj = -GSL_REAL(z1); } if (j < N - 1) { gsl_matrix_complex_view m; m = gsl_matrix_complex_submatrix(LLT, j + 1, j + 1, N - j - 1, N - j - 1); v1 = gsl_matrix_complex_subcolumn(LLT, j, j + 1, N - j - 1); gsl_blas_ztrmv(CblasLower, CblasNoTrans, CblasNonUnit, &m.matrix, &v1.vector); gsl_blas_zdscal(ajj, &v1.vector); } } /* for (i = 0; i < N; ++i) */ /* * The lower triangle of LLT now contains L^{-1}. Now compute * A^{-1} = L^{-H} L^{-1} * * The (ij) element of A^{-1} is column i of conj(L^{-1}) dotted into * column j of L^{-1} */ for (i = 0; i < N; ++i) { gsl_complex sum; for (j = i + 1; j < N; ++j) { gsl_vector_complex_view v2; v1 = gsl_matrix_complex_subcolumn(LLT, i, j, N - j); v2 = gsl_matrix_complex_subcolumn(LLT, j, j, N - j); /* compute Ainv[i,j] = sum_k{conj(Linv[k,i]) * Linv[k,j]} */ gsl_blas_zdotc(&v1.vector, &v2.vector, &sum); /* store in upper triangle */ gsl_matrix_complex_set(LLT, i, j, sum); } /* now compute the diagonal element */ v1 = gsl_matrix_complex_subcolumn(LLT, i, i, N - i); gsl_blas_zdotc(&v1.vector, &v1.vector, &sum); gsl_matrix_complex_set(LLT, i, i, sum); } /* copy the Hermitian upper triangle to the lower triangle */ for (j = 1; j < N; j++) { for (i = 0; i < j; i++) { gsl_complex z = gsl_matrix_complex_get(LLT, i, j); gsl_matrix_complex_set(LLT, j, i, gsl_complex_conjugate(z)); } } return GSL_SUCCESS; } } /* gsl_linalg_complex_cholesky_invert() */
int main(void) { gsl_matrix *TS; /* the training set of real waveforms */ gsl_matrix_complex *cTS; /* the training set of complex waveforms */ size_t TSsize; /* the size of the training set (number of waveforms) */ size_t wl; /* the length of each waveform */ size_t k = 0, j = 0, i = 0, nbases = 0, cnbases = 0; REAL8 *RB = NULL; /* the real reduced basis set */ COMPLEX16 *cRB = NULL; /* the complex reduced basis set */ LALInferenceREALROQInterpolant *interp = NULL; LALInferenceCOMPLEXROQInterpolant *cinterp = NULL; gsl_vector *freqs; double tolerance = TOLERANCE; /* tolerance for reduced basis generation loop */ TSsize = TSSIZE; wl = WL; /* allocate memory for training set */ TS = gsl_matrix_calloc(TSsize, wl); cTS = gsl_matrix_complex_calloc(TSsize, wl); /* the waveform model is just a simple chirp so set up chirp mass range for training set */ double fmin0 = 48, fmax0 = 256, f0 = 0., m0 = 0.; double df = (fmax0-fmin0)/(wl-1.); /* model time steps */ freqs = gsl_vector_alloc(wl); /* times at which to calculate the model */ double Mcmax = 2., Mcmin = 1.5, Mc = 0.; gsl_vector_view fweights = gsl_vector_view_array(&df, 1); /* set up training sets (one real and one complex) */ for ( k=0; k < TSsize; k++ ){ Mc = pow(pow(Mcmin, 5./3.) + (double)k*(pow(Mcmax, 5./3.)-pow(Mcmin, 5./3.))/((double)TSsize-1), 3./5.); for ( j=0; j < wl; j++ ){ f0 = fmin0 + (double)j*(fmax0-fmin0)/((double)wl-1.); gsl_complex gctmp; COMPLEX16 ctmp; m0 = real_model(f0, Mc); ctmp = imag_model(f0, Mc); GSL_SET_COMPLEX(&gctmp, creal(ctmp), cimag(ctmp)); gsl_vector_set(freqs, j, f0); gsl_matrix_set(TS, k, j, m0); gsl_matrix_complex_set(cTS, k, j, gctmp); } } /* create reduced orthonormal basis from training set */ if ( (RB = LALInferenceGenerateREAL8OrthonormalBasis(&fweights.vector, tolerance, TS, &nbases)) == NULL){ fprintf(stderr, "Error... problem producing basis\n"); return 1; } if ( (cRB = LALInferenceGenerateCOMPLEX16OrthonormalBasis(&fweights.vector, tolerance, cTS, &cnbases)) == NULL){ fprintf(stderr, "Error... problem producing basis\n"); return 1; } /* free the training set */ gsl_matrix_free(TS); gsl_matrix_complex_free(cTS); gsl_matrix_view RBview = gsl_matrix_view_array(RB, nbases, wl); gsl_matrix_complex_view cRBview = gsl_matrix_complex_view_array((double*)cRB, cnbases, wl); fprintf(stderr, "No. nodes (real) = %zu, %zu x %zu\n", nbases, RBview.matrix.size1, RBview.matrix.size2); fprintf(stderr, "No. nodes (complex) = %zu, %zu x %zu\n", cnbases, cRBview.matrix.size1, cRBview.matrix.size2); /* get the interpolant */ interp = LALInferenceGenerateREALROQInterpolant(&RBview.matrix); cinterp = LALInferenceGenerateCOMPLEXROQInterpolant(&cRBview.matrix); /* free the reduced basis */ XLALFree(RB); XLALFree(cRB); /* now get the terms for the likelihood with and without the reduced order quadrature * and do some timing tests */ /* create the model dot model weights */ REAL8 varval = 1.; gsl_vector_view vars = gsl_vector_view_array(&varval, 1); gsl_matrix *mmw = LALInferenceGenerateREALModelModelWeights(interp->B, &vars.vector); gsl_matrix_complex *cmmw = LALInferenceGenerateCOMPLEXModelModelWeights(cinterp->B, &vars.vector); /* let's create some Gaussian random data */ const gsl_rng_type *T; gsl_rng *r; gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc(T); REAL8 *data = XLALCalloc(wl, sizeof(REAL8)); COMPLEX16 *cdata = XLALCalloc(wl, sizeof(COMPLEX16)); for ( i=0; i<wl; i++ ){ data[i] = gsl_ran_gaussian(r, 1.0); /* real data */ cdata[i] = gsl_ran_gaussian(r, 1.0) + I*gsl_ran_gaussian(r, 1.0); /* complex data */ } /* create the data dot model weights */ gsl_vector_view dataview = gsl_vector_view_array(data, wl); gsl_vector *dmw = LALInferenceGenerateREAL8DataModelWeights(interp->B, &dataview.vector, &vars.vector); gsl_vector_complex_view cdataview = gsl_vector_complex_view_array((double*)cdata, wl); gsl_vector_complex *cdmw = LALInferenceGenerateCOMPLEX16DataModelWeights(cinterp->B, &cdataview.vector, &vars.vector); /* pick a chirp mass and generate a model to compare likelihoods */ double randMc = 1.873; /* a random frequency to create a model */ gsl_vector *modelfull = gsl_vector_alloc(wl); gsl_vector *modelreduced = gsl_vector_alloc(nbases); gsl_vector_complex *cmodelfull = gsl_vector_complex_alloc(wl); gsl_vector_complex *cmodelreduced = gsl_vector_complex_alloc(cnbases); /* create models */ for ( i=0; i<wl; i++ ){ /* models at all frequencies */ gsl_vector_set(modelfull, i, real_model(gsl_vector_get(freqs, i), randMc)); COMPLEX16 cval = imag_model(gsl_vector_get(freqs, i), randMc); gsl_complex gcval; GSL_SET_COMPLEX(&gcval, creal(cval), cimag(cval)); gsl_vector_complex_set(cmodelfull, i, gcval); } /* models at interpolant nodes */ for ( i=0; i<nbases; i++ ){ /* real model */ gsl_vector_set(modelreduced, i, real_model(gsl_vector_get(freqs, interp->nodes[i]), randMc)); } for ( i=0; i<cnbases; i++ ){ /* complex model */ COMPLEX16 cval = imag_model(gsl_vector_get(freqs, cinterp->nodes[i]), randMc); gsl_complex gcval; GSL_SET_COMPLEX(&gcval, creal(cval), cimag(cval)); gsl_vector_complex_set(cmodelreduced, i, gcval); } /* timing variables */ struct timeval t1, t2, t3, t4; double dt1, dt2; /* start with the real model */ /* get the model model term with the full model */ REAL8 mmfull, mmred; gettimeofday(&t1, NULL); XLAL_CALLGSL( gsl_blas_ddot(modelfull, modelfull, &mmfull) ); /* real model */ gettimeofday(&t2, NULL); /* now get it with the reduced order quadrature */ gettimeofday(&t3, NULL); mmred = LALInferenceROQREAL8ModelDotModel(mmw, modelreduced); gettimeofday(&t4, NULL); dt1 = (double)((t2.tv_sec + t2.tv_usec*1.e-6) - (t1.tv_sec + t1.tv_usec*1.e-6)); dt2 = (double)((t4.tv_sec + t4.tv_usec*1.e-6) - (t3.tv_sec + t3.tv_usec*1.e-6)); fprintf(stderr, "Real Signal:\n - M dot M (full) = %le [%.9lf s], M dot M (reduced) = %le [%.9lf s], time ratio = %lf\n", mmfull, dt1, mmred, dt2, dt1/dt2); /* get the data model term with the full model */ REAL8 dmfull, dmred; gettimeofday(&t1, NULL); XLAL_CALLGSL( gsl_blas_ddot(&dataview.vector, modelfull, &dmfull) ); gettimeofday(&t2, NULL); /* now get it with the reduced order quadrature */ gettimeofday(&t3, NULL); dmred = LALInferenceROQREAL8DataDotModel(dmw, modelreduced); gettimeofday(&t4, NULL); dt1 = (double)((t2.tv_sec + t2.tv_usec*1.e-6) - (t1.tv_sec + t1.tv_usec*1.e-6)); dt2 = (double)((t4.tv_sec + t4.tv_usec*1.e-6) - (t3.tv_sec + t3.tv_usec*1.e-6)); fprintf(stderr, " - D dot M (full) = %le [%.9lf s], D dot M (reduced) = %le [%.9lf s], time ratio = %lf\n", dmfull, dt1, dmred, dt2, dt1/dt2); /* check difference in log likelihoods */ double Lfull, Lred, Lfrac; Lfull = mmfull - 2.*dmfull; Lred = mmred - 2.*dmred; Lfrac = 100.*fabs(Lfull-Lred)/fabs(Lfull); /* fractional log likelihood difference (in %) */ fprintf(stderr, " - Fractional difference in log likelihoods = %lf%%\n", Lfrac); XLALFree(data); gsl_vector_free(modelfull); gsl_vector_free(modelreduced); gsl_matrix_free(mmw); gsl_vector_free(dmw); /* check log likelihood difference is within tolerance */ if ( Lfrac > LTOL ) { return 1; } /* now do the same with the complex model */ /* get the model model term with the full model */ COMPLEX16 cmmred, cmmfull; gsl_complex cmmfulltmp; gettimeofday(&t1, NULL); XLAL_CALLGSL( gsl_blas_zdotc(cmodelfull, cmodelfull, &cmmfulltmp) ); /* complex model */ cmmfull = GSL_REAL(cmmfulltmp) + I*GSL_IMAG(cmmfulltmp); gettimeofday(&t2, NULL); gettimeofday(&t3, NULL); cmmred = LALInferenceROQCOMPLEX16ModelDotModel(cmmw, cmodelreduced); gettimeofday(&t4, NULL); dt1 = (double)((t2.tv_sec + t2.tv_usec*1.e-6) - (t1.tv_sec + t1.tv_usec*1.e-6)); dt2 = (double)((t4.tv_sec + t4.tv_usec*1.e-6) - (t3.tv_sec + t3.tv_usec*1.e-6)); fprintf(stderr, "Complex Signal:\n - M dot M (full) = %le [%.9lf s], M dot M (reduced) = %le [%.9lf s], time ratio = %lf\n", creal(cmmfull), dt1, creal(cmmred), dt2, dt1/dt2); COMPLEX16 cdmfull, cdmred; gsl_complex cdmfulltmp; gettimeofday(&t1, NULL); XLAL_CALLGSL( gsl_blas_zdotc(&cdataview.vector, cmodelfull, &cdmfulltmp) ); cdmfull = GSL_REAL(cdmfulltmp) + I*GSL_IMAG(cdmfulltmp); gettimeofday(&t2, NULL); gettimeofday(&t3, NULL); cdmred = LALInferenceROQCOMPLEX16DataDotModel(cdmw, cmodelreduced); gettimeofday(&t4, NULL); dt1 = (double)((t2.tv_sec + t2.tv_usec*1.e-6) - (t1.tv_sec + t1.tv_usec*1.e-6)); dt2 = (double)((t4.tv_sec + t4.tv_usec*1.e-6) - (t3.tv_sec + t3.tv_usec*1.e-6)); fprintf(stderr, " - D dot M (full) = %le [%.9lf s], D dot M (reduced) = %le [%.9lf s], time ratio = %lf\n", creal(cdmfull), dt1, creal(cdmred), dt2, dt1/dt2); /* check difference in log likelihoods */ Lfull = creal(cmmfull) - 2.*creal(cdmfull); Lred = creal(cmmred) - 2.*creal(cdmred); Lfrac = 100.*fabs(Lfull-Lred)/fabs(Lfull); /* fractional log likelihood difference (in %) */ fprintf(stderr, " - Fractional difference in log likelihoods = %lf%%\n", Lfrac); XLALFree(cdata); gsl_vector_complex_free(cmodelfull); gsl_vector_complex_free(cmodelreduced); gsl_matrix_complex_free(cmmw); gsl_vector_complex_free(cdmw); LALInferenceRemoveREALROQInterpolant( interp ); LALInferenceRemoveCOMPLEXROQInterpolant( cinterp ); /* check log likelihood difference is within tolerance */ if ( Lfrac > LTOL ) { return 1; } return 0; }
int lls_complex_lcurve(gsl_vector *reg_param, gsl_vector *rho, gsl_vector *eta, lls_complex_workspace *w) { const size_t N = rho->size; /* number of points on L-curve */ if (N != reg_param->size) { GSL_ERROR("size of reg_param and rho do not match", GSL_EBADLEN); } else if (N != eta->size) { GSL_ERROR("size of eta and rho do not match", GSL_EBADLEN); } else { int s; const gsl_complex negtwo = gsl_complex_rect(-2.0, 0.0); /* smallest regularization parameter */ const double smin_ratio = 16.0 * GSL_DBL_EPSILON; double s1, sp, ratio, tmp; size_t i; /* compute eigenvalues of A^H A */ gsl_matrix_complex_transpose_memcpy(w->work_A, w->AHA); s = gsl_eigen_herm(w->work_A, w->eval, w->eigen_p); if (s) return s; /* find largest and smallest eigenvalues */ gsl_vector_minmax(w->eval, &sp, &s1); /* singular values are square roots of eigenvalues */ s1 = sqrt(s1); if (sp > GSL_DBL_EPSILON) sp = sqrt(fabs(sp)); tmp = GSL_MAX(sp, s1*smin_ratio); gsl_vector_set(reg_param, N - 1, tmp); /* ratio so that reg_param(1) = s(1) */ ratio = pow(s1 / tmp, 1.0 / (N - 1.0)); /* calculate the regularization parameters */ for (i = N - 1; i > 0 && i--; ) { double rp1 = gsl_vector_get(reg_param, i + 1); gsl_vector_set(reg_param, i, ratio * rp1); } for (i = 0; i < N; ++i) { double r2; double lambda = gsl_vector_get(reg_param, i); gsl_complex val; lls_complex_solve(lambda, w->c, w); /* store ||c|| */ gsl_vector_set(eta, i, gsl_blas_dznrm2(w->c)); /* compute: A^H A c - 2 A^H b */ gsl_vector_complex_memcpy(w->work_b, w->AHb); gsl_blas_zhemv(CblasUpper, GSL_COMPLEX_ONE, w->AHA, w->c, negtwo, w->work_b); /* compute: c^T A^T A c - 2 c^T A^T b */ gsl_blas_zdotc(w->c, w->work_b, &val); r2 = GSL_REAL(val) + w->bHb; gsl_vector_set(rho, i, sqrt(r2)); } return GSL_SUCCESS; } } /* lls_complex_lcurve() */
int gsl_linalg_hermtd_decomp (gsl_matrix_complex * A, gsl_vector_complex * tau) { if (A->size1 != A->size2) { GSL_ERROR ("hermitian tridiagonal decomposition requires square matrix", GSL_ENOTSQR); } else if (tau->size + 1 != A->size1) { GSL_ERROR ("size of tau must be (matrix size - 1)", GSL_EBADLEN); } else { const size_t N = A->size1; size_t i; const gsl_complex zero = gsl_complex_rect (0.0, 0.0); const gsl_complex one = gsl_complex_rect (1.0, 0.0); const gsl_complex neg_one = gsl_complex_rect (-1.0, 0.0); for (i = 0 ; i < N - 1; i++) { gsl_vector_complex_view c = gsl_matrix_complex_column (A, i); gsl_vector_complex_view v = gsl_vector_complex_subvector (&c.vector, i + 1, N - (i + 1)); gsl_complex tau_i = gsl_linalg_complex_householder_transform (&v.vector); /* Apply the transformation H^T A H to the remaining columns */ if ((i + 1) < (N - 1) && !(GSL_REAL(tau_i) == 0.0 && GSL_IMAG(tau_i) == 0.0)) { gsl_matrix_complex_view m = gsl_matrix_complex_submatrix (A, i + 1, i + 1, N - (i+1), N - (i+1)); gsl_complex ei = gsl_vector_complex_get(&v.vector, 0); gsl_vector_complex_view x = gsl_vector_complex_subvector (tau, i, N-(i+1)); gsl_vector_complex_set (&v.vector, 0, one); /* x = tau * A * v */ gsl_blas_zhemv (CblasLower, tau_i, &m.matrix, &v.vector, zero, &x.vector); /* w = x - (1/2) tau * (x' * v) * v */ { gsl_complex xv, txv, alpha; gsl_blas_zdotc(&x.vector, &v.vector, &xv); txv = gsl_complex_mul(tau_i, xv); alpha = gsl_complex_mul_real(txv, -0.5); gsl_blas_zaxpy(alpha, &v.vector, &x.vector); } /* apply the transformation A = A - v w' - w v' */ gsl_blas_zher2(CblasLower, neg_one, &v.vector, &x.vector, &m.matrix); gsl_vector_complex_set (&v.vector, 0, ei); } gsl_vector_complex_set (tau, i, tau_i); } return GSL_SUCCESS; } }