racket/collects/math/private/bigfloat/bigfloat-hurwitz-zeta.rkt
Neil Toronto 96d1400654 Renamed functions
* bernoulli -> bernoulli-number
 * farey -> farey-sequence
 * fibonacci/mod -> modular-fibonacci
 * order -> unit-group-order
 * orders -> unit-group-orders

Documented `make-fibonacci' and `make-modular-fibonacci'

Reworked text about loading external libraries in docs for `math/bigfloat'

Removed type aliases like Z, Q, Prime (I like them, but TR was printing them
in unexpected places like array return types)
2012-11-27 22:23:42 -07:00

70 lines
2.6 KiB
Racket

#lang typed/racket/base
(require racket/fixnum
"../../flonum.rkt"
"../../base.rkt"
"../number-theory/bernoulli.rkt"
"../number-theory/factorial.rkt"
"bigfloat-struct.rkt")
(provide bfhurwitz-zeta)
(define 0.5b0 (parameterize ([bf-precision 2]) (bf 0.5)))
(: bfhurwitz-zeta-series (Bigfloat Bigfloat -> Bigfloat))
(define (bfhurwitz-zeta-series s q)
(define eps (bf* 0.5b0 epsilon.bf))
(let loop ([i 0] [y 0.bf])
(define dy (bfexpt (bf+ q (bf i)) (bf- s)))
(define new-y (bf+ y dy))
(cond [(or ((bfabs dy) . bf<= . (bf* eps new-y))
(not (bfrational? new-y)))
new-y]
[else
(loop (+ i 1) new-y)])))
(: bfhurwitz-zeta-euler-maclaurin (Bigfloat Bigfloat -> Bigfloat))
(define (bfhurwitz-zeta-euler-maclaurin s q)
(define n (exact-ceiling (+ (* 0.5 (bf-precision) (/ (log 2) (log 10))) 10)))
(: f (Integer -> Bigfloat))
(define (f k) (bfexpt (bf+ (bf k) q) (bf- s)))
(define fn (f n))
(define n+q (bf+ (bf n) q))
(define sqr-n+q (bf* n+q n+q))
(define eps epsilon.bf)
(define y0
(for/fold: ([y0 : Bigfloat (bf* fn (bf+ (bf/ n+q (bf- s 1.bf)) 0.5b0))]
) ([k (in-range n)])
(bf+ y0 (f k))))
(define max-k 100)
(let: loop : Bigfloat ([y : Bigfloat y0]
[numer : Bigfloat s]
[denom : Bigfloat (bf/ fn n+q)]
[k : Nonnegative-Fixnum 0])
(define ck (bf (/ (bernoulli-number (* 2 (fx+ k 1))) (factorial (* 2 (fx+ k 1))))))
(define dy (bf* (bf* numer denom) ck))
(define new-y (bf+ y dy))
(cond [((bfabs dy) . bf<= . (bf* eps (bfabs new-y)))
new-y]
[else
(define k.bf (bf k))
(loop new-y
(bf* (bf* numer (bf+ s (bf+ (bf* 2.bf k.bf) 1.bf)))
(bf+ s (bf+ (bf* 2.bf k.bf) 2.bf)))
(bf/ denom sqr-n+q)
(fx+ k 1))])))
(: bfhurwitz-zeta (Bigfloat Bigfloat -> Bigfloat))
(define (bfhurwitz-zeta s q)
(cond [(s . bf<= . 1.bf) (if (bf= s 1.bf) +inf.bf +nan.bf)]
[(q . bf<= . 0.bf) (if (bf= q 0.bf) +inf.bf +nan.bf)]
[(s . bf> . (bf/ (bflog (bf* 0.5b0 epsilon.bf)) (bf- (bflog q) (bflog1p q))))
;; At this point, only the first term in the series is necessary; the condition can had by
;; solving for s in (q+1)^-s < 0.5 * epsilon.0 * q^-s
(bfexpt q (bf- s))]
[(s . bf> . (bf+ (bf* 2.bf q) (bf 15)))
;; Determined experimentally that the series computes fewer total iterations here
(bfhurwitz-zeta-series s q)]
[else
(bfhurwitz-zeta-euler-maclaurin s q)]))