Normal view

Before yesterdayNews from the Ada programming language world

The problem with π (iv) – Fortran to Ada

18 January 2023 at 16:03

The Fortran program can also be translated to Ada. Below is the Ada program. It contains some code to output the resulting value of pi to the text file `piCalc1000ADA.txt`. In this code `a` is a “dynamic” array of integers, which is allocated using a `declare` block. In reality `a` is just of type `pia`, declared at a later point in the program.

```with ada.Text_IO; use Ada.Text_IO;

procedure piSpigotDYN is

n, len : integer;
q, x, nines, predigit : integer;
type pia is array(integer range <>) of integer;
infp : file_type;

begin
n := 1000;
len := 10 * n / 3;

declare
a : pia(1..len);
begin

a := (1..len => 2);
nines := 0;
predigit := 0;

for j in 1..n loop
q := 0;
for i in reverse 1..len loop
x := 10 * a(i) + q * i;
a(i) := x mod (2*i-1);
q := x / (2*i-1);
end loop;
a(1) := q mod 10;
q := q / 10;
if q = 9 then
nines := nines + 1;
elsif q = 10 then
put(infp,predigit+1,width=>1);
for k in 1..nines loop
put(infp,0,width=>1);
end loop;
predigit := 0;
nines := 0;
else
put(infp,predigit,width=>1);
predigit := q;
if nines /= 0 then
for k in 1..nines loop
put(infp,9,width=>1);
nines := 0;
end loop;
end if;
end if;
end loop;
put(infp,predigit,width=>1);

close(infp);
end;
end piSpigotDYN;
```
• 18 January 2023 at 16:03

The problem with π (iii) – Pascal to Fortran

13 January 2023 at 15:31

A while back I posted on the Spigot algorithm in Pascal (and C) for calculating the first 1000 decimal places of π. Now converting it to Fortran is quite easy.

```program piSpigot

integer :: n, len
integer :: i, j, k, q, x, nines, predigit
integer, dimension(3500) :: a

n = 1000
len = (10 * n) / 3

a = 2
nines = 0
predigit = 0
999 format(I1)

do j = 1,n
q = 0
do i = len,1,-1
x = 10 * a(i) + q * i
a(i) = mod(x,2*i-1)
q = x / (2*i-1)
end do
a(1) = mod(q,10)
q = q / 10
if (q == 9) then
nines = nines + 1
elseif (q == 10) then
do k = 1, nines
end do
predigit = 0
nines = 0
else
predigit = q
if (nines /= 0) then
do k = 1,nines
nines = 0
end do
end if
end if
end do

end program piSpigot
```

This algorithm is good, but it could be improved upon by making the array dynamic. All that really involves is reworking some code at the top of the program. In the snippet of code below, the array `a` is made allocatable (Line 5), I/O is added to prompt for the number of decimal points required to be calculated, and then on Line 11 the space for `a` is allocated. At the end of the program, the memory is deallocated.

```program piSpigot

integer :: n, len
integer :: i, j, k, q, x, nines, predigit
integer, dimension(:), allocatable :: a

write(*,*) 'Number of decimal points? '
len = (10 * n) / 3

allocate(a(len))
...
deallocate(a)
end program piSpigot
```
• 13 January 2023 at 15:31

Programming made easy – nested loops

1 May 2020 at 13:21

We’re not quite done with loops yet. There are still a few things to learn, although some can be left for later. There are certain situations where it is appropriate to use a loop inside another loop. Such a loop is called a nested loop. A nested loop is executed, essentially, from the inside out. Each loop is like a layer and has its own loop control, its own condition and its own loop body. Below is a schematic of three nested loops.

There are many different kinds of nested loops, and they are largely dependent on the underlying algorithm. Below are some examples of the types of nested loops that are possible.

We will consider how a nested loop can be used to create a times table. It basically works by iterating the inner loop 12 times for every iteration of the outer loop. So, 12 × 12 = 144 iterations. The outer loop is highlighted in blue, and the inner loop in red. Here is a sample output:

