This is gsl-ref.info, produced by Makeinfo version 3.12h from
gsl-ref.texi.

INFO-DIR-SECTION Scientific software
START-INFO-DIR-ENTRY
* gsl-ref: (gsl-ref).                   GNU Scientific Library - Reference
END-INFO-DIR-ENTRY

   This file documents the GNU Scientific Library.

   Copyright (C) 1996, 1997, 1998, 1999 The GSL Project.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Foundation.


File: gsl-ref.info,  Node: Minimization Algorithms,  Next: Minimization Examples,  Prev: Minimization Stopping Parameters,  Up: Minimization

Minimization Algorithms
=======================

   The minimization algorithms described in this section require an
initial interval which is guaranteed to contain a minimum -- if a and b
are the endpoints of the interval and x is an estimate of the minimum
then f(a) > f(x) < f(b).  This ensures that the function has at least
one minimum somewhere in the interval.  If a valid initial interval is
used then these algorithm cannot fail, provided the function is
well-behaved.

 - Minimizer: gsl_min_fminimizer_goldensection
     The "golden section algorithm" is the simplest method of bracketing
     the minimum of a function.  It is the slowest algorithm provided
     by the library, with linear convergence.

     On each iteration, the algorithm first compares the subintervals
     from the endpoints to the current minimum.  The larger subinterval
     is divided in a golden section (using the famous ratio (3-\sqrt
     5)/2) and the value of the function at this new point is
     calculated.  The new value is used with the constraint f(a') >
     f(x') < f(b') to a select new interval containing the minimum, by
     discarding the least useful point.  This procedure can be
     continued indefinitely until the interval is sufficiently small.
     Choosing the golden section as the bisection ratio can be shown to
     provide the fastest convergence for this type of algorithm.


 - Minimizer: gsl_min_fminimizer_brent
     The "Brent minimization algorithm" combines a parabolic
     interpolation with the golden section algorithm.  This produces a
     fast algorithm which is still robust.

     The outline of the algorithm can be summarized as follows: on each
     iteration Brent's method approximates the function using an
     interpolating parabola through three existing points.  The minimum
     of the parabola is taken as a guess for the minimum.  If it lies
     within the bounds of the current interval then the interpolating
     point is accepted, and used to generate a smaller interval.  If
     the interpolating point is not accepted then the algorithm falls
     back to an ordinary golden section step.  The full details of
     Brent's method include some additional checks to improve
     convergence.


File: gsl-ref.info,  Node: Minimization Examples,  Next: Minimization References and Further Reading,  Prev: Minimization Algorithms,  Up: Minimization

Examples
========

   The following program uses the Brent algorithm to find the minimum of
the function f(x) = \cos(x) + 1, which occurs at x = \pi.  The starting
interval is (0,6), with an initial guess for the minimum of 2.

     #include <stdio.h>
     #include <gsl/gsl_errno.h>
     #include <gsl/gsl_math.h>
     #include <gsl/gsl_min.h>
     
     double fn1 (double x, void * params);
     
     double fn1 (double x, void * params)
     {
       return cos(x) + 1.0 ;
     }
     
     int
     main ()
     {
       int status;
       int iterations = 0, max_iterations = 100;
       gsl_min_fminimizer *s;
       double m = 2.0, m_expected = M_PI;
       gsl_interval x =  {0, 6.0};
       gsl_function F;
     
       F.function = &fn1;
       F.params = 0;
     
       s = gsl_min_fminimizer_alloc (gsl_min_fminimizer_brent, &F, m, x);
     
       printf ("using %s method\n", gsl_min_fminimizer_name (s));
     
       printf ("%5s [%9s, %9s] %9s %9s %10s %9s\n",
     	  "iter", "lower", "upper", "min", "actual", "err", "err(est)");
     
       printf ("%5d [%.7f, %.7f] %.7f %.7f %+.7f %.7f\n",
               iterations, x.lower, x.upper,
               m, m_expected, m - m_expected, x.upper - x.lower);
     
       do
         {
           iterations++;
           status = gsl_min_fminimizer_iterate (s);
     
           m = gsl_min_fminimizer_minimum (s);
           x = gsl_min_fminimizer_interval (s);
     
           status = gsl_min_test_interval (x, 0.001, 0.0);
     
           if (status == GSL_SUCCESS)
     	printf ("Converged:\n");
     
           printf ("%5d [%.7f, %.7f] %.7f %.7f %+.7f %.7f\n",
     	      iterations, x.lower, x.upper,
     	      m, m_expected, m - m_expected, x.upper - x.lower);
         }
       while (status == GSL_CONTINUE && iterations < max_iterations);
     
     }

Here are the results of the minimization procedure.

     bash$ ./a.out
         0 [0.0000000, 6.0000000] 2.0000000 3.1415927 -1.1415927 6.0000000
         1 [2.0000000, 6.0000000] 3.2758640 3.1415927 +0.1342713 4.0000000
         2 [2.0000000, 3.2831929] 3.2758640 3.1415927 +0.1342713 1.2831929
         3 [2.8689068, 3.2831929] 3.2758640 3.1415927 +0.1342713 0.4142862
         4 [2.8689068, 3.2831929] 3.2758640 3.1415927 +0.1342713 0.4142862
         5 [2.8689068, 3.2758640] 3.1460585 3.1415927 +0.0044658 0.4069572
         6 [3.1346075, 3.2758640] 3.1460585 3.1415927 +0.0044658 0.1412565
         7 [3.1346075, 3.1874620] 3.1460585 3.1415927 +0.0044658 0.0528545
         8 [3.1346075, 3.1460585] 3.1460585 3.1415927 +0.0044658 0.0114510
         9 [3.1346075, 3.1460585] 3.1424060 3.1415927 +0.0008133 0.0114510
        10 [3.1346075, 3.1424060] 3.1415885 3.1415927 -0.0000041 0.0077985
     Converged:
        11 [3.1415885, 3.1424060] 3.1415927 3.1415927 -0.0000000 0.0008175


File: gsl-ref.info,  Node: Minimization References and Further Reading,  Prev: Minimization Examples,  Up: Minimization

References and Further Reading
==============================

   Further information on Brent's algorithm is available in the
following book,

     Richard Brent, `Algorithms for minimization without derivatives',
     Prentice-Hall (1973)


File: gsl-ref.info,  Node: Simulated Annealing,  Next: Fast Fourier Transforms,  Prev: Minimization,  Up: Top

Simulated Annealing
*******************

   Stochastic search techniques are used when the structure of a space
is not well understood or is not smooth, so that techniques like
Newton's method (which requires calculating Jacobian derivative
matrices) cannot be used.

   In particular, these techniques are frequently used to solve
_combinatorial optimization_ problems, such as the traveling salesman
problem.

   The basic problem layout is that we are looking for a point in the
space at which a real valued _energy function_ (or _cost function_) is
minimized.

   Simulated annealing is a technique which has given good results in
avoiding local minima; it is based on the idea of taking a random walk
through the space at successively lower temperatures, where the
probability of taking a step is given by a Boltzmann distribution.

* Menu:

* Simulated Annealing algorithm::
* Simulated Annealing functions::
* Examples with Simulated Annealing::


File: gsl-ref.info,  Node: Simulated Annealing algorithm,  Next: Simulated Annealing functions,  Prev: Simulated Annealing,  Up: Simulated Annealing

Simulated Annealing algorithm
=============================

   We take random walks through the problem space, looking for points
with low energies; in these random walks, the probability of taking a
step is determined by the Boltzmann distribution

     p = e^{-(E_{i+1} - E_i)/(kT)}

if E_{i+1} < E_i, and p = 0 when E_{i+1} \ge E_i.

   In other words, a step _will_ occur if the new energy is lower.  If
the new energy is higher, the transition can still occur, and its
likelihood is proportional to the temperature T and inversely
proportional to the energy difference E_{i+1} - E_i.

   The temperature T is initially set to a high value, and a random
walk is carried out at that temperature.  Then the temperature is
lowered very slightly (according to a _cooling schedule_) and another
random walk is taken.

   This slight probability of taking a step that gives _higher_ energy
is what allows simulated annealing to frequently get out of local
minima.

   An initial guess is supplied.  At each step, a point is chosen at a
random distance from the current one, where the random distance _r_ is
distributed according to a Boltzmann distribution r = e^(-E/kT).  After
a few search steps using this distribution, the temperature _T_ is
lowered according to some scheme, for example T -> T/mu_T where mu_T is
slightly greater than 1.


File: gsl-ref.info,  Node: Simulated Annealing functions,  Next: Examples with Simulated Annealing,  Prev: Simulated Annealing algorithm,  Up: Simulated Annealing

Simulated Annealing functions
=============================

 - Simulated annealing: gsl_Efunc_t
          typedef double (*gsl_Efunc_t) (void *xp);

 - Simulated annealing: gsl_siman_step_t
          typedef void (*gsl_siman_step_t) (void *xp, double step_size);

 - Simulated annealing: gsl_siman_metric_t
          typedef double (*gsl_siman_metric_t) (void *xp, void *yp);

 - Simulated annealing: gsl_siman_print_t
          typedef void (*gsl_siman_print_t) (void *xp);

 - Simulated annealing: gsl_siman_params_t
     These are the parameters that control a run of `gsl_siman_solve'.

          /* this structure contains all the information needed to structure
             the search, beyond the energy function, the step function and the
             initial guess. */
          struct s_siman_params {
            int n_tries;          /* how many points to try for each step */
            int iters_fixed_T;    /* how many iterations at each temperature? */
            double step_size;     /* max step size in the random walk */
            /* the following parameters are for the Boltzmann distribution */
            double k, t_initial, mu_t, t_min;
          };
          
          typedef struct s_siman_params gsl_siman_params_t;

 - Simulated annealing: void gsl_siman_solve (void *X0_P, gsl_Efunc_t
          EF, gsl_siman_metric_t DISTANCE, gsl_siman_print_t
          PRINT_POSITION, size_t ELEMENT_SIZE, gsl_siman_params_t
          params)
     Does a _simulated annealing_ search through a given space.  The
     space is specified by providing the functions EF, DISTANCE,
     PRINT_POSITION, ELEMENT_SIZE.

     The PARAMS structure (described above) controls the run by
     providing the temperature schedule and other tunable parameters to
     the algorithm (*note Simulated Annealing algorithm::.).  p The
     result (optimal point in the space) is placed in `*X0_P'.

     If PRINT_POSITION is not null, a log will be printed to the screen
     with the following columns:

          number_of_iterations temperature x x-(*x0_p) Ef(x)

     If PRINT_POSITION is null, no information is printed to the screen.


File: gsl-ref.info,  Node: Examples with Simulated Annealing,  Prev: Simulated Annealing functions,  Up: Simulated Annealing

Examples with Simulated Annealing
=================================

   GSL's Simulated Annealing package is clumsy, and it has to be
because it is written in C, for C callers, and tries to be polymorphic
at the same time.  But here we provide some examples which can be
pasted into your application with little change and should make things
easier.

* Menu:

* Trivial example::
* Traveling Salesman Problem::


File: gsl-ref.info,  Node: Trivial example,  Next: Traveling Salesman Problem,  Prev: Examples with Simulated Annealing,  Up: Examples with Simulated Annealing

Trivial example
---------------

   The first example, in one dimensional cartesian space, sets up an
energy function which is a damped sine wave; this has many local
minima, but only one global minimum, somewhere between 1.0 and 1.5.
The initial guess given is 15.5, which is several local minima away
from the global minimum.

     /* set up parameters for this simulated annealing run */
     #define N_TRIES 200             /* how many points do we try before stepping */
     #define ITERS_FIXED_T 10        /* how many iterations for each T? */
     #define STEP_SIZE 10            /* max step size in random walk */
     #define K 1.0                   /* Boltzmann constant */
     #define T_INITIAL 0.002         /* initial temperature */
     #define MU_T 1.005              /* damping factor for temperature */
     #define T_MIN 2.0e-6
     
     gsl_siman_params_t params = {N_TRIES, ITERS_FIXED_T, STEP_SIZE,
                                  K, T_INITIAL, MU_T, T_MIN};
     
     /* now some functions to test in one dimension */
     double E1(void *xp)
     {
       double x = * ((double *) xp);
     
       return exp(-square(x-1))*sin(8*x);
     }
     
     double M1(void *xp, void *yp)
     {
       double x = *((double *) xp);
       double y = *((double *) yp);
     
       return fabs(x - y);
     }
     
     void S1(void *xp, double step_size)
     {
       double r;
       double old_x = *((double *) xp);
       double new_x;
     
       r = gsl_ran_uniform();
       new_x = r*2*step_size - step_size + old_x;
     
       memcpy(xp, &new_x, sizeof(new_x));
     }
     
     void P1(void *xp)
     {
       printf("%12g", *((double *) xp));
     }
     
     int main(int argc, char *argv[])
     {
       Element x0;                   /* initial guess for search */
     
       double x_initial = 15.5;
     
       gsl_siman_solve(&x_initial, E1, S1, M1, P1, sizeof(double), params);
       return 0;
     }

   Here are a couple of plots that are generated by running
`siman_test' in the following way:
     ./siman\_test | grep -v "^#" | xyplot -xyil -y -0.88 -0.83 -d "x...y" | xyps -d > siman-test.eps
     ./siman\_test | grep -v "^#" | xyplot -xyil -xl "generation" -yl "energy" -d "x..y" | xyps -d > siman-energy.eps


File: gsl-ref.info,  Node: Traveling Salesman Problem,  Prev: Trivial example,  Up: Examples with Simulated Annealing

Traveling Salesman Problem
--------------------------

   The TSP (_Traveling Salesman Problem_) is the classic combinatorial
optimization problem.  I have provided a very simple version of it,
based on the coordinates of twelve cities in the southwestern United
States.  This should maybe be called the _Flying Salesman Problem_,
since I am using the great-circle distance between cities, rather than
the driving distance.  Also: I assume the earth is a sphere, so I don't
use geoid distances.

   The `gsl_siman_solve()' routine finds a route which is 3490.62
Kilometers long; this is confirmed by an exhaustive search of all
possible routes with the same initial city.

   The full code can be found in `siman/siman_tsp.c', but I include
here some plots generated with in the following way:
     ./siman_tsp > tsp.output
     grep -v "^#" tsp.output  | xyplot -xyil -d "x................y" -lx "generation" -ly "distance" -lt "TSP -- 12 southwest cities" | xyps -d > 12-cities.eps
     grep initial_city_coord tsp.output | awk '{print $2, $3, $4, $5}' | xyplot -xyil -lb0 -cs 0.8 -lx "longitude (- means west)" -ly "latitude" -lt "TSP -- initial-order" | xyps -d > initial-route.eps
     grep final_city_coord tsp.output | awk '{print $2, $3, $4, $5}' | xyplot -xyil -lb0 -cs 0.8 -lx "longitude (- means west)" -ly "latitude" -lt "TSP -- final-order" | xyps -d > final-route.eps

   This is the output showing the initial order of the cities;
longitude is negative, since it is west and I want the plot to look
like a map.
     # initial coordinates of cities (longitude and latitude)
     ###initial_city_coord: -105.95 35.68 Santa Fe
     ###initial_city_coord: -112.07 33.54 Phoenix
     ###initial_city_coord: -106.62 35.12 Albuquerque
     ###initial_city_coord: -103.2 34.41 Clovis
     ###initial_city_coord: -107.87 37.29 Durango
     ###initial_city_coord: -96.77 32.79 Dallas
     ###initial_city_coord: -105.92 35.77 Tesuque
     ###initial_city_coord: -107.84 35.15 Grants
     ###initial_city_coord: -106.28 35.89 Los Alamos
     ###initial_city_coord: -106.76 32.34 Las Cruces
     ###initial_city_coord: -108.58 37.35 Cortez
     ###initial_city_coord: -108.74 35.52 Gallup
     ###initial_city_coord: -105.95 35.68 Santa Fe

   The optimal route turns out to be:
     # final coordinates of cities (longitude and latitude)
     ###final_city_coord: -105.95 35.68 Santa Fe
     ###final_city_coord: -106.28 35.89 Los Alamos
     ###final_city_coord: -106.62 35.12 Albuquerque
     ###final_city_coord: -107.84 35.15 Grants
     ###final_city_coord: -107.87 37.29 Durango
     ###final_city_coord: -108.58 37.35 Cortez
     ###final_city_coord: -108.74 35.52 Gallup
     ###final_city_coord: -112.07 33.54 Phoenix
     ###final_city_coord: -106.76 32.34 Las Cruces
     ###final_city_coord: -96.77 32.79 Dallas
     ###final_city_coord: -103.2 34.41 Clovis
     ###final_city_coord: -105.92 35.77 Tesuque
     ###final_city_coord: -105.95 35.68 Santa Fe

Here's a plot of the cost function (energy) versus generation (point in
the calculation at which a new temperature is set) for this problem:


