# 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):

`     Address    Variable name           Function`
```        \$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 to be added.
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.
REGISTERS PRESERVED: B and X.

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`

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 including leading or trailing zeros)
• 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 to be in radians.

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 (2.35619449019 radians) 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\$TAN
LDX     RTA_SP:         ;source address for copying result
LDD     #8
STD     UTW_S0:         ;length for copying result
```    FN_ARG:
```    FN_RESULT:
`ER_FN_BA - bad argument in function call`