racket/collects/math/private/number-theory/partitions.rkt
Neil Toronto 60dd8d065f Fixes for errors Pierpaolo Bernardi found by reviewing the docs; also,
renamed `partition-count' to `partitions' to be consistent with
`permutations', and gave better examples in `multinomial' docs

 * (flulp-error +inf.0 +nan.0) was returning +nan.0 instead of +inf.0

 * Type of `multinomial' didn't match its docs or `flmultinomial'

 * Reworded docs for `diagonal-array'

 * Reworked/reordered quite a few things in docs for `math/bigfloat'

 * Fixed first identity given in `gamma-inc' docs

 * Fixed descrption for `+max.0', etc.
2012-12-17 11:40:37 -07:00

41 lines
1.3 KiB
Racket

#lang typed/racket/base
(require racket/flonum
"../../base.rkt"
"../vector/vector.rkt"
"types.rkt")
(provide partitions)
(define num-global-ps 200)
(: global-ps (Vectorof Natural))
(define global-ps (make-vector num-global-ps 0))
(vector-set! global-ps 0 1)
(: partitions : Integer -> Natural)
; http://en.wikipedia.org/wiki/Partition_(number_theory)
(define (partitions n)
(define: local-ps : (Vectorof Natural)
(make-vector (max 0 (- (+ n 1) num-global-ps)) 0))
(: ps-ref! (Integer (-> Natural) -> Natural))
(define (ps-ref! n thnk)
(cond [(n . < . num-global-ps)
(vector-ref! global-ps n thnk exact-zero?)]
[else
(vector-ref! local-ps (- n num-global-ps) thnk exact-zero?)]))
(let: loop : Natural ([n : Integer n])
(cond [(< n 0) 0]
[(= n 0) 1]
[else
(ps-ref!
n (λ ()
(define m (/ (+ 1.0 (flsqrt (+ 1.0 (* 24.0 n)))) 6.0))
(assert
(for/fold: ([sum : Integer 0]) ([k (in-range 1 (add1 (exact-floor m)))])
(+ sum (* (if (odd? k) 1 -1)
(+ (loop (- n (quotient (* k (- (* 3 k) 1)) 2)))
(loop (- n (quotient (* k (+ (* 3 k) 1)) 2)))))))
natural?)))])))