File: gsl-ref.info,  Node: Fast Fourier Transforms,  Next: Discrete Hankel Transforms,  Prev: Simulated Annealing,  Up: Top

Fast Fourier Transforms (FFTs)
******************************

   This chapter describes functions for performing Fast Fourier
Transforms (FFTs).  The library includes radix-2 routines (for lengths
which are a power of two) and mixed-radix routines (which work for any
length).  For efficiency there are separate versions of the routines
for real data and for complex data.  The mixed-radix routines are a
reimplementation of the FFTPACK library by Paul Swarztrauber.  Fortran
code for FFTPACK is available on Netlib (FFTPACK also includes some
routines for sine and cosine transforms but these are currently not
available in GSL).  For details and derivations of the underlying
algorithms consult the document `GSL FFT Algorithms' (*note FFT
References and Further Reading::.)

* Menu:

* Mathematical Definitions::
* Overview of complex data FFTs::
* Radix-2 FFT routines for complex data::
* Mixed-radix FFT routines for complex data::
* Overview of real data FFTs::
* Radix-2 FFT routines for real data::
* Mixed-radix FFT routines for real data::
* FFT References and Further Reading::


File: gsl-ref.info,  Node: Mathematical Definitions,  Next: Overview of complex data FFTs,  Up: Fast Fourier Transforms

Mathematical Definitions
========================

   Fast Fourier Transforms are efficient algorithms for calculating the
discrete fourier transform (DFT),

     x_j = \sum_{k=0}^{N-1} z_k \exp(-2\pi i j k / N)

   The DFT usually arises as an approximation to the continuous fourier
transform when functions are sampled at discrete intervals in space or
time.  The naive evaluation of the discrete fourier transform is a
matrix-vector multiplication W\vec{z}. A general matrix-vector
multiplication takes O(N^2) operations for N data-points.  Fast fourier
transform algorithms use a divide-and-conquer strategy to factorize the
matrix W into smaller sub-matrices, corresponding to the integer
factors of the length N.  If N can be factorized into a product of
integers f_1 f_2 ... f_n then the DFT can be computed in O(N \sum f_i)
operations.  For a radix-2 FFT this gives an operation count of O(N
\log_2 N).

   All the FFT functions offer three types of transform: forwards,
inverse and backwards, based on the same mathematical definitions.  The
definition of the "forward fourier transform", x = FFT(z), is,

     x_j = \sum_{k=0}^{N-1} z_k \exp(-2\pi i j k / N)

and the definition of the "inverse fourier transform", x = IFFT(z), is,

     z_j = {1 \over N} \sum_{k=0}^{N-1} x_k \exp(2\pi i j k / N).

The factor of 1/N makes this a true inverse.  For example, a call to
`gsl_fft_complex_forward' followed by a call to
`gsl_fft_complex_inverse' should return the original data (within
numerical errors).

   In general there are two possible choices for the sign of the
exponential in the transform/ inverse-transform pair. GSL follows the
same convention as FFTPACK, using a negative exponential for the forward
transform.  The advantage of this convention is that the inverse
transform recreates the original function with simple fourier
synthesis.  Numerical Recipes uses the opposite convention, a positive
exponential in the forward transform.

   The "backwards FFT" is simply our terminology for an unscaled
version of the inverse FFT,

     z^{backwards}_j = \sum_{k=0}^{N-1} x_k \exp(2\pi i j k / N).

When the overall scale of the result is unimportant it is often
convenient to use the backwards FFT instead of the inverse to save
unnecessary divisions.


File: gsl-ref.info,  Node: Overview of complex data FFTs,  Next: Radix-2 FFT routines for complex data,  Prev: Mathematical Definitions,  Up: Fast Fourier Transforms

Overview of complex data FFTs
=============================

   The inputs and outputs for the complex FFT routines are "packed
arrays" of floating point numbers.  In a packed array the real and
imaginary parts of each complex number are placed in alternate
neighboring elements.  For example, the following definition of a packed
array of length 6,

     gsl_complex_packed_array data[6] ;

can be used to hold an array of three complex numbers, `z[3]', in the
following way,

     data[0] = Re(z[0])
     data[1] = Im(z[0])
     data[2] = Re(z[1])
     data[3] = Im(z[1])
     data[4] = Re(z[2])
     data[5] = Im(z[2])

