# Standard library: Numerics

The standard library provides support for common numeric operations on floating-point types as well as on complex types and matrices. In the sections below, we present a brief introduction to these numeric operations.

## Elementary Functions

The `Ada.Numerics.Elementary_Functions` package provides common operations for floating-point types, such as square root, logarithm, and the trigonometric functions (e.g., sin, cos). For example:

```

procedure Show_Elem_Math is
X : Float;
begin
X := 2.0;
Put_Line ("Square root of "
& Float'Image (X)
& " is "
& Float'Image (Sqrt (X)));

X := e;
Put_Line ("Natural log of "
& Float'Image (X)
& " is "
& Float'Image (Log (X)));

X := 10.0 ** 6.0;
Put_Line ("Log_10      of "
& Float'Image (X)
& " is "
& Float'Image (Log (X, 10.0)));

X := 2.0 ** 8.0;
Put_Line ("Log_2       of "
& Float'Image (X)
& " is "
& Float'Image (Log (X, 2.0)));

X := Pi;
Put_Line ("Cos         of "
& Float'Image (X)
& " is "
& Float'Image (Cos (X)));

X := -1.0;
Put_Line ("Arccos      of "
& Float'Image (X)
& " is "
& Float'Image (Arccos (X)));
end Show_Elem_Math;

Enable tabbed editor view for this editor

Use the dark theme

```

Here we use the standard `e` and `Pi` constants from the `Ada.Numerics` package.

The `Ada.Numerics.Elementary_Functions` package provides operations for the `Float` type. Similar packages are available for `Long_Float` and `Long_Long_Float` types. For example, the `Ada.Numerics.Long_Elementary_Functions` package offers the same set of operations for the `Long_Float` type. In addition, the `Ada.Numerics.Generic_Elementary_Functions` package is a generic version of the package that you can instantiate for custom floating-point types. In fact, the `Elementary_Functions` package can be defined as follows:

```package Elementary_Functions is new
```

## Random Number Generation

The `Ada.Numerics.Float_Random` package provides a simple random number generator for the range between 0.0 and 1.0. To use it, declare a generator `G`, which you pass to `Random`. For example:

```

procedure Show_Float_Random_Num is
G : Generator;
X : Uniformly_Distributed;
begin
Reset (G);

Put_Line ("Some random numbers between "
& Float'Image (Uniformly_Distributed'First)
& " and "
& Float'Image (Uniformly_Distributed'Last)
& ":");
for I in 1 .. 15 loop
X := Random (G);
Put_Line (Float'Image (X));
end loop;
end Show_Float_Random_Num;

Enable tabbed editor view for this editor

Use the dark theme

```

The standard library also includes a random number generator for discrete numbers, which is part of the `Ada.Numerics.Discrete_Random` package. Since it's a generic package, you have to instantiate it for the desired discrete type. This allows you to specify a range for the generator. In the following example, we create an application that displays random integers between 1 and 10:

```

procedure Show_Discrete_Random_Num is

subtype Random_Range is Integer range 1 .. 10;

package R is new
use R;

G : Generator;
X : Random_Range;
begin
Reset (G);

Put_Line ("Some random numbers between "
& Integer'Image (Random_Range'First)
& " and "
& Integer'Image (Random_Range'Last)
& ":");

for I in 1 .. 15 loop
X := Random (G);
Put_Line (Integer'Image (X));
end loop;
end Show_Discrete_Random_Num;

Enable tabbed editor view for this editor

Use the dark theme

```

Here, package `R` is instantiated with the `Random_Range` type, which has a constrained range between 1 and 10. This allows us to control the range used for the random numbers. We could easily modify the application to display random integers between 0 and 20 by changing the specification of the `Random_Range` type. We can also use floating-point or fixed-point types.

## Complex Types

The `Ada.Numerics.Complex_Types` package provides support for complex number types and the `Ada.Numerics.Complex_Elementary_Functions` package provides support for common operations on complex number types, similar to the `Ada.Numerics.Elementary_Functions` package. Finally, you can use the `Ada.Text_IO.Complex_IO` package to perform I/O operations on complex numbers. In the following example, we declare variables of the `Complex` type and initialize them using an aggregate:

```

procedure Show_Elem_Math is

package C_IO is new
use C_IO;

X, Y  : Complex;
R, Th : Float;
begin
X := (2.0, -1.0);
Y := (3.0,  4.0);

Put (X);
Put (" * ");
Put (Y);
Put (" is ");
Put (X * Y);
New_Line;
New_Line;

R  := 3.0;
Th := Pi / 2.0;
X  := Compose_From_Polar (R, Th);
--  Alternatively:
--  X := R * Exp ((0.0, Th));
--  X := R * e ** Complex'(0.0, Th);

Put ("Polar form:    "
& Float'Image (R)  & " * e**(i * "
& Float'Image (Th) & ")");
New_Line;

Put ("Modulus     of ");
Put (X);
Put (" is ");
Put (Float'Image (abs (X)));
New_Line;

Put ("Argument    of ");
Put (X);
Put (" is ");
Put (Float'Image (Argument (X)));
New_Line;
New_Line;

Put ("Sqrt        of ");
Put (X);
Put (" is ");
Put (Sqrt (X));
New_Line;
end Show_Elem_Math;

Enable tabbed editor view for this editor

Use the dark theme

```

