iPhoenix has been able to share images of the copy of Shampine and Allen's book he got, which is moderately interesting. I haven't spent much time studying the implementation, but it seems plausible that their
ZEROIN function is exactly the algorithm used by TI.
In the prose describing this implementation, they say that in general the two endpoints B and C must bracket a zero (f(B)*f(C)<0) which is as we'd expect from the normal closed methods, consistent with the description of this algorithm as combining bisection and the secant method. They go on to describe "abnormal" situations though, which include cases where the endpoints do not have opposite sign:
Numerical Computing: An Introduction, page 98 wrote:
If on input f(B)f(C) > 0, we do not know whether there are roots in the interval at all. The code bisects, always choosing the interval which has the smaller function values at its ends. If at any time a sign change is detected, it then proceeds in the usual way. If the length of the interval meets the convergence test but there is no sign change, this is reported to the user. The code may have computed a root of even multiplicity. If not, there appears to be no root in the interval.
(Recall that a root of even multiplicity is a point x where f(x)=0, but all points on either side of x have the same sign: the function does not cross the X axis.)
Here's the code I manually transcribed (because OCR on this FORTRAN didn't work very well). It's possible there are still some errors, because I don't fully understand how to read archaic FORTRAN like this.Code: SUBROUTINE ZEROIN(F,B,C,ABSERR,RELERR,IFLAG)
C
C ZEROIN COMPUTES A ROOT OF THE NONLINEAR EQUATION F(X)=0
C WHERE F(X) IS A CONTINUOUS REAL FUNCTION OF A SINGLE REAL
C VARIABLE X. THE METHOD USED IS A COMBINATION OF BISECTION
C AND THE SECANT RULE.
C
C NORMAL INPUT CONSISTS OF A CONTINUOUS FUNCTION F AND AN
C INTERVAL (B,C) SUCH THAT F(B)*F(C).LE.1.0. EACH ITERATION
C FINDS NEW VALUES OF B AND C SUCH THAT THE INTERVAL (B,C) IS
C SHRUNK AND F(B)*F(C).LE.0.0. THE STOPPING CRITERION IS
C
C ABS(B-C).LE.2.0*(RELERR*ABS(B)+ABSERR)
C
C WHERE RELERR=RELATIVE ERROR AND ABSERR=ABSOLUTE ERROR ARE
C INPUT QUANTITIES. AS B AND C ARE USED FOR BOTH INPUT AND
C OUTPUT, THEY MUST BE VARIABLES IN THE CALLING PROGRAM.
C THE FUNCTION NAME F MUST APPEAR IN AN EXTERNAL STATEMENT IN
C THE CALLING PROGRAM.
C
C IF 0 IS A POSSIBLE ZERO, ONE SHOULD NOT CHOOSE ABSERR=0.0.
C
C THE OUTPUT VALUE OF B IS THE BETTER APPROXIMATION TO A ROOT
C AS B AND C ARE ALWAYS REDEFINED SO THAT ABS(F(B)).LE.ABS(F(C)).
C
C A FLAG, IFLAG, IS PROVIDED AS AN OUTPUT QUANTITY. IT MAY ASSUME
C THE VALUES 1-5 WHERE
C
C IFLAG=1 IF F(B)*F(C).LE.0 AND THE STOPPING CRITERION IS MET.
C
C =2 IF A VALUE B IS FOUND SUCH THAT THE COMPUTED VALUE
C F(B) IS EXACTLY ZERO. THE INTERVAL (B,C) MAY NOT
C SATISFY THE STOPPING CRITERION.
C
C =3 IF ABS(F(B)) EXCEEDS THE INPUT VALUES ABS(F(B)),
C ABS(F(C)). IN THIS CASE IT IS LIKELY THAT B IS CLOSE
C TO A POLE OF F.
C
C =4 IF NO ODD ORDER ZERO WAS FOUND IN THE INTERVAL. A
C LOCAL MINIMUM MAY HAVE BEEN OBTAINED.
C
C =5 IF TOO MANY FUNCTION EVALUATIONS WERE MADE.
C (AS PROGRAMMED, 500 ARE ALLOWED.)
C
C
C SET U TO APPROXIMATELY THE UNIT ROUND-OFF OF SPECIFIC MACHINE.
C (HERE AN IBM 360/67)
C
U=9.0E-7
C
RE=AMAX1(RELERR,U)
IC=0
ACBS=ABS(B-C)
A=C
FA=F(A)
FB=F(B)
FC=FA
KOUNT=2
FX=AMAX1(ABS(FB),ABS(FC))
1 IF(ABS(FC).GE.ABS(FB))GO TO 2
C
C INTERCHANGE B AND C SO THAT ABS(F(B)).LE.ABS(F(C)).
C
A=B
FA=FB
B=C
FB=FC
C=A
FC=FA
2 CMB=0.5*(C-B)
ACMB=ABS(CMB)
TOL=RE*ABS(B)+ABSERR
C
C TEST STOPPING CRITERION AND FUNCTION COUNT
C
IF(ACMB.LE.TOL)GO TO 8
IF(KOUNT.GE.500)GO TO 12
C
C CALCULATE NEW ITERATE IMPLICITLY AS B+P/Q
C WHERE WE ARRANGE P.GE.0. THE IMPLICIT
C FORM IS USED TO PREVENT OVERFLOW.
C
P=(B-A)*FB
Q=FA-FB
IF(P.GE.0.0)GO TO 3
P=-P
Q=-Q
C
C UPDATE A, CHECK IF REDUCTION IN THE SIZE OF BRACKETING
C INTERVAL IS SATISFACTORY. IF NOT, BISECT UNTIL IT IS.
C
3 A=B
FA=FB
IC=IC+1
IF(IC.LT.4)GO TO 4
IF(8.0*ACMB.GE.ACBS)GO TO 6
IC=0
ACBS=ACMB
C
C TEST FOR TOO SMALL A CHANGE.
C
4 IF(P.GT.ABS(Q)*TOL)GO TO 5
C
C INCREMENT BY TOLERANCE.
C
B=B+SIGN(TOL,CMB)
GO TO 7
C
C ROOT OUGHT TO BE BETWEEN B AND (C+B)/2.
C
5 IF(P.GE.CMB*Q)GO TO 6
C
C USE SECANT RULE.
C
B=B+P/Q
GO TO 7
C
C USE BISECTION
C
6 B=0.5*(C+B)
C
C HAVE COMPLETED COMPUTATION FOR NEW ITERATE B.
C
7 FB=F(B)
IF(FB.EQ.0.0)GO TO 9
KOUNT=KOUNT+1
IF(SIGN(1.0,FB).NE.SIGN(1.0,FC))GO TO 1
C=A
FC=FA
GO TO 1
C
C FINISHED. SET IFLAG.
C
8 IF(SIGN(1.0,FB).EQ.SIGN(1.0,FC))GO TO 11
IF(ABS(FB).GT.FX)GO TO 10
IFLAG=1
RETURN
9 IFLAG=2
RETURN
10 IFLAG=3
RETURN
11 IFLAG=4
RETURN
12 IFLAG=5
RETURN
END
This seems like it ticks the major boxes: it still works if the provided endpoints have the same sign, and gives up after a while if unable to find a sign change (ERR: NO SIGN CHANGE). It doesn't permit the caller to provide an initial guess, but the TI-83 Plus manual appears to provide us with enough information to understand how it gets incorporated: TI-83 Plus / TI-83 Plus Silver Edition Graphing Calculator Guidebook, page 75 wrote:
Enter an initial guess for the variable for which you are solving. This is optional, but it may help find the solution more quickly. Also, for equations with multiple roots, the TI-83 Plus will attempt to display the solution that is closest to your guess.
The default guess is calculated as (upper+lower)/2.
So it seems like the initial guess would replace the midpoint between the two endpoints as the point at which to bisect; the first iteration won't strictly be bisecting, depending on what guess is provided.
A moderately interesting prediction made by these observations is that because roots of even multiplicity cannot be exactly pinpointed, it should be relatively easy to construct functions where the calculator returns answers that are off by a few least-significant digits, depending on the permitted relative and absolute errors.