void MCPMPCoeffs::GeoUpdate(double seconds) { for (int i=0;i<2*M();i++) { gsl_complex v = gsl_vector_complex_get(geoVelocities,i); // expressed in deltalon/s,deltalat/s gsl_complex p = gsl_vector_complex_get(geoPositions,i); // expressed in lon,lat gsl_complex np = gsl_complex_add(p,gsl_complex_mul_real(v, seconds)); gsl_vector_complex_set(geoPositions,i,np); // cout << "node " << i << " position = " << GSL_IMAG(np) << ", " << GSL_REAL(np) << endl; } }
static void cholesky_complex_conj_vector(gsl_vector_complex *v) { size_t i; for (i = 0; i < v->size; ++i) { gsl_complex z = gsl_vector_complex_get(v, i); gsl_vector_complex_set(v, i, gsl_complex_conjugate(z)); } } /* cholesky_complex_conj_vector() */
vectorc vectorc::operator=(const vectorc& vec) { if (this==&vec) return *this; gsl_vector_complex_free (v_m); size_m=vec.size_m; v_m=gsl_vector_complex_alloc(size_m); for (int i=0; i<size_m; i++) gsl_vector_complex_set(v_m, i, gsl_vector_complex_get(vec.v_m, i)); return *this; }
void test_eigenvalues_complex (const gsl_vector_complex * eval, const gsl_vector_complex * eval2, const char * desc, const char * desc2) { const size_t N = eval->size; size_t i; for (i = 0; i < N; i++) { gsl_complex ei = gsl_vector_complex_get (eval, i); gsl_complex e2i = gsl_vector_complex_get (eval2, i); gsl_test_rel(GSL_REAL(ei), GSL_REAL(e2i), 10*N*GSL_DBL_EPSILON, "%s, direct eigenvalue(%d) real, %s", desc, i, desc2); gsl_test_rel(GSL_IMAG(ei), GSL_IMAG(e2i), 10*N*GSL_DBL_EPSILON, "%s, direct eigenvalue(%d) imag, %s", desc, i, desc2); } }
int main(void) { double data[] = { -1.0, 1.0, -1.0, 1.0, -8.0, 4.0, -2.0, 1.0, 27.0, 9.0, 3.0, 1.0, 64.0, 16.0, 4.0, 1.0 }; gsl_matrix_view m = gsl_matrix_view_array(data, 4, 4); gsl_vector_complex *eval = gsl_vector_complex_alloc(4); gsl_matrix_complex *evec = gsl_matrix_complex_alloc(4, 4); gsl_eigen_nonsymmv_workspace * w = gsl_eigen_nonsymmv_alloc(4); gsl_eigen_nonsymmv(&m.matrix, eval, evec, w); gsl_eigen_nonsymmv_free(w); gsl_eigen_nonsymmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); { int i, j; for (i = 0; i < 4; i++) { gsl_complex eval_i = gsl_vector_complex_get(eval, i); gsl_vector_complex_view evec_i = gsl_matrix_complex_column(evec, i); printf("eigenvalue = %g + %gi\n", GSL_REAL(eval_i), GSL_IMAG(eval_i)); printf("eigenvector = \n"); for (j = 0; j < 4; ++j) { gsl_complex z = gsl_vector_complex_get(&evec_i.vector, j); printf("%g + %gi\n", GSL_REAL(z), GSL_IMAG(z)); } } } gsl_vector_complex_free(eval); gsl_matrix_complex_free(evec); return 0; }
/// Resize the vector /// @param n :: The new length void ComplexVector::resize(const size_t n) { auto oldVector = m_vector; m_vector = gsl_vector_complex_alloc(n); size_t m = oldVector->size < n ? oldVector->size : n; for (size_t i = 0; i < m; ++i) { gsl_vector_complex_set(m_vector, i, gsl_vector_complex_get(oldVector, i)); } for (size_t i = m; i < n; ++i) { gsl_vector_complex_set(m_vector, i, gsl_complex{{0, 0}}); } gsl_vector_complex_free(oldVector); }
/// get an element /// @param i :: The element index ComplexType ComplexVector::get(size_t i) const { if (i < m_vector->size) { auto value = gsl_vector_complex_get(m_vector, i); return ComplexType(GSL_REAL(value), GSL_IMAG(value)); } std::stringstream errmsg; errmsg << "ComplexVector index = " << i << " is out of range = " << m_vector->size << " in ComplexVector.get()"; throw std::out_of_range(errmsg.str()); }
void MarkovChain::setupCDFS(const gsl_matrix * Q) { double cdf, norm; gsl_vector_complex *eval; gsl_matrix_complex *evec; gsl_eigen_nonsymmv_workspace * w; gsl_vector_complex_view S; gsl_matrix_memcpy (m_cdfQ, Q); eval = gsl_vector_complex_alloc (Q->size1); evec = gsl_matrix_complex_alloc (Q->size1, Q->size2); w = gsl_eigen_nonsymmv_alloc(Q->size1); gsl_eigen_nonsymmv (m_cdfQ, eval, evec, w); gsl_eigen_nonsymmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_DESC); /*vector of stationary probabilities corresponding to the eigenvalue 1 */ S = gsl_matrix_complex_column(evec, 0); /*sum of vector elements*/ norm = 0.0; for(size_t i = 0; i < Q->size1; ++i) { norm += GSL_REAL(gsl_vector_complex_get(&S.vector, i)); } /*cdfs*/ cdf = 0.0; for(size_t i = 0; i < Q->size1; ++i) { cdf += GSL_REAL(gsl_vector_complex_get(&S.vector, i)) / norm; gsl_vector_set(m_cdfS, i, cdf); } gsl_eigen_nonsymmv_free (w); gsl_vector_complex_free(eval); gsl_matrix_complex_free(evec); }
double epidemicGrowthRate(const double theta[numParam], const double r0time, double * eigenvec) { gsl_matrix * Fmat = gsl_matrix_calloc(NG*(DS-1)*RG, NG*(DS-1)*RG); gsl_matrix * Vmat = gsl_matrix_calloc(NG*(DS-1)*RG, NG*(DS-1)*RG); createNGM(theta, r0time, Fmat, Vmat); gsl_matrix_sub(Fmat, Vmat); gsl_eigen_nonsymmv_workspace * w = gsl_eigen_nonsymmv_alloc(NG*(DS-1)*RG); gsl_vector_complex * eval = gsl_vector_complex_alloc(NG*(DS-1)*RG); gsl_matrix_complex * evec = gsl_matrix_complex_alloc(NG*(DS-1)*RG, NG*(DS-1)*RG); gsl_set_error_handler_off(); gsl_eigen_nonsymmv(Fmat, eval, evec, w); size_t growth_rate_idx = 0; double growth_rate = -INFINITY; for(size_t i = 0; i < NG*(DS-1)*RG; i++){ if(GSL_REAL(gsl_vector_complex_get(eval, i)) > growth_rate){ growth_rate_idx = i; growth_rate = GSL_REAL(gsl_vector_complex_get(eval, i)); } } if(eigenvec != NULL){ for(size_t i = 0; i < NG*(DS-1)*RG; i++) eigenvec[i] = GSL_REAL(gsl_matrix_complex_get(evec, i, growth_rate_idx)); } gsl_matrix_free(Fmat); gsl_matrix_free(Vmat); gsl_vector_complex_free(eval); gsl_matrix_complex_free(evec); gsl_eigen_nonsymmv_free(w); return growth_rate; }
double MCPMPCoeffs::GeoDistance(unsigned int tx, unsigned int rx) { gsl_complex txPos = gsl_vector_complex_get(geoPositions,tx); // lat,lon gsl_complex rxPos = gsl_vector_complex_get(geoPositions,rx+_M); // lat,lon double txPosLat = GSL_REAL(txPos)*M_PI_OVER_180; double txPosLon = GSL_IMAG(txPos)*M_PI_OVER_180; double rxPosLat = GSL_REAL(rxPos)*M_PI_OVER_180; double rxPosLon = GSL_IMAG(rxPos)*M_PI_OVER_180; double deltaLat = rxPosLat-txPosLat; // ok double deltaLon = rxPosLon-txPosLon; // be careful around 180E/W double meanLat = (rxPosLat+txPosLat)/2.0; // be careful around poles if (deltaLon > M_PI) // es Lon1 =-179 Lon2=179 D=2 deltaLon -= 2*M_PI; if (deltaLon < -M_PI) deltaLon += 2*M_PI; double tmparg = gsl_sf_cos(meanLat)*deltaLon; return EARTH_RADIUS * gsl_hypot( deltaLat,tmparg ); }
int print_Lcurve(const char *filename, poltor_workspace *w) { int s = 0; FILE *fp; const size_t p = w->p; double rnorm, Lnorm; gsl_vector_complex_view v = gsl_vector_complex_subvector(w->rhs, 0, p); size_t i; fp = fopen(filename, "a"); if (!fp) { fprintf(stderr, "print_Lcurve: unable to open %s: %s\n", filename, strerror(errno)); return -1; } /* construct A and b, and calculate chi^2 = ||b - A c||^2 */ poltor_build_ls(0, w); rnorm = sqrt(w->chisq); /* compute v = L c; L is stored in w->L by poltor_solve() */ for (i = 0; i < p; ++i) { gsl_complex ci = gsl_vector_complex_get(w->c, i); double li = gsl_vector_get(w->L, i); gsl_complex val = gsl_complex_mul_real(ci, li); gsl_vector_complex_set(&v.vector, i, val); } /* compute || L c || */ Lnorm = gsl_blas_dznrm2(&v.vector); fprintf(fp, "%.12e %.12e %.6e %.6e %.6e\n", log(rnorm), log(Lnorm), w->alpha_int, w->alpha_sh, w->alpha_tor); printcv_octave(w->residuals, "r"); printcv_octave(w->c, "c"); printv_octave(w->L, "L"); fclose(fp); return s; } /* print_Lcurve() */
int eigenscan_stepIM(double partial[EdgeN],long unsigned int sam,double point,double*eigen){ double kappa; double data[EdgeN]; int i; kappa = EIGENVALUESCAN_MINKAPPA * pow(EIGENVALUESCAN_MAXKAPPA/EIGENVALUESCAN_MINKAPPA, point); for (i=0;i<EdgeN;i++){ data[i]=partial[i]; if( (int)i/NodeN == i%NodeN ) data[i]-=kappa*Sample[sam].D[(int)i/NodeN]; } gsl_matrix_view m; gsl_vector_complex * eval; gsl_eigen_nonsymm_workspace * w; m = gsl_matrix_view_array (data, NodeN, NodeN); eval = gsl_vector_complex_alloc (NodeN); w = gsl_eigen_nonsymm_alloc (NodeN); gsl_eigen_nonsymm (&m.matrix, eval, w); for ( i = 0; i < NodeN; i ++ ){ if ( fabs(GSL_IMAG( gsl_vector_complex_get( eval, i ))) > 1e-15 && GSL_REAL( gsl_vector_complex_get( eval, i ) ) > 0 ) { *eigen=GSL_REAL( gsl_vector_complex_get( eval, i )); gsl_vector_complex_free(eval); gsl_eigen_nonsymm_free (w); return GSL_SUCCESS; } } gsl_vector_complex_free(eval); gsl_eigen_nonsymm_free (w); return GSL_CONTINUE; }
Real DAESolver::solve() { if (the_system_size_ == 0) { return 0.0; } const VariableArray::size_type a_size(the_system_size_); gsl_linalg_LU_solve(the_jacobian_matrix1_, the_permutation1_, the_velocity_vector1_, the_solution_vector1_); gsl_linalg_complex_LU_solve(the_jacobian_matrix2_, the_permutation2_, the_velocity_vector2_, the_solution_vector2_); Real a_norm(0.0); Real delta_w(0.0); gsl_complex comp; VariableArray a_tmp_value_buffer = the_value_differential_buffer_; a_tmp_value_buffer.insert( a_tmp_value_buffer.end(), the_value_algebraic_buffer_.begin(), the_value_algebraic_buffer_.end()); for (VariableArray::size_type c(0); c < a_size; ++c) { Real a_tolerance2(rtoler_ * fabs(a_tmp_value_buffer[c]) + atoler_); a_tolerance2 = a_tolerance2 * a_tolerance2; delta_w = gsl_vector_get(the_solution_vector1_, c); the_w_[c] += delta_w; a_norm += delta_w * delta_w / a_tolerance2; comp = gsl_vector_complex_get(the_solution_vector2_, c); delta_w = GSL_REAL(comp); the_w_[c + a_size] += delta_w; a_norm += delta_w * delta_w / a_tolerance2; delta_w = GSL_IMAG(comp); the_w_[c + a_size * 2] += delta_w; a_norm += delta_w * delta_w / a_tolerance2; } return sqrt(a_norm / (3 * a_size)); }
void print_vector(gsl_vector_complex *eval, const char *str) { size_t N = eval->size; size_t i; gsl_complex z; printf("%s = [\n", str); for (i = 0; i < N; ++i) { z = gsl_vector_complex_get(eval, i); printf("%.18e %.18e;\n", GSL_REAL(z), GSL_IMAG(z)); } printf("]\n"); } /* print_vector() */
/* Uses the GSL library to solve the GEVP */ int gevp(const double **a0, const double **a1, double *ev, int ms){ int i,j; gsl_set_error_handler_off(); gsl_matrix *c0 = gsl_matrix_alloc(ms,ms); gsl_matrix *c1 = gsl_matrix_alloc(ms,ms); for (i = 0; i < ms; i++) { for (j = 0; j < ms; j++) { gsl_matrix_set(c0, i, j, a0[i][j]); gsl_matrix_set(c1, i, j, a1[i][j]); } } /* Run GEVP */ gsl_eigen_gen_workspace *gevp_ws = gsl_eigen_gen_alloc(ms); gsl_vector_complex *al = gsl_vector_complex_alloc(ms); gsl_vector *be = gsl_vector_alloc(ms); int err = gsl_eigen_gen(c1, c0, al, be, gevp_ws); if (err) { fprintf(stderr, "GEVP had errors.\n"); return err; } /* Sort into descending order */ gsl_vector *evs = gsl_vector_alloc(ms); for (i = 0; i < ms; i++) { gsl_complex q = gsl_vector_complex_get(al,i); double w = gsl_vector_get(be,i); if (w == 0) gsl_vector_set(evs,i,0); else gsl_vector_set(evs,i,GSL_REAL(q)/w); } gsl_sort_vector(evs); for (i = 0; i < ms; i++) { ev[i] = gsl_vector_get(evs,ms-i-1); } /* Clean up */ gsl_matrix_free(c0); gsl_matrix_free(c1); gsl_vector_complex_free(al); gsl_vector_free(be); gsl_vector_free(evs); gsl_eigen_gen_free(gevp_ws); return 0; }
// 2014-11-26 calculateExp, may be we should delete? gsl_vector * CRebuildGraph::calculateExp(const gsl_vector_complex *eval){ CFuncTrace lFuncTrace(false,"calculateExp"); int order = (int)eval->size; lFuncTrace.trace(CTrace::TRACE_DEBUG,"Ordre for Expo %d",order); gsl_vector *evalexp = gsl_vector_alloc (order); for ( int i = 0; i < order; i++){ gsl_complex eval_i = gsl_vector_complex_get (eval, i); // printf ("eigenvalue = %g + %gi\n", // GSL_REAL(eval_i), GSL_IMAG(eval_i)); gsl_vector_set(evalexp,i,gsl_sf_exp(GSL_REAL(eval_i))); printf("W exp %g\n",gsl_sf_exp(GSL_REAL(eval_i))); } return evalexp; }
int lls_complex_correlation(gsl_matrix_complex *B, const lls_complex_workspace *w) { size_t n = w->AHA->size1; if (B->size1 != n || B->size2 != n) { fprintf(stderr, "lls_complex_correlation: B has wrong dimensions\n"); return GSL_EBADLEN; } else { int s; size_t i; gsl_vector_complex_view d = gsl_matrix_complex_diagonal(B); /* compute covariance matrix */ s = lls_complex_invert(B, w); if (s) { fprintf(stderr, "lls_complex_correlation: error computing covariance matrix: %d\n", s); return s; } /* compute diag(C)^{-1/2} C diag(C)^{-1/2} */ for (i = 0; i < n; ++i) { gsl_complex di = gsl_vector_complex_get(&d.vector, i); gsl_vector_complex_view ri = gsl_matrix_complex_row(B, i); gsl_vector_complex_view ci = gsl_matrix_complex_column(B, i); gsl_complex z; GSL_SET_COMPLEX(&z, 1.0 / sqrt(GSL_REAL(di)), 0.0); gsl_vector_complex_scale(&ri.vector, z); gsl_vector_complex_scale(&ci.vector, z); } return s; } } /* lls_complex_correlation() */
// // General matrices // int qdpack_matrix_eigen_zgeev(qdpack_matrix_t *m, qdpack_matrix_t *eval, qdpack_matrix_t *evec, int sort_order) { int i; gsl_vector_complex *eval_vector; eval_vector = gsl_vector_complex_alloc(eval->m); gsl_ext_eigen_zgeev(m->data, evec->data, eval_vector); gsl_ext_eigen_sort(evec->data, eval_vector, sort_order); for (i = 0; i < eval->m; i++) { qdpack_matrix_set(eval, i, 0, gsl_vector_complex_get(eval_vector, i)); } return 0; }
static void nonsymmv_normalize_eigenvectors(gsl_vector_complex *eval, gsl_matrix_complex *evec) { const size_t N = evec->size1; size_t i; /* looping */ gsl_complex ei; gsl_vector_complex_view vi; gsl_vector_view re, im; double scale; /* scaling factor */ for (i = 0; i < N; ++i) { ei = gsl_vector_complex_get(eval, i); vi = gsl_matrix_complex_column(evec, i); re = gsl_vector_complex_real(&vi.vector); if (GSL_IMAG(ei) == 0.0) { scale = 1.0 / gsl_blas_dnrm2(&re.vector); gsl_blas_dscal(scale, &re.vector); } else if (GSL_IMAG(ei) > 0.0) { im = gsl_vector_complex_imag(&vi.vector); scale = 1.0 / gsl_hypot(gsl_blas_dnrm2(&re.vector), gsl_blas_dnrm2(&im.vector)); gsl_blas_zdscal(scale, &vi.vector); vi = gsl_matrix_complex_column(evec, i + 1); gsl_blas_zdscal(scale, &vi.vector); } } } /* nonsymmv_normalize_eigenvectors() */
/** * Returns the symmetry axis for the given matrix * * According to ITA, 11.2 the axis of a symmetry operation can be determined by * solving the Eigenvalue problem \f$Wu = u\f$ for rotations or \f$Wu = -u\f$ * for rotoinversions. This is implemented using the general real non-symmetric * eigen-problem solver provided by the GSL. * * @param matrix :: Matrix of a SymmetryOperation * @return Axis of symmetry element. */ V3R SymmetryElementWithAxisGenerator::determineAxis( const Kernel::IntMatrix &matrix) const { gsl_matrix *eigenMatrix = getGSLMatrix(matrix); gsl_matrix *identityMatrix = getGSLIdentityMatrix(matrix.numRows(), matrix.numCols()); gsl_eigen_genv_workspace *eigenWs = gsl_eigen_genv_alloc(matrix.numRows()); gsl_vector_complex *alpha = gsl_vector_complex_alloc(3); gsl_vector *beta = gsl_vector_alloc(3); gsl_matrix_complex *eigenVectors = gsl_matrix_complex_alloc(3, 3); gsl_eigen_genv(eigenMatrix, identityMatrix, alpha, beta, eigenVectors, eigenWs); gsl_eigen_genv_sort(alpha, beta, eigenVectors, GSL_EIGEN_SORT_ABS_DESC); double determinant = matrix.determinant(); Kernel::V3D eigenVector; for (size_t i = 0; i < matrix.numCols(); ++i) { double eigenValue = GSL_REAL(gsl_complex_div_real( gsl_vector_complex_get(alpha, i), gsl_vector_get(beta, i))); if (fabs(eigenValue - determinant) < 1e-9) { for (size_t j = 0; j < matrix.numRows(); ++j) { double element = GSL_REAL(gsl_matrix_complex_get(eigenVectors, j, i)); eigenVector[j] = element; } } } eigenVector *= determinant; double sumOfElements = eigenVector.X() + eigenVector.Y() + eigenVector.Z(); if (sumOfElements < 0) { eigenVector *= -1.0; } gsl_matrix_free(eigenMatrix); gsl_matrix_free(identityMatrix); gsl_eigen_genv_free(eigenWs); gsl_vector_complex_free(alpha); gsl_vector_free(beta); gsl_matrix_complex_free(eigenVectors); double min = 1.0; for (size_t i = 0; i < 3; ++i) { double absoluteValue = fabs(eigenVector[i]); if (absoluteValue != 0.0 && (eigenVector[i] < min && (absoluteValue - fabs(min)) < 1e-9)) { min = eigenVector[i]; } } V3R axis; for (size_t i = 0; i < 3; ++i) { axis[i] = static_cast<int>(boost::math::round(eigenVector[i] / min)); } return axis; }
void MCPMPChan::Run() { /// fetch data objects gsl_matrix_complex inmat = min1.GetDataObj(); gsl_matrix_complex cmat = min2.GetDataObj(); // inmat : input signal matrix x(n) (NxM) // i // complex sample at time n from Tx number i // cmat : channel coeffs matrix h(n) (M**2xN) // ij // cmat matrix structure // // +- -+ // | h(0) . . . . h(n) | | // | 11 11 | | // | | | Rx1 // | h(0) . . . . h(n) | | // | 12 12 | | // | | // | h(0) . . . . h(n) | | // | 21 21 | | // | | | Rx2 // | h(0) . . . . h(n) | | // | 22 22 | | // +- -+ // // where h(n) represents the channel impulse response // ij // // at time n, from tx i to rx j // the matrix has MxM rows and N comumns. // The (i,j) channel is locater at row i*M+j // with i,j in the range [0,M-1] and rows counting from 0 // // gsl_matrix_complex_set_zero(outmat); for (int rx=0;rx<M();rx++) { //loop through Rx // // csubmat creates a view on cmat extracting the MxN submatrix for Rx number u // gsl_matrix_complex_const_view csubmat = gsl_matrix_complex_const_submatrix(&cmat,rx*M(),0,M(),N()); // // cut a slice of outmat // gsl_vector_complex_view outvec = gsl_matrix_complex_column(outmat,rx); for (int tx=0;tx<M();tx++) { // loop through Tx // // input signal from tx // gsl_vector_complex_view x = gsl_matrix_complex_column(&inmat,tx); gsl_vector_complex *tmp = gsl_vector_complex_alloc(N()); // // // extract the current tx-rx channel matrix // // for (int i=0; i<N(); i++) { gsl_complex h = gsl_matrix_complex_get(&csubmat.matrix,tx,(N()-i)%N()); for (int j=0; j<N(); j++) { gsl_matrix_complex_set(user_chan,j,(j+i) % N(),h); } } // cout << "Channel (" << tx << "-" << rx << "):" << endl; // gsl_matrix_complex_show(user_chan); // // compute the signal rx = H tx // gsl_blas_zgemv(CblasNoTrans, gsl_complex_rect(1.0,0), user_chan, &x.vector, gsl_complex_rect(0,0), tmp); // // sum for each tx // gsl_vector_complex_add(&outvec.vector,tmp); gsl_vector_complex_free(tmp); } // tx loop for (int i=0; i< N(); i++) { gsl_complex noisesample = gsl_complex_rect( gsl_ran_gaussian(ran,noisestd), gsl_ran_gaussian(ran,noisestd)); gsl_complex ctmp = gsl_complex_add(gsl_vector_complex_get(&outvec.vector,i),noisesample); gsl_vector_complex_set(&outvec.vector,i,ctmp); } } // rx loop // cout << "received signals matrix (" << N() << "x" << M() << ")" << endl; // gsl_matrix_complex_show(outmat); //////// production of data mout1.DeliverDataObj( *outmat ); }
static void nonsymmv_get_right_eigenvectors(gsl_matrix *T, gsl_matrix *Z, gsl_vector_complex *eval, gsl_matrix_complex *evec, gsl_eigen_nonsymmv_workspace *w) { const size_t N = T->size1; const double smlnum = GSL_DBL_MIN * N / GSL_DBL_EPSILON; const double bignum = (1.0 - GSL_DBL_EPSILON) / smlnum; int i; /* looping */ size_t iu, /* looping */ ju, ii; gsl_complex lambda; /* current eigenvalue */ double lambda_re, /* Re(lambda) */ lambda_im; /* Im(lambda) */ gsl_matrix_view Tv, /* temporary views */ Zv; gsl_vector_view y, /* temporary views */ y2, ev, ev2; double dat[4], /* scratch arrays */ dat_X[4]; double scale; /* scale factor */ double xnorm; /* |X| */ gsl_vector_complex_view ecol, /* column of evec */ ecol2; int complex_pair; /* complex eigenvalue pair? */ double smin; /* * Compute 1-norm of each column of upper triangular part of T * to control overflow in triangular solver */ gsl_vector_set(w->work3, 0, 0.0); for (ju = 1; ju < N; ++ju) { gsl_vector_set(w->work3, ju, 0.0); for (iu = 0; iu < ju; ++iu) { gsl_vector_set(w->work3, ju, gsl_vector_get(w->work3, ju) + fabs(gsl_matrix_get(T, iu, ju))); } } for (i = (int) N - 1; i >= 0; --i) { iu = (size_t) i; /* get current eigenvalue and store it in lambda */ lambda_re = gsl_matrix_get(T, iu, iu); if (iu != 0 && gsl_matrix_get(T, iu, iu - 1) != 0.0) { lambda_im = sqrt(fabs(gsl_matrix_get(T, iu, iu - 1))) * sqrt(fabs(gsl_matrix_get(T, iu - 1, iu))); } else { lambda_im = 0.0; } GSL_SET_COMPLEX(&lambda, lambda_re, lambda_im); smin = GSL_MAX(GSL_DBL_EPSILON * (fabs(lambda_re) + fabs(lambda_im)), smlnum); smin = GSL_MAX(smin, GSL_NONSYMMV_SMLNUM); if (lambda_im == 0.0) { int k, l; gsl_vector_view bv, xv; /* real eigenvector */ /* * The ordering of eigenvalues in 'eval' is arbitrary and * does not necessarily follow the Schur form T, so store * lambda in the right slot in eval to ensure it corresponds * to the eigenvector we are about to compute */ gsl_vector_complex_set(eval, iu, lambda); /* * We need to solve the system: * * (T(1:iu-1, 1:iu-1) - lambda*I)*X = -T(1:iu-1,iu) */ /* construct right hand side */ for (k = 0; k < i; ++k) { gsl_vector_set(w->work, (size_t) k, -gsl_matrix_get(T, (size_t) k, iu)); } gsl_vector_set(w->work, iu, 1.0); for (l = i - 1; l >= 0; --l) { size_t lu = (size_t) l; if (lu == 0) complex_pair = 0; else complex_pair = gsl_matrix_get(T, lu, lu - 1) != 0.0; if (!complex_pair) { double x; /* * 1-by-1 diagonal block - solve the system: * * (T_{ll} - lambda)*x = -T_{l(iu)} */ Tv = gsl_matrix_submatrix(T, lu, lu, 1, 1); bv = gsl_vector_view_array(dat, 1); gsl_vector_set(&bv.vector, 0, gsl_vector_get(w->work, lu)); xv = gsl_vector_view_array(dat_X, 1); gsl_schur_solve_equation(1.0, &Tv.matrix, lambda_re, 1.0, 1.0, &bv.vector, &xv.vector, &scale, &xnorm, smin); /* scale x to avoid overflow */ x = gsl_vector_get(&xv.vector, 0); if (xnorm > 1.0) { if (gsl_vector_get(w->work3, lu) > bignum / xnorm) { x /= xnorm; scale /= xnorm; } } if (scale != 1.0) { gsl_vector_view wv; wv = gsl_vector_subvector(w->work, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); } gsl_vector_set(w->work, lu, x); if (lu > 0) { gsl_vector_view v1, v2; /* update right hand side */ v1 = gsl_matrix_subcolumn(T, lu, 0, lu); v2 = gsl_vector_subvector(w->work, 0, lu); gsl_blas_daxpy(-x, &v1.vector, &v2.vector); } /* if (l > 0) */ } /* if (!complex_pair) */ else { double x11, x21; /* * 2-by-2 diagonal block */ Tv = gsl_matrix_submatrix(T, lu - 1, lu - 1, 2, 2); bv = gsl_vector_view_array(dat, 2); gsl_vector_set(&bv.vector, 0, gsl_vector_get(w->work, lu - 1)); gsl_vector_set(&bv.vector, 1, gsl_vector_get(w->work, lu)); xv = gsl_vector_view_array(dat_X, 2); gsl_schur_solve_equation(1.0, &Tv.matrix, lambda_re, 1.0, 1.0, &bv.vector, &xv.vector, &scale, &xnorm, smin); /* scale X(1,1) and X(2,1) to avoid overflow */ x11 = gsl_vector_get(&xv.vector, 0); x21 = gsl_vector_get(&xv.vector, 1); if (xnorm > 1.0) { double beta; beta = GSL_MAX(gsl_vector_get(w->work3, lu - 1), gsl_vector_get(w->work3, lu)); if (beta > bignum / xnorm) { x11 /= xnorm; x21 /= xnorm; scale /= xnorm; } } /* scale if necessary */ if (scale != 1.0) { gsl_vector_view wv; wv = gsl_vector_subvector(w->work, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); } gsl_vector_set(w->work, lu - 1, x11); gsl_vector_set(w->work, lu, x21); /* update right hand side */ if (lu > 1) { gsl_vector_view v1, v2; v1 = gsl_matrix_subcolumn(T, lu - 1, 0, lu - 1); v2 = gsl_vector_subvector(w->work, 0, lu - 1); gsl_blas_daxpy(-x11, &v1.vector, &v2.vector); v1 = gsl_matrix_subcolumn(T, lu, 0, lu - 1); gsl_blas_daxpy(-x21, &v1.vector, &v2.vector); } --l; } /* if (complex_pair) */ } /* for (l = i - 1; l >= 0; --l) */ /* * At this point, w->work is an eigenvector of the * Schur form T. To get an eigenvector of the original * matrix, we multiply on the left by Z, the matrix of * Schur vectors */ ecol = gsl_matrix_complex_column(evec, iu); y = gsl_matrix_column(Z, iu); if (iu > 0) { gsl_vector_view x; Zv = gsl_matrix_submatrix(Z, 0, 0, N, iu); x = gsl_vector_subvector(w->work, 0, iu); /* compute Z * w->work and store it in Z(:,iu) */ gsl_blas_dgemv(CblasNoTrans, 1.0, &Zv.matrix, &x.vector, gsl_vector_get(w->work, iu), &y.vector); } /* if (iu > 0) */ /* store eigenvector into evec */ ev = gsl_vector_complex_real(&ecol.vector); ev2 = gsl_vector_complex_imag(&ecol.vector); scale = 0.0; for (ii = 0; ii < N; ++ii) { double a = gsl_vector_get(&y.vector, ii); /* store real part of eigenvector */ gsl_vector_set(&ev.vector, ii, a); /* set imaginary part to 0 */ gsl_vector_set(&ev2.vector, ii, 0.0); if (fabs(a) > scale) scale = fabs(a); } if (scale != 0.0) scale = 1.0 / scale; /* scale by magnitude of largest element */ gsl_blas_dscal(scale, &ev.vector); } /* if (GSL_IMAG(lambda) == 0.0) */ else { gsl_vector_complex_view bv, xv; size_t k; int l; gsl_complex lambda2; /* complex eigenvector */ /* * Store the complex conjugate eigenvalues in the right * slots in eval */ GSL_SET_REAL(&lambda2, GSL_REAL(lambda)); GSL_SET_IMAG(&lambda2, -GSL_IMAG(lambda)); gsl_vector_complex_set(eval, iu - 1, lambda); gsl_vector_complex_set(eval, iu, lambda2); /* * First solve: * * [ T(i:i+1,i:i+1) - lambda*I ] * X = 0 */ if (fabs(gsl_matrix_get(T, iu - 1, iu)) >= fabs(gsl_matrix_get(T, iu, iu - 1))) { gsl_vector_set(w->work, iu - 1, 1.0); gsl_vector_set(w->work2, iu, lambda_im / gsl_matrix_get(T, iu - 1, iu)); } else { gsl_vector_set(w->work, iu - 1, -lambda_im / gsl_matrix_get(T, iu, iu - 1)); gsl_vector_set(w->work2, iu, 1.0); } gsl_vector_set(w->work, iu, 0.0); gsl_vector_set(w->work2, iu - 1, 0.0); /* construct right hand side */ for (k = 0; k < iu - 1; ++k) { gsl_vector_set(w->work, k, -gsl_vector_get(w->work, iu - 1) * gsl_matrix_get(T, k, iu - 1)); gsl_vector_set(w->work2, k, -gsl_vector_get(w->work2, iu) * gsl_matrix_get(T, k, iu)); } /* * We must solve the upper quasi-triangular system: * * [ T(1:i-2,1:i-2) - lambda*I ] * X = s*(work + i*work2) */ for (l = i - 2; l >= 0; --l) { size_t lu = (size_t) l; if (lu == 0) complex_pair = 0; else complex_pair = gsl_matrix_get(T, lu, lu - 1) != 0.0; if (!complex_pair) { gsl_complex bval; gsl_complex x; /* * 1-by-1 diagonal block - solve the system: * * (T_{ll} - lambda)*x = work + i*work2 */ Tv = gsl_matrix_submatrix(T, lu, lu, 1, 1); bv = gsl_vector_complex_view_array(dat, 1); xv = gsl_vector_complex_view_array(dat_X, 1); GSL_SET_COMPLEX(&bval, gsl_vector_get(w->work, lu), gsl_vector_get(w->work2, lu)); gsl_vector_complex_set(&bv.vector, 0, bval); gsl_schur_solve_equation_z(1.0, &Tv.matrix, &lambda, 1.0, 1.0, &bv.vector, &xv.vector, &scale, &xnorm, smin); if (xnorm > 1.0) { if (gsl_vector_get(w->work3, lu) > bignum / xnorm) { gsl_blas_zdscal(1.0/xnorm, &xv.vector); scale /= xnorm; } } /* scale if necessary */ if (scale != 1.0) { gsl_vector_view wv; wv = gsl_vector_subvector(w->work, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); wv = gsl_vector_subvector(w->work2, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); } x = gsl_vector_complex_get(&xv.vector, 0); gsl_vector_set(w->work, lu, GSL_REAL(x)); gsl_vector_set(w->work2, lu, GSL_IMAG(x)); /* update the right hand side */ if (lu > 0) { gsl_vector_view v1, v2; v1 = gsl_matrix_subcolumn(T, lu, 0, lu); v2 = gsl_vector_subvector(w->work, 0, lu); gsl_blas_daxpy(-GSL_REAL(x), &v1.vector, &v2.vector); v2 = gsl_vector_subvector(w->work2, 0, lu); gsl_blas_daxpy(-GSL_IMAG(x), &v1.vector, &v2.vector); } /* if (lu > 0) */ } /* if (!complex_pair) */ else { gsl_complex b1, b2, x1, x2; /* * 2-by-2 diagonal block - solve the system */ Tv = gsl_matrix_submatrix(T, lu - 1, lu - 1, 2, 2); bv = gsl_vector_complex_view_array(dat, 2); xv = gsl_vector_complex_view_array(dat_X, 2); GSL_SET_COMPLEX(&b1, gsl_vector_get(w->work, lu - 1), gsl_vector_get(w->work2, lu - 1)); GSL_SET_COMPLEX(&b2, gsl_vector_get(w->work, lu), gsl_vector_get(w->work2, lu)); gsl_vector_complex_set(&bv.vector, 0, b1); gsl_vector_complex_set(&bv.vector, 1, b2); gsl_schur_solve_equation_z(1.0, &Tv.matrix, &lambda, 1.0, 1.0, &bv.vector, &xv.vector, &scale, &xnorm, smin); x1 = gsl_vector_complex_get(&xv.vector, 0); x2 = gsl_vector_complex_get(&xv.vector, 1); if (xnorm > 1.0) { double beta; beta = GSL_MAX(gsl_vector_get(w->work3, lu - 1), gsl_vector_get(w->work3, lu)); if (beta > bignum / xnorm) { gsl_blas_zdscal(1.0/xnorm, &xv.vector); scale /= xnorm; } } /* scale if necessary */ if (scale != 1.0) { gsl_vector_view wv; wv = gsl_vector_subvector(w->work, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); wv = gsl_vector_subvector(w->work2, 0, iu + 1); gsl_blas_dscal(scale, &wv.vector); } gsl_vector_set(w->work, lu - 1, GSL_REAL(x1)); gsl_vector_set(w->work, lu, GSL_REAL(x2)); gsl_vector_set(w->work2, lu - 1, GSL_IMAG(x1)); gsl_vector_set(w->work2, lu, GSL_IMAG(x2)); /* update right hand side */ if (lu > 1) { gsl_vector_view v1, v2, v3, v4; v1 = gsl_matrix_subcolumn(T, lu - 1, 0, lu - 1); v4 = gsl_matrix_subcolumn(T, lu, 0, lu - 1); v2 = gsl_vector_subvector(w->work, 0, lu - 1); v3 = gsl_vector_subvector(w->work2, 0, lu - 1); gsl_blas_daxpy(-GSL_REAL(x1), &v1.vector, &v2.vector); gsl_blas_daxpy(-GSL_REAL(x2), &v4.vector, &v2.vector); gsl_blas_daxpy(-GSL_IMAG(x1), &v1.vector, &v3.vector); gsl_blas_daxpy(-GSL_IMAG(x2), &v4.vector, &v3.vector); } /* if (lu > 1) */ --l; } /* if (complex_pair) */ } /* for (l = i - 2; l >= 0; --l) */ /* * At this point, work + i*work2 is an eigenvector * of T - backtransform to get an eigenvector of the * original matrix */ y = gsl_matrix_column(Z, iu - 1); y2 = gsl_matrix_column(Z, iu); if (iu > 1) { gsl_vector_view x; /* compute real part of eigenvectors */ Zv = gsl_matrix_submatrix(Z, 0, 0, N, iu - 1); x = gsl_vector_subvector(w->work, 0, iu - 1); gsl_blas_dgemv(CblasNoTrans, 1.0, &Zv.matrix, &x.vector, gsl_vector_get(w->work, iu - 1), &y.vector); /* now compute the imaginary part */ x = gsl_vector_subvector(w->work2, 0, iu - 1); gsl_blas_dgemv(CblasNoTrans, 1.0, &Zv.matrix, &x.vector, gsl_vector_get(w->work2, iu), &y2.vector); } else { gsl_blas_dscal(gsl_vector_get(w->work, iu - 1), &y.vector); gsl_blas_dscal(gsl_vector_get(w->work2, iu), &y2.vector); } /* * Now store the eigenvectors into evec - the real parts * are Z(:,iu - 1) and the imaginary parts are * +/- Z(:,iu) */ /* get views of the two eigenvector slots */ ecol = gsl_matrix_complex_column(evec, iu - 1); ecol2 = gsl_matrix_complex_column(evec, iu); /* * save imaginary part first as it may get overwritten * when copying the real part due to our storage scheme * in Z/evec */ ev = gsl_vector_complex_imag(&ecol.vector); ev2 = gsl_vector_complex_imag(&ecol2.vector); scale = 0.0; for (ii = 0; ii < N; ++ii) { double a = gsl_vector_get(&y2.vector, ii); scale = GSL_MAX(scale, fabs(a) + fabs(gsl_vector_get(&y.vector, ii))); gsl_vector_set(&ev.vector, ii, a); gsl_vector_set(&ev2.vector, ii, -a); } /* now save the real part */ ev = gsl_vector_complex_real(&ecol.vector); ev2 = gsl_vector_complex_real(&ecol2.vector); for (ii = 0; ii < N; ++ii) { double a = gsl_vector_get(&y.vector, ii); gsl_vector_set(&ev.vector, ii, a); gsl_vector_set(&ev2.vector, ii, a); } if (scale != 0.0) scale = 1.0 / scale; /* scale by largest element magnitude */ gsl_blas_zdscal(scale, &ecol.vector); gsl_blas_zdscal(scale, &ecol2.vector); /* * decrement i since we took care of two eigenvalues at * the same time */ --i; } /* if (GSL_IMAG(lambda) != 0.0) */ } /* for (i = (int) N - 1; i >= 0; --i) */ } /* nonsymmv_get_right_eigenvectors() */
void SteadyState::classifyState( const double* T ) { #ifdef USE_GSL // unsigned int nConsv = numVarPools_ - rank_; gsl_matrix* J = gsl_matrix_calloc ( numVarPools_, numVarPools_ ); // double* yprime = new double[ numVarPools_ ]; // vector< double > yprime( numVarPools_, 0.0 ); // Generate an approximation to the Jacobean by generating small // increments to each of the molecules in the steady state, one // at a time, and putting the resultant rate vector into a column // of the J matrix. // This needs a bit of heuristic to decide what is a 'small' increment. // Use the CoInits for this. Stoichiometry shouldn't matter too much. // I used the totals from consv rules earlier, but that can have // negative values. double tot = 0.0; Stoich* s = reinterpret_cast< Stoich* >( stoich_.eref().data() ); vector< double > nVec = LookupField< unsigned int, vector< double > >::get( s->getKsolve(), "nVec", 0 ); for ( unsigned int i = 0; i < numVarPools_; ++i ) { tot += nVec[i]; } tot *= DELTA; vector< double > yprime( nVec.size(), 0.0 ); // Fill up Jacobian for ( unsigned int i = 0; i < numVarPools_; ++i ) { double orig = nVec[i]; if ( isnan( orig ) ) { cout << "Warning: SteadyState::classifyState: orig=nan\n"; solutionStatus_ = 2; // Steady state OK, eig failed gsl_matrix_free ( J ); return; } if ( isnan( tot ) ) { cout << "Warning: SteadyState::classifyState: tot=nan\n"; solutionStatus_ = 2; // Steady state OK, eig failed gsl_matrix_free ( J ); return; } nVec[i] = orig + tot; /// Here we assume we always use voxel zero. s->updateRates( &nVec[0], &yprime[0], 0 ); nVec[i] = orig; // Assign the rates for each mol. for ( unsigned int j = 0; j < numVarPools_; ++j ) { gsl_matrix_set( J, i, j, yprime[j] ); } } // Jacobian is now ready. Find eigenvalues. gsl_vector_complex* vec = gsl_vector_complex_alloc( numVarPools_ ); gsl_eigen_nonsymm_workspace* workspace = gsl_eigen_nonsymm_alloc( numVarPools_ ); int status = gsl_eigen_nonsymm( J, vec, workspace ); eigenvalues_.clear(); eigenvalues_.resize( numVarPools_, 0.0 ); if ( status != GSL_SUCCESS ) { cout << "Warning: SteadyState::classifyState failed to find eigenvalues. Status = " << status << endl; solutionStatus_ = 2; // Steady state OK, eig classification failed } else { // Eigenvalues are ready. Classify state. nNegEigenvalues_ = 0; nPosEigenvalues_ = 0; for ( unsigned int i = 0; i < numVarPools_; ++i ) { gsl_complex z = gsl_vector_complex_get( vec, i ); double r = GSL_REAL( z ); nNegEigenvalues_ += ( r < -EPSILON ); nPosEigenvalues_ += ( r > EPSILON ); eigenvalues_[i] = r; // We have a problem here because numVarPools_ usually > rank // This means we have several zero eigenvalues. } if ( nNegEigenvalues_ == rank_ ) stateType_ = 0; // Stable else if ( nPosEigenvalues_ == rank_ ) // Never see it. stateType_ = 1; // Unstable else if (nPosEigenvalues_ == 1) stateType_ = 2; // Saddle else if ( nPosEigenvalues_ >= 2 ) stateType_ = 3; // putative oscillatory else if ( nNegEigenvalues_ == ( rank_ - 1) && nPosEigenvalues_ == 0 ) stateType_ = 4; // one zero or unclassified eigenvalue. Messy. else stateType_ = 5; // Other } gsl_vector_complex_free( vec ); gsl_matrix_free ( J ); gsl_eigen_nonsymm_free( workspace ); #endif }
void vector_acc(gsl_vector_complex *V,unsigned n, double _Complex a){ gsl_complex T1; T1=gsl_vector_complex_get(V,n); gsl_vector_complex_set(V,n,gsl_complex_add(T1,c2g(a))); }
double _Complex vector_get(gsl_vector_complex *V,unsigned n){ return g2c(gsl_vector_complex_get(V,n)); }
void SoftDemapper::Run() { unsigned int nbits,nsymbs,count; /// fetch data objects gsl_vector_complex_class input = vin1.GetDataObj(); // number of input symbs nsymbs = input.vec->size; // cout << "received " << nsymbs << " elements in vector." << endl; // number of output symbols nbits = nsymbs * Nb(); gsl_vector *llr=gsl_vector_alloc(nbits); double *den = (double *)calloc( Nb(), sizeof(double) ); double *num = (double *)calloc( Nb(), sizeof(double) ); // determine symb_likelyhood for (int i=0;i<nsymbs;i++) { // cycle through received symbols for (int k=0;k<Nb();k++) { num[k] = GSL_NEGINF; den[k] = GSL_NEGINF; } // the received symbol gsl_complex recsym = gsl_vector_complex_get(input.vec,i); // cout << "received symbol = (" // << GSL_REAL(recsym) // << "," // << GSL_IMAG(recsym) // << ") " << endl; for (int j=0;j<Ns;j++) { // cycle through postulated symbol // gray encoded symbol id unsigned int symbol_id = gsl_vector_uint_get(gray_encoding,j); // complex symbol gsl_complex refsym = gsl_complex_polar(1.0,symbol_arg * symbol_id ); // likelyhood metric double metric = gsl_complex_abs( gsl_complex_sub(refsym,recsym) ); metric = -EsNo()*metric*metric; //gsl_matrix_complex_set(symb_likelihoods,j,i); // // HERE is available a metric for symb i and refsymb j // int mask = 1 << Nb() - 1; for (int k=0;k<Nb();k++) { /* loop over bits */ if (mask&j) { /* this bit is a one */ num[k] = ( *max_star[LMAP()] )( num[k], metric ); } else { /* this bit is a zero */ den[k] = ( *max_star[LMAP()] )( den[k], metric ); } mask = mask >> 1; } //bits } // alphabet for (int k=0;k<Nb();k++) { gsl_vector_set(llr,Nb()*i+k,num[k] - den[k]); } } // symbols gsl_vector_class outv(llr); // outv.show(); // output bitwise LLR vout1.DeliverDataObj(outv); gsl_vector_free(llr); // free dynamic structures free(num); free(den); }
vectorc::vectorc(const vectorc& vec) : size_m(vec.size_m), v_m(gsl_vector_complex_alloc(vec.size_m)) { for (int i=0; i<size_m; i++) gsl_vector_complex_set(v_m, i, gsl_vector_complex_get(vec.v_m, i)); }
vectorc::ComplexProxy& vectorc::ComplexProxy::operator=(const ComplexProxy& rhs) { gsl_vector_complex_set(theVector.v_m, ComplexIndex, gsl_vector_complex_get(rhs.theVector.v_m, ComplexIndex)); return *this; }
vectorc::ComplexProxy::operator gsl_complex() const { return gsl_vector_complex_get(theVector.v_m, ComplexIndex); }
/** * \brief Find a change point in complex data * * This function is based in the Bayesian Blocks algorithm of \cite Scargle1998 that finds "change points" in data - * points at which the statistics of the data change. It is based on calculating evidence, or odds, ratios. The * function first computes the marginal likelihood (or evidence) that the whole of the data is described by a single * Gaussian (with mean of zero). This comes from taking a Gaussian likelihood function and analytically marginalising * over the standard deviation (using a prior on the standard deviation of \f$1/\sigma\f$), giving (see * [\cite DupuisWoan2005]) a Students-t distribution (see * <a href="https://wiki.ligo.org/foswiki/pub/CW/PulsarParameterEstimationNestedSampling/studentst.pdf">here</a>). * Following this the data is split into two segments (with lengths greater than, or equal to the minimum chunk length) * for all possible combinations, and the joint evidence for each of the two segments consisting of independent * Gaussian (basically multiplying the above equation calculated for each segment separately) is calculated and the * split point recorded. However, the value required for comparing to that for the whole data set, to give the odds * ratio, is the evidence that having any split is better than having no split, so the individual split data evidences * need to be added incoherently to give the total evidence for a split. The index at which the evidence for a single * split is maximum (i.e. the most favoured split point) is that which is returned. * * \param data [in] a complex data vector * \param logodds [in] a pointer to return the natural logarithm of the odds ratio/Bayes factor * \param minlength [in] the minimum chunk length * * \return The position of the change point */ UINT4 find_change_point( gsl_vector_complex *data, REAL8 *logodds, UINT4 minlength ){ UINT4 changepoint = 0, i = 0; UINT4 length = (UINT4)data->size, lsum = 0; REAL8 datasum = 0.; REAL8 logsingle = 0., logtot = -INFINITY; REAL8 logdouble = 0., logdouble_min = -INFINITY; REAL8 logratio = 0.; REAL8 sumforward = 0., sumback = 0.; gsl_complex dval; /* check that data is at least twice the minimum length, if not return an odds ratio of zero (log odds = -inf [or close to that!]) */ if ( length < (UINT4)(2*minlength) ){ logratio = -INFINITY; memcpy(logodds, &logratio, sizeof(REAL8)); return 0; } /* calculate the sum of the data squared */ for (i = 0; i < length; i++) { dval = gsl_vector_complex_get( data, i ); datasum += SQUARE( gsl_complex_abs( dval ) ); } /* calculate the evidence that the data consists of a Gaussian data with a single standard deviation */ logsingle = -LAL_LN2 - (REAL8)length*LAL_LNPI + gsl_sf_lnfact(length-1) - (REAL8)length * log( datasum ); lsum = length - 2*minlength + 1; for ( i = 0; i < length; i++ ){ dval = gsl_vector_complex_get( data, i ); if ( i < minlength-1 ){ sumforward += SQUARE( gsl_complex_abs( dval ) ); } else{ sumback += SQUARE( gsl_complex_abs( dval ) ); } } /* go through each possible change point and calculate the evidence for the data consisting of two independent * Gaussian's either side of the change point. Also calculate the total evidence for any change point. * Don't allow single points, so start at the second data point. */ for (i = 0; i < lsum; i++){ UINT4 ln1 = i+minlength, ln2 = (length-i-minlength); REAL8 log_1 = 0., log_2 = 0.; dval = gsl_vector_complex_get( data, ln1-1 ); REAL8 adval = SQUARE( gsl_complex_abs( dval ) ); sumforward += adval; sumback -= adval; /* get log evidences for the individual segments */ log_1 = -LAL_LN2 - (REAL8)ln1*LAL_LNPI + gsl_sf_lnfact(ln1-1) - (REAL8)ln1 * log( sumforward ); log_2 = -LAL_LN2 - (REAL8)ln2*LAL_LNPI + gsl_sf_lnfact(ln2-1) - (REAL8)ln2 * log( sumback ); /* get evidence for the two segments */ logdouble = log_1 + log_2; /* add to total evidence for a change point */ logtot = LOGPLUS(logtot, logdouble); /* find maximum value of logdouble and record that as the change point */ if ( logdouble > logdouble_min ){ changepoint = ln1; logdouble_min = logdouble; } } /* get the log odds ratio of segmented versus non-segmented model */ logratio = logtot - logsingle; memcpy(logodds, &logratio, sizeof(REAL8)); return changepoint; }