As we can see from this example, all the common operators, such as `*` and `+`, are available for complex types. You also have typical operations on complex numbers, such as `Argument` and `Exp`. In addition to initializing complex numbers in the cartesian form using aggregates, you can do so from the polar form by calling the `Compose_From_Polar` function.

The `Ada.Numerics.Complex_Types` and `Ada.Numerics.Complex_Elementary_Functions` packages provide operations for the `Float` type. Similar packages are available for `Long_Float` and `Long_Long_Float` types. In addition, the `Ada.Numerics.Generic_Complex_Types` and `Ada.Numerics.Generic_Complex_Elementary_Functions` packages are generic versions that you can instantiate for custom or pre-defined floating-point types. For example:

```with Ada.Numerics.Generic_Complex_Types;

procedure Show_Elem_Math is

package Complex_Types is new
use Complex_Types;

package Elementary_Functions is new
(Complex_Types);
use Elementary_Functions;

(Complex_Types);
use C_IO;

X, Y  : Complex;
R, Th : Float;
```

## Vector and Matrix Manipulation

The `Ada.Numerics.Real_Arrays` package provides support for vectors and matrices. It includes common matrix operations such as inverse, determinant, eigenvalues in addition to simpler operators such as matrix addition and multiplication. You can declare vectors and matrices using the `Real_Vector` and `Real_Matrix` types, respectively.

The following example uses some of the operations from the `Ada.Numerics.Real_Arrays` package:

```

procedure Show_Matrix is

procedure Put_Vector (V : Real_Vector) is
begin
Put ("    (");
for I in V'Range loop
Put (Float'Image (V (I)) & " ");
end loop;
Put_Line (")");
end Put_Vector;

procedure Put_Matrix (M : Real_Matrix) is
begin
for I in M'Range (1) loop
Put ("    (");
for J in M'Range (2) loop
Put (Float'Image (M (I, J)) & " ");
end loop;
Put_Line (")");
end loop;
end Put_Matrix;

V1       : Real_Vector := (1.0, 3.0);
V2       : Real_Vector := (75.0, 11.0);

M1       : Real_Matrix :=
((1.0, 5.0, 1.0),
(2.0, 2.0, 1.0));
M2       : Real_Matrix :=
((31.0, 11.0, 10.0),
(34.0, 16.0, 11.0),
(32.0, 12.0, 10.0),
(31.0, 13.0, 10.0));
M3       : Real_Matrix := ((1.0, 2.0),
(2.0, 3.0));
begin
Put_Line ("V1");
Put_Vector (V1);
Put_Line ("V2");
Put_Vector (V2);
Put_Line ("V1 * V2 =");
Put_Line ("    "
& Float'Image (V1 * V2));
Put_Line ("V1 * V2 =");
Put_Matrix (V1 * V2);
New_Line;

Put_Line ("M1");
Put_Matrix (M1);
Put_Line ("M2");
Put_Matrix (M2);
Put_Line ("M2 * Transpose(M1) =");
Put_Matrix (M2 * Transpose (M1));
New_Line;

Put_Line ("M3");
Put_Matrix (M3);
Put_Line ("Inverse (M3) =");
Put_Matrix (Inverse (M3));
Put_Line ("abs Inverse (M3) =");
Put_Matrix (abs Inverse (M3));
Put_Line ("Determinant (M3) =");
Put_Line ("    "
& Float'Image (Determinant (M3)));
Put_Line ("Solve (M3, V1) =");
Put_Vector (Solve (M3, V1));
Put_Line ("Eigenvalues (M3) =");
Put_Vector (Eigenvalues (M3));
New_Line;
end Show_Matrix;

Enable tabbed editor view for this editor

Use the dark theme

```

Matrix dimensions are automatically determined from the aggregate used for initialization when you don't specify them. You can, however, also use explicit ranges. For example:

```M1       : Real_Matrix (1 .. 2, 1 .. 3) :=
((1.0, 5.0, 1.0),
(2.0, 2.0, 1.0));
```

The `Ada.Numerics.Real_Arrays` package implements operations for the `Float` type. Similar packages are available for `Long_Float` and `Long_Long_Float` types. In addition, the `Ada.Numerics.Generic_Real_Arrays` package is a generic version that you can instantiate with custom floating-point types. For example, the `Real_Arrays` package can be defined as follows:

```package Real_Arrays is new