module Numeric.Search.Integer (
        
        search, searchFrom, searchTo,
        
        search2) where
import Data.Maybe (fromMaybe)
search :: (Integer -> Bool) -> Integer
search :: (Integer -> Bool) -> Integer
search Integer -> Bool
p = Integer -> Maybe Integer -> Integer
forall a. a -> Maybe a -> a
fromMaybe ((Integer -> Bool) -> Integer -> Integer
searchFrom Integer -> Bool
p Integer
1) ((Integer -> Bool) -> Integer -> Maybe Integer
searchTo Integer -> Bool
p Integer
0)
searchFrom :: (Integer -> Bool) -> Integer -> Integer
searchFrom :: (Integer -> Bool) -> Integer -> Integer
searchFrom Integer -> Bool
p = Integer -> Integer -> Integer
search_from Integer
1
  where search_from :: Integer -> Integer -> Integer
search_from Integer
step Integer
l
          | Integer -> Bool
p Integer
l' = (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange Integer -> Bool
p Integer
l (Integer
l'Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1)
          | Bool
otherwise = Integer -> Integer -> Integer
search_from (Integer
2Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
step) (Integer
l'Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1)
          where l' :: Integer
l' = Integer
l Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
step
searchTo :: (Integer -> Bool) -> Integer -> Maybe Integer
searchTo :: (Integer -> Bool) -> Integer -> Maybe Integer
searchTo Integer -> Bool
p Integer
h0
  | Integer -> Bool
p Integer
h0 = Integer -> Maybe Integer
forall a. a -> Maybe a
Just (Integer -> Integer -> Integer
search_to Integer
1 Integer
h0)
  | Bool
otherwise = Maybe Integer
forall a. Maybe a
Nothing
  where search_to :: Integer -> Integer -> Integer
search_to Integer
step Integer
h                
          | Integer -> Bool
p Integer
h' = Integer -> Integer -> Integer
search_to (Integer
2Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
step) Integer
h'
          | Bool
otherwise = (Integer -> Bool) -> Integer -> Integer -> Integer
searchSafeRange Integer -> Bool
p (Integer
h'Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer
h
          where h' :: Integer
h' = Integer
h Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
step
search2 :: (Integer -> Integer -> Bool) -> [(Integer,Integer)]
search2 :: (Integer -> Integer -> Bool) -> [(Integer, Integer)]
search2 Integer -> Integer -> Bool
p = (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p Integer
0 Integer
0 Integer
hx Integer
hy []
  where
    hx :: Integer
hx = (Integer -> Bool) -> Integer -> Integer
searchFrom (\ Integer
x -> Integer -> Integer -> Bool
p Integer
x Integer
0) Integer
0
    hy :: Integer
hy = (Integer -> Bool) -> Integer -> Integer
searchFrom (\ Integer
y -> Integer -> Integer -> Bool
p Integer
0 Integer
y) Integer
0
search2Rect :: (Integer -> Integer -> Bool) ->
        Integer -> Integer -> Integer -> Integer ->
        [(Integer,Integer)] -> [(Integer,Integer)]
search2Rect :: (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p Integer
lx Integer
ly Integer
hx Integer
hy
  | Integer
lx Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
hx Bool -> Bool -> Bool
|| Integer
ly Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
hy = [(Integer, Integer)] -> [(Integer, Integer)]
forall a. a -> a
id
  | Integer
lx Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
hx Bool -> Bool -> Bool
&& Integer
ly Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
hy = if Integer -> Integer -> Bool
p Integer
lx Integer
ly then ((Integer
lx, Integer
ly) (Integer, Integer) -> [(Integer, Integer)] -> [(Integer, Integer)]
forall a. a -> [a] -> [a]
:) else [(Integer, Integer)] -> [(Integer, Integer)]
forall a. a -> a
id
  | Integer
hxInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
lx Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
hyInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
ly =
        let        mx :: Integer
mx = (Integer
lxInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
hx) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
                   my :: Integer
my = (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange (\ Integer
y -> Integer -> Integer -> Bool
p Integer
mx Integer
y) Integer
ly Integer
hy
        in (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p Integer
lx Integer
my Integer
mx Integer
hy ([(Integer, Integer)] -> [(Integer, Integer)])
-> ([(Integer, Integer)] -> [(Integer, Integer)])
-> [(Integer, Integer)]
-> [(Integer, Integer)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p (Integer
mxInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer
ly Integer
hx (Integer
myInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1)
  | Bool
otherwise =
        let        mx :: Integer
mx = (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange (\ Integer
x -> Integer -> Integer -> Bool
p Integer
x Integer
my) Integer
lx Integer
hx
                   my :: Integer
my = (Integer
lyInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
hy) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
        in (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p Integer
lx (Integer
myInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) (Integer
mxInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1) Integer
hy ([(Integer, Integer)] -> [(Integer, Integer)])
-> ([(Integer, Integer)] -> [(Integer, Integer)])
-> [(Integer, Integer)]
-> [(Integer, Integer)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Bool)
-> Integer
-> Integer
-> Integer
-> Integer
-> [(Integer, Integer)]
-> [(Integer, Integer)]
search2Rect Integer -> Integer -> Bool
p Integer
mx Integer
ly Integer
hx Integer
my
searchIntegerRange :: (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange :: (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange Integer -> Bool
p Integer
l Integer
h
  | Integer
h Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
l = Integer
hInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1
  | Integer -> Bool
p Integer
m = (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange Integer -> Bool
p Integer
l (Integer
mInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1)
  | Bool
otherwise = (Integer -> Bool) -> Integer -> Integer -> Integer
searchIntegerRange Integer -> Bool
p (Integer
mInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer
h
  where m :: Integer
m = (Integer
lInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
h) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
searchSafeRange :: (Integer -> Bool) -> Integer -> Integer -> Integer
searchSafeRange :: (Integer -> Bool) -> Integer -> Integer -> Integer
searchSafeRange Integer -> Bool
p Integer
l Integer
h
  | Integer
l Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
h = Integer
l
  | Integer -> Bool
p Integer
m = (Integer -> Bool) -> Integer -> Integer -> Integer
searchSafeRange Integer -> Bool
p Integer
l Integer
m
  | Bool
otherwise = (Integer -> Bool) -> Integer -> Integer -> Integer
searchSafeRange Integer -> Bool
p (Integer
mInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) Integer
h
  where m :: Integer
m = (Integer
l Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
h) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2