CReal.agda 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. {-# OPTIONS --no-termination-check #-}
  2. module Data.Real.CReal where
  3. import Prelude
  4. import Data.Bool
  5. import Data.String
  6. import Data.Real.Complete
  7. import Data.Real.Base
  8. import Data.Nat
  9. import Data.Integer
  10. import Data.Rational as Rational
  11. import Data.Interval
  12. import Data.Real.Gauge
  13. import Data.Show
  14. import Data.List
  15. import Data.Tuple
  16. open Prelude
  17. open Data.Real.Base
  18. open Data.Real.Complete
  19. open Data.Integer using (Int; pos) renaming (_-_ to _-i_; _<_ to _<i_)
  20. open Rational hiding (fromInt)
  21. open Data.Bool
  22. open Data.String
  23. open Data.Interval
  24. open Data.Real.Gauge
  25. open Data.Nat using (Nat)
  26. open Data.Tuple
  27. data CReal : Set where
  28. cReal : Complete Base -> CReal
  29. approx : CReal -> Complete Base
  30. approx (cReal f) ε = f ε
  31. inject : Base -> CReal
  32. inject x = cReal (unit x)
  33. data BoundedCReal : Set where
  34. _∈_ : CReal -> Interval Base -> BoundedCReal
  35. around : CReal -> Int
  36. around (cReal f) = round (f (pos 1 % pos 2))
  37. integerInterval : CReal -> Interval Base
  38. integerInterval f = [ i - fromNat 1 ▻ i + fromNat 1 ]
  39. where
  40. i = Rational.fromInt (around f)
  41. compact : CReal -> BoundedCReal
  42. compact x = x ∈ integerInterval x
  43. choke : BoundedCReal -> CReal
  44. choke (cReal x ∈ [ lb ▻ ub ]) = cReal f
  45. where
  46. f : Complete Base
  47. f ε = ! y < lb => lb
  48. ! ub < y => ub
  49. ! otherwise y
  50. where
  51. y = x ε
  52. compress : Complete Base -> Complete Base
  53. compress x ε = approxBase (x ε2) ε2
  54. where
  55. ε2 = ε / fromNat 2
  56. mapCR : (Base ==> Base) -> CReal -> CReal
  57. mapCR f (cReal x) = cReal $ mapC f (compress x)
  58. mapCR2 : (Base ==> Base ==> Base) -> CReal -> CReal -> CReal
  59. mapCR2 f (cReal x) (cReal y) = cReal $ mapC2 f (compress x) (compress y)
  60. bindR : (Base ==> Complete Base) -> CReal -> CReal
  61. bindR f (cReal x) = cReal $ bind f (compress x)
  62. approxRange : CReal -> Gauge -> Interval Base
  63. approxRange x ε = [ r - ε ▻ r + ε ]
  64. where
  65. r = approx x ε
  66. -- non-terminates for 0
  67. proveNonZeroFrom : Gauge -> CReal -> Base
  68. proveNonZeroFrom g r =
  69. ! high < fromNat 0 => high
  70. ! fromNat 0 < low => low
  71. ! otherwise proveNonZeroFrom (g / fromNat 2) r
  72. where
  73. i = approxRange r g
  74. low = lowerBound i
  75. high = upperBound i
  76. proveNonZero : CReal -> Base
  77. proveNonZero = proveNonZeroFrom (fromNat 1)
  78. -- Negation
  79. negateCts : Base ==> Base
  80. negateCts = uniformCts id (-_)
  81. realNegate : CReal -> CReal
  82. realNegate = mapCR negateCts
  83. -- Addition
  84. plusBaseCts : Base -> Base ==> Base
  85. plusBaseCts a = uniformCts id (_+_ a)
  86. plusCts : Base ==> Base ==> Base
  87. plusCts = uniformCts id plusBaseCts
  88. realPlus : CReal -> CReal -> CReal
  89. realPlus = mapCR2 plusCts
  90. realTranslate : Base -> CReal -> CReal
  91. realTranslate a = mapCR (plusBaseCts a)
  92. -- Multiplication
  93. multBaseCts : Base -> Base ==> Base
  94. multBaseCts (pos 0 %' _) = constCts (fromNat 0)
  95. multBaseCts a = uniformCts μ (_*_ a)
  96. where
  97. μ = \ε -> ε / ! a !
  98. -- First argument must be ≠ 0
  99. multCts : Base -> Base ==> Base ==> Base
  100. multCts maxy = uniformCts μ multBaseCts
  101. where
  102. μ = \ε -> ε / maxy
  103. realScale : Base -> CReal -> CReal
  104. realScale a = mapCR (multBaseCts a)
  105. bound : Interval Base -> Base
  106. bound [ lb ▻ ub ] = max ub (- lb)
  107. realMultBound : BoundedCReal -> CReal -> CReal
  108. realMultBound (x ∈ i) y = mapCR2 (multCts b) y (choke (x ∈ i))
  109. where
  110. b = bound i
  111. realMult : CReal -> CReal -> CReal
  112. realMult x y = realMultBound (compact x) y
  113. -- Absolute value
  114. absCts : Base ==> Base
  115. absCts = uniformCts id !_!
  116. realAbs : CReal -> CReal
  117. realAbs = mapCR absCts
  118. fromInt : Int -> CReal
  119. fromInt x = inject (Rational.fromInt x)
  120. fromRational : Rational -> CReal
  121. fromRational = inject
  122. -- Reciprocal
  123. recipCts : Base -> Base ==> Base
  124. recipCts nz = uniformCts μ f
  125. where
  126. f : Base -> Base
  127. f a = ! fromNat 0 ≤ nz => recip (max nz a)
  128. ! otherwise recip (min a nz)
  129. μ = \ε -> ε * nz ^ pos 2
  130. realRecipWitness : Base -> CReal -> CReal
  131. realRecipWitness nz = mapCR (recipCts nz)
  132. realRecip : CReal -> CReal
  133. realRecip x = realRecipWitness (proveNonZero x) x
  134. -- Exponentiation
  135. intPowerCts : Gauge -> Int -> Base ==> Base
  136. intPowerCts _ (pos 0) = constCts (fromNat 1)
  137. intPowerCts maxx n = uniformCts μ (flip _^_ n)
  138. where
  139. μ = \ε -> ε / (Rational.fromInt n * maxx ^ (n -i pos 1))
  140. realPowerIntBound : BoundedCReal -> Int -> CReal
  141. realPowerIntBound (x ∈ i) n = mapCR (intPowerCts b n) (choke (x ∈ i))
  142. where
  143. b = bound i
  144. realPowerInt : CReal -> Int -> CReal
  145. realPowerInt = realPowerIntBound ∘ compact
  146. showReal : Nat -> CReal -> String
  147. showReal n x =
  148. ! len ≤' n => sign ++ "0." ++ fromList (replicate (n -' len) '0') ++ s
  149. ! otherwise sign ++ i ++ "." ++ f
  150. where
  151. open Data.Nat using () renaming
  152. ( _^_ to _^'_
  153. ; div to div'; mod to mod'
  154. ; _==_ to _=='_; _≤_ to _≤'_
  155. ; _-_ to _-'_
  156. )
  157. open Data.Show
  158. open Data.List hiding (_++_)
  159. open Data.Integer using () renaming (-_ to -i_)
  160. k = 10 ^' n
  161. m = around $ realScale (fromNat k) x
  162. m' = if m <i pos 0 then -i m else m
  163. s = showInt m'
  164. sign = if m <i pos 0 then "-" else ""
  165. len = length (toList s)
  166. p = splitAt (len -' n) $ toList s
  167. i = fromList $ fst p
  168. f = fromList $ snd p