I've been thinking about the details of how TI's Z80-based calculators implement trigonometric operations (sin, cos, tan, ...) and have concluded that the details may be interesting but don't seem well-documented.
It's well-known that TI use CORDIC to iteratively compute approximations for these functions, but the details of that algorithm matter. The "classical" CORDIC as described by Volder is well suited to base-2 computers, but it's not directly applicable to a machine like a pocket calculator that "thinks" in base 10 (also well-documented, TI use a BCD floating-point numeric representation).
Hermann Schmid's 1974 book Decimal Computation describes in Chapter 7 a straightforward adaptation for CORDIC to base 10, which certainly works but suffers somewhat in that it requires 9*(number of digits) iterations to converge to an answer rather than simply (number of bits) iterations.
The most obvious reference for a pocket calculator's use of CORDIC is the HP-35, where the precise algorithms in use were described by William Egbert in the June 1977 issue of the HP Journal. Although this isn't obviously a CORDIC implementation, it borrows the terminology for pseudo-multiplication and pseudo-division from Meggit's 1962 work and the recurrence relation in use clearly matches the shift-and-add loop in CORDIC.
Rather interestingly, there seems to be an important difference between this implementation and Schmid's in that HP's version computes the tangent of an input angle only, and the sine or cosine of the angle are expressed as a ratio of the tangent or cotangent (requiring exponentiation and division to get the final result) whereas classical CORDIC can apply pre-scaled gain to get those results directly.
I've found that a straightforward implementation of Schmid's version of CORDIC in software (with decimal floating point) achieves fairly good results, but of course requires many iterations to achieve 14 digits of precision as is used on TI-Z80 calculators. That approach is also most relevant to fixed-point computations: it simply does not handle very small values (smaller than 1e-14) well.
While there exist techniques for doing accurate CORDIC in floating-point, those are both newer than I expect the TI-Z80 implementation to be, and seem very storage-intensive to implement (needing a lot of ROM). According to Mike Sebastian, every TI-Z80 calculator (82 through 86, numerically) seems to use the same implementation for these functions, the earliest of which (the 85) was released in 1992.
Although I haven't experimented with an implementation similar to the one described by Egbert, I think there's more to the story of TI's version than any single one of these sources. In particular, I found that TI's version appears to treat values smaller than 1e-6 specially: TI displays sin(1e-5) as 1e-5, but we can see the undisplayed guard digits by subtracting 1e-5 from that result, getting -1.666e-16. At sin(1e-6) however, the result is precisely equal to 1e-6.
It seems suggestive to me that the result drops off after exactly 5 decimal digits, because that matches the 5-digit pseudo-quotient described by HP. It seems that TI's implementation may assume that the sine of any angle smaller than 1e-6 radians is simply the angle itself (which tends to be accurate to about the first 12 digits!), and might also be able to recognize common angles (multiples of π/4) to return exact answers.
I'd be curious to see if anybody else has ideas on what exactly TI have done here or has interesting examples of the calculators' behavior around assorted limits, so I hope this is a suitably interesting nerd-snipe to yield discussion.
It's well-known that TI use CORDIC to iteratively compute approximations for these functions, but the details of that algorithm matter. The "classical" CORDIC as described by Volder is well suited to base-2 computers, but it's not directly applicable to a machine like a pocket calculator that "thinks" in base 10 (also well-documented, TI use a BCD floating-point numeric representation).
Hermann Schmid's 1974 book Decimal Computation describes in Chapter 7 a straightforward adaptation for CORDIC to base 10, which certainly works but suffers somewhat in that it requires 9*(number of digits) iterations to converge to an answer rather than simply (number of bits) iterations.
The most obvious reference for a pocket calculator's use of CORDIC is the HP-35, where the precise algorithms in use were described by William Egbert in the June 1977 issue of the HP Journal. Although this isn't obviously a CORDIC implementation, it borrows the terminology for pseudo-multiplication and pseudo-division from Meggit's 1962 work and the recurrence relation in use clearly matches the shift-and-add loop in CORDIC.
Rather interestingly, there seems to be an important difference between this implementation and Schmid's in that HP's version computes the tangent of an input angle only, and the sine or cosine of the angle are expressed as a ratio of the tangent or cotangent (requiring exponentiation and division to get the final result) whereas classical CORDIC can apply pre-scaled gain to get those results directly.
I've found that a straightforward implementation of Schmid's version of CORDIC in software (with decimal floating point) achieves fairly good results, but of course requires many iterations to achieve 14 digits of precision as is used on TI-Z80 calculators. That approach is also most relevant to fixed-point computations: it simply does not handle very small values (smaller than 1e-14) well.
While there exist techniques for doing accurate CORDIC in floating-point, those are both newer than I expect the TI-Z80 implementation to be, and seem very storage-intensive to implement (needing a lot of ROM). According to Mike Sebastian, every TI-Z80 calculator (82 through 86, numerically) seems to use the same implementation for these functions, the earliest of which (the 85) was released in 1992.
Although I haven't experimented with an implementation similar to the one described by Egbert, I think there's more to the story of TI's version than any single one of these sources. In particular, I found that TI's version appears to treat values smaller than 1e-6 specially: TI displays sin(1e-5) as 1e-5, but we can see the undisplayed guard digits by subtracting 1e-5 from that result, getting -1.666e-16. At sin(1e-6) however, the result is precisely equal to 1e-6.
It seems suggestive to me that the result drops off after exactly 5 decimal digits, because that matches the 5-digit pseudo-quotient described by HP. It seems that TI's implementation may assume that the sine of any angle smaller than 1e-6 radians is simply the angle itself (which tends to be accurate to about the first 12 digits!), and might also be able to recognize common angles (multiples of π/4) to return exact answers.
I'd be curious to see if anybody else has ideas on what exactly TI have done here or has interesting examples of the calculators' behavior around assorted limits, so I hope this is a suitably interesting nerd-snipe to yield discussion.