Submitted by Steve Fewell
Routine:LN
Name: LN (Natural Logarithm)
Starting Address: &A746
Entry criteria: The FWA contains the value to work with
Exit: The FWA contains the result.
Description:
Get the Numeric value (if integer then convert to Float, if String then Type Mismatch error).
If the number is zero or negative then generate a Log range error.
Set the FWB value to -1.0.
Scale the value in the FWA to a number between 1 and 2. [This is done by setting
the FWA exponent to #&81 if the Mantissa byte 1 value is less than #&B5, or to #&80 if
the FWA value is 0.0 or the Mantissa 1 value is more than #&B4].
The previous exponent is stored on the Stack (X). This will be used to calculate the
difference between the original and scaled exponents later on.
Note: If the FWA value is 0.0 or the Mantissa 1 value is more than #&B4 then the value
or the original exponent (on the stack) is incremented, to represent the exponent variance
(the actual difference) rather than the exact original value.
Subtract 1 from the FWA value to further reduce the the FWA value to a number between 0 and 1
(a fractional value). [This is done by adding FWB (value=-1) to the FWA].
Store this fractional value in Temporary Floating-Point variable address &047B.
Evaluate the LN continued-fraction expansion series (A861) with X=#&51, A=#&6F and Y=#&02.
Thus the parameters to the evaluate series routine are as follows:
Default value (if FWA value too small to calculate) = &BF6F = -0.5
First Floating-Point constant to use = &BF51.
Number of cycles to evaluate = #&02.
The series is evaluated as follows:
If FWA too small then return -0.5 (&BF6F).
FWA = 1/FWA (store in Temporary Floating-Point variable address &046C)
FWA = 0.546254168 + FWA [Floating-Point constant &BF51]
FWA = -0.0513882861 / FWA [Floating-Point constant &BF56]
FWA = 0.583293331 + FWA [Floating-Point constant &BF5B]
FWA = &046C [1/orig FWA] + FWA
FWA = -0.0374986753 / FWA [Floating-Point constant &BF60]
FWA = 0.750000063 + FWA [Floating-Point constant &BF65]
FWA = &046C [1/orig FWA] + FWA
FWA = 0.33333334 / FWA [Floating-Point constant &BF6A]
FWA = -0.5 + FWA [Floating-Point constant &BF6F]
Multiply the series result by 5 * &047B (the scaled FWA value before series calculation was done)
This is achieved by multiplying the result by &047B twice and then adding &047B.
Store the FWA value in Temporary Floating-Point location &046C. This is the LN result
for the scaled value.
Subtract #&81 from the original exponent before the value was scaled. This will give
the difference between the exponent of the original value and the exponent of the scaled
value that was used for the series calculation.
Place this value into the FWA.
Multiply the FWA (exponent difference) by Floating-Point constant &BF4C (0.693147181).
Add &046C (the result calculated with the scaled value) to the FWA.
The value in the FWA is now the LN value of the original value.
Example 1:
Calculate LN(3.14)
3.14 => Exponent = &82, Mantissa 1 = &48, Mantissa 2 = &F5, Mantissa 3 = &C2, Mantissa 4 = &8F
Change Exponent to &81 to scale the value to 1.57 (exponent difference = 1)
Subtract 1 from the FWA to give 0.57, store this value in &047B.
Calculate reciple -> FWA = 1/FWA = 1.75438596. Store this value in location &046C.
FWA = 0.546254168 + FWA = 2.30064013291
FWA = -0.0513882861 / FWA = -0.0223365164
FWA = 0.583293331 + FWA = 0.56095681458
FWA = &046C + FWA = 2.3153427745823
FWA = -0.0374986753 / FWA = -0.0161957338
FWA = 0.750000063 + FWA = 0.73380432917
FWA = &046C + FWA = 2.488190289171
FWA = 0.33333334 / FWA = 0.133966176723
FWA = -0.5 + FWA = -0.366033823
FWA = FWA * 0.57 (&047B) = -0.20863927926778
FWA = FWA * 0.57 (again) = -0.11892438918
FWA = FWA + 0.57 = 0.451075610756108
This is the LN value of the scaled number (1.57). Store in &046C.
FWA = 1 (exponent difference) * 0.693147181 (&BF4C) = 0.693147181.
FWA = 0.451075610756108 + FWA = 1.14422279. This is the LN value of 3.14.
Example 2:
Calculate LN(15)
15 => Exponent = &84, Mantissa 1 = &70, Mantissa 2 = &00, Mantissa 3 = &00, Mantissa 4 = &00
Change Exponent to &81 to scale the value to 1.875 (exponent difference = 3)
Subtract 1 from the FWA to give 0.875, store this value in &047B.
Calculate reciple -> FWA = 1/FWA = 1.142857142857. Store this value in location &046C.
FWA = 0.546254168 + FWA = 1.689111310857
FWA = -0.0513882861 / FWA = -0.0304232680047
FWA = 0.583293331 + FWA = 0.552870062995
FWA = &046C + FWA = 1.69572720585
FWA = -0.0374986753 / FWA = -0.02211362486288
FWA = 0.750000063 + FWA = 0.727886438137
FWA = &046C + FWA = 1.8707435809941
FWA = 0.33333334 / FWA = 0.17818227114956
FWA = -0.5 + FWA = -0.3218177288504
FWA = FWA * 0.875 (&047B) = -0.28159051274413
FWA = FWA * 0.875 (again) = -0.246391698651115
FWA = FWA + 0.875 = 0.6286083013488848
This is the LN value of the scaled number (1.875). Store in &046C.
FWA = 3 (exponent difference) * 0.693147181 (&BF4C) = 2.079441543.
FWA = 0.6286083013488848 + FWA = 2.708049844. This is the LN value of 15.
A746 | 032 218 150 | 20 DA 96 | JSR &96DA Get and check Float value | |
A749 | 032 242 163 | 20 F2 A3 | JSR &A3F2 Float Sign | |
A74C | 240 002 | F0 02 | BEQ 2 --> &A750 | |
A74E | 016 022 | 10 16 | BPL 22 --> &A766 | |
A750 | ...Log range and -ve root Error messages... | |||
A766 | v | 032 118 165 | 20 76 A5 | JSR &A576 Clear FWB Mantissa bytes 2 to 5 |
A769 | 160 128 | A0 80 | LDY#&80 | |
A76B | ; | 132 059 | 84 3B | STY &3B |
A76D | = | 132 061 | 84 3D | STY &3D |
A76F | 200 | C8 | INY | |
A770 | < | 132 060 | 84 3C | STY &3C |
A772 | 0 | 166 048 | A6 30 | LDX &30 |
A774 | 240 006 | F0 06 | BEQ 6 --> &A77C | |
A776 | 1 | 165 049 | A5 31 | LDA &31 |
A778 | 201 181 | C9 B5 | CMP#&B5 | |
A77A | 144 002 | 90 02 | BCC 2 --> &A77E | |
A77C | 232 | E8 | INX | |
A77D | 136 | 88 | DEY | |
A77E | 218 | DA | PHX | |
A77F | 0 | 132 048 | 84 30 | STY &30 |
A781 | 032 146 166 | 20 92 A6 | JSR &A692 FWA = FWA + FWB | |
A784 | { | 169 123 | A9 7B | LDA#&7B |
A786 | 032 019 165 | 20 13 A5 | JSR &A513 Store FWA to &047B | |
A789 | Q | 162 081 | A2 51 | LDX#&51 |
A78B | o | 169 111 | A9 6F | LDA#&6F |
A78D | 160 002 | A0 02 | LDY#&02 | |
A78F | a | 032 097 168 | 20 61 A8 | JSR &A861 Evaluate continued-fraction expansion series |
A792 | { | 169 123 | A9 7B | LDA#&7B |
A794 | 032 161 169 | 20 A1 A9 | JSR &A9A1 Multiply FWA by &047B | |
A797 | 032 166 166 | 20 A6 A6 | JSR &A6A6 Multiply the FWA by argp [i.e. &047B again] | |
A79A | 032 141 166 | 20 8D A6 | JSR &A68D Add argp to the FWA [argp = &047B] | |
A79D | 032 017 165 | 20 11 A5 | JSR &A511 Store FWA to &046C | |
A7A0 | h | 104 | 68 | PLA |
A7A1 | 8 | 056 | 38 | SEC |
A7A2 | 233 129 | E9 81 | SBC#&81 | |
A7A4 | 032 213 129 | 20 D5 81 | JSR &81D5 Set FWA to 1-byte value (i.e. FWA = the exponent difference) | |
A7A7 | L | 169 076 | A9 4C | LDA#&4C |
A7A9 | 032 212 169 | 20 D4 A9 | JSR &A9D4 Multply FWA by &BF4C | |
A7AC | 032 146 165 | 20 92 A5 | JSR &A592 Set argp to &046C | |
A7AF | 032 141 166 | 20 8D A6 | JSR &A68D FWA = FWA + argp [&046C] | |
A7B2 | 169 255 | A9 FF | LDA#&FF | |
A7B4 | ` | 096 | 60 | RTS |