From: Nasser M. Abbasi on
I never used complex variables before in Ada, so for the last 3 hrs I
was learning how to do it. I wrote a simple program, to find the DFT of
an array of 3 elements {1,2,3} (DFT=discrete Fourier transform).

The definition of DFT is one equation with summation, here it is, first
equation you'll see:

http://en.wikipedia.org/wiki/Discrete_Fourier_transform

Since I have not programmed in Ada nor in FORTRAN for a looong time, I
am very rusty, I program in Mathematica and sometimes in matlab these
days, but I wanted to try Ada on complex numbers.

I also wrote a FORTRAN equivalent of the small Ada function. Here is
below the Ada code, and the FORTRAN code. Again, do not scream too much
if it is not good code, I just learned this now, I am sure this can be
improved a lot.

And for comparing, I show the Matlab and the Mathematica output just to
make sure.


====== START ADA ============
--
-- dtf.adb, compiled with GNAT 4.3.4 20090804 (release) 1
-- under CYGWIN 1.7.5
-- gnatmake dft.adb
--
-- ./dft.exe
-- ( 6.00000E+00, 0.00000E+00)
-- (-1.50000E+00, 8.66026E-01)
-- (-1.50000E+00,-8.66025E-01)
-- $


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Complex_Types; use Ada.Numerics.Complex_Types;

with Ada.Numerics; use Ada.Numerics;

with Ada.Numerics.Complex_Elementary_Functions;
use Ada.Numerics.Complex_Elementary_Functions;

with Ada.Complex_Text_IO; use Ada.Complex_Text_IO;

procedure dft is
N : positive := 3;
J : constant complex :=(0.0,1.0); -- SQRT(-1)
X : array(0 .. N-1) of Complex := (others=>(0.0,0.0));
data : array(0 .. N-1) of float :=(1.0,2.0,3.0);

begin
FOR k in X'range LOOP
FOR m in data'range LOOP
X(k) := X(k) + data(m) * exp(- J*(2.0*Pi)/float(N) *
float(m*k) );
END LOOP;
put(X(k)); new_line;
END LOOP;

end dft;
================== END ADA ==============

======= FORTRAN code ===========
! dtf.f90, compiled with GCC 4.3.4
! under CYGWIN 1.7.5
! gfortran -Wall dft.f90
! ./a.exe
! ( 6.0000000 , 0.0000000 )
! ( -1.4999999 , 0.86602557 )
! ( -1.5000005 ,-0.86602497 )
!

PROGRAM dft

IMPLICIT NONE

INTEGER, PARAMETER :: N = 3
COMPLEX, parameter :: J =(0,1)

REAL, parameter :: Pi = ACOS(-1.0)
INTEGER :: k,m
COMPLEX, dimension(N) :: X
REAL, dimension(N) :: data=(/1.0,2.0,3.0/)

DO k=1,N
X(k)=(0,0)
DO m=1,N
X(k) = X(k) + data(m) * EXP(-1.0*J*2.0*Pi/N *(m-1)*(k-1) )
END DO
print *,X(k)

END DO

END PROGRAM dft
==================================

==== Matlab code ====
EDU>> fft([1,2,3])'

ans =

6.0000
-1.5000 - 0.8660i
-1.5000 + 0.8660i
===============================

=== Mathematica ====
In[5]:= Chop[Fourier[{1, 2, 3}, FourierParameters -> {1, -1}]]

Out[5]= {6., -1.5 + 0.8660254037844386*I, -1.5 - 0.8660254037844386*I}
=========================

Conclusion:
I actually liked the Ada implementation more than FORTRAN because:

1. In Ada, I did not have to change the index of m and k in the
summation to reflect the 1-off per the definition of DFT.
DFT starts from 0 to N-1. In Ada, using 'Range and defining the arrays
to go from 0 .. N-1 solved the problem.

2. In Ada, the compiler complained more times more about types being
mixed up. I placed float() around the places it complained about.

3. It actually took me less time to do the Ada function than the FORTRAN
one, even though I am equally not familiar with both at this time :)

ok, this was a fun learning exercise


--Nasser
From: Ludovic Brenta on
On Jun 9, 12:49 pm, "Nasser M. Abbasi" <n...(a)12000.org> wrote:
> I never used complex variables before in Ada, so for the last 3 hrs I
> was learning how to do it. I wrote a simple program, to find the DFT of
> an array of 3 elements {1,2,3} (DFT=discrete Fourier transform).
>
> The definition of DFT is one equation with summation, here it is, first
> equation you'll see:
>
> http://en.wikipedia.org/wiki/Discrete_Fourier_transform
>
> Since I have not programmed in Ada nor in FORTRAN for a looong time, I
> am very rusty, I program in Mathematica and sometimes in matlab these
> days, but I wanted to try Ada on complex numbers.
>
> I also wrote a FORTRAN equivalent of the small Ada function.  Here is
> below the Ada code, and the FORTRAN code.  Again, do not scream too much
> if it is not good code, I just learned this now, I am sure this can be
> improved a lot.
>
> And for comparing, I show the Matlab and the Mathematica output just to
> make sure.
>
> ====== START ADA ============
> --
> -- dtf.adb, compiled with GNAT 4.3.4 20090804 (release) 1
> -- under CYGWIN 1.7.5
> -- gnatmake dft.adb
> --
> -- ./dft.exe
> -- ( 6.00000E+00, 0.00000E+00)
> -- (-1.50000E+00, 8.66026E-01)
> -- (-1.50000E+00,-8.66025E-01)
> -- $
>
> with Ada.Text_IO; use Ada.Text_IO;
> with Ada.Numerics.Complex_Types; use  Ada.Numerics.Complex_Types;
>
> with Ada.Numerics; use  Ada.Numerics;
>
> with Ada.Numerics.Complex_Elementary_Functions;
> use  Ada.Numerics.Complex_Elementary_Functions;
>
> with Ada.Complex_Text_IO; use Ada.Complex_Text_IO;
>
> procedure dft is
>      N : positive := 3;
>      J : constant complex :=(0.0,1.0);  -- SQRT(-1)
>      X : array(0 .. N-1) of Complex  := (others=>(0.0,0.0));
>      data : array(0 .. N-1) of float :=(1.0,2.0,3.0);
>
> begin
>      FOR k in X'range LOOP
>          FOR m in data'range LOOP
>              X(k) := X(k) + data(m) * exp(- J*(2.0*Pi)/float(N) *
> float(m*k) );
>          END LOOP;
>          put(X(k)); new_line;
>      END LOOP;
>
> end dft;
> ================== END ADA ==============
>
> ======= FORTRAN code ===========
> ! dtf.f90, compiled with GCC 4.3.4
> ! under CYGWIN 1.7.5
> ! gfortran -Wall dft.f90
> ! ./a.exe
> ! (  6.0000000    ,  0.0000000    )
> ! ( -1.4999999    , 0.86602557    )
> ! ( -1.5000005    ,-0.86602497    )
> !
>
> PROGRAM dft
>
>    IMPLICIT NONE
>
>    INTEGER, PARAMETER :: N = 3
>    COMPLEX, parameter :: J =(0,1)
>
>    REAL, parameter :: Pi = ACOS(-1.0)
>    INTEGER :: k,m
>    COMPLEX, dimension(N) :: X
>    REAL, dimension(N) :: data=(/1.0,2.0,3.0/)
>
> DO k=1,N
>     X(k)=(0,0)
>     DO m=1,N
>        X(k) = X(k) + data(m) * EXP(-1.0*J*2.0*Pi/N *(m-1)*(k-1) )
>     END DO
>     print *,X(k)
>
> END DO
>
> END PROGRAM dft
> ==================================
>
> ==== Matlab code ====
> EDU>> fft([1,2,3])'
>
> ans =
>
>     6.0000
>    -1.5000 - 0.8660i
>    -1.5000 + 0.8660i
> ===============================
>
> === Mathematica ====
> In[5]:= Chop[Fourier[{1, 2, 3}, FourierParameters -> {1, -1}]]
>
> Out[5]= {6., -1.5 + 0.8660254037844386*I,  -1.5 - 0.8660254037844386*I}
> =========================
>
> Conclusion:
> I actually liked the Ada implementation more than FORTRAN because:
>
> 1. In Ada, I did not have to change the index of m and k in the
> summation to reflect the 1-off per the definition of DFT.
> DFT starts from 0 to N-1. In Ada, using 'Range and defining the arrays
> to go from 0 .. N-1 solved the problem.
>
> 2. In Ada, the compiler complained more times more about types being
> mixed up. I placed float() around the places it complained about.
>
> 3. It actually took me less time to do the Ada function than the FORTRAN
> one, even though I am equally not familiar with both at this time :)
>
> ok, this was a fun learning exercise