``` 1   2   3   4   5   6   7   8   9  10  11  12
2   4   6   8  10  12  14  16  18  20  22  24
3   6   9  12  15  18  21  24  27  30  33  36
4   8  12  16  20  24  28  32  36  40  44  48
5  10  15  20  25  30  35  40  45  50  55  60
6  12  18  24  30  36  42  48  54  60  66  72
7  14  21  28  35  42  49  56  63  70  77  84
8  16  24  32  40  48  56  64  72  80  88  96
9  18  27  36  45  54  63  72  81  90  99 108
10  20  30  40  50  60  70  80  90 100 110 120
11  22  33  44  55  66  77  88  99 110 121 132
12  24  36  48  60  72  84  96 108 120 132 144```

```with ada.Text_IO; use Ada.Text_IO;
procedure nested is
begin
for x in 1..12 loop
for y in 1..12 loop
put(x*y, width=>4);
end loop;
new_line;
end loop;
end nested;```

Fortran

```program nested
integer :: x, y
do x = 1, 12
do y = 1, 12
10 format(I4)
end do
write(*,*)
end do
end program nested```

C

```#include <stdio.h>
int main(void){
int x, y;
for (x=1; x<=12; x=x+1)
{
for (y=1; y<=12; y=y+1)
printf("%4d", x*y);
printf("\n");
}
return 0;
}```

Julia

```for x = 1:12
for y = 1:12
@printf("%4d", x*y)
end
println()
end
println(h)```

spqr

• 1 May 2020 at 13:21

Programming made easy – loops (iii)

27 April 2020 at 13:44

There are of course other loops. These loops are normally used when the number of times a loop iterates isn’t known. These type of loops generally use some form of condition to control the loop. The most prominent type of loop is the while loop. A while loop checks a condition, and if true, processes the code in the loop body, otherwise it exists the loop. Unlike the for loop, which controls the values of the loop index in terms of updating its value, in the loops like while, this process must be added, i.e. the value of i is given the value 1, before the loop is activated, and its value is incremented within the loop body.

We will consider some of these loops using the same Harmonic series, this time in increasing order. The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.

Fortran

```program harmonic
integer :: n, i
real :: h

h = 0
i = 1
do while (i <= n)
h = h + 1.0/i
i = i + 1
end do
write(*,*) h
end program harmonic```

Here the index variable, i, must be initiated to the value 1 before the loop begins, and incremented within the loop. The condition states that the loop continues while the value of i is less than or equal to n, i.e. (i <= n) . Fortran also provides a more generic do/end do loop.

C

```#include <stdio.h>

int main(void){
int i, n;
float h;

scanf("%d", &n);
printf("%d\n", n);
h = 0.0;
i = 1;
while (i <= n){
h = h + 1.0/i;
i = i + 1;
}
printf("%lf\n", h);
return 0;
}```

In the C version, the structure is almost the same, except that the do while of Fortran has been replace with a simple while. With the addition of the statement to increment the value of i, the loop “contents” are now enclosed within { and }. C also has another loop, the do/while() loop, that performs the loop once, then evaluates the condition at the end.

```with ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure harmonic is
n, i : integer;
h : float;
begin
get(n);
h := 0.0;
i := 1;
while i <= n loop
h := h + 1.0/float(i);
i := i + 1;
end loop;
put(h);
end harmonic;```

In Ada, the while loop looks similar to that of the other to Fortran and C, it is just subtleties in syntax that set them apart. Here there are no parenthesis around the condition. Also note that in the for loop, the index variable, i, did not have to be declared, but here it does. Ada also provides a generic loop/end loop loop.

Julia

```n = parse(Int64, chomp(readline()))
println(n)
h = 0
i = 1
while i <= n
h = h + 1.0/i
i = i + 1
end
println(h)```

Same deal here. Similar to Ada, except the loop keyword after the condition isn’t needed. There are only two loops in Julia.

As you can see, over four languages, the only thing that fundamentally changes is the basic syntax of the loop.

spqr

• 27 April 2020 at 13:44

Programming made easy – loops (ii)

24 April 2020 at 14:39

With the basics of for loops, let’s look at an example of an actual program which calculates the Harmonic series, which is an infinite series of the form:

h(n) = 1 + 1/2 + 1/3 + … + 1/n

The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.  For interest sake, the loops are presented in reverse, i.e. 1/n + 1/(n-1) + … + 1, as it illustrates clearly how each language deals with the simple issue of a decreasing index. In each case the starting value of the index variable i is n, and the ending value is 1. Here it is the algorithm for the Harmonic series depicted visually, clearly showing the role of the loop:

