!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 !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: generic type Real is digits <>; package Ada.Numerics.Generic_Real_Arrays is pragma Pure(Generic_Real_Arrays); -- Types type Real_Vector is array (Integer range <>) of Real'Base; type Real_Matrix is array (Integer range <>, Integer range <>) of Real'Base; -- Subprograms for Real_Vector Types -- Real_Vector arithmetic operations function "+" (Right : Real_Vector) return Real_Vector; function "-" (Right : Real_Vector) return Real_Vector; function "abs" (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; function "/" (Left, Right : Real_Vector) return Real_Vector; function "**" (Left : Real_Vector; Right : Integer) return Real_Vector; function "*" (Left, Right : Real_Vector) return Real'Base; -- Real_Vector scaling operations function "*" (Left : Real'Base; Right : Real_Vector) return Real_Vector; function "*" (Left : Real_Vector; Right : Real'Base) return Real_Vector; function "/" (Left : Real_Vector; Right : Real'Base) return Real_Vector; -- Other Real_Vector operations function Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) return Real_Vector; -- Subprograms for Real_Matrix Types -- Real_Matrix arithmetic operations function "+" (Right : Real_Matrix) return Real_Matrix; function "-" (Right : Real_Matrix) return Real_Matrix; function "abs" (Right : Real_Matrix) return Real_Matrix; function Transpose (X : Real_Matrix) return Real_Matrix; function "+" (Left, Right : Real_Matrix) return Real_Matrix; function "-" (Left, Right : Real_Matrix) return Real_Matrix; function "*" (Left, Right : Real_Matrix) return Real_Matrix; function "*" (Left, Right : Real_Vector) return Real_Matrix; function "*" (Left : Real_Vector; Right : Real_Matrix) return Real_Vector; function "*" (Left : Real_Matrix; Right : Real_Vector) return Real_Vector; -- Real_Matrix scaling operations function "*" (Left : Real'Base; Right : Real_Matrix) return Real_Matrix; function "*" (Left : Real_Matrix; Right : Real'Base) return Real_Matrix; function "/" (Left : Real_Matrix; Right : Real'Base) return Real_Matrix; -- Other Real_Matrix operations function Identity_Matrix (Order : Positive; First_1, First_2 : Integer := 1) return Real_Matrix; end Ada.Numerics.Generic_Real_Arrays; 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. function Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) return Real_Vector; 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. function Transpose (X : Real_Matrix) return Real_Matrix; 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. function Identity_Matrix (Order : Positive; First_1, First_2 : Integer := 1) return Real_Matrix; 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: with Ada.Numerics.Generic_Real_Arrays, Ada.Numerics.Generic_Complex_Types; generic with package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (<>); use Real_Arrays; with package Complex_Types is new Ada.Numerics.Generic_Complex_Types (Real); use Complex_Types; package Ada.Numerics.Generic_Complex_Arrays is pragma Pure(Generic_Complex_Arrays); -- Types type Complex_Vector is array (Integer range <>) of Complex; type Complex_Matrix is array (Integer range <>, Integer range <>) of Complex; -- Subprograms for Complex_Vector types -- Complex_Vector selection, conversion and composition operations function Re (X : Complex_Vector) return Real_Vector; function Im (X : Complex_Vector) return Real_Vector; procedure Set_Re (X : in out Complex_Vector; Re : in Real_Vector); procedure Set_Im (X : in out Complex_Vector; Im : in Real_Vector); function Compose_From_Cartesian (Re : Real_Vector) return Complex_Vector; function Compose_From_Cartesian (Re, Im : Real_Vector) return Complex_Vector; function Modulus (X : Complex_Vector) return Real_Vector; function "abs" (Right : Complex_Vector) return Real_Vector renames Modulus; function Argument (X : Complex_Vector) return Real_Vector; function Argument (X : Complex_Vector; Cycle : Real'Base) return Real_Vector; function Compose_From_Polar (Modulus, Argument : Real_Vector) return Complex_Vector; function Compose_From_Polar (Modulus, Argument : Real_Vector; Cycle : Real'Base) return Complex_Vector; -- Complex_Vector arithmetic operations function "+" (Right : Complex_Vector) return Complex_Vector; function "-" (Right : Complex_Vector) return Complex_Vector; function Conjugate (X : Complex_Vector) return Complex_Vector; function "+" (Left, Right : Complex_Vector) return Complex_Vector; function "-" (Left, Right : Complex_Vector) return Complex_Vector; function "*" (Left, Right : Complex_Vector) return Complex_Vector; function "/" (Left, Right : Complex_Vector) return Complex_Vector; function "**" (Left : Complex_Vector; Right : Integer) return Complex_Vector; function "*" (Left, Right : Complex_Vector) return Complex; -- Mixed Real_Vector and Complex_Vector arithmetic operations function "+" (Left : Real_Vector; Right : Complex_Vector) return Complex_Vector; function "+" (Left : Complex_Vector; Right : Real_Vector) return Complex_Vector; function "-" (Left : Real_Vector; Right : Complex_Vector) return Complex_Vector; function "-" (Left : Complex_Vector; Right : Real_Vector) return Complex_Vector; function "*" (Left : Real_Vector; Right : Complex_Vector) return Complex_Vector; function "*" (Left : Complex_Vector; Right : Real_Vector) return Complex_Vector; function "/" (Left : Real_Vector; Right : Complex_Vector) return Complex_Vector; function "/" (Left : Complex_Vector; Right : Real_Vector) return Complex_Vector; function "*" (Left : Real_Vector; Right : Complex_Vector) return Complex; function "*" (Left : Complex_Vector; Right : Real_Vector) return Complex; -- Complex_Vector scaling operations function "*" (Left : Complex; Right : Complex_Vector) return Complex_Vector; function "*" (Left : Complex_Vector; Right : Complex) return Complex_Vector; function "/" (Left : Complex_Vector; Right : Complex) return Complex_Vector; function "*" (Left : Real'Base; Right : Complex_Vector) return Complex_Vector; function "*" (Left : Complex_Vector; Right : Real'Base) return Complex_Vector; function "/" (Left : Complex_Vector; Right : Real'Base) return Complex_Vector; -- Other Complex_Vector operations function Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) return Complex_Vector; -- Subprograms for Complex_Matrix Types -- Complex_Matrix selection, conversion and composition operations function Re (X : Complex_Matrix) return Real_Matrix; function Im (X : Complex_Matrix) return Real_Matrix; procedure Set_Re (X : in out Complex_Matrix; Re : in Real_Matrix); procedure Set_Im (X : in out Complex_Matrix; Im : in Real_Matrix); function Compose_From_Cartesian (Re : Real_Matrix) return Complex_Matrix; function Compose_From_Cartesian (Re, Im : Real_Matrix) return Complex_Matrix; function Modulus (X : Complex_Matrix) return Real_Matrix; function "abs" (Right : Complex_Matrix) return Real_Matrix renames Modulus; function Argument (X : Complex_Matrix) return Real_Matrix; function Argument (X : Complex_Matrix; Cycle : Real'Base) return Real_Matrix; function Compose_From_Polar (Modulus, Argument : Real_Matrix) return Complex_Matrix; function Compose_From_Polar (Modulus, Argument : Real_Matrix; Cycle : Real'Base) return Complex_Matrix; -- Complex_Matrix arithmetic operations function "+" (Right : Complex_Matrix) return Complex_Matrix; function "-" (Right : Complex_Matrix) return Complex_Matrix; function Conjugate (X : Complex_Matrix) return Complex_Matrix; function Transpose (X : Complex_Matrix) return Complex_Matrix; function "+" (Left, Right : Complex_Matrix) return Complex_Matrix; function "-" (Left, Right : Complex_Matrix) return Complex_Matrix; function "*" (Left, Right : Complex_Matrix) return Complex_Matrix; function "*" (Left, Right : Complex_Vector) return Complex_Matrix; function "*" (Left : Complex_Vector; Right : Complex_Matrix) return Complex_Vector; function "*" (Left : Complex_Matrix; Right : Complex_Vector) return Complex_Vector; -- Mixed Real_Matrix and Complex_Matrix arithmetic operations function "+" (Left : Real_Matrix; Right : Complex_Matrix) return Complex_Matrix; function "+" (Left : Complex_Matrix; Right : Real_Matrix) return Complex_Matrix; function "-" (Left : Real_Matrix; Right : Complex_Matrix) return Complex_Matrix; function "-" (Left : Complex_Matrix; Right : Real_Matrix) return Complex_Matrix; function "*" (Left : Real_Matrix; Right : Complex_Matrix) return Complex_Matrix; function "*" (Left : Complex_Matrix; Right : Real_Matrix) return Complex_Matrix; function "*" (Left : Real_Vector; Right : Complex_Vector) return Complex_Matrix; function "*" (Left : Complex_Vector; Right : Real_Vector) return Complex_Matrix; function "*" (Left : Real_Vector; Right : Complex_Matrix) return Complex_Vector; function "*" (Left : Complex_Vector; Right : Real_Matrix) return Complex_Vector; function "*" (Left : Real_Matrix; Right : Complex_Vector) return Complex_Vector; function "*" (Left : Complex_Matrix; Right : Real_Vector) return Complex_Vector; -- Complex_Matrix scaling operations function "*" (Left : Complex; Right : Complex_Matrix) return Complex_Matrix; function "*" (Left : Complex_Matrix; Right : Complex) return Complex_Matrix; function "/" (Left : Complex_Matrix; Right : Complex) return Complex_Matrix; function "*" (Left : Real'Base; Right : Complex_Matrix) return Complex_Matrix; function "*" (Left : Complex_Matrix; Right : Real'Base) return Complex_Matrix; function "/" (Left : Complex_Matrix; Right : Real'Base) return Complex_Matrix; -- Other Complex_Matrix operations function Identity_Matrix (Order : Positive; First_1, First_2 : Integer := 1) return Complex_Matrix; end Ada.Numerics.Generic_Complex_Arrays; 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. ****************************************************************