# Ada 2005 access type

I am trying to solve a differential equation with Euler's method using the technique employed with the access type shown in *Ben Ari second editions of Ada for Software Engineers*, Section 13.6.1 starting on Page 263.

I have modified the differential equation given in the book to dy/dx = 2*x*y with Initial Condition y(x=1) = 1. The increment is h = 0.1 and I have to find output the values of y(1), y(1.1), y(1.2), y(1.3), y(1.4) and y(1.5).

There are 3 Ada files: diff.adb which is the main file, euler.ads and euler.adb.

The file **diff.adb** is

```
with Ada.Text_IO;
with Euler;
procedure Diff is
type Real is digits 6;
type Vector is array(Integer range <>) of Real;
type Ptr is access function (X: Real; Y: Real) return Real;
procedure Solve is new Euler(Real, Vector, Ptr);
function Ident(X: Real; Y: Real) return Real is
begin
return 2.0*X*Y;
end Ident;
package Real_IO is new Ada.Text_IO.Float_IO(Real);
use Real_IO;
Answer: Vector(1..10);
begin
Solve(Ident'Access, 1.0, 0.1, Answer);
for N in Answer'Range loop
Put(1.0 + 0.1 * Real(N-1), Exp => 0);
Put( Answer(N), Exp => 0);
Ada.Text_IO.New_Line;
end loop;
end Diff;
```

The file **euler.ads** is

```
--
-- Solving a differential equation.
-- Demonstrates generic floating point type.
--
generic
type Float_Type is digits <>;
type Vector is array(Integer range <>) of Float_Type;
type Function_Ptr is access function (X: Float_Type; Y: Float_Type) return Float_Type;
procedure Euler(
F: in Function_Ptr; Init, H: in Float_Type; Result: out Vector);
```

And the file **euler.adb** is

```
procedure Euler(
F: in Function_Ptr; Init, H: in Float_Type; Result: out Vector) is
begin
Result(Result'First) := Init;
for N in Result'First+1..Result'Last loop
Result(N) := Result(N-1) + H * F(Result(N-1));
end loop;
end Euler;
```

When I compile **diff.adb**, I get the error message:

euler.adb: Builder results euler.adb:6:36 missing argument for parameter Y

As I don't understand access types well, I would be very grateful if I can get help making the above codes work.

PS: The results to be outputtted should be as follows when worked out by hand and a calculator:

x | y |
---|---|

1 | 1 |

1.1 | 1.2 |

1.2 | 1.464 |

1.3 | 1.815360 |

1.4 | 2.287354 |

1.5 | 2.927813 |

The first column gives the x values (with an increment of 0.1) and the second column gives the ouput of the Euler method (y values).

**After Simon's help:**

I used Simon's code for euler.adb:

This was changed to Simon's code:

```
procedure Euler
(F : in Function_Ptr; Init, H : in Float_Type; Result : out Vector)
is
Step : constant Float_Type := H;
Current_X : Float_Type := 1.0;
begin
Result (Result'First) := Init;
for N in Result'First + 1 .. Result'Last loop
Current_X := Current_X + Step;
Result (N) := Result (N - 1) + Step * F (Current_X, Result (N - 1));
end loop;
end Euler;
```

The initial value of X is 1.0 and it is 1.0 as well for Y. In diff.adb, the output line Put(0.1 * Real(N-1), Exp => 0) has been changed to Put(1.0 + 0.1 * Real(N-1), Exp => 0) so as to get the sequence 1.0 to 1.5 (with also the line Answer: Vector(1..6) accordingly modified from 10 to 6).

When I run the corrected code I now get:

x | y |
---|---|

1 | 1.00000 |

1.1 | 1.22000 |

1.2 | 1.51280 |

1.3 | 1.90613 |

1.4 | 2.43984 |

1.5 | 3.17180 |

The Y values from the above table are not OK as compared with the values from the table given up earlier. For instance by hand calculation, Y(1.1)= 1 + 0.1 * 2.0 * 1 * 1 = 1.2 where I am using the equation Y1 = Y0 + h*f(X0, Y0) with Y0 and X0 as the initial values of 1 both and h is the X increment of 0.1. Then Y(1.2) = 1.2 + 0.1 * 2 * 1.1 * 1.2 = 1.464000 where I used the equation Y2 = Y1 + h * f(X1, Y1) with X1 = X0 + h = 1 + 0.1 = 1.1 and Y1 has been calculated in the previous iteration as Y(X=1.1)=1.2. Then we can continue calculating for Y(X=1.3), Y(X=1.4) and Y(X=1.5) in a similar manner.