{ Subroutine to compute the tangent of a floating point input. Y=TAN(X) Calling Registers F0 = Input Value X=[6E-20, 6E20] l_reg = 0 (usually L3) Result Registers F0 = tangent of input X Altered Registers F0, F1, F2, F4, F7, F8, F12 i_reg (usually I3) Computation Time 38 Cycles Version 0.03 7/5/90 Gordon A. Sterling } #include "asm_glob.h" .SEGMENT/PM Assembly_Library_Code_Space; .PRECISION=MACHINE_PRECISION; .GLOBAL tan; tan: i_reg=tangent_data; F8=PASS F0, F2=mem(i_reg,1); { Use absolute value of input } compute_modulo: F4=F8*F2, F1=F0; { Compute fp modulo value } R2=FIX F4, F12=mem(i_reg,1); { Rnd nearest fractional portion } F4=FLOAT R2, R0=R2; { Return to fp } compute_f: F12=F12*F4, F2=mem(i_reg,1); { Compute XN*C1 } F2=F2*F4, F12=F8-F12; { Compute X-XN*C1, and XN*C2 } F8=F12-F2, F4=mem(i_reg,1); { Compute f=(X-XN*C1)-XN*C2 } F12=ABS F8, F7=F8; F4=F12-F4, F12=mem(i_reg,1); { Check for TAN(x)=x } IF LT JUMP compute_quot; { Compute quotient with NUM=f DEN=1 } compute_P: F12=F8*F8, F4=mem(i_reg,1); { g=f*f } F4=F12*F4, F2=mem(i_reg,1); { Compute p3*g } F4=F2+F4; { Compute (p3*g + p2) } F4=F12*F4, F2=mem(i_reg,1); { Compute (p3*g + p2)*g } F4=F2+F4; { Compute (p3*g + p2)*g + p1 } F4=F12*F4; { Compute ((p3*g + p2)*g + p1)*g } F4=F4*F8; { Compute ((p3*g + p2)*g + p1)*g*f } F8=F4+F8, F4=mem(i_reg,1); { Compute f*P(g) } compute_Q: F4=F12*F4, F2=mem(i_reg,1); { Compute sum*g } F4=F2+F4; { Compute sum=sum+next q } F4=F12*F4, F2=mem(i_reg,1); { Compute sum*g } F4=F2+F4; { Compute sum=sum+next q } F4=F12*F4, F2=mem(i_reg,1); { Compute sum*g } F12=F2+F4, F7=F8; { Compute sum=sum+next q } compute_quot: BTST R0 BY 0; IF NOT SZ F12=-F7, F7=F12; F0=RECIPS F12; { Get 4 bit seed R0=1/D } F12=F0*F12, F11=mem(i_reg,1); { D(prime) = D*R0 } F7=F0*F7, F0=F11-F12; { F0=R1=2-D(prime), F7=N*R0 } F12=F0*F12; { F12=D(prime)=D(prime)*R1 } F7=F0*F7, F0=F11-F12; { F7=N*R0*R1, F0=R2=2-D(prime) } RTS (DB), F12=F0*F12; { F12=D(prime)=D(prime)*R2 } F7=F0*F7, F0=F11-F12; { F7=N*R0*R1*R2, F0=R3=2-D(prime) } F0=F0*F7; { F7=N*R0*R1*R2*R3 } .ENDSEG; .SEGMENT/SPACE Assembly_Library_Data_Space; .PRECISION=MEMORY_PRECISION; .VAR tangent_data[13] = 0.6366197723675834308, { 2/PI } 1.57080078125, { C1, almost PI/2 } -4.454455103380768678308E-6, { C2, PI/2=C1+C2 } 9.536743164E-7, { eps, TAN(eps)=eps } 1.0, { Used in one path } -0.7483634966612065149E-5, { P3 } 0.2805918241169988906E-2, { P2 } -0.1282834704095743847, { P1 } -0.2084480442203870948E-3, { Q3 } 0.2334485282206872802E-1, { Q2 } -0.4616168037429048840, { Q1 } 1.0, { Q0 } 2.0; { Used in divide } .ENDSEG;