#!../src/tops  -s ../sys  -u ../usr

# Tests for real-only and complex forward and inverse Fourier
# transforms.

"icfft" missing
IF
    "tops not compiled with FFTW; cannot run fft" nl .
    halt
THEN


define: chk_fft ( n --- )
    1.0e-12 is TOLERANCE

    2 /
    rand * integer 1 + 2 * into nPts  # force even nPts
    nPts " N=%5.0f  " format .

    # For tests 1 to 4, signal is real-only

    nPts 1 random      into signal
    nPts 1 null        into n_zero

    # test 1:  error = | real inv fft ( real fft ( signal ) ) - signal |
    #
    signal fft ifft signal 
    - abs maxfetch drop drop
    dup .
    TOLERANCE > 
    IF  
        " fft <-> ifft      ERROR " . 
        quit
    ELSE  
        " fft <-> ifft      OK " . 
    THEN
    nl

    # test 2:  error = | real inv fft ( complex fft ( signal ) ) - signal |
    #
    signal n_zero cfft ifft signal 
    - abs maxfetch drop drop
    dup "              " . .
    TOLERANCE > 
    IF  
        " cfft <-> ifft     ERROR " . 
        quit
    ELSE  
        " cfft <-> ifft     OK " . 
    THEN
    nl

    # test 3:  error = | imag. of complex inv fft ( complex fft ( signal ) ) |
    #
    signal n_zero cfft icfft
    abs maxfetch drop drop
    dup "              " . .
    TOLERANCE > 
    IF  
        " icfft imag        ERROR " . 
        quit
    ELSE  
        " icfft imag        OK " . 
    THEN
    drop
    nl

    # test 4:  error = | complex inv fft ( complex fft ( signal ) ) - signal |
    #
    signal n_zero cfft icfft drop signal
    - abs maxfetch drop drop
    dup "              " . .
    TOLERANCE > 
    IF  
        " cfft <-> icfft    ERROR " . 
        quit
    ELSE  
        " cfft <-> icfft    OK " . 
    THEN
    nl

    # For tests 5 and 6 use a complex signal

    nPts 1 random      into signal_Re
    nPts 1 random      into signal_Im

    signal_Re signal_Im cfft icfft 
    signal_Im - abs maxfetch drop drop

    # test 5:  compare imaginary components of 
    #             | complex inv fft ( complex fft ( signal ) ) - signal |
    dup "              " . .
    TOLERANCE > 
    IF  
        " cfft <-> icfft Im ERROR " . 
        quit
    ELSE  
        " cfft <-> icfft Im OK " . 
    THEN
    nl

    # test 6:  compare real components of 
    #             | complex inv fft ( complex fft ( signal ) ) - signal |
    signal_Re - abs maxfetch drop drop
    dup "              " . .
    TOLERANCE > 
    IF  
        " cfft <-> icfft Re ERROR " . 
        quit
    ELSE  
        " cfft <-> icfft Re OK " . 
    THEN
    nl

    xx
    ;

define: n_fft_tests ( nIter nSize  --- )
    \ Invokes chk_fft nIter times for a random sized systems (up to nSize)
    into nSize
    1 DO I nSize 
        I "%5.0f.  " format .
        chk_fft 
    LOOP
    ;

time seedset
10 (iterations) 10000 (max fft size) n_fft_tests
