//*************************************************TERM 3************************************************* dcomplex Zetafunc::term3full(const double q2){ double resultre=0.,resultim=0.; #pragma omp parallel { double tmp,r,theta,phi,wdprod,ghatwnorm; dcomplex result(0.,0.),tmpcomp1,tmpcomp2,tmpcomp3; threevec<double> wvec,ghatw,wpar,wperp; Zetafuncint integrand2; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) for(int z=-MAXRUN; z<=MAXRUN; z++){ for(int y=-MAXRUN; y<=MAXRUN; y++){ for(int x=-MAXRUN; x<=MAXRUN; x++){ if( (x==0) && (y==0) && (z==0) ) continue; //exclude zero! wvec(static_cast<double>(x),static_cast<double>(y),static_cast<double>(z)); //compute scalar product and orthogonal projection: if(!is_zeroboost){ orthogonal_projection(wvec,boost,wpar,wperp); ghatw=gamma*wpar+wperp; } else{ ghatw=wvec; } ghatwnorm=ghatw.norm(); //solve the integral: integrand2.set(q2,ghatwnorm,l); Midpnt<TFunctor> int2(integrand2,0.,lambda); tmp=qromo(int2); if(l!=0) tmp*=::std::pow(ghatwnorm,static_cast<double>(l)); //compute the complex parts: ghatw.get_spherical_coordinates(r,theta,phi); tmpcomp1=spherical_harmonicy(l,m,theta,phi); //exip(-ipi w*d)-term if(!is_zeroboost){ wdprod=wvec*boost; tmpcomp2(cos(pimath*wdprod),-sin(pimath*wdprod)); } else tmpcomp2(1.,0.); tmpcomp3=tmpcomp1*tmpcomp2*tmp; //result+=tmpcomp3; resultre+=tmpcomp3.re(); resultim+=tmpcomp3.im(); } } } } dcomplex result(resultre,resultim); result*=gamma*::std::pow(pimath,static_cast<double>(1.5+l)); return result; }
inline int getri (MatrA& a, IVec& ipiv) { #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS typedef typename traits::matrix_traits<MatrA>::value_type val_t; #else typedef typename MatrA::value_type val_t; #endif //TODO: compute optimal size of work array. Useful for small arrays? int const o = traits::matrix_size2 (a) < traits::matrix_size1 (a) ? traits::matrix_size2 (a) : traits::matrix_size1 (a); traits::detail::array <val_t> wvec (o); return getri (a, ipiv, wvec); }
static void Diagonalizer_and_CrossCorrelationTable_qdiag (Diagonalizer me, CrossCorrelationTables thee, double *cweights, long maxNumberOfIterations, double delta) { try { CrossCorrelationTable c0 = (CrossCorrelationTable) thy item[1]; double **w = my data; long dimension = c0 -> numberOfColumns; autoEigen eigen = Thing_new (Eigen); autoCrossCorrelationTables ccts = Data_copy (thee); autoNUMmatrix<double> pinv (1, dimension, 1, dimension); autoNUMmatrix<double> d (1, dimension, 1, dimension); autoNUMmatrix<double> p (1, dimension, 1, dimension); autoNUMmatrix<double> m1 (1, dimension, 1, dimension); autoNUMmatrix<double> wc (1, dimension, 1, dimension); autoNUMvector<double> wvec (1, dimension); autoNUMvector<double> wnew (1, dimension); autoNUMvector<double> mvec (1, dimension); for (long i = 1; i <= dimension; i++) // Transpose W for (long j = 1; j <= dimension; j++) { wc[i][j] = w[j][i]; } // d = diag(diag(W'*C0*W)); // W = W*d^(-1/2); NUMdmatrix_normalizeColumnVectors (wc.peek(), dimension, dimension, c0 -> data); // scale eigenvectors for sphering // [vb,db] = eig(C0); // P = db^(-1/2)*vb'; Eigen_initFromSymmetricMatrix (eigen.peek(), c0 -> data, dimension); for (long i = 1; i <= dimension; i++) { if (eigen -> eigenvalues[i] < 0) { Melder_throw (U"Covariance matrix not positive definite, eigenvalue[", i, U"] is negative."); } double scalef = 1 / sqrt (eigen -> eigenvalues[i]); for (long j = 1; j <= dimension; j++) { p[dimension - i + 1][j] = scalef * eigen -> eigenvectors[i][j]; } } // P*C[i]*P' for (long ic = 1; ic <= thy size; ic++) { CrossCorrelationTable cov1 = (CrossCorrelationTable) thy item[ic]; CrossCorrelationTable cov2 = (CrossCorrelationTable) ccts -> item[ic]; NUMdmatrices_multiply_VCVp (cov2 -> data, p.peek(), dimension, dimension, cov1 -> data, 1); } // W = P'\W == inv(P') * W NUMpseudoInverse (p.peek(), dimension, dimension, pinv.peek(), 0); NUMdmatrices_multiply_VpC (w, pinv.peek(), dimension, dimension, wc.peek(), dimension); // initialisation for order KN^3 for (long ic = 2; ic <= thy size; ic++) { CrossCorrelationTable cov = (CrossCorrelationTable) ccts -> item[ic]; // C * W NUMdmatrices_multiply_VC (m1.peek(), cov -> data, dimension, dimension, w, dimension); // D += scalef * M1*M1' NUMdmatrices_multiplyScaleAdd (d.peek(), m1.peek(), dimension, dimension, 2 * cweights[ic]); } long iter = 0; double delta_w; autoMelderProgress progress (U"Simultaneous diagonalization of many CrossCorrelationTables..."); try { do { // the standard diagonality measure is rather expensive to calculate so we compare the norms of // differences of eigenvectors. delta_w = 0; for (long kol = 1; kol <= dimension; kol++) { for (long i = 1; i <= dimension; i++) { wvec[i] = w[i][kol]; } update_one_column (ccts.peek(), d.peek(), cweights, wvec.peek(), -1, mvec.peek()); Eigen_initFromSymmetricMatrix (eigen.peek(), d.peek(), dimension); // Eigenvalues already sorted; get eigenvector of smallest ! for (long i = 1; i <= dimension; i++) { wnew[i] = eigen -> eigenvectors[dimension][i]; } update_one_column (ccts.peek(), d.peek(), cweights, wnew.peek(), 1, mvec.peek()); for (long i = 1; i <= dimension; i++) { w[i][kol] = wnew[i]; } // compare norms of eigenvectors. We have to compare ||wvec +/- w_new|| because eigenvectors // may change sign. double normp = 0, normm = 0; for (long j = 1; j <= dimension; j++) { double dm = wvec[j] - wnew[j], dp = wvec[j] + wnew[j]; normp += dm * dm; normm += dp * dp; } normp = normp < normm ? normp : normm; normp = sqrt (normp); delta_w = normp > delta_w ? normp : delta_w; } iter++; Melder_progress ((double) iter / (double) (maxNumberOfIterations + 1), U"Iteration: ", iter, U", norm: ", delta_w); } while (delta_w > delta && iter < maxNumberOfIterations); } catch (MelderError) { Melder_clearError (); } // Revert the sphering W = P'*W; // Take transpose to make W*C[i]W' diagonal instead of W'*C[i]*W => (P'*W)'=W'*P NUMmatrix_copyElements (w, wc.peek(), 1, dimension, 1, dimension); NUMdmatrices_multiply_VpC (w, wc.peek(), dimension, dimension, p.peek(), dimension); // W = W'*P: final result // Calculate the "real" diagonality measure // double dm = CrossCorrelationTables_and_Diagonalizer_getDiagonalityMeasure (thee, me, cweights, 1, thy size); } catch (MelderError) { Melder_throw (me, U" & ", thee, U": no joint diagonalization (qdiag)."); } }