Chapter 2 Variables and Math

Syntax and Type

Fig-Forth v2 uses 4 kinds of variables within the dictionary space, each having a format built upon the concept of a fixed or local address within the system memory. The first type of variable is a 16 bit general storage space, created following the Forth79 or Fig-Forth lines. In this type of definition the initial or starting value of the variable precedes its declaration, followed by a name word of what the variable is to be called;

0 VARIABLE MYVALUE -- Creates a 16 bit variable with a starting value of Zero
10 VARIABLE NEWVALUE -- creates a variable with a starting value of 10.

Variables of this type may be accessed as a single signed 16 bit word or 2 unsigned 8 bit values by the appropriate functions listed in Table 2.1. When the word name of these variables is executed by direct or program command, the memory address of the variable's contents is returned on the parameter stack.

To facilitate larger data areas three other types of variables are possible, the 2VARIABLE, 4VARIABLE and ARRAY words. All words create the same type of structure as the basic VARIABLE word, but 2VARIABLE adds to the reserved space another 16 bit word for the purpose of saving a double precision number into the variable. As with VARIABLE, an initial value and name are required to complete the construction;

4. 2VARIABLE DOUBLE -- create a double word variable with the value of 4.

(Please note that the decimal point must be included in the numeric value to be saved to the variable, to force the compiler to create a double word number. See below.)

By contrast, the 4VARIABLE word expands the 2VARIABLE by a second double word, and does not require a starting value because their entry from the keyboard or file would be cumbersome;

4VARIABLE BIG-NUMBER -- create a variable for large values. (Starting value=0)

Note that quad values are stored in Low Double, High Double format, with the high word of each double saved in reverse notation. (As with doubles themselves.) Thus the following is true;

DOUBLE @ -- fetches the High Word of the double defined above
BIG-NUMBER @ -- fetches the High Word of the Lower Double in the quad
BIG-NUMBER 2@ -- fetches the Lower Double of the Quad Number
DOUBLE 2+ @ -- fetches the Low Word of the Double
BIG-NUMBER 4+ 2@ -- fetches the High Double of the Quad Number

Numeric constants come in three varieties for Fig-Forth v2, the word and double word fixed constants, and the single word arithmetic. As in the definitions of both VARIABLE and 2VARIABLE, the value of the constant must precede the definition. Fixed constants will return their value rather than their address when the word is executed;

15 CONSTANT MYSIZE -- create a constant of 15
5. 2CONSTANT MYWORD -- create a double-word constant of 5

The arithmetic constant is defined in the same manner as above, except that the constant value is added immediately to the top stack item at the time of execution;

5 +CONSTANT 5+ -- define a word of "five plus"
10 +CONSTANT DECA -- define a word that adds 10
0 5+ -- returns 5
6 DECA -- returns 16.

Finally, the ARRAY word expands upon the variable space by individual byte values, the size of that space being given before the ARRAY word. When such an array is constructed all bytes within the array are automatically filled with zeros, and the array returns its starting address value when run.

25 ARRAY MYSTRING -- create a byte array of 25 characters in size.
MYSTRING -- returns the address of the first byte.

The ARRAY word also resets the system variable NAE, (Next Array Element) such that a record oriented data structure can be defined using the word +OFF. This word defines a numeric offset within the array previously created, allowing that the resulting address may be adjusted to the start of the record desired. The +OFF word creates the same operation as the +CONSTANT definition, but keeps a running record of the offset defined within the NAE variable. For example;

150 ARRAY CUSTOMER -- define an array to hold customer data
35 +OFF .ADDRESS -- reserve 35 bytes for the name, set address location
43 +OFF .CITY -- reserve 43 bytes for street address, set city location
30 +OFF .ZIP -- reserve 30 bytes for the city, set Zip Code location

At this point the value of the NAE variable is 108, which will be reset when the next ARRAY is defined. Using this method allows Fig-Forth to create the proper constants by direct definition using the size limits for each record, returning the proper location in one of two ways;

CUSTOMER .CITY -- return address of customer's city string.

---or---

