module Data.Realnumber where
import Data.Bits
import GHC.Real
import Debug.Trace
type FigureSequence = [Int]
figureValue :: FigureSequence -> Int
figureValue (1:_) = 1
figureValue ( 0:_) = 0
figureValue ( 1:_) = 1
twoFigureValue :: FigureSequence -> Int
twoFigureValue fs = 2 * (figureValue fs) + (figureValue . nextFig) fs
nFigureValue :: Integer -> FigureSequence -> Integer
nFigureValue n fs = acc (n, fs, 0)
where
acc (0, fs, v) = v
acc (i,1:fs, v) = acc (i1, fs, 2*v 1)
acc (i, 0:fs, v) = acc (i1, fs, 2*v)
acc (i, 1:fs, v) = acc (i1, fs, 2*v +1)
showFigureSequence :: FigureSequence -> [Char]
showFigureSequence (1:fs) = "_" ++ (showFigureSequence fs)
showFigureSequence ( 0:fs) = "0" ++ (showFigureSequence fs)
showFigureSequence ( 1:fs) = "1" ++ (showFigureSequence fs)
zeroS :: FigureSequence
zeroS = 0:zeroS
nextFig :: FigureSequence -> FigureSequence
nextFig = tail
uberNextFig :: FigureSequence -> FigureSequence
uberNextFig = nextFig . nextFig
negateSequence :: FigureSequence -> FigureSequence
negateSequence (1:fs) = 1:(negateSequence fs)
negateSequence ( 0:fs) = 0:(negateSequence fs)
negateSequence ( 1:fs) = 1:(negateSequence fs)
data RealNumber = R Integer FigureSequence
instance Show RealNumber where
show (R i fs) = "2^" ++ (show i) ++ " * 0." ++ (showFigureSequence fs)
sumWithOneFigure :: (FigureSequence, FigureSequence) -> Int
sumWithOneFigure (xs, ys) = figureValue xs + figureValue ys
sequencePlus :: (FigureSequence, FigureSequence) -> FigureSequence
sequencePlus (fs1, fs2) = plusAcc (nextFig fs1, nextFig fs2, sumWithOneFigure (fs1, fs2))
where
plusAcc (fs1, fs2, c)
| 6 <= s && s <= 2 = 1:(plusAcc (nfs1, nfs2, s + 4))
| 2 <= s && s <= 2 = 0:(plusAcc (nfs1, nfs2, s + 0))
| 2 <= s && s <= 6 = 1:(plusAcc (nfs1, nfs2, s 4))
where
s = sumWithOneFigure (fs1, fs2) + 2 * c
nfs1 = nextFig fs1
nfs2 = nextFig fs2
sequenceProduct :: (FigureSequence, FigureSequence) -> FigureSequence
sequenceProduct (fs1, fs2)
| 1 <= v1 && v1 <= 1
= 0: sequenceProduct (v1 : r1, fs2)
| 1 <= v2 && v2 <= 1
= sequenceProduct (fs2, fs1)
| v1 < 0 && v2 < 0
= sequenceProduct (negateSequence fs1, negateSequence fs2)
| v1 < 0 || v2 < 0
= negateSequence (sequenceProduct (negateSequence fs1, fs2))
| v1 == 3 && v2 == 2
= sequenceProduct (fs2, fs1)
| v1 == 3 && v2 == 3
= 1: sequencePlus (sequenceProduct (1:r1, 1:r2),
sequencePlus (r1, r2))
--example:
| v1 == 2 && v2 == 3
= 1: sequencePlus (sequencePlus(r1, r2),
1: sequenceProduct(r1, 1:r2))
| v1 == 2 && v2 == 2
= 1: (forceSimplify . sequencePlus)
(1: sequencePlus (r1, r2),
0:0: sequenceProduct (r1, r2))
where
r1 = uberNextFig fs1
r2 = uberNextFig fs2
v1 = twoFigureValue fs1
v2 = twoFigureValue fs2
absSequence :: FigureSequence -> FigureSequence
absSequence ( 0:fs) = 0: (absSequence fs)
absSequence ( 1:fs) = 1: fs
absSequence (1:fs) = 1: (negateSequence fs)
sequenceSignum :: FigureSequence -> FigureSequence
sequenceSignum ( 0: fs) = sequenceSignum fs
sequenceSignum (1: _) = 1: zeroS
sequenceSignum ( 1: _) = 1: zeroS
compareZero :: RealNumber -> Ordering
compareZero (R e (1:fs)) = LT
compareZero (R e ( 1:fs)) = GT
compareZero (R e ( 0:fs)) = compareZero (R (e1) fs)
maxReal :: RealNumber -> RealNumber -> RealNumber
maxReal (R e1 fs1) (R e2 fs2)
| e1 > e2 = maxReal (R e1 fs1) (R e1 (headingZeros (e1e2) fs2))
| e2 > e1 = maxReal (R e2 (headingZeros (e2e1) fs1)) (R e2 fs2)
| otherwise = R e1 (maxSequence 0 fs1 fs2)
maxSequence :: Int -> FigureSequence -> FigureSequence -> FigureSequence
maxSequence u (f1:fs1) (f2:fs2)
| u > 1 = f1:fs1
| u > 0 = f1:maxSequence (2*u +f1f2) fs1 fs2
| u < 1 = f2:fs2
| u < 0 = f2:maxSequence (2*u +f1f2) fs1 fs2
| f1 >=f2 = f1:maxSequence ( f1f2) fs1 fs2
| f2 >=f1 = f2:maxSequence ( f1f2) fs1 fs2
minReal :: RealNumber -> RealNumber -> RealNumber
minReal x y = (maxReal (x) (y))
einsdurch :: Integer -> FigureSequence
einsdurch 0 = error "division by zero"
einsdurch m = helper (1, m)
where
helper (n, m)
| 2*m*n < m*m = 1: (helper (2*(n+m), m))
| 2*m*n > m*m = 1: (helper (2*(nm), m))
| otherwise = 0: (helper (2*n, m))
msb :: Integer -> Int
msb i = msbH (abs i, 1)
where
msbH :: (Integer, Int) -> Int
msbH (i, erg)
| i == 0 = erg
|otherwise= msbH (shiftR i 1, erg+1)
headingZeros :: Integer -> FigureSequence -> FigureSequence
headingZeros 0 fs = fs
headingZeros n fs = headingZeros (n1) ( 0: fs)
simplify :: RealNumber -> RealNumber
simplify (R e ( 0: fs)) = R (e1) fs
simplify (R e ( 1: (1: fs))) = R (e1) ( 1: fs)
simplify (R e (1: ( 1: fs))) = R (e1) (1: fs)
simplify x = x
simplifyAll :: RealNumber -> RealNumber
simplifyAll (R e ( 0: fs)) = simplifyAll (R (e1) fs)
simplifyAll (R e ( 1: (1: fs))) = simplifyAll (R (e1) ( 1: fs))
simplifyAll (R e (1: ( 1: fs))) = simplifyAll (R (e1) (1: fs))
simplifyAll x = x
forceSimplify :: FigureSequence -> FigureSequence
forceSimplify ( 0: fs) = fs
forceSimplify ( 1: (1: fs)) = 1: fs
forceSimplify (1: ( 1: fs)) = 1: fs
forceSimplify fs = error (show (take 5 fs))
forceNSimplify :: Integer -> FigureSequence -> FigureSequence
forceNSimplify 0 fs = fs
forceNSimplify n fs = forceNSimplify (n1) (forceSimplify fs)
shiftReal :: RealNumber -> Integer -> RealNumber
shiftReal (R e fs) s = R (e+s) fs
instance Num RealNumber where
negate (R e fs) = R e (negateSequence fs)
fromInteger i
| i < 0 = negate (fromInteger (i))
|otherwise= R (toInteger (msb i +1)) (helper (msb i))
where
helper v
| v < 0 = zeroS
|testBit i v= 1: (helper (v1))
| otherwise = 0: (helper (v1))
R e1 fs1 + R e2 fs2
| e1 > e2 = (R e2 fs2) + (R e1 fs1)
| e1 <= e2 = simplify (R (e2+1) fsNew)
where
fsNew = sequencePlus (headingZeros (e2e1) fs1, fs2)
R e1 fs1 * R e2 fs2
= R (e2+e1) (sequenceProduct (fs1, fs2))
abs (R e fs) = R e (absSequence fs)
signum (R e fs) = R 1 (sequenceSignum fs)
instance Eq RealNumber where
x == y = compareZero (xy) == EQ
instance Ord RealNumber where
compare x y = compareZero (xy)
data ApproxReal = A Integer [Int]
takeI :: Integer -> [a] -> [a]
takeI _ [] = []
takeI i (x:xs)
| i <= 0 = []
| otherwise = x: takeI (i1) xs
approx :: RealNumber -> Integer -> ApproxReal
approx (R e fs) i
| e > i = A e (takeI (ei) fs)
| e <= i = A i []
type Intervall = (RealNumber, RealNumber)
intervallToApprox :: Intervall -> ApproxReal
intervallToApprox (R e1 (f1':fs1'), R e2 (f2':fs2'))
| e1 < e2 = intervallToApprox (R e2 (headingZeros (e2e1) (f1':fs1')), R e2 (f2':fs2'))
| e1 > e2 = intervallToApprox (R e1 (f1':fs1'), R e1 (headingZeros (e1e2) (f2':fs2')))
| e1 == e2 = A e1 (helper f1' fs1' f2' fs2')
where
helper u1 (f1:fs1) u2 (f2:fs2)
| 2*u2 +f2 +1 < 2*u1 +f1 || u2 < 1 || u1 > 1 = error "in intervallToApprox: (a, b) with b > a is forbidden!"
| abs (2*u1 +f1) < 2 && abs (2*u2 +f2) < 2
= 0 : helper (2*u1 +f1 ) fs1 (2*u2 +f2 ) fs2
| 2*u2 +f2 < 0 && 2*u1 +f1 < 0 = 1 : helper (2*u1 +f1 +2) fs1 (2*u2 +f2 +2) fs2
| 2*u1 +f1 > 0 && 2*u1 +f1 > 0 = 1 : helper (2*u1 +f1 2) fs1 (2*u2 +f2 2) fs2
| otherwise = []
instance Show ApproxReal where
show (A e fs) = "2^" ++ (show e) ++ " * 0." ++ (showEndingSequence fs)
where
showEndingSequence (1:fs) = "_" ++ (showEndingSequence fs)
showEndingSequence ( 0:fs) = "0" ++ (showEndingSequence fs)
showEndingSequence ( 1:fs) = "1" ++ (showEndingSequence fs)
showEndingSequence [] = "&c"
type ApproxRealSchachtelung = [ApproxReal]
realFromAppRealSchach :: ApproxRealSchachtelung -> RealNumber
realFromAppRealSchach (A e fs : ars)
= R e (fs ++ moreFigures fs ars)
where
moreFigures fs_fix (A e_next fs_next : ars)
| e_next > e = moreFigures fs_fix (A e (forceNSimplify (e_next e) fs_next) : ars)
| e_next < e = moreFigures fs_fix (A e (headingZeros (e e_next) fs_next) :ars)
| otherwise = fs_next_rest ++ (moreFigures (fs_fix ++ fs_next_rest) ars)
where
fs_next_rest = getBest 0 fs_fix fs_next
getBest u [] (f2:fs2)
| abs (2*u +f2) > 1 = error "approximations given to realFromAppRealSchach are not nested!"
| otherwise = (2*u +f2):fs2
getBest _ [] [] = []
getBest u fs1 [] = []
getBest u (f1:fs1) (f2:fs2) = getBest (2*u +f2f1) fs1 fs2
type IntervallSchachtelung = [Intervall]
approxRealSchachtelung :: IntervallSchachtelung -> ApproxRealSchachtelung
approxRealSchachtelung = map intervallToApprox
realFromSchach :: IntervallSchachtelung -> RealNumber
realFromSchach = realFromAppRealSchach . approxRealSchachtelung
intervallEinsdurch :: RealNumber -> IntervallSchachtelung
intervallEinsdurch xs = map einsdurchSequence [0..]
where
e :: Integer
fs :: FigureSequence
R e fs = simplifyAll xs
einsdurchSequence :: Integer -> (RealNumber, RealNumber)
einsdurchSequence m = (R (e+m+3) (einsdurch v1), R (e+m+3) (einsdurch v_))
where
v_ = nFigureValue (m+2) fs 1
v1 = nFigureValue (m+2) fs + 1
instance Fractional RealNumber where
fromRational (x :% y) = fromInteger x * R 1 (einsdurch y)
recip = realFromSchach . intervallEinsdurch
zero = R 0 zeroS
one = R 1 ( 1: zeroS)