by Robin Vowels. Copyright © 2003. All rights reserved.
No part of this article may be reproduced without permission
of the author.
iSUB may be used to simplify some operations involving arrays.
iSUB may be used to define two or more arrays that share the same storage.
For example, suppose a square matrix A exists of size 10 × 10.
We may specify a second array D of size 10 that references only those
elements on the diagonal. The declaration is:
DECLARE A(10,10) FLOAT,
D(10) DEFINED A(1SUB, 1SUB) FLOAT;
Thus PUT (D); will print only the diagonal elements of A.
In another instance, suppose a matrix has zero elements everywhere
except for those on the diagonal. iSUB may be used in such a way that only those
diagonal elements are held in storage, with a considerable saving in storage.
However, iSUB allows that matrix
to be referenced as if all elements (including the zero elements) were held
in storage.
The next example declaration reserves storage for the diagonal
elements and provides the means to reference all elements of the matrix B.
DECLARE A(11) FLOAT INITIAL (7, 5, 8, 2, 6, 1, 4, 9, 3, 10, 0),
B(10,10) DEFINED A(1SUB*(1SUB=2SUB) +
(1SUB^=2SUB)*HBOUND(A) ) FLOAT;
In the example, the 10 elements on the diagonal are stored in a(1) to A(10),
and one zero element is stored in A(11). This latter element is accessed
whenever a reference is made to an off-diagonal element.
The statement PUT (A); will print only 11 elements,
while the statement PUT (B); will print all 100 elements of the matrix.
But note that only 11 elements of the matrix are stored.
The following declaration will allow access to elements of the other
diagonal (from the top right-hand corner to the bottom left-hand corner).
DECLARE A(10,10) FLOAT,
D(10) DEFINED A(1SUB, HBOUND(A)-1SUB+1) FLOAT;
Symmetric Matrix
In a symmetric matrix, the elements above the diagonal are
the mirror image of those below the diagonal. In other words, element
A(i,j) = A(j,i) for all i ^= j.
Under these circumstances, only the diagonal elements and all those
below the diagonal need to be stored. For an n × n matrix, the storage required
is n(n-1)/2 elements (or just over one-half the number of elements in the full
matrix.
We may therefore define a vector consisting of n(n-1)/2 elements, and
we may define an n × n matrix that accesses those elements. This is possible
because the position of an element (i,j) is given by the formula i*(i-1)/2+j.
Thus:
DECLARE S(N*(N-1)/2) FLOAT,
A(N,N) DEFINED B(1SUB*(1SUB-1)/2+2SUB) FLOAT;
Thus a reference to element A(i,j) is translated to a reference to
S(i*(i-1)/2+j).
This declaration permits the matrix A to be referenced by
A(i,j) provided that i <= j.
An alternative declaration is required when the the diagonal and those
elements above it are stored instead. This requires a more involved formula.
DECLARE S(N*(N-1)/2) FLOAT,
A(N,N) DEFINED B(N*(1SUB-1)-1SUB*(1SUB-1)/2+2SUB) FLOAT;
This declaration permits the matrix A to be referenced by
A(i,j) provided that i >= j.
For both declarations, however, the formula needs to be modified
if all elements of the matrix A are to be referenced (that is, if A(i,j)
is to be used for all values of i and j.
The declaration for the lower triangular form thus becomes:
DECLARE S(N*(N-1)/2) FLOAT,
A(N,N) DEFINED B(
(1SUB*(1SUB-1)/2+2SUB)*(1SUB <= 2SUB) +
(2SUB+(2SUB-1)/2+1SUB)*(1SUB >= 2SUB) ) FLOAT;
In all cases above where division by 2 is required, ISRL may be used
instead (provided that n > 1).
Upper Triangular Matrix
If the matrix is upper triangular (that is, all elements below the
diagonal are zero), the following declaration may be used to define storage
for the matrix:
DECLARE S(N*(N-1)/2) FLOAT,
A(N,N) DEFINED B
(N*(1SUB-1)-1SUB*(1SUB-1)/2 + 2SUB) FLOAT;
(Fike, p. 58)
The elements A(i,j) stored may be referenced for all values of i and j such
that i <= j. That means that the user may need to include a test to
avoid referencing any element below the diagonal (which would, of course,
be zero).
If it is desired to reference all elements of the array -- including
the zero-valued elements beneath the diagonal, the following declaration
and assignment would be required:
DECLARE S(ISRL(N*(N-1),1)+1) FLOAT,
A(N,N) DEFINED B(
(N*(1SUB-1)-1SUB*(1SUB-1)/2 + 2SUB)*(1SUB <= 2SUB) +
N*(1SUB>2SUB) ) FLOAT;
A(N) = 0;
Submatrix
An interesting application is to define a sub-matrix. Consider the
declaration
DECLARE A(N,N) FLOAT,
Submatrix (N-2,N-2) DEFINED A(1SUB+1,2SUB+1) FLOAT;
This declaration causes B to be the same as matrix A
except that the first and last rows are missing,
and the first and last columns are missing.
Thus, if matrix A is -
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
Then matrix B is -
7 8 9
12 13 14
Cyclic Shift
To perform a cyclic shift or rotation of the elements of a matrix,
the following declaration would suffice. This declaration assumes that
the number of shifts is held in the variable Shift.
DECLARE A (M,N) FLOAT(18),
B (M,N) DEFINED
A(LBOUND(A,1)+MOD(1SUB-Shift-LBOUND(A,1),
HBOUND(A,1)-LBOUND(A,1)+1),2SUB) FLOAT (18);
Given that matrix A is:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
Then if Shift = 1, all rows of B are as if rows of A are shifted
up by one row
(the top row re-appears at the bottom). B appears as:
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
1 2 3 4 5
If Shift = -1, B is the same as A, but with all rows shifted down by one
row (the bottom row appears at the top. B appears as:
21 22 23 24 25
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
In each case, the shifted array is obtained without actually shifting
any rows of matrix A, with some savings in execution time.
Other possibilities include obtaining the elements of a vector in reverse order:
DECLARE V(N) FLOAT,
W DEFINED V(N - 1SUB + 1) FLOAT;
If V is the array 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, then W is the array
10 9 8 7 6 5 4 3 2 1.
References:
C. T. Fike, PL/I for Scientific Programmers, Prentice-Hall,
Englewood Cliffs, N. J., 1970, pp. 57-58, 125.
IBM, OS/2 PL/I Version 2 Programming: Language Reference, 3rd Ed.,
ref. SC26-4308-2, 1990, pp. 160-164.
IBM, Enterprise PL/I for z/OS amd OS/390 Language Reference,
Version 3 Release 1.0, 3rd Ed.,
ref. SC27-1460-00, 2001, pp. 260-264.
Announcements
-
GCC front-end for the PL/I programming language,
by Henrik Sorensen, 17 Dec 2003
Some time ago an open source project was started with the goal to create a
free PL/I compiler. The project moves slowly but surely forward. Currently a
scanner and parser has been integrated into the build system of the GNU Compiler
Collection (gcc). The integration into the gcc build system was non trivial,
and would not have been possible without the help of
the sample language Treelang by Tim Josling.
The GCC PL/I 0.0.2 release follows the syntax of IBM OS PL/I Version 2.
PL/I for GCC is released under the terms of the GNU Public License; version 2.
The pl1gcc v0.0.2, contains integration into gcc build system, plus a scanner
and parser.
As you can tell, there is still a long way to go before any code
generation is done.
For more information please visit
http://pl1gcc.sourceforge.net
Looking forward to see you there.
-
Update PL/I kit for Alpha OpenVMS, by Tom Linden,
12 December 2003.
An update kit is now available which may be downloaded from
http://www.kednos.com
Also NEW is the documentation in BookReader, Postscript, Acrobat and
HTML formats.
For more info, see the release notes available on the web site.
The new Built-in Functions of IBM Enterprise PL/I
by Robin Vowels
-
CS The function reference CS (old, current, new)
compares the fixed binary(31) values pointed at by old
and current.
If they are equal, the function returns zero, otherwise the
value pointed at by old is replaced by fixed binary (31) value
new and 1 is returned.
"The purpose is (I
believe) to execute a hardware CS (Compare and Swap) instruction, which
is guaranteed to do the compare and (optionally) the swap as an atomic
operation, making it useful for implementing semaphores, etc. in
multi-threaded code." (Peter Flass)
- LOWERCASE returns the lower-case version of the string
argument.
- UPPERCASE returns the upper-case version of the string
argument.
- PLIDUMP produces a formatted dump of storage used by the
program.
For a detailed description (including details of arguments
that specify the content of the dump),
see Chapter 17 of IBM, Enterprise PL/I for z/OS and OS/390
Programming Guide Version 3 Release 1.0, 3rd Ed., San Jose,
CA, 2001, ref., SC27-1457-00, pp. 348-350.
- PLISAXA and PLISAXB invoke the high-speed XML parser.
Subroutine
PLISAXA process an XML document held in memory, while subroutine PLISAXB
processes a file of XML data.
The calling sequences are:
CALL PLISAXA (event_structure, pointer_value, buffer_address, n);
CALL PLISAXA (event_structure, pointer_value, buffer_address, n, code_page);
pointer_value is passed back by the XML parser.
n is the number of bytes in the buffer (if WIDECHAR data is used,
n is twice the length of the string reported by LENGTH).
ADDRDATA must be used when the buffer is VARYING.
The calling sequences are:
CALL PLISAXB (event_structure, pointer_value, file);
CALL PLISAXB (event_structure, pointer_value, file, code_page);
Supports 21 EBCDIC code pages and 3 ASCII code pages.
For a detailed description (including examples and
details of the supported
code pages and error messages and their explanations),
see Chapter 16 of IBM, Enterprise PL/I for z/OS and OS/390
Programming Guide Version 3 Release 1.0, 3rd Ed., San Jose,
CA, 2001, ref., SC27-1457-00, pp. 323-347.
Usefulle Webbe Lynx ...
Peter Flass is building a resource at:
Peter Flass's PL/I home page.
Current IBM PL/I offerings in the U.S.
IBM has enhanced VisualAge® PL/I with powerful features to increase
development productivity, simplify the maintenance of your legacy code,
and provide seamless portability from your host to your workstation. It
also provides the tools needed to identify your Year 2000 date-related
fields on both OS/2 and Windows NT.
VisualAge PL/I Enterprise Edition Version 2.1 combines the two separate
offerings from the previous release of VisualAge PL/I (Standard and
Professional) into a single offering available on both the OS/2 and
Windows NT platforms. By doing so, it provides these productivity
features:
- remote edit/compile
- redevelopment tools
- cross platform development
- year 2000 assessment strategies, find and fix, and test capabilities
Also included as an extra bonus offering is VisualAge CICS® Enterprise
Application Development, which enables CICS host application development
on the workstation.
- Product number 04L6564: VisualAge PL/1 Enterprise V2.1
- 04L6565: VisualAge PL/I Enterprise V2.1 Upgrade from Prior
IBM PL/I Workstation or Competitive Products Program Package
CD-ROM
- 04L6567: VisualAge PL/I Enterprise V2.1 Upgrade from
Professional V2.0 Program Package CD-ROM
- 04L6566: VisualAge PL/I Enterprise V2.1 Upgrade from Standard
V2.0 Package CD-ROM
Cool Codes
by Robin Vowels
To display a progress summary on the same line on the PC screen,
use the following:
DCL ESC CHARACTER(1) INITIAL ('1B'X);
PUT SKIP EDIT ('Completed ', K, '%', ESC, '[1A' ) (A, F(3), 2 A);
To accept a password from the keyboard (without displaying it
on the screen), use the following:
declare ESC character (1) initial ('1B'x);
declare password character (20) varying initial ('');
put edit (ESC, '[8m') (A);
get edit (password) (L);
put edit (ESC, '[0m') (A);
As each keystroke is made, the cursor moves along the screen.
You will neeed to have ANSI.SYS loaded.