CUSTOMER.CITY -- customer's city

These "dotted" access words are fully understood by the input processor, generating the same code as would occur with a literal constant. Because Fig-Forth version 2.30 and up contains an internal code optimizer, the above sequence would generate a single Forth engine token and take one engine cycle to access the record. (See Chapter 10.)

For those cases where the period character is not appealing or would care to be avoided, the location of the system variable NAE+2 contains the character used to separate the terms. Note that you cannot use the +OFF word unless the first character matches the character defined in this location;

47 NAE 2+ C! OK. -- change separator to a slash mark.
12 +OFF .TEST Not terminated! -- attempt to use old character
12 +OFF /TEST OK. -- define value using new character
CUSTOMER/TEST 1K. -- use former array as source.

Owing to the free-form style of Fig-Forth such an array and its offsets may be defined in a top down manner, using the system variable of NEA to determine the size of the array to hold the record data. Because Fig-Forth begins its operation with the NEA value as zero, the array definition is not required to be the first operation;

35 +OFF .ADDRESS -- reserve 35 bytes for the name, set address location
43 +OFF .CITY -- reserve 43 bytes for street address, set city location
30 +OFF .ZIP -- reserve 30 bytes for the city, set Zip Code location
NEA @ CONSTANT C_SIZE -- define a constant of the array size
C_SIZE ARRAY CUSTOMER -- use the size to define the array

This process becomes quite transparent within stardard use, utilizing the compiler's internal bookkeeping operation for the creation of user records.

As a manual operation individual bytes or words can be added to the dictionary space via the comma or c-comma words, to expand variables to custom sizes, construct machine language routines, or other purposes;

0 VARIABLE MYVAR 0 C, -- makes a variable space of 3 bytes (24 bits)
0. 2VARIABLE MYVAR 0 , -- makes a variable space of 3 words (48 bits.)

Finally, custom assignments of reserved space are available through the word ALLOT, which adjusts the dictionary end point by the value specified;

0 VARIABLE MYSTRING 23 ALLOT -- create a byte array of 25 characters in size.
0 VARIABLE SMALL -1 ALLOT -- create a variable consiting of a single byte.

Note that in the use of ALLOT the reserved space is not initialized, such that it must be set to any starting values required before subsequent use.

See also Defining Statements and Functions, Chapter 6.

Using Decimal Numbers

The central core of all Math functions in Fig-Forth v2 is the Double Word Value, or integers within the range of -232 to +232-1. This size of number allows up to 8 decimal digits of mathematical accuracy, so long as the result remains within the range specified. During the input process Fig-Forth will accept any numeric string including that of decimal point containing values, converting the ASCII into a Non-Point or Traveling Point Integer for the current number base. For those unfamiliar with this process or term, Fig-Forth attempts to construct a Double Word Value from the given numeric string, ignoring any decimal point included in the process;

345.56 -- creates the double value of 34,556 on the parameter stack.
12.345 -- creates the double value of 12,345 on the parameter stack.

In this way Fig-Forth can resolve any 8 digit number into a fixed value for program operation. The System variable DPL holds the Decimal Point Location, to be used as an Exponent when manipulating these numbers. Using the above examples;

345.56 -- creates 34,556 on the stack with DPL set to 2.
12.345 -- creates 12,345 on the stack with DPL set to 3.

It is up to the programmer to separately retrieve and store the DPL value if any from the input process, and to make any adjustments to the double word values being used in any math operation. (This includes printing functions.) To maintain the accuracy of internal computations, Quad Word math routines have been added to this compiler.

Note: When inputting Single Word numbers (normal integers) Fig-Forth follows the same procedure above, however upon resolution of the NUMBER word the Fig-Forth command interpretter drops or discards the upper portion of the resulting value when a decimal point character is not detected. (Hence the need to always include a decimal point for any Double Word Value entered.)

Storage Operators

Once a variable's memory space has been assigned within the dictionary area, Fig-Forth v2 offers a wide variety of operators to access the data contained. Eight of these operators deal specifically with data storage or retrieval, given that the variable word has placed its address upon the parameter stack. The 8 operators can be grouped into four sets of reciprocal functions to set or retrieve the four data types;