You should use constants and named numbers instead of variables
wherever possible; this simplifies your Ada program. Also, i and j are
predefined so you do not need to declare a "new" value for J:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Complex_Types; use Ada.Numerics.Complex_Types;

with Ada.Numerics; use Ada.Numerics;

with Ada.Numerics.Complex_Elementary_Functions;
use Ada.Numerics.Complex_Elementary_Functions;

with Ada.Complex_Text_IO; use Ada.Complex_Text_IO;

procedure dft is
N : constant := 3; -- named number, no conversion to Float needed
X : array(0 .. N-1) of Complex := (others=>(0.0,0.0));
data : constant array(0 .. N-1) of float :=(1.0,2.0,3.0);
Two_Pi_Over_N : constant := 2 * Pi / N;
-- named number, outside the loop, like in ARM 3.3.2(9)
begin
FOR k in X'range LOOP
FOR m in data'range LOOP
X(k) := X(k) + data(m) * exp(- J*Two_Pi_Over_N *
float(m*k) );
END LOOP;
put(X(k)); new_line;
END LOOP;
end dft;

--
Ludovic Brenta.
From: Niklas Holsti on
Nasser M. Abbasi wrote [much snipped]:
> I wrote a simple program, to find the DFT of
> an array of 3 elements {1,2,3} (DFT=discrete Fourier transform).
> I also wrote a FORTRAN equivalent of the small Ada function. Here is
> below the Ada code, and the FORTRAN code.
>
> ====== START ADA ============
> X(k) := X(k) + data(m) * exp(- J*(2.0*Pi)/float(N) *
> float(m*k) );

> ======= FORTRAN code ===========
> X(k) = X(k) + data(m) * EXP(-1.0*J*2.0*Pi/N *(m-1)*(k-1) )

There is an obscure difference in these computations, which can cause
trouble when the data vector is much longer than the N = 3 in the
example. The Ada version may then fail because the product m*k may
overflow the Integer range. It would be safer to write float(m)*float(k).

In the Fortran version, as far as I understand the Fortran rules, the
compiler may choose to multiply the integer subexpressions (m-1) and
(k-1) as integers, and then convert the product to REAL (as is done in
Nasser's Ada version), or the compiler may choose to convert separately
(m-1) to REAL and (k-1) to REAL and use REAL multiplication, as I
suggest above for the Ada code. IIUC it would be safer in Fortran, too,
to prevent integer overflow by explicit conversions of (m-1) and (k-1)
to REAL before multiplication.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
From: Jerry on
On Jun 9, 4:26 am, Ludovic Brenta <ludo...(a)ludovic-brenta.org> wrote:
snip
>      Two_Pi_Over_N : constant := 2 * Pi / N;
>       -- named number, outside the loop, like in ARM 3.3.2(9)
snip
> Ludovic Brenta.

So 2 and N are universal_integer and Pi is probably a universal_real.
I didn't know that one could ever do mixed-mode arithmetic in Ada, but
this is obviously allowed here. By the way, I don't see where in ARM
3.3.2 this mixed operation is described. Line 9 on that ARM page uses
2.0*Ada.Numerics.Pi which is not mixed mode. Is this described
somewhere else?

Jerry
From: Jeffrey R. Carter on
Jerry wrote:
>
> So 2 and N are universal_integer and Pi is probably a universal_real.
> I didn't know that one could ever do mixed-mode arithmetic in Ada, but
> this is obviously allowed here. By the way, I don't see where in ARM
> 3.3.2 this mixed operation is described. Line 9 on that ARM page uses
> 2.0*Ada.Numerics.Pi which is not mixed mode. Is this described
> somewhere else?

In ARM 4.5.5 you'll find

function "*"(Left : root_real; Right : root_integer) return root_real
function "*"(Left : root_integer; Right : root_real) return root_real
function "/"(Left : root_real; Right : root_integer) return root_real

--
Jeff Carter
"I've got to stay here, but there's no reason
why you folks shouldn't go out into the lobby
until this thing blows over."
Horse Feathers
50