Numeric objects in RPL models (long) Message #12 Posted by James M. Prange (Michigan) on 7 Jan 2008, 2:55 p.m., in response to message #8 by Karl Schneider
For the RPL models, which use the Saturn processor or an emulated
"Saturn+" processor, each object starts with its prologue address
(a 5nibble address pointer to its "prologue", the ROM code that
executes that type of object), followed by the "body" of the
object.
Note that some objects are built into ROM, in which case they may
be represented by 5nibble pointers to the objects in ROM.
Everything is stored in memory in littleendian order
(leastsignificant nibble first), but when loaded into one of the
processor's registers (or a field of a register), the lowest
nibble from memory ends up as the least significant nibble in the
register or field (bigendian order). Similarly, when a register
or field is copied to memory, its leastsignificant nibble is
stored at the starting address.
For a "real" number object, the prologue address is 02933, and the
body is 16 BCD nibbles and fits perfectly into one of the Saturn
processor's 64bit working or scratch registers. Let's represent
this object as 33920EEEMMMMMMMMMMMMS.
The first three nibbles of the body represent the exponent from
499 through 499, with negative exponents in the ten's complement
form. For example, 1 is represented in ten's complement form as
999, and 499 as 501. But remember that it's stored in
littleendian order, so 499 is actually stored in memory as 105.
The next twelve nibbles are the mantissa, with an implied decimal
point between the 1st and 2nd digits, with the first nibble
nonzero for nonzero numbers, again in littleendian order
The last nibble is used for the sign, with 0 representing
nonnegative and 9 representing negative.
But when loaded into the processor's register, the nibbles of the
body are loaded in reverse order, so it becomes SMMMMMMMMMMMMEEE,
that is, first the sign, then the mantissa, and finally the
exponent, with the mantissa and exponent in bigendian order.
Some examples:

1.23456789012E499 is stored as 339209942109876543210 (breaking
this down, 33920 is the prologue address, 994 is the exponent,
210987654321 is the mantissa, and 0 is the sign nibble, all in
littleendian order), and the body is loaded into a register as
0123456789012499 (breaking this down, 0 is the sign nibble,
123456789012 is the mantissa, and 499 is the exponent, all in
bigendian order).

1.23456789012E499 is stored as 339209942109876543219, and the
body is loaded into a register as 9123456789012499.

1.23456789012E499 is stored as 339201052109876543210, and the
body is loaded into a register as 0123456789012501.

