123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- {-# OPTIONS --no-termination-check #-}
- module Data.Real.CReal where
- import Prelude
- import Data.Bool
- import Data.String
- import Data.Real.Complete
- import Data.Real.Base
- import Data.Nat
- import Data.Integer
- import Data.Rational as Rational
- import Data.Interval
- import Data.Real.Gauge
- import Data.Show
- import Data.List
- import Data.Tuple
- open Prelude
- open Data.Real.Base
- open Data.Real.Complete
- open Data.Integer using (Int; pos) renaming (_-_ to _-i_; _<_ to _<i_)
- open Rational hiding (fromInt)
- open Data.Bool
- open Data.String
- open Data.Interval
- open Data.Real.Gauge
- open Data.Nat using (Nat)
- open Data.Tuple
- data CReal : Set where
- cReal : Complete Base -> CReal
- approx : CReal -> Complete Base
- approx (cReal f) ε = f ε
- inject : Base -> CReal
- inject x = cReal (unit x)
- data BoundedCReal : Set where
- _∈_ : CReal -> Interval Base -> BoundedCReal
- around : CReal -> Int
- around (cReal f) = round (f (pos 1 % pos 2))
- integerInterval : CReal -> Interval Base
- integerInterval f = [ i - fromNat 1 ▻ i + fromNat 1 ]
- where
- i = Rational.fromInt (around f)
- compact : CReal -> BoundedCReal
- compact x = x ∈ integerInterval x
- choke : BoundedCReal -> CReal
- choke (cReal x ∈ [ lb ▻ ub ]) = cReal f
- where
- f : Complete Base
- f ε = ! y < lb => lb
- ! ub < y => ub
- ! otherwise y
- where
- y = x ε
- compress : Complete Base -> Complete Base
- compress x ε = approxBase (x ε2) ε2
- where
- ε2 = ε / fromNat 2
- mapCR : (Base ==> Base) -> CReal -> CReal
- mapCR f (cReal x) = cReal $ mapC f (compress x)
- mapCR2 : (Base ==> Base ==> Base) -> CReal -> CReal -> CReal
- mapCR2 f (cReal x) (cReal y) = cReal $ mapC2 f (compress x) (compress y)
- bindR : (Base ==> Complete Base) -> CReal -> CReal
- bindR f (cReal x) = cReal $ bind f (compress x)
- approxRange : CReal -> Gauge -> Interval Base
- approxRange x ε = [ r - ε ▻ r + ε ]
- where
- r = approx x ε
- -- non-terminates for 0
- proveNonZeroFrom : Gauge -> CReal -> Base
- proveNonZeroFrom g r =
- ! high < fromNat 0 => high
- ! fromNat 0 < low => low
- ! otherwise proveNonZeroFrom (g / fromNat 2) r
- where
- i = approxRange r g
- low = lowerBound i
- high = upperBound i
- proveNonZero : CReal -> Base
- proveNonZero = proveNonZeroFrom (fromNat 1)
- -- Negation
- negateCts : Base ==> Base
- negateCts = uniformCts id (-_)
- realNegate : CReal -> CReal
- realNegate = mapCR negateCts
- -- Addition
- plusBaseCts : Base -> Base ==> Base
- plusBaseCts a = uniformCts id (_+_ a)
- plusCts : Base ==> Base ==> Base
- plusCts = uniformCts id plusBaseCts
- realPlus : CReal -> CReal -> CReal
- realPlus = mapCR2 plusCts
- realTranslate : Base -> CReal -> CReal
- realTranslate a = mapCR (plusBaseCts a)
- -- Multiplication
- multBaseCts : Base -> Base ==> Base
- multBaseCts (pos 0 %' _) = constCts (fromNat 0)
- multBaseCts a = uniformCts μ (_*_ a)
- where
- μ = \ε -> ε / ! a !
- -- First argument must be ≠ 0
- multCts : Base -> Base ==> Base ==> Base
- multCts maxy = uniformCts μ multBaseCts
- where
- μ = \ε -> ε / maxy
- realScale : Base -> CReal -> CReal
- realScale a = mapCR (multBaseCts a)
- bound : Interval Base -> Base
- bound [ lb ▻ ub ] = max ub (- lb)
- realMultBound : BoundedCReal -> CReal -> CReal
- realMultBound (x ∈ i) y = mapCR2 (multCts b) y (choke (x ∈ i))
- where
- b = bound i
- realMult : CReal -> CReal -> CReal
- realMult x y = realMultBound (compact x) y
- -- Absolute value
- absCts : Base ==> Base
- absCts = uniformCts id !_!
- realAbs : CReal -> CReal
- realAbs = mapCR absCts
- fromInt : Int -> CReal
- fromInt x = inject (Rational.fromInt x)
- fromRational : Rational -> CReal
- fromRational = inject
- -- Reciprocal
- recipCts : Base -> Base ==> Base
- recipCts nz = uniformCts μ f
- where
- f : Base -> Base
- f a = ! fromNat 0 ≤ nz => recip (max nz a)
- ! otherwise recip (min a nz)
- μ = \ε -> ε * nz ^ pos 2
- realRecipWitness : Base -> CReal -> CReal
- realRecipWitness nz = mapCR (recipCts nz)
- realRecip : CReal -> CReal
- realRecip x = realRecipWitness (proveNonZero x) x
- -- Exponentiation
- intPowerCts : Gauge -> Int -> Base ==> Base
- intPowerCts _ (pos 0) = constCts (fromNat 1)
- intPowerCts maxx n = uniformCts μ (flip _^_ n)
- where
- μ = \ε -> ε / (Rational.fromInt n * maxx ^ (n -i pos 1))
- realPowerIntBound : BoundedCReal -> Int -> CReal
- realPowerIntBound (x ∈ i) n = mapCR (intPowerCts b n) (choke (x ∈ i))
- where
- b = bound i
- realPowerInt : CReal -> Int -> CReal
- realPowerInt = realPowerIntBound ∘ compact
- showReal : Nat -> CReal -> String
- showReal n x =
- ! len ≤' n => sign ++ "0." ++ fromList (replicate (n -' len) '0') ++ s
- ! otherwise sign ++ i ++ "." ++ f
- where
- open Data.Nat using () renaming
- ( _^_ to _^'_
- ; div to div'; mod to mod'
- ; _==_ to _=='_; _≤_ to _≤'_
- ; _-_ to _-'_
- )
- open Data.Show
- open Data.List hiding (_++_)
- open Data.Integer using () renaming (-_ to -i_)
- k = 10 ^' n
- m = around $ realScale (fromNat k) x
- m' = if m <i pos 0 then -i m else m
- s = showInt m'
- sign = if m <i pos 0 then "-" else ""
- len = length (toList s)
- p = splitAt (len -' n) $ toList s
- i = fromList $ fst p
- f = fromList $ snd p
|