OONSTD: The next time you're at a party

E. Robert Tisdale (edwin@netwood.net)
Thu, 25 Mar 1999 19:47:11 -0800

The next time you're at a party, make your way over to the food.
At the first opportunity, mention that you're involved in an effort
to standardize numerical programming and keep talking
until you have the hors d'oeuvres all to your self.
After you've had your fill, make your way over to the bar.

Bob Tisdale

The C++ Scalar, Vector, Matrix and Tensor (SVMT) class library standard

Introduction

A standard Application Programmer's Interface (API)
for scalar, vector, matrix and tensor arithmetic libraries
specifies an Abstract Data Type (ADT) for each class of objects
and a language binding for each programming language.

This document describes
1.) the abstract data types,
2.) the proposed C++ language binding and
3.) the SVMT portable reference library.

1.) The Abstract Data Types

The abstract data types:
* one dimensional array of numbers referenced through
* strided real and complex multidimensional views
are common to most modern numerical libraries
which manipulate vector, matrix and higher order objects
whether they appear explicitly or implicitly in the code.

0.) A one dimensional array of complex numbers is just
a one dimensional array of real numbers twice as long
where the imaginary part follows immediately after
the real part of each complex element so that
even elements are real and odd elements are imaginary.
Complex scalars are a pair of real numbers stored
in a real one dimensional array of length two.
There are no pure imaginary objects of any order.

1.) An N-dimensional view references a subtensor of order N.
The first four orders have special names:

order view std:: shape
---------------------------------------------------
0 subscalar
1 subvector slice_array (n)
2 submatrix gslice_array (m, n)
3 subtensor gslice_array (l, m, n)

2.) The same one dimensional array of numbers
may be referenced through different views.

3.) Any element of the one dimensional array
can be the first element of a view.

4.) Each dimension has a stride as well as an extent.
Strides may be positive, negative or even zero
which means that an element of the one dimensional array
may be referenced by more than one element of a view.

5.) The one dimensional array must contain
every element referenced through the view.

2.) The Proposed C++ Language Binding

The C++ Scalar, Vector, Matrix and Tensor class library was designed
to help professional programmers write commercial applications.
The priorities:
0.) performance
* speed
* efficiency
1.) safety
2.) convenience
might well be different or even reversed in a class library designed
to help amateur programmers write applications for their own use.

SVMT class libraries are easy for C and C++ programmers to learn and remember.

A C programmer can use SVMT class libraries to write applications
without any experience or training in C++ or object oriented programming.
The design is similar to the numerical class libraries described in:
Bjarne Stroustrup, "The C++ Programming Language: Third Edition",
Chapter 22 "Numerics", pages 657-687, September 1997, Addison-Wesley.
It strives to be simple but complete and consistent within itself
in order to minimize the number of rules and exceptions
that the C or C++ programmer must memorize and understand.
It also strives to be complete and consistent with respect to C and C++.
The elements of matrix and tensor objects are stored in the same order
as they are stored in two and three dimensional C arrays respectively.
Almost all C and C++ scalar operators and functions apply to subvector,
submatrix and subtensor objects element-by-element
but the order in which they are applied is not specified.

Fortran and C compilers almost always store multidimensional arrays in
exactly the same way but the order of the subscripted indices is reversed.
Two dimensional arrays appear to be transposed when a C program calls
a Fortran subroutine or when a Fortran program calls a C function.
Fortran programmers interpret a two dimensional array as a matrix
which is a collection of column vectors so it is natural for them
to interpret a one dimensional array as a column vector.
This interpretation conforms with the conventional interpretation
of vector and matrix objects.
But C programmers interpret a two dimensional array as a matrix
which is a collection of row vectors so it is natural for them
to interpret a one dimensional array as a row vector.
This interpretation has subtle conceptual and practical advantages
over the conventional interpretation.
The elements of vector and matrix objects are stored in memory
in the same order in which they appear in the input/output stream.
The elements of a (short) row vector can displayed on a single line.
The application programmer simply writes v.dot(M).dot(L)
to compute the matrix-matrix-vector product LMv^{T} efficiently.