1.23456789012E499 is stored as 339201052109876543219, and the
body is loaded into a register as 9123456789012501.
Note that the real numbers 9 through 9 are compiled as ROM object
pointers. When loaded into a register, the body of the object
pointed to is loaded.
For a complex number object, the prologue address is 02977, and
the body consists of the bodies of two "real" numbers, with the
real part first, followed by the imaginary part.
For an extended real number object (SysRPL only), the prologue
address is 02955, and the body is 21 BCD nibbles, starting with
5 nibbles representing the exponent from 49999 through 49999
(again with negative exponents in ten's complement form), followed
by a 15nibble mantissa, followed by the sign nibble, 0 for
nonnegative or 9 for negative. In the processor, the mantissa and
sign nibble use one entire working or scratch register, and the
exponent uses the "address" field of another.
For an extended complex number object (SysRPL only), the prologue
address is 0299D, followed by the bodies of two extended real
numbers.
For a "hex string" object (used for user binary integers), the
prologue address is 02A4E, and the body starts with a 5nibble
selfinclusive length field (in hexadecimal), followed by the
nibbles of the hexadecimal number. User binary integers are always
stored as 16nibble (64bit) integers, so always have a "length"
of 00015 hex (21 decimal) (excluding the prologue address, of
course). Although you can (in SysRPL) have hex strings with values
longer than 16 nibbles, the available RPL arithmetic commands for
hex strings use no more than the leastsignificant 64 bits
(respecting the current wordsize), and it's up to the programmer
to deal with this, presumably using hex "substrings" with values
of no more than 16 nibbles each to fit into the processor's
registers.
For a system binary integer object (bint) (SysRPL only), the
prologue address is 02911, and the body consists of a 5nibble
hexadecimal number.
In the 49 series, we can have an "exact integer" (zint), which has
a prologue address of 02614, and the body starts with a 5nibble
selfinclusive length field (as always, in hexadecimal), followed
by the BCD nibbles of the integer, followed by a sign nibble, 0
for nonnegative or 9 for negative. The zint 0 is the exception,
being stored as 41620600000, which I suppose we could say has the
BCD integer nibble 0 with a missing sign nibble, or else as having
no BCD integer nibble, with a nonnegative sign; in any case, it's
the only zint with a length of 00006.
Note that the zints 9 through 9 are compiled as ROM object
pointers.
An array object (used for a real or complex vector or matrix in
UserRPL, and not to be confused with the 49 series' "symbolic
matrix") has a prologue address of 029E8, and the body starts with
a selfinclusive length field (number of nibbles in the entire
body), followed by a 5nibble prologue address indicating which
type its elements are (all must be the same type), followed by a
5nibble dimension count field, followed, for each dimension, by a
5nibble dimension size field, and finally followed by the object
bodies of its elements, in order. All elements must be present.
For arrays compiled from UserRPL source code, the element type
will always be "real number" or "complex number", and the
dimension count will always be 1 for a "vector" or 2 for a
"matrix"; note that the UserRPL commands for arrays are intended
for these kinds of arrays only; experiment with trying them with
other kinds of arrays at your own risk.
A linked array (SysRPL only) has a prologue address of 02A0A, and
the body starts with a selfinclusive length (number of nibbles in
the entire body), followed by a prologue address indicating which
type its elements are (all must be the same type), followed by a
5nibble dimension count field, followed, for each dimension, by a
5nibble dimension size field, followed by a pointer table,
followed by the elements (object bodies). The pointer table
consists of selfreferencing 5nibble forward offsets to the
actual elements. All pointers must be present, and each must
either point to a valid element or have the value of 00000. A
pointer value of 00000 indicates a missing element at that
position in the array. The elements (object bodies) themselves may
be in any order. Note that more than one pointer may point to the
same element. As far as I know, there are very few supported
SysRPL commands for dealing with linked arrays. Linked arrays of
character strings are used for some of the builtin message
tables, but I don't know whether linked arrays are used anywhere
else in ROM. You could, for example, make an identity matrix with
a 5nibble pointer for each element, but using only two actual
elements, the 16nibble object bodies for the real numbers 0 and
1.
All of the above are "atomic" objects; that is, they can't contain
any proper "objects", complete with their own prologue addresses.
In the 49 series, we can also have a "symbolic matrix", which is a
"composite" object, similar to a list, or a list of samesized
"sublists". Each element is a complete object in itself (or an
object pointer). The elements can be real numbers, complex
numbers, zints, or algebraic objects (or pointers to objects of
these types), or any combination of these, and all elements must
be present. The prologue address is 02686, and the object body
ends with an object pointer to the primitive code object (pco)
SEMI, at 0312B. A 1dimensional symbolic matrix object starts with
the prologue address, followed by the element objects (or object
pointers), followed by the object pointer to SEMI. A 2dimensional
symbolic matrix object starts with the prologue address, followed
by a series of samesized 1dimensional symbolic matrix objects,
and ends with the object pointer to SEMI. The UserRPL compilers
will build only 1 or 2dimensional symbolic matrices. In concept,
we can use the development tools to build a symbolic matrix with
more dimensions (as arrays and linked arrays can have), but I
don't know how the system will handle them; experiment at your own
risk.
Of course the various "numeric" objects can also be embedded
within the composite objects lists and programs, and for some
types, within algebraic objects, and a unit object always includes
a real number object and sometimes real number objects for powers.
Of course, the size of everything is limited by available memory.
For example, a hex string or zint could, in concept, have a length
field of FFFFF hex (10448575 decimal), which would make an object
(including the prologue address) of 1048580 nibbles or 524290
bytes, but the calculators don't have enough system RAM to hold
anything that large.
Regards, James
Edited: 7 Jan 2008, 3:06 p.m.
