PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/pkgs/math-pkgs/math-lib/math/private/flonum/flonum-error.rkt

http://github.com/plt/racket
Racket | 190 lines | 132 code | 29 blank | 29 comment | 15 complexity | 39fd07ef94e43ac0a8ee5ed9a6ea0083 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, BSD-3-Clause, CC-BY-SA-3.0
  1. #lang racket/base
  2. (provide flsplit
  3. fast-mono-fl+/error
  4. fast-mono-fl-/error
  5. fast-fl+/error
  6. fast-fl-/error
  7. fast-fl*/error
  8. fast-flsqr/error
  9. fast-fl//error
  10. fl+/error
  11. fl-/error
  12. fl*/error
  13. flsqr/error
  14. fl//error)
  15. (module untyped-defs racket/base
  16. (require (for-syntax racket/base)
  17. "flonum-functions.rkt")
  18. (provide (all-defined-out))
  19. ;(: flsplit (Flonum -> (Values Flonum Flonum)))
  20. ;; Splits a flonum into a two flonums `hi' and `lo' with 26 bits precision each, such that
  21. ;; |hi| >= |lo| and hi + lo = a. (The extra sign bit accounts for the missing bit.)
  22. ;; This function returns (values +nan.0 +nan.0) for |a| >= 1.3393857490036326e+300.
  23. (define-syntax-rule (flsplit a-expr)
  24. (let ([a a-expr])
  25. (let* ([c (fl* a (fl+ 1.0 (flexpt 2.0 27.0)))]
  26. [x2 (fl- c (fl- c a))])
  27. (values x2 (fl- a x2)))))
  28. ;; =================================================================================================
  29. ;; Fast monotone addition and subtraction
  30. ;(: fast-mono-fl+/error (Flonum Flonum -> (Values Flonum Flonum)))
  31. ;; Returns a+b and its rounding error
  32. ;; Assumes |a| >= |b|
  33. (define-syntax-rule (fast-mono-fl+/error a-expr b-expr)
  34. (let ([a a-expr] [b b-expr])
  35. (let ([x2 (+ a b)])
  36. (values x2 (- b (- x2 a))))))
  37. ;(: fast-mono-fl-/error (Flonum Flonum -> (Values Flonum Flonum)))
  38. ;; Returns a+b and its rounding error
  39. ;; Assumes |a| >= |b|
  40. (define-syntax-rule (fast-mono-fl-/error a-expr b-expr)
  41. (let ([a a-expr] [b b-expr])
  42. (let ([x2 (- a b)])
  43. (values x2 (- (- a x2) b)))))
  44. ;; =================================================================================================
  45. ;; Fast arithmetic that returns rounding error
  46. ;(: fast-fl+/error (Flonum Flonum -> (Values Flonum Flonum)))
  47. ;; Returns a+b and its rounding error
  48. (define-syntax-rule (fast-fl+/error a-expr b-expr)
  49. (let ([a a-expr] [b b-expr])
  50. (let* ([x2 (fl+ a b)]
  51. [v (fl- x2 a)])
  52. (values x2 (fl+ (fl- a (fl- x2 v)) (fl- b v))))))
  53. ;(: fast-fl-/error (Flonum Flonum -> (Values Flonum Flonum)))
  54. ;; Returns a-b and its rounding error
  55. (define-syntax-rule (fast-fl-/error a-expr b-expr)
  56. (let ([a a-expr] [b b-expr])
  57. (let* ([x2 (fl- a b)]
  58. [v (fl- x2 a)])
  59. (values x2 (fl- (fl- a (fl- x2 v)) (fl+ b v))))))
  60. ;(: fast-fl*/error (Flonum Flonum -> (Values Flonum Flonum)))
  61. ;; Returns a*b and its rounding error
  62. (define-syntax-rule (fast-fl*/error a-expr b-expr)
  63. (let ([a a-expr] [b b-expr])
  64. (let*-values ([(x2) (fl* a b)]
  65. [(a2 a1) (flsplit a)]
  66. [(b2 b1) (flsplit b)])
  67. (values x2 (- (fl- (fl- (fl- (fl- x2 (fl* a2 b2))
  68. (fl* a1 b2))
  69. (fl* a2 b1))
  70. (fl* a1 b1)))))))
  71. ;(: fast-flfma/error (Flonum Flonum Flonum -> (Values Flonum Flonum)))
  72. ;; Returns a*b+c and its rounding error
  73. (define-syntax-rule (fast-flfma/error a-expr b-expr c-expr)
  74. (let*-values ([(y2 y1) (fast-fl*/error a-expr b-expr)]
  75. [(h0 h1) (fast-fl+/error c-expr y1)]
  76. [(h3 h2) (fast-fl+/error h0 y2)])
  77. (values h3 (fl+ h2 h1))))
  78. #;; If we had hardware fused multiply-add:
  79. (define-syntax-rule (fast-fl*/error a-expr b-expr)
  80. (let ([a a-expr] [b b-expr])
  81. (let ([x2 (fl* a b)])
  82. (values x2 (flfma a b (- x2))))))
  83. ;(: fast-flsqr/error (Flonum -> (Values Flonum Flonum)))
  84. ;; Returns a*a and its rounding error
  85. (define-syntax-rule (fast-flsqr/error a-expr)
  86. (let ([a a-expr])
  87. (let*-values ([(x2) (fl* a a)]
  88. [(a2 a1) (flsplit a)])
  89. (values x2 (- (fl- (fl- (fl- x2 (fl* a2 a2))
  90. (fl* 2.0 (fl* a2 a1)))
  91. (fl* a1 a1)))))))
  92. ;(: fast-fl//error (Flonum Flonum -> (Values Flonum Flonum)))
  93. ;; Returns a/b and its rounding error
  94. (define-syntax-rule (fast-fl//error a-expr b-expr)
  95. (let ([a a-expr] [b b-expr])
  96. (let*-values ([(x2) (fl/ a b)]
  97. [(w2 w1) (fast-fl*/error x2 b)])
  98. (fast-mono-fl+/error x2 (fl/ (fl- (fl- a w2) w1) b)))))
  99. ) ; module
  100. (require (submod "." untyped-defs))
  101. (module typed-defs typed/racket/base
  102. (require racket/performance-hint
  103. (submod ".." untyped-defs)
  104. "flonum-functions.rkt"
  105. "utils.rkt")
  106. (provide (all-defined-out))
  107. ;; =================================================================================================
  108. ;; Function versions of the above that are well-defined for the largest domain, and return 0.0 as
  109. ;; the second argument whenever the first isn't rational
  110. (begin-encourage-inline
  111. (: fl+/error (Flonum Flonum -> (Values Flonum Flonum)))
  112. (define (fl+/error a b)
  113. (let-values ([(x2 x1) (fast-fl+/error a b)])
  114. (values x2 (if (flrational? x2) x1 0.0))))
  115. (: fl-/error (Flonum Flonum -> (Values Flonum Flonum)))
  116. (define (fl-/error a b)
  117. (let-values ([(x2 x1) (fast-fl-/error a b)])
  118. (values x2 (if (flrational? x2) x1 0.0))))
  119. (: fl*/error (Flonum Flonum -> (Values Flonum Flonum)))
  120. (define (fl*/error a b)
  121. (let ([x2 (fl* a b)])
  122. (values x2 (if (and (flrational? x2) (not (flsubnormal? x2)))
  123. (let*-values ([(da db) (values (near-pow2 a) (near-pow2 b))]
  124. [(d) (fl* da db)]
  125. [(d?) (and (d . fl> . 0.0) (d . fl< . +inf.0))]
  126. [(a2 a1) (flsplit (fl/ a da))]
  127. [(b2 b1) (flsplit (fl/ b db))]
  128. [(x2) (if d? (fl/ x2 d) (fl/ (fl/ x2 da) db))]
  129. [(x1) (- (fl- (fl- (fl- (fl- x2 (fl* a2 b2))
  130. (fl* a1 b2))
  131. (fl* a2 b1))
  132. (fl* a1 b1)))])
  133. (if d? (fl* x1 d) (fl* (fl* x1 da) db)))
  134. 0.0))))
  135. (: flsqr/error (Flonum -> (Values Flonum Flonum)))
  136. (define (flsqr/error a)
  137. (let ([x2 (fl* a a)])
  138. (values x2 (if (and (flrational? x2) (not (flsubnormal? x2)))
  139. (let*-values ([(d) (near-pow2 a)]
  140. [(d^2) (fl* d d)]
  141. [(d^2?) (and (d^2 . fl> . 0.0) (d^2 . fl< . +inf.0))]
  142. [(a2 a1) (flsplit (fl/ a d))]
  143. [(x2) (if d^2? (fl/ x2 d^2) (fl/ (fl/ x2 d) d))]
  144. [(x1) (- (fl- (fl- (fl- x2 (fl* a2 a2))
  145. (fl* 2.0 (fl* a1 a2)))
  146. (fl* a1 a1)))])
  147. (if d^2? (fl* x1 d^2) (fl* (fl* x1 d) d)))
  148. 0.0))))
  149. (: fl//error (Flonum Flonum -> (Values Flonum Flonum)))
  150. (define (fl//error a b)
  151. (let ([x2 (fl/ a b)])
  152. (values x2 (if (and (flrational? x2) (flrational? b))
  153. (let* ([d (near-pow2/div a b)]
  154. [a (fl/ a d)]
  155. [b (fl/ b d)])
  156. (let-values ([(w2 w1) (fl*/error x2 b)])
  157. (fl/ (fl- (fl- a w2) w1) b)))
  158. 0.0))))
  159. ) ; begin-encourage-inline
  160. ) ; module
  161. (require (submod "." typed-defs))