18.03.2013 - Bug fixes, add in/out speed diagnostic to PIProtocol, fixed PIConsole tab switch segfault, PIObject EVENT / EVENT_HANDLER mechanism update - new EVENT macros that use EVENT_HANDLER with raiseEvent implementation.
This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
This commit is contained in:
1134
pimath.cpp
Executable file → Normal file
1134
pimath.cpp
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Math
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
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
|
||||
@@ -19,160 +19,6 @@
|
||||
|
||||
#include "pimath.h"
|
||||
|
||||
/*
|
||||
* Fast Fourier Transformation
|
||||
* ====================================================
|
||||
* Coded by Miroslav Voinarovsky, 2002
|
||||
* This source is freeware.
|
||||
*/
|
||||
|
||||
// This array contains values from 0 to 255 with reverse bit order
|
||||
static uchar reverse256[]= {
|
||||
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
|
||||
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
||||
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
|
||||
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
||||
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
|
||||
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
||||
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
|
||||
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
||||
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
|
||||
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
||||
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
|
||||
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
||||
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
|
||||
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
||||
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
|
||||
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
||||
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
|
||||
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
||||
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
|
||||
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
||||
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
|
||||
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
||||
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
|
||||
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
||||
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
|
||||
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
||||
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
|
||||
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
||||
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
|
||||
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
||||
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
|
||||
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
|
||||
};
|
||||
|
||||
//This is array exp(-2*pi*j/2^n) for n= 1,...,32
|
||||
//exp(-2*pi*j/2^n) = complexd( cos(2*pi/2^n), -sin(2*pi/2^n) )
|
||||
static complexd W2n[32] = {
|
||||
complexd(-1.00000000000000000000000000000000, 0.00000000000000000000000000000000), // W2 calculator (copy/paste) : po, ps
|
||||
complexd( 0.00000000000000000000000000000000, -1.00000000000000000000000000000000), // W4: p/2=o, p/2=s
|
||||
complexd( 0.70710678118654752440084436210485, -0.70710678118654752440084436210485), // W8: p/4=o, p/4=s
|
||||
complexd( 0.92387953251128675612818318939679, -0.38268343236508977172845998403040), // p/8=o, p/8=s
|
||||
complexd( 0.98078528040323044912618223613424, -0.19509032201612826784828486847702), // p/16=
|
||||
complexd( 0.99518472667219688624483695310948, -9.80171403295606019941955638886e-2), // p/32=
|
||||
complexd( 0.99879545620517239271477160475910, -4.90676743274180142549549769426e-2), // p/64=
|
||||
complexd( 0.99969881869620422011576564966617, -2.45412285229122880317345294592e-2), // p/128=
|
||||
complexd( 0.99992470183914454092164649119638, -1.22715382857199260794082619510e-2), // p/256=
|
||||
complexd( 0.99998117528260114265699043772857, -6.13588464915447535964023459037e-3), // p/(2y9)=
|
||||
complexd( 0.99999529380957617151158012570012, -3.06795676296597627014536549091e-3), // p/(2y10)=
|
||||
complexd( 0.99999882345170190992902571017153, -1.53398018628476561230369715026e-3), // p/(2y11)=
|
||||
complexd( 0.99999970586288221916022821773877, -7.66990318742704526938568357948e-4), // p/(2y12)=
|
||||
complexd( 0.99999992646571785114473148070739, -3.83495187571395589072461681181e-4), // p/(2y13)=
|
||||
complexd( 0.99999998161642929380834691540291, -1.91747597310703307439909561989e-4), // p/(2y14)=
|
||||
complexd( 0.99999999540410731289097193313961, -9.58737990959773458705172109764e-5), // p/(2y15)=
|
||||
complexd( 0.99999999885102682756267330779455, -4.79368996030668845490039904946e-5), // p/(2y16)=
|
||||
complexd( 0.99999999971275670684941397221864, -2.39684498084182187291865771650e-5), // p/(2y17)=
|
||||
complexd( 0.99999999992818917670977509588385, -1.19842249050697064215215615969e-5), // p/(2y18)=
|
||||
complexd( 0.99999999998204729417728262414778, -5.99211245264242784287971180889e-6), // p/(2y19)=
|
||||
complexd( 0.99999999999551182354431058417300, -2.99605622633466075045481280835e-6), // p/(2y20)=
|
||||
complexd( 0.99999999999887795588607701655175, -1.49802811316901122885427884615e-6), // p/(2y21)=
|
||||
complexd( 0.99999999999971948897151921479472, -7.49014056584715721130498566730e-7), // p/(2y22)=
|
||||
complexd( 0.99999999999992987224287980123973, -3.74507028292384123903169179084e-7), // p/(2y23)=
|
||||
complexd( 0.99999999999998246806071995015625, -1.87253514146195344868824576593e-7), // p/(2y24)=
|
||||
complexd( 0.99999999999999561701517998752946, -9.36267570730980827990672866808e-8), // p/(2y25)=
|
||||
complexd( 0.99999999999999890425379499688176, -4.68133785365490926951155181385e-8), // p/(2y26)=
|
||||
complexd( 0.99999999999999972606344874922040, -2.34066892682745527595054934190e-8), // p/(2y27)=
|
||||
complexd( 0.99999999999999993151586218730510, -1.17033446341372771812462135032e-8), // p/(2y28)=
|
||||
complexd( 0.99999999999999998287896554682627, -5.85167231706863869080979010083e-9), // p/(2y29)=
|
||||
complexd( 0.99999999999999999571974138670657, -2.92583615853431935792823046906e-9), // p/(2y30)=
|
||||
complexd( 0.99999999999999999892993534667664, -1.46291807926715968052953216186e-9), // p/(2y31)=
|
||||
};
|
||||
|
||||
/*
|
||||
* x: x - array of items
|
||||
* T: 1 << T = 2 power T - number of items in array
|
||||
* complement: false - normal (direct) transformation, true - reverse transformation
|
||||
*/
|
||||
void fft(complexd * x, int T, bool complement)
|
||||
{
|
||||
uint I, J, Nmax, N, Nd2, k, m, mpNd2, Skew;
|
||||
uchar *Ic = (uchar*) &I;
|
||||
uchar *Jc = (uchar*) &J;
|
||||
complexd S;
|
||||
complexd * Wstore, * Warray;
|
||||
complexd WN, W, Temp, *pWN;
|
||||
|
||||
Nmax = 1 << T;
|
||||
|
||||
//first interchanging
|
||||
for(I = 1; I < Nmax - 1; I++)
|
||||
{
|
||||
Jc[0] = reverse256[Ic[3]];
|
||||
Jc[1] = reverse256[Ic[2]];
|
||||
Jc[2] = reverse256[Ic[1]];
|
||||
Jc[3] = reverse256[Ic[0]];
|
||||
J >>= (32 - T);
|
||||
if (I < J)
|
||||
{
|
||||
S = x[I];
|
||||
x[I] = x[J];
|
||||
x[J] = S;
|
||||
}
|
||||
}
|
||||
|
||||
//rotation multiplier array allocation
|
||||
Wstore = new complexd[Nmax / 2];
|
||||
Wstore[0] = complexd(1., 0.);
|
||||
|
||||
//main loop
|
||||
for(N = 2, Nd2 = 1, pWN = W2n, Skew = Nmax >> 1; N <= Nmax; Nd2 = N, N += N, pWN++, Skew >>= 1)
|
||||
{
|
||||
//WN = W(1, N) = exp(-2*pi*j/N)
|
||||
WN= *pWN;
|
||||
if (complement)
|
||||
WN = complexd(WN.real(), -WN.imag());
|
||||
for(Warray = Wstore, k = 0; k < Nd2; k++, Warray += Skew)
|
||||
{
|
||||
if (k & 1)
|
||||
{
|
||||
W *= WN;
|
||||
*Warray = W;
|
||||
}
|
||||
else
|
||||
W = *Warray;
|
||||
|
||||
for(m = k; m < Nmax; m += N)
|
||||
{
|
||||
mpNd2 = m + Nd2;
|
||||
Temp = W;
|
||||
Temp *= x[mpNd2];
|
||||
x[mpNd2] = x[m];
|
||||
x[mpNd2] -= Temp;
|
||||
x[m] += Temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] Wstore;
|
||||
|
||||
if (complement)
|
||||
{
|
||||
for( I = 0; I < Nmax; I++ )
|
||||
x[I] /= Nmax;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char Solver::methods_desc[] = "b{Methods:}\
|
||||
\n -1 - Global settings\
|
||||
@@ -401,3 +247,981 @@ void Solver::solvePA(double u, double h, uint deg) {
|
||||
}
|
||||
moveF();
|
||||
}
|
||||
|
||||
|
||||
|
||||
PIFFT::PIFFT() {
|
||||
prepared = false;
|
||||
}
|
||||
|
||||
|
||||
PIVector<complexd> * PIFFT::calcFFT(const PIVector<complexd> & val) {
|
||||
// for (uint i=0; i<result.size(); i+=2)
|
||||
// {
|
||||
// result[i] = val.at(indexes[i]) + val.at(indexes[i+1]);
|
||||
// result[i+1] = val.at(indexes[i]) - val.at(indexes[i+1]);
|
||||
// }
|
||||
// return &result;
|
||||
result.clear();
|
||||
if (val.size_s() < 4) return &result;
|
||||
fftc1d(val, val.size());
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
||||
PIVector<complexd> *PIFFT::calcFFTinverse(const PIVector<complexd> &val)
|
||||
{
|
||||
result.clear();
|
||||
if (val.size_s() < 4) return &result;
|
||||
fftc1dinv(val, val.size());
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
||||
PIVector<complexd> *PIFFT::calcHilbert(const PIVector<double> &val)
|
||||
{
|
||||
result.clear();
|
||||
if (val.size_s() < 4) return &result;
|
||||
fftc1r(val, val.size());
|
||||
for (uint i=0; i<result.size()/2; i++) result[i] = result[i]*2.;
|
||||
for (uint i=result.size()/2; i<result.size(); i++) result[i] = 0;
|
||||
fftc1dinv(result, result.size());
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
||||
PIVector< complexd >* PIFFT::calcFFT(const PIVector<double> & val) {
|
||||
result.clear();
|
||||
if (val.size_s() < 4) return &result;
|
||||
fftc1r(val, val.size());
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
||||
PIVector<double> PIFFT::getAmplitude() {
|
||||
PIVector<double> a;
|
||||
double tmp;
|
||||
for (uint i=0; i<result.size(); i++) {
|
||||
tmp = sqrt(result.at(i).real()*result.at(i).real()+result.at(i).imag()*result.at(i).imag());
|
||||
a.push_back(tmp);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::fftc1d(const PIVector<complexd> &a, uint n) {
|
||||
createPlan(n);
|
||||
uint i;
|
||||
PIVector<double> buf;
|
||||
buf.resize(2*n);
|
||||
for(i=0; i<n; i++) {
|
||||
buf[2*i+0] = a.at(i).real();// a->ptr.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<n; i++)
|
||||
result[i]=complexd(buf[2*i+0],buf[2*i+1]);
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::fftc1r(const PIVector<double> & a, uint n) {
|
||||
uint i;
|
||||
if( n%2==0 ) {
|
||||
PIVector<double> 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<n; i++)
|
||||
result[i] = conj(result[n-i]);
|
||||
} else {
|
||||
PIVector<complexd> cbuf;
|
||||
cbuf.resize(n);
|
||||
for(i=0; i<n; i++)
|
||||
cbuf[i] = complexd(a[i], 0.);
|
||||
fftc1d(cbuf, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::fftc1dinv(const PIVector<complexd> &a, uint n)
|
||||
{
|
||||
PIVector<complexd> cbuf;
|
||||
cbuf.resize(n);
|
||||
uint i;
|
||||
for(i=0; i<n; i++)
|
||||
{
|
||||
cbuf[i] = conj(a[i]);
|
||||
}
|
||||
fftc1d(cbuf, n);
|
||||
// result.resize(n);
|
||||
for(i=0; i<n; i++)
|
||||
{
|
||||
result[i] = conj(result[i] / (double)n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::createPlan(uint n) {
|
||||
curplan.plan.clear();
|
||||
curplan.precomputed.clear();
|
||||
curplan.stackbuf.clear();
|
||||
curplan.tmpbuf.clear();
|
||||
if (n<2) return;
|
||||
ftbasegeneratecomplexfftplan(n, &curplan);
|
||||
prepared = true;
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::ftbasegeneratecomplexfftplan(uint n, ftplan* plan) {
|
||||
int planarraysize;
|
||||
int plansize;
|
||||
int precomputedsize;
|
||||
int tmpmemsize;
|
||||
int stackmemsize;
|
||||
ae_int_t stackptr;
|
||||
planarraysize = 1;
|
||||
plansize = 0;
|
||||
precomputedsize = 0;
|
||||
stackmemsize = 0;
|
||||
stackptr = 0;
|
||||
tmpmemsize = 2*n;
|
||||
curplan.plan.resize(planarraysize);
|
||||
int ftbase_ftbasecffttask = 0;
|
||||
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
|
||||
if (stackptr!=0) { return;}//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
curplan.stackbuf.resize(piMax(stackmemsize,1));//ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
|
||||
curplan.tmpbuf.resize(piMax(tmpmemsize,1));//ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
|
||||
curplan.precomputed.resize(piMax(precomputedsize,1));//ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
|
||||
stackptr = 0;
|
||||
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
|
||||
if (stackptr!=0) { return;}//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Recurrent subroutine for the FFTGeneratePlan:
|
||||
|
||||
PARAMETERS:
|
||||
N plan size
|
||||
IsReal whether input is real or not.
|
||||
subroutine MUST NOT ignore this flag because real
|
||||
inputs comes with non-initialized imaginary parts,
|
||||
so ignoring this flag will result in corrupted output
|
||||
HalfOut whether full output or only half of it from 0 to
|
||||
floor(N/2) is needed. This flag may be ignored if
|
||||
doing so will simplify calculations
|
||||
Plan plan array
|
||||
PlanSize size of used part (in integers)
|
||||
PrecomputedSize size of precomputed array allocated yet
|
||||
PlanArraySize plan array size (actual)
|
||||
TmpMemSize temporary memory required size
|
||||
BluesteinMemSize temporary memory required size
|
||||
|
||||
-- ALGLIB --
|
||||
Copyright 01.05.2009 by Bochkanov Sergey
|
||||
*************************************************************************/
|
||||
void PIFFT::ftbase_ftbasegenerateplanrec(
|
||||
int n,
|
||||
int tasktype,
|
||||
ftplan* plan,
|
||||
int* plansize,
|
||||
int* precomputedsize,
|
||||
int* planarraysize,
|
||||
int* tmpmemsize,
|
||||
int* stackmemsize,
|
||||
ae_int_t stackptr, int debugi)
|
||||
{
|
||||
int k, m, n1, n2, esize, entryoffset;
|
||||
int ftbase_ftbaseplanentrysize = 8;
|
||||
int ftbase_ftbasecffttask = 0;
|
||||
int ftbase_fftcooleytukeyplan = 0;
|
||||
int ftbase_fftbluesteinplan = 1;
|
||||
int ftbase_fftcodeletplan = 2;
|
||||
int ftbase_fftrealcooleytukeyplan = 5;
|
||||
int ftbase_fftemptyplan = 6;
|
||||
if( *plansize+ftbase_ftbaseplanentrysize>(*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; i<n; i++) {
|
||||
bx = cos(M_PI*sqr(i)/n);
|
||||
by = sin(M_PI*sqr(i)/n);
|
||||
curplan.precomputed[offs+2*i+0] = bx;
|
||||
curplan.precomputed[offs+2*i+1] = by;
|
||||
curplan.precomputed[offs+2*m+2*i+0] = bx;
|
||||
curplan.precomputed[offs+2*m+2*i+1] = by;
|
||||
if( i>0 ) {
|
||||
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<n)
|
||||
best = 2*best;
|
||||
ftbase_ftbasefindsmoothrec(n, 1, 2, &best);
|
||||
result = best;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void PIFFT::ftbase_internalreallintranspose(PIVector<double>* a, int m, int n, int astart, PIVector<double>* 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<double>* a, int astart, int astride, PIVector<double>* 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<double>* a, int m, int n, int astart, PIVector<double>* 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<double>* a, int astart, int astride, PIVector<double>* 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<double>* 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<double>* 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<double> & 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<n; i++) {
|
||||
bx = curplan.precomputed[offsp+0];
|
||||
by = curplan.precomputed[offsp+1];
|
||||
x = (*a)[offsa+0];
|
||||
y = (*a)[offsa+1];
|
||||
curplan.stackbuf[offsb+0] = x*bx-y*(-by);
|
||||
curplan.stackbuf[offsb+1] = x*(-by)+y*bx;
|
||||
offsp = offsp+2;
|
||||
offsa = offsa+2;
|
||||
offsb = offsb+2;
|
||||
}
|
||||
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset+5], stackptr+2*2*m);
|
||||
offsb = stackptr;
|
||||
offsp = offs;
|
||||
for(int i=0; i<=m-1; i++) {
|
||||
x = curplan.stackbuf[offsb+0];
|
||||
y = curplan.stackbuf[offsb+1];
|
||||
bx = curplan.precomputed[offsp+0];
|
||||
by = curplan.precomputed[offsp+1];
|
||||
curplan.stackbuf[offsb+0] = x*bx-y*by;
|
||||
curplan.stackbuf[offsb+1] = -(x*by+y*bx);
|
||||
offsb = offsb+2;
|
||||
offsp = offsp+2;
|
||||
}
|
||||
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset+5], stackptr+2*2*m);
|
||||
offsb = stackptr;
|
||||
offsp = offs+2*m;
|
||||
offsa = aoffset;
|
||||
for(int i=0; i<n; i++) {
|
||||
x = curplan.stackbuf[offsb+0]/m;
|
||||
y = -curplan.stackbuf[offsb+1]/m;
|
||||
bx = curplan.precomputed[offsp+0];
|
||||
by = curplan.precomputed[offsp+1];
|
||||
(*a)[offsa+0] = x*bx-y*(-by);
|
||||
(*a)[offsa+1] = x*(-by)+y*bx;
|
||||
offsp = offsp+2;
|
||||
offsa = offsa+2;
|
||||
offsb = offsb+2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Twiddle factors calculation
|
||||
|
||||
-- ALGLIB --
|
||||
Copyright 01.05.2009 by Bochkanov Sergey
|
||||
*************************************************************************/
|
||||
void PIFFT::ftbase_ffttwcalc(PIVector<double> * 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<n1-1 ) {
|
||||
if( j%ftbase_ftbaseupdatetw==0 ) {
|
||||
v = -2*M_PI*i*(j+1)/n;
|
||||
twxm1 = -2*sqr(sin(0.5*v));
|
||||
twy = sin(v);
|
||||
} else {
|
||||
tmpx = twrowxm1+twxm1*twrowxm1-twy*twrowy;
|
||||
tmpy = twrowy+twxm1*twrowy+twy*twrowxm1;
|
||||
twxm1 = twxm1+tmpx;
|
||||
twy = twy+tmpy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( i<n2-1 ) {
|
||||
if( j%ftbase_ftbaseupdatetw==0 ) {
|
||||
v = -2*M_PI*(i+1)/n;
|
||||
twrowxm1 = -2*sqr(sin(0.5*v));
|
||||
twrowy = sin(v);
|
||||
} else {
|
||||
tmpx = twbasexm1+twrowxm1*twbasexm1-twrowy*twbasey;
|
||||
tmpy = twbasey+twrowxm1*twbasey+twrowy*twbasexm1;
|
||||
twrowxm1 = twrowxm1+tmpx;
|
||||
twrowy = twrowy+tmpy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PIStatistic::PIStatistic() {
|
||||
mean = 0.;
|
||||
variance = 0.;
|
||||
skewness = 0.;
|
||||
kurtosis = 0.;
|
||||
}
|
||||
|
||||
|
||||
bool PIStatistic::calculate(const PIVector<double> & 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user