Fortran

```program harmonic
integer :: n, i
real :: h

h = 0
do i = n,1,-1
h = h + 1.0/i
end do
write(*,*) h
end program harmonic```

Here the third item (the modifier) in the Fortran loop denotes the type of change to the loop index, in this case, a decrease by 1. In a  normal loop incrementing by 1, the modifier can be omitted.

C

```#include <stdio.h>

int main(void){
int i, n;
float h;

scanf("%d", &n);
printf("%d\n", n);
h = 0.0;
for (i=n; i>=1; i=i-1)
h = h + 1.0/i;
printf("%lf\n", h);
return 0;
}```

In the C version, the loop index is decremented using the statement i=i–1. For more than one statement after the for loop definition, the statements would have to be encapsulated in { and }.

```with ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure harmonic is
n : integer;
h : float;
begin
get(n);
h := 0.0;
for i in reverse 1..n loop
h := h + 1.0/float(i);
end loop;
put(h);
end harmonic;```

In Ada, the keyword reverse is used to specify a loop will be decreasing in value.

Julia

```n = parse(Int64, chomp(readline()))
println(n)
h = 0
for i = n:-1:1
h = h + 1.0/i
end
println(h)```

Here the index modifier is placed in the centre, n:-1:1, implying i has the values n to 1, modified by -1 each loop iteration. In a  normal loop incrementing by 1, the modifier can be omitted.

spqr

• 24 April 2020 at 14:39

Programming made easy – loops (i)

23 April 2020 at 19:53

Humans are, by nature, repetitive beings. Watch the Star Trek: TNG episode “Cause and Effect”, and you will quickly understand what a loop is as the Enterprise is caught in a causality time loop. There are also times when programs must do a task more than once. If the repetition is limited to some countable number of recurrences with a foreseeable end then it is called a loop. And if, at least in the perception of the individual who is experiencing a certain situation, there is no end in sight then one is talking about endless or infinite loops. All of the above can be desirable or not. Here is a visual illustration:

The code in the program moves linearly from statement A, until it encounters a loop. At the start of the loop, the loop control tests some condition. If the condition is true, then the loop activates the piece of code (made up of one or more statements) in what is called the loop body. When that code is done the loop returns to the loop control, and the process starts all over. If the condition in the loop control becomes false, nothing happens, and the program ends the loop, and continues on to statement B. There is also a possibility that the first time into the loop, the condition becomes false, and in that case the loop is bypassed.

Loops are structures that allow for repetition – repeating an activity a number of times. There are different kinds of repetition:

1. Loops where the number of repetitions is known before the loop activates.
2. Loops where the number of repetitions isn’t known, and is controlled by some condition.
3. Loops that are infinite, i.e. could continue to infinity and beyond.

The best example of the first case encountered in most languages is the for loop. Here we use a variable called a loop index to control the loop. Each time a loop loops it is called an iteration. So if the loop index is x, and it repeats 100 times, then x will begin with a value of 1, and increment by 1 each iteration, until x reaches 100. In Julia this is easily achieved in the following manner (in this case the loop simply prints out each value of x):

```for x = 1:100
println(x)
end```

In Ada it takes a similar format (the printing part is a little different, but just ignore that bit):

```for x in 1..100 loop
put(x);
new_line;
end loop;```

Ada uses the keyword loop to signify it as a loop. Fortran also uses a similar construct, but has never used the for loop, opting instead for the keyword do. Same concept, different name.

```do x = 1, 100
write(*,*) x
end do```

C also uses a for loop, although it can be somewhat more convoluted:

```for (x=1; x<=100; x=x+1)
printf("%d\n",x);```

All have their varied syntax, but achieve the same goal – a known number of iterations.

spqr

• 23 April 2020 at 19:53

Programming made easy – nested loops

1 May 2020 at 13:21

We’re not quite done with loops yet. There are still a few things to learn, although some can be left for later. There are certain situations where it is appropriate to use a loop inside another loop. Such a loop is called a nested loop. A nested loop is executed, essentially, from the inside out. Each loop is like a layer and has its own loop control, its own condition and its own loop body. Below is a schematic of three nested loops.

There are many different kinds of nested loops, and they are largely dependent on the underlying algorithm. Below are some examples of the types of nested loops that are possible.

