Numerical integration: Difference between revisions
Content deleted Content added
→{{header|Ada}}: Fixed incorrect integration. Split up package specification and body. Added a test driver. |
|||
Line 90: | Line 90: | ||
</lang> |
</lang> |
||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
Specification of a generic package implementing the five specified kinds of numerical integration: |
|||
{{incorrect|Ada|Right_Rect stops one H too soon; Mid_Rect doesn't sample at midpoints but merely recreates Trapezium differently.}} |
|||
This solution creates a generic package into which the function F(X) is passed during generic instantiation. The first part is the package specification. The second part is the package body. |
|||
<lang ada>generic |
<lang ada>generic |
||
type Scalar is digits <>; |
|||
with function F(X : Long_Float) return Long_Float; |
|||
with function F (X : Scalar) return Scalar; |
|||
package Integrate is |
package Integrate is |
||
function |
function Left_Rectangular (A, B : Scalar; N : Positive) return Scalar; |
||
function |
function Right_Rectangular (A, B : Scalar; N : Positive) return Scalar; |
||
function |
function Midpoint_Rectangular (A, B : Scalar; N : Positive) return Scalar; |
||
function |
function Trapezium (A, B : Scalar; N : Positive) return Scalar; |
||
function |
function Simpsons (A, B : Scalar; N : Positive) return Scalar; |
||
end Integrate; |
end Integrate;</lang> |
||
An alternative solution is to pass a function reference to the integration function. This solution is probably slightly faster, and works even with Ada83. One could also make each integration function generic, instead of making the whole package generic. |
|||
package body Integrate is |
|||
Body of the package implementing numerical integration: |
|||
--------------- |
|||
<lang ada>package body Integrate is |
|||
-- Left_Rect -- |
|||
function Left_Rectangular (A, B : Scalar; N : Positive) return Scalar is |
|||
--------------- |
|||
H : constant Scalar := (B - A) / Scalar (N); |
|||
Sum : Scalar := 0.0; |
|||
function Left_Rect (A, B, N : Long_Float) return Long_Float is |
|||
X : Scalar; |
|||
Sum : Long_Float := 0.0; |
|||
X : Long_Float := A; |
|||
begin |
begin |
||
for I in 0 .. N - 1 loop |
|||
X := A + Scalar (I) * H; |
|||
Sum := Sum + H * F (X); |
|||
end loop; |
end loop; |
||
return Sum; |
return Sum; |
||
end |
end Left_Rectangular; |
||
function Right_Rectangular (A, B : Scalar; N : Positive) return Scalar is |
|||
---------------- |
|||
H : constant Scalar := (B - A) / Scalar (N); |
|||
-- Right_Rect -- |
|||
Sum : Scalar := 0.0; |
|||
---------------- |
|||
X : Scalar; |
|||
function Right_Rect (A, B, N : Long_Float) return Long_Float is |
|||
H : constant Long_Float := (B - A) / N; |
|||
Sum : Long_Float := 0.0; |
|||
X : Long_Float := A + H; |
|||
begin |
begin |
||
for I in 1 .. N loop |
|||
X := A + Scalar (I) * H; |
|||
Sum := Sum + H * F (X); |
|||
end loop; |
end loop; |
||
return Sum; |
return Sum; |
||
end |
end Right_Rectangular; |
||
function Midpoint_Rectangular (A, B : Scalar; N : Positive) return Scalar is |
|||
-------------- |
|||
H : constant Scalar := (B - A) / Scalar (N); |
|||
-- Mid_Rect -- |
|||
Sum : Scalar := 0.0; |
|||
-------------- |
|||
X : Scalar; |
|||
function Mid_Rect (A, B, N : Long_Float) return Long_Float is |
|||
H : constant Long_Float := (B - A) / N; |
|||
Sum : Long_Float := 0.0; |
|||
X : Long_Float := A; |
|||
begin |
begin |
||
for I in 1 .. N loop |
|||
X := A + Scalar (I) * H - 0.5 * H; |
|||
Sum := Sum + H * F (X); |
|||
end loop; |
end loop; |
||
return Sum; |
return Sum; |
||
end |
end Midpoint_Rectangular; |
||
function Trapezium (A, B : Scalar; N : Positive) return Scalar is |
|||
--------------- |
|||
H : constant Scalar := (B - A) / Scalar (N); |
|||
-- Trapezium -- |
|||
Sum : Scalar := F(A) + F(B); |
|||
--------------- |
|||
X : Scalar := 1.0; |
|||
function Trapezium (A, B, N : Long_Float) return Long_Float is |
|||
H : constant Long_Float := (B - A) / N; |
|||
Sum : Long_Float := F(A) + F(B); |
|||
X : Long_Float := 1.0; |
|||
begin |
begin |
||
while X <= N - 1.0 loop |
while X <= Scalar (N) - 1.0 loop |
||
Sum := Sum + 2.0 * F(A + X * (B - A) / N); |
Sum := Sum + 2.0 * F (A + X * (B - A) / Scalar (N)); |
||
X := X + 1.0; |
X := X + 1.0; |
||
end loop; |
end loop; |
||
return (B - A) / (2.0 * N) * Sum; |
return (B - A) / (2.0 * Scalar (N)) * Sum; |
||
end Trapezium; |
end Trapezium; |
||
function Simpsons (A, B : Scalar; N : Positive) return Scalar is |
|||
------------- |
|||
H : constant Scalar := (B - A) / Scalar (N); |
|||
-- Simpson -- |
|||
Sum_1 : Scalar := 0.0; |
|||
------------- |
|||
Sum_2 : Scalar := 0.0; |
|||
function Simpson (A, B, N : Long_Float) return Long_Float is |
|||
H : constant Long_Float := (B - A) / N; |
|||
Sum1 : Long_Float := 0.0; |
|||
Sum2 : Long_Float := 0.0; |
|||
Limit : Integer := Integer(N) - 1; |
|||
begin |
begin |
||
for I in 0.. |
for I in 0 .. N - 1 loop |
||
Sum_1 := Sum_1 + F (A + H * Scalar (I) + 0.5 * H); |
|||
Sum_2 := Sum_2 + F (A + H * Scalar (I)); |
|||
end loop; |
end loop; |
||
return H / 6.0 * (F (A) + F (B) + 4.0 * Sum_1 + 2.0 * Sum_2); |
|||
for I in 1..Limit loop |
|||
end Simpsons; |
|||
Sum2 := Sum2 + F(A + H * Long_Float(I)); |
|||
end loop; |
|||
return H / 6.0 * (F(A) + F(B) + 4.0 * Sum1 + 2.0 * Sum2); |
|||
end Simpson; |
|||
end Integrate;</lang> |
end Integrate;</lang> |
||
Test driver: |
|||
<lang ada>with Ada.Text_IO, Ada.Integer_Text_IO; |
|||
with Integrate; |
|||
procedure Numerical_Integration is |
|||
type Scalar is digits 18; |
|||
package Scalar_Text_IO is new Ada.Text_IO.Float_IO (Scalar); |
|||
generic |
|||
with function F (X : Scalar) return Scalar; |
|||
Name : String; |
|||
From, To : Scalar; |
|||
Steps : Positive; |
|||
procedure Test; |
|||
procedure Test is |
|||
package Integrate_Scalar_F is new Integrate (Scalar, F); |
|||
use Ada.Text_IO, Ada.Integer_Text_IO, Integrate_Scalar_F, Scalar_Text_IO; |
|||
begin |
|||
Put (Name & " integrated from "); |
|||
Put (From); |
|||
Put (" to "); |
|||
Put (To); |
|||
Put (" in "); |
|||
Put (Steps); |
|||
Put_Line (" steps:"); |
|||
Put ("Rectangular (left): "); |
|||
Put (Left_Rectangular (From, To, Steps)); |
|||
New_Line; |
|||
Put ("Rectangular (right): "); |
|||
Put (Right_Rectangular (From, To, Steps)); |
|||
New_Line; |
|||
Put ("Rectangular (midpoint): "); |
|||
Put (Midpoint_Rectangular (From, To, Steps)); |
|||
New_Line; |
|||
Put ("Trapezium: "); |
|||
Put (Trapezium (From, To, Steps)); |
|||
New_Line; |
|||
Put ("Simpson's: "); |
|||
Put (Simpsons (From, To, Steps)); |
|||
New_Line; |
|||
New_Line; |
|||
end Test; |
|||
begin |
|||
Ada.Integer_Text_IO.Default_Width := 0; |
|||
Scalar_Text_IO.Default_Fore := 0; |
|||
Scalar_Text_IO.Default_Exp := 0; |
|||
Cubed: |
|||
declare |
|||
function F (X : Scalar) return Scalar is |
|||
begin |
|||
return X ** 3; |
|||
end F; |
|||
procedure Run is new Test (F => F, |
|||
Name => "x^3", |
|||
From => 0.0, |
|||
To => 1.0, |
|||
Steps => 100); |
|||
begin |
|||
Run; |
|||
end Cubed; |
|||
One_Over_X: |
|||
declare |
|||
function F (X : Scalar) return Scalar is |
|||
begin |
|||
return 1.0 / X; |
|||
end F; |
|||
procedure Run is new Test (F => F, |
|||
Name => "1/x", |
|||
From => 1.0, |
|||
To => 100.0, |
|||
Steps => 1_000); |
|||
begin |
|||
Run; |
|||
end One_Over_X; |
|||
X: |
|||
declare |
|||
function F (X : Scalar) return Scalar is |
|||
begin |
|||
return X; |
|||
end F; |
|||
procedure Run_1 is new Test (F => F, |
|||
Name => "x", |
|||
From => 0.0, |
|||
To => 5_000.0, |
|||
Steps => 5_000_000); |
|||
procedure Run_2 is new Test (F => F, |
|||
Name => "x", |
|||
From => 0.0, |
|||
To => 6_000.0, |
|||
Steps => 6_000_000); |
|||
begin |
|||
Run_1; |
|||
Run_2; |
|||
end X; |
|||
end Numerical_Integration; |
|||
</lang> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |