!standard G (00) 03-02-21 AI95-00296/01

!class amendment 02-06-07

!status received 02-06-07

!priority Medium

!difficulty Medium

!subject Vector and matrix operations

!class amendment 02-06-07

!status received 02-06-07

!priority Medium

!difficulty Medium

!subject Vector and matrix operations

!summary

The vector and matrix operations in ISO/IEC 13813 are added to Ada.Numerics in
Annex G.

!problem

A number of secondary standards for Ada 83 were produced for the numerics area.
Most of the functionality of these standards was incorporated into Ada 95 (some
in the core language and some in the Numerics Annex) but two packages from
ISO/IEC 13813 were not. These are generic packages for the manipulation of real
and complex vectors and matrices.

The UK was asked to review the situation and to make a recommendation; they
recommended that if Ada were amended then consideration should be given to
including the packages within the Numerics annex.

The packages can be implemented entirely in Ada and thus present little burden
to implementors. Providing secondary standards has not proved satisfactory
because they are not sufficiently visible to the user community as a whole.

!proposal

It is proposed that two generic packages be added to the numerics annex. They
are Ada.Numerics.Generic_Real_Arrays and Ada.Numerics.Generic_Complex_Arrays.
They are included as a new subclause G.3 in order to avoid excessive
renumbering of other clauses.

However, if rearrangement of the Annex were deemed acceptable then it might be
better to put the real arrays package in G.1 (any other non-complex numeric
library packages might then also be in G.1), to renumber G.1 (Complex
Arithmetic) as G.2 and G.2 (Numeric Performance Requirements) as G.3. The
complex arrays package could then be G.2.5.

!wording

Add a new clause G.3 as follows

G.3 Vector and matrix manipulation

Types and operations for the manipulation of real vectors and matrices are
provided in Generic_Real_Arrays, which is defined in G.3.1. Types and
operations for the manipulation of complex vectors and matrices are provided in
Generic_Complex_Arrays, which is defined in G.3.2. Both of these library units
are generic children of the predefind package Numerics (see A.5).

??? do we need non-generic equivalents ???

G.3.1 Real Vectors and Matrices

The generic library package Numerics.Generic_Real_Arrays has the following
declaration:

-- Types

-- Subprograms for Real_Vector Types

-- Real_Vector arithmetic operations

-- Real_Vector scaling operations

-- Other Real_Vector operations

-- Subprograms for Real_Matrix Types

-- Real_Matrix arithmetic operations

-- Real_Matrix scaling operations

-- Other Real_Matrix operations

Two types are defined and exported by Ada.Numerics.Generic_Real_Arrays. The
composite type Real_Vector is provided to represent a vector with components of
type Real; it is defined as an unconstrained, one-dimensional array with an
index of type Integer. The composite type Real_Matrix is provided to represent
a matrix with components of type Real; it is defined as an unconstrained,
two-dimensional array with indices of type Integer.

?? maybe indexes ??

The effect of the various functions is as described below. In most cases the
functions are described in terms of corresponding scalar operations of the type
Real; any exception raised by those operations is propagated by the array
operation. Moreover the accuracy of the result for each individual component is
as defined for the scalar operation unless stated otherwise.

function "+" (Right : Real_Vector) return Real_Vector;
function "-" (Right : Real_Vector) return Real_Vector;
function "abs" (Right : Real_Vector) return Real_Vector;

Each operation returns the result of applying the corresponding operation of
the type Real to each component of Right. These are the standard mathematical
operations for vector identity, negation and absolute value respectively. The
bounds of the result are those of Right.

function "+" (Left, Right : Real_Vector) return Real_Vector;
function "-" (Left, Right : Real_Vector) return Real_Vector;
function "*" (Left, Right : Real_Vector) return Real_Vector;
function "/" (Left, Right : Real_Vector) return Real_Vector;

Each operation returns the result of applying the corresponding operation of
the type Real to each component of Left and the matching component of Right.
These are the standard mathematical operations for vector addition,
subtraction, multiplication and division respectively. The bounds of the result
are those of the left operand. The exception Constraint_Error is raised if
Left'Length is not equal to Right'Length.

function "**" (Left : Real_Vector; Right : Integer) return Real_Vector;

This operation returns the result of applying the corresponding operation "**"
of the type Real with integer power Right to each component of Left. The bounds
of the result are those of the left operand.

function "*" (Left, Right : Real_Vector) return Real'Base;

This operation returns the inner (dot) product of Left and Right. The exception
Constraint_Error is raised if Left'Length is not equal to Right'Length. This
operation involves an inner product; an accuracy requirement is not specified.
Constraint_Error is raised if an intermediate result is outside the range of
Real'Base even though the mathematical final result would not be.

function "*" (Left : Real'Base; Right : Real_Vector) return Real_Vector;

This operation returns the result of multiplying each component of Right by the
scalar Left using the "*" operation of the type Real. This is the standard
mathematical operation for scaling a vector Right by a real number Left. The
bounds of the result are those of the right operand.

function "*" (Left : Real_Vector; Right : Real'Base) return Real_Vector;
function "/" (Left : Real_Vector; Right : Real'Base) return Real_Vector;

Each operation returns the result of applying the corresponding operation of
the type Real to each component of Left and to the scalar Right. These are
standard mathematical operations for scaling a vector Left by a real number
Right. The bounds of the result are those of the left operand.

This function returns a "unit vector" with Order components and a lower bound
of First. All components are set to 0.0 except for the Index component which is
set to 1.0. The exception Constraint_Error is raised if Index < First, Index >
First + Order - 1 or if First + Order - 1 > Integer'Last. This function is
exact.

function "+" (Right : Real_Matrix) return Real_Matrix;
function "-" (Right : Real_Matrix) return Real_Matrix;
function "abs" (Right : Real_Matrix) return Real_Matrix;

Each operation returns the result of applying the corresponding operation of
the type Real to each component of Right. These are the standard mathematical
operations for matrix identity, negation and absolute value respectively. The
bounds of the result are those of Right.

This function returns the transpose of a matrix X. The index ranges of the
result are X'Range(2) and X'Range(1) (first and second index respectively).
This function is exact.

function "+" (Left, Right : Real_Matrix) return Real_Matrix;
function "-" (Left, Right : Real_Matrix) return Real_Matrix;

Each operation returns the result of applying the corresponding operation of
type Real to each component of Left and the matching component of Right. These
are also the standard mathematical operations for matrix addition and
subtraction. The bounds of the result are those of Left. The exception
Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or
Left'Length(2) is not equal to Right'Length(2).

function "*" (Left, Right : Real_Matrix) return Real_Matrix;

This operation provides the standard mathematical operation for matrix
multiplication. The index ranges of the result are Left'Range(1) and
Right'Range(2) (first and second index respectively). The exception
Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1).
This operation involves an inner product; an accuracy requirement is not
specified. Constraint_Error is raised if an intermediate result is outside the
range of Real'Base even though the mathematical final result would not be.

function "*" (Left, Right : Real_Vector) return Real_Matrix;

This operation provides the standard mathematical operation for multiplication
of a (column) vector Left by a (row) vector Right. The index ranges of the
matrix result are Left'Range and Right'Range (first and second index
respectively).

function "*" (Left : Real_Vector; Right : Real_Matrix) return Real_Vector;

This operation provides the standard mathematical operation for multiplication
of a (row) vector Left by a matrix Right. The index range of the (row) vector
result is Right'Range(2). The exception Constraint_Error is raised if
Left'Length is not equal to Right'Length(1). This operation involves an inner
product; an accuracy requirement is not specified. Constraint_Error is raised
if an intermediate result is outside the range of Real'Base even though the
mathematical final result would not be.

function "*" (Left : Real_Matrix; Right : Real_Vector) return Real_Vector;

This operation provides the standard mathematical operation for multiplication
of a matrix Left by a (column) vector Right. The index range of the (column)
vector result is Left'Range(1). The exception Constraint_Error is raised if
Left'Length(2) is not equal to Right'Length. This operation involves an inner
product; an accuracy requirement is not specified. Constraint_Error is raised
if an intermediate result is outside the range of Real'Base even though the
mathematical final result would not be.

function "*" (Left : Real'Base; Right : Real_Matrix) return Real_Matrix;

This operation returns the result of multiplying each component of Right by the
scalar Left using the "*" operation of the type Real. This is the standard
mathematical operation for scaling a matrix Right by a real number Left. The
index ranges of the matrix result are those of Right.

function "*" (Left : Real_Matrix; Right : Real'Base) return Real_Matrix;
function "/" (Left : Real_Matrix; Right : Real'Base) return Real_Matrix;

Each operation returns the result of applying the corresponding operation of
the type Real to each component of Left and to the scalar Right. These are
standard mathematical operations for scaling a matrix Left by a real number
Right. The index ranges of the matrix result are those of Left.

This function returns a square "identity matrix" with Order**2 components and
lower bounds of First_1 and First_2 (for the first and second index ranges
respectively). All components are set to 0.0 except for the main diagonal,
whose components are set to 1.0. The exception Constraint_Error is raised if
First_1 + Order - 1 > Integer'Last or First_2 + Order - 1 > Integer'Last. This
function is exact.

G.3.2 Complex Vectors and Matrices

The generic library package Numerics.Generic_Complex_Arrays has the following
declaration:

-- Types

-- Subprograms for Complex_Vector types

-- Complex_Vector selection, conversion and composition operations

-- Complex_Vector arithmetic operations

-- Mixed Real_Vector and Complex_Vector arithmetic operations

-- Complex_Vector scaling operations

-- Other Complex_Vector operations

-- Subprograms for Complex_Matrix Types

-- Complex_Matrix selection, conversion and composition operations

-- Complex_Matrix arithmetic operations

-- Mixed Real_Matrix and Complex_Matrix arithmetic operations

-- Complex_Matrix scaling operations

-- Other Complex_Matrix operations

To be concluded

!example

To be done

!discussion

To be done

!ACATS Test

ACATS test(s) need to be created.

!appendix

**************************************************************** Recommendation on ISO/IEC 13813 from the UK The standard ISO/IEC 13813 entitled generic packages of real and complex type declarations and basic operations for Ada (including vector and matrix types) will soon be up for review. This note reviews the background to the development of the standard and makes a recommendation that the standard be revised. Background The Numerics Working Group of WG9 met many times during the period when Ada 95 was being designed and produced a number of standards. They were faced with the problem of whether to produce standards based on Ada 83 (87 in ISO terms) or whether to base them on Ada 95 or subsume them into Ada 95. One dilemma was of course that although Ada 95 was on the way nevertheless Ada 83 was expected to continue in use for many years. The standards are 11430: Generic package of elementary functions for Ada. 11729: Generic package of primitive functions for Ada. 13813: Generic packages of real and complex type declarations and basic operations for Ada (including vector and matrix types). 13814: Generic package of complex elementary functions for Ada. 11430 and 11729 are mentioned for completeness. They were published in 1994. They were based entirely on Ada 83 and their facilities are provided in the Ada 95 core language. The elementary functions, 11430, became the package Ada.Numerics.Generic_Elementary_Functions and the primitive functions, 11729, became the various attributes such as 'Floor and 'Ceiling, and 'Exponent and 'Fraction. These two standards were withdrawn recently and need no further mention. The other two standards, 13813 and 13814, were published in 1998 and will soon be up for review at the end of their five year period. Three possible fates can befall a standard when it is reviewed. It can be withdrawn, revised or confirmed. In the case of 13814, the functionality is all incorporated into the Numerics Annex of Ada 95 as the package Ada.Numerics.Generic_Complex_Elementary_Functions. There are a few changes in presentation because the Ada 95 package uses the generic package parameter feature which of course did not exist in Ada 83. Nevertheless there seems little point in continuing with 13814 and so at the Leuven meeting of WG9 it was agreed to recommend that it be withdrawn. However, the situation regarding 13813 is not so clear. Some of its functionality is included in Ada 95 but quite a lot is not. The topics covered are (1) a complex types package including various complex arithmetic operations, (2) a real arrays package covering both vectors and matrices, (3) a complex arrays package covering both vectors and matrices, (4) a complex input-output package. The complex types package (1) became the package Ada.Numerics.Generic_Complex_Types and the input-output package (4) became Ada.Text_IO.Complex_IO. However, the array packages, both real and complex, were not incorporated into the Ada 95 standard. At the Leuven meeting, it was agreed that 13813 should not be withdrawn without further study. The UK was asked to study whether small or large changes are required in 13813 and to report back. The Ada Rapporteur Group would then decide whether the functionality should be included in a future revision or amendment to Ada 95. This is the report from the UK. Recommendation It is recommended that 13813 be revised so that it only contains the functionality not included in Ada 95. The revised standard should contain two generic packages namely Ada.Numerics.Generic_Real_Arrays and Ada.Numerics.Generic_Complex_Arrays. There should also be standard non-generic packages corresponding to the predefined types such as Float in an analogous manner to the standard packages such as Ada.Numerics.Complex_Types and Ada.Numerics.Long_Complex_Types for Float and Long_Float respectively. The text of the Ada specifications of the two generic packages should be essentially as given in the nonnormative Annex G of the existing standard 13813. (This Annex illustrates how the existing standard packages might be rewritten using Ada 95. There is an error regarding the formal package parameters which has been corrected in the revised text.) There is an important issue regarding what should happen if there is a mismatch in the array lengths of the parameters in a number of the subprograms provided by the packages. For example if function "+" (Left, Right: Real_Vector) return Real_Vector be called with parameters such that Left'Length /= Right'Length. The existing standard raises the exception Array_Index_Error which is declared alone in a package Array_Exceptions. The nonnormative Annex G shows this exception incorporated into the package Ada.Numerics thereby producing an incompatibility with the existing definition of Ada.Numerics. We considered four possibilities regarding this exception 1) Add Array_Index_Error to Ada.Numerics as in Annex G. 2) Place Array_Index_Error in a new child package such as Ada.Numerics.Arrays. 3) Eliminate Array_Index_Error and raise Constraint_Error instead. 4) State that the behaviour with mismatched arrays is implementation-defined. We concluded that Option (1) is undesirable because of incompatibility. Option (2) is feasible but one ought then to place the generic packages themselves into this package so that they become Ada.Numerics.Arrays.Generic_Real_Arrays and Ada.Numerics.Arrays.Generic_Complex_Arrays. This nesting is considered cumbersome. Option(3) gives the same behaviour as similar mismatching on predefined operations and although losing some specificacity has practical simplicity. Option (4) is disliked since gratuitous implementation-defined behaviour should be avoided. We therefore recommend Option (3) that Constraint_Error be raised on mismatching of parameters. If the Ada95 standard itself be revised at some later date then consideration should be given to incorporating the functionality of the revised 13813 into the Numerics Annex. Proposed text The proposed normative text of the revised standard is distributed separately as N404, Working Draft, Revision of ISO/IEC 13813. Note that the non-normative rationale section remains to be completed and that consequently the bibliography might need alterations to match. Acknowledgment We acknowledge the valuable assistance of Donald Sando, the editor of the original standard, in the preparation of this recommendation. **************************************************************** From: John Barnes Sent: Tuesday, January 21, 2003 10:33 AM Gosh - I have made a start on AI-296. [Editor's note: This is version /01 of the AI.] I have pulled all the Ada text in and written a first cut at the description for the real vectors and matrices. I thought maybe it would be a good idea to get the style settled before spending time on the complex ones. Here are some thoughts. There are questions of how to arrange the annex in !proposal. What do we use for the plural of index when talking about arrays? I suspect that it ought to be indexes and not indices as Don had. I have slimmed down the accuracy and error stuff that Don Sando had by simply referring to the underlying real operations. There are as yet no useful remarks on the accuracy of inner product. I started by explaining the bounds of the result in terms of the bounds of the parameters whereas Don had done it in terms of ranges. Later I discovered that ranges are much easier for the more elaborate matrix cases so perhaps I should have used ranges throughout. Thus saying for example "the index range of the result is Left'Range" rather than "the bounds of the result are those of the left operand". I am not sure whether I need to say anything about null arrays. I note that 4.5.1(8) doesn't seem to. Incidentally, I am still overwhelmed with other work. Although the Spark book has gone away to be proof read, it re-emerges tomorrow and will keep me busy for several days in doing final corrections. Also I have to prepare a one-day course on Spark at the University of York the week after Padua so I have to send the notes beforehand. I do this course each year but at the last minute they want a lot of changes. But we do have a baseline to discuss on AI-296 for Padua even if I don't get a chance to spend much more time on it before then. So I don't feel too guilty. There is a lot of interest in this stuff (especially problems of accuracy) in the UK and we have a BSI meeting in mid February to discuss this. **************************************************************** From: Pascal Leroy Sent: Wednesday, January 22, 2003 8:24 AM > There are as yet no useful remarks on the > accuracy of inner product. I think that the accuracy of the inner product should be defined in a way similar to that of the complex multiplication. If you look at the inner product of vectors (a1, a2) and (b1, b2), the result is quite similar to the real part of the (complex) multiplication of a1 + ib1 and a1 - ib2. The box error in G.2.5 ensures that if the result of a multiplication lands very close to one of the axis, you don't have to provide an unreasonable accuracy on the "small" component, because presumably cancellations happened. Moreover, the "large" component gives you some information on the magnitude of the cancellation, so it can be used to define the acceptable error. That's essentially what the box error does (at least that's my understanding). For the inner product of v1 and v2, I believe that the error should similarly be defined to be of the form d * length(v1) * length (v2). If cancellations happen, i.e. if the vectors are nearly orthogonal, the error can be quite large compared to the final result. In the absence of cancellations, i.e. if the vectors are not orthogonal, then with a proper choice for d we can require good accuracy. The alert reader will notice that this amounts to defining the relative error on the result as d/cos (A) where A is the angle of the two vectors. This is just a back-of-an-envelope proposal. No rigorous analysis was done. ****************************************************************

Questions? Ask the ACAA Technical Agent