We will consider how a nested loop can be used to create a times table. It basically works by iterating the inner loop 12 times for every iteration of the outer loop. So, 12 × 12 = 144 iterations. The outer loop is highlighted in blue, and the inner loop in red. Here is a sample output:

``` 1   2   3   4   5   6   7   8   9  10  11  12
2   4   6   8  10  12  14  16  18  20  22  24
3   6   9  12  15  18  21  24  27  30  33  36
4   8  12  16  20  24  28  32  36  40  44  48
5  10  15  20  25  30  35  40  45  50  55  60
6  12  18  24  30  36  42  48  54  60  66  72
7  14  21  28  35  42  49  56  63  70  77  84
8  16  24  32  40  48  56  64  72  80  88  96
9  18  27  36  45  54  63  72  81  90  99 108
10  20  30  40  50  60  70  80  90 100 110 120
11  22  33  44  55  66  77  88  99 110 121 132
12  24  36  48  60  72  84  96 108 120 132 144```

```with ada.Text_IO; use Ada.Text_IO;
procedure nested is
begin
for x in 1..12 loop
for y in 1..12 loop
put(x*y, width=>4);
end loop;
new_line;
end loop;
end nested;```

Fortran

```program nested
integer :: x, y
do x = 1, 12
do y = 1, 12
10 format(I4)
end do
write(*,*)
end do
end program nested```

C

```#include <stdio.h>
int main(void){
int x, y;
for (x=1; x<=12; x=x+1)
{
for (y=1; y<=12; y=y+1)
printf("%4d", x*y);
printf("\n");
}
return 0;
}```

Julia

```for x = 1:12
for y = 1:12
@printf("%4d", x*y)
end
println()
end
println(h)```

spqr

• 1 May 2020 at 13:21

Programming made easy – loops (iii)

27 April 2020 at 13:44

There are of course other loops. These loops are normally used when the number of times a loop iterates isn’t known. These type of loops generally use some form of condition to control the loop. The most prominent type of loop is the while loop. A while loop checks a condition, and if true, processes the code in the loop body, otherwise it exists the loop. Unlike the for loop, which controls the values of the loop index in terms of updating its value, in the loops like while, this process must be added, i.e. the value of i is given the value 1, before the loop is activated, and its value is incremented within the loop body.

We will consider some of these loops using the same Harmonic series, this time in increasing order. The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.

Fortran

```program harmonic
integer :: n, i
real :: h

h = 0
i = 1
do while (i <= n)
h = h + 1.0/i
i = i + 1
end do
write(*,*) h
end program harmonic```

Here the index variable, i, must be initiated to the value 1 before the loop begins, and incremented within the loop. The condition states that the loop continues while the value of i is less than or equal to n, i.e. (i <= n) . Fortran also provides a more generic do/end do loop.

C

```#include <stdio.h>

int main(void){
int i, n;
float h;

scanf("%d", &n);
printf("%d\n", n);
h = 0.0;
i = 1;
while (i <= n){
h = h + 1.0/i;
i = i + 1;
}
printf("%lf\n", h);
return 0;
}```

In the C version, the structure is almost the same, except that the do while of Fortran has been replace with a simple while. With the addition of the statement to increment the value of i, the loop “contents” are now enclosed within { and }. C also has another loop, the do/while() loop, that performs the loop once, then evaluates the condition at the end.

```with ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure harmonic is
n, i : integer;
h : float;
begin
get(n);
h := 0.0;
i := 1;
while i <= n loop
h := h + 1.0/float(i);
i := i + 1;
end loop;
put(h);
end harmonic;```

In Ada, the while loop looks similar to that of the other to Fortran and C, it is just subtleties in syntax that set them apart. Here there are no parenthesis around the condition. Also note that in the for loop, the index variable, i, did not have to be declared, but here it does. Ada also provides a generic loop/end loop loop.

Julia

```n = parse(Int64, chomp(readline()))
println(n)
h = 0
i = 1
while i <= n
h = h + 1.0/i
i = i + 1
end
println(h)```

Same deal here. Similar to Ada, except the loop keyword after the condition isn’t needed. There are only two loops in Julia.

As you can see, over four languages, the only thing that fundamentally changes is the basic syntax of the loop.

spqr

• 27 April 2020 at 13:44

Programming made easy – loops (ii)