Table 2-1. Storage Access Words.
Word Parameters Operation

C@

adr -- c

Fetch a Byte character from the specified address and save it on the stack as a 16 bit value. (Upper bits zeroed)

C!

c adr --

Store the byte item on the stack into the address. (Upper bits lost.)

@

adr -- n

Fetch a 16 bit word from the address specified.

!

n adr --

Store a word item into the 16 bit space of the top address.

2@

adr -- d

Fetch the double word value from the address specified.

2!

d adr --

Store the double word item into the top address given.

4@

adr -- qd

Fetch the quad word value from the address specified.

4!

qd adr --

Store the quad word item into the top address given.

No type-checking or address validity tests are made during the operation of these functions; they operate expressly as stated. Thus the following sequences would have the corresponding actions upon the variable listed;

MYVAR C@ Fetch a character from the variable MYVAR.
65 MYVAR C! Store an ASCII 'A' into variable MYVAR.
MYVAR @ Fetch a 16 bit word from MYVAR
65 MYVAR ! Store the number 65 into MYVAR.
MYVAR 2@ Fetch the double word value in MYVAR
65. MYVAR 2! Store the double word value of 65 into MYVAR.
------However------ ----Caution must be exercised----
65. MYVAR 2! Will destroy the dictionary chain if MYVAR is not a double.
MYVAR 2@ Will return an incorrect result if MYVAR is not a double.
65 MYVAR ! Will store an incorrect result when the double MYVAR is retrieved by using 2@.
65. 100 2! Will store the value directly into memory, causing potential damage to the user space.

The second class of variable operators are those intermixed with simple arithmetic, because variables are expected to contain fluctuating values that are often used as loop counters or memory pointers. As before, the type of operator used is explicit to the data being operated upon;

Table 2-2. Memory Math Words

-!

n adr -- Subtract the single number from the contents of the variable specified.

+!

n adr -- Add the single number to the contents of the variable specified.

2-!

d adr -- Subtract the double number from the contents of the variable specified.

2+!

d adr -- Add the double number value to the contents of the variable specified.

4-!

q adr -- Subtract the quad number from the contents of the variable specified.

4+!

q adr -- Add the quad number value to the contents of the variable specified.

The third class of general variable operators are the variable movers, which implicitly perform the combined functions of Fetch and Store in one operation. These words require two variable addresses and should not be mixed with their opposite types, or incorrect data may result. Again, no type checking of the targeted addresses is performed by the compiler.

Table 2-3. New Variable Movers*
-> VAR1 -> VAR2 Move the contents of word variable VAR1 to VAR2.
TO VAR1 TO VAR2 Move the contents of double word variable VAR1 to VAR2.

(*Hint: Remember that TO is very similar to TWO, meaning 2 words while -> moves one.)

The above words compile or execute the @! and 2@! functions from the kernel's list of definitions, and the latter words are held over for compatibility with previous versions. All new application source should use the above definitions, however the originals are included in the dictionary and can be used with caution because the RPN nature of Forth creates possible confusion in formatting them correctly;

Table 2-4. Out-dated Variable Moves
@! adr1 adr2 -- Move the word contents of adr2 to the contents of adr1.
2@! adr1 adr2 -- Move the double word contents of adr2 to the contents of adr1.

The biggest mistake one can make using the above words is not specifying the variables in the proper order, as in a VAR1 VAR2 @! sequence in an attempt to move the contents of Variable 1 to that of Variable 2. Such a statement is incorrect, for in reading the @! word its explicit form gives us "Fetch (@) and then Store (!)." Thus the proper statement to move the contents of Variable 1 to Variable 2 is VAR2 VAR1 @!. The new move functions clear up this confusion, compiling the addresses and command in their proper order.

For methods involving the movement of larger memory areas see the chapter on Strings, using the words STR>, CMOVE, -CMOVE, LMOVE and -LMOVE.

