Previous | Table of Contents | Next |
10.4.2.8. Using the Generic Matrix Package
Before examining the implementation of HB.Matrices_Generic, see how it might be used. Show_Matrices is a sample client in which the matrix element type is Rational.
1 with Ada.Text_IO; use Ada.Text_IO; 2 with HB.Rationals; use HB.Rationals; 3 with HB.Rationals.IO; use HB.Rationals.IO; 4 with HB.Matrices_Generic; 5 procedure Show_Matrices is 6 7 package Rational_Matrices is new HB.Matrices_Generic 8 (ElementType => Rational, 9 Zero => 0/1, 10 Unity => 1/1, 11 + => HB.Rationals.+, 12 * => HB.Rationals.*); 13 use Rational_Matrices; 14 15 procedure Put(Item: in Vector) is 16 begin 17 for Element in ItemRange loop 18 Put(Item(Element)); 19 Put( ); 20 end loop; 21 New_Line(Spacing => 2); 22 end Put; 23 24 procedure Put(Item: in Matrix) is 25 begin 26 for Row in ItemRange(1) loop 27 for Col in ItemRange(2) loop 28 Put(Item(Row, Col)); 29 Put( ); 30 end loop; 31 New_Line; 32 end loop; 33 New_Line; 34 end Put; 35 36 V: Vector(1..3) := (1/3, 2/3, 0/1); 37 M: Matrix(1..3, 1..4) := ((0/1, 1/3, 1/2, 1/4), 38 (1/1, 1/2, 1/2, 0/1), 39 (1/4, 2/3, 1/4, 1/5)); 40 41 begin 42 43 Put_Line(V =); Put(V); 44 Put_Line(M =); Put(M); 45 Put_Line(1/2 * M =); Put(1/2 * M); 46 Put_Line(V * M =); Put(V * M); 47 48 begin 49 Put_Line(M * V =); Put(M * V); 50 Put_Line(Exception should have been raised); 51 exception 52 when Bounds_Error => 53 Put_Line(Exception properly raised); 54 end; 55 56 end Show_Matrices;
This program is in terse style with use clauses supplied and named parameters used only where extra clarity is needed. Lines 7-12 create an instance Rational_Matrices of the generic template. In line 11, the association
+ => HB.Rationals.+
is written verbosely, just for claritys sake. Indeed, the instantiation could have been written (tersely but more opaquely) as
package Rational_Matrices is new HB.Matrices_Generic (Rational, 0/1, 1/1, +, *);
The instance is now a use-able package, so I can supply a use clause (line 13). This instance gives me the types Rational_Matrices.Vector and Rational_Matrices.Matrix; the use lets me refer to these just as Vector and Matrix.
Lines 15-22 is a procedure to display the elements of a vector. There is nothing new here except (line 21) the use of the Spacing parameter to New_Line, which has the obvious meaning of move the cursor to the next line and then move it again.
Lines 24-34 show a procedure to display a matrix, row-by-row. Note in line 26 the attribute ItemRange(1), which means the range of Items first dimension, and in line 27, the attribute ItemRange(2), which means the range of Items second dimension. Here again you see the power of attributes to work with arrays whose bounds are unknown at compilation time.
Lines 36-39 declare a vector and matrix, both initialized with aggregates of rational quantities. The 2D aggregate initializes M row-by-row. Lines 43-46 display the vector and the matrix, followed by the matrix scaled by 1/2 and then by the product of the vector and the matrix.
Lines 48-54 are used to illustrate a frame style that is commonly used in writing a program designed to test a package. The product M*V is mathematically impossible because M has 4 columns, but there, column vector V has only 3 columns. Bounds_Error is raised to signal this abstraction violation, if and only if the product operation is correctly implemented in the package.
The actual output of this program should be
V = 1/3 2/3 0/1 M = 0/1 1/3 1/2 1/4 1/1 1/2 1/2 0/1 1/4 2/3 1/4 1/5 1/2 * M = 0/2 1/6 1/4 1/8 1/2 1/4 1/4 0/2 1/8 2/6 1/8 1/10 V * M = 24/36 72/162 72/144 15/180 M * V = Exception properly raised
Previous | Table of Contents | Next |