24 April 2020 at 14:39

With the basics of for loops, let’s look at an example of an actual program which calculates the Harmonic series, which is an infinite series of the form:

h(n) = 1 + 1/2 + 1/3 + … + 1/n

The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.  For interest sake, the loops are presented in reverse, i.e. 1/n + 1/(n-1) + … + 1, as it illustrates clearly how each language deals with the simple issue of a decreasing index. In each case the starting value of the index variable i is n, and the ending value is 1. Here it is the algorithm for the Harmonic series depicted visually, clearly showing the role of the loop:

Fortran

```program harmonic
integer :: n, i
real :: h

h = 0
do i = n,1,-1
h = h + 1.0/i
end do
write(*,*) h
end program harmonic```

Here the third item (the modifier) in the Fortran loop denotes the type of change to the loop index, in this case, a decrease by 1. In a  normal loop incrementing by 1, the modifier can be omitted.

C

```#include <stdio.h>

int main(void){
int i, n;
float h;

scanf("%d", &n);
printf("%d\n", n);
h = 0.0;
for (i=n; i>=1; i=i-1)
h = h + 1.0/i;
printf("%lf\n", h);
return 0;
}```

In the C version, the loop index is decremented using the statement i=i–1. For more than one statement after the for loop definition, the statements would have to be encapsulated in { and }.

```with ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure harmonic is
n : integer;
h : float;
begin
get(n);
h := 0.0;
for i in reverse 1..n loop
h := h + 1.0/float(i);
end loop;
put(h);
end harmonic;```

In Ada, the keyword reverse is used to specify a loop will be decreasing in value.

Julia

```n = parse(Int64, chomp(readline()))
println(n)
h = 0
for i = n:-1:1
h = h + 1.0/i
end
println(h)```

Here the index modifier is placed in the centre, n:-1:1, implying i has the values n to 1, modified by -1 each loop iteration. In a  normal loop incrementing by 1, the modifier can be omitted.

spqr

• 24 April 2020 at 14:39

Programming made easy – loops (i)

23 April 2020 at 19:53

Humans are, by nature, repetitive beings. Watch the Star Trek: TNG episode “Cause and Effect”, and you will quickly understand what a loop is as the Enterprise is caught in a causality time loop. There are also times when programs must do a task more than once. If the repetition is limited to some countable number of recurrences with a foreseeable end then it is called a loop. And if, at least in the perception of the individual who is experiencing a certain situation, there is no end in sight then one is talking about endless or infinite loops. All of the above can be desirable or not. Here is a visual illustration:

The code in the program moves linearly from statement A, until it encounters a loop. At the start of the loop, the loop control tests some condition. If the condition is true, then the loop activates the piece of code (made up of one or more statements) in what is called the loop body. When that code is done the loop returns to the loop control, and the process starts all over. If the condition in the loop control becomes false, nothing happens, and the program ends the loop, and continues on to statement B. There is also a possibility that the first time into the loop, the condition becomes false, and in that case the loop is bypassed.

Loops are structures that allow for repetition – repeating an activity a number of times. There are different kinds of repetition:

1. Loops where the number of repetitions is known before the loop activates.
2. Loops where the number of repetitions isn’t known, and is controlled by some condition.
3. Loops that are infinite, i.e. could continue to infinity and beyond.

The best example of the first case encountered in most languages is the for loop. Here we use a variable called a loop index to control the loop. Each time a loop loops it is called an iteration. So if the loop index is x, and it repeats 100 times, then x will begin with a value of 1, and increment by 1 each iteration, until x reaches 100. In Julia this is easily achieved in the following manner (in this case the loop simply prints out each value of x):

```for x = 1:100
println(x)
end```

In Ada it takes a similar format (the printing part is a little different, but just ignore that bit):

```for x in 1..100 loop
put(x);
new_line;
end loop;```

Ada uses the keyword loop to signify it as a loop. Fortran also uses a similar construct, but has never used the for loop, opting instead for the keyword do. Same concept, different name.

```do x = 1, 100
write(*,*) x
end do```

C also uses a for loop, although it can be somewhat more convoluted:

```for (x=1; x<=100; x=x+1)
printf("%d\n",x);```

All have their varied syntax, but achieve the same goal – a known number of iterations.

spqr

• 23 April 2020 at 19:53