racket/collects/math/private/distributions/poisson-dist.rkt
Neil Toronto 2d34811ab6 Finished `math/distributions' documentation!
Fixed a few limit cases in some distributions (e.g. (uniform-dist 0 0) didn't
act like a delta distribution, (beta-dist 0 0) and (beta-dist +inf.0 +inf.0)
pretended to be defined by unique limits even though they can't be)

Made integer distributions' pdfs return +nan.0 when given non-integers

Added "private/statistics/counting.rkt", for hashing and binning samples

Added `flvector-sums' (cumulative sums with single rounding error)

Added `flinteger?', `flnan?' and `flrational?', which are faster than their
non-flonum counterparts (at least in Typed Racket; haven't tested untyped)
2012-11-27 13:44:15 -07:00

78 lines
2.9 KiB
Racket

#lang typed/racket/base
(require racket/performance-hint
racket/promise
"../../flonum.rkt"
"../../vector.rkt"
"../unsafe.rkt"
"../functions/incomplete-gamma.rkt"
(prefix-in impl: "impl/poisson-pdf.rkt")
"impl/poisson-random.rkt"
"normal-dist.rkt"
"dist-struct.rkt"
"utils.rkt")
(provide flpoisson-pdf
flpoisson-cdf
flpoisson-inv-cdf
flpoisson-sample
flpoisson-median
Poisson-Dist poisson-dist poisson-dist-mean)
(: flpoisson-pdf (Flonum Flonum Any -> Flonum))
(define (flpoisson-pdf l k log?)
(cond [(or (l . fl< . 0.0) (not (integer? k))) +nan.0]
[log? (impl:flpoisson-log-pdf l k)]
[else (impl:flpoisson-pdf l k)]))
(: flpoisson-cdf (Flonum Flonum Any Any -> Flonum))
(define (flpoisson-cdf l k log? 1-p?)
(cond [(l . fl< . 0.0) +nan.0]
[log? (fllog-gamma-inc (flfloor (fl+ k 1.0)) l (not 1-p?) #t)]
[else (flgamma-inc (flfloor (fl+ k 1.0)) l (not 1-p?) #t)]))
(: flpoisson-inv-cdf (Flonum Flonum Any Any -> Flonum))
(define (flpoisson-inv-cdf l p log? 1-p?)
(cond [(l . fl< . 0.0) +nan.0]
[(not (flprobability? p log?)) +nan.0]
[(flprobability-one? p log? 1-p?) +inf.0]
[(flprobability-zero? p log? 1-p?) 0.0]
[1-p? (flfind-least-integer
(λ: ([k : Flonum]) ((flpoisson-cdf l k log? 1-p?) . fl< . p))
0.0 +inf.0
(flmax 0.0 (flnormal-inv-cdf l (flsqrt l) p log? 1-p?)))]
[else (flfind-least-integer
(λ: ([k : Flonum]) ((flpoisson-cdf l k log? 1-p?) . fl>= . p))
0.0 +inf.0
(flmax 0.0 (flnormal-inv-cdf l (flsqrt l) p log? 1-p?)))]))
(: flpoisson-median (Flonum -> Flonum))
(define (flpoisson-median l)
(cond [(l . fl< . 0.0) +nan.0]
[else
(define k (flfloor (fl+ l #i1/3)))
(cond [(fl= k 0.0) k]
[else (if ((flpoisson-cdf l (- k 1.0) #f #f) . fl< . 0.5) k (- k 1.0))])]))
(define-real-dist: poisson-dist Poisson-Dist
poisson-dist-struct ([mean : Flonum]))
(begin-encourage-inline
(: poisson-dist (case-> (-> Poisson-Dist)
(Real -> Poisson-Dist)))
(define (poisson-dist [l 0.5])
(let ([l (fl l)])
(define pdf (opt-lambda: ([k : Real] [log? : Any #f])
(flpoisson-pdf l (fl k) log?)))
(define cdf (opt-lambda: ([k : Real] [log? : Any #f] [1-p? : Any #f])
(flpoisson-cdf l (fl k) log? 1-p?)))
(define inv-cdf (opt-lambda: ([p : Real] [log? : Any #f] [1-p? : Any #f])
(flpoisson-inv-cdf l (fl p) log? 1-p?)))
(define sample (case-lambda:
[() (unsafe-flvector-ref (flpoisson-sample l 1) 0)]
[([n : Integer]) (flvector->list (flpoisson-sample l n))]))
(poisson-dist-struct pdf sample cdf inv-cdf 0.0 +inf.0 (delay (flpoisson-median l)) l)))
)