A "stride" parameter allows the user to perform transforms on the
elements `z[stride*i]' instead of `z[i]'.  A stride greater than 1 can
be used to take an in-place FFT of the column of a matrix. A stride of
1 accesses the array without any additional spacing between elements.

   The array indices have the same ordering as those in the definition
of the DFT -- i.e. there are no index transformations or permutations of
the data.

   For physical applications it is important to remember that the index
appearing in the DFT does not correspond directly to a physical
frequency.  If the time-step of the DFT is \Delta then the
frequency-domain includes both positive and negative frequencies,
ranging from -1/(2\Delta) through 0 to +1/(2\Delta).  The positive
frequencies are stored from the beginning of the array up to the
middle, and the negative frequencies are stored backwards from the end
of the array.

   Here is a table which shows the layout of the array DATA, and the
correspondence between the time-domain data z, and the frequency-domain
data x.

             index    z               x = FFT(z)
     
             0        z(t = 0)        x(f = 0)
             1        z(t = 1)        x(f = 1/(N Delta))
             2        z(t = 2)        x(f = 2/(N Delta))
             .        ........        ..................
             N/2      z(t = N/2)      x(f = +1/(2 Delta),-1/(2 Delta))
             .        ........        ..................
             N-3      z(t = N-3)      x(f = -3/(N Delta))
             N-2      z(t = N-2)      x(f = -2/(N Delta))
             N-1      z(t = N-1)      x(f = -1/(N Delta))

