summaryrefslogtreecommitdiff
path: root/macros/goertzel.sci
blob: bc0061ccfff68404b802e532acbf83283035f9bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
function Y = goertzel(X,INDVEC,DIM)
//Computes DFT using the second order Goertzel Algorithm
//Calling Sequence
//Y = goertzel(X,INDVEC,DIM)
//Parameters
//X
//A vector matrix or n-dimensional array
//INDVEC
//The indices at which the DFT is to be computed
//DIM
//The dimension along which the algorithm is to be implemented
//Description
//goertzel(X,INDVEC)
//Computes the DFT of X at indices INDVEC using the second order algorithm along
//the first non-singleton dimension. Elements of INDVEC must be positive integers
//less than the length of the first non-singleton dimension. If INDVEC is empty
//the DFT is computed at all indices along the first non-singleton dimension
//goertzel(X,INDVEC,DIM)
//Implements the algorithm along dimension DIM
//In general goertzel is slower than fft when computing the DFT for all indices
//along a particular dimension. However it is computationally more efficient when
//the DFT at only a subset of indices is desired
//Example
//x=rand(1,5)
//x  =
// 
//    0.6283918    0.8497452    0.6857310    0.8782165    0.0683740  
//y=goertzel(x,2);
//y  =
// 
//  - 0.3531539 - 0.6299881i  
//Author
//Ankur Mallick
//References
//Goertzel, G. (January 1958), "An Algorithm for the Evaluation of Finite Trigonometric Series", American Mathematical Monthly 65 (1): 34–35, doi:10.2307/2310304
    funcprot(0);
    if(argn(2)<3|isempty(DIM))
        DIM=find(size(X)>1,1); //First non-singleton dimension
    end
    if(DIM>ndims(X))
        error('Invalid Dimensions');
    end
    perm=[DIM, 1:DIM-1, DIM+1:ndims(X)];
    X=permute(X,perm); //Makes DIM the leading dimension
    S=size(X);
    if(argn(2)<2|isempty(INDVEC))
        INDVEC=1:S(1);
    end
    if(max(INDVEC)>S(1)|min(INDVEC)<1)
        error('Index out of bounds');
    elseif(or(INDVEC~=round(INDVEC)))
        error('Indices must be integers');
    end
    X1=matrix(X,1,prod(S));
    T=[type(X1), type(INDVEC), type(DIM)]; //all inputs should be of type double
    if(~and(T==1))
        error('Invalid data type');
    end
    //Implementing Goertzel algorithm
    len=[length(INDVEC), S(2:length(S))];
    Y=matrix(zeros(1,prod(len)),len);
    v=ones(length(INDVEC),1);
    w=(2*%pi*(INDVEC-1)/S(1))';
    re=2*cos(w);
    im=sin(w);
    for i=1:prod(S(2:length(S)))
        x=X(:,i)
        sp1=0;
        sp2=0;
        for j=1:S(1)
            s=x(j)*v+re.*sp1-sp2;
            sp2=sp1;
            sp1=s;
        end
        Y(:,i)=((re/2)+im*%i).*sp1-sp2;
    end
    iperm(perm)=1:length(perm);
    Y=permute(Y,iperm); //Converting Y to the original shape of X
endfunction