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

is incorrect. It should read:

.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.

15.2.1 MT$FADD

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 OS MT$FADD

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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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 ADDD RTA_SP: ;add 8 to stack pointer 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