When N is even the location N/2 contains the most positive and negative
frequencies +1/(2 \Delta), -1/(2 \Delta)) which are equivalent.  If N
is odd then general structure of the table above still applies, but N/2
does not appear.


File: gsl-ref.info,  Node: Radix-2 FFT routines for complex data,  Next: Mixed-radix FFT routines for complex data,  Prev: Overview of complex data FFTs,  Up: Fast Fourier Transforms

Radix-2 FFT routines for complex data
=====================================

   The radix-2 algorithms described in this section are simple and
compact, although not necessarily the most efficient.  They use the
Cooley-Tukey algorithm to compute in-place complex FFTs for lengths
which are a power of 2 -- no additional storage is required.  The
corresponding self-sorting mixed-radix routines offer better
performance at the expense of requiring additional scratch space.

   All these functions are declared in the header file
`gsl_fft_complex.h'.

 - Function: int gsl_fft_complex_radix2_forward
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_transform
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_backward
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_inverse
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
     These functions compute forward, backward and inverse FFTs of
     length N with stride STRIDE, on the packed complex array DATA
     using an in-place radix-2 decimation-in-time algorithm.  The
     length of the transform N is restricted to powers of two.

     The functions return a value of `GSL_SUCCESS' if no errors were
     detected, or one of the following error codes in the case of error.

    `GSL_EDOM'
          The length of the data N is not a power of two.


 - Function: int gsl_fft_complex_radix2_dif_forward
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_dif_transform
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_dif_backward
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
 - Function: int gsl_fft_complex_radix2_dif_inverse
          (gsl_complex_packed_array DATA[], size_t STRIDE, size_t N)
     These are decimation-in-frequency versions of the radix-2 FFT
     functions.


   Here is an example program which computes the FFT of a short pulse
in a sample of length 128.  To make the resulting fourier transform
real the pulse is defined for equal positive and negative times (-10
... 10) (the negative times wrap around the end of the array).

     #include <stdio.h>
     #include <math.h>
     #include <gsl/gsl_errno.h>
     #include <gsl/gsl_fft_complex.h>
     
     #define REAL(z,i) ((z)[2*(i)])
     #define IMAG(z,i) ((z)[2*(i)+1])
     
     int main ()
     {
       int i;
       double data[2*128];
     
       for (i = 0; i < 128; i++)
         {
            REAL(z,i) = 0.0;
            IMAG(z,i) = 0.0;
         }
     
       REAL(data,0) = 1.0;
     
       for (i = 1; i <= 10; i++)
         {
            REAL(data,i) = REAL(data,128-i) = 1.0;
         }
     
       for (i = 0; i < 128; i++)
         {
           printf ("%d %e %e\n", i, REAL(data,i), IMAG(data,i));
         }
       printf ("\n");
     
       gsl_fft_complex_radix2_forward (data, 1, 128);
     
       for (i = 0; i < 128; i++)
         {
           printf ("%d %e %e\n", i, REAL(data,i)/sqrt(128),
                                    IMAG(data,i)/sqrt(128));
         }
     
     }

Note that we have assumed that the program is using the default error
handler (which calls `abort' for any errors).  If you are not using a
safe error handler you would need to check the return status of
`gsl_fft_complex_radix2_forward'.


File: gsl-ref.info,  Node: Mixed-radix FFT routines for complex data,  Next: Overview of real data FFTs,  Prev: Radix-2 FFT routines for complex data,  Up: Fast Fourier Transforms

Mixed-radix FFT routines for complex data
=========================================

   This section describes mixed-radix FFT algorithms for complex data.
The mixed-radix functions work for FFTs of any length.  They are a
reimplementation of the Fortran FFTPACK library by Paul Swarztrauber.
The theory is explained in the review article `Self-sorting Mixed-radix
FFTs' by Clive Temperton.  The routines here use the same indexing
scheme and basic algorithms as FFTPACK.

   The mixed-radix algorithm is based on sub-transform modules - highly