Finally, we come to the last of the variable operators, a function implemented for the compiler's internal use and made available to your programming. This command is TOGGLE, the sole direct variable operator of the Logical type. TOGGLE operates only upon the Byte contents of the specified address and does not follow the RPN notation of the previous commands;

VAR1 1 TOGGLE -- Will invert bit zero of variable VAR1

TOGGLE performs a Logical XOR of the data byte on the top of the stack with the byte contents of the address in the second stack item, to selectively set or reset Boolean values in the variable specified. This function is used by the compiler for completing definitions, and is called by SMUDGE.

Arithmetic Functions

Owing to the wide range and interpretation of integers allowed in Fig-Forth v2, a great many words exist in the vocabulary for handling these values. These operators include the four basic computations, along with mixed-type functions and operations meant to expand or allow for the expansion of the basic integer types. As a general rule, the smaller the operands corresponding to any function, the faster the function operates. There is no precedence followed by the Arithmetic functions, they are executed in the order received.

Basic Functions

The first set of operators are of course + - / *. Each of these words process single precision values, requiring two word-length 2's complement numbers upon which to operate. All will return a single word signed 2's complement number as a result. All values are integers, and no rounding or flooring occurs. If a divide overflow occurs the value returned will be zero and the OV flag will be set, while a multiply beyond the 16 bit limit will return the lowest 16 bits only of the operation.

The second set of operators are the Increment and Decrement functions of 1+ 2+ 3+ 4+ 1- 2- 3- and 4-. As each word name implies, the top stack item is incremented or decremented by the value of the command. Increments and Decrements operate upon the unsigned value of the number given, without an overflow being indicated in the event of a carry.

The third set of word operators are the U* and U/ words, which perform an unsigned multiply or divide upon the two values given. Specifically, U/ will divide an unsigned 16 bit number by a second unsigned 16 bit number, returning an unsigned 16 bit result. If a divide overflow occurs the value returned will be zero and the OV flag will be set. U* will multiply an unsigned 16 bit value by a second 16 bit unsigned value, returning a double word unsigned result.

The fourth set of basic operations are MOD and /MOD, which perform a divide and return the remainder of the answer. MOD returns the remainder alone while /MOD returns both the quotient and remainder upon the stack. If a divide overflow occurs the value returned will be zero and the OV flag will be set.

The last set of basic operators are the multi-word functions of D+ Q+ D- and Q- which will add and subtract double word signed values or quad values respectively.

Extended Functions

Beyond the basic set of operators for mathematic functions are the extended functions, or those functions which operate upon or return mixed number type values. Similar to U* mentioned in the Basic Functions collection, each of these words change their number types during processing for greater accuracy or results. In some cases the values returned are signed, while others are unsigned as specified.

The first such words are the number conversion definitions, which sign-extend a starting value into a number of the second type. Fig-Forth v2 contains three of these conversion definitions, meant to convert smaller width numbers into their larger word equivalents. S->D will convert a single precision value into a double word one, S->Q will convert a single value into a quad word number, and D->Q will convert a double word number into a quad word value.

The conversion of a larger word value into a smaller one is not supported by the kernel code, mainly because the resulting size is unpredictable without an additional flag to indicate the result. Since the inclusion of such a flag violates basic Forth definitions, it has not been included at this time. Users should define such a conversion routine for themselves when required by their program, or expect the larger word type for all operations.

The next extended math words are */ and */MOD, which perform a multiply followed by a divide of three 16 bit values. During the function of these words a 32 bit interim value is maintained, such that the result contains greater accuracy than a 16 bit multiply or divide alone. A common example of this increased accuracy is in the form of multiplying a value by a constant or irrational such as Pi;

RADIUS @ 355 113 */ -- multiply by Pi (to 6 places accuracy)
MYVAL @ 1960 1386 */ -- multiply by the square root of 2
MYVAL @ 1881 1086 */ -- multiply by the square root of 3
MYVAL @ 2866 1054 */ -- multiply by e.

And so on. */MOD performs the same function of */ but returns both the quotient and the remainder of the final division. If a divide overflow occurs the value returned will be zero and the OV flag will be set.

