/* PIP - Platform Independent Primitives Math Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "pimath.h" const char Solver::methods_desc[] = "b{Methods:}\ \n -1 - Global settings\ \n 01 - Eyler 1\ \n 02 - Eyler 2\ \n 14 - Runge-Kutta 4\ \n 23 - Adams-Bashfort-Moulton 3\ \n 24 - Adams-Bashfort-Moulton 4\ \n 32 - Polynomial Approximation 2\ \n 33 - Polynomial Approximation 3\ \n 34 - Polynomial Approximation 4\ \n 35 - Polynomial Approximation 5"; Solver::Method Solver::method_global = Solver::Eyler_2; void Solver::solve(double u, double h) { switch (method) { case Global: switch (method_global) { case Eyler_1: solveEyler1(u, h); break; case Eyler_2: solveEyler2(u, h); break; case RungeKutta_4: solveRK4(u, h); break; case AdamsBashfortMoulton_2: solveABM2(u, h); break; case AdamsBashfortMoulton_3: solveABM3(u, h); break; case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; case PolynomialApproximation_2: solvePA2(u, h); break; case PolynomialApproximation_3: solvePA3(u, h); break; case PolynomialApproximation_4: solvePA4(u, h); break; case PolynomialApproximation_5: solvePA5(u, h); break; } break; case Eyler_1: solveEyler1(u, h); break; case Eyler_2: solveEyler2(u, h); break; case RungeKutta_4: solveRK4(u, h); break; case AdamsBashfortMoulton_2: solveABM2(u, h); break; case AdamsBashfortMoulton_3: solveABM3(u, h); break; case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; case PolynomialApproximation_2: solvePA2(u, h); break; case PolynomialApproximation_3: solvePA3(u, h); break; case PolynomialApproximation_4: solvePA4(u, h); break; case PolynomialApproximation_5: solvePA5(u, h); break; } step++; } void Solver::fromTF(const TransferFunction & TF) { if (TF.vector_An.size() >= TF.vector_Bm.size()) size = TF.vector_An.size()-1; else { cout << "Solver error: {A} should be greater than {B}" << endl; return; } if (size == 0) return; step = 0; times.fill(0.); A.resize(size, size); d.resize(size + 1); d.fill(0.); a1.resize(size + 1); a1.fill(0.); b1.resize(size + 1); b1.fill(0.); X.resize(size); X.fill(0.); F.resize(5); for (uint i = 0; i < 5; ++i) F[i].resize(size), F[i].fill(0.); k1.resize(size); k1.fill(0.); k2.resize(size); k2.fill(0.); k3.resize(size); k3.fill(0.); k4.resize(size); k4.fill(0.); xx.resize(size); xx.fill(0.); XX.resize(size); XX.fill(0.); for (uint i = 0; i < size + 1; ++i) a1[size - i] = TF.vector_An[i]; for (uint i = 0; i < TF.vector_Bm.size(); ++i) b1[size - i] = TF.vector_Bm[i]; double a0 = a1[0]; a1 /= a0; b1 /= a0; d[0] = b1[0]; // Рассчитываем вектор d for (uint i = 1; i < size + 1; ++i) { sum = 0.; for (uint m = 0; m < i; ++m) sum += a1[i - m] * d[m]; d[i] = b1[i] - sum; } for (uint i = 0; i < size - 1; ++i) // Заполняем матрицу А for (uint j = 0; j < size; ++j) A[j][i] = (j == i + 1); for (uint i = 0; i < size; ++i) A[i][size - 1] = -a1[size - i]; for (uint i = 0; i < size; ++i) d[i] = d[i + 1]; } void Solver::solveEyler1(double u, double h) { /*for (uint i = 0; i < size; ++i) { * sum = 0.; * for (uint j = 0; j < size; ++j) * sum += A[j][i] * X[j]; * xx[i] = sum + d[i] * u; }*/ F[0] = A * X + d * u; X += F[0] * h; moveF(); } void Solver::solveEyler2(double u, double h) { F[0] = A * X + d * u; X += (F[0] + F[1]) * h / 2.; moveF(); } void Solver::solveRK4(double u, double h) { td = X[0] - F[0][0]; k1 = A * X + d * u; xx = k1 * h / 2.; XX = X + xx; k2 = A * (XX + k1 * h / 2.) + d * (u + td/3.); xx = k2 * h / 2.; XX += xx; k3 = A * (XX + k2 * h / 2.) + d * (u + td*2./3.); xx = k3 * h; XX += xx; k4 = A * (XX + k3 * h) + d * (u + td); //cout << k1 << k2 << k3 << k4 << endl; X += (k1 + k2 * 2. + k3 * 2. + k4) * h / 6.; F[0] = X; } void Solver::solveABM2(double u, double h) { F[0] = A * X + d * u; XX = X + (F[0] * 3. - F[1]) * (h / 2.); F[1] = A * XX + d * u; X += (F[1] + F[0]) * (h / 2.); moveF(); } void Solver::solveABM3(double u, double h) { F[0] = A * X + d * u; XX = X + (F[0] * 23. - F[1] * 16. + F[2] * 5.) * (h / 12.); F[2] = A * XX + d * u; X += (F[2] * 5. + F[0] * 8. - F[1]) * (h / 12.); moveF(); } void Solver::solveABM4(double u, double h) { F[0] = A * X + d * u; XX = X + (F[0] * 55. - F[1] * 59. + F[2] * 37. - F[3] * 9.) * (h / 24.); F[3] = A * XX + d * u; X += (F[3] * 9. + F[0] * 19. - F[1] * 5. + F[2]) * (h / 24.); moveF(); } void Solver::solvePA(double u, double h, uint deg) { F[0] = A * X + d * u; M.resize(deg, deg); Y.resize(deg); pY.resize(deg); for (uint k = 0; k < size; ++k) { for (uint i = 0; i < deg; ++i) { td = 1.; ct = times[i]; for (uint j = 0; j < deg; ++j) { M[j][i] = td; td *= ct; } } for (uint i = 0; i < deg; ++i) Y[i] = F[i][k]; /// find polynom //if (step == 1) cout << M << endl << Y << endl; M.invert(&ok, &Y); //if (step == 1) cout << Y << endl; if (!ok) { solveEyler2(u, h); break; } /// calc last piece x0 = 0.; td = 1.; t = times[0]; for (uint i = 0; i < deg; ++i) { x0 += Y[i] * td / (i + 1.); td *= t; } x0 *= t; x1 = 0.; td = 1.; t = times[1]; for (uint i = 0; i < deg; ++i) { x1 += Y[i] * td / (i + 1.); td *= t; } x1 *= t; lp = x0 - x1; if (deg > 2) { /// calc prev piece x0 = 0.; td = 1.; dh = times[1] - times[2]; if (dh != 0. && step > 1) { t = times[2]; for (uint i = 0; i < deg; ++i) { x0 += Y[i] * td / (i + 1.); td *= t; } x0 *= t; ct = x1 - x0; /// calc correction ct -= pY[k]; } /// calc final X[k] += lp - ct; pY[k] = lp; } else { X[k] += lp; pY[k] = lp; } } moveF(); } PIFFT::PIFFT() { prepared = false; } PIVector * PIFFT::calcFFT(const PIVector & val) { // for (uint i=0; i *PIFFT::calcFFTinverse(const PIVector &val) { result.clear(); if (val.size_s() < 4) return &result; fftc1dinv(val, val.size()); return &result; } PIVector *PIFFT::calcHilbert(const PIVector &val) { result.clear(); if (val.size_s() < 4) return &result; fftc1r(val, val.size()); for (uint i=0; i* PIFFT::calcFFT(const PIVector & val) { result.clear(); if (val.size_s() < 4) return &result; fftc1r(val, val.size()); return &result; } PIVector PIFFT::getAmplitude() { PIVector a; double tmp; for (uint i=0; i &a, uint n) { createPlan(n); uint i; PIVector buf; buf.resize(2*n); for(i=0; iptr.p_complex[i].x; buf[2*i+1] = a.at(i).imag();//a->ptr.p_complex[i].y; } ftbaseexecuteplan(&buf, 0, n, &curplan); result.resize(n); for(i=0; i & a, uint n) { uint i; if( n%2==0 ) { PIVector buf; uint n2 = n/2; //buf.resize(n); buf = a; createPlan(n2); //cout << "fftr " << n2 << endl; ftbaseexecuteplan(&buf, 0, n2, &curplan); result.resize(n); uint idx; complexd hn, hmnc, v; for(i=0; i<=n2; i++) { idx = 2*(i%n2); hn = complexd(buf[idx+0], buf[idx+1]); idx = 2*((n2-i)%n2); hmnc = complexd(buf[idx+0], -buf[idx+1]); v = complexd(sin(M_PI*i/n2), cos(M_PI*i/n2)); result[i] = ((hn + hmnc) - (v * (hn - hmnc))); result[i] *= 0.5; } for(i=n2+1; i cbuf; cbuf.resize(n); for(i=0; i &a, uint n) { PIVector cbuf; cbuf.resize(n); uint i; for(i=0; i(*planarraysize) ) { curplan.plan.resize(8*(*planarraysize)); *planarraysize = 8*(*planarraysize); } entryoffset = *plansize; esize = ftbase_ftbaseplanentrysize; *plansize = *plansize+esize; if( n==1 ) { curplan.plan[entryoffset+0] = esize; curplan.plan[entryoffset+1] = -1; curplan.plan[entryoffset+2] = -1; curplan.plan[entryoffset+3] = ftbase_fftemptyplan; curplan.plan[entryoffset+4] = -1; curplan.plan[entryoffset+5] = -1; curplan.plan[entryoffset+6] = -1; curplan.plan[entryoffset+7] = -1; return; } ftbasefactorize(n, &n1, &n2); if( n1!=1 ) { *tmpmemsize = piMax(*tmpmemsize, 2*n1*n2); curplan.plan[entryoffset+0] = esize; curplan.plan[entryoffset+1] = n1; curplan.plan[entryoffset+2] = n2; if( tasktype==ftbase_ftbasecffttask ) curplan.plan[entryoffset+3] = ftbase_fftcooleytukeyplan; else curplan.plan[entryoffset+3] = ftbase_fftrealcooleytukeyplan; curplan.plan[entryoffset+4] = 0; curplan.plan[entryoffset+5] = *plansize; debugi++; ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); curplan.plan[entryoffset+6] = *plansize; ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); curplan.plan[entryoffset+7] = -1; return; } else { if (n>=2 && n<=5) { curplan.plan[entryoffset+0] = esize; curplan.plan[entryoffset+1] = n1; curplan.plan[entryoffset+2] = n2; curplan.plan[entryoffset+3] = ftbase_fftcodeletplan; curplan.plan[entryoffset+4] = 0; curplan.plan[entryoffset+5] = -1; curplan.plan[entryoffset+6] = -1; curplan.plan[entryoffset+7] = *precomputedsize; if( n==3 ) *precomputedsize = *precomputedsize+2; if( n==5 ) *precomputedsize = *precomputedsize+5; return; } else { k = 2*n2-1; m = ftbasefindsmooth(k); *tmpmemsize = piMax(*tmpmemsize, 2*m); curplan.plan[entryoffset+0] = esize; curplan.plan[entryoffset+1] = n2; curplan.plan[entryoffset+2] = -1; curplan.plan[entryoffset+3] = ftbase_fftbluesteinplan; curplan.plan[entryoffset+4] = m; curplan.plan[entryoffset+5] = *plansize; stackptr = stackptr+2*2*m; *stackmemsize = piMax(*stackmemsize, stackptr); ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr); stackptr = stackptr-2*2*m; curplan.plan[entryoffset+6] = -1; curplan.plan[entryoffset+7] = *precomputedsize; *precomputedsize = *precomputedsize+2*m+2*n; return; } } } /************************************************************************* Recurrent subroutine for precomputing FFT plans -- ALGLIB -- Copyright 01.05.2009 by Bochkanov Sergey *************************************************************************/ void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan, int entryoffset, ae_int_t stackptr) { int n1, n2, n, m, offs; double v, bx, by; int ftbase_fftcooleytukeyplan = 0; int ftbase_fftbluesteinplan = 1; int ftbase_fftcodeletplan = 2; int ftbase_fhtcooleytukeyplan = 3; int ftbase_fhtcodeletplan = 4; int ftbase_fftrealcooleytukeyplan = 5; if( (curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan||curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan)||curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) { ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+6], stackptr); return; } if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan||curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; n = n1*n2; if( n==3 ) { offs = curplan.plan[entryoffset+7]; curplan.precomputed[offs+0] = cos(2*M_PI/3)-1; curplan.precomputed[offs+1] = sin(2*M_PI/3); return; } if( n==5 ) { offs = curplan.plan[entryoffset+7]; v = 2*M_PI/5; curplan.precomputed[offs+0] = (cos(v)+cos(2*v))/2-1; curplan.precomputed[offs+1] = (cos(v)-cos(2*v))/2; curplan.precomputed[offs+2] = -sin(v); curplan.precomputed[offs+3] = -(sin(v)+sin(2*v)); curplan.precomputed[offs+4] = sin(v)-sin(2*v); return; } } if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) { ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); n = curplan.plan[entryoffset+1]; m = curplan.plan[entryoffset+4]; offs = curplan.plan[entryoffset+7]; for(int i=0; i<=2*m-1; i++) curplan.precomputed[offs+i] = 0; for(int i=0; i0 ) { curplan.precomputed[offs+2*(m-i)+0] = bx; curplan.precomputed[offs+2*(m-i)+1] = by; } } ftbaseexecuteplanrec(&curplan.precomputed, offs, plan, curplan.plan[entryoffset+5], stackptr); return; } } void PIFFT::ftbasefactorize(int n, int* n1, int* n2) { *n1 = *n2 = 0; int ftbase_ftbasecodeletrecommended = 5; if( (*n1)*(*n2)!=n ) { for(int j=ftbase_ftbasecodeletrecommended; j>=2; j--) { if( n%j==0 ) { *n1 = j; *n2 = n/j; break; } } } if( (*n1)*(*n2)!=n ) { for(int j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) { if( n%j==0 ) { *n1 = j; *n2 = n/j; break; } } } if( (*n1)*(*n2)!=n ) { *n1 = 1; *n2 = n; } if( (*n2)==1 && (*n1)!=1 ) { *n2 = *n1; *n1 = 1; } } /************************************************************************* Is number smooth? -- ALGLIB -- Copyright 01.05.2009 by Bochkanov Sergey *************************************************************************/ void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int* best) { if( seed>=n ) { *best = piMin(*best, seed); return; } if( leastfactor<=2 ) ftbase_ftbasefindsmoothrec(n, seed*2, 2, best); if( leastfactor<=3 ) ftbase_ftbasefindsmoothrec(n, seed*3, 3, best); if( leastfactor<=5 ) ftbase_ftbasefindsmoothrec(n, seed*5, 5, best); } int PIFFT::ftbasefindsmooth(int n) { int best, result; best = 2; while(best* a, int m, int n, int astart, PIVector* buf) { ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n); for (int i=0; i<2*m*n; i++) (*a)[astart+i] = (*buf)[i]; } void PIFFT::ftbase_fftirltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { int idx1, idx2; int m1, n1; if( m==0||n==0 ) return; if( piMax(m, n)<=8 ) { for(int i=0; i<=m-1; i++) { idx1 = bstart+i; idx2 = astart+i*astride; for(int j=0; j<=n-1; j++) { (*b)[idx1] = a->at(idx2); idx1 = idx1+bstride; idx2 = idx2+1; } } return; } if( n>m ) { n1 = n/2; if( n-n1>=8&&n1%8!=0 ) n1 = n1+(8-n1%8); ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1); ftbase_fftirltrec(a, astart+n1, astride, b, bstart+n1*bstride, bstride, m, n-n1); } else { m1 = m/2; if( m-m1>=8&&m1%8!=0 ) m1 = m1+(8-m1%8); ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n); ftbase_fftirltrec(a, astart+m1*astride, astride, b, bstart+m1, bstride, m-m1, n); } } void PIFFT::ftbase_internalcomplexlintranspose(PIVector* a, int m, int n, int astart, PIVector* buf) { ftbase_ffticltrec(a, astart, n, buf, 0, m, m, n); for (int i=0; i<2*m*n; i++) (*a)[astart+i] = (*buf)[i]; } void PIFFT::ftbase_ffticltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { int idx1, idx2, m2, m1, n1; if( m==0||n==0 ) return; if( piMax(m, n)<=8 ) { m2 = 2*bstride; for(int i=0; i<=m-1; i++) { idx1 = bstart+2*i; idx2 = astart+2*i*astride; for(int j=0; j<=n-1; j++) { (*b)[idx1+0] = a->at(idx2+0); (*b)[idx1+1] = a->at(idx2+1); idx1 = idx1+m2; idx2 = idx2+2; } } return; } if( n>m ) { n1 = n/2; if( n-n1>=8&&n1%8!=0 ) n1 = n1+(8-n1%8); ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1); ftbase_ffticltrec(a, astart+2*n1, astride, b, bstart+2*n1*bstride, bstride, m, n-n1); } else { m1 = m/2; if( m-m1>=8&&m1%8!=0 ) m1 = m1+(8-m1%8); ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n); ftbase_ffticltrec(a, astart+2*m1*astride, astride, b, bstart+2*m1, bstride, m-m1, n); } } void PIFFT::ftbaseexecuteplan(PIVector* a, int aoffset, int n, ftplan* plan) { ae_int_t stackptr; stackptr = 0; ftbaseexecuteplanrec(a, aoffset, plan, 0, stackptr); } /************************************************************************* Recurrent subroutine for the FTBaseExecutePlan Parameters: A FFT'ed array AOffset offset of the FFT'ed part (distance is measured in doubles) -- ALGLIB -- Copyright 01.05.2009 by Bochkanov Sergey *************************************************************************/ void PIFFT::ftbaseexecuteplanrec(PIVector* a, int aoffset, ftplan* plan, int entryoffset, ae_int_t stackptr) { int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp; double hk, hnk, x, y, bx, by, v0, v1, v2, v3; double a0x, a0y, a1x, a1y, a2x, a2y, a3x, a3y; double t1x, t1y, t2x, t2y, t3x, t3y, t4x, t4y, t5x, t5y; double m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y; double s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y; double c1, c2, c3, c4, c5; int ftbase_fftcooleytukeyplan = 0; int ftbase_fftbluesteinplan = 1; int ftbase_fftcodeletplan = 2; int ftbase_fhtcooleytukeyplan = 3; int ftbase_fhtcodeletplan = 4; int ftbase_fftrealcooleytukeyplan = 5; int ftbase_fftemptyplan = 6; PIVector & tmpb(curplan.tmpbuf); if( curplan.plan[entryoffset+3]==ftbase_fftemptyplan ) return; if( curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n2-1; i++) ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); ftbase_ffttwcalc(a, aoffset, n1, n2); ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n1-1; i++) ftbaseexecuteplanrec(a, aoffset+i*n2*2, plan, curplan.plan[entryoffset+6], stackptr); ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); return; } if( curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n1/2-1; i++) { offs = aoffset+2*i*n2*2; for(int k=0; k<=n2-1; k++) (*a)[offs+2*k+1] = (*a)[offs+2*n2+2*k+0]; ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset+6], stackptr); tmpb[0] = (*a)[offs+0]; tmpb[1] = 0; tmpb[2*n2+0] = (*a)[offs+1]; tmpb[2*n2+1] = 0; for(int k=1; k<=n2-1; k++) { offs1 = 2*k; offs2 = 2*n2+2*k; hk = (*a)[offs+2*k+0]; hnk = (*a)[offs+2*(n2-k)+0]; tmpb[offs1+0] = 0.5*(hk+hnk); tmpb[offs2+1] = -0.5*(hk-hnk); hk = (*a)[offs+2*k+1]; hnk = (*a)[offs+2*(n2-k)+1]; tmpb[offs2+0] = 0.5*(hk+hnk); tmpb[offs1+1] = 0.5*(hk-hnk); } for (int i=0; i<2*n2*2; i++) (*a)[offs+i] = tmpb[i]; } if( n1%2!=0 ) ftbaseexecuteplanrec(a, aoffset+(n1-1)*n2*2, plan, curplan.plan[entryoffset+6], stackptr); ftbase_ffttwcalc(a, aoffset, n2, n1); ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n2-1; i++) ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); return; } if( curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; n = n1*n2; ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n2-1; i++) ftbaseexecuteplanrec(a, aoffset+i*n1, plan, curplan.plan[entryoffset+5], stackptr); for(int i=0; i<=n2-1; i++) { for(int j=0; j<=n1-1; j++) { offsa = aoffset+i*n1; hk = (*a)[offsa+j]; hnk = (*a)[offsa+(n1-j)%n1]; offs = 2*(i*n1+j); tmpb[offs+0] = -0.5*(hnk-hk); tmpb[offs+1] = 0.5*(hk+hnk); } } ftbase_ffttwcalc(&(curplan.tmpbuf), 0, n1, n2); for(int j=0; j<=n1-1; j++) (*a)[aoffset+j] = tmpb[2*j+0]+tmpb[2*j+1]; if( n2%2==0 ) { offs = 2*(n2/2)*n1; offsa = aoffset+n2/2*n1; for(int j=0; j<=n1-1; j++) (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs+2*j+1]; } for(int i=1; i<=(n2+1)/2-1; i++) { offs = 2*i*n1; offs2 = 2*(n2-i)*n1; offsa = aoffset+i*n1; for(int j=0; j<=n1-1; j++) (*a)[offsa+j] = tmpb[offs+2*j+1]+tmpb[offs2+2*j+0]; offsa = aoffset+(n2-i)*n1; for(int j=0; j<=n1-1; j++) (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs2+2*j+1]; } ftbase_internalreallintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); for(int i=0; i<=n1-1; i++) ftbaseexecuteplanrec(a, aoffset+i*n2, plan, curplan.plan[entryoffset+6], stackptr); ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); return; } if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; n = n1*n2; if( n==2 ) { a0x = (*a)[aoffset+0]; a0y = (*a)[aoffset+1]; a1x = (*a)[aoffset+2]; a1y = (*a)[aoffset+3]; v0 = a0x+a1x; v1 = a0y+a1y; v2 = a0x-a1x; v3 = a0y-a1y; (*a)[aoffset+0] = v0; (*a)[aoffset+1] = v1; (*a)[aoffset+2] = v2; (*a)[aoffset+3] = v3; return; } if( n==3 ) { offs = curplan.plan[entryoffset+7]; c1 = curplan.precomputed[offs+0]; c2 = curplan.precomputed[offs+1]; a0x = (*a)[aoffset+0]; a0y = (*a)[aoffset+1]; a1x = (*a)[aoffset+2]; a1y = (*a)[aoffset+3]; a2x = (*a)[aoffset+4]; a2y = (*a)[aoffset+5]; t1x = a1x+a2x; t1y = a1y+a2y; a0x = a0x+t1x; a0y = a0y+t1y; m1x = c1*t1x; m1y = c1*t1y; m2x = c2*(a1y-a2y); m2y = c2*(a2x-a1x); s1x = a0x+m1x; s1y = a0y+m1y; a1x = s1x+m2x; a1y = s1y+m2y; a2x = s1x-m2x; a2y = s1y-m2y; (*a)[aoffset+0] = a0x; (*a)[aoffset+1] = a0y; (*a)[aoffset+2] = a1x; (*a)[aoffset+3] = a1y; (*a)[aoffset+4] = a2x; (*a)[aoffset+5] = a2y; return; } if( n==4 ) { a0x = (*a)[aoffset+0]; a0y = (*a)[aoffset+1]; a1x = (*a)[aoffset+2]; a1y = (*a)[aoffset+3]; a2x = (*a)[aoffset+4]; a2y = (*a)[aoffset+5]; a3x = (*a)[aoffset+6]; a3y = (*a)[aoffset+7]; t1x = a0x+a2x; t1y = a0y+a2y; t2x = a1x+a3x; t2y = a1y+a3y; m2x = a0x-a2x; m2y = a0y-a2y; m3x = a1y-a3y; m3y = a3x-a1x; (*a)[aoffset+0] = t1x+t2x; (*a)[aoffset+1] = t1y+t2y; (*a)[aoffset+4] = t1x-t2x; (*a)[aoffset+5] = t1y-t2y; (*a)[aoffset+2] = m2x+m3x; (*a)[aoffset+3] = m2y+m3y; (*a)[aoffset+6] = m2x-m3x; (*a)[aoffset+7] = m2y-m3y; return; } if( n==5 ) { offs = curplan.plan[entryoffset+7]; c1 = curplan.precomputed[offs+0]; c2 = curplan.precomputed[offs+1]; c3 = curplan.precomputed[offs+2]; c4 = curplan.precomputed[offs+3]; c5 = curplan.precomputed[offs+4]; t1x = (*a)[aoffset+2]+(*a)[aoffset+8]; t1y = (*a)[aoffset+3]+(*a)[aoffset+9]; t2x = (*a)[aoffset+4]+(*a)[aoffset+6]; t2y = (*a)[aoffset+5]+(*a)[aoffset+7]; t3x = (*a)[aoffset+2]-(*a)[aoffset+8]; t3y = (*a)[aoffset+3]-(*a)[aoffset+9]; t4x = (*a)[aoffset+6]-(*a)[aoffset+4]; t4y = (*a)[aoffset+7]-(*a)[aoffset+5]; t5x = t1x+t2x; t5y = t1y+t2y; (*a)[aoffset+0] = (*a)[aoffset+0]+t5x; (*a)[aoffset+1] = (*a)[aoffset+1]+t5y; m1x = c1*t5x; m1y = c1*t5y; m2x = c2*(t1x-t2x); m2y = c2*(t1y-t2y); m3x = -c3*(t3y+t4y); m3y = c3*(t3x+t4x); m4x = -c4*t4y; m4y = c4*t4x; m5x = -c5*t3y; m5y = c5*t3x; s3x = m3x-m4x; s3y = m3y-m4y; s5x = m3x+m5x; s5y = m3y+m5y; s1x = (*a)[aoffset+0]+m1x; s1y = (*a)[aoffset+1]+m1y; s2x = s1x+m2x; s2y = s1y+m2y; s4x = s1x-m2x; s4y = s1y-m2y; (*a)[aoffset+2] = s2x+s3x; (*a)[aoffset+3] = s2y+s3y; (*a)[aoffset+4] = s4x+s5x; (*a)[aoffset+5] = s4y+s5y; (*a)[aoffset+6] = s4x-s5x; (*a)[aoffset+7] = s4y-s5y; (*a)[aoffset+8] = s2x-s3x; (*a)[aoffset+9] = s2y-s3y; return; } } if( curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) { n1 = curplan.plan[entryoffset+1]; n2 = curplan.plan[entryoffset+2]; n = n1*n2; if( n==2 ) { a0x = (*a)[aoffset+0]; a1x = (*a)[aoffset+1]; (*a)[aoffset+0] = a0x+a1x; (*a)[aoffset+1] = a0x-a1x; return; } if( n==3 ) { offs = curplan.plan[entryoffset+7]; c1 = curplan.precomputed[offs+0]; c2 = curplan.precomputed[offs+1]; a0x = (*a)[aoffset+0]; a1x = (*a)[aoffset+1]; a2x = (*a)[aoffset+2]; t1x = a1x+a2x; a0x = a0x+t1x; m1x = c1*t1x; m2y = c2*(a2x-a1x); s1x = a0x+m1x; (*a)[aoffset+0] = a0x; (*a)[aoffset+1] = s1x-m2y; (*a)[aoffset+2] = s1x+m2y; return; } if( n==4 ) { a0x = (*a)[aoffset+0]; a1x = (*a)[aoffset+1]; a2x = (*a)[aoffset+2]; a3x = (*a)[aoffset+3]; t1x = a0x+a2x; t2x = a1x+a3x; m2x = a0x-a2x; m3y = a3x-a1x; (*a)[aoffset+0] = t1x+t2x; (*a)[aoffset+1] = m2x-m3y; (*a)[aoffset+2] = t1x-t2x; (*a)[aoffset+3] = m2x+m3y; return; } if( n==5 ) { offs = curplan.plan[entryoffset+7]; c1 = curplan.precomputed[offs+0]; c2 = curplan.precomputed[offs+1]; c3 = curplan.precomputed[offs+2]; c4 = curplan.precomputed[offs+3]; c5 = curplan.precomputed[offs+4]; t1x = (*a)[aoffset+1]+(*a)[aoffset+4]; t2x = (*a)[aoffset+2]+(*a)[aoffset+3]; t3x = (*a)[aoffset+1]-(*a)[aoffset+4]; t4x = (*a)[aoffset+3]-(*a)[aoffset+2]; t5x = t1x+t2x; v0 = (*a)[aoffset+0]+t5x; (*a)[aoffset+0] = v0; m2x = c2*(t1x-t2x); m3y = c3*(t3x+t4x); s3y = m3y-c4*t4x; s5y = m3y+c5*t3x; s1x = v0+c1*t5x; s2x = s1x+m2x; s4x = s1x-m2x; (*a)[aoffset+1] = s2x-s3y; (*a)[aoffset+2] = s4x-s5y; (*a)[aoffset+3] = s4x+s5y; (*a)[aoffset+4] = s2x+s3y; return; } } if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) { n = curplan.plan[entryoffset+1]; m = curplan.plan[entryoffset+4]; offs = curplan.plan[entryoffset+7]; for(int i=stackptr+2*n; i<=stackptr+2*m-1; i++) curplan.stackbuf[i] = 0; offsp = offs+2*m; offsa = aoffset; offsb = stackptr; for(int i=0; i * a, int aoffset, int n1, int n2) { int n, idx, offs; double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v; int ftbase_ftbaseupdatetw = 4; n = n1*n2; v = -2*M_PI/n; twbasexm1 = -2*sqr(sin(0.5*v)); twbasey = sin(v); twrowxm1 = 0; twrowy = 0; for(int i=0, j = 0; i<=n2-1; i++) { twxm1 = 0; twy = 0; for(j=0; j<=n1-1; j++) { idx = i*n1+j; offs = aoffset+2*idx; x = (*a)[offs+0]; y = (*a)[offs+1]; tmpx = x*twxm1-y*twy; tmpy = x*twy+y*twxm1; (*a)[offs+0] = x+tmpx; (*a)[offs+1] = y+tmpy; if( j & val) { double v = 0., v1 = 0., v2 = 0., stddev = 0.; int i, n = val.size(); if (n < 2) return false; /* * Mean */ for (i = 0; i < n; i++) mean += val[i]; mean /= n; /* * Variance (using corrected two-pass algorithm) */ for (i = 0; i < n; i++) v1 += sqr(val[i] - mean); for (i = 0; i < n; i++) v2 += val[i] - mean; v2 = sqr(v2) / n; variance = (v1 - v2) / (n - 1); if(variance < 0) variance = 0.; stddev = sqrt(variance); /* * Skewness and kurtosis */ if (stddev != 0) { for (i = 0; i < n; i++) { v = (val[i] - mean) / stddev; v2 = sqr(v); skewness = skewness + v2 * v; kurtosis = kurtosis + sqr(v2); } skewness /= n; kurtosis = kurtosis / n - 3.; } return true; }