# Jaap's Psion II Page

```                                CHAPTER 15

_______________
MATHS FUNCTIONS

This chapter describes the floating-point mathematics  routines  (add,
subtract,  multiply  and divide), the scientific functions and the routines
to convert between a floating-point number and an ascii text string.

______________________
15.1  FLOATING-POINT NUMBERS

These consist of a 12-digit precision BCD-packed mantissa with one byte for
the  sign  and  a  one byte signed binary exponent.  They are structured as
follows:  (low memory -> high memory)

mantissa_1      low-order byte
mantissa_2          .
mantissa_3          .
mantissa_4          .
mantissa_5          .
mantissa_6      high-order byte
exponent        1 byte
sign            1 byte

Each byte of the mantissa contains two decimal digits, the high-order digit
in  the  top 4 bits and the low-order digit in the bottom 4 bits.  The sign
byte has the normal sign convention i.e.  negative if bit  7  set,  positive
otherwise.   Standard practice in the Organiser operating system is \$80 for
negative and zero for positive.  An  exponent  of  zero  (with  a  non-zero
mantissa)  implies  that  the  value  of  the  number  lies  between  1 and
9.99999999999 inclusive.

The mathematical routines operate on two  floating-point  registers,  which
are  identical  in  structure to the floating-point numbers described above
except for the addition of a guard byte to the mantissa.  These  bytes  are
used for rounding purposes.

The registers are arranged in zero-page  memory  as  follows  (see  section
6.5.1.2 on memory usage):
_______    _____________           ________

\$c5      MTT_AMAN               accumulator: guard byte
\$c6         -                   start of accumulator mantissa
\$cc      MTB_AEXP               accumulator exponent
\$cd      MTB_ASGN               accumulator sign

\$ce      MTT_OMAN               operand: guard byte
\$cf         -                   start of operand mantissa
\$d5      MTB_OEXP               operand exponent
\$d6      MTB_OSGN               operand sign

Thus the floating-point number -12345.0006789 can be declared as follows:

FP_CONST:
.BYTE   \$89,\$67,\$00,\$50,\$34,\$12         ;mantissa
.BYTE   4                               ;exponent
.BYTE   \$80                             ;negative sign

and copied into the accumulator by the following code:

LDD     #MTT_AMAN+1
LDX     #8
STX     UTW_S0:
LDX     #FP_CONST
OS      UT\$CPYB

_________________________
15.2  FLOATING-POINT ARITHMETIC

The four binary  operators  add,  subtract,  multiply  and  divide  operate
directly on the floating-point registers in the order

accumulator (operator) operand = accumulator

e.g.  to do the operation 6/3 = 2, 6 is placed in the accumulator, 3 in the
operand  and  the  result after calling mt_fdiv will be in the accumulator.
Any number used as an argument to these routines must  be  normalised,  i.e.
the  most  significant  digit  of  the  mantissa  must  be non-zero for all
non-zero numbers.  Any number having zero in the most significant  byte  is
treated as zero.  For example declaring the number 0.00009999 as follows

.BYTE   0,0,\$99,\$99,0,0         ;most significant digit is zero
.BYTE   -1
.BYTE   0

.BYTE   0,0,0,0,\$99,\$99         ;non-zero digits shifted to
;most significant position
.BYTE   -5                      ;and exponent adjusted accordingly
.BYTE   0

These routines also require the exponent to be in the range -99 to 99.  The
result  is  always  returned  as  a normalised floating-point number in the
accumulator, the operand remains  unchanged,  and  both  guard  digits  are
cleared to zero.  No validation is made of the contents of the registers on
input, and the arithmetic routines  will  attempt  to  operate  on  invalid
floating-point numbers with unpredictable results.

To prevent it from being corrupted, the operand is copied into the start of
the work buffer MTT_WBUF at \$2288 (see section 6.5.1.3 on memory usage) and
then restored before returning from the routine.

A description of the system services to  handle  floating-point  arithmetic
follows.

_______

VECTOR NUMBER:          082
INPUT PARAMETERS:       Floating-point registers contain the two numbers
OUTPUT VALUES:          Accumulator contains accumulator + operand.

DESCRIPTION

Does a floating-point add on the accumulator and operand registers.

When adding two numbers of equal exponent, the register  mantissas  are
added  (or the smaller mantissa subtracted from the larger if the signs
are not the same).  The exponent is incremented  by  1  if  the  result
overflows,  and decremented if underflow occurs in subtraction.  If the
exponents differ,  the  mantissa  of  the  register  with  the  smaller
exponent  is  shifted  to  the  right (downwards in memory) by n digits
where n is the difference  between  the  two  exponents.   The  shifted
mantissa  is  then  added  to or subtracted from the other.  The larger
exponent is taken as the exponent of the  result  after  adjusting  for
over- or underflow as above.

The alignment and addition/subtraction of mantissas are always done  on
the  full 7 bytes of the register mantissas, i.e.  to 14 digit accuracy.
If the result requires more than 12  digits  of  precision,  the  guard
digits are used to round the least significant digit accordingly.

EXAMPLE

To add 1.0E+11 and 202.88, the following constants can be set up:

FP_CONST1:
.BYTE   0,0,0,0,0,\$10           ;mantissa
.BYTE   11                      ;exponent
.BYTE   0                       ;positive sign
DUMMY_GUARD_BYTE:
.BYTE   0
FP_CONST2:
.BYTE   0,0,0,\$80,\$28,\$20       ;mantissa
.BYTE   2                       ;exponent
.BYTE   0                       ;sign

and the following code executed (taking advantage of the fact that  the
operand follows immediately after the accumulator in memory):

LDD     #MTT_AMAN+1             ;D -> byte above guard digit
LDX     #2*SZBCD+1              ;length to move
STX     UTW_S0:
LDX     #FP_CONST1
OS      UT\$CPYB                 ;copy constants into registers

then after the mantissas  have  been  aligned  they  will  contain  the
following:

________                    ___________
Mantissa                    Guard Digit

Accumulator:            10 00 00 00 00 00           00
Operand:                00 00 00 00 02 02           88

Result after adding:    10 00 00 00 02 02           88

Before returning this is rounded up and  the  guard  digit  cleared  to
give:

10 00 00 00 02 03           00

ERRORS:                 ER_MT_EX - exponent overflow
i.e. MTB_AEXP > 99 or MTB_AEXP < -99

_______
15.2.2  MT\$FSUB

VECTOR NUMBER:          090
INPUT PARAMETERS:       Floating-point registers contain the two numbers
to be subtracted.
OUTPUT VALUES:          Accumulator contains accumulator - operand.

DESCRIPTION

Subtracts the floating-point operand from the accumulator.

The subtract routine simply toggles the sign byte of  the  operand  and
adds  the registers as described in MT\$FADD above, and is called in the
same way.

ERRORS:                 ER_MT_EX - exponent overflow
i.e. MTB_AEXP > 99 or MTB_AEXP < -99

_______
15.2.3  MT\$FNGT

VECTOR NUMBER:          089
INPUT PARAMETERS:       X register - address of the floating-point
register to be negated.
OUTPUT VALUES:          None.

DESCRIPTION

Toggles the sign of the register pointed to by X.

Note that as this routine operates on a register, it assumes a mantissa
length  of  7  bytes.  To negate a normal BCD number, X should point to
the byte below the first byte of the number in memory.

EXAMPLE

To change the sign of the accumulator, execute the following code:

LDX     #MTT_AMAN
OS      MT\$FNGT

and to negate the constant 202.88 in the addition  example  in  section
15.2.1 above:

LDX     #FP_CONST2-1
OS      MT\$FNGT

REGISTERS PRESERVED:    B and X.
ERRORS:                 None.

_______
15.2.4  MT\$FMUL

VECTOR NUMBER:          088
INPUT PARAMETERS:       Floating-point registers contain the numbers
to be multiplied.
OUTPUT VALUES:          Accumulator contains accumulator * operand.

DESCRIPTION

Performs a floating-point multiply on the BCD registers.

The mantissas are  multiplied  by  repeated  addition  of  the  operand
mantissa into a temporary 28-digit double-precision mantissa (14 bytes)
located in the floating-point  work  buffer  (see  section  6.5.1.3  on
memory usage) at MTT_WBUF+8, i.e.  immediately following the stored copy
of the operand (see 15.2 above).  The top seven bytes,  i.e.   the  most
significant  14  digits,  are  then  copied from this register into the
accumulator and rounded to 12 digits as for addition above.

EXAMPLE

To multiply pi (3.14159265359) by -7160, set up the following:

FP_PI:
.BYTE   \$59,\$53,\$26,\$59,\$41,\$31 ;mantissa
.BYTE   0                       ;exponent
.BYTE   0                       ;sign
DUMMY_GUARD_BYTE:
.BYTE   0
FP_CONST:
.BYTE   0,0,0,0,\$60,\$71         ;mantissa
.BYTE   3                       ;exponent
.BYTE   \$80

and execute the following code (taking advantage of the fact  that  the
operand follows immediately after the accumulator in memory):

LDD     #MTT_AMAN+1             ;D -> byte above guard digit
LDX     #2*SZBCD+1              ;length to move
STX     UTW_S0:
LDX     #FP_PI
OS      UT\$CPYB                 ;copy constants into registers
OS      MT\$FMUL

The accumulator will now contain the result of -22493.8033997 and  will
look like this:

MTT_AMAN:   00
MTT_AMAN+1: 97
MTT_AMAN+2: 39
MTT_AMAN+3: 03
MTT_AMAN+4: 38
MTT_AMAN+5: 49
MTT_AMAN+6: 22
MTB_AEXP:   04
MTB_ASGN:   80

The operand is not affected by the operation, so still contains -7160.

ERRORS:                 ER_MT_EX - exponent overflow
i.e. MTB_AEXP > 99 or MTB_AEXP < -99

_______
15.2.5  MT\$FDIV

VECTOR NUMBER:          087
INPUT PARAMETERS:       Floating-point dividend in accumulator, divisor in
operand.
OUTPUT VALUES:          Accumulator contains accumulator / operand.

DESCRIPTION

Performs a floating-point divide on the BCD registers.

The mantissas are divided  by  repeated  subtraction  of  the  operator
mantissa  from the accumulator mantissa, with the result being built up
in a seven-byte temporary mantissa located  at  MTT_WBUF+8.   Once  the
process  is  complete,  the  contents  of  the  register  are copied to
MTT_AMAN and rounded to 12 digits as with multiplication above.

EXAMPLE

To divide the result of -22493.8033997 obtained in  the  multiplication
example above by 0.00654, first set up the divisor as a constant:

FP_DIVISOR:
.BYTE   0,0,0,0,\$40,\$65         ;mantissa
.BYTE   -3                      ;exponent
.BYTE   0                       ;sign

then execute the following code:

LDD     #MTT_OMAN+1             ;target is operand
LDX     #SZBCD                  ;length of one f.p. number
STX     UTW_S0:
LDX     #FP_DIVISOR
OS      UT\$CPYB                 ;copy divisor into operand
OS      MT\$FDIV                 ;and do division

The accumulator will now contain the  result  -3439419.48008  and  will
look like this:

MTT_AMAN:   00
MTT_AMAN+1: 08
MTT_AMAN+2: 80
MTT_AMAN+3: 94
MTT_AMAN+4: 41
MTT_AMAN+5: 39
MTT_AMAN+6: 34
MTB_AEXP:   06
MTB_ASGN:   80

ERRORS:                 ER_MT_EX - exponent overflow
ER_MT_DI - divide by zero

_________________________________________
15.3  CONVERTING NUMERIC TEXT TO FLOATING POINT

15.3.1  MT\$BTOF

VECTOR NUMBER:          081
INPUT PARAMETERS:       X register - address of start of input string.
D register - address of target floating-point
number.
OUTPUT VALUES:          Floating-point representation of input string.
X points to terminator at end of input string.

DESCRIPTION

Converts the numeric ascii string at X to the floating-point number  at
D.   The string may be terminated by any character which is not numeric
(and not by ".", "E" or "e" unless these have  previously  occurred  in
the input string).

The floating-point result is returned in  the  8  bytes  following  the
address  given by D on entry (D should be preserved before calling this
routine, as there is no pointer to the result on exit from it).

Error ER_MT_IS is returned if:

-  The exponent is greater than 99 or less than -99  (irrespective  of
the value of the mantissa)

-  The input string contains more  than  12  significant  digits  (not

-  The total of significant digits + trailing zeros exceeds 44

-  There are no valid numeric digits in the mantissa (e.g.  .E5)

-  There are no valid numeric digits in the exponent (e.g.  6E)

EXAMPLE

The following code will convert the string "172.65" to floating-point:

LDX     #INP_STRING
LDD     #FP_BUF
OS      MT\$BTOF

INP_STRING:
.ASCIZ  "172.65"

FP_BUF:
.BLKB   8

It may be useful to put the floating-point representation of  a  string
into  one  of  the  registers used by the arithmetic routines described
above.  The  following  code  will  convert  the  same  string  into  a
floating-point number in the accumulator:

LDX     #INP_STRING
LDD     #MTT_AMAN+1             ;skip guard digit
OS      MT\$BTOF

ERRORS:                 ER_MT_IS - String to floating-point failed

________________________________________
15.4  CONVERTING FLOATING-POINT TO TEXT STRING

There are four routines to handle this, one for each of  the  four  formats
decimal,  scientific,  integer  and  general.   On  entry,  the  X register
contains the address of the start of the  output  string,  the  A  register
contains  the maximum length of the output string, and the B register gives
the number of decimal places if relevant.  The  floating-point  accumulator
(see  section  15.1 on floating-point numbers above) is always taken as the
source number to  be  converted,  since  it  contains  the  result  of  all
floating-point arithmetic operations.

The floating-point work buffer MTT_WBUF  (see  section  6.5.1.3  on  memory
usage) is used to build up the intermediate result, which is then copied to
the output area pointed to by X provided there is sufficient space for  it.
The floating-point registers are preserved.

If   successful,   these   routines   return   the   output   string   (not
zero-terminated) at the address given by X on entry, with the length of the
string in B.  There is no right-justification  of  the  string  within  the
given field width.  X should be preserved before calling these routines, as
there is no pointer to the output string on exit.

There is no validation of the number contained in the accumulator, so if it
contains garbage then the output routines will produce garbage.

A description of the four routines for floating-point  to  text  conversion
follows.

15.4.1  MT\$FBDC

VECTOR NUMBER:          083
INPUT PARAMETERS:       A register - field width of output string.
B register - decimal places required.
X register - address of output buffer.
OUTPUT VALUES:          B register - length of the output string.

DESCRIPTION

Converts floating-point accumulator  to  numeric  ascii  text,  decimal
format.   This  is  the  format nnnn.nnn, i.e.  a decimal number with no
exponent.  If the number of significant digits after the decimal  point
is  greater  than  the  decimal  places  specified  in B, the number is
rounded off to B decimal places.  Otherwise it is  zero-filled  on  the
right to make up the necessary decimal places.

EXAMPLES

The following  code  will  convert  the  value  172.65  placed  in  the
accumulator  in  the  example  in  MT\$BTOF  (section 15.3.1 above) to a
decimal format string with 5 decimal places in a field width of 16:

LDX     #STRING_BUF
LDD     #16*256 + 5     ;field width in A, dec. places in B
OS      MT\$FBDC

STRING_BUF:
.BLKB   16

STRING_BUF will now contain the string "172.65000" and the  B  register
will  contain  9.   The  string  will  not  be  zero-terminated  unless
STRING_BUF is zero-filled before the routine is called.

Further  examples  of  the  output  strings  corresponding  to  various
floating-point values follow:

___________         _____   ___________     _____________
Accumulator         Width   Dec. Places     Output String

0.0000004            20        4            0.0000
0.00006              20        4            0.0001
0                    20        4            0.0000
1234.5               20        4            1234.5000
1234.5                8        4            Error
(Width too small)
34E+10               20        4            340000000000.0000
9E+20                60       14            Error
(Too long for work buffer)

ERRORS:                 ER_MT_FL - output string too long for field width
or greater than maximum work buffer length of 34

15.4.2  MT\$FBEX

VECTOR NUMBER:          084
INPUT PARAMETERS:       A register - field width of output string.
B register - decimal places required.
X register - address of output buffer.
OUTPUT VALUES:          B register - length of the output string.

DESCRIPTION

Converts  floating-point  accumulator  to  numeric   ascii   text,   in
exponential  (scientific)  format.   This is in the form n.nnnnnE+nn, a
decimal mantissa with one digit before the decimal  point  followed  by
the  exponent.   The  exponent  is  always  expressed  as a + or - sign
followed by 2 numeric digits.

EXAMPLES

The following  code  will  convert  the  value  172.65  placed  in  the
accumulator  in  the  example  in  MT\$BTOF (section 15.3.1 above) to an
exponential format string with 4 decimal places in a field width of 16:

LDX     #STRING_BUF
LDD     #16*256 + 4     ;field width in A, dec. places in B
OS      MT\$FBEX

STRING_BUF:
.BLKB   16

STRING_BUF will now contain the string "1.7267E+02" and the B  register
will  contain 10.  Further examples of the output strings corresponding
to various floating-point values follow:

___________         _____   ___________     _____________
Accumulator         Width   Dec. Places     Output String

0                    10         4           0.0000E+00
640                  16         4           6.4000E+02
112233445566         30        16           1.1223344556600000E+11
112233445566         20        16           Error
(Width too small)
0.000071             10         0           7E-05
0.000076             10         0           8E-05
0.99999              10         3           1.000E+00

ERRORS:                 ER_MT_FL - output string too long for field width
or greater than maximum work buffer length of 34

15.4.3  MT\$FBIN

VECTOR NUMBER:          086
INPUT PARAMETERS:       A register - field width of output string.
X register - address of output buffer.
OUTPUT VALUES:          B register - length of the output string.

DESCRIPTION

Converts floating-point accumulator to numeric ascii text,  in  integer
format.   The value in the B register is irrelevant in this routine, as
there  are  no  decimal  places  involved.   If  the   value   in   the
floating-point accumulator is not an integer, then the string output is
the accumulator value rounded to the nearest integer.

EXAMPLES

The following  code  will  convert  the  value  172.65  placed  in  the
accumulator  in  the  example  in  MT\$BTOF (section 15.3.1 above) to an
integer format string in a field width of 16:

LDX     #STRING_BUF
LDA     A,#16           ;field width in A
OS      MT\$FBIN

STRING_BUF:
.BLKB   16

STRING_BUF will now contain the string "173" and the  B  register  will
contain  3.   Further  examples  of the output strings corresponding to
various floating-point values follow:

___________         _____           _____________
Accumulator         Width           Output String

-10102               10             -10102
500                   3             500
-500                  3             Error
6666.7               10             6667
0                    10             0
0.0002                5             0

ERRORS:                 ER_MT_FL - output string too long for field width
or greater than maximum work buffer length of 34

15.4.4  MT\$FBGN

VECTOR NUMBER:          085
INPUT PARAMETERS:       A register - field width of output string.
B register - number of decimal places
(disabled if negative).
X register - address of output buffer.
OUTPUT VALUES:          B register - length of the output string.

DESCRIPTION

Converts floating-point accumulator to numeric ascii  text  in  general
format,  i.e.   in  whichever  of  the  above  three formats is the most
suitable for the given number and field width.

The output string will  be  in  integer  format  if  the  number  is  a
floating-point  integer,  otherwise decimal format.  If the field width
is not sufficient for the above, the number  is  output  in  scientific
format  rounded  to  as  many decimal places as can be accommodated.  A
field width of 7 is sufficient to  convert  any  floating-point  number
without  returning  an  error, though severe truncation of the mantissa
may result.

Fixing the number of decimal places is optional, and is disabled  if  B
is  negative  (bit  7  set).  In this case the number of decimal places
will be set equal to the number of significant digits to the  right  of
the  decimal  point.   If B is positive, then it contains the number of
decimal places to be fixed.

EXAMPLES

The following  code  will  convert  the  value  172.65  placed  in  the
accumulator  in the example in MT\$BTOF (section 15.3.1 above) to a text
string in a field width of 16:

LDX     #STRING_BUF
LDA     B,#\$80          ;disable fixed decimal places
LDA     A,#16           ;field width in A
OS      MT\$FBGN

STRING_BUF:
.BLKB   16

STRING_BUF will now contain the string "172.65" and the B register will
contain 6.  Note that the format in this case is decimal as this can be
fitted into the given width.  Further examples of  the  output  strings
corresponding to various floating-point values follow:

___________         _____   ___________     _____________
Accumulator         Width   Dec. Places     Output String

0                     1     Disabled        0
3000000.078          20     Disabled        3000000.078
-0.00005              8     Disabled        -0.00005
-0.00005              7     Disabled        -5E-05
123456789012000000   16     Disabled        1.2345678901E+17
0.00123456789012     16     Disabled        0.00123456789012
0.99999999            6     Disabled        1E+00
-0.9                  6     Disabled        -0.9
-0.99999999           7     Disabled        -1E+00
7000000               4     Disabled        Error
7000000               7     Disabled        7000000
5000                 10        3            5000.000
234.77               20       12            234.770000000000

ERRORS:                 ER_MT_FL - output string too long for field width

________________________
15.5  THE SCIENTIFIC FUNCTIONS

With a few exceptions, the system services for these  functions  require  a
single  floating-point  number  on the run-time stack (described in section
17.2.13) as input.  On exit this number is replaced by  the  floating-point
result,  with  the stack pointer unchanged.  The result is also left in the
floating-point  accumulator  (see  section  15.1  above  on  floating-point
numbers).

A call to one  of  these  services  can  be  set  up  by  decrementing  the
stack-pointer  RTA_SP at \$A5 (see section 6.5.1.2 on memory usage) by 8 and
copying the argument into the 8 bytes pointed to by RTA_SP.  After  calling
the system service corresponding to the desired function the result will be
pointed to by RTA_SP which must be incremented by 8 to restore  it  to  its
original value.

Note that RTA_SP is used extensively  by  the  operating  system,  so  care
should  be  taken always to leave it pointing to the same place after using
it in these routines.  No testing for sufficient stack space  is  necessary
as  the  operating system ensures that there are always at least \$100 bytes
available on the stack.  Beware of using the  stack  pointer  simply  as  a
pointer  to a floating-point constant in memory as intermediate results are
pushed onto the run-time stack and will destroy anything  in  memory  below
the  argument.   At least 60 bytes should be reserved as a work area in the
memory area immediately below the argument.

The functions make use of the table interpreter (see chapter  18)  and  the
floating-point  addition, subtraction, multiplication and division routines
described in section  15.2  above,  and  follow  the  algorithms  given  in
"Software Manual For The Elementary Functions" by Cody and Waite.

15.5.1  FN\$ATAN

VECTOR NUMBER:          056
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the arctangent in radians of the floating-point number  on  the
run-time stack.  The stack pointer (RTA_SP) remains unchanged.

EXAMPLE

The following subroutine will return the arctan of 0.5 in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$ATAN
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   0,0,0,0,0,\$50,-1,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result 0.463647609001.

ERRORS:                 ER_MT_EX - exponent overflow

15.5.2  FN\$COS

VECTOR NUMBER:          057
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the cosine of the  floating-point  number  (assumed  to  be  in
radians)  on  the  run-time  stack.  The stack pointer (RTA_SP) remains
unchanged.

Error ER_FN_BA is returned if the argument is greater than 3141590.4292
or less than -3141590.4292.

EXAMPLE

The following subroutine will return the cosine  of  3.1416  (PI  to  4
decimal places) in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$COS
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   0,0,0,\$60,\$41,\$31,0,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result -0.999999999974.

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.3  FN\$EXP

VECTOR NUMBER:          058
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the result of the arithmetic constant  e  (2.71828...)  to  the
power  of  the  floating-point number on the run-time stack.  The stack
pointer (RTA_SP) remains unchanged.

Error ER_FN_BA is returned if the argument is greater than or equal  to
231.

EXAMPLE

The following subroutine will return e to the power 230 in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$EXP
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   0,0,0,0,0,\$23,2,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result 7.72201849998E+99

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.4  FN\$LN

VECTOR NUMBER:          059
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the logarithm to the base e of the floating-point number on the
run-time stack.  The stack pointer (RTA_SP) remains unchanged.

Error ER_FN_BA is returned if the argument is negative or zero.

EXAMPLE

The  following  subroutine  will  return   the   natural   log   of   e
(2.71828182846) in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$LN
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   \$46,\$28,\$18,\$28,\$18,\$27,0,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result of 1.0.

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.5  FN\$LOG

VECTOR NUMBER:          060
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the logarithm to the base 10 of the  floating-point  number  on
the run-time stack.  The stack pointer (RTA_SP) remains unchanged.

Error ER_FN_BA is returned if the argument is negative or zero.

EXAMPLE

The following subroutine will return the log to  the  base  10  of  the
largest floating-point number (9.99999999999E+99) in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$LOG
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   \$99,\$99,\$99,\$99,\$99,\$99,\$63,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result of 100.

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.6  FN\$POWR

VECTOR NUMBER:          064
INPUT PARAMETERS:       Two floating-point arguments on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the result of X ** Y where X and Y are  floating-point  numbers
on  the  run-time stack.  The arguments should be pushed onto the stack
in the order X first, then Y.   The  stack  pointer  (RTA_SP)  will  be
incremented by 8 after the operation.

Error ER_FN_BA is returned if:

-  Both arguments are zero

-  X is negative and Y non-integer

-  The result is greater than 9.99999999999E+99

EXAMPLE

The following subroutine will return 2 ** 10 in FN_RESULT.

LDD     RTA_SP:
SUBD    #16             ;make room for arguments on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #16             ;length for copying arguments
STX     UTW_S0:         ;(copying both together)
LDX     #FN_Y           ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy arguments to stack
OS      FN\$POWR
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_Y:                               ;Y first, then X
.BYTE   0,0,0,0,0,\$10,1,0       ;(from low -> high memory)
FN_X:
.BYTE   0,0,0,0,0,\$20,0,0
FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result 1024.0.

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.7  FN\$RND

VECTOR NUMBER:          062
INPUT PARAMETERS:       None.
OUTPUT VALUES:          Floating-point random number on the stack.

DESCRIPTION

Pushes a random floating-point number onto  the  run-time  stack.   The
number  will  always  lie  between 0 and 0.999999999999 inclusive.  The
stack pointer (RTA_SP) is decremented by 8.

The seed for the random number generator is held  in  the  7  bytes  at
FNT_SEED.   If  these  bytes  are  set  to  a particular value then the
sequence of random numbers following this will always be the same.

EXAMPLE

The following subroutine will place a random floating-point  number  in
FN_RESULT.

OS      FN\$RND          ;call random number generator
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_RESULT:
.BLKB   8

ERRORS:                 None.

15.5.8  FN\$SIN

VECTOR NUMBER:          063
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the sine of the floating-point number (assumed to  be  radians)
on the run-time stack.  The stack pointer (RTA_SP) remains unchanged.

Error ER_FN_BA is returned if the argument is greater than  3141592  or
less than -3141592.

EXAMPLE

The following subroutine will return  the  sine  of  3.1416  (PI  to  4
decimal places) in FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$SIN
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   0,0,0,\$60,\$41,\$31,0,0

FN_RESULT:
.BLKB   8

FN_RESULT will contain the floating-point result -7.34641020669E-06.

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.9  FN\$SQRT

VECTOR NUMBER:          064
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the square root of the floating-point number  on  the  run-time
stack.  The stack pointer (RTA_SP) remains unchanged.

Error ER_FN_BA is returned if the argument is negative.

EXAMPLE

The following  subroutine  will  return  the  square  root  of  101  in
FN_RESULT.

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$SQRT
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   0,0,0,0,\$10,\$10,2,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result 10.0498756211

ERRORS:                 ER_FN_BA - bad argument in function call

15.5.10  FN\$TAN

VECTOR NUMBER:          065
INPUT PARAMETERS:       Floating-point argument on the stack.
OUTPUT VALUES:          Floating-point result on the stack.

DESCRIPTION

Returns the tangent of the floating-point number on the run-time stack.
The  stack pointer (RTA_SP) remains unchanged.  The argument is assumed

Error ER_FN_BA is returned if the argument is greater than 3141590.4292
or less than -3141590.4292.

EXAMPLE

The  following  subroutine  will   return   the   tangent   of   3*PI/4

LDD     RTA_SP:
SUBD    #8              ;make room for argument on stack
STD     RTA_SP:         ;D now has destination for UT\$CPYB
LDX     #8              ;length for copying argument
STX     UTW_S0:
LDX     #FN_ARG         ;source address for UT\$CPYB
OS      UT\$CPYB         ;copy argument to stack
OS      FN\$TAN
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
STD     RTA_SP:         ;restore stack pointer
LDD     #FN_RESULT      ;destination for copy
OS      UT\$CPYB
RTS

FN_ARG:
.BYTE   \$19,\$90,\$44,\$19,\$56,\$23,0,0

FN_RESULT:
.BLKB   8

FN_RESULT will now contain the floating-point result -1.0.

ERRORS:                 ER_FN_BA - bad argument in function call

```