Previous Table of Contents Next


Furthermore, because any programmer-defined type can be used as an element, it is not self-evident that addition and multiplication are defined for this type. I therefore list formal parameters for these operations (lines 7-10) and the client must supply the corresponding actuals. To instantiate for Float, you would write

   package Float_Matrices is new HB.Matrices_Generic
     (ElementType => Float,
      Zero        => 0.0,
      Unity       => 1.0,
      “+” => “+”,
      “*” => “*”);

and to instantiate for Boolean (say, for a graph-theory application that represents graphs as Boolean matrices), you would write

   package Boolean_Matrices is new HB.Matrices_Generic
     (ElementType => Boolean,
      Zero        => False,
      Unity       => True,
      “+” => “or”,
      “*” => “and”);

Returning to the package interface, lines 14-17 declare two types, Vector and Matrix. The second declaration shows a matrix as a two-dimensional unconstrained array. This lets me declare objects such as

   M: Matrix(1..3, 25..100);

which I view as having three rows and 76 columns.

The Matrix type raises two related issues. First, a two-dimensional (2D) array is not a 1D array of 1D arrays (as it would be in Pascal or C, for example); it is a different type entirely. Second, the Ada standard does not specify a storage structure for multidimensional arrays; an implementer could choose row-major, or column-major, or another scheme entirely (such as a tree structure). This is an advantage because the storage structure can be tailored to the underlying computer’s memory structure. Generally, a programmer need not be concerned about the storage structure.

On the other hand, in a program using the Ada 95 interface to Fortran (as described in Annex B of the standard), for example, to call pre-existing Fortran subprograms, I could attach to a matrix type a compiler directive—pragma in Ada—of the form

   pragma Convention(Fortran, Matrix);

indicating that all objects of the Ada type Matrix must be stored to match the column-major convention used by the related Fortran compiler.

Lines 19-24 are essentially repeated from HB.Vectors. Lines 26-27 declare a scaling operation for matrices; line 28 declares a matrix transposition operation in which rows are interchanged with columns, line 29 gives a matrix sum (similar to the vector sum), and line 30 provides the matrix product. In this last operation, given matrices Left, Right, and Result, for a given row R and column C of Result, Result(R,C) is the vector inner product of row R of Left and column C of Right. The conformability condition is that Left must have as many columns as Right has rows; Result has the number of rows of Left and the number of columns of Right.

Finally, lines 32-35 provide “mixed” vector/matrix operations. In the first “*”, Left is a row vector; multiplying it by the matrix Right produces another vector. This is similar to a matrix product operation in which Left has only one row. Similarly, the second “*” operation provides for multiplying a matrix Left by a vector Right.

A comment on package design: That I choose to export two types from this package shows clearly that the Ada package is an encapsulation mechanism that gives us flexibility to export one or more types—or, indeed, not to export any types at all, as in HB.Rationals.IO. This is a clearly different style from “class”-oriented languages in which the type and the encapsulation mechanisms are the same. Naturally, there is debate about the superiority of one style over another; however, neither side can prove its case because these are just different syntactic mechanisms—matters of preference, really—for reaching similar program-design goals.


Previous Table of Contents Next