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.
While I don't have the math abilities to contribute to discussions on their algorithms I am curious if you or anyone else tried to dig into the code or one of the dissassemblies floating around to see if they can decipher what is going on from there? I'm sure considering some of your projects it likely better to do this more black box style. I'm also curious if that would even be a worthwhile route to look into, I know TI's float code can pretty esoteric to understand so I could also see a situation where it actually makes things harder to figure out instead of easier.
I've considered looking into the implementation, but haven't yet bothered. When I first posted this I think I saw Zeroko imply in chat that they were going to load up a disassembly but seemed stymied by some kind of tooling update (since the last time they had used the tools for that).
Somebody asked a question on Reddit about where error creeps in when taking exponents of i that seems relevant to this investigation as well.

Small exponents like i² (1) and i³ (-1) are displayed exactly, but when you reach an exponent of 7 then the displayed value is off by a factor of about 1e-13. I suppose that exponentiation of complex numbers may be implemented by converting to polar form and back, taking advantage of the same CORDIC algorithm to do those conversions.

When the input angle to CORDIC is large we know that it needs to be scaled to be in range (usually 0-π/2), so I suspect that large exponents end up like large angles where scaling them to be in range introduces a small error (on the order of 1 least-significant digit per turn) which becomes evident when the exponent of i becomes large enough.

It's also a little bit interesting that powers that are a multiple of 10 (i10, i20) continue to yield exact results (-1). I suspect this is because the power of 10 simply causes the exponent of the value to change, which doesn't introduce any further error in the mantissa.
I've been investigating the OS behavior when displaying numbers in FLOAT + NORMAL mode, the results of which seem relevant to the notes here.
• Numbers in the range of 0.001 (inclusive) to 1e10 (exclusive) are displayed as decimals; others are displayed in exponential notation.
• Values are rounded to 10 significant digits, with trailing zeroes truncated in FLOAT mode.
• It seems like some exponents cause the value to be rounded to 9 significant digits instead: -9.999999999 displays all 10 digits, whereas -9.999999999e-99 (same number of digits but with a very small exponent) is displayed as 1e-98: the 10th digit was rounded off.

The last point is particularly interesting to me, because the maximum width (in characters) of a number with 10 significant digits is 16 characters (a negative sign, 10 digits, a decimal point, the exponent E, and two more digits with a negative sign); conveniently exactly the width of the homescreen. It seems like it might be designed to limit the display format of a number to 15 characters, but even small exponents (like on the value -9.999999999e-3) are still rounded off so it's not clear when the calculator decides to reduce to 9-digit precision.
It's also possible that it's losing a digit of precision when evaluating the exponent (because I believe the expression "1.23e8" first parses the value 1.23 then adjusts the exponent by +8), but I'd expect that exponent adjustment to not affect the precision of the mantissa.

The 83+ manual isn't much help, though it does seem to suggest that under some conditions FLOAT mode will display fewer than 10 digits:
Quote:
Note: If you select Normal notation, but the answer cannot display in 10 digits (or the absolute value is less than .001), the TI-83 Plus expresses the answer in scientific notation.
This is consistent with my experiments.
Quote:
Float (floating) decimal mode displays up to 10 digits, plus the sign and decimal.
That seems like a load-bearing "up to," but it's a shame that they didn't specify the conditions under which you might get fewer.

Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

»
» All times are UTC - 5 Hours

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum