module Quantum.Synthesis.Ring where
import Data.Bits
import Data.Complex
import Data.Ratio
type Ring a = (Num a)
class (Ring a) => HalfRing a where
half :: a
fromDyadic :: Dyadic -> a
fromDyadic x
| n >= 0 = fromInteger a * half^n
| otherwise = fromInteger a * 2^(n)
where
(a,n) = decompose_dyadic x
instance HalfRing Double where
half = 0.5
instance HalfRing Float where
half = 0.5
instance HalfRing Rational where
half = 1%2
instance (HalfRing a, RealFloat a) => HalfRing (Complex a) where
half = half :+ 0
fromDyadic x = fromDyadic x :+ 0
class (Ring a) => RootTwoRing a where
roottwo :: a
fromZRootTwo :: (RootTwoRing a) => ZRootTwo -> a
fromZRootTwo (RootTwo x y) = fromInteger x + roottwo * fromInteger y
instance RootTwoRing Double where
roottwo = sqrt 2
instance RootTwoRing Float where
roottwo = sqrt 2
instance (RootTwoRing a, RealFloat a) => RootTwoRing (Complex a) where
roottwo = roottwo :+ 0
class (HalfRing a, RootTwoRing a) => RootHalfRing a where
roothalf :: a
fromDRootTwo :: (RootHalfRing a) => DRootTwo -> a
fromDRootTwo (RootTwo x y) = fromDyadic x + roottwo * fromDyadic y
instance RootHalfRing Double where
roothalf = sqrt 0.5
instance RootHalfRing Float where
roothalf = sqrt 0.5
instance (RootHalfRing a, RealFloat a) => RootHalfRing (Complex a) where
roothalf = roothalf :+ 0
class (Ring a) => ComplexRing a where
i :: a
instance (Ring a, RealFloat a) => ComplexRing (Complex a) where
i = 0 :+ 1
instance (RealFloat a, RootHalfRing a) => OmegaRing (Complex a) where
omega = roothalf * (1 + i)
class (Ring a) => OmegaRing a where
omega :: a
class Adjoint a where
adj :: a -> a
instance Adjoint Integer where
adj x = x
instance Adjoint Int where
adj x = x
instance Adjoint Double where
adj x = x
instance Adjoint Float where
adj x = x
instance Adjoint Rational where
adj x = x
instance (Adjoint a, Ring a) => Adjoint (Complex a) where
adj (a :+ b) = adj a :+ (adj b)
class Adjoint2 a where
adj2 :: a -> a
instance Adjoint2 Integer where
adj2 x = x
instance Adjoint2 Int where
adj2 x = x
instance Adjoint2 Rational where
adj2 x = x
class (Ring r) => NormedRing r where
norm :: r -> Integer
instance NormedRing Integer where
norm x = x
class (Ring r) => Floor r where
floor_of :: r -> Integer
floor_of x = (ceiling_of (x))
ceiling_of :: r -> Integer
ceiling_of x = (floor_of (x))
instance Floor Integer where
floor_of = id
ceiling_of = id
instance Floor Rational where
floor_of = floor
ceiling_of = ceiling
instance Floor Float where
floor_of = floor
ceiling_of = ceiling
instance Floor Double where
floor_of = floor
ceiling_of = ceiling
data Z2 = Even | Odd
deriving (Eq)
instance Show Z2 where
show Even = "0"
show Odd = "1"
instance Num Z2 where
Even + x = x
x + Even = x
Odd + Odd = Even
Even * x = Even
x * Even = Even
Odd * Odd = Odd
negate x = x
fromInteger n = if even n then Even else Odd
abs x = x
signum x = 1
instance Adjoint Z2 where
adj x = x
instance Adjoint2 Z2 where
adj2 x = x
data Dyadic = Dyadic !Integer !Integer
decompose_dyadic :: Dyadic -> (Integer, Integer)
decompose_dyadic (Dyadic a n)
| a == 0 = (0, 0)
| n >= k = (a `shiftR` fromInteger k, nk)
| otherwise = (a `shiftR` fromInteger n, 0)
where
k = lobit a
integer_of_dyadic :: Dyadic -> Integer -> Integer
integer_of_dyadic (Dyadic a n) k =
shift a (fromInteger (kn))
instance Real Dyadic where
toRational (Dyadic a n)
| n >= 0 = a % 2^n
| otherwise = a * 2^(n) % 1
instance Show Dyadic where
showsPrec d a = showsPrec_rational d (toRational a)
instance Eq Dyadic where
Dyadic a n == Dyadic b m = a * 2^(kn) == b * 2^(km) where
k = max n m
instance Ord Dyadic where
compare (Dyadic a n) (Dyadic b m) = compare (a * 2^(kn)) (b * 2^(km)) where
k = max n m
instance Num Dyadic where
Dyadic a n + Dyadic b m
| n < m = Dyadic c m
| otherwise = Dyadic d n
where
c = shiftL a (fromInteger (mn)) + b
d = a + shiftL b (fromInteger (nm))
Dyadic a n * Dyadic b m = Dyadic (a*b) (n+m)
negate (Dyadic a n) = Dyadic (a) n
abs x = if x >= 0 then x else x
signum x = case compare 0 x of { LT -> 1; EQ -> 0; GT -> 1 }
fromInteger n = Dyadic n 0
instance HalfRing Dyadic where
half = Dyadic 1 1
fromDyadic = id
instance Adjoint Dyadic where
adj x = x
instance Adjoint2 Dyadic where
adj2 x = x
newtype Rationals = ToRationals { unRationals :: Rational }
deriving (Num, Eq, Ord, Fractional, Real, RealFrac, HalfRing, Adjoint, Adjoint2, ToQOmega, Floor)
showsPrec_rational :: (Show a, Integral a) => Int -> Ratio a -> ShowS
showsPrec_rational d a
| denom == 1 = showsPrec d numer
| numer < 0 = showParen (d >= 7) $ showString "-" . showsPrec_rational 7 (a)
| otherwise = showParen (d >= 8) $
showsPrec 7 numer . showString "/" . showsPrec 8 denom
where
numer = numerator a
denom = denominator a
instance Show Rationals where
showsPrec d (ToRationals a) = showsPrec_rational d a
fromRationals :: (Fractional a) => Rationals -> a
fromRationals = fromRational . unRationals
data RootTwo a = RootTwo !a !a
deriving (Eq)
instance (Eq a, Num a) => Num (RootTwo a) where
RootTwo a b + RootTwo a' b' = RootTwo a'' b'' where
a'' = a + a'
b'' = b + b'
RootTwo a b * RootTwo a' b' = RootTwo a'' b'' where
a'' = a * a' + 2 * b * b'
b'' = a * b' + a' * b
negate (RootTwo a b) = RootTwo a' b' where
a' = a
b' = b
fromInteger n = RootTwo n' 0 where
n' = fromInteger n
abs f = f * signum f
signum f@(RootTwo a b)
| sa == 0 && sb == 0 = 0
| sa /= 1 && sb /= 1 = 1
| sa /= 1 && sb /= 1 = 1
| sa /= 1 && sb /= 1 && signum (a*a 2*b*b) /= 1 = 1
| sa /= 1 && sb /= 1 && signum (a*a 2*b*b) /= 1 = 1
| otherwise = 1
where
sa = signum a
sb = signum b
instance (Eq a, Ring a) => Ord (RootTwo a) where
x <= y = signum (yx) /= (1)
instance (Show a, Eq a, Ring a) => Show (RootTwo a) where
showsPrec d (RootTwo a 0) = showsPrec d a
showsPrec d (RootTwo 0 1) = showString "roottwo"
showsPrec d (RootTwo 0 (1)) = showParen (d >= 7) $ showString "-roottwo"
showsPrec d (RootTwo 0 b) = showParen (d >= 8) $
showsPrec 7 b . showString "*roottwo"
showsPrec d (RootTwo a b) | signum b == 1 = showParen (d >= 7) $
showsPrec 6 a . showString " + " . showsPrec 6 (RootTwo 0 b)
showsPrec d (RootTwo a b) | otherwise = showParen (d >= 7) $
showsPrec 6 a . showString " - " . showsPrec 7 (RootTwo 0 (b))
instance (Eq a, Fractional a) => Fractional (RootTwo a) where
recip (RootTwo a b) = RootTwo (a/k) (b/k) where
k = a^2 2*b^2
fromRational r = RootTwo (fromRational r) 0
instance (Eq a, Ring a) => RootTwoRing (RootTwo a) where
roottwo = RootTwo 0 1
instance (Eq a, HalfRing a) => HalfRing (RootTwo a) where
half = RootTwo half 0
fromDyadic x = RootTwo (fromDyadic x) 0
instance (Eq a, HalfRing a) => RootHalfRing (RootTwo a) where
roothalf = RootTwo 0 half
instance (Eq a, ComplexRing a) => ComplexRing (RootTwo a) where
i = RootTwo i 0
instance (Eq a, ComplexRing a, HalfRing a) => OmegaRing (RootTwo a) where
omega = roothalf * (1 + i)
instance (Adjoint a) => Adjoint (RootTwo a) where
adj (RootTwo a b) = RootTwo (adj a) (adj b)
instance (Adjoint2 a, Num a) => Adjoint2 (RootTwo a) where
adj2 (RootTwo a b) = RootTwo (adj2 a) (adj2 b)
instance (Eq a, NormedRing a) => NormedRing (RootTwo a) where
norm (RootTwo a b) = (norm a)^2 2 * (norm b)^2
type ZRootTwo = RootTwo Integer
zroottwo_root :: ZRootTwo -> Maybe ZRootTwo
zroottwo_root z@(RootTwo a b) = res where
d = a^2 2*b^2
r = intsqrt d
x1 = intsqrt ((a + r) `div` 2)
x2 = intsqrt ((a r) `div` 2)
y1 = intsqrt ((a r) `div` 4)
y2 = intsqrt ((a + r) `div` 4)
w1 = RootTwo x1 y1
w2 = RootTwo x2 y2
w3 = RootTwo x1 (y1)
w4 = RootTwo x2 (y2)
res
| w1*w1 == z = Just w1
| w2*w2 == z = Just w2
| w3*w3 == z = Just w3
| w4*w4 == z = Just w4
| otherwise = Nothing
type DRootTwo = RootTwo Dyadic
type QRootTwo = RootTwo Rationals
instance Floor QRootTwo where
floor_of x@(RootTwo a b)
| r'+1 <= x = r+1
| r' <= x = r
| otherwise = r1
where
a' = floor a
b' = intsqrt (floor (2 * b^2))
r | b >= 0 = a' + b'
| otherwise = a' b'
r' = fromInteger r
fromQRootTwo :: (RootTwoRing a, Fractional a) => QRootTwo -> a
fromQRootTwo (RootTwo x y) = fromRationals x + roottwo * fromRationals y
data Cplx a = Cplx !a !a
deriving (Eq)
instance (Eq a, Show a, Num a) => Show (Cplx a) where
showsPrec d (Cplx a 0) = showsPrec d a
showsPrec d (Cplx 0 1) = showString "i"
showsPrec d (Cplx 0 (1)) = showParen (d >= 7) $ showString "-i"
showsPrec d (Cplx 0 b) = showParen (d >= 8) $
showsPrec 7 b . showString "*i"
showsPrec d (Cplx a b) | signum b == 1 = showParen (d >= 7) $
showsPrec 6 a . showString " + " . showsPrec 6 (Cplx 0 b)
showsPrec d (Cplx a b) | otherwise = showParen (d >= 7) $
showsPrec 6 a . showString " - " . showsPrec 7 (Cplx 0 (b))
instance (Num a) => Num (Cplx a) where
Cplx a b + Cplx a' b' = Cplx a'' b'' where
a'' = a + a'
b'' = b + b'
Cplx a b * Cplx a' b' = Cplx a'' b'' where
a'' = a * a' b * b'
b'' = a * b' + a' * b
negate (Cplx a b) = Cplx a' b' where
a' = a
b' = b
fromInteger n = Cplx n' 0 where
n' = fromInteger n
abs x = x
signum x = 1
instance (Fractional a) => Fractional (Cplx a) where
recip (Cplx a b) = Cplx (a/d) (b/d) where
d = a^2 + b^2
fromRational a = Cplx (fromRational a) 0
instance (Ring a) => ComplexRing (Cplx a) where
i = Cplx 0 1
instance (Ring a, RootHalfRing a) => OmegaRing (Cplx a) where
omega = roothalf * (1 + i)
instance (HalfRing a) => HalfRing (Cplx a) where
half = Cplx half 0
fromDyadic x = Cplx (fromDyadic x) 0
instance (RootHalfRing a) => RootHalfRing (Cplx a) where
roothalf = Cplx roothalf 0
instance (RootTwoRing a) => RootTwoRing (Cplx a) where
roottwo = Cplx roottwo 0
instance (Adjoint a, Ring a) => Adjoint (Cplx a) where
adj (Cplx a b) = (Cplx (adj a) ((adj b)))
instance (Adjoint2 a, Ring a) => Adjoint2 (Cplx a) where
adj2 (Cplx a b) = (Cplx (adj2 a) (adj2 b))
instance (NormedRing a) => NormedRing (Cplx a) where
norm (Cplx a b) = (norm a)^2 + (norm b)^2
type ZComplex = Cplx Integer
fromZComplex :: (ComplexRing a) => ZComplex -> a
fromZComplex (Cplx a b) = fromInteger a + i * fromInteger b
type DComplex = Cplx Dyadic
fromDComplex :: (ComplexRing a, HalfRing a) => DComplex -> a
fromDComplex (Cplx a b) = fromDyadic a + i * fromDyadic b
type QComplex = Cplx Rationals
fromQComplex :: (ComplexRing a, Fractional a) => QComplex -> a
fromQComplex (Cplx a b) = fromRationals a + i * fromRationals b
type DRComplex = Cplx DRootTwo
fromDRComplex :: (RootHalfRing a, ComplexRing a) => DRComplex -> a
fromDRComplex (Cplx a b) = fromDRootTwo a + i * fromDRootTwo b
type QRComplex = Cplx QRootTwo
fromQRComplex :: (RootTwoRing a, ComplexRing a, Fractional a) => QRComplex -> a
fromQRComplex (Cplx a b) = fromQRootTwo a + i * fromQRootTwo b
type CDouble = Cplx Double
type CFloat = Cplx Float
data Omega a = Omega !a !a !a !a
deriving (Eq)
omega_real :: Omega a -> a
omega_real (Omega a b c d) = d
instance (Show a, Ring a) => Show (Omega a) where
showsPrec p (Omega a b c d) =
showParen (p >= 11) $ showString "Omega " .
showsPrec 11 a . showString " " .
showsPrec 11 b . showString " " .
showsPrec 11 c . showString " " .
showsPrec 11 d
instance (Num a) => Num (Omega a) where
Omega a b c d + Omega a' b' c' d' = Omega a'' b'' c'' d'' where
a'' = a + a'
b'' = b + b'
c'' = c + c'
d'' = d + d'
Omega a b c d * Omega a' b' c' d' = Omega a'' b'' c'' d'' where
a'' = a*d' + b*c' + c*b' + d*a'
b'' = b*d' + c*c' + d*b' a*a'
c'' = c*d' + d*c' a*b' b*a'
d'' = d*d' a*c' b*b' c*a'
negate (Omega a b c d) = Omega (a) (b) (c) (d) where
fromInteger n = Omega 0 0 0 n' where
n' = fromInteger n
abs x = x
signum x = 1
instance (Fractional a) => Fractional (Omega a) where
recip (Omega a b c d) = x1 * x2 * x3 * Omega 0 0 0 (1/denom)
where
x1 = Omega (c) (b) (a) d
x2 = Omega (a) b (c) d
x3 = Omega c (b) a d
denom = (a^2+b^2+c^2+d^2)^22*(a*b+b*c+c*dd*a)^2
fromRational r = fromInteger a / fromInteger b where
a = numerator r
b = denominator r
instance (HalfRing a) => HalfRing (Omega a) where
half = Omega 0 0 0 half
fromDyadic x = Omega 0 0 0 (fromDyadic x)
instance (HalfRing a) => RootHalfRing (Omega a) where
roothalf = Omega (half) 0 half 0
instance (Ring a) => RootTwoRing (Omega a) where
roottwo = Omega (1) 0 1 0
instance (Ring a) => ComplexRing (Omega a) where
i = Omega 0 1 0 0
instance (Adjoint a, Ring a) => Adjoint (Omega a) where
adj (Omega a b c d) = Omega ((adj c)) ((adj b)) ((adj a)) (adj d)
instance (Adjoint2 a, Ring a) => Adjoint2 (Omega a) where
adj2 (Omega a b c d) = Omega (adj2 a) (adj2 b) (adj2 c) (adj2 d)
instance (NormedRing a) => NormedRing (Omega a) where
norm (Omega x y z w) = (a^2+b^2+c^2+d^2)^22*(a*b+b*c+c*dd*a)^2
where
a = norm x
b = norm y
c = norm z
d = norm w
instance (Ring a) => OmegaRing (Omega a) where
omega = Omega 0 0 1 0
type ZOmega = Omega Integer
fromZOmega :: (OmegaRing a) => ZOmega -> a
fromZOmega (Omega a b c d) = fromInteger a * omega^3 + fromInteger b * omega^2 + fromInteger c * omega + fromInteger d
zroottwo_of_zomega :: ZOmega -> ZRootTwo
zroottwo_of_zomega (Omega a b c d)
| a == c && b == 0 = RootTwo d c
| otherwise = error "zroottwo_of_zomega: non-real value"
type DOmega = Omega Dyadic
fromDOmega :: (OmegaRing a, HalfRing a) => DOmega -> a
fromDOmega (Omega a b c d) = fromDyadic a * omega^3 + fromDyadic b * omega^2 + fromDyadic c * omega + fromDyadic d
instance Show DOmega where
showsPrec = showsPrec_DenomExp
instance Show DRComplex where
showsPrec = showsPrec_DenomExp
type QOmega = Omega Rationals
fromQOmega :: (OmegaRing a, Fractional a) => QOmega -> a
fromQOmega (Omega a b c d) = fromRationals a * omega^3 + fromRationals b * omega^2 + fromRationals c * omega + fromRationals d
class ToDyadic a b | a -> b where
maybe_dyadic :: a -> Maybe b
to_dyadic :: (ToDyadic a b) => a -> b
to_dyadic a = case maybe_dyadic a of
Just b -> b
Nothing -> error "to_dyadic: denominator not a power of 2"
instance ToDyadic Dyadic Dyadic where
maybe_dyadic = return
instance ToDyadic Rational Dyadic where
maybe_dyadic x = do
k <- log2 denom
return (Dyadic numer k)
where denom = denominator x
numer = numerator x
instance ToDyadic Rationals Dyadic where
maybe_dyadic = maybe_dyadic . unRationals
instance (ToDyadic a b) => ToDyadic (RootTwo a) (RootTwo b) where
maybe_dyadic (RootTwo x y) = do
x' <- maybe_dyadic x
y' <- maybe_dyadic y
return (RootTwo x' y')
instance (ToDyadic a b) => ToDyadic (Cplx a) (Cplx b) where
maybe_dyadic (Cplx x y) = do
x' <- maybe_dyadic x
y' <- maybe_dyadic y
return (Cplx x' y')
instance (ToDyadic a b) => ToDyadic (Omega a) (Omega b) where
maybe_dyadic (Omega x y z w) = do
x' <- maybe_dyadic x
y' <- maybe_dyadic y
z' <- maybe_dyadic z
w' <- maybe_dyadic w
return (Omega x' y' z' w')
class RealPart a b | a -> b where
real :: a -> b
instance RealPart (Cplx a) a where
real (Cplx a b) = a
instance (HalfRing a) => RealPart (Omega a) (RootTwo a) where
real (Omega a b c d) = RootTwo d (half * (c a))
class WholePart a b | a -> b where
from_whole :: b -> a
to_whole :: a -> b
instance WholePart Dyadic Integer where
from_whole = fromInteger
to_whole d
| n == 0 = a
| otherwise = error "to_whole: non-integral value"
where
(a,n) = decompose_dyadic d
instance WholePart DRootTwo ZRootTwo where
from_whole = fromZRootTwo
to_whole (RootTwo x y) = RootTwo (to_whole x) (to_whole y)
instance WholePart DOmega ZOmega where
from_whole = fromZOmega
to_whole (Omega x y z w) = Omega (to_whole x) (to_whole y) (to_whole z) (to_whole w)
instance (WholePart a a', WholePart b b') => WholePart (a,b) (a',b') where
from_whole (x,y) = (from_whole x, from_whole y)
to_whole (x,y) = (to_whole x, to_whole y)
instance WholePart () () where
from_whole = const ()
to_whole = const ()
instance (WholePart a b) => WholePart [a] [b] where
from_whole = map from_whole
to_whole = map to_whole
instance (WholePart a b) => WholePart (Cplx a) (Cplx b) where
from_whole (Cplx a b) = Cplx (from_whole a) (from_whole b)
to_whole (Cplx a b) = Cplx (to_whole a) (to_whole b)
class DenomExp a where
denomexp :: a -> Integer
denomexp_factor :: a -> Integer -> a
denomexp_decompose :: (WholePart a b, DenomExp a) => a -> (b, Integer)
denomexp_decompose a = (b, k) where
k = denomexp a
b = to_whole (denomexp_factor a k)
showsPrec_DenomExp :: (WholePart a b, Show b, DenomExp a) => Int -> a -> ShowS
showsPrec_DenomExp d a
| k == 0 = showsPrec d b
| k == 1 = showParen (d >= 8) $
showString "roothalf * " . showsPrec 7 b
| otherwise = showParen (d >= 8) $
showString ("roothalf^" ++ show k ++ " * ") . showsPrec 7 b
where (b, k) = denomexp_decompose a
instance DenomExp DRootTwo where
denomexp (RootTwo x y) = k'
where
(a,k) = decompose_dyadic x
(b,l) = decompose_dyadic y
k' = maximum [2*k, 2*l1]
denomexp_factor a k = a * roottwo^k
instance DenomExp DOmega where
denomexp (Omega x y z w) = k'
where
(a,ak) = decompose_dyadic x
(b,bk) = decompose_dyadic y
(c,ck) = decompose_dyadic z
(d,dk) = decompose_dyadic w
k = maximum [ak, bk, ck, dk]
a' = if k == ak then a else 0
b' = if k == bk then b else 0
c' = if k == ck then c else 0
d' = if k == dk then d else 0
k' | k>0 && even (a'c') && even (b'd') = 2*k1
| otherwise = 2*k
denomexp_factor a k = a * roottwo^k
instance (DenomExp a, DenomExp b) => DenomExp (a,b) where
denomexp (a,b) = denomexp a `max` denomexp b
denomexp_factor (a,b) k = (denomexp_factor a k, denomexp_factor b k)
instance DenomExp () where
denomexp _ = 0
denomexp_factor _ k = ()
instance (DenomExp a) => DenomExp [a] where
denomexp as = maximum (0 : [ denomexp a | a <- as ])
denomexp_factor as k = [ denomexp_factor a k | a <- as ]
instance (DenomExp a) => DenomExp (Cplx a) where
denomexp (Cplx a b) = denomexp a `max` denomexp b
denomexp_factor (Cplx a b) k = Cplx (denomexp_factor a k) (denomexp_factor b k)
class ToQOmega a where
toQOmega :: a -> QOmega
instance ToQOmega Integer where
toQOmega = fromInteger
instance ToQOmega Rational where
toQOmega = fromRational
instance (ToQOmega a) => ToQOmega (RootTwo a) where
toQOmega (RootTwo a b) = toQOmega a + roottwo * toQOmega b
instance ToQOmega Dyadic where
toQOmega (Dyadic a n)
| n >= 0 = toQOmega a * half^n
| otherwise = toQOmega a * 2^(n)
instance (ToQOmega a) => ToQOmega (Cplx a) where
toQOmega (Cplx a b) = toQOmega a + i * toQOmega b
instance (ToQOmega a) => ToQOmega (Omega a) where
toQOmega (Omega a b c d) = omega^3 * a' + omega^2 * b' + omega * c' + d'
where
a' = toQOmega a
b' = toQOmega b
c' = toQOmega c
d' = toQOmega d
class Parity a where
parity :: a -> Z2
instance Integral a => Parity a where
parity x = if even x then 0 else 1
instance Parity ZRootTwo where
parity (RootTwo a b) = parity a
lobit :: Integer -> Integer
lobit 0 = 1
lobit n = aux 1 where
aux k
| n .&. (2^k1) == 0 = aux (2*k)
| otherwise = aux2 k (k `div` 2)
aux2 upper lower
| upper lower < 2 = lower
| n .&. (2^middle1) == 0 = aux2 upper middle
| otherwise = aux2 middle lower
where
middle = (upper + lower) `div` 2
log2 :: Integer -> Maybe Integer
log2 n
| n <= 0 = Nothing
| n == 2^k = Just k
| otherwise = Nothing
where
k = lobit n
hibit :: Integer -> Int
hibit 0 = 0
hibit n = aux 1 where
aux k
| n >= 2^k = aux (2*k)
| otherwise = aux2 k (k `div` 2)
aux2 upper lower
| upper lower < 2 = upper
| n >= 2^middle = aux2 upper middle
| otherwise = aux2 middle lower
where
middle = (upper + lower) `div` 2
intsqrt :: (Integral n) => n -> n
intsqrt n
| n <= 0 = 0
| otherwise = iterate a
where
iterate m
| m_sq <= n && m_sq + 2*m + 1 > n = m
| otherwise = iterate ((m + n `div` m) `div` 2)
where
m_sq = m*m
a = 2^(b `div` 2)
b = hibit (fromIntegral n)