optimized small length FFTs which are combined to create larger FFTs.
There are efficient modules for factors of 2, 3, 4, 5, 6 and 7.  The
modules for the composite factors of 4 and 6 are faster than combining
the modules for 2*2 and 2*3.

   For factors which are not implemented as modules there is a
fall-back to a general length-n module which uses Singleton's method for
efficiently computing a DFT. This module is O(n^2), and slower than a
dedicated module would be but works for any length n.  Of course,
lengths which use the general length-n module will still be factorized
as much as possible.  For example, a length of 143 will be factorized
into 11*13.  Large prime factors are the worst case scenario, e.g. as
found in n=2*3*99991, and should be avoided because their O(n^2)
scaling will dominate the run-time (consult `GSL FFT Algorithms' for
possible ways around this problem).

   The mixed-radix initialization function `gsl_fft_complex_alloc'
returns the list of factors chosen by the library for a given length N.
It can be used to check how well the length has been factorized, and
estimate the run-time.  To a first approximation the run-time scales as
N \sum f_i, where the f_i are the factors of N.  For programs under
user control you may wish to issue a warning that the transform will be
slow when the length is poorly factorized.  If you frequently encounter
data lengths which cannot be factorized using the existing small-prime
modules consult `GSL FFT Algorithms' for details on adding support for
other factors.

   All these functions are declared in the header file
`gsl_fft_complex.h'.

 - Function: gsl_fft_complex_wavetable * gsl_fft_complex_alloc (size_t
          N)
     This function allocates space for a `gsl_fft_complex_wavetable'
     struct, and a scratch area and trigonometric lookup table, both of
     size N complex elements.  The relevant components of the wavetable
     are initialized to point to the newly allocated memory.

     The function initializes WAVETABLE.  It selects a factorization of
     the length N into the implemented subtransforms, storing the
     details of the factorization in WAVETABLE.  Using this
     factorization it then prepares a trigonometric lookup table.

     The wavetable is computed using direct calls to `sin' and `cos',
     for accuracy.  It could be computed faster using recursion
     relations if necessary.  If an application performs many FFTs of
     the same length then computing the wavetable is a one-off overhead
     which does not affect the final throughput.

     The wavetable structure can be used repeatedly for any transform
     of the same length.  The table is not modified by calls to any of
     the other FFT functions.  The same wavetable can be used for both
     forward and backward (or inverse) transforms of a given length.

     The function returns a pointer to the newly allocated
     `gsl_fft_complex_wavetable' if no errors were detected, and 0 in
     the case of error.  The following `gsl_errno' conditions are
     defined for this function:

    `GSL_ENOMEM'
          The requested memory could not be allocated (`malloc' returned
          a null pointer).

    `GSL_EDOM'
          The length of the data N is not a positive integer (i.e. N is
          zero).

    `GSL_EFACTOR'
          The length N could not be factorized (this shouldn't happen).

    `GSL_EFAILED'
          A failure was detected in the wavetable generation.


 - Function: void gsl_fft_complex_free (gsl_fft_complex_wavetable *
          WAVETABLE)
     This function frees the blocks of memory previously allocated by
     `gsl_fft_complex_alloc' and pointed to by the components of
     WAVETABLE.

     The wavetable should be freed if no further FFTs of the same
     length will be needed.

   The functions `gsl_fft_complex_alloc' and `gsl_fft_complex_free' all
operate on a structure `gsl_fft_complex_wavetable'.  This structure
contains internal parameters for the FFT.

   It is not necessary to set any of the members directly except for
advanced usage.  However, it can useful to examine the wavetable
returned by `gsl_fft_complex_alloc'.  For example, the factorization
chosen by `gsl_fft_complex_alloc' is given and can be used to provide
an estimate of the run-time or numerical error.

   Here is the wavetable structure.  It is declared in the header file
`gsl_fft_complex.h'.

 - Data Type: gsl_fft_complex_wavetable
     This is a structure that holds the factorization and pointers to
     the scratch area and trigonometric lookup tables for the mixed
     radix fft algorithm.  It has the following members:

    `size_t n'
          This is the number of complex data points

    `size_t nf'
          This is the number of factors that the length `n' was
          decomposed into.

    `size_t factor[64]'
          This is the array of factors.  Only the first `nf' elements
          are used.

    `gsl_complex * scratch'
          This is a pointer to a scratch area of `n' complex elements,
          capable of holding intermediate copies of the original data
          set.

    `gsl_complex * trig'
          This is a pointer to a preallocated trigonometric lookup
          table of `n' complex elements.

    `gsl_complex * twiddle[64]'
          This is an array of pointers into `trig', giving the twiddle
          factors for each pass.


 - Function: int gsl_fft_complex_forward (gsl_complex_packed_array
          DATA[], size_t STRIDE, size_t N, const gsl_fft_wavetable *
          WAVETABLE)
 - Function: int gsl_fft_complex_transform (gsl_complex_packed_array
          DATA[], size_t STRIDE, size_t N, const gsl_fft_wavetable *
          WAVETABLE)
 - Function: int gsl_fft_complex_backward (gsl_complex_packed_array
          DATA[], size_t STRIDE, size_t N, const
          gsl_fft_complex_wavetable * WAVETABLE)
 - Function: int gsl_fft_complex_inverse (gsl_complex_packed_array
          DATA[], size_t STRIDE, size_t N, const
          gsl_fft_complex_wavetable * WAVETABLE)
     These functions compute forward, backward and inverse FFTs of
     length N with stride STRIDE, on the packed complex array DATA,
     using a mixed radix decimation-in-frequency algorithm.

     The caller must supply a WAVETABLE containing the chosen
     factorization, trigonometric lookup tables and scratch area.  The
     wavetable can be easily prepared using the function
     `gsl_fft_complex_alloc'.

     There is no restriction on the length N.  Efficient modules are
     provided for subtransforms of length 2, 3, 4, 5, 6 and 7.  Any
     remaining factors are computed with a slow, O(n^2), general-n
     module.

     The functions return a value of `0' if no errors were detected,
     and `-1' in the case of error.  The following `gsl_errno'
     conditions are defined for these functions:

    `GSL_EDOM'
          The length of the data N is not a positive integer (i.e. N is
          zero).

    `GSL_EINVAL'
          The length of the data N and the length used to compute the
          given WAVETABLE do not match.

   Here is an example program which computes the FFT of a short pulse
in a sample of length 630 (=2*3*3*5*7) using the mixed-radix algorithm.

     #include <stdio.h>
     #include <math.h>
     #include <gsl/gsl_errno.h>
     #include <gsl/gsl_fft_complex.h>
     
     #define REAL(z,i) ((z)[2*(i)])
     #define IMAG(z,i) ((z)[2*(i)+1])
     
     int main ()
     {
       int i;
       const int n = 630 ;
       double data[2*n];
     
       gsl_fft_complex_wavetable * wavetable;
     
       for (i = 0; i < n; i++)
         {
           REAL(data,i) = 0.0 ;
           IMAG(data,i) = 0.0 ;
         }
     
       data[0].real = 1.0 ;
     
       for (i = 1; i <= 10; i++)
         {
           REAL(data,i) = REAL(data,n-i) = 1.0 ;
         }
     
       for (i = 0; i < n; i++)
         {
           printf ("%d: %e %e\n", i, REAL(data,i), IMAG(data,i));
         }
       printf ("\n");
     
       wavetable = gsl_fft_complex_alloc (n);
     
       for (i = 0; i < wavetable->nf; i++)
         {
            printf("# factor %d: %d\n", i, wavetable->factor[i]);
         }
     
       gsl_fft_complex_forward (data, 1, n, wavetable);
     
       for (i = 0; i < n; i++)
         {
           printf ("%d: %e %e\n", i, REAL(data,i), IMAG(data,i));
         }
     
       gsl_fft_complex_free (wavetable);
     
     }

Note that we have assumed that the program is using the default `gsl'
error handler (which calls `abort' for any errors).  If you are not
using a safe error handler you would need to check the return status of
of all the `gsl' routines.


File: gsl-ref.info,  Node: Overview of real data FFTs,  Next: Radix-2 FFT routines for real data,  Prev: Mixed-radix FFT routines for complex data,  Up: Fast Fourier Transforms

Overview of real data FFTs
==========================

   The functions for real data are similar to those for complex data.
However, there is an important difference between forward and inverse
transforms.  The fourier transform of a real sequence is not real.  It
is a complex sequence with a special symmetry:

     z_k = z_{N-k}^*

A sequence with this symmetry is called "conjugate-complex" or
"half-complex".  This different structure requires different
storage-layouts for the forward transform (from real to half-complex)
and inverse transform (from half-complex back to real).  As a
consequence the routines are divided into two sets: functions in
`gsl_fft_real' which operate on real sequences and functions in
`gsl_fft_halfcomplex' which operate on half-complex sequences.

   Functions in `gsl_fft_real' compute the frequency coefficients of a
real sequence.  The half-complex coefficients c of a real sequence x
are given by fourier analysis,

     c_k = \sum_{j=0}^{N-1} x_k \exp(-2 \pi i j k /N)

Functions in `gsl_fft_halfcomplex' compute inverse or backwards
transforms.  They reconstruct real sequences by fourier synthesis from
their half-complex frequency coefficients, c,

     x_j = {1 \over N} \sum_{k=0}^{N-1} c_k \exp(2 \pi i j k /N)

The symmetry of the half-complex sequence implies that only half of the
complex numbers in the output need to be stored.  The remaining half can
be reconstructed using the half-complex symmetry condition. (This works
for all lengths, even and odd.  When the length is even the middle
value, where k=N/2, is also real).  Thus only N real numbers are
required to store the half-complex sequence, and the transform of a real
sequence can be stored in the same size array as the original data.

   The precise storage arrangements depend on the algorithm, and are
different for radix-2 and mixed-radix routines.  The radix-2 function
operates in-place, which constrain the locations where each element can
be stored.  The restriction forces real and imaginary parts to be stored
far apart.  The mixed-radix algorithm does not have this restriction,
and it stores the real and imaginary parts of a given term in
neighboring locations.  This is desirable for better locality of memory
accesses.


File: gsl-ref.info,  Node: Radix-2 FFT routines for real data,  Next: Mixed-radix FFT routines for real data,  Prev: Overview of real data FFTs,  Up: Fast Fourier Transforms

Radix-2 FFT routines for real data
==================================

   This section describes radix-2 FFT algorithms for real data.  They
use the Cooley-Tukey algorithm to compute in-place FFTs for lengths
which are a power of 2.

   The radix-2 FFT functions for real data are declared in the header
files `gsl_fft_real.h'

 - Function: int gsl_fft_real_radix2_transform (double DATA[], size_t
          STRIDE, size_t N)
     This function computes an in-place radix-2 FFT of length N and
     stride STRIDE on the real array DATA.  The output is a
     half-complex sequence, which is stored in-place.  The arrangement
     of the half-complex terms uses the following scheme: for k < N/2
     the real part of the k-th term is stored in location k, and the
     corresponding imaginary part is stored in location N-k.  Terms
     with k > N/2 can be reconstructed using the symmetry z_k =
     z^*_{N-k}.  The terms for k=0 and k=N/2 are both purely real, and
     count as a special case.  Their real parts are stored in locations
     0 and N/2 respectively, while their imaginary parts which are zero
     are not stored.

     The following table shows the correspondence between the output
     DATA and the equivalent results obtained by considering the input
     data as a complex sequence with zero imaginary part,

          complex[0].real    =    data[0]
          complex[0].imag    =    0
          complex[1].real    =    data[1]
          complex[1].imag    =    data[N-1]
          ...............         ................
          complex[k].real    =    data[k]
          complex[k].imag    =    data[N-k]
          ...............         ................
          complex[N/2].real  =    data[N/2]
          complex[N/2].real  =    0
          ...............         ................
          complex[k'].real   =    data[k]        k' = N - k
          complex[k'].imag   =   -data[N-k]
          ...............         ................
          complex[N-1].real  =    data[1]
          complex[N-1].imag  =   -data[N-1]

   The radix-2 FFT functions for halfcomplex data are declared in the
header file `gsl_fft_halfcomplex.h'.

 - Function: int gsl_fft_halfcomplex_radix2_inverse (double DATA[],
          size_t STRIDE, size_t N)
 - Function: int gsl_fft_halfcomplex_radix2_backward (double DATA[],
          size_t STRIDE, size_t N)
     These functions compute the inverse or backwards in-place radix-2
     FFT of length N and stride STRIDE on the half-complex sequence
     DATA stored according the output scheme used by
     `gsl_fft_real_radix2'.  The result is a real array stored in
     natural order.