Finally, we get to the mixed-math words, of which U* is an example. All of the words in this class return values of different types after execution, or return values of differing types as appropriate to the definition. However, where U* is an unsigned multiplication of two 16 bit values to return a 32 bit unsigned result, M* will multiply two signed 16 bit values to return their signed 32 bit quotient.

M/ will divide a 32 bit double word number by a 16 bit word number, returning a signed 32 bit value as the result. M/MOD on the other hand performs the same function as M/, but returns both a 16 bit remainder and the 32 bit quotient. If a divide overflow occurs the value returned will be zero and the OV flag will be set.

The last category of these mixed math words is DU* and DU/, which call upon the Quad number system within the kernel. DU* will multiply two 32 bit (double) numbers and return a quad word result, while DU/ will divide a quad word number by a 32 bit value and return a 32 bit answer and its 32 bit remainder. All quad based arithmetic is unsigned at this time, however sign control is provided as outlined later. If a divide overflow occurs the value returned will be zero and the OV flag will be set.

Table 2-5. Mixed Math Words

word

stack

operation

S->D

n -- d

sign extend 16 bit n to 32 bits.

S->Q

n -- qd

sign extend 16 bit n to 64 bits.

D->Q

d -- qd

sign extend 32 bit n to 64 bits.

*/

n1 n2 n3 -- q

perform (n1*n2)/n3 in 32 bits.

*/MOD

n1 n2 n3 -- r q

(n1*n2)/n3 w/ remainder.

U*

u1 u2 -- ud

unsigned multiply, 32 bit result.

M*

n1 n2 -- d

signed multiply, 32 bit result.

M/

d n -- d

signed divide.

M/MOD

d n -- r d

signed divide, w/ 16 bit remainder

DU*

d2 d1 -- qd

unsigned multiply, 64 bit result.

DU/

qd d -- rd qd

unsigned divide, w/ 32 bit remainder.

OV

-- f

True if a divide overflow occurred

Trigonometric and Other Functions

Fig-Forth v2 contains two basic trigonometric functions, SIN and COS. These words are calibrated to operate given the target angle in degrees, and return the corresponding decimal value as a single precision word multiplied by 10,000. Angles are adjusted to their proper quadrant relative to the video screen's major axis or the 3 o'clock position as zero, and move in a clockwise direction for positive values.

Version 2.24 and beyond also contains the functions of SQR, 2SQR and 4SQR, which return the largest integer square root for the value given. As with other operations, the command name carries an explicit definition of the size of the value given, with the understanding that the value returned will be one-half the size of the source. I.e., SQR takes an integer and returns a byte value converted to an integer, 2SQR accepts a double word number and returns an integer, 4SQR accepts a quad number and returns a valid double. All square root functions contain an internal call to the associated absolute value routine, so user programs are not required to make this jump.

For the purposes of file block and buffer addressing, Fig-Forth v2 also has one specialized math word, the function of 1KU/MOD. This function right shifts the double word value given it by 11 Binary places, returning the bits shifted out as the second word and the remaining bits as the top word. See the section on Advanced Input Output and file addressing for more information.

Fig-Forth v2 also has the UP_CRC word, which performs a 16 bit logical CRC function with the byte value given it and the CRC system variable contents. This routine is designed to provide a Cyclic Redundancy Check value suitable for Ymodem communication, but can be used to verify program contents. Both of these words are located in the MOUSE vocabulary, along with the modem control functions.

Finally, Fig-Forth includes an internal pseudo-random number generator, loosely based upon the Lagged Fibonacci, UC Berkeley trinomial shift register, and a standard Monte Carlo routine. (I call it "My Super-Secret Random Generator.") This function will return a random integer when the RND0 word is executed, and should be seeded by the RANDOMIZE function before use. (Though the compiler does this internally as of version 2.25 and beyond when Fig-Forth is started, the range of the seed data used is limited.) When executing RANDOMIZE an address pointing to 500 bytes of seed data must be provided, which is copied to the generator for the purpose of creating the random sequence. As with most generators of this type, any single seed will produce the same results in a repeatable fashion. The precise formula used is;

