packages feed

AERN-Real-Double-2011.1: demos/Zero.hs

module Main where 

import Numeric.AERN.DoubleBasis.RealIntervalApprox
import Numeric.AERN.DoubleBasis.MRealIntervalApprox

import Control.Monad.ST (ST, runST)

type RI = RealIntervalApprox

main =
  do
  putStrLn $ "zero   0.1 (\\x -> x^2-0.5) (1 </\\> 2) = " ++ 
    show (zero 0.1 (\x -> x^2-0.5) (1 </\> 2))  
  putStrLn $ "zero   0.1 (\\x -> x^2-0.5) (0 </\\> 1) = " ++ 
    show (zero 0.1 (\x -> x^2-0.5) (0 </\> 1))
  putStrLn $ "zero  0.01 (\\x -> x^2-0.5) (0 </\\> 1) = " ++ 
    show (zero 0.01 (\x -> x^2-0.5) (0 </\> 1))
  putStrLn $ "zero 0.001 (\\x -> x^2-0.5) (0 </\\> 1) = " ++ 
    show (zero 0.001 (\x -> x^2-0.5) (0 </\> 1))

-- find leftmost zero of f in d to within e accuracy
zero :: RI -> (RI -> RI) -> RI -> Maybe RI
zero e f d =
  zero' e f [d]
zero' :: RI -> (RI -> RI) -> [RI] -> Maybe RI
zero' _ _ [] = Nothing 
zero' e f (d:ds)
  | imageContainsZero == Just False = 
      zero' e f ds
  | imageContainsZero == Just True && reachedSufficientAccuracy = 
      Just d
  | cannotSplit =
      error $ "zero: cannot split interval " ++ show d
  | otherwise = 
      zero' e f (dl:dr:ds)
  where
  cannotSplit = (dl |==? d) == Just True || (dr |==? d) == Just True
  imageContainsZero = fd |<=? 0 
  reachedSufficientAccuracy = 
    case width fd <? e of
      Just True -> True
      _ -> False
  (dl,dr) = bisect Nothing d
  fd = f d