.packageName <- "kzft"
coeff.kzft<-function(m, k){
      poly<-polynomial(rep(1,m))
      polyk<-poly^k
      coef<-as.vector(polyk)
      coef<-coef/m^k
      return(coef)
}

transfun.kzft<-function(m, k, lamda=seq(-0.5,0.5,by=0.01), omega=0){

      lamda<-lamda*2*pi
      omega<-omega*2*pi

      N<-length(lamda)

      tf<-array(0,dim=c(N, m))

      for ( j in (1:m) ){
         tf[,j]<-exp(1i*(lamda-omega)*j)
      }

      tf1<-rep(0,N)
      for ( i in (1:N) ){
         tf1[i]<-sum(tf[i,])
      }

      tf2<-(1/m)*tf1
      tf2<-abs(tf2)^k
      return(tf2)
}

kzft<-function(x,m,k,p=1,n=1){

    data<-as.vector(x)

    if (((m-1)*k+1)>length(data))
        stop("invalid 'm' & 'k':(m-1)k+1 should be less equal length of data")
 
    coef<-coeff.kzft(m,k)

    N<-length(data)
    M<-(m-1)*k+1
    L<-round(M*p)
    T<-floor((N-M)/L)+1
    kzft<-array(NA,dim=c(T,n*m))

    omega<-2*pi*seq(0,1,length=n*m+1)[-1]

    s<-0:(M-1)

    coefft<-coef*exp(-1i*s%o%omega)

    for ( t in (1:T) ){
        kzft[t,]<-data[((t-1)*L+1):((t-1)*L+M)]%*%coefft
    }
    kzftf<-colMeans(kzft)
    lst<-list(tfmatrix=kzft, fft=kzftf)
    return(lst)
}



kzp<-function(x,m,k,p=1,n=1){
    data<-as.vector(x)
    if (((m-1)*k+1)>length(data))
        stop("invalid 'm' & 'k':(m-1)k+1 should be less equal length of data")

    coef<-coeff.kzft(m,k)

    N<-length(data);
    M<-(m-1)*k+1
    L<-round(M*p)    
    T<-floor((N-M)/L)+1

    kzft<-array(NA,dim=c(T,n*m))
    pg<-array(NA,dim=c(T,n*m))


    omega<-2*pi*seq(0,1,length=n*m+1)[-1]

    s<-0:(M-1);

    coefft<-coef*exp(-1i*s%o%omega)

    for ( t in (1:T) ){
        kzft[t,]<-data[((t-1)*L+1):((t-1)*L+M)]%*%coefft
        pg[t,]<-((abs(kzft[t,]))^2)*M
    }

    kzp<-colMeans(pg)

    kzp<-kzp[1:round(n*m/2)]

    return(kzp)
}

nonlinearity.kzp<-function(pg,K=length(pg)){
    N<-length(pg)

    S<-rep(0,N)
    S[1]<-0
    S[N]<-0
    for ( t in 2:(N-1) ) {
        S[t]<-abs(pg[t+1]-2*pg[t]+pg[t-1])
    }

    total<-sum(S)

    sq<-array(0, dim=c(N, K))

    for ( i in (1:N) ) for ( j in (2:K) ) {
        sq[i,j]<-sum(S[(max(1,(i-j+1))):(min(N,(i+j-1)))])
    }

    lst<-list(total=total, sqmatrix=sq)
    return(lst)
}


variation.kzp<-function(pg,K=length(pg)){
    N<-length(pg)
    S=c(diff(pg)^2,0)

    total<-sum(S)

    sq<-array(0, dim=c(N, K))
    for ( i in (1:N) ) for ( j in (2:K) ) {
        sq[i,j]<-sum(S[(max(1,(i-j+1))):(min(N,(i+j-2)))])
    }

    lst<-list(total=total, sqmatrix=sq)
    return(lst)
}