Xf = (Xn-144 XOR Xn-317)*256 + (Xn-143 XOR Xn-316)

During the process the buffer tail is updated in the following manner;

Xn-498 = Xn-498 + (Xf AND 255)

Xn-499 = Xn-499 + (Xf/256) + CARRY (Xn-498)

Xn-500 = Xn-500 + CARRY (Xn-499) if n<498

Xn = Xn + CARRY (Xn-500) if n<498

n=n+1 MOD 499

The combined bytes of (Xn-498 through Xn) are treated as a 32 bit double number when adding Xf to the ring buffer before updating the N pointer, bringing any carry ahead 4 iterations in total when N<498. The Monte Carlo process dictates that any carry beyond N=499 is ignored, meaning that on the 498th pass the buffer update process is truncated to 16 bits. For an examination of the distribution pattern produced by this generator, execute the following commands;

ONLY ALSO VIDEO ALSO FORTH

: CDIST HGR13 BEGIN RND0 &A000 2DUP LC@ 1+ 15 MIN -ROT LC!

?TERMINAL UNTIL ;

This routine will produce a color spectral distribution pattern of all values output from the generator, (mod 216) starting with black and limiting itself to 15 hits per value. More advanced check routines can be found in the file RNDGEN.4TH. The period of this generator is equal to (2500-1)*231 with a suitably random seed. (7E159)

Because the internal function of the generator is XOR followed by a shifted ADD, the average run of the generator is 3, with a maximum value of 6 or 7 depending on the seed data and the current location of N.

Logical & Sign Control Functions

Fig-Forth v2 has five kinds of logical based functions, Boolean, Flow Control and Stack Control are mentioned elsewhere in this manual. Logical and Sign Control are mentioned here.

The first set of Logical Functions are the primary Boolean operators of AND, OR and XOR. Each of these act upon two 16 bit unsigned words, returning the 16 bit result as it applies to the function. TOGGLE is a unique function in that it operates only upon a memory pointer byte, using the lower 8 bits of the first parameter for it's second term.

The second set of Logical operators are the word number control functions of MIN, DMIN, MAX, DMAX and SPLIT. MIN and MAX accept two signed items and return the value consistent with their English meaning. SPLIT accepts a single 16 bit word value and returns two 8-bit values, the lower and upper 8 bits of the word respectively.

The third set of Logical operators are 2*, 2/, D2* and D2/, which perform logical shifts of word or double word values. In all cases of logical shifts a 16 bit word is returned on the top of the stack with the shifted-out bit in the least significant digit. The source value as changed is beneath the shifted bit word, and Zeros are shifted into the least significant bit for the direction of the shift.

The forth type of Logical function is simple Sign Control, the ABS, DABS, QABS and MINUS, DMINUS and QMINUS number functions. ABS in any form returns the absolute value of the number given, while MINUS of any type will create the 2's complement of the current value. With these and sign-checking of the most significant word for each number, returning the proper value is a simple matter of flow control.

Finally, the words of +-, D+- and Q+- apply the sign carried by a single word value on top of the stack to the targetted value located beneath it. As with other operations no type checking is employed for the stack's depth or contents when executing these words.

Please make note however that the word SIGN is to be used only during Number Formatting, and cannot be used as a numeric sign function.

Boolean Functions

Fig-Forth v2 has five kinds of logical based functions, Flow Control, Logic & Sign Control and Stack Control are mentioned elsewhere in this manual, while Boolean type are mentioned here. These functions are the Logical compare routines which return a truth flag value alone, generally destroying the terms which they have used. As a matter of routine Fig-Forth v2 declares that only a Zero is a False condition, while any other value is considered True. The logical operators return a value of 1 if the condition is met, or a zero if the condition is not met. Many of these definitions have been included for programmer convenience.

All Boolean values (except subtract) can be used with the Logical Functions of AND, OR and XOR, but by Forth convention should not be used arithmetically.

Table 2-6. Logical Comparisons

word

stack

function

0=

n -- f

