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