# Python: Bisekce a Newton-Raphsonova metoda tečen
import numpy as np
import math
from numba import njit

@njit
def fpol(x):
#  return x*x*x-1,3*x*x   # verze pro Newton-Raphson (s derivaci)
  return x*x*x-1          # verze pro bisekci (bez derivace)

@njit
def fgon(x):
#  return np.sin(x),np.cos(x)   # verze pro Newton-Raphson (s derivaci)
  return np.sin(x)              # verze pro bisekci (bez derivace)

@njit
def Bisect(f,a,b,eps,delta,nmax):
# Hledání kořenů funkce s relativní chybou eps,
# nebo přesností delta, nebo maximálním počtem kroků
# - co vyjde dřív

  n= 0; x= 0.5*(a+b)
  fa= f(a)
  fx= f(x)

  while (abs(b-a) > eps*abs(x) and abs(fx) > delta and n < nmax):
    if (fa*fx < 0):
      b= x
    else:
      a= x; fa= fx
    x= 0.5*(a+b)
    fx= f(x)
    n= n+1
  return x

@njit
def NewtonRaphson(f,x0,eps,delta,nmax):
# Hledání kořenů funkce metodou tečen
# s relativní chybou eps, nebo přesností delta,
# nebo maximálním počtem kroků - co vyjde dřív
  
  n= 0; xold= x0
  fx,ffx= f(xold)
  x= xold - fx/ffx
  
  while (abs(x-xold) > eps*abs(x) and abs(fx) > delta and n < nmax):
    xold= x
    fx,ffx= f(xold)
    x= xold - fx/ffx
    n= n+1
  return x

eps= 1.E-3
delta= 1.E-12
nmax= 1_000_000

print(Bisect(fpol,-10.0,10.0,eps,delta,nmax))
# print(NewtonRaphson(fgon,2.0,eps,delta,nmax)) 