Returns True if n equals Zero.

0<

n -- f

Returns True if n is negative.

-

n n -- n

Subtract: Though not generally considered a logical, it returns True if the second item DOES NOT equal the first.

=

n1 n2 -- f

Returns True if n1 equal n2.

<

n1 n2 -- f

Returns True if n1 is less than n2.

>

n1 n2 -- f

Returns True if n1 is greater than n2.

<>

n1 n2 -- f

Returns True if n1 and n2 are not equal.

=>

n1 n2 -- f

Returns True if n1 is equal to or greater than n2.

>=

n1 n2 -- f

Returns True if n1 is equal to or greater than n2.

<=

n1 n2 -- f

Returns True if n1 is equal to or less than n2.

=<

n1 n2 -- f

Returns True if n1 is equal to or less than n2.

D=

d1 d2 -- f

Returns True if double d1 equals double d2.

D<

d1 d2 -- f

Returns True if double d1 is less than double d2.

D>

d1 d2 -- f

Returns True if double d1 is greater than double d2.

D0=

d -- f

Returns True if double number equals zero.

U<

n1 n2 -- f

Returns True if unsigned n1 is less than unsigned n2.

U>

n1 n2 -- f

Returns True if unsigned n2 is greater than unsigned n2.
WITHIN

n1 n2 n3 -- f

Returns True if n2 <= n1 < n3.

Number Formatting Functions

Though closely related to the chapter on Strings, Fig-Forth v2 has a variety of number formatting and printing functions, which operate on each number type within the above definitions. For ease of outputting values contained on the stack or within variables, the following words will print the associated numbers without formatting;

Table 2-7. Unformatted Number Printing

word

stack

operation

.

n --

print a signed single precision value

?

adr --

print contents of single precision variable

u.

u --

print an unsigned single precision value

d.

d --

print a signed double precision value

q.

q --

print a signed quad precision value (see note)

The quad number print word listed above is only accurate to 260th, while the numbers themselves are 263rd. The definition of this word is listed below should you desire to modify or change the printing of numbers of this type.

          : Q. >R R QABS <# BEGIN 1000000000. DU/ 2SWAP 2OVER OR IF 9 0 DO # LOOP

               ELSE #S THEN 2DROP 2DUP OR WHILE D->Q REPEAT R> 0< IF &2D HOLD

               THEN #> TYPE SPACE ;

The above definition demonstrates some of the number picture format functions in Fig-Forth v2, with the complete list shown in table 2-8. The number formatting process begins with the <# word, which sets the system variable HLD to the value returned by PAD. This "scratch pad" area is defined as 88 bytes beyond (deeper) in the dictionary area than the current dictionary end point, and is consumed backwards towards the dictionary tail as the number format words operate. At the end of the number format process the #> word places the address of this space and number of characters contained in it upon the parameter stack, for printing with the TYPE word.

Table 2-8. Number Formatting Words

word

stack

function

<#

--

initialize formatting variables.

#>

d -- adr n

drop double number, retrieve address and length of output string.

#

d -- d

extract one digit in the current number base.

#S

d -- d0

extract all remaining digits in the current number base.

SIGN

hw1 lw hw -- lw hw

extract the sign from hw1 and place minus sign in buffer if negative. (hw1 d -- d)

HOLD

c --

place character c into the hold buffer.

.R

n1 n2 --

print single precision n1 right justified to n2 columns.

D.R

d1 n1 --

print double precision d1 right justified to n1 columns.

Number picture formatting is defined from the Least Significant Digit to the higher ones within the double word values given the operation, and allows the use of mathematical, logical or flow control operations within the structure as show above for q-dot.

Examples
: .$ <# # # 46 HOLD #S 36 HOLD #> TYPE ; -- prints 1234. as $12.34
: .DATE <# # # 47 HOLD # # 47 HOLD #S #> TYPE ; -- prints 123456. as 12/34/56
: .PH <# # # # # 45 HOLD # # # #> TYPE ; -- prints 1234567. as 123-4567

Return to Contents.   Next Chapter.    Previous Chapter.