@@ -511,13 +511,13 @@ def solve_newton(
511511 maxiter : int = 50 ,
512512 rtol : float = RTOL ,
513513 atol : float = ATOL ,
514- ostrowski : bool = False ,
514+ order : int = 2 ,
515515 bounds : tuple [float , float ] | None = None ,
516516) -> tuple [float , bool | None ]:
517517 """
518518 Solve equation using Newton's method.
519519
520- If the second derivative is given, Halley's method will be used as an additional step.
520+ If order <= 3 and second derivative is given, Halley's method will be used as an additional step.
521521 Newton provides 2nd order convergence and Halley provides 3rd order convergence.
522522
523523 ```
@@ -535,7 +535,16 @@ def solve_newton(
535535 Step4: halley = xn - yn / (1 - 0.5 * yn * f''(xn) / f'(xn))
536536 ```
537537
538- If Ostrowski method is enabled, only one derivative is needed, but you can get 4th order convergence.
538+ If order == 3 and 2nd derivative is not provided, we can use Traub's method which gives 3rd order convergence
539+ without a second derivative.
540+
541+ ```
542+ yn = xn - f(xn) / f'(xn)
543+ traub = yn - f(yn) / f'(xn)
544+ ```
545+
546+ If order >= 3, we can use Ostrowski method where only one derivative is needed, but you can get 4th order
547+ convergence.
539548
540549 ```
541550 yn = xn - f(xn) / f'(xn)
@@ -545,6 +554,9 @@ def solve_newton(
545554 Return result along with True if converged, False if did not converge, None if could not converge.
546555 """
547556
557+ if dx2 is not None and order < 3 :
558+ order = 3
559+
548560 if bounds is not None :
549561 lo , hi = bounds
550562 bracketed = True
@@ -579,22 +591,26 @@ def solve_newton(
579591 return x0 , None
580592
581593 # Newton step
582- newton = fx / d1
583-
584- # If second derivative is provided, apply the Halley's method step: 3rd order convergence.
585- # The Newton step has been factored out of Halley's such that we can apply the rest to make
586- # it Halley's, and if we can't, or shouldn't apply it, it remains a Newton step.
587- if dx2 is not None and not ostrowski :
588- d2 = dx2 (x0 , * args ) if args else dx2 (x0 )
589- denom = 1 - (0.5 * newton * d2 ) / d1
590- if abs (denom ) >= ATOL :
591- newton /= denom
594+ newton = fx / d1
595+
596+ if order == 3 :
597+ # Halley's method: 3rd order convergence.
598+ if dx2 is not None :
599+ d2 = dx2 (x0 , * args ) if args else dx2 (x0 )
600+ denom = 1 - (0.5 * newton * d2 ) / d1
601+ if abs (denom ) >= ATOL :
602+ newton /= denom
603+
604+ # Traub's method: 3rd order convergence
605+ else :
606+ fy = f0 (x0 - newton , * args ) if args else f0 (x0 - newton )
607+ newton -= fy / d1
592608
593609 # If change is under our epsilon, we can consider the result converged.
594610 x0 -= newton
595611
596- # Use Ostrowski method: 4th order convergence
597- if ostrowski :
612+ # Ostrowski's method: 4th order convergence
613+ if order == 4 :
598614 fy = f0 (x0 , * args ) if args else f0 (x0 )
599615 denom = fx - 2 * fy
600616 if abs (denom ) >= ATOL :
0 commit comments