#ifdef newc #include #include #include #include #include #include using namespace std; #else #include #include #include #include #include #endif #include #include "misc.h" #include "macrodef.h" #include "zbesh.h" #define PI M_PI void misc::tillherecheck(int myrank) { int atp = 1, tatp; MPI_Allreduce(&atp, &tatp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); if (myrank == 0) cout << " here now: " << tatp << " processors." << endl; } void misc::tillherecheck(const char str[]) { int myrank; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); int atp = 1, tatp; MPI_Allreduce(&atp, &tatp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); if (myrank == 0) { cout << " here now: " << tatp << " processors." << endl; cout << str << endl; } } void misc::tillherecheck(MPI_Comm Comm_here, int out_rank, const char str[]) { int myrank; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); int atp = 1, tatp; MPI_Allreduce(&atp, &tatp, 1, MPI_INT, MPI_SUM, Comm_here); if (myrank == out_rank) { cout << " here now: " << tatp << " processors." << endl; cout << str << endl; } } void misc::tillherecheck(MPI_Comm Comm_here, int out_rank, const string str) { int myrank; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); int atp = 1, tatp; MPI_Allreduce(&atp, &tatp, 1, MPI_INT, MPI_SUM, Comm_here); if (myrank == out_rank) { cout << " here now: " << tatp << " processors." << endl; cout << str << endl; } } // pick out value from input string int misc::parse_parts(string str, string &sgrp, string &skey, string &sval, int &ind) { int pos1, pos2; string s0; ind = 0; // remove comments str = str.substr(0, str.find("#")); if (rTrim(str).empty()) return 0; // continue; // parse {group, key, val} pos1 = str.find("::"); pos2 = str.find("="); if (pos1 == string::npos || pos2 == string::npos) return -1; s0 = str.substr(0, pos1); sgrp = lTrim(s0); s0 = str.substr(pos1 + 2, pos2 - pos1 - 2); skey = rTrim(s0); s0 = str.substr(pos2 + 1); sval = Trim(s0); pos1 = sval.find("\""); pos2 = sval.rfind("\""); if (pos1 != string::npos) { sval = sval.substr(1, pos2 - 1); } pos1 = skey.find("["); pos2 = skey.find("]"); if (pos1 != string::npos) { s0 = skey.substr(0, pos1); ind = atoi(skey.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); skey = s0; } return 1; } int misc::parse_parts(string str, string &sgrp, string &skey, string &sval, int &ind1, int &ind2) { int pos1, pos2; string s0, s1; ind1 = ind2 = 0; // remove comments str = str.substr(0, str.find("#")); if (rTrim(str).empty()) return 0; // continue; // parse {group, key, val} pos1 = str.find("::"); pos2 = str.find("="); if (pos1 == string::npos || pos2 == string::npos) return -1; s0 = str.substr(0, pos1); sgrp = lTrim(s0); s0 = str.substr(pos1 + 2, pos2 - pos1 - 2); skey = rTrim(s0); s0 = str.substr(pos2 + 1); sval = Trim(s0); pos1 = sval.find("\""); pos2 = sval.rfind("\""); if (pos1 != string::npos) { sval = sval.substr(1, pos2 - 1); } pos1 = skey.find("["); pos2 = skey.find("]"); if (pos1 != string::npos) { s0 = skey.substr(0, pos1); s1 = skey.substr(pos2 + 1); ind1 = atoi(skey.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); skey = s0; } pos1 = s1.find("["); pos2 = s1.find("]"); if (pos1 != string::npos) { s0 = s1.substr(pos2 + 1); ind2 = atoi(s1.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); } return 1; } int misc::parse_parts(string str, string &sgrp, string &skey, string &sval, int &ind1, int &ind2, int &ind3) { int pos1, pos2; string s0, s1; ind1 = ind2 = ind3 = 0; // remove comments str = str.substr(0, str.find("#")); if (rTrim(str).empty()) return 0; // continue; // parse {group, key, val} pos1 = str.find("::"); pos2 = str.find("="); if (pos1 == string::npos || pos2 == string::npos) return -1; s0 = str.substr(0, pos1); sgrp = lTrim(s0); s0 = str.substr(pos1 + 2, pos2 - pos1 - 2); skey = rTrim(s0); s0 = str.substr(pos2 + 1); sval = Trim(s0); pos1 = sval.find("\""); pos2 = sval.rfind("\""); if (pos1 != string::npos) { sval = sval.substr(1, pos2 - 1); } pos1 = skey.find("["); pos2 = skey.find("]"); if (pos1 != string::npos) { s0 = skey.substr(0, pos1); s1 = skey.substr(pos2 + 1); ind1 = atoi(skey.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); skey = s0; } pos1 = s1.find("["); pos2 = s1.find("]"); if (pos1 != string::npos) { s0 = s1.substr(pos2 + 1); ind2 = atoi(s1.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); } pos1 = s0.find("["); pos2 = s0.find("]"); if (pos1 != string::npos) { ind3 = atoi(s0.substr(pos1 + 1, pos2 - pos1 - 1).c_str()); } return 1; } // sent me from Roman Gold on 2010-10-8 void misc::gaulegf(double x1, double x2, double *x, double *w, int n) { int i, j, m; double eps = 1.2E-16; double p1, p2, p3, pp, xl, xm, z, z1; m = (n + 1) / 2; xm = 0.5 * (x2 + x1); xl = 0.5 * (x2 - x1); for (i = 0; i < m; i++) { z = cos(PI * ((double)i + 0.75) / ((double)n + 0.5)); do { p1 = 1.0; p2 = 0.0; for (j = 0; j < n; j++) { p3 = p2; p2 = p1; p1 = ((2 * (double)j + 1) * z * p2 - (double)j * p3) / ((double)j + 1); } pp = n * (z * p1 - p2) / (z * z - 1.0); z1 = z; z = z1 - p1 / pp; } while (fabs(z - z1) > eps); x[i] = xm - xl * z; x[n - 1 - i] = xm + xl * z; w[i] = 2.0 * xl / ((1.0 - z * z) * pp * pp); w[n - 1 - i] = w[i]; } } /* end gaulegf */ void misc::inversearray(double *aa, int NN) { int i, m; m = (NN + 1) / 2; double rr; for (i = 0; i < m; i++) { rr = aa[i]; aa[i] = aa[NN - 1 - i]; aa[NN - 1 - i] = rr; } } // Eq.(42) of PRD 77, 024027 (2008) double misc::Wigner_d_function(int l, int m, int s, double costheta) { // we consider only theta in [0,pi] int C1 = max(0, m - s), C2 = min(l + m, l - s); double vv = 0; double sinht = sqrt((1 - costheta) / 2.0), cosht = sqrt((1 + costheta) / 2.0); if (C1 % 2 == 0) { for (int t = C1; t < C2 + 1; t += 2) vv = vv + pow(cosht, 2 * l + m - s - 2 * t) * pow(sinht, 2 * t + s - m) / (fact(l + m - t) * fact(l - s - t) * fact(t) * fact(t + s - m)); for (int t = C1 + 1; t < C2 + 1; t += 2) vv = vv - pow(cosht, 2 * l + m - s - 2 * t) * pow(sinht, 2 * t + s - m) / (fact(l + m - t) * fact(l - s - t) * fact(t) * fact(t + s - m)); } else { for (int t = C1; t < C2 + 1; t += 2) vv = vv - pow(cosht, 2 * l + m - s - 2 * t) * pow(sinht, 2 * t + s - m) / (fact(l + m - t) * fact(l - s - t) * fact(t) * fact(t + s - m)); for (int t = C1 + 1; t < C2 + 1; t += 2) vv = vv + pow(cosht, 2 * l + m - s - 2 * t) * pow(sinht, 2 * t + s - m) / (fact(l + m - t) * fact(l - s - t) * fact(t) * fact(t + s - m)); } return vv * sqrt(fact(l + m) * fact(l - m) * fact(l + s) * fact(l - s)); } double misc::fact(int N) { if (N < 0) cout << "error input for factorial." << endl; double f; if (N == 0) f = 1; else f = N * fact(N - 1); return f; } int misc::num_of_str(char *c) { int NN = 0, N1 = 0; std::istringstream iss; iss.str(c); char c1[1000]; while (!iss.eof()) { iss >> c1; if (int(c1[0]) == 45 || int(c1[0]) == 46 || (int(c1[0]) > 47 && int(c1[0]) < 58)) NN++; N1++; } char *c2 = c; while (*(c2 + 1)) c2++; if (int(*c2) == 32) { NN--; N1--; } // cout<<"found "< &f0, std::vector &f1, std::vector &f_rhs, const int RK4) { const int N = f0.size(); const double F1o6 = 1.0 / 6, HLF = 0.5, TWO = 2; switch (RK4) { case 0: for (int i = 0; i < N; i++) f1[i] = f0[i] + HLF * dT * f_rhs[i]; break; case 1: for (int i = 0; i < N; i++) { f_rhs[i] = f_rhs[i] + TWO * f1[i]; f1[i] = f0[i] + HLF * dT * f1[i]; } break; case 2: for (int i = 0; i < N; i++) { f_rhs[i] = f_rhs[i] + TWO * f1[i]; f1[i] = f0[i] + dT * f1[i]; } break; case 3: for (int i = 0; i < N; i++) f1[i] = f0[i] + F1o6 * dT * (f1[i] + f_rhs[i]); break; default: cout << "misc::rungekutta4: something is wrong in RK4 counting!!" << endl; } } void misc::dividBlock(const int DIM, int *shape_here, double *bbox_here, const int pices, double *picef, int *shape_res, double *bbox_res, const int min_width) { if (pices < 1) { cerr << "error in dividBlock: pices = " << pices << endl; return; } if (pices == 1) { for (int i = 0; i < DIM; i++) { shape_res[i] = shape_here[i]; bbox_res[i] = bbox_here[i]; bbox_res[DIM + i] = bbox_here[DIM + i]; } return; } double dd = picef[0]; for (int i = 1; i < pices; i++) dd += picef[i]; if (feq(dd, 1, 1e-8)) { int leg = shape_here[0]; int legi = 0; for (int i = 1; i < DIM; i++) { if (leg < shape_here[i]) { leg = shape_here[i]; legi = i; } } int pic = 0; for (int ip = 0; ip < pices; ip++) { for (int i = 0; i < DIM; i++) { if (i == legi) { if (ip == pices - 1) shape_res[ip * DIM + i] = shape_here[i] - pic; else { shape_res[ip * DIM + i] = shape_here[i] * picef[ip]; pic += shape_res[ip * DIM + i]; } } else shape_res[ip * DIM + i] = shape_here[i]; } } for (int ip = 0; ip < pices; ip++) { for (int i = 0; i < DIM; i++) { #ifdef Vertex #ifdef Cell #error Both Cell and Vertex are defined #endif dd = (bbox_here[DIM + i] - bbox_here[i]) / (shape_here[i] - 1); #else #ifdef Cell dd = (bbox_here[DIM + i] - bbox_here[i]) / shape_here[i]; #else #error Not define Vertex nor Cell #endif #endif if (i == legi) { if (shape_res[ip * DIM + i] < min_width) { cerr << "dividBlock: resulted too small shape, shapeo = " << shape_here[i] << ", shape = " << shape_res[ip * DIM + i] << ", min_width = " << min_width << endl; MPI_Abort(MPI_COMM_WORLD, 1); } if (ip == 0) bbox_res[ip * 2 * DIM + i] = bbox_here[i]; #ifdef Vertex #ifdef Cell #error Both Cell and Vertex are defined #endif else bbox_res[ip * 2 * DIM + i] = bbox_res[(ip - 1) * 2 * DIM + DIM + i] - ghost_width * dd + dd; // because for ip-1 we have already considered ghost points #else #ifdef Cell else bbox_res[ip * 2 * DIM + i] = bbox_res[(ip - 1) * 2 * DIM + DIM + i] - ghost_width * dd; #else #error Not define Vertex nor Cell #endif #endif if (ip == pices - 1) bbox_res[ip * 2 * DIM + DIM + i] = bbox_here[DIM + i]; #ifdef Vertex #ifdef Cell #error Both Cell and Vertex are defined #endif else bbox_res[ip * 2 * DIM + DIM + i] = bbox_res[ip * 2 * DIM + i] + (shape_res[ip * DIM + i] - 1) * dd; #else #ifdef Cell else bbox_res[ip * 2 * DIM + DIM + i] = bbox_res[ip * 2 * DIM + i] + shape_res[ip * DIM + i] * dd; #else #error Not define Vertex nor Cell #endif #endif if (ip > 0) { shape_res[ip * DIM + i] += ghost_width; bbox_res[ip * 2 * DIM + i] -= ghost_width * dd; } if (ip < pices - 1) { shape_res[ip * DIM + i] += ghost_width; bbox_res[ip * 2 * DIM + DIM + i] += ghost_width * dd; } } else { bbox_res[ip * 2 * DIM + i] = bbox_here[i]; bbox_res[ip * 2 * DIM + DIM + i] = bbox_here[DIM + i]; } } } } else { cerr << "error in dividBlock: "; for (int i = 0; i < pices; i++) cerr << picef[i] << " "; cerr << endl; } #if 0 // for check int myrank; MPI_Comm_rank(MPI_COMM_WORLD,&myrank); if(myrank == 0) { cerr<<"original one"< &f0, std::vector &f1) { const int N = f0.size(); double tt; for (int i = 0; i < N; i++) { tt = f0[i]; f0[i] = f1[i]; f1[i] = tt; } } complex misc::complex_gamma(complex z) { const double p[9] = {0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7}; if (real(z) < 0.5) { return PI / (sin(PI * z) * complex_gamma(1.0 - z)); } z -= 1.0; complex x = p[0]; for (int i = 1; i < 9; i++) { x += p[i] / (z + complex(i, 0)); } complex t = z + (7 + 0.5); t = sqrt(2 * PI) * pow(t, z + 0.5) * exp(-t) * x; return t; } // also called Kummer function, // Confluent hypergeometric function 1F1 #if 1 complex misc::KummerComplex(const complex a, const complex b, complex x) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. const double tol = 1e-10; // Estimates the value by summing powers of the generalized hypergeometric // series: // // sum(n=0-->Inf)[(a)_n*x^n/{(b)_n*n!}] // // until the specified tolerance is acheived. complex term = x * a / b; complex f = 1.0 + term; int n = 1; complex an = a; complex bn = b; int nmin = 100000; while (n < nmin && (abs(term)) > tol) { n = n + 1; an = an + 1.0; bn = bn + 1.0; term = x * term * an / bn / double(n); f = f + term; } if ((abs(term)) > tol && n == nmin) cout << "misc::KummerComplex has n > " << nmin << " with error " << abs(term) << endl << "a = " << a << " b = " << b << " x = " << x << endl; return f; } // new code #else complex misc::KummerComplex(const complex a, const complex b, complex z) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. int precision = 15; int m, j, k; complex cr, chg; double cMax; complex g1, g2, g3; complex ba; complex cs1, cs2, cr1, cr2; double c1Max, c2Max; // Special cases if (b.imag() == 0 && b.real() <= 0 && b.real() == int(b.real())) // b==-n;n=1,2,3,.. { if (a.imag() == 0 && a.real() <= 0 && a.real() == int(a.real()) && abs(a) < abs(b)) // a==-m;m=1,2,.. { m = int(-a.real()); cr = 1; chg = 1; cMax = abs(cr); for (k = 1; k <= m; k++) { cr = cr * (k - 1.0 + a) / double(k) / (k - 1.0 + b) * z; chg = chg + cr; cMax = max(cMax, max(abs(cr), abs(chg))); } precision = 15 - int(log10(cMax / abs(chg))); } else if (a.imag() == 0 && a.real() <= 0 && a.real() == int(a.real()) && abs(a) == abs(b)) // a==b; { cout << "!!!Confluent hypergeometric function is indeterminate for input a = " << a << " b = " << b << " z = " << z << endl; chg = 0; } else { cout << "!!!Confluent hypergeometric function error for input a = " << a << " b = " << b << " z = " << z << endl; chg = 0; } } else if (a == 0.0 || z == 0.0) { chg = 1; } else if (a == -1.0) { chg = 1.0 - z / b; } else if (a == b) { chg = exp(z); } else if ((a - b) == 1.0) { chg = (1.0 + z / b) * exp(z); } else if (a == 1.0 && b == 2.0) { chg = (exp(z) - 1.0) / z; } // finite number of elements in a row else if (a.imag() == 0 && a.real() < 0 && a.real() == int(a.real())) { m = int(-a.real()); cr = 1; chg = 1; cMax = abs(cr); for (k = 1; k <= m; k++) { cr = cr * (k - 1.0 + a) / double(k) / (k - 1.0 + b) * z; chg = chg + cr; cMax = max(cMax, max(abs(cr), abs(chg))); } precision = 15 - int(log10(cMax / abs(chg))); } else if (abs(z) > 10 * abs(a) && abs(z) > 10 * abs(b)) // Abramowitz Stegun 13.5.1 { g1 = complex_gamma(a); g2 = complex_gamma(b); ba = b - a; g3 = complex_gamma(ba); cs1 = 1; cs2 = 1; cr1 = 1; cr2 = 1; c1Max = abs(cr1); c2Max = abs(cr2); for (j = 1; j <= 500; j++) { cr1 = -cr1 * (j - 1.0 + a) * (a - b + double(j)) / (z * double(j)); cr2 = cr2 * (j - 1.0 + b - a) * (double(j) - a) / (z * double(j)); cs1 = cs1 + cr1; cs2 = cs2 + cr2; c1Max = max(c1Max, max(abs(cr1), abs(cs1))); c2Max = max(c2Max, max(abs(cr2), abs(cs2))); if (abs(cr1) / abs(cs1) < 1e-15 && abs(cr2) / abs(cs2) < 1e-15) break; // break j if (j == 500) { cout << "Got to the " << j << " limit in the series of confluent hypergeometric function!" << endl; chg = 0; return chg; } } precision = 15 - int(log10(max(c1Max / abs(cs1), c2Max / abs(cs2)))); double x = z.real(); double y = z.imag(); double phi; complex cfac, chg1, chg2; int ns; if (x == 0.0 && y >= 0.0) phi = 0.5 * PI; else if (x == 0.0 && y <= 0.0) phi = -0.5 * PI; else phi = atan(y / x); if (phi > -0.5 * PI && phi < 1.5 * PI) ns = 1; if (phi > -1.5 * PI && phi <= -0.5 * PI) ns = -1; cfac = exp(PI * ns * (complex(0, 1)) * a); if (y == 0) cfac = cos(PI * a); chg1 = g2 / g3 * pow(z, -a) * cfac * cs1; chg2 = g2 / g1 * exp(z) * pow(z, a - b) * cs2; chg = chg1 + chg2; } else // General case { chg = 1; complex crg = 1; double cgMax = abs(crg); for (j = 1; j <= 500; j++) { crg = crg * (j - 1.0 + a) / (double(j) * (j - 1.0 + b)) * z; // Abramowitz Stegun 13.1.2 chg = chg + crg; cgMax = max(cgMax, max(abs(crg), abs(chg))); if (abs(crg) / abs(chg) < 1e-15) break; // break j if (j == 500) { cout << "Got to the " << j << " limit in the series of confluent hypergeometric function!" << endl; chg = 0; return chg; } } precision = 15 - int(log10(cgMax / abs(chg))); } if (precision <= 0) { precision = 0; chg = 0; } if (precision < 10) cout << "!!! Warning!!! Only about " << precision << " first digits are correct!!!" << endl; return chg; } #endif // Bessel function of the first kind: J_a #if 0 // // sum(m=0-->Inf)(-1)^m/m!/Gamma(m+a+1) (x/2)^{2 m+a} // complex misc::First_Bessel(const complex a,complex x) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. const double tol = 1e-10; x = x/2.0; complex term,term1=pow(x,a),term2=1.0/complex_gamma(a+1.0); complex f = term1*term2; int m = 0; const int mmax = 50; term = f; while(m < mmax && (abs(term)) > tol) { m++; term1 = x*x*term1; term2 = -term2/double(m*m); term = term1*term2; f = f + term; } if((abs(term)) > tol && m == mmax) cout<<"misc::First_Bessel has m > "< " << jmax << ", error = " << abs(sum2 - sum) << endl; return sum2; } complex misc::Simpson_Int(const double xmin, const double xmax, complex fun(double x)) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. const double tol = 1e-8; int N = 1000; double dx = (xmax - xmin) / (N - 1); complex sum = 0, sum2 = 0; sum2 = 17.0 * fun(xmin) + 59.0 * fun(xmin + dx) + 43.0 * fun(xmin + 2 * dx) + 49.0 * fun(xmin + 3 * dx); for (int i = 4; i < N - 3; i++) { sum2 += 48.0 * fun(xmin + i * dx); } sum2 = sum2 + 17.0 * fun(xmax) + 59.0 * fun(xmax - dx) + 43.0 * fun(xmax - 2 * dx) + 49.0 * fun(xmax - 3 * dx); sum2 = sum2 * dx / 48.0; int j = 1; const int jmax = 50; while (j < jmax && abs(sum2 - sum) > tol) { j++; N = N * 2; dx = (xmax - xmin) / (N - 1); sum = sum2; sum2 = 17.0 * fun(xmin) + 59.0 * fun(xmin + dx) + 43.0 * fun(xmin + 2 * dx) + 49.0 * fun(xmin + 3 * dx); for (int i = 4; i < N - 3; i++) { sum2 += 48.0 * fun(xmin + i * dx); } sum2 = sum2 + 17.0 * fun(xmax) + 59.0 * fun(xmax - dx) + 43.0 * fun(xmax - 2 * dx) + 49.0 * fun(xmax - 3 * dx); sum2 = sum2 * dx / 48.0; // cout<<"j = "< " << jmax << ", error = " << abs(sum2 - sum) << endl; return sum2; } complex misc::Simpson3o8_Int(const double xmin, const double xmax, complex fun(double x)) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. const double tol = 1e-8; int m = 300, N; N = 3 * m + 2; double dx = (xmax - xmin) / (N - 1); complex sum = 0, sum2; sum2 = fun(xmin) + fun(xmax); for (int i = 0; i < m; i++) { sum2 += 3.0 * (fun(xmin + (3 * i + 1) * dx) + fun(xmin + (3 * i + 2) * dx)) + 2.0 * fun(xmin + (3 * i + 3) * dx); // cout< tol) { j++; m = m * 2; N = 3 * m + 2; dx = (xmax - xmin) / (N - 1); sum = sum2; sum2 = fun(xmin) + fun(xmax); for (int i = 0; i < m; i++) { sum2 += 3.0 * (fun(xmin + (3 * i + 1) * dx) + fun(xmin + (3 * i + 2) * dx)) + 2.0 * fun(xmin + (3 * i + 3) * dx); } sum2 = sum2 * dx * 3.0 / 8.0; // cout<<"j = "< " << jmax << ", error = " << abs(sum2 - sum) << endl; return sum2; } #if 0 complex misc::Gauss_Int(const double xmin,const double xmax,complex fun(double x)) { // Default tolerance is tol = 1e-10. Feel free to change this as needed. const double tol = 1e-8; int N=int(xmax-xmin)*10; if(N<1000) N = 1000; double *arcostheta,*wtcostheta; // weight function cover all of [xmin,xmax] arcostheta = new double[N]; wtcostheta = new double[N]; gaulegf(xmin,xmax,arcostheta,wtcostheta,N); complex sum=0,sum2=0; for(int i =0;i tol) { j++; N = N*2; arcostheta = new double[N]; wtcostheta = new double[N]; gaulegf(xmin,xmax,arcostheta,wtcostheta,N); sum=sum2; sum2=0; for(int i =0;i "< " << jmax << ", error = " << abs(sum2 - sum) << endl; return sum2; } #endif complex misc::gaulegf(double x1, double x2, int n, complex fun(double x)) { int i, j, m; double eps = 1.2E-16; double p1, p2, p3, pp, xl, xm, z, z1; double w; m = (n + 1) / 2; xm = 0.5 * (x2 + x1); xl = 0.5 * (x2 - x1); complex sum = 0; for (i = 0; i < m; i++) { z = cos(PI * ((double)i + 0.75) / ((double)n + 0.5)); do { p1 = 1.0; p2 = 0.0; for (j = 0; j < n; j++) { p3 = p2; p2 = p1; p1 = ((2 * (double)j + 1) * z * p2 - (double)j * p3) / ((double)j + 1); } pp = n * (z * p1 - p2) / (z * z - 1.0); z1 = z; z = z1 - p1 / pp; // cout<<"here"< eps); // cout<<"there"<> 1; j = 0; for (i = 0; i < n - 1; i++) { if (i < j) { tx = x[i]; ty = y[i]; x[i] = x[j]; y[i] = y[j]; x[j] = tx; y[j] = ty; } k = i2; while (k <= j) { j -= k; k >>= 1; } j += k; } /* Compute the FFT */ c1 = -1.0; c2 = 0.0; l2 = 1; for (l = 0; l < m; l++) { l1 = l2; l2 <<= 1; u1 = 1.0; u2 = 0.0; for (j = 0; j < l1; j++) { for (i = j; i < n; i += l2) { i1 = i + l1; t1 = u1 * x[i1] - u2 * y[i1]; t2 = u1 * y[i1] + u2 * x[i1]; x[i1] = x[i] - t1; y[i1] = y[i] - t2; x[i] += t1; y[i] += t2; } z = u1 * c1 - u2 * c2; u2 = u1 * c2 + u2 * c1; u1 = z; } c2 = sqrt((1.0 - c1) / 2.0); if (dir == 1) c2 = -c2; c1 = sqrt((1.0 + c1) / 2.0); } /* Scaling for forward transform */ if (dir == 1) { for (i = 0; i < n; i++) { x[i] /= n; y[i] /= n; } } } // assume a[0] a[1]......a[NN/2-1] a[NN/2] ...... a[NN-1] // 0 df (NN/2-1)*df combine of \pm NN/2*df -df // 0 1 2 3 4 5 // ^ ^ ^ o ^ ^ // 0 1 2 3 // ^ ^ o ^ void misc::Low_Pass_Filt(const int NN, double *a) { // we use 2/3 law, NN/2 * 2/3 = NN/3 for (int i = 0; i < NN / 3; i++) { a[NN / 2 + i] = 0; a[NN / 2 - i] = 0; } } void misc::polyinterp(double t, double &rr, double *ti, double *ri, const int ORD) { // (x -x_1)...(x -x_i-1)(x -x_i+1)...(x -x_N) // ------------------------------------------------f_i // (x_i-x_1)...(x_i-x_i-1)(x_i-x_i+1)...(x_i-x_N) rr = 0; for (int i = 0; i < ORD; i++) { double ss = 1, xx = 1; for (int j = 0; j < ORD; j++) { if (j != i) { ss *= t - ti[j]; xx *= ti[i] - ti[j]; } } rr += ss / xx * ri[i]; } #if 0 if(!isfinite(rr)) { cout.setf(ios::scientific); cout<<"misc::polyinterp: error at t = "< Nin } int misc::MYpow2(int i) { if (i == 0) return 1; else if (i > 0) return 2 * MYpow2(i - 1); else return MYpow2(i + 1) / 2; }