racket/collects/math/private/flonum/expansion/expansion-base.rkt
Neil Toronto 1e52736089 Documentation style changes
Fixes after merge weirdness from pull request (specifically, removed `bfrandom' from "mpfr.rkt" again)
Removed dependence of math/flonum on math/bigfloat (better build parallelization)
Changed `divides?' to return #f when its first argument is 0
Made return type of `quadratic-character' more precise
Made argument types more permissive:
 * second argument to `solve-chinese'
 * second argument to `next-primes'
 * second argument to `prev-primes'
2012-11-17 21:02:37 -09:00

175 lines
6.6 KiB
Racket
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#lang typed/racket/base
#|
Arithmetic based on:
Jonathan Richard Shewchuk
Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates
Discrete & Computational Geometry 18(3):305363, October 1997
|#
(require "../flonum-functions.rkt"
"../flonum-syntax.rkt")
(provide fl2 fl2->real
fl2+ fl2- fl2*split-fl fl2* fl2/
flsqrt/error fl2sqrt)
;; ===================================================================================================
;; Conversion
(: fl2 (case-> (Real -> (Values Flonum Flonum))
(Flonum Flonum -> (Values Flonum Flonum))))
(define fl2
(case-lambda
[(x)
(cond [(flonum? x) (values x 0.0)]
[(single-flonum? x) (values (fl x) 0.0)]
[else (let ([x2 (fl x)])
(values x2 (fl (- x (inexact->exact x2)))))])]
[(x y)
(fast-fl+/error x y)]))
(: fl2->real (Flonum Flonum -> Real))
(define (fl2->real x2 x1)
(cond [(and (x1 . fl> . -inf.0) (x1 . fl< . +inf.0)
(x2 . fl> . -inf.0) (x2 . fl< . +inf.0))
(+ (inexact->exact x2) (inexact->exact x1))]
[else (fl+ x1 x2)]))
(: fl3->fl2 (Flonum Flonum Flonum -> (Values Flonum Flonum)))
(define (fl3->fl2 e3 e2 e1)
(values e3 (fl+ e2 e1)))
(: fl4->fl2 (Flonum Flonum Flonum Flonum -> (Values Flonum Flonum)))
(define (fl4->fl2 e4 e3 e2 e1)
(values e4 (fl+ e3 (fl+ e2 e1))))
;; ===================================================================================================
;; Addition and subtraction
(: raw-fl2+fl (Flonum Flonum Flonum -> (Values Flonum Flonum Flonum)))
(define (raw-fl2+fl e2 e1 b)
(let*-values ([(Q h1) (fast-fl+/error b e1)]
[(h3 h2) (fast-fl+/error Q e2)])
(values h3 h2 h1)))
(: raw-fl2+ (Flonum Flonum Flonum Flonum -> (Values Flonum Flonum Flonum Flonum)))
(define (raw-fl2+ e2 e1 f2 f1)
(let*-values ([(h3 h2 h1) (raw-fl2+fl e2 e1 f1)]
[(h4 h3 h2) (raw-fl2+fl h3 h2 f2)])
(values h4 h3 h2 h1)))
(: fl2+ (case-> (Flonum Flonum Flonum -> (Values Flonum Flonum))
(Flonum Flonum Flonum Flonum -> (Values Flonum Flonum))))
(define fl2+
(case-lambda
[(e2 e1 b)
(let-values ([(h3 h2 h1) (raw-fl2+fl e2 e1 b)])
(fl3->fl2 h3 h2 h1))]
[(x2 x1 y2 y1)
(let*-values ([(e4 e3 e2 e1) (raw-fl2+ x2 x1 y2 y1)])
(fl4->fl2 e4 e3 e2 e1))]))
(: fl2- (case-> (Flonum Flonum Flonum -> (Values Flonum Flonum))
(Flonum Flonum Flonum Flonum -> (Values Flonum Flonum))))
(define fl2-
(case-lambda
[(e2 e1 b)
(let-values ([(h3 h2 h1) (raw-fl2+fl e2 e1 (- b))])
(fl3->fl2 h3 h2 h1))]
[(x2 x1 y2 y1)
(let*-values ([(e4 e3 e2 e1) (raw-fl2+ x2 x1 (- y2) (- y1))])
(fl4->fl2 e4 e3 e2 e1))]))
;; ===================================================================================================
;; Multiplication and division
(: raw-split-fl2*split-fl (Flonum Flonum Flonum Flonum Flonum Flonum
-> (Values Flonum Flonum Flonum Flonum)))
(define (raw-split-fl2*split-fl e2-hi e2-lo e1-hi e1-lo b-hi b-lo)
(let*-values ([(b) (fl+ b-lo b-hi)]
[(Q1) (fl* (fl+ e1-lo e1-hi) b)]
[(h1) (- (- Q1
(fl* e1-hi b-hi)
(fl* e1-lo b-hi)
(fl* e1-hi b-lo)
(fl* e1-lo b-lo)))]
[(T) (fl* (fl+ e2-lo e2-hi) b)]
[(t) (- (- T
(fl* e2-hi b-hi)
(fl* e2-lo b-hi)
(fl* e2-hi b-lo)
(fl* e2-lo b-lo)))]
[(Q2 h2) (fast-fl+/error Q1 t)]
[(h4 h3) (fast-mono-fl+/error T Q2)])
(values h4 h3 h2 h1)))
(: split-fl2*split-fl (Flonum Flonum Flonum Flonum Flonum Flonum -> (Values Flonum Flonum)))
(define (split-fl2*split-fl e2-hi e2-lo e1-hi e1-lo b-hi b-lo)
(let-values ([(h4 h3 h2 h1) (raw-split-fl2*split-fl e2-hi e2-lo e1-hi e1-lo b-hi b-lo)])
(fl4->fl2 h4 h3 h2 h1)))
(: fl2*split-fl (Flonum Flonum Flonum Flonum -> (Values Flonum Flonum)))
(define (fl2*split-fl e2 e1 b-hi b-lo)
(let*-values ([(e2-hi e2-lo) (flsplit e2)]
[(e1-hi e1-lo) (flsplit e1)]
[(h4 h3 h2 h1) (raw-split-fl2*split-fl e2-hi e2-lo e1-hi e1-lo b-hi b-lo)])
(fl4->fl2 h4 h3 h2 h1)))
(: fl2* (case-> (Flonum Flonum Flonum -> (Values Flonum Flonum))
(Flonum Flonum Flonum Flonum -> (Values Flonum Flonum))))
(define fl2*
(case-lambda
[(e2 e1 b)
(let-values ([(b-hi b-lo) (flsplit b)])
(fl2*split-fl e2 e1 b-hi b-lo))]
[(x2 x1 y2 y1)
(let*-values ([(x2-hi x2-lo) (flsplit x2)]
[(x1-hi x1-lo) (flsplit x1)]
[(y2-hi y2-lo) (flsplit y2)]
[(y1-hi y1-lo) (flsplit y1)]
[(a2 a1) (split-fl2*split-fl x2-hi x2-lo x1-hi x1-lo y1-hi y1-lo)]
[(b2 b1) (split-fl2*split-fl x2-hi x2-lo x1-hi x1-lo y2-hi y2-lo)])
(fl2+ a2 a1 b2 b1))]))
(: fl2/ (case-> (Flonum Flonum Flonum -> (Values Flonum Flonum))
(Flonum Flonum Flonum Flonum -> (Values Flonum Flonum))))
(define fl2/
(case-lambda
[(x2 x1 y)
(let*-values ([(a2 a1) (fast-fl//error x1 y)]
[(b2 b1) (fast-fl//error x2 y)])
(fl2+ a2 a1 b2 b1))]
[(x2 x1 y2 y1)
;; Compute three "digits" (flonums) of two-flonum long division; the third ensures the result is
;; correctly rounded
(let*-values ([(z2) (fl/ x2 y2)]
[(w2 w1) (fl2* y2 y1 z2)]
[(x2 x1) (fl2- x2 x1 w2 w1)]
[(z1) (fl/ x2 y2)]
[(w2 w1) (fl2* y2 y1 z1)]
[(x2 x1) (fl2- x2 x1 w2 w1)])
(fl3->fl2 z2 z1 (/ x2 y2)))]))
;; ===================================================================================================
;; Square roots
(: flsqrt/error (Flonum -> (Values Flonum Flonum)))
;; One-flonum estimate followed by one Newton's method iteration
;; This could be a little faster if `y' were split only once
(define (flsqrt/error x)
(let*-values ([(y) (flsqrt x)]
[(z2 z1) (fast-flsqr/error y)]
[(dy2 dy1) (fl2+ (- z2) (- z1) x)]
[(dy2 dy1) (fl2/ dy2 dy1 y)])
(fl2+ (* 0.5 dy2) (* 0.5 dy1) y)))
(: fl2sqrt (Flonum Flonum -> (Values Flonum Flonum)))
(define (fl2sqrt x2 x1)
(let*-values ([(y) (flsqrt (fl+ x1 x2))]
[(z2 z1) (fast-flsqr/error y)]
[(dy2 dy1) (fl2- x2 x1 z2 z1)]
[(dy2 dy1) (fl2/ dy2 dy1 y)])
(fl2+ (* 0.5 dy2) (* 0.5 dy1) y)))