array style Fortran and Matlab C, C++ and SVMT
---------------------------------------------------------------------------
index order left to right (column major) right to left (row major)
index base 1 0
index subset range(first, stride, final) slice(offset, extent, stride)
subscripting operator () operator []
u dot v u^{T}v uv^{T}
---------------------------------------------------------------------------

The SVMT class library standard liberates SVMT class library developers
to implement their library as they see fit as long as it supports
portable SVMT application programs. It specifies specializations
for a restricted set of numerical types-- not generic container classes.
But it does not preclude or require implementation with prototype files,
templates or any other generic method. It does not preclude or require
optimization involving reference counting, copy on write, lazy evaluation,
inline expression classes or any other optimization technique.
It does not preclude or require implementation
based upon public libraries or standard libraries.
The actual representation of all data objects including
the one dimensional arrays of numbers is hidden
from the application programmer.

The subscalar, subvector, submatrix and subtensor classes define objects
which reference an existing one dimensional array of numbers.
The copy constructor copies memberwise.
The copy assignment operator does not copy any data members
but copies the corresponding elements
from the one dimensional array of numbers referenced by the right hand side
to the one dimensional array of numbers referenced by the left hand side.
The result is undefined unless both sides have the same size and shape.
Only the resize member function can change data members.

The vector, matrix and tensor classes inherit from the subvector, submatrix
and subtensor classes respectively but automatically allocate new storage
for the one dimensional array of numbers when the constructor is called
then deallocate the storage when the corresponding destructor is called.
Only the resize member function can change data members
and reallocate storage for the one dimensional array of numbers.

The SVMT class library detects most programming errors at compile time
and does not preclude or require any run time error checking
but optional error checking code can be compiled and/or linked into
SVMT class libraries to detect programming errors at run time.
It is left up to the SVMT class library developer to decide
how run time programming errors are handled but error checking code
should issue an informative warning message to the application programmer.
For example, error checking code should should issue
an informative warning message to the application programmer
if other references to the one dimensional array of numbers still exist
when the destructor is called for a vector, matrix or tensor object
even if it is allowed to persist until the last reference is destroyed.

Most binary operations including assignment are undefined
on operands of the same type unless they are exactly the same size.
Error checking code should issue an informative warning message
to the application programmer if binary operands do not match
even if the library accepts mismatched binary operands.

The result of an assignment operation is well defined
if the object on the left hand side
appears only in element-by-element operations on the right hand side.
But, for example, the the result of assignment operation S = M.dot(S)
where M.dot(S) is the matrix-matrix dot product is undefined
because the SVMT class library may optimize away the temporary result
of the matrix-matrix dot product and corrupt source matrix S
as it stores partial results back into destination matrix S.
The result of an assignment operation may be undefined
if the object on the left hand side references
a different view of the same one dimensional array of numbers
from an object on the right hand side. For example, S = M + S.t()
where S.t() is a transposed view of square matrix S is undefined
because the SVMT class library may optimize away the temporary result
of the matrix-matrix addition and corrupt source matrix S
as it stores partial results back into destination matrix S.
In this case, the application programmer should write S.transpose() += M
where S.transpose() transposes S in place.

3.) The SVMT Portable Reference Library

SVMT class library developers compare the behavior of their implementation
against the the behavior of the SVMT portable reference library
to verify compliance with the SVMT class library standard.
It is designed to be easy to read, understand and maintain but not
a high performance implementation of the SVMT class library standard.
It is portable even to platforms which support only Embedded C++
because it does not use templates or the standard template library.
Programmers are permitted to use the SVMT portable reference library
to develop, copyright and distribute commercial applications for profit
without disclosing any of the application program source code.
SVMT class library developers are permitted and encouraged
to implement the SVMT class library standard from scratch
then copyright and distribute it for profit
without disclosing any library source code except header files.
The SVMT portable reference library itself may not be modified
and distributed unless the programmer complies with the terms
of the GNU General Public License (GPL).
The SVMT portable reference library design minimizes the likelihood
of copyleft violation by high performance implementations.