A90E COS
Submitted by Steve Fewell
Description:
On entry to the COS routine, the carry flag will be set  this indicates that the Cosine result is required (a clear carry
flag indicates that the Sine result is required!).
Store the 6502 flags to the 6502 stack, so that the carry flag can be checked later.
Call routine &A93A to obtain the FloatingPoint argument and calculate the Sine or Cosine value (the value returned
will be either COS or SIN  depending on the value of the FloatingPoint argument.

Routine &A93A does the following:
 * Call routine &96DA to obtain the value at the Text pointer B location (convert it to Float if it is
 Integer or issue 'Type mismatch' error if it is a String value).
 * If the FWA exponent (location &30) is more than or equal to #&98 then issue 'Accuracy lost' error
 as the FWA value is too large to use to calculate the SIN/COS value.
 * Store the FWA value to temporary Floating point value location &046C&0470.
 * Set the argument pointer (&4A&4B) to &BF2E (which points to the Float value 1.57079633 in the
 FloatingPoint constant table).
 * Call &A4E0 to unpack the FloatingPoint constant at &BF2E (1.57079633, which is PI/2) to the FWB
 * Store the FWA sign (location &2E) in the FWB sign byte (location &3B) so that the PI/2 value has
 the same sign as the argument (the FWA value).
 * Decrement the FWB exponent (location &3C) to divide the FWB value by 2  so the FWB now contains the
 value 0.785398165.
 * Call routine &A692 to add the FWB value (PI/4) to the FWA value.
 * Set A to #&33.
 * Call routine &A9D4 to set the argument pointer (&4A&4B) to &BF00 + A = &BF33 (which points to
 the Float value 0.636619772 (which is 2/PI) in the FloatingPoint constant table)
 and then multiply the FWA by the Float value pointed to by the argument pointer (&4A&4B).
 * Call routine &96C3 to convert the Float value (FWA) to an Integer and place the result in the IWA.
 * Store A (the LSB of the IWA value  from location &2A) in location &49.
 * If the Integer value (&2A&2C) is zero then jump to &A98D (as the FWA value does not need to be
 reduced to a value within the required range (PI/4) to (PI/4) [i.e. 0.785398 to 0.785398]),
 so [&A98D] load the FWA with the original Sine/Cosine argument (from location &046C&0470).
 * Otherwise, the FWA value is out of the Sine/Cosine range, and needs to be reduced, so:
 * Call &8189 to convert the Integer value (IWA) to a Float and store the result in the temporary
 Floatingpoint variable located at &0471&0475.
 * Then set the argp pointer (&4A&4B) to pointer to &BF24 (which is the Floatingpoint constant
 value 1.57080078) and multiply the FWA by this constant.
 * Set the argp pointer (&4A&4B) to point to the temporary Floatingpoint variable location &046C
 (which is the original FWA Sine/Cosine argument value) and add the FloatingPoint
 value at &046C&0470 to the FWA value.
 * Store the result in temporary FloatingPoint value location &046C&0470.
 * Set the FWA to the FloatingPoint value stored at location &0471&0475 (the IWA value).
 * Set the argp pointer (&4A&4B) to point to &BF29 (the address of the value 0.00000445445511
 in the FloatingPoint constant table).
 * Multiply the FWA by the FloatingPoint constant 0.00000445445511 (store the result in the FWA).
 * Set the argp pointer (&4A&4B) to &046C and add the FloatingPoint value at &046C&0470
 to the FWA.
 * Jump to &A990 to perform the Sine/Cosine calculation as the value is now within the required range.
 * [A990] Store the FWA value (the actual Sine/Cosine argument, which has been reduced where necessary) to location
 &0476&047A.
 * Multiply the FWA by the Floatingpoint value at &0476&047A (i.e. square the FWA value).
 * Set X to #&74 (i.e. the LSB of the first fraction to apply)
 * Set A to #&92 (i.e. the LSB of the default value (if the FWA value is too small to evaluate)
 * Set Y to #&02 (the number of continuedfraction expansion cycles to evaluate)
 * Call routine &A861 to evaluate the continuedfraction expansions, as follows:
 * If the FWA exponent is less than #&40 then the FWA value is too small to evaluate, so exit with the
 FWA set to the FloatingPoint constant at &BF92 (i.e. 1.0).
 * Calculate the reciple of the FWA value (FWA = 1/FWA) and store the result in the FWA and location
 &046C&0470
 * Add the FloatingPoint constant at &BF74 (0.0119090311) to the FWA
 * Cycle 1:
 * Divide the FloatingPoint constant at &BF79 (0.000107499459) by the FWA, storing the result in the FWA.
 * Add the FloatingPoint constant at &BF7E (0.0171640246) to the FWA.
 * Add the Reciple value (from location &046C&0470) to the FWA.
 * Cycle 2:
 * Divide the FloatingPoint constant at &BF83 (0.0013095369) by the FWA, storing the result in the FWA.
 * Add the FloatingPoint constant at &BF88 (0.0499999922) to the FWA.
 * Add the Reciple value (from location &046C&0470) to the FWA.
 Last Cycle calculation:
 * Divide the FloatingPoint constant at &BF8D (0.166666666) by the FWA, storing the result in the FWA.
 * Add the FloatingPoint constant at &BF92 (1.0) to the FWA.
 * Multiply the FWA by the Temporary FloatingPoint variable stored at location &0476&047A (the argument
 value).
 * Exit with A = #&FF (as the result is a FloatingPoint value in the FWA)
Now, the FWA contains either the Sine result or the Cosine result (which will have to be converted to the value
requested by the user).
Retrieve the carry flag value from the 6502 stack.
As the carry flag is set (Cosine result required), increment the value stored at location &49 (the integer part of
the FWA argument value).
[&A923] If bit 0 of location &49 is clear (i.e. the original argument was an even value (in the case of Sine)  or
an odd value (in the case of Cosine)) then Set A to #&FF (to indicate that the result is a Floatingpoint value) and
[&A917] check the value in location &49  if bit 1 is not set then complement the FWA value (FWA=FWA) and exit;
otherwise, just exit.

Otherwise, bit 0 of location &49 is set (indicating that the original argument was odd (in the case of Sine) or even (in
the case of Cosine); so, adjust the calculated result as follows:
 * Square the FWA value (FWA = FWA * FWA),
 * Subtract the FWA value from 1 (FWA=1.0FWA) and
 * Set the FWA value to the square root of the FWA (FWA=SQR(FWA)).
[&A917] check the value in location &49  if bit 1 is not set then complement the FWA value (FWA=FWA) and exit;
otherwise, just exit.
Example 1: COS(1.5)

 Set &046C = 1.5 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 2.285398
 FWA = FWA * 0.636619772 = 1.4549294
 ?&49 = 1 (Integer part of FWA value). FWA = IWA = 1
 Store the FWA in &0471
 FWA = FWA * 1.57080078 = 1.57080078
 FWA = FWA + &046C = 0.07080078
 Store FWA in &046C
 Store &0471 (1) in FWA
 FWA = FWA * 0.0000044544511 = 0.0000044544511
 FWA = FWA + &046C = 0.0707963255
 Store the FWA in &0476
 FWA = FWA * FWA = 0.0050121197
 [&A861]: FWA = 1 / FWA = 199.51638
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 199.504474778
 FWA = 0.000107499 / FWA = 0.00000005388
 FWA = 0.017164024 + FWA = 0.017163485
 FWA = &046C + FWA = 199.499216515
 FWA = 0.0013095369 / FWA = 0.000006564
 FWA = 0.04999999 + FWA = 0.050006554
 FWA = &046C + FWA = 199.566387
 FWA = 0.16666666 / FWA = 0.00083514
 FWA = 1 + FWA = 0.999164856
 FWA = FWA * &0476 = 0.070737200377

 Increment &49 > now &49 = 2
 Bit 0 of &49 is clear and Bit 1 of &49 is set, indicating that the FWA value needs
 to be complemented  so exit with FWA =  FWA = 0.070737200377
Example 2: COS(0.75)

 Set &046C = 0.75 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 1.535398165
 FWA = FWA * 0.636619772 = 0.9774646
 ?&49 = 0 (Integer part of FWA value). FWA = IWA = 0
 [&A98D] As &49 is 0, store value at &046C in FWA = 0.75
 Store the FWA in &0476
 FWA = FWA * FWA = 0.5625
 [&A861]: FWA = 1 / FWA = 1.777777
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 1.7896868
 FWA = 0.000107499 / FWA = 0.00006
 FWA = 0.017164024 + FWA = 0.0171039
 FWA = &046C + FWA = 1.7606737
 FWA = 0.0013095369 / FWA = 0.0007437
 FWA = 0.04999999 + FWA = 0.0507436
 FWA = &046C + FWA = 1.8285213
 FWA = 0.16666666 / FWA = 0.0911482
 FWA = 1 + FWA = 0.9088517
 FWA = FWA * &0476 = 0.6816387

 Increment &49 > now &49 = 1
 Bit 0 of &49 is set, so adjust the calculated value as follows:
 FWA = FWA * FWA = 0.4646313
 FWA = 1  FWA = 0.5353686
 FWA = SQR(FWA) = 0.7316889
 Bit 1 of &49 is not set, so exit with FWA unchanged.
Example 3: COS(0.0)

 Set &046C = 0.0 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 0.785398165
 FWA = FWA * 0.636619772 = 0.50000000
 ?&49 = 0 (Integer part of FWA value). FWA = IWA = 0
 [&A98D] As &49 is 0, store value at &046C in FWA = 0.0
 Store the FWA in &0476
 FWA = FWA * FWA = 0.0
 [&A861]: FWA = 1.0 (as argument is zero)
 FWA = FWA * &0476 = 0.0

 Increment &49 > now &49 = 1
 Bit 0 of &49 is set, so adjust the calculated value as follows:
 FWA = FWA * FWA = 0.0
 FWA = 1  FWA = 1.0
 FWA = SQR(FWA) = 1.0
 Bit 1 of &49 is not set, so exit with FWA unchanged.
Example 4: COS(0.25)

 Set &046C = 0.25 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 1.0353982
 FWA = FWA * 0.636619772 = 0.6591548
 ?&49 = 0 (Integer part of FWA value). FWA = IWA = 0
 [&A98D] As &49 is 0, store value at &046C in FWA = 0.25
 Store the FWA in &0476
 FWA = FWA * FWA = 0.0625
 [&A861]: FWA = 1 / FWA = 16
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 15.988091
 FWA = 0.000107499 / FWA = 0.0000067
 FWA = 0.0171640246 + FWA = 0.0171572
 FWA = &046C + FWA = 15.982843
 FWA = 0.0013095369 / FWA = 0.0000819
 FWA = 0.04999999 + FWA = 0.0500818
 FWA = &046C + FWA = 16.050082
 FWA = 0.16666666 / FWA = 0.0103841
 FWA = 1 + FWA = 0.9896158
 FWA = FWA * &0476 = 0.2474039

 Increment &49 > now &49 = 1
 Bit 0 of &49 is set, so adjust the calculated value as follows:
 FWA = FWA * FWA = 0.0612086
 FWA = 1  FWA = 0.9387913
 FWA = SQR(FWA) = 0.9689124
 Bit 1 of &49 is not set, so exit with FWA unchanged.
Example 5: COS(2.41)

 Set &046C = 2.41 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 3.195398
 FWA = FWA * 0.636619772 = 2.0342533
 ?&49 = 2 (Integer part of FWA value). FWA = IWA = 2
 Store the FWA in &0471
 FWA = FWA * 1.57080078 = 3.1416014
 FWA = FWA + &046C = 0.7316014
 Store FWA in &046C
 Store &0471 (2) in FWA
 FWA = FWA * 0.0000044544511 = 0.0000089
 FWA = FWA + &046C = 0.7315924
 Store the FWA in &0476
 FWA = FWA * FWA = 0.5352275
 [&A861]: FWA = 1 / FWA = 1.8683641
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 1.8564551
 FWA = 0.000107499 / FWA = 0.0000057
 FWA = 0.017164024 + FWA = 0.0171583
 FWA = &046C + FWA = 1.8512058
 FWA = 0.0013095369 / FWA = 0.0007073
 FWA = 0.04999999 + FWA = 0.0507072
 FWA = &046C + FWA = 1.9190714
 FWA = 0.16666666 / FWA = 0.0868475
 FWA = 1 + FWA = 0.9131524
 FWA = FWA * &0476 = 0.6680554

 Increment &49 > now &49 = 3
 Bit 0 of &49 is set, so adjust the calculated value as follows:
 FWA = FWA * FWA = 0.446298
 FWA = 1  FWA = 0.5537019
 FWA = SQR(FWA) = 0.7441115
 Bit 1 of &49 is set, so FWA =  FWA = 0.7441115
Example 6: COS(5.63)

 Set &046C = 5.63 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 6.415398
 FWA = FWA * 0.636619772 = 4.0841688
 ?&49 = 4 (Integer part of FWA value). FWA = IWA = 4
 Store the FWA in &0471
 FWA = FWA * 1.57080078 = 6.2832028
 FWA = FWA + &046C = 0.6532028
 Store FWA in &046C
 Store &0471 (4) in FWA
 FWA = FWA * 0.0000044544511 = 0.0000178
 FWA = FWA + &046C = 0.6531849
 [&A990] Store the FWA in &0476
 FWA = FWA * FWA = 0.4266506
 [&A861]: FWA = 1 / FWA = 2.3438381
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 2.3319291
 FWA = 0.000107499 / FWA = 0.000046
 FWA = 0.017164024 + FWA = 0.0171179
 FWA = &046C + FWA = 2.3267202
 FWA = 0.0013095369 / FWA = 0.0056282
 FWA = 0.04999999 + FWA = 0.0556281
 FWA = &046C + FWA = 2.3994662
 FWA = 0.16666666 / FWA = 0.0694598
 FWA = 1 + FWA = 0.9305401
 FWA = FWA * &0476 = 0.6078147

 Increment &49 > now &49 = 5
 Bit 0 of &49 is set, so adjust the calculated value as follows:
 FWA = FWA * FWA = 0.3694387
 FWA = 1  FWA = 0.6305612
 FWA = SQR(FWA) = 0.7940788
 Bit 1 of &49 is not set, so exit with FWA unchanged.
Example 7: COS(90)

 Set &046C = 90 (the argument)
 Set FWB to 0.785398165 (PI/4)
 FWA = FWA + FWB = 90.785398
 FWA = FWA * 0.636619772 = 57.795773
 ?&49 = 57 (Integer part of FWA value). FWA = IWA = 57
 Store the FWA in &0471
 FWA = FWA * 1.57080078 = 89.53564
 FWA = FWA + &046C = 0.4643601
 Store FWA in &046C
 Store &0471 (57) in FWA
 FWA = FWA * 0.0000044544511 = 0.0002539
 FWA = FWA + &046C = 0.464614
 Store the FWA in &0476
 FWA = FWA * FWA = 0.2158661
 [&A861]: FWA = 1 / FWA = 4.6324998
 Store FWA in &046C
 FWA = FWA + 0.0119090311 = 4.6205908
 FWA = 0.000107499 / FWA = 0.0000023
 FWA = 0.017164024 + FWA = 0.0171616
 FWA = &046C + FWA = 4.6153381
 FWA = 0.0013095369 / FWA = 0.0002837
 FWA = 0.04999999 + FWA = 0.0502836
 FWA = &046C + FWA = 4.6827834
 FWA = 0.16666666 / FWA = 0.0355913
 FWA = 1 + FWA = 0.9644086
 FWA = FWA * &0476 = 0.4480777

 Increment &49 > now &49 = 58 (0011 1010)
 Bit 0 of &49 is clear and Bit 1 of &49 is set, indicating that the FWA value needs
 to be complemented  so exit with FWA =  FWA = 0.4480777
This diagram shows the relationship between the trig functions.
Disassembly for the COS routine
A90E 

008 
08 
PHP 
A90F 
: 
032 058 169 
20 3A A9 
JSR &A93A Get value and calculate Sine or Cosine wave 
A912 
( 
040 
28 
PLP 
A913 

144 002 
90 02 
BCC 2 > &A917 
A915 
I 
230 073 
E6 49 
INC &49 
A917 
I 
165 073 
A5 49 
LDA &49 
A919 

137 002 
89 02 
BIT#&02 
A91B 

240 006 
F0 06 
BEQ 6 > &A923 
A91D 
# 
032 035 169 
20 23 A9 
JSR &A923 
A920 
L 
076 202 172 
4C CA AC 
JMP &ACCA Compliment FWA value [FWA=FWA] 
A923 
J 
074 
4A 
LSR A 
A924 

176 003 
B0 03 
BCS 3 > &A929 
A926 

169 255 
A9 FF 
LDA#&FF 
A928 
` 
096 
60 
RTS 
A929 

032 017 165 
20 11 A5 
JSR &A511 Store FWA to &046C & set argp=&046C 
A92C 

032 166 166 
20 A6 A6 
JSR &A6A6 Multiply the FWA by argp [i.e. &046C] 
A92F 

169 146 
A9 92 
LDA#&92 
A931 

032 139 165 
20 8B A5 
JSR &A58B Set argp to &BF00 + A 
A934 

032 138 166 
20 8A A6 
JSR &A68A FloatingPoint Subtraction [FWA=argpFWA] 
A937 
L 
076 184 167 
4C B8 A7 
JMP &A7B8 Floatingpoint Square Root [FWA = SQRT(FWA)] 
A93A 

032 218 150 
20 DA 96 
JSR &96DA Get and Check Float (convert if Int) 
A93D 
0 
165 048 
A5 30 
LDA &30 
A93F 

201 152 
C9 98 
CMP#&98 
A941 
j 
176 106 
B0 6A 
BCS 106 > &A9AD 'Accuracy lost' error 
A943 

032 017 165 
20 11 A5 
JSR &A511 Store FWA to &046C & set argp=&046C 
A946 

032 137 165 
20 89 A5 
JSR &A589 Set argp to &BF2E 
A949 

032 224 164 
20 E0 A4 
JSR &A4E0 Unpack (&4A, &4B) variable to FWB 
A94C 
. 
165 046 
A5 2E 
LDA &2E 
A94E 
; 
133 059 
85 3B 
STA &3B 
A950 
< 
198 060 
C6 3C 
DEC &3C 
A952 

032 146 166 
20 92 A6 
JSR &A692 FWA = FWA + FWB (PI/4) 
A955 
3 
169 051 
A9 33 
LDA#&33 
A957 

032 212 169 
20 D4 A9 
JSR &A9D4 Multiply FWA by &BF33 (0.636619772  2/PI) 
A95A 

032 195 150 
20 C3 96 
JSR &96C3 Convert Float to Integer 
A95D 
I 
133 073 
85 49 
STA &49 
A95F 
+ 
005 043 
05 2B 
ORA &2B 
A961 
, 
005 044 
05 2C 
ORA &2C 
A963 
( 
240 040 
F0 28 
BEQ 40 > &A98D 
A965 

032 137 129 
20 89 81 
JSR &8189 Convert Integer value (IWA) to FloatingPoint (FWA) 
A968 
q 
169 113 
A9 71 
LDA#&71 
A96A 

032 019 165 
20 13 A5 
JSR &A513 Store FWA to &047B 
A96D 
$ 
169 036 
A9 24 
LDA#&24 
A96F 

032 212 169 
20 D4 A9 
JSR &A9D4 Multiply FWA by &BF24 (1.57080078) 
A972 

032 146 165 
20 92 A5 
JSR &A592 Set argp to &046C 
A975 

032 141 166 
20 8D A6 
JSR &A68D FloatingPoint Addition [FWA=argp+FWA] 
A978 

032 025 165 
20 19 A5 
JSR &A519 Store FWA to argp address (&4A&4B) 
A97B 
q 
169 113 
A9 71 
LDA#&71 
A97D 
; 
032 059 165 
20 3B A5 
JSR &A53B Load FWA from variable at &0400 + A (i.e. &0471) 
A980 
) 
169 041 
A9 29 
LDA#&29 
A982 

032 212 169 
20 D4 A9 
JSR &A9D4 Multiply FWA by &BF29 (0.00000445445511) 
A985 

032 146 165 
20 92 A5 
JSR &A592 Set argp to &046C 
A988 

032 141 166 
20 8D A6 
JSR &A68D FloatingPoint Addition [FWA=argp+FWA] 
A98B 

128 003 
80 03 
BRA 3 > &A990 
A98D 
9 
032 057 165 
20 39 A5 
JSR &A539 Load FWA from &046C 
A990 

032 013 165 
20 0D A5 
JSR &A50D Store FWA to &0476 and set argp to &0476 
A993 

032 166 166 
20 A6 A6 
JSR &A6A6 Multiply the FWA by argp [i.e. &0476] 
A996 
t 
162 116 
A2 74 
LDX#&74 
A998 

169 146 
A9 92 
LDA#&92 
A99A 

160 002 
A0 02 
LDY#&02 
A99C 
a 
032 097 168 
20 61 A8 
JSR &A861 Evaluate continuedfraction expansion series 
A99F 
v 
169 118 
A9 76 
LDA#&76 
A9A1 Multiply FWA by &0400 + A
A9A1 

160 004 
A0 04 
LDY#&04 
A9A3 
K 
132 075 
84 4B 
STY &4B 
A9A5 
J 
133 074 
85 4A 
STA &4A 
A9A7 

032 166 166 
20 A6 A6 
JSR &A6A6 Multiply the FWA by argp [i.e. &0400 + A] 
A9AA 

169 255 
A9 FF 
LDA#&FF 
A9AC 
` 
096 
60 
RTS 
Or