/* computes the svd of a complex matrix. Missing in gsl. */ int svd(gsl_matrix_complex *A, gsl_matrix_complex *V, gsl_vector *S) { int n = A->size1; gsl_eigen_hermv_workspace *gsl_work = gsl_eigen_hermv_alloc(n); gsl_matrix_complex *Asq = gsl_matrix_complex_alloc(n, n); gsl_complex zero = gsl_complex_rect(0., 0.); gsl_complex one = gsl_complex_rect(1., 0.); gsl_vector *e = gsl_vector_alloc(n); gsl_matrix_complex *U = gsl_matrix_complex_alloc(n, n); gsl_blas_zgemm(CblasNoTrans, CblasConjTrans, one, A, A, zero, Asq); gsl_eigen_hermv(Asq, e, U, gsl_work); gsl_eigen_hermv_sort(e, U, GSL_EIGEN_SORT_VAL_DESC); gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, A, A, zero, Asq); gsl_eigen_hermv(Asq, e, V, gsl_work); gsl_eigen_hermv_sort(e, V, GSL_EIGEN_SORT_VAL_DESC); gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, one, A, V, zero, Asq); gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, U, Asq, zero, A); for(int i=0; i<n; i++){ gsl_complex x = gsl_matrix_complex_get(A, i, i); double phase = gsl_complex_arg(gsl_complex_mul_real(x, 1./sqrt(e->data[i]))); gsl_vector_complex_view U_col = gsl_matrix_complex_column(U, i); gsl_vector_complex_scale(&U_col.vector, gsl_complex_polar(1., phase)); gsl_vector_set(S, i, sqrt(gsl_vector_get(e, i))); } gsl_matrix_complex_memcpy(A, U); gsl_vector_free(e); gsl_matrix_complex_free(U); gsl_matrix_complex_free(Asq); gsl_eigen_hermv_free(gsl_work); return 0; }
/// Multiply by a number /// @param d :: The number ComplexVector &ComplexVector::operator*=(const ComplexType d) { gsl_vector_complex_scale(gsl(), gsl_complex{{d.real(), d.imag()}}); return *this; }
int lls_complex_stdform(gsl_matrix_complex *A, gsl_vector_complex *b, const gsl_vector *wts, const gsl_vector *L, lls_complex_workspace *w) { const size_t n = A->size1; const size_t p = A->size2; if (p != w->p) { fprintf(stderr, "lls_complex_stdform: A has wrong size2\n"); return GSL_EBADLEN; } else if (n != b->size) { fprintf(stderr, "lls_complex_stdform: b has wrong size\n"); return GSL_EBADLEN; } else if (wts != NULL && n != wts->size) { fprintf(stderr, "lls_complex_stdform: wts has wrong size\n"); return GSL_EBADLEN; } else if (L != NULL && p != L->size) { fprintf(stderr, "lls_complex_stdform: L has wrong size\n"); return GSL_EBADLEN; } else { int s = 0; size_t i; if (wts != NULL) { for (i = 0; i < n; ++i) { gsl_vector_complex_view rv = gsl_matrix_complex_row(A, i); gsl_complex bi = gsl_vector_complex_get(b, i); double wi = gsl_vector_get(wts, i); double sqrtwi = sqrt(wi); gsl_complex val; GSL_SET_COMPLEX(&val, sqrtwi, 0.0); /* A <- sqrt(W) A */ gsl_vector_complex_scale(&rv.vector, val); /* b <- sqrt(W) b */ val = gsl_complex_mul_real(bi, sqrtwi); gsl_vector_complex_set(b, i, val); } } if (L != NULL) { /* A <- sqrt(W) A L^{-1} */ for (i = 0; i < p; ++i) { gsl_vector_complex_view cv = gsl_matrix_complex_column(A, i); double Li = gsl_vector_get(L, i); gsl_complex val; if (Li == 0.0) { GSL_ERROR("L matrix is singular", GSL_ESING); } GSL_SET_COMPLEX(&val, 1.0 / Li, 0.0); gsl_vector_complex_scale(&cv.vector, val); } } return s; } } /* lls_complex_stdform() */