smooth.kzp<-function(pg,c,K=length(pg),method = "DZ") {
    N<-length(pg)
    spg<-rep(0,N)
    m<-rep(0,N)

    if      (method == "DZ") sq<-variation.kzp(pg,K)
    else if (method == "NZ") sq<-nonlinearity.kzp(pg,K)

    cc<-c*sq$total

    for ( i in (1:N) ) {
        m[i]<-sum(sq$sqmatrix[i,1:K]<=cc)
        spg[i]<-mean(pg[(max(1,(i-m[i]+1))):(min(N,(i+m[i]-1)))])
    }

    lst<-list(periodogram=spg,number=m)
    return(lst)
}

kztp<-function(x,m,k,p=1,n=1,rp1=0,rp2=0.5,cp1=0,cp2=0.5){
    data<-as.vector(x)
    if (((m-1)*k+1)>length(data))
        stop("invalid 'm' & 'k':(m-1)k+1 should be less equal length of data")

    coef<-coeff.kzft(m,k)

    N<-length(data)
    M<-(m-1)*k+1
    L<-round(M*p)
    T<-floor((N-M)/L)+1

    kzft<-array(NA,dim=c(T,n*m))

    omega<-2*pi*seq(0,1,length=n*m+1)[-1]

    s<-0:(M-1)

    coefft<-coef*exp(-1i*s%o%omega)

    for ( t in (1:T) ){
        kzft[t,]<-data[((t-1)*L+1):((t-1)*L+M)]%*%coefft
    }

    rm1<-max(round(m*n*rp1),1)
    rm2<-round(m*n*rp2)
    cm1<-max(round(m*n*cp1),1)
    cm2<-round(m*n*cp2)
    delta.rm<-rm2-rm1+1
    delta.cm<-cm2-cm1+1

    kztp<-array(NA,dim=c(delta.rm,delta.cm,T))
    for ( i in (1:delta.rm) ) for ( j in (1:delta.cm) ){
         kztp[i,j,]<-kzft[,i+rm1-1]*kzft[,j+cm1-1]*Conj(kzft[,i+j+rm1+cm1-2])*M^2
    }               
        
    kztp<-rowMeans(kztp,dim=2)

    lst<-list(bispectrum=kztp, modulus=Mod(kztp), argument=Arg(kztp))
    return(lst)
}

variation.kztp<-function(pg, K=dim(pg)[1]){
    N<-dim(pg)[1]
    sq<-array(0,dim=c(N,N,K))

    sqvar2<-function(pg){
        sdif1<-sum(diff(pg)^2)
        sdif2<-sum(diff(t(pg))^2)

        sumsq<-sdif1+sdif2
        return(sumsq)
    }

    total<-sqvar2(pg)

    for ( i in (1:N) ) for ( j in (1:N) ) for ( k in (2:K) ) {
        sq[i,j,k]<-sqvar2(pg[(max(1,(i-k+1)):min(N,(i+k-1))),(max(1,(j-k+1)):min(N,(j+k-1)))])
    }

    lst<-list(total=total, sqmatrix=sq)
    return(lst)
}

smooth.kztp<-function(pg,c,K=dim(pg)[1]) {
    N<-dim(pg)[1]
    spg<-array(0,dim=c(N,N))
    m<-array(0,dim=c(N,N))

    sq<-variation.kztp(pg,K)

    cc<-c*sq$total


    for ( i in (1:N) ) for ( j in (1:N) ) {
        m[i,j]<-sum(sq$sqmatrix[i,j,1:K]<=cc)
        spg[i,j]<-mean(pg[(max(1,(i-m[i,j]+1))):(min(N,(i+m[i,j]-1))),(max(1,(j-m[i,j]+1))):(min(N,(j+m[i,j]-1)))])
    }

    lst<-list(bispectrum=spg,number=m)
    return(lst)
}



