
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)
78 lines
2.9 KiB
Racket
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)))
|
|
|
|
)
|