Tessendorf's paper

- about Constant_g: Tessendorf talk about gravitational constant (i.e.
  G = 6.673e-11 m^3 / kg s^2) but give a value of 9.8 m.s^2 (i.e. the
  standard gravitational acceleration on Earth).

- about displacement computation: we have a sign problem.


****************************************************************

getopt.c


This file is part of the GNU C Library. There is no real waste compiling
it when using GNU C Library with the same version of getopt, because in
this case, it doesn't define any function (and we use the ones provided
by the system).



****************************************************************


aqua_wave.cpp


The function "void Aqua_Wave::frequency_set(float depth)" compute
equation 15 (or 14 if depth is 0.0).


****************************************************************


aqua_fft.cpp


- about "plan_type":

Type of the FFTW plan used to compute the FFT, from "Estimate", the
fastest to create (MIGHT give the slowest FFT computation) to
"Exhaustive", the slowest to create (MIGHT give the fastest FFT
computation). "Measure" seems to be the right choice.

See FTTW documentation for details.


- about FFT computation:

To compute FFT, we use real to complex forward FFT with input in
[ 0, N [, while we want real or imaginary to real backward one with
input in [ -N / 2, N / 2 [. Let explain.

FFTW provide a real to complex forward FFT (fftw_plan_dft_r2c) which can
"achieve roughly a factor of two improvement in both speed and memory
usage", so this is what we use rather than a complex to complex one.

For an input of size N * M, we get an output of size
(N + 2) / 2 * (M + 2) / 2 with redundancies, so we have to fill the
missing outputs by recopy.

We take the real part of the output for a real to real FFT and the
imaginary part for an imaginary to real one (which is in fact a real to
imaginary one, but we just have to change some signs).

The difference between forward and backward FFT is that the signs of the
imaginary part of the output are inversed. This is not a big constraint.

Finally, as the input is in [ -N / 2, N / 2 [ and not in [ 0, N [, we
have to swap some outputs and change some signs (or don't change any
signs but swap input and output the same way).


So, logically, to get the right output in "reals_array" from the
fftw_plan_dft_r2c output in "array", we should use this:

void
copy_array_to_reals_array(float **reals_array,
			  enum aqua_fft_input_type input_type)
{
  /*  fill reals_array with "input_type" part of "array"  */

  int i, j;

  /*  get the first half of "reals_array" from "array"  */
  for (i = 0; i < size_x; i++)
    {
      for (j = 0; j < array_width; j++)
        {
 	  reals_array[i][j] = array[i * array_width + j][input_type];
 	}
    }

  Z ->                 Z ->
X  --------------    X  -----------------------
| | X| X| X| X| X|   | | X| X| X| X| X|  |  |  |
V |--------------|   V |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X| --> | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
  |--------------|     |-----------------------|     
  | X| X| X| X| X|     | X| X| X| X| X|  |  |  |     
   --------------       -----------------------     
X: modified elements
x: non modified elements
size_x = size_z = 8
array_width = (size_z + 2) / 2 = 5


  /*  arrange "reals_array" to get the second half  */
  for (j = array_width; j < size_z; j++)
    {
      reals_array[0][j] = reals_array[0][size_z - j];
    }

       -----------------
      |   ___________   |
      |  |    ____   |  |
  Z ->|  |   |    V  V  V
X  -----------------------
| | x|X1|X2|X3| x|X3|X2|X1|
V |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
  |-----------------------|
  | x| x| x| x| x|  |  |  |
   -----------------------


  for (i = 1; i < size_x; i++)
    {
      for (j = array_width; j < size_z; j++)
 	{
 	  reals_array[i][j] = reals_array[size_x - i][size_z - j];
 	}
    }

  Z ->
X  -----------------------
| | x| x| x| x| x| x| x| x|
V |-----------------------|
  | x|X1|X2|X3| x|X9|X8|X7| ^
  |-----------------------| |
  | x|X4|X5|X6| x|Xx|Xx|Xx| |
  |-----------------------| |
  | x|Xx|Xx|Xx| x|Xx|Xx|Xx| |
  |-----------------------| |
  | x|Xx|Xx|Xx| x|Xx|Xx|Xx| |
  |-----------------------| |
  | x|Xx|Xx|Xx| x|Xx|Xx|Xx| |
  |-----------------------| |
  | x|Xx|Xx|Xx| x|X6|X5|X4| |
  |-----------------------| |
  | x|X7|X8|X9| x|X3|X2|X1| |
   -----------------------


  /*
    For imaginary input, we need to change the sign of some output.
    Making it this way we get backward FFT.
  */
  if (input_type == Imaginary)
    {
      for (i = 0; i < size_x; i++)
 	{
 	  for (j = array_width; j < size_z; j++)
 	    {
 	      reals_array[i][j] = - reals_array[i][j];
 	    }
 	}
    }

  Z ->
X  -----------------------
| | x| x| x| x| x|-X|-X|-X|
V |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
  |-----------------------|
  | x| x| x| x| x|-X|-X|-X|
   -----------------------


  /*
    arrange reals_array, as the input of the FFT should be in [0, N [,
    not in [ -N/2, N/2 [
  */
  arrange(points_x, points_z, reals_array);
}


void
arrange(int size_x, int size_z, float **reals_array)
{
  const int size_x_by_two = size_x / 2;
  const int size_z_by_two = size_z / 2;

  int i, j;


  for (i = 0; i < size_x_by_two; i++)
    {
      for (j = 0; j < size_z_by_two; j++)
	{
	  element_swap(reals_array[i][j],
		       reals_array[i + size_x_by_two][j + size_z_by_two]);
	}
    }
  for (i = size_x_by_two; i <  size_x; i++)
    {
      for (j = 0; j < size_z_by_two; j++)
	{
	  element_swap(reals_array[i][j],
		       reals_array[i - size_x_by_two][j + size_z_by_two]);
	}
    }

  Z ->                        Z ->                    
X  ---------------------    X  ---------------------  
| |          |          |   | |          |          | 
V |          |          |   V |          |          | 
  |    X1    |    X2    |     |    X4    |    X3    | 
  |          |          |     |          |          | 
  |          |          |     |          |          | 
  |---------------------| --> |---------------------| 
  |          |          |     |          |          | 
  |          |          |     |          |          | 
  |    X3    |    X4    |     |    X2    |    X1    | 
  |          |          |     |          |          | 
  |          |          |     |          |          | 
   ---------------------       ---------------------  


   /*  change some signs  */
   for (i = 0; i <  size_x; i += 2)
     {
       for (j = 0; j < size_z; j += 2)
	 {
	   reals_array[i][j + 1] = - reals_array[i][j + 1];
	   reals_array[i + 1][j] = - reals_array[i + 1][j];
	 }
     }

  Z ->
X  -----------------------
| | x|-X| x|-X| x|-X| x|-X|
V |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
   -----------------------

}


void
element_swap(float &element1, float &element2)
{
  float temp;

  temp = element1;
  element1 = element2;
  element2 = temp;
}


To reduce time consumption, we have to avoid call to "element_swap()"
and directly put elements at the right place, (unfortunately, this
obscure the code). So we use this instead:

void
copy_array_to_reals_array(float **reals_array,
			  enum aqua_fft_input_type input_type)
{
  /*  fill reals_array with "input_type" part of "array"  */

  /*  This is a macro. This is BAD(TM). Don't do this at home, kids. */
#define ARRAY(x, z) array[x * array_width + z][input_type]

  int i, j;

  for (i = 0; i < size_x_by_two; i++)
    {
      reals_array[i + size_x_by_two][size_z_by_two] = ARRAY(i, 0);
      reals_array[i + size_x_by_two][0] = ARRAY(i, size_z_by_two);
    }

  Z ->                 Z ->                       
X  --------------    X  -----------------------   
| |X1|  |  |  |X5|   | |  |  |  |  |  |  |  |  |  
V |---------------   V |-----------------------|  
  |X2|  |  |  |X6|     |  |  |  |  |  |  |  |  |  
  |---------------     |-----------------------|  
  |X3|  |  |  |X7|     |  |  |  |  |  |  |  |  |  
  |---------------     |-----------------------|  
  |X4|  |  |  |X8| --> |  |  |  |  |  |  |  |  |  
  |---------------     |-----------------------|  
  |  |  |  |  |  |     |X5|  |  |  |X1|  |  |  |  
  |---------------     |-----------------------|  
  |  |  |  |  |  |     |X6|  |  |  |X2|  |  |  |  
  |---------------     |-----------------------|  
  |  |  |  |  |  |     |X7|  |  |  |X3|  |  |  |  
  |---------------     |-----------------------|  
  |  |  |  |  |  |     |X8|  |  |  |X4|  |  |  |  
   --------------       -----------------------  


  for (i = size_x_by_two; i < size_x; i++)
    {
      reals_array[i - size_x_by_two][size_z_by_two] = ARRAY(i, 0);
      reals_array[i - size_x_by_two][0] = ARRAY(i, size_z_by_two);
    }

  Z ->                 Z ->                       
X  --------------    X  -----------------------   
| | x|  |  |  | x|   | |X5|  |  |  |X1|  |  |  |  
V |---------------   V |-----------------------|  
  | x|  |  |  | x|     |X6|  |  |  |X2|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     |X7|  |  |  |X3|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x| --> |X8|  |  |  |X4|  |  |  |  
  |---------------     |-----------------------|  
  |X1|  |  |  |X5|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  |X2|  |  |  |X6|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  |X3|  |  |  |X7|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  |X4|  |  |  |X8|     | x|  |  |  | x|  |  |  |  
   --------------       -----------------------  


  for (j = 1; j < size_z_by_two; j++)
    {
      reals_array[size_x_by_two][j + size_z_by_two] = ARRAY(0, j);
      reals_array[size_x_by_two][size_z_by_two - j] = ARRAY(0, j);
      reals_array[0][j + size_z_by_two] = ARRAY(size_x_by_two, j);
      reals_array[0][size_z_by_two - j] = ARRAY(size_x_by_two, j);
    }

  Z ->                 Z ->                       
X  --------------    X  -----------------------   
| | x|X1|X2|X3| x|   | | x|X6|X5|X4| x|X4|X5|X6|  
V |---------------   V |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x| --> | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  | x|X4|X5|X6| x|     | x|X3|X2|X1| x|X1|X2|X3|  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|  |  |  |  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|  |  |  |  
   --------------       -----------------------  


  for (i = 1; i < size_x_by_two; i++)
    {
      for (j = 1; j < size_z_by_two; j++)
	{
	  reals_array[i + size_x_by_two][j + size_z_by_two] = ARRAY(i, j);
	  reals_array[size_x_by_two - i][size_z_by_two - j] = ARRAY(i, j);
	}
    }

  Z ->                 Z ->                       
X  --------------    X  -----------------------   
| | x| x| x| x| x|   | | x| x| x| x| x| x| x| x|  
V |---------------   V |-----------------------|  
  | x|X1|X2|X3| x|     | x|X9|X8|X7| x|  |  |  |  
  |---------------     |-----------------------|  
  | x|X4|X5|X6| x|     | x|X6|X5|X4| x|  |  |  |  
  |---------------     |-----------------------|  
  | x|X7|X8|X9| x| --> | x|X3|X2|X1| x|  |  |  |  
  |---------------     |-----------------------|  
  | x| x| x| x| x|     | x| x| x| x| x| x| x| x|  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|X1|X2|X3|  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|X4|X5|X6|  
  |---------------     |-----------------------|  
  | x|  |  |  | x|     | x|  |  |  | x|X7|X8|X9|  
   --------------       -----------------------  


  for (i = size_x_by_two + 1; i < size_x; i++)
    {
      for (j = 1; j < size_z_by_two; j++)
	{
	  reals_array[i - size_x_by_two][j + size_z_by_two] = ARRAY(i, j);
	  reals_array[size_x + size_x_by_two - i][size_z_by_two - j] =
	    ARRAY(i, j);
	}
    }

  Z ->                 Z ->                       
X  --------------    X  -----------------------   
| | x| x| x| x| x|   | | x| x| x| x| x| x| x| x|  
V |---------------   V |-----------------------|  
  | x| x| x| x| x|     | x| x| x| x| x|X1|X2|X3|  
  |---------------     |-----------------------|  
  | x| x| x| x| x|     | x| x| x| x| x|X4|X5|X6|  
  |---------------     |-----------------------|  
  | x| x| x| x| x| --> | x| x| x| x| x|X7|X8|X9|  
  |---------------     |-----------------------|  
  | x| x| x| x| x|     | x| x| x| x| x| x| x| x|  
  |---------------     |-----------------------|  
  | x|X1|X2|X3| x|     | x|X9|X8|X7| x| x| x| x|  
  |---------------     |-----------------------|  
  | x|X4|X5|X6| x|     | x|X6|X5|X4| x| x| x| x|  
  |---------------     |-----------------------|  
  | x|X7|X8|X9| x|     | x|X3|X2|X1| x| x| x| x|  
   --------------       -----------------------  


   /*  change some signs  */
   for (i = 0; i <  size_x; i += 2)
     {
       for (j = 0; j < size_z; j += 2)
	 {
	   reals_array[i][j + 1] = - reals_array[i][j + 1];
	   reals_array[i + 1][j] = - reals_array[i + 1][j];
	 }
     }

  Z ->
X  -----------------------
| | x|-X| x|-X| x|-X| x|-X|
V |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
  |-----------------------|
  | x|-X| x|-X| x|-X| x|-X|
  |-----------------------|
  |-X| x|-X| x|-X| x|-X| x|
   -----------------------


  /*
    For imaginary input, we need to change the sign of some output.
    Making it this way we get backward FFT.
  */
  if (input_type == Imaginary)
    {
      for (i = 0; i <  size_x; i++)
	{
	  for (j = 1; j < size_z_by_two; j++)
	    {
	      reals_array[i][j] = - reals_array[i][j];
	    }
	}
    }

  Z ->
X  -----------------------
| | x|-X|-X|-X| x| x| x| x|
V |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
  |-----------------------|
  | x|-X|-X|-X| x| x| x| x|
   -----------------------


  /*  please keep this place as clean as you found it  */
#undef ARRAY
}