kzw<-function(x,f1=1/length(x),f2=0.5,delta.f=1/length(x),t1=1,t2=length(x),delta.t=1,n,k=3,method="zero"){

updown<-function(x){
    n<-length(x)
    y<-rep(NA,n)

    for ( i in (1:n)) {
     y[i] = x[n-i+1]
    }
    return(y)
}

    data<-as.vector(x)

    left.extra<-floor((round(n/f1)-1)*k/2)
    right.extra<-ceiling((round(n/f1)-1)*k/2)

    left.n.extra<-floor(left.extra/length(data)/2)+1
    right.n.extra<-floor(right.extra/length(data)/2)+1    

    data.left<-rep(c(data,updown(data)),left.n.extra)
    data.right<-rep(c(updown(data),data),right.n.extra)
    
    data_left <-updown(data.left[1:left.extra])
    data_right<-data.right[1:right.extra]
    data_new1<-c(data_left,data,data_right)
   
    left.zero = rep(0,left.extra)
    right.zero = rep(0,right.extra)
    data_new2<-c(left.zero,data,right.zero)
    

    if      (method == "repeat") data_new<-data_new1
    else if (method == "zero")   data_new<-data_new2
    
    ff<-seq(f1,f2,by=delta.f)
    tt<-seq(t1,t2,by=delta.t)

    length.f<-length(ff)
    length.t<-length(tt)  

    kzft<-array(NA,dim=c(length.t,length.f))
    kzw <-array(NA,dim=c(length.t,length.f))
    em  <-array(NA,dim=c(length.t,length.f))
    pg  <-array(NA,dim=c(length.t,length.f))

    for ( f in (1:length.f) )  { 

    m = round(n/ff[f])
    coef<-coeff.kzft(m,k)
    M<-(m-1)*k+1
    left.half.M<-floor((M-1)/2)
    right.half.M<-ceiling((M-1)/2)
    s<-0:(M-1)
    coefft<-coef*exp(-1i*s*2*pi*ff[f]) 

    for( t in (1:length.t) ) {
 
       kzft[t,f]<-data_new[(tt[t]+left.extra-left.half.M):(tt[t]+left.extra+right.half.M)]%*%coefft
       kzw[t,f]<-2*Re(kzft[t,f])
       em[t,f]<-kzw[t,f]^2
       pg[t,f]<-((abs(kzft[t,f]))^2)*M

    }
}

    lst<-list(kzw=kzw, em=em, pg=pg)
    return(lst)
}


kzww<-function(x,f1=1/length(x),f2=0.5,delta.f=1/length(x),t1=1,t2=length(x),delta.t=1, m, k=3, method="zero"){

updown<-function(x){
    n<-length(x)
    y<-rep(NA,n)

    for ( i in (1:n)) {
     y[i] = x[n-i+1]
    }
    return(y)
}

    data<-as.vector(x)

    left.extra<-floor((m-1)*k/2)
    right.extra<-ceiling((m-1)*k/2)

    left.n.extra<-floor(left.extra/length(data)/2)+1
    right.n.extra<-floor(right.extra/length(data)/2)+1    

    data.left<-rep(c(data,updown(data)),left.n.extra)
    data.right<-rep(c(updown(data),data),right.n.extra)
    
    data_left <-updown(data.left[1:left.extra])
    data_right<-data.right[1:right.extra]
    data_new1<-c(data_left,data,data_right)
   
    left.zero = rep(0,left.extra)
    right.zero = rep(0,right.extra)
    data_new2<-c(left.zero,data,right.zero)
    

    if      (method == "repeat") data_new<-data_new1
    else if (method == "zero")   data_new<-data_new2
    
    ff<-seq(f1,f2,by=delta.f)
    tt<-seq(t1,t2,by=delta.t)

    length.f<-length(ff)
    length.t<-length(tt)  

    kzft<-array(NA,dim=c(length.t,length.f))
    kzw <-array(NA,dim=c(length.t,length.f))
    em  <-array(NA,dim=c(length.t,length.f))
    pg  <-array(NA,dim=c(length.t,length.f))

    coef<-coeff.kzft(m,k)
    M<-(m-1)*k+1
    left.half.M<-floor((M-1)/2)
    right.half.M<-ceiling((M-1)/2)
    s<-0:(M-1)
    omega<-2*pi*ff
    coefft<-coef*exp(-1i*s%o%omega)

    for( t in (1:length.t) ) {
       kzft[t,]<-data_new[(tt[t]+left.extra-left.half.M):(tt[t]+left.extra+right.half.M)]%*%coefft
       kzw[t,]<-2*Re(kzft[t,])
       em[t,]<-kzw[t,]^2
       pg[t,]<-((abs(kzft[t,]))^2)*M

    }

    lst<-list(kzw=kzw, em=em, pg=pg)
    return(lst) 
}

