ln subroutine 3713 Called from 0028 FP CALC with literal 25h; the executiveroutine of the LN function, but also used in calculating square roots and "to-power". It could be called direct, but its argument X must always be last value on the calculator stack even for direct calls. Finds LN X, the natural logarithm of any positive numberX; that is, the logarithm to base e = 2.718281828...d, see indexentry on 36C4 EXP. See CALCULATE for the structure of FP numbers. If E is the true binary exponent of X and M is the true binary mantissa of X, called X' in the notes, then X = 2**E times M, and LN X = LN 2**E + LN M. LN 2**E is easily found: LN 2**E = E * LN 2. LN 2 is just a number, 0.6931471806...d, in FP form 80 31 72 17 FB; see 373D GRE.8, near the beginning. To find LN M, the subroutine uses the series generator, using twelve Chebyshev polynomials with the constants: FP form Decimal 1. 61 AC -0.0000000003 2. 64 09 0.0000000020 3. 66 DA A5 -0.0000000127 4. 69 30 C5 0.0000000823 5. 6C 90 AA -0.0000005389 6. 6E 70 6F 61 0.0000035828 7. 71 CB DA 96 -0.0000243013 8. 74 31 9F B4 0.0001693953 9. 77 A0 FE 5C FC -0.0012282837 10. 7A 1B 43 CA 36 0.0094766116 11. 7D A7 9C 7E 5E -0.0818414567 12. 80 6E 23 80 93 0.9302292213 To adjust it to the range over which the Chebyshev polynomials can approximate the LN function, the mantissa M is adjusted to Z by the following set of formulas. The range of Z is -1 to +1, that of M is only 0.5d to 0.9999999999d; all numbers are decimals: if M > 0.8, Z = 2.5M - 3 (range -1 to -0.5); if M <= 0.8, Z = 5M - 3 (range -0.5 to +1) and E is reduced by 1. The series produces the result (LN M)/(M - 1) or (LN 2M)/(2M - 1) depending on whether M is more or less than 0.8d; in either case LN M, and then LN 2**E + LN M, are easily calculated. Input parameters: none - the number X is last value on the calculator stack. Action: restack X in full format - if it is negative or zero report "Invalid argument"; such numbers don't have a logarithm in real numbers. _371C_VALID: put a zero on the calculator stack and delete it; this makes HL point to the exponent of X - get the exponent of X - replace it with 80h; the last value is now M - put the exponent on the stack; because of the format of FP numbers, this is E + 80h - subtract 80h; the stack holds, from the top, E and M - if M is more than 0.8d jump on to GRE.8 - (M <= 0.8d) decrement E - double M; the short way is just to increment its exponent. The stack holds, from the top, 2*M, E - 1. _373D_GRE.8: calculate E*LN 2; if M was < 0.8d this is (E- 1)*LN 2 - subtract one from M; by twice subtracting half - why? this seems quite pointless. If M was < 0.8d this is 2M - 1 - multiply it by 2.5d and subtract half again; the result, in decimals, is 2.5(M - 1) - 0.5 = 2.5M - 3 or 2.5(2M - 1) - 0.5 = 5M - 3; either way it is Z as required for the series calculation - call series-0C with the twelve Chebyshev constants listed above; giving the result (LN M)/(M - 1), or the equivalent with M = 2M if M was doubled - multiply the result by M - 1 already on the stack; theanswer is LN M - add this to E*LN 2 already on the stack; the answer is E*LN 2 + LN M = LN 2**E + LN M = LN X. Exit: RET. Output parameters: none - LN X has replaced X as last value on the stack. Called from: 3851 to-power Rems: Introduction approximation found by Chebyshev polynomial 3449 series-06 LN produced by Chebyshev polynomials 384A sqr LN produces error for negative numbers L NEW$ 2BC0 (2AFF LET) Jumps from: 2B1F L TEST CH LN FETCH subroutine 190F Finds the next line number in the BASIC program following the line number held at a given address in lo-hi form;this is a line number in one of the svs, 5C6C S TOP or 5C49 E PPC, or in ROM, not at a line start, which would be in hi-lo form. Input parameters: HL holds the address. Action: read the line number and save the address - increment the line number - call 196E LINE ADDR, which returns the start address of the line with this number if there is one, or of the next line - call 1695 LINE NO to get its number. Exit: into 191C LN STORE, which loads the number into thegiven address. Output parameters: HL is incremented by one from its input value - DE holds the required line number - BC unchanged. Called from: 0FF3 ED DOWN 1835 LIST ALL L NO SP 2B0C (2AFF LET) Jumps from: auto (twice) LN STORE subroutine 191C An "ad hoc" routine, used to store line numbers in system variables. Input parameters: HL holds the hi byte address of a system variable, 5C49 E PPC or 5C6C S TOP - DE holds a BASIC line number. Action: in input mode, return at once - (in editing mode) load D into HL and E into HL - 1, the lo byte of the system variable. Exit: RET. Output parameters: HL decremented, others unchanged. Called from: 1059 ED UP Exit from: 190F LN FETCH L NUMERIC 2B59 (2AFF LET) Jumps from: 2B66 L EXISTS LOAD key (EF) see also commands, functions and operators, KEYBOARD SCANNING The J key in K mode produces the command LOAD. The "LOADstatement" must include a filename, though it may be null "", and may also include modifiers such as CODE. The command is read by 1B29 STMT L 1 referring through the syntax offset table 1A48 to the syntax parameter table 1A7A.1AE0 P LOAD causes a jump via 1CDB CLASS 0B to the executive routine for all the cassette handling commands, 0605 SAVE ETC. The routine distinguishes between SAVE, LOAD, VERIFY and MERGE by looking at 5C74 T ADDR, which was used to step through the 1A7A table: its low byte reads one more than the low byte of the"P" label, E0, E1, E2 or E3 respectively, so E1 for LOAD. 04C2 SA BYTES cassette handling routines start here 053F SA/LD RET common to SAVE and LOAD 0556 LD BYTES loads both headers and data 058F LD SYNC gets ready to load 05A9 LD LOOP loading loop 05E3 LD EDGE 2 main action when loading 0629 SA BLANK name can be null for LOAD 075A SA ALL ready to load header 0767 LD LOOK H loop to load header 07AD LD CH PR jump forward for LOAD 07CB VR CONTRL used for LOAD SCREEN$/CODE 07F4 VR CONT 2 jump forward for LOAD 0800 VR CONT 3 load data block 0802 LD BLOCK used for all loading 0808 LD CONTRL loading programs/variables/arrays 082E LD DATA loading arrays 084C LD DATA 1 loads arrays 0873 LD PROG loads programs 08AD LD PROG 1 loads program block 08B6 ME CONTRL part i is a load 1CDB CLASS 0B jumps to executive routine LOAD A DATA BLOCK SUBROUTINE see 0802 LD BLOCK LOAD CONTROL ROUTINE see 0808 LD CONTRL LOADing routines Ie LOAD (0808 LD CONTRL), MERGE (08B6 ME CONTRL), VERIFY (07CB VR CONTRL). 0802 LD BLOCK common to all LOC MEM subroutine 3406 Adds five times the parameter supplied to a base address. Used to find a FP number, usually in the calculator memory. Input parameters: HL holds the base address, usually of the memory area - A holds the parameter, usually derived from the literal of get-mem-0 etc. Action: double the parameter twice and add the original value; ie multiply it by five - add it to HL. Exit: RET. Output parameters: HL holds the address required; the first byte of an FP number - DE unchanged - [the notes appear to suggest that the value of BC, five times the parameter, is an output parameter, but it isn't used in the ROM]. Called from: 0427 BE OCTAVE 340F get-mem 342D st-mem logically true/false, logical value see also AND key, greater-0, IF key, 368F jump-true, OR key The_logical_values of expressions are: numeric expressions of value zero: zero all other numeric expressions (even negative) one equalities which equate eg 7=4+3, "h"="h" one equalities which don't equate eg 7=4+4, "h"="s" zero inequalities which are "true" eg 1>0, "s">"h" one inequalities which aren't "true" eg 0>1, "h">"s" zero values of logic operations AND, OR, etc: depending Zero means_false, one means_true. The logical value is numeric; even string comparisons are evaluated as numeric expressions. Other kinds of expression, eg strings, cannot be used asoperands of logic commands or operators such as IF, OR; a stringmay precede AND, but then isn't read for its logical value. It may not follow AND. The terms "true" and "not-false" are used in a slightly different sense in the notes on 368F jump-true, where the only possible non-zero value is one. [To be more precise, the subroutine will make a jump on any last value with a non-zero third byte, and won't jump on any with a zero third byte. If theone happened to be in full FP format, 81 00 00 00 00, jump-true would regard it as a zero and make no jump. This comment appliesto m/c programming uses of jump-true, but not to the ROM, where it is only ever asked to distinguish between zero and one in small integer format.] 2E24 PF SMALL wrong answer can result from STR$ error 368F jump-true any +ve value counts as true LOG(2**A) subroutine 2DC1 Calculates log 2**A, rounded up or down to an integer; Aitself is an integer. Log 2**A always means the logarithm of 2**A to the base ten: the number of the power to which ten must be raised to equal 2**A, ie the kind of logarithm one used to learn at school. Not the same as LN 2**A, which means the logarithm to the base e. Used to estimate the amount of space that will be required to print an FP number in decimal form; A is its binary exponent. The number of digits before the decimal point of a number X written in decimal notation is one more than the integer part of log X; if X is less than one the number of leading zeroes after the decimal point is the absolute value of its log, which will then be negative. The subroutine uses a well-known mathematical identity: logarithm X to the base Y = logarithm X to the base Z times logarithm Z to the base Y Using 2 for the helping number Z, we have log X = logarithm of X to the base 2 times log 2 Log 2 is just a number, which anyone can figure or look up: 0.3010299957...d, or in FP format 7F 1A 20 9A 85. The logarithm of X to the base 2 would take a little figuring to get in full, but its integer part is just the true binary exponent of X, so it is easily available when X is written in full FP format. In this case X = 2**A, so the exponent is just A, and the required result is A log 2, rounded up or down to an integer. Input parameters: A holds the true binary exponent E of the number, if this was positive. If it was negative -E, A holds-(ABS E - 2), two closer to zero than -E. Action: copy A to D - rotate the hi bit of A into carry and SBC A,A; this makes a sign byte, zero for positive, FF for negative - copy the sign byte to E and C - zero A and copy it to B; all this makes a small integer version of the exponent, positive or negative, in registers AEDCB, 00 00 XX 00 00 for +XX and 00 FF YY FF 00 for 100h - YY = -XX - call 2AB6 STK STORE to put this on the stack - use the calculator to multiply it by log 2 and round the result down to an integer. Exit: into 2DD5 FP TO A, which returns in A the last value on the stack; an approximation to the number of digits before the decimal point in the decimal print of the number whose binary exponent is A, or of the number of leading zeroes after the decimal point; usually one too large. Output parameters: none - the last value on the stack is the value required. Called from: 2E24 PF SMALL 2E56 PF LARGE Rems: 2AB1 STK ST 0 used to put small integer on stack long multiplication see 30CA multiply long name of variable see variables LOOK PROG subroutine 1D86 Finds the line and statement number of the next occurrence of a specified command code in the BASIC program; used to find DATA, DEF FN, NEXT token bytes. Input parameters: E holds the code of the token to be matched - HL holds the start address from 5C53 PROG, the beginning of the BASIC program, ifthe search is for DEF FN of the first byte after a FOR statement, if NEXT is being looked for from 5C57 DATADD, if the search is for DATA. The address may be the start address of the next line, with the hi byte of the line number, or in the last two cases may hold a colon. In all three cases, if there are no more linesin the program HL holds the first variable letter or the 80-byteat the end of the variables area.