Floats.agda 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. module _ where
  2. open import Common.IO
  3. renaming (then to _>>_
  4. )
  5. open import Agda.Builtin.Unit
  6. open import Agda.Builtin.Bool
  7. open import Agda.Builtin.Equality using (_≡_; refl)
  8. open import Agda.Builtin.Float
  9. renaming ( primFloatEquality to _≡ᵇ_
  10. ; primFloatInequality to _≤ᵇ_
  11. ; primFloatLess to _<ᵇ_
  12. ; primFloatPlus to infixl 6 _+_
  13. ; primFloatMinus to infixl 6 _-_
  14. ; primFloatTimes to infixl 7 _*_
  15. ; primFloatDiv to infixl 7 _÷_
  16. ; primFloatPow to infix 8 _**_
  17. ; primFloatNegate to infix 9 -_
  18. ; primFloatSqrt to sqrt
  19. ; primFloatExp to e^_
  20. ; primFloatLog to log
  21. ; primFloatSin to sin
  22. ; primFloatCos to cos
  23. ; primFloatTan to tan
  24. ; primFloatASin to asin
  25. ; primFloatACos to acos
  26. ; primFloatATan to atan
  27. ; primFloatATan2 to atan2
  28. ; primFloatSinh to sinh
  29. ; primFloatCosh to cosh
  30. ; primFloatTanh to tanh
  31. ; primFloatASinh to asinh
  32. ; primFloatACosh to acosh
  33. ; primFloatATanh to atanh
  34. ; primFloatRound to round
  35. ; primFloatFloor to floor
  36. ; primFloatCeiling to ceiling
  37. ; primShowFloat to showF
  38. ; primFloatToWord64 to toWord
  39. ; primFloatToRatio to toRatio
  40. ; primRatioToFloat to fromRatio
  41. ; primFloatDecode to decode
  42. ; primFloatEncode to encode
  43. ; primFloatIsInfinite to isInfinite
  44. ; primFloatIsNaN to isNaN
  45. ; primFloatIsNegativeZero to isNegativeZero
  46. ; primFloatIsSafeInteger to isSafeInteger
  47. )
  48. open import Agda.Builtin.Int
  49. using (Int; pos; negsuc)
  50. renaming ( primShowInteger to showI
  51. )
  52. open import Agda.Builtin.Nat
  53. using (Nat)
  54. renaming ( _==_ to _==N_
  55. )
  56. open import Agda.Builtin.Maybe
  57. open import Agda.Builtin.Sigma
  58. open import Agda.Builtin.String
  59. using (String)
  60. renaming ( primStringEquality to _==S_
  61. ; primShowNat to showN
  62. ; primStringAppend to _++_
  63. )
  64. open import Agda.Builtin.Word
  65. using (Word64)
  66. renaming ( primWord64ToNat to toℕ
  67. )
  68. -- Prelude
  69. data ⊥ : Set where
  70. _≢_ : {A : Set} (P Q : A) → Set
  71. P ≢ Q = P ≡ Q → ⊥
  72. NaN : Float
  73. NaN = 0.0 ÷ 0.0
  74. -NaN : Float
  75. -NaN = - NaN
  76. Infinity : Float
  77. Infinity = 1.0 ÷ 0.0
  78. -Infinity : Float
  79. -Infinity = - Infinity
  80. MaxFloat : Float
  81. MaxFloat = 1.7976931348623157e308
  82. MinFloat : Float
  83. MinFloat = 2.2250738585072014e-308
  84. MaxSafeIntF : Float
  85. MaxSafeIntF = 9007199254740991.0
  86. MaxSafeIntZ : Int
  87. MaxSafeIntZ = pos 9007199254740991
  88. -- * Tests
  89. showB : Bool → String
  90. showB false = "false"
  91. showB true = "true"
  92. maybeShow : {A : Set} (show : A → String) → Maybe A → String
  93. maybeShow show (just x) = "(just (" ++ (show x ++ "))")
  94. maybeShow show nothing = "nothing"
  95. pairShow : {A B : Set} (showA : A → String) (showB : B → String) → Σ A (λ _ → B) → String
  96. pairShow showA showB (x , y) = "(" ++ (showA x ++ (" , " ++ (showB y ++ ")")))
  97. showR = pairShow showI showI
  98. newline : IO ⊤
  99. newline = putStr "\n"
  100. T : Bool → Set
  101. T false = ⊥
  102. T true = ⊤
  103. _==F_ : Float → Float → Bool
  104. x ==F y = toℕ (toWord x) ==N toℕ (toWord x)
  105. _==B_ : Bool → Bool → Bool
  106. false ==B false = true
  107. false ==B true = false
  108. true ==B false = false
  109. true ==B true = true
  110. _==I_ : Int → Int → Bool
  111. pos n ==I pos m = n ==N m
  112. pos n ==I negsuc m = false
  113. negsuc n ==I pos m = false
  114. negsuc n ==I negsuc m = n ==N m
  115. maybeEq : {A : Set} (eq : A → A → Bool) → Maybe A → Maybe A → Bool
  116. maybeEq eq (just x) (just y) = eq x y
  117. maybeEq eq (just x) nothing = false
  118. maybeEq eq nothing (just y) = false
  119. maybeEq eq nothing nothing = true
  120. pairEq : {A B : Set} (eqA : A → A → Bool) (eqB : B → B → Bool) → Σ A (λ _ → B) → Σ A (λ _ → B) → Bool
  121. pairEq eqA eqB (x , y) (z , w) = eqA x z && eqB y w
  122. where
  123. _&&_ : Bool → Bool → Bool
  124. true && true = true
  125. x && y = false
  126. _==R_ = pairEq _==I_ _==I_
  127. check : {A : Set} (show : A → String) (eq : A → A → Bool) (str : String) (exp act : A) {p : T (eq act exp)} → IO ⊤
  128. check show eq str exp act = do
  129. putStr str; putStr " = "; putStr (show exp); putStr " = "; putStr (show act); newline
  130. checkB = check showB _==B_
  131. checkS = check (λ x → x) _==S_
  132. checkN = check showN _==N_
  133. checkI = check showI _==I_
  134. checkMI = check (maybeShow showI) (maybeEq _==I_)
  135. checkR = check showR _==R_
  136. checkF = check showF _==F_
  137. checkMR = check (maybeShow showR) (maybeEq _==R_)
  138. checkMF = check (maybeShow showF) (maybeEq _==F_)
  139. -- ** Relations
  140. main : IO ⊤
  141. main = do
  142. -- ** Relations
  143. checkB " NaN ≡ᵇ NaN " false ( NaN ≡ᵇ NaN )
  144. checkB "-NaN ≡ᵇ NaN " false (-NaN ≡ᵇ NaN )
  145. checkB " NaN ≡ᵇ -NaN " false ( NaN ≡ᵇ -NaN )
  146. checkB "-NaN ≡ᵇ -NaN " false (-NaN ≡ᵇ -NaN )
  147. checkB " Infinity ≡ᵇ Infinity" true ( Infinity ≡ᵇ Infinity)
  148. checkB "-Infinity ≡ᵇ Infinity" false (-Infinity ≡ᵇ Infinity)
  149. checkB " Infinity ≡ᵇ -Infinity" false ( Infinity ≡ᵇ -Infinity)
  150. checkB "-Infinity ≡ᵇ -Infinity" true (-Infinity ≡ᵇ -Infinity)
  151. checkB " MaxFloat ≡ᵇ MaxFloat" true ( MaxFloat ≡ᵇ MaxFloat)
  152. checkB " MinFloat ≡ᵇ MinFloat" true ( MinFloat ≡ᵇ MinFloat)
  153. checkB " 1.0 ≡ᵇ 1.5 " false ( 1.0 ≡ᵇ 1.5 )
  154. checkB " 1.0 ≡ᵇ 1.0 " true ( 1.0 ≡ᵇ 1.0 )
  155. checkB " 1.5 ≡ᵇ 1.5 " true ( 1.5 ≡ᵇ 1.5 )
  156. checkB " NaN ≤ᵇ NaN " false ( NaN ≤ᵇ NaN )
  157. checkB "-NaN ≤ᵇ NaN " false (-NaN ≤ᵇ NaN )
  158. checkB " NaN ≤ᵇ -NaN " false ( NaN ≤ᵇ -NaN )
  159. checkB "-NaN ≤ᵇ -NaN " false (-NaN ≤ᵇ -NaN )
  160. checkB " NaN ≤ᵇ 5.0 " false ( NaN ≤ᵇ 5.0 )
  161. checkB "-NaN ≤ᵇ 5.0 " false (-NaN ≤ᵇ 5.0 )
  162. checkB " 5.0 ≤ᵇ -NaN " false ( 5.0 ≤ᵇ -NaN )
  163. checkB "-5.0 ≤ᵇ -NaN " false (-5.0 ≤ᵇ -NaN )
  164. checkB " NaN ≤ᵇ Infinity" false ( NaN ≤ᵇ Infinity)
  165. checkB "-NaN ≤ᵇ Infinity" false (-NaN ≤ᵇ Infinity)
  166. checkB " Infinity ≤ᵇ -NaN " false ( Infinity ≤ᵇ -NaN )
  167. checkB "-Infinity ≤ᵇ -NaN " false (-Infinity ≤ᵇ -NaN )
  168. checkB " Infinity ≤ᵇ Infinity" true ( Infinity ≤ᵇ Infinity)
  169. checkB "-Infinity ≤ᵇ Infinity" true (-Infinity ≤ᵇ Infinity)
  170. checkB " Infinity ≤ᵇ -Infinity" false ( Infinity ≤ᵇ -Infinity)
  171. checkB "-Infinity ≤ᵇ -Infinity" true (-Infinity ≤ᵇ -Infinity)
  172. checkB " MaxFloat ≤ᵇ MaxFloat" true ( MaxFloat ≤ᵇ MaxFloat)
  173. checkB " MinFloat ≤ᵇ MinFloat" true ( MinFloat ≤ᵇ MinFloat)
  174. checkB " 1.0 ≤ᵇ 1.5 " true ( 1.0 ≤ᵇ 1.5 )
  175. checkB " 1.0 ≤ᵇ 1.0 " true ( 1.0 ≤ᵇ 1.0 )
  176. checkB " 1.5 ≤ᵇ 1.5 " true ( 1.5 ≤ᵇ 1.5 )
  177. checkB " NaN <ᵇ NaN " false ( NaN <ᵇ NaN )
  178. checkB "-NaN <ᵇ NaN " false (-NaN <ᵇ NaN )
  179. checkB " NaN <ᵇ -NaN " false ( NaN <ᵇ -NaN )
  180. checkB "-NaN <ᵇ -NaN " false (-NaN <ᵇ -NaN )
  181. checkB " NaN <ᵇ 5.0 " false ( NaN <ᵇ 5.0 )
  182. checkB "-NaN <ᵇ 5.0 " false (-NaN <ᵇ 5.0 )
  183. checkB " 5.0 <ᵇ -NaN " false ( 5.0 <ᵇ -NaN )
  184. checkB "-5.0 <ᵇ -NaN " false (-5.0 <ᵇ -NaN )
  185. checkB " NaN <ᵇ Infinity" false ( NaN <ᵇ Infinity)
  186. checkB "-NaN <ᵇ Infinity" false (-NaN <ᵇ Infinity)
  187. checkB " Infinity <ᵇ -NaN " false ( Infinity <ᵇ -NaN )
  188. checkB "-Infinity <ᵇ -NaN " false (-Infinity <ᵇ -NaN )
  189. checkB " Infinity <ᵇ Infinity" false ( Infinity <ᵇ Infinity)
  190. checkB "-Infinity <ᵇ Infinity" true (-Infinity <ᵇ Infinity)
  191. checkB " Infinity <ᵇ -Infinity" false ( Infinity <ᵇ -Infinity)
  192. checkB "-Infinity <ᵇ -Infinity" false (-Infinity <ᵇ -Infinity)
  193. checkB " MaxFloat <ᵇ MaxFloat" false ( MaxFloat <ᵇ MaxFloat)
  194. checkB " MinFloat <ᵇ MinFloat" false ( MinFloat <ᵇ MinFloat)
  195. checkB " 1.0 <ᵇ 1.5 " true ( 1.0 <ᵇ 1.5 )
  196. checkB " 1.0 <ᵇ 1.0 " false ( 1.0 <ᵇ 1.0 )
  197. checkB " 1.5 <ᵇ 1.5 " false ( 1.5 <ᵇ 1.5 )
  198. checkB "isNaN NaN " true (isNaN NaN )
  199. checkB "isNaN -NaN " true (isNaN -NaN )
  200. checkB "isNaN Infinity " false (isNaN Infinity )
  201. checkB "isNaN -Infinity " false (isNaN -Infinity )
  202. checkB "isNaN 0.0 " false (isNaN 0.0 )
  203. checkB "isNaN -0.0 " false (isNaN -0.0 )
  204. checkB "isNaN 1.0 " false (isNaN 1.0 )
  205. checkB "isNaN 1.5 " false (isNaN 1.5 )
  206. checkB "isInfinite NaN " false (isInfinite NaN )
  207. checkB "isInfinite -NaN " false (isInfinite -NaN )
  208. checkB "isInfinite Infinity " true (isInfinite Infinity )
  209. checkB "isInfinite -Infinity " true (isInfinite -Infinity )
  210. checkB "isInfinite 0.0 " false (isInfinite 0.0 )
  211. checkB "isInfinite -0.0 " false (isInfinite -0.0 )
  212. checkB "isInfinite 1.0 " false (isInfinite 1.0 )
  213. checkB "isInfinite 1.5 " false (isInfinite 1.5 )
  214. -- Depends on optimisation settings:
  215. --
  216. -- - with -O0 the test succeeds
  217. -- - with -O the test fails
  218. --
  219. -- checkB "isInfinite ((MaxFloat * MaxFloat) ÷ MaxFloat)"
  220. -- true
  221. -- (isInfinite ((MaxFloat * MaxFloat) ÷ MaxFloat))
  222. checkB "isNegativeZero NaN " false (isNegativeZero NaN )
  223. checkB "isNegativeZero -NaN " false (isNegativeZero -NaN )
  224. checkB "isNegativeZero Infinity " false (isNegativeZero Infinity )
  225. checkB "isNegativeZero -Infinity " false (isNegativeZero -Infinity )
  226. checkB "isNegativeZero 0.0 " false (isNegativeZero 0.0 )
  227. checkB "isNegativeZero -0.0 " true (isNegativeZero -0.0 )
  228. checkB "isNegativeZero 1.0 " false (isNegativeZero 1.0 )
  229. checkB "isNegativeZero 1.5 " false (isNegativeZero 1.5 )
  230. checkB "isSafeInteger 1.0 " true (isSafeInteger 1.0 )
  231. checkB "isSafeInteger 1.5 " false (isSafeInteger 1.5 )
  232. checkB "isSafeInteger MaxFloat " false (isSafeInteger MaxFloat )
  233. checkB "isSafeInteger MinFloat " false (isSafeInteger MinFloat )
  234. checkB "isSafeInteger MaxSafeIntF " true (isSafeInteger MaxSafeIntF )
  235. -- ** Conversions
  236. checkS "show NaN " "NaN" (showF NaN )
  237. checkS "show -NaN " "NaN" (showF -NaN )
  238. checkS "show 0.0 " "0.0" (showF 0.0 )
  239. checkS "show -0.0 " "-0.0" (showF -0.0 )
  240. checkS "show Infinity" "Infinity" (showF Infinity)
  241. checkS "show -Infinity" "-Infinity" (showF -Infinity)
  242. checkS "show 1.0 " "1.0" (showF 1.0 )
  243. checkS "show 1.5 " "1.5" (showF 1.5 )
  244. -- Breaks the JavaScript backend, on account of it being... too big:
  245. --
  246. -- checkN "toℕ (toWord 1.0) " 4607182418800017408 (toℕ (toWord 1.0) )
  247. -- checkN "toℕ (toWord 1.5) " 4609434218613702656 (toℕ (toWord 1.5) )
  248. -- checkN "toℕ (toWord 0.0) " 0 (toℕ (toWord 0.0) )
  249. -- checkN "toℕ (toWord -0.0) " 9223372036854775808 (toℕ (toWord -0.0) )
  250. -- checkN "toℕ (toWord NaN) " 18444492273895866368 (toℕ (toWord NaN) )
  251. -- checkN "toℕ (toWord -NaN) " 18444492273895866368 (toℕ (toWord -NaN) )
  252. -- checkN "toℕ (toWord Infinity) " 9218868437227405312 (toℕ (toWord Infinity) )
  253. -- checkN "toℕ (toWord -Infinity)" 18442240474082181120 (toℕ (toWord -Infinity))
  254. checkMI "round 1.0 " (just (pos 1)) (round 1.0 )
  255. checkMI "round 1.5 " (just (pos 2)) (round 1.5 )
  256. checkMI "round NaN " (nothing ) (round NaN )
  257. checkMI "round -NaN " (nothing ) (round -NaN )
  258. checkMI "round Infinity " (nothing ) (round Infinity )
  259. checkMI "round -Infinity" (nothing ) (round -Infinity)
  260. checkMI "round MinFloat " (just (pos 0)) (round MinFloat )
  261. --
  262. -- Breaks the JavaScript backend, on account of it being... too big:
  263. --
  264. -- checkMI "round MaxFloat " (just (pos 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368)) (round MaxFloat )
  265. checkMI "floor 1.0 " (just (pos 1)) (floor 1.0 )
  266. checkMI "floor 1.5 " (just (pos 1)) (floor 1.5 )
  267. checkMI "floor NaN " (nothing ) (floor NaN )
  268. checkMI "floor -NaN " (nothing ) (floor -NaN )
  269. checkMI "floor Infinity " (nothing ) (floor Infinity )
  270. checkMI "floor -Infinity" (nothing ) (floor -Infinity)
  271. checkMI "floor MinFloat " (just (pos 0)) (floor MinFloat )
  272. --
  273. -- Breaks the JavaScript backend, on account of it being... too big:
  274. --
  275. -- checkMI "floor MaxFloat " (just (pos 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368)) (floor MaxFloat )
  276. checkMI "ceiling 1.0 " (just (pos 1)) (ceiling 1.0 )
  277. checkMI "ceiling 1.5 " (just (pos 2)) (ceiling 1.5 )
  278. checkMI "ceiling NaN " (nothing ) (ceiling NaN )
  279. checkMI "ceiling -NaN " (nothing ) (ceiling -NaN )
  280. checkMI "ceiling Infinity " (nothing ) (ceiling Infinity )
  281. checkMI "ceiling -Infinity" (nothing ) (ceiling -Infinity)
  282. checkMI "ceiling MinFloat " (just (pos 1)) (ceiling MinFloat )
  283. --
  284. -- Breaks the JavaScript backend, on account of it being... too big:
  285. --
  286. -- checkMI "ceiling MaxFloat " (just (pos 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368)) (ceiling MaxFloat )
  287. checkMR "decode NaN " (nothing ) (decode NaN )
  288. checkMR "decode Infinity" (nothing ) (decode Infinity)
  289. checkMR "decode -Infinity" (nothing ) (decode -Infinity)
  290. checkMR "decode 1.0 " (just (pos 1 , pos 0)) (decode 1.0 )
  291. checkMR "decode 1.5 " (just (pos 3 , negsuc 0)) (decode 1.5 )
  292. checkMR "decode MinFloat" (just (pos 1 , negsuc 1021)) (decode MinFloat)
  293. --
  294. -- Breaks the JavaScript backend, on account of it being... too big:
  295. --
  296. -- checkMR "decode MaxFloat" (just (MaxSafeIntZ , pos 971)) (decode MaxFloat)
  297. checkMF "encode (pos 1) (pos 0)" (just 1.0 ) (encode (pos 1) (pos 0))
  298. checkMF "encode (pos 3) (negsuc 0)" (just 1.5 ) (encode (pos 3) (negsuc 0))
  299. --
  300. -- Breaks the JavaScript backend, on account of it being... too big:
  301. --
  302. -- checkMF "encode MaxSafeIntZ (pos 0)" (just MaxSafeIntF) (encode MaxSafeIntZ (pos 0))
  303. -- checkMF "encode MaxSafeIntZ (pos 971)" (just MaxFloat ) (encode MaxSafeIntZ (pos 971))
  304. -- checkMF "encode MaxSafeIntZ (pos 972)" (nothing ) (encode MaxSafeIntZ (pos 972))
  305. -- checkMF "encode (pos 1) (negsuc 1021)" (just MinFloat ) (encode (pos 1) (negsuc 1021))
  306. -- checkMF "encode MaxSafeIntZ (negsuc 1075)" (nothing ) (encode MaxSafeIntZ (negsuc 1075))
  307. checkR "toRatio NaN " (pos 0 , pos 0) (toRatio NaN )
  308. checkR "toRatio Infinity" (pos 1 , pos 0) (toRatio Infinity)
  309. checkR "toRatio -Infinity" (negsuc 0 , pos 0) (toRatio -Infinity)
  310. checkR "toRatio 1.0 " (pos 1 , pos 1) (toRatio 1.0 )
  311. checkR "toRatio 1.5 " (pos 3 , pos 2) (toRatio 1.5 )
  312. checkF "fromRatio (pos 0) (pos 0)" ( NaN ) (fromRatio (pos 0) (pos 0))
  313. checkF "fromRatio (pos 1) (pos 0)" ( Infinity) (fromRatio (pos 1) (pos 0))
  314. checkF "fromRatio (negsuc 0) (pos 0)" (-Infinity) (fromRatio (negsuc 0) (pos 0))
  315. checkF "fromRatio (pos 1) (pos 1)" ( 1.0 ) (fromRatio (pos 1) (pos 1))
  316. checkF "fromRatio (pos 3) (pos 2)" ( 1.5 ) (fromRatio (pos 3) (pos 2))
  317. checkF "e^ 1.0 " 2.718281828459045 (e^ 1.0 )
  318. checkF "sin (asin 0.6) " 0.6 (sin (asin 0.6) )
  319. checkF "cos (acos 0.6) " 0.6 (cos (acos 0.6) )
  320. checkF "tan (atan 0.4) " 0.4 (tan (atan 0.4) )
  321. checkF "tan (atan2 0.4 1.0)" 0.4 (tan (atan2 0.4 1.0))