Routines 
Prev: 343C  Up: Map  Next: 346A 
The address of this routine is found in the table of addresses. It is called via a calculator literal (+86, +88 or +8C) by the routines at exp, ln, sin and atn.
This important subroutine generates the series of Chebyshev polynomials which are used to approximate to SIN, ATN, LN and EXP and hence to derive the other arithmetic functions which depend on these (COS, TAN, ASN, ACS, ** and SQR).
The polynomials are generated, for n=1, 2, etc. by the recurrence relation T_{n+1}(z)=2zT_{n}(z)T_{n1}(z), where T_{n}(z) is the nth Chebyshev polynomial in z.
The series in fact generates T_{0}, 2T_{1}, 2T_{2}, ..., 2T_{n1}, where n is 6 for SIN, 8 for EXP, and 12 for LN and ATN.
The coefficients of the powers of z in these polynomials may be found in the Handbook of Mathematical Functions by M. Abramowitz and I. A. Stegun (Dover 1965), page 795.
In simple terms this subroutine is called with the 'last value' on the calculator stack, say Z, being a number that bears a simple relationship to the argument, say X, when the task is to evaluate, for instance, SIN X. The calling subroutine also supplies the list of constants that are to be required (six constants for SIN). The series generator then manipulates its data and returns to the calling routine a 'last value' that bears a simple relationship to the requested function, for instance, SIN X.


This subroutine can be considered to have four major parts.
i. The setting of the loop counter. The calling subroutine passes its parameters in the A register for use as a counter. The calculator is entered at GEN_ENT_1 so that the counter can be set.


series  3449  LD B,A  Move the parameter to B.  
344A  CALL GEN_ENT_1  In effect a RST $28 instruction but sets the counter.  
ii. The handling of the 'last value', Z. The loop of the generator requires 2*Z to be placed in mem0, zero to be placed in mem2 and the 'last value' to be zero.


344D  DEFB $31  duplicate: Z, Z  
344E  DEFB $0F  addition: 2*Z  
344F  DEFB $C0  st_mem_0: 2*Z (mem0 holds 2*Z)  
3450  DEFB $02  delete:   
3451  DEFB $A0  stk_zero: 0  
3452  DEFB $C2  st_mem_2: 0 (mem2 holds 0)  
iii. The main loop.
The series is generated by looping, using BREG as a counter; the constants in the calling subroutine are stacked in turn by calling stk_data; the calculator is reentered at GEN_ENT_2 so as not to disturb the value of BREG; and the series is built up in the form:
B(R)=2*Z*B(R1)B(R2)+A(R), for R=1, 2, ..., N, where A(1), A(2)...A(N) are the constants supplied by the calling subroutine (SIN, ATN, LN and EXP) and B(0)=0=B(1).
The (R+1)th loop starts with B(R) on the stack and with 2*Z, B(R2) and B(R1) in mem0, mem1 and mem2 respectively.


G_LOOP  3453  DEFB $31  duplicate: B(R), B(R)  
3454  DEFB $E0  get_mem_0: B(R), B(R), 2*Z  
3455  DEFB $04  multiply: B(R), 2*B(R)*Z  
3456  DEFB $E2  get_mem_2: B(R),2*B(R)*Z, B(R1)  
3457  DEFB $C1  st_mem_1: mem1 holds B(R1)  
3458  DEFB $03  subtract: B(R), 2*B(R)*ZB(R1)  
3459  DEFB $38  end_calc  
The next constant is placed on the calculator stack.


345A  CALL stk_data  B(R), 2*B(R)*ZB(R1), A(R+1)  
The calculator is reentered without disturbing BREG.


345D  CALL GEN_ENT_2  
3460  DEFB $0F  addition: B(R), 2*B(R)*ZB(R1)+A(R+1)  
3461  DEFB $01  exchange: 2*B(R)*ZB(R1)+A(R+1), B(R)  
3462  DEFB $C2  st_mem_2: mem2 holds B(R)  
3463  DEFB $02  delete: 2*B(R)*ZB(R1)+A(R+1)=B(R+1)  
3464  DEFB $35  dec_jr_nz to G_LOOP: B(R+1)  
3465  DEFB $EE  
iv. The subtraction of B(N2). The loop above leaves B(N) on the stack and the required result is given by B(N)B(N2).


3466  DEFB $E1  get_mem_1: B(N), B(N2)  
3467  DEFB $03  subtract: B(N)B(N2)  
3468  DEFB $38  end_calc  
3469  RET  Finished. 
Prev: 343C  Up: Map  Next: 346A 