Finished array documentation!

Cleaned up other docs in preparation for alpha-testing announcement

Created `math/utils' module for stuff that doesn't go anywhere else (e.g.
FFT scaling convention, max-math-threads parameters)

Reduced the number of macros that expand to applications of `array-map'

Added `flvector-sum', defined `flsum' in terms of it

Reduced the number of pointwise `flvector', `flarray' and `fcarray' operations

Reworked `inline-build-flvector' and `inline-flvector-map' to be faster and
expand to less code in both typed and untyped Racket

Redefined conversions like `list->flvector' in terms of for loops (can do
it now that TR has working `for/flvector:', etc.)
This commit is contained in:
Neil Toronto 2012-11-29 13:34:09 -07:00
parent 6009eed8d2
commit 5a43f2c6bc
26 changed files with 699 additions and 663 deletions

View File

@ -7,7 +7,6 @@
"private/flonum/flonum-search.rkt" "private/flonum/flonum-search.rkt"
"private/flonum/flonum-exp.rkt" "private/flonum/flonum-exp.rkt"
"private/flonum/flonum-log.rkt" "private/flonum/flonum-log.rkt"
"private/flonum/flonum-sum.rkt"
"private/flonum/flonum-more-functions.rkt" "private/flonum/flonum-more-functions.rkt"
"private/flonum/flonum-factorial.rkt" "private/flonum/flonum-factorial.rkt"
"private/flonum/flonum-log1pmx.rkt" "private/flonum/flonum-log1pmx.rkt"
@ -25,7 +24,6 @@
"private/flonum/flonum-search.rkt" "private/flonum/flonum-search.rkt"
"private/flonum/flonum-exp.rkt" "private/flonum/flonum-exp.rkt"
"private/flonum/flonum-log.rkt" "private/flonum/flonum-log.rkt"
"private/flonum/flonum-sum.rkt"
"private/flonum/flonum-more-functions.rkt" "private/flonum/flonum-more-functions.rkt"
"private/flonum/flonum-factorial.rkt" "private/flonum/flonum-factorial.rkt"
"private/flonum/flonum-log1pmx.rkt" "private/flonum/flonum-log1pmx.rkt"

View File

@ -10,7 +10,7 @@
"vector.rkt" "vector.rkt"
"array.rkt" "array.rkt"
;"matrix.rkt" ;"matrix.rkt"
"parameters.rkt") "utils.rkt")
(provide (all-from-out (provide (all-from-out
"base.rkt" "base.rkt"
@ -23,4 +23,4 @@
"vector.rkt" "vector.rkt"
"array.rkt" "array.rkt"
;"matrix.rkt" ;"matrix.rkt"
"parameters.rkt")) "utils.rkt"))

View File

@ -1,8 +1,8 @@
#lang typed/racket/base #lang typed/racket/base
(require "../../parameters.rkt" (require "../../base.rkt"
"../../base.rkt"
"../../flonum.rkt" "../../flonum.rkt"
"../parameters.rkt"
"../unsafe.rkt" "../unsafe.rkt"
"../vector/vector-fft.rkt" "../vector/vector-fft.rkt"
"fcarray-struct.rkt" "fcarray-struct.rkt"
@ -13,7 +13,6 @@
(provide array-axis-fft (provide array-axis-fft
array-fft array-fft
fcarray-fft
array-axis-inverse-fft array-axis-inverse-fft
array-inverse-fft) array-inverse-fft)

View File

@ -3,7 +3,7 @@
(require racket/future (require racket/future
racket/list racket/list
"../unsafe.rkt" "../unsafe.rkt"
"../../parameters.rkt" "../parameters.rkt"
"array-struct.rkt" "array-struct.rkt"
"mutable-array.rkt" "mutable-array.rkt"
"utils.rkt") "utils.rkt")

View File

@ -28,38 +28,23 @@
(define-syntax-rule (array-scale arr x) (define-syntax-rule (array-scale arr x)
(inline-array-map (λ (y) (* x y)) arr)) (inline-array-map (λ (y) (* x y)) arr))
(define-array-op1 array-sqr sqr)
(define-array-op1 array-sqrt sqrt)
(define-array-op1 array-abs abs) (define-array-op1 array-abs abs)
(define-array-op1 array-round round)
(define-array-op1 array-floor floor)
(define-array-op1 array-ceiling ceiling)
(define-array-op1 array-truncate truncate)
(define-array-op1 array-conjugate conjugate)
(define-array-op1 array-magnitude magnitude) (define-array-op1 array-magnitude magnitude)
(define-array-op1 array-angle angle) (define-array-op1 array-angle angle)
(define-array-op1 array-sqrt sqrt) (define-array-op1 array-conjugate conjugate)
(define-array-op1 array-log log)
(define-array-op1 array-sqr sqr)
(define-array-op1 array-exp exp)
(define-array-op1 array-sin sin)
(define-array-op1 array-cos cos)
(define-array-op1 array-tan tan)
(define-array-op1 array-asin asin)
(define-array-op1 array-acos acos)
(define-array-op1 array-atan atan)
(define-array-op1 array-inexact->exact inexact->exact)
(define-array-op1 array-exact->inexact exact->inexact)
(define-array-op1 array-fl real->double-flonum)
(define-array-op1 array-fc number->float-complex)
(define-array-op1 array-real-part real-part) (define-array-op1 array-real-part real-part)
(define-array-op1 array-imag-part imag-part) (define-array-op1 array-imag-part imag-part)
(define-array-op2 array-make-rectangular make-rectangular) (define-array-op2 array-make-rectangular make-rectangular)
(define-array-op2 array-make-polar make-polar)
(define-array-op array+ +) (define-array-op array+ +)
(define-array-op array* *) (define-array-op array* *)
(define-array-op1+ array- -) (define-array-op1+ array- -)
(define-array-op1+ array/ /) (define-array-op1+ array/ /)
(define-array-op2 array-expt expt)
(define-array-op1+ array-min min) (define-array-op1+ array-min min)
(define-array-op1+ array-max max) (define-array-op1+ array-max max)
@ -81,29 +66,20 @@
array-map array-map
;; Lifted operators ;; Lifted operators
array-scale array-scale
array-abs
array-round
array-floor
array-ceiling
array-truncate
array-sqr array-sqr
array-sqrt array-sqrt
array-conjugate array-abs
array-magnitude array-magnitude
array-angle array-angle
array-log array-conjugate
array-exp array-real-part
array-sin array-imag-part
array-cos array-make-rectangular
array-tan array-make-polar
array-asin
array-acos
array-atan
array+ array+
array- array-
array* array*
array/ array/
array-expt
array-min array-min
array-max array-max
array= array=
@ -114,12 +90,4 @@
array-not array-not
array-and array-and
array-or array-or
array-if array-if)
;; Number conversions
array-inexact->exact
array-exact->inexact
array-fl
array-fc
array-real-part
array-imag-part
array-make-rectangular)

View File

@ -20,25 +20,17 @@
fcarray-scale fcarray-scale
fcarray-sqr fcarray-sqr
fcarray-sqrt fcarray-sqrt
fcarray-conjugate
fcarray-magnitude fcarray-magnitude
fcarray-angle fcarray-angle
fcarray-log
fcarray-exp
fcarray-sin
fcarray-cos
fcarray-tan
fcarray-asin
fcarray-acos
fcarray-atan
fcarray+ fcarray+
fcarray* fcarray*
fcarray- fcarray-
fcarray/ fcarray/
fcarray-expt fcarray-conjugate
fcarray-real-part fcarray-real-part
fcarray-imag-part fcarray-imag-part
fcarray-make-rectangular fcarray-make-rectangular
fcarray-make-polar
) )
;; =================================================================================================== ;; ===================================================================================================
@ -143,9 +135,6 @@
;; =================================================================================================== ;; ===================================================================================================
;; Pointwise operations ;; Pointwise operations
(define-syntax-rule (lift1 f)
(λ (arr) (inline-fcarray-map f arr)))
(define-syntax-rule (lift1->fl f) (define-syntax-rule (lift1->fl f)
(λ (arr) (λ (arr)
(define ds (array-shape arr)) (define ds (array-shape arr))
@ -162,73 +151,63 @@
[else [else
(unsafe-flarray ds new-xs)])))) (unsafe-flarray ds new-xs)]))))
(define-syntax-rule (lift1 f)
(λ: ([arr : FCArray]) (inline-fcarray-map f arr)))
(define-syntax-rule (lift2 f) (define-syntax-rule (lift2 f)
(λ (arr1 arr2) (inline-fcarray-map f arr1 arr2))) (λ: ([arr1 : FCArray] [arr2 : FCArray]) (inline-fcarray-map f arr1 arr2)))
(: fcarray-scale (FCArray (U Float Float-Complex) -> FCArray)) (: fcarray-scale (FCArray (U Float Float-Complex) -> FCArray))
(: fcarray-sqr (FCArray -> FCArray))
(: fcarray-sqrt (FCArray -> FCArray))
(: fcarray-conjugate (FCArray -> FCArray))
(: fcarray-magnitude (FCArray -> FlArray))
(: fcarray-angle (FCArray -> FlArray))
(: fcarray-log (FCArray -> FCArray))
(: fcarray-exp (FCArray -> FCArray))
(: fcarray-sin (FCArray -> FCArray))
(: fcarray-cos (FCArray -> FCArray))
(: fcarray-tan (FCArray -> FCArray))
(: fcarray-asin (FCArray -> FCArray))
(: fcarray-acos (FCArray -> FCArray))
(: fcarray-atan (FCArray -> FCArray))
(: fcarray+ (FCArray FCArray -> FCArray))
(: fcarray* (FCArray FCArray -> FCArray))
(: fcarray- (case-> (FCArray -> FCArray)
(FCArray FCArray -> FCArray)))
(: fcarray/ (case-> (FCArray -> FCArray)
(FCArray FCArray -> FCArray)))
(: fcarray-expt (FCArray FCArray -> FCArray))
(: fcarray-real-part (FCArray -> FlArray))
(: fcarray-imag-part (FCArray -> FlArray))
(: fcarray-make-rectangular (FlArray FlArray -> FCArray))
(define (fcarray-scale arr y) (define (fcarray-scale arr y)
(if (flonum? y) (if (flonum? y)
(inline-fcarray-map (λ (z) (* z y)) arr) (inline-fcarray-map (λ (z) (* z y)) arr)
(inline-fcarray-map (λ (z) (* z y)) arr))) (inline-fcarray-map (λ (z) (* z y)) arr)))
(define fcarray-sqr (lift1 (λ (x) (* x x)))) (: fcarray-sqr (FCArray -> FCArray))
(define fcarray-sqrt (lift1 sqrt)) (define fcarray-sqr (lift1 (λ: ([z : Float-Complex]) (* z z))))
(define fcarray-conjugate (lift1 conjugate))
(define fcarray-magnitude (lift1->fl magnitude))
(define fcarray-angle (lift1->fl angle))
(define fcarray-log (lift1 log))
(define fcarray-exp (lift1 exp))
(define fcarray-sin (lift1 sin))
(define fcarray-cos (lift1 cos))
(define fcarray-tan (lift1 tan))
(define fcarray-asin (lift1 asin))
(define fcarray-acos (lift1 acos))
(define fcarray-atan (lift1 atan))
(: fcarray-sqrt (FCArray -> FCArray))
(define fcarray-sqrt (lift1 sqrt))
(: fcarray-magnitude (FCArray -> FlArray))
(define fcarray-magnitude (lift1->fl magnitude))
(: fcarray-angle (FCArray -> FlArray))
(define fcarray-angle (lift1->fl angle))
(: fcarray-conjugate (FCArray -> FCArray))
(define fcarray-conjugate (lift1 conjugate))
(: fcarray+ (FCArray FCArray -> FCArray))
(define fcarray+ (lift2 +)) (define fcarray+ (lift2 +))
(: fcarray* (FCArray FCArray -> FCArray))
(define fcarray* (lift2 *)) (define fcarray* (lift2 *))
(: fcarray- (case-> (FCArray -> FCArray)
(FCArray FCArray -> FCArray)))
(define fcarray- (define fcarray-
(case-lambda (case-lambda
[(arr) (inline-fcarray-map (λ (z) (- 0.0 z)) arr)] [(arr) (inline-fcarray-map (λ (z) (- 0.0 z)) arr)]
[(arr1 arr2) (inline-fcarray-map - arr1 arr2)])) [(arr1 arr2) (inline-fcarray-map - arr1 arr2)]))
(: fcarray/ (case-> (FCArray -> FCArray)
(FCArray FCArray -> FCArray)))
(define fcarray/ (define fcarray/
(case-lambda (case-lambda
[(arr) (inline-fcarray-map (λ (z) (/ 1.0 z)) arr)] [(arr) (inline-fcarray-map (λ (z) (/ 1.0 z)) arr)]
[(arr1 arr2) (inline-fcarray-map / arr1 arr2)])) [(arr1 arr2) (inline-fcarray-map / arr1 arr2)]))
(define fcarray-expt (lift2 expt)) (: fcarray-real-part (FCArray -> FlArray))
(define fcarray-real-part (lift1->fl real-part)) (define fcarray-real-part (lift1->fl real-part))
(: fcarray-imag-part (FCArray -> FlArray))
(define fcarray-imag-part (lift1->fl imag-part)) (define fcarray-imag-part (lift1->fl imag-part))
(: fcarray-make-rectangular (FlArray FlArray -> FCArray))
(define (fcarray-make-rectangular arr1 arr2) (define (fcarray-make-rectangular arr1 arr2)
(array->fcarray (array-make-rectangular arr1 arr2))) (array->fcarray (array-make-rectangular arr1 arr2)))
(: fcarray-make-polar (FlArray FlArray -> FCArray))
(define (fcarray-make-polar arr1 arr2)
(array->fcarray (array-make-polar arr1 arr2)))

View File

@ -16,33 +16,15 @@
flarray-map flarray-map
;; Pointwise operations ;; Pointwise operations
flarray-scale flarray-scale
flarray-round
flarray-floor
flarray-ceiling
flarray-truncate
flarray-abs
flarray-sqr flarray-sqr
flarray-sqrt flarray-sqrt
flarray-log flarray-abs
flarray-exp
flarray-sin
flarray-cos
flarray-tan
flarray-asin
flarray-acos
flarray-atan
flarray+ flarray+
flarray* flarray*
flarray- flarray-
flarray/ flarray/
flarray-expt
flarray-min flarray-min
flarray-max flarray-max)
flarray=
flarray<
flarray<=
flarray>
flarray>=)
;; =================================================================================================== ;; ===================================================================================================
;; Mapping ;; Mapping
@ -53,7 +35,7 @@
[(_ f arr-expr) [(_ f arr-expr)
(syntax/loc stx (syntax/loc stx
(let: ([arr : FlArray arr-expr]) (let: ([arr : FlArray arr-expr])
(unsafe-flarray (array-shape arr) (flvector-map f (flarray-data arr)))))] (unsafe-flarray (array-shape arr) (inline-flvector-map f (flarray-data arr)))))]
[(_ f arr-expr arr-exprs ...) [(_ f arr-expr arr-exprs ...)
(with-syntax ([(arrs ...) (generate-temporaries #'(arr-exprs ...))] (with-syntax ([(arrs ...) (generate-temporaries #'(arr-exprs ...))]
[(dss ...) (generate-temporaries #'(arr-exprs ...))] [(dss ...) (generate-temporaries #'(arr-exprs ...))]
@ -65,7 +47,7 @@
(define dss (array-shape arrs)) ... (define dss (array-shape arrs)) ...
(cond [(and (equal? ds dss) ...) (cond [(and (equal? ds dss) ...)
(unsafe-flarray (unsafe-flarray
ds (flvector-map f (flarray-data arr) (flarray-data arrs) ...))] ds (inline-flvector-map f (flarray-data arr) (flarray-data arrs) ...))]
[else [else
(define new-ds (array-shape-broadcast (list ds dss ...))) (define new-ds (array-shape-broadcast (list ds dss ...)))
(define proc (unsafe-array-proc (array-broadcast arr new-ds))) (define proc (unsafe-array-proc (array-broadcast arr new-ds)))
@ -115,91 +97,42 @@
(cond [(equal? ds1 ds2) (unsafe-flarray ds1 (f (flarray-data arr1) (flarray-data arr2)))] (cond [(equal? ds1 ds2) (unsafe-flarray ds1 (f (flarray-data arr1) (flarray-data arr2)))]
[else (array->flarray (array-f arr1 arr2))]))) [else (array->flarray (array-f arr1 arr2))])))
(define-syntax (lift2 stx)
(syntax-case stx ()
[(_ f) (syntax/loc stx (λ (arr1 arr2) (inline-flarray-map f arr1 arr2)))]))
(define-syntax-rule (lift-flvector-compare flvector-comp array-comp)
(λ (arr1 arr2)
(define ds1 (array-shape arr1))
(define ds2 (array-shape arr2))
(cond [(equal? ds1 ds2)
(unsafe-mutable-array ds1 (flvector-comp (flarray-data arr1) (flarray-data arr2)))]
[else (array-comp arr1 arr2)])))
(: flarray-scale (FlArray Float -> FlArray)) (: flarray-scale (FlArray Float -> FlArray))
(: flarray-round (FlArray -> FlArray))
(: flarray-floor (FlArray -> FlArray))
(: flarray-ceiling (FlArray -> FlArray))
(: flarray-truncate (FlArray -> FlArray))
(: flarray-abs (FlArray -> FlArray))
(: flarray-sqr (FlArray -> FlArray))
(: flarray-sqrt (FlArray -> FlArray))
(: flarray-log (FlArray -> FlArray))
(: flarray-exp (FlArray -> FlArray))
(: flarray-sin (FlArray -> FlArray))
(: flarray-cos (FlArray -> FlArray))
(: flarray-tan (FlArray -> FlArray))
(: flarray-asin (FlArray -> FlArray))
(: flarray-acos (FlArray -> FlArray))
(: flarray-atan (FlArray -> FlArray))
(: flarray+ (FlArray FlArray -> FlArray))
(: flarray* (FlArray FlArray -> FlArray))
(: flarray- (case-> (FlArray -> FlArray)
(FlArray FlArray -> FlArray)))
(: flarray/ (case-> (FlArray -> FlArray)
(FlArray FlArray -> FlArray)))
(: flarray-expt (FlArray FlArray -> FlArray))
(: flarray-min (FlArray FlArray -> FlArray))
(: flarray-max (FlArray FlArray -> FlArray))
(: flarray= (FlArray FlArray -> (Array Boolean)))
(: flarray< (FlArray FlArray -> (Array Boolean)))
(: flarray<= (FlArray FlArray -> (Array Boolean)))
(: flarray> (FlArray FlArray -> (Array Boolean)))
(: flarray>= (FlArray FlArray -> (Array Boolean)))
(define (flarray-scale arr y) (define (flarray-scale arr y)
(define-syntax-rule (fun xs) (flvector-scale xs y)) (define-syntax-rule (fun xs) (flvector-scale xs y))
((lift-flvector1 fun) arr)) ((lift-flvector1 fun) arr))
(define flarray-round (lift-flvector1 flvector-round)) (: flarray-sqr (FlArray -> FlArray))
(define flarray-floor (lift-flvector1 flvector-floor)) (define flarray-sqr (lift-flvector1 flvector-sqr))
(define flarray-ceiling (lift-flvector1 flvector-ceiling))
(define flarray-truncate (lift-flvector1 flvector-truncate))
(define flarray-abs (lift-flvector1 flvector-abs))
(define flarray-sqr (lift-flvector1 flvector-sqr))
(define flarray-sqrt (lift-flvector1 flvector-sqrt))
(define flarray-log (lift-flvector1 flvector-log))
(define flarray-exp (lift-flvector1 flvector-exp))
(define flarray-sin (lift-flvector1 flvector-sin))
(define flarray-cos (lift-flvector1 flvector-cos))
(define flarray-tan (lift-flvector1 flvector-tan))
(define flarray-asin (lift-flvector1 flvector-asin))
(define flarray-acos (lift-flvector1 flvector-acos))
(define flarray-atan (lift-flvector1 flvector-atan))
(: flarray-sqrt (FlArray -> FlArray))
(define flarray-sqrt (lift-flvector1 flvector-sqrt))
(: flarray-abs (FlArray -> FlArray))
(define flarray-abs (lift-flvector1 flvector-abs))
(: flarray+ (FlArray FlArray -> FlArray))
(define flarray+ (lift-flvector2 flvector+ array+)) (define flarray+ (lift-flvector2 flvector+ array+))
(: flarray* (FlArray FlArray -> FlArray))
(define flarray* (lift-flvector2 flvector* array*)) (define flarray* (lift-flvector2 flvector* array*))
(: flarray- (case-> (FlArray -> FlArray)
(FlArray FlArray -> FlArray)))
(define flarray- (define flarray-
(case-lambda (case-lambda
[(arr) ((lift-flvector1 flvector-) arr)] [(arr) ((lift-flvector1 flvector-) arr)]
[(arr1 arr2) ((lift-flvector2 flvector- array-) arr1 arr2)])) [(arr1 arr2) ((lift-flvector2 flvector- array-) arr1 arr2)]))
(: flarray/ (case-> (FlArray -> FlArray)
(FlArray FlArray -> FlArray)))
(define flarray/ (define flarray/
(case-lambda (case-lambda
[(arr) ((lift-flvector1 flvector/) arr)] [(arr) ((lift-flvector1 flvector/) arr)]
[(arr1 arr2) ((lift-flvector2 flvector/ array/) arr1 arr2)])) [(arr1 arr2) ((lift-flvector2 flvector/ array/) arr1 arr2)]))
(define flarray-expt (lift2 flexpt)) (: flarray-min (FlArray FlArray -> FlArray))
(define flarray-min (lift-flvector2 flvector-min array-min)) (define flarray-min (lift-flvector2 flvector-min array-min))
(define flarray-max (lift-flvector2 flvector-max array-max))
(define flarray= (lift-flvector-compare flvector= array=)) (: flarray-max (FlArray FlArray -> FlArray))
(define flarray< (lift-flvector-compare flvector< array<)) (define flarray-max (lift-flvector2 flvector-max array-max))
(define flarray<= (lift-flvector-compare flvector<= array<=))
(define flarray> (lift-flvector-compare flvector> array>))
(define flarray>= (lift-flvector-compare flvector>= array>=))

View File

@ -1,7 +1,7 @@
#lang typed/racket/base #lang typed/racket/base
(require racket/flonum (require racket/flonum
"../flonum/flonum-sum.rkt" "../flonum/flvector.rkt"
"../flonum/flonum-functions.rkt" "../flonum/flonum-functions.rkt"
"../flonum/flonum-more-functions.rkt") "../flonum/flonum-more-functions.rkt")

View File

@ -5,8 +5,8 @@
"flonum-functions.rkt" "flonum-functions.rkt"
"flonum-constants.rkt" "flonum-constants.rkt"
"flonum-exp.rkt" "flonum-exp.rkt"
"flonum-sum.rkt" "flonum-syntax.rkt"
"flonum-syntax.rkt") "flvector.rkt")
(provide fllog1p fllog+ (provide fllog1p fllog+
lg1+ lg+ lg1- lg- lgsum lg1+ lg+ lg1- lg- lgsum

View File

@ -5,7 +5,8 @@
"flonum-constants.rkt" "flonum-constants.rkt"
"flonum-exp.rkt" "flonum-exp.rkt"
"flonum-log.rkt" "flonum-log.rkt"
"flonum-syntax.rkt") "flonum-syntax.rkt"
"flvector.rkt")
(provide flsqrt1pm1 (provide flsqrt1pm1
flsinh flcosh fltanh flsinh flcosh fltanh

View File

@ -1,38 +0,0 @@
#lang typed/racket/base
;; Computes sums without incurring rounding error more than once
;; See (flsum '(1.0 1e-16 1e-16)) vs. (+ 1.0 1e-16 1e-16)
#|
Algorithm adapted from:
J R Shewchuk. Adaptive Precision Floating-Point Arithmetic and Fast Geometric Predicates.
Discrete & Computational Geometry, 1996, vol 18, pp 305--363.
|#
(require "../unsafe.rkt"
"flonum-functions.rkt")
(provide flsum)
(: flsum ((Listof Flonum) -> Flonum))
(define (flsum xs)
(define ys (make-flvector (length xs)))
(define num-ys
(for/fold: ([num-ys : Nonnegative-Fixnum 0]) ([x (in-list xs)])
(define-values (new-x i)
(for/fold: ([x : Flonum x] [i : Nonnegative-Fixnum 0]) ([p (in-range num-ys)])
(define y (unsafe-flvector-ref ys p))
(let-values ([(x y) (if ((flabs x) . fl< . (flabs y)) (values y x) (values x y))])
(define z (fl+ x y))
(define-values (hi lo)
(cond [(rational? z) (values z (fl- y (fl- z x)))]
[else (values x y)]))
(cond [(fl= lo 0.0) (values hi i)]
[else (unsafe-flvector-set! ys i lo)
(values hi (unsafe-fx+ i 1))]))))
(unsafe-flvector-set! ys i new-x)
(unsafe-fx+ i 1)))
(for/fold: ([sum : Flonum 0.0]) ([p (in-range num-ys)])
(fl+ sum (unsafe-flvector-ref ys p))))

View File

@ -1,79 +1,119 @@
#lang racket/base #lang racket/base
(module syntax-defs* racket/base (provide inline-build-flvector
build-flvector
inline-flvector-map
flvector-map)
(require (for-syntax racket/base) (module syntax-defs racket/base
(require (for-syntax racket/base
syntax/parse
typed/untyped-utils)
typed/racket/base typed/racket/base
racket/unsafe/ops
racket/flonum racket/flonum
racket/fixnum racket/fixnum
racket/unsafe/ops
"../syntax-utils.rkt" "../syntax-utils.rkt"
"../exception.rkt") "../exception.rkt"
"../utils.rkt")
(provide (all-defined-out)) (provide (all-defined-out))
(define-syntax-rule (ensure-flvector/length name xs-expr n) (define-syntax (unsafe-flvector-fill! stx)
(let*: ([xs : FlVector (ensure-flvector name xs-expr)]) (syntax-parse stx
(if (fx= (unsafe-flvector-length xs) n) xs (raise-length-error name "FlVector" xs n)))) [(_ xs:id n:id f-expr:expr)
(syntax/loc stx
(let: loop : FlVector ([i : Nonnegative-Fixnum 0])
(if (i . unsafe-fx< . n)
(begin (unsafe-flvector-set! xs i (f-expr i))
(loop (unsafe-fx+ i 1)))
xs)))]))
(define-syntax-rule (unsafe-build-flvector n f) (define-syntax (inline-build-flvector stx)
(let ([xs (make-flvector n)]) (syntax-case stx ()
(let: loop : FlVector ([i : Nonnegative-Fixnum 0]) [(_ n-expr f-expr)
(if (i . unsafe-fx< . n) (cond
(begin (unsafe-flvector-set! xs i (f i)) [(syntax-local-typed-context?)
(loop (unsafe-fx+ i 1))) (syntax/loc stx
xs)))) (let*: ([xs : FlVector (make-flvector (ann n-expr Integer))]
[n : Index (flvector-length xs)])
(unsafe-flvector-fill! xs n (ann f-expr (Index -> Flonum)))))]
[else
(syntax/loc stx
(let* ([xs (make-flvector n-expr)]
[n (flvector-length xs)])
(define-syntax-rule (new-f i)
(let ([x (f-expr i)])
(if (flonum? x) x (raise-result-error 'build-flvector "Flonum" x))))
(unsafe-flvector-fill! xs n new-f)))])]))
(define-syntax-rule (inline-build-flvector* n-expr f-expr) (define-syntax (inline-flvector-map stx)
(let ([n (ensure-index 'build-flvector n-expr)]
[f (ensure-procedure 'build-flvector f-expr (Index -> Flonum))])
(define-syntax-rule (new-f i)
(let ([x (f i)])
(if (flonum? x) x (raise-result-error 'build-flvector "Flonum" x))))
(unsafe-build-flvector n new-f)))
(define-syntax (inline-flvector-map* stx)
(syntax-case stx () (syntax-case stx ()
[(_ f-expr xs-expr) [(_ f-expr xs-expr)
(syntax/loc stx (cond
(let ([f (ensure-procedure 'flvector-map f-expr (Flonum -> Flonum))] [(syntax-local-typed-context?)
[xs (ensure-flvector 'flvector-map xs-expr)]) (syntax/loc stx
(define n (unsafe-flvector-length xs)) (let*: ([xs : FlVector xs-expr]
(define-syntax-rule (new-f i) [n : Index (flvector-length xs)])
(let ([y (f (unsafe-flvector-ref xs i))]) (define-syntax-rule (new-f i)
(if (flonum? y) y (raise-result-error 'flvector-map "Flonum" y)))) ((ann f-expr (Flonum -> Flonum)) (unsafe-flvector-ref xs i)))
(unsafe-build-flvector n new-f)))] (define ys (make-flvector n))
(unsafe-flvector-fill! ys n new-f)))]
[else
(syntax/loc stx
(let* ([xs (ensure-flvector 'flvector-map xs-expr)]
[n (flvector-length xs)])
(define-syntax-rule (new-f i)
(let ([y (f-expr (unsafe-flvector-ref xs i))])
(if (flonum? y) y (raise-result-error 'flvector-map "Flonum" y))))
(define ys (make-flvector n))
(unsafe-flvector-fill! ys n new-f)))])]
[(_ f-expr xs-expr xss-expr ...) [(_ f-expr xs-expr xss-expr ...)
(with-syntax ([(f) (generate-temporaries #'(f-expr))] (with-syntax ([(f) (generate-temporaries #'(f-expr))]
[(xs xss ...) (generate-temporaries #'(xs-expr xss-expr ...))] [(xs xss ...) (generate-temporaries #'(xs-expr xss-expr ...))]
[(n ns ...) (generate-temporaries #'(xs-expr xss-expr ...))] [(n ns ...) (generate-temporaries #'(xs-expr xss-expr ...))]
[(Flonums ...) (build-list (length (syntax->list #'(xs-expr xss-expr ...))) [(Flonums ...) (build-list (length (syntax->list #'(xs-expr xss-expr ...)))
(λ _ #'Flonum))]) (λ _ #'Flonum))])
(syntax/loc stx (cond
(let* ([f (ensure-procedure 'flvector-map f-expr (Flonums ... -> Flonum))] [(syntax-local-typed-context?)
[xs (ensure-flvector 'flvector-map xs-expr)] (syntax/loc stx
[n (unsafe-flvector-length xs)] (let*: ([xs : FlVector xs-expr]
[xss (ensure-flvector/length 'flvector-map xss-expr n)] ...) [n : Index (flvector-length xs)]
(define-syntax-rule (new-f i) [xss : FlVector xss-expr] ...)
(let ([y (f (unsafe-flvector-ref xs i) (unsafe-flvector-ref xss i) ...)]) (check-flvector-lengths! 'flvector-map n xss ...)
(cond [(flonum? y) y] (define-syntax-rule (new-f i)
[else (raise-result-error 'flvector-map "Flonum" y)]))) ((ann f-expr (Flonums ... -> Flonum)) (unsafe-flvector-ref xs i)
(unsafe-build-flvector n new-f))))])) (unsafe-flvector-ref xss i) ...))
(define ys (make-flvector n))
(unsafe-flvector-fill! ys n new-f)))]
[else
(syntax/loc stx
(let* ([xs (ensure-flvector 'flvector-map xs-expr)]
[n (unsafe-flvector-length xs)]
[xss (ensure-flvector 'flvector-map xss-expr)] ...)
(check-flvector-lengths! 'flvector-map n xss ...)
(define-syntax-rule (new-f i)
(let ([y (f-expr (unsafe-flvector-ref xs i) (unsafe-flvector-ref xss i) ...)])
(cond [(flonum? y) y]
[else (raise-result-error 'flvector-map "Flonum" y)])))
(define ys (make-flvector n))
(unsafe-flvector-fill! ys n new-f)))]))]))
) ) ; module
(module defs typed/racket/base (module defs typed/racket/base
(require racket/flonum (require racket/flonum
racket/fixnum racket/fixnum
racket/unsafe/ops racket/unsafe/ops
(submod ".." syntax-defs*) (submod ".." syntax-defs)
"../utils.rkt"
"../exception.rkt") "../exception.rkt")
(provide (all-defined-out)) (provide (all-defined-out))
(: build-flvector (Integer (Index -> Flonum) -> FlVector)) (: build-flvector (Integer (Index -> Flonum) -> FlVector))
(define (build-flvector n f) (define (build-flvector n f) (inline-build-flvector n f))
(inline-build-flvector* n f))
(: flvector-map (case-> ((Flonum -> Flonum) FlVector -> FlVector) (: flvector-map (case-> ((Flonum -> Flonum) FlVector -> FlVector)
((Flonum Flonum Flonum * -> Flonum) FlVector FlVector FlVector * ((Flonum Flonum Flonum * -> Flonum) FlVector FlVector FlVector *
@ -81,46 +121,20 @@
(define flvector-map (define flvector-map
(case-lambda: (case-lambda:
[([f : (Flonum -> Flonum)] [xs : FlVector]) [([f : (Flonum -> Flonum)] [xs : FlVector])
(inline-flvector-map* f xs)] (inline-flvector-map f xs)]
[([f : (Flonum Flonum -> Flonum)] [xs : FlVector] [ys : FlVector]) [([f : (Flonum Flonum -> Flonum)] [xs : FlVector] [ys : FlVector])
(inline-flvector-map* f xs ys)] (inline-flvector-map f xs ys)]
[([f : (Flonum Flonum Flonum * -> Flonum)] [xs : FlVector] [ys : FlVector] . [yss : FlVector *]) [([f : (Flonum Flonum Flonum * -> Flonum)] [xs : FlVector] [ys : FlVector] . [yss : FlVector *])
(define n (flvector-length xs)) (define n (flvector-length xs))
(for: ([ys (in-list (cons ys yss))]) (apply check-flvector-lengths! 'flvector-map n ys yss)
(unless (fx= n (flvector-length ys)) (raise-length-error 'flvector-map "FlVector" ys n))) (inline-build-flvector
(inline-build-flvector*
n (λ: ([i : Index]) n (λ: ([i : Index])
(apply f (apply f
(unsafe-flvector-ref xs i) (unsafe-flvector-ref xs i)
(unsafe-flvector-ref ys i) (unsafe-flvector-ref ys i)
(map (λ: ([ys : FlVector]) (unsafe-flvector-ref ys i)) yss))))])) (map (λ: ([ys : FlVector]) (unsafe-flvector-ref ys i)) yss))))]))
) ) ; module
(module syntax-defs racket/base (require 'syntax-defs 'defs)
(require (for-syntax racket/base)
(submod ".." syntax-defs*)
(submod ".." defs))
(provide (all-defined-out))
(define-syntax (inline-build-flvector stx)
(syntax-case stx ()
[(_ n-expr f-expr) (syntax/loc stx (inline-build-flvector* n-expr f-expr))]
[(_ . args) (syntax/loc stx (build-flvector . args))]
[_ (syntax/loc stx build-flvector)]))
(define-syntax (inline-flvector-map stx)
(syntax-case stx ()
[(_ f-expr xs-expr xss-expr ...)
(syntax/loc stx (inline-flvector-map* f-expr xs-expr xss-expr ...))]
[(_ . args) (syntax/loc stx (flvector-map . args))]
[_ (syntax/loc stx flvector-map)]))
)
(require 'defs
'syntax-defs)
(provide (rename-out [inline-build-flvector build-flvector]
[inline-flvector-map flvector-map]))

View File

@ -1,10 +1,8 @@
#lang typed/racket/base #lang typed/racket/base
(require racket/fixnum (require racket/fixnum
racket/string
(for-syntax racket/base syntax/parse)
"flonum-functions.rkt"
"../unsafe.rkt" "../unsafe.rkt"
"flonum-functions.rkt"
"flvector-syntax.rkt") "flvector-syntax.rkt")
(provide (provide
@ -19,38 +17,22 @@
flvector->vector flvector->vector
;; Pointwise operations ;; Pointwise operations
flvector-scale flvector-scale
flvector-round
flvector-floor
flvector-ceiling
flvector-truncate
flvector-abs
flvector-sqr flvector-sqr
flvector-sqrt flvector-sqrt
flvector-log flvector-abs
flvector-exp
flvector-sin
flvector-cos
flvector-tan
flvector-asin
flvector-acos
flvector-atan
flvector+ flvector+
flvector* flvector*
flvector- flvector-
flvector/ flvector/
flvector-expt
flvector-min flvector-min
flvector-max flvector-max
flvector= ;; Sum
flvector< flvector-sum
flvector<= flvector-sums
flvector> flsum)
flvector>=
;;
flvector-sums)
;; =================================================================================================== ;; ===================================================================================================
;; flvector-copy ;; flvector-copy!
(: unsafe-flvector-copy! (FlVector Integer FlVector Integer Integer -> Void)) (: unsafe-flvector-copy! (FlVector Integer FlVector Integer Integer -> Void))
(define (unsafe-flvector-copy! dest dest-start src src-start src-end) (define (unsafe-flvector-copy! dest dest-start src src-start src-end)
@ -92,12 +74,8 @@
(: list->flvector ((Listof Real) -> FlVector)) (: list->flvector ((Listof Real) -> FlVector))
(define (list->flvector vs) (define (list->flvector vs)
(define n (length vs)) (for/flvector: #:length (length vs) ([v (in-list vs)])
(define xs (make-flvector n)) (fl v)))
(let loop ([#{i : Nonnegative-Fixnum} 0] [vs vs])
(cond [(i . < . n) (unsafe-flvector-set! xs i (real->double-flonum (unsafe-car vs)))
(loop (+ i 1) (unsafe-cdr vs))]
[else xs])))
(: flvector->list (FlVector -> (Listof Float))) (: flvector->list (FlVector -> (Listof Float)))
(define (flvector->list xs) (define (flvector->list xs)
@ -105,148 +83,156 @@
(: vector->flvector ((Vectorof Real) -> FlVector)) (: vector->flvector ((Vectorof Real) -> FlVector))
(define (vector->flvector vs) (define (vector->flvector vs)
(define n (vector-length vs)) (for/flvector: #:length (vector-length vs) ([v (in-vector vs)])
(define xs (make-flvector n)) (fl v)))
(let loop ([#{i : Nonnegative-Fixnum} 0])
(cond [(i . < . n) (unsafe-flvector-set! xs i (real->double-flonum (unsafe-vector-ref vs i)))
(loop (+ i 1))]
[else xs])))
(: flvector->vector (FlVector -> (Vectorof Float))) (: flvector->vector (FlVector -> (Vectorof Float)))
(define (flvector->vector xs) (define (flvector->vector xs)
(define n (flvector-length xs)) (for/vector: #:length (flvector-length xs) ([x (in-flvector xs)]) : Flonum
(define vs (make-vector n 0.0)) x))
(let loop ([#{i : Nonnegative-Fixnum} 0])
(cond [(i . < . n) (unsafe-vector-set! vs i (unsafe-flvector-ref xs i))
(loop (+ i 1))]
[else vs])))
;; =================================================================================================== ;; ===================================================================================================
;; Pointwise operations ;; Pointwise operations
(define-syntax (lift1 stx) (define-syntax-rule (lift1 f)
(syntax-case stx () (λ: ([arr : FlVector])
[(_ f) (syntax/loc stx (λ (arr) (flvector-map f arr)))])) (inline-flvector-map f arr)))
(define-syntax (lift2 stx) (define-syntax-rule (lift2 f)
(syntax-case stx () (λ: ([arr0 : FlVector] [arr1 : FlVector])
[(_ f) (syntax/loc stx (λ (arr1 arr2) (flvector-map f arr1 arr2)))])) (inline-flvector-map f arr0 arr1)))
(define-syntax-rule (lift-comparison name comp)
(λ (xs1 xs2)
(define n1 (flvector-length xs1))
(define n2 (flvector-length xs2))
(unless (= n1 n2) (error name "flvectors must be the same length; given lengths ~e and ~e" n1 n2))
(build-vector
n1 (λ: ([j : Index])
(comp (unsafe-flvector-ref xs1 j)
(unsafe-flvector-ref xs2 j))))))
(: flvector-scale (FlVector Float -> FlVector)) (: flvector-scale (FlVector Float -> FlVector))
(define (flvector-scale arr y) (flvector-map (λ (x) (fl* x y)) arr)) (define (flvector-scale arr y) (inline-flvector-map (λ: ([x : Flonum]) (fl* x y)) arr))
(: flvector-sqr (FlVector -> FlVector))
(define flvector-sqr (lift1 (λ: ([x : Flonum]) (fl* x x))))
(: flvector-round (FlVector -> FlVector))
(: flvector-floor (FlVector -> FlVector))
(: flvector-ceiling (FlVector -> FlVector))
(: flvector-truncate (FlVector -> FlVector))
(: flvector-abs (FlVector -> FlVector))
(: flvector-sqr (FlVector -> FlVector))
(: flvector-sqrt (FlVector -> FlVector)) (: flvector-sqrt (FlVector -> FlVector))
(: flvector-log (FlVector -> FlVector)) (define flvector-sqrt (lift1 flsqrt))
(: flvector-exp (FlVector -> FlVector))
(: flvector-sin (FlVector -> FlVector)) (: flvector-abs (FlVector -> FlVector))
(: flvector-cos (FlVector -> FlVector)) (define flvector-abs (lift1 flabs))
(: flvector-tan (FlVector -> FlVector))
(: flvector-asin (FlVector -> FlVector))
(: flvector-acos (FlVector -> FlVector))
(: flvector-atan (FlVector -> FlVector))
(: flvector+ (FlVector FlVector -> FlVector)) (: flvector+ (FlVector FlVector -> FlVector))
(: flvector* (FlVector FlVector -> FlVector))
(: flvector- (case-> (FlVector -> FlVector)
(FlVector FlVector -> FlVector)))
(: flvector/ (case-> (FlVector -> FlVector)
(FlVector FlVector -> FlVector)))
(: flvector-expt (FlVector FlVector -> FlVector))
(: flvector-min (FlVector FlVector -> FlVector))
(: flvector-max (FlVector FlVector -> FlVector))
(: flvector= (FlVector FlVector -> (Vectorof Boolean)))
(: flvector< (FlVector FlVector -> (Vectorof Boolean)))
(: flvector<= (FlVector FlVector -> (Vectorof Boolean)))
(: flvector> (FlVector FlVector -> (Vectorof Boolean)))
(: flvector>= (FlVector FlVector -> (Vectorof Boolean)))
(define flvector-round (lift1 flround))
(define flvector-floor (lift1 flfloor))
(define flvector-ceiling (lift1 flceiling))
(define flvector-truncate (lift1 fltruncate))
(define flvector-abs (lift1 flabs))
(define flvector-sqr (lift1 (λ: ([x : Float]) (fl* x x))))
(define flvector-sqrt (lift1 flsqrt))
(define flvector-log (lift1 fllog))
(define flvector-exp (lift1 flexp))
(define flvector-sin (lift1 flsin))
(define flvector-cos (lift1 flcos))
(define flvector-tan (lift1 fltan))
(define flvector-asin (lift1 flasin))
(define flvector-acos (lift1 flacos))
(define flvector-atan (lift1 flatan))
(define flvector+ (lift2 fl+)) (define flvector+ (lift2 fl+))
(: flvector* (FlVector FlVector -> FlVector))
(define flvector* (lift2 fl*)) (define flvector* (lift2 fl*))
(: flvector- (case-> (FlVector -> FlVector)
(FlVector FlVector -> FlVector)))
(define flvector- (define flvector-
(case-lambda (case-lambda:
[(arr) (flvector-map (λ: ([x : Float]) (fl- 0.0 x)) arr)] [([arr0 : FlVector])
[(arr1 arr2) (flvector-map fl- arr1 arr2)])) (inline-flvector-map (λ: ([x : Float]) (fl- 0.0 x)) arr0)]
[([arr0 : FlVector] [arr1 : FlVector])
(inline-flvector-map fl- arr0 arr1)]))
(: flvector/ (case-> (FlVector -> FlVector)
(FlVector FlVector -> FlVector)))
(define flvector/ (define flvector/
(case-lambda (case-lambda:
[(arr) (flvector-map (λ: ([x : Float]) (fl/ 1.0 x)) arr)] [([arr0 : FlVector])
[(arr1 arr2) (flvector-map fl/ arr1 arr2)])) (inline-flvector-map (λ: ([x : Float]) (fl/ 1.0 x)) arr0)]
[([arr0 : FlVector] [arr1 : FlVector])
(inline-flvector-map fl/ arr0 arr1)]))
(define flvector-expt (lift2 flexpt)) (: flvector-min (FlVector FlVector -> FlVector))
(define flvector-min (lift2 flmin)) (define flvector-min (lift2 flmin))
(define flvector-max (lift2 flmax))
(define flvector= (lift-comparison 'flvector= fl=)) (: flvector-max (FlVector FlVector -> FlVector))
(define flvector< (lift-comparison 'flvector< fl<)) (define flvector-max (lift2 flmax))
(define flvector<= (lift-comparison 'flvector<= fl<=))
(define flvector> (lift-comparison 'flvector> fl>))
(define flvector>= (lift-comparison 'flvector>= fl>=))
;; =================================================================================================== ;; ===================================================================================================
;; Summation
#|
Algorithm adapted from:
J R Shewchuk. Adaptive Precision Floating-Point Arithmetic and Fast Geometric Predicates.
Discrete & Computational Geometry, 1996, vol 18, pp 305--363.
|#
(: flvector-sum (FlVector -> Flonum))
;; Returns the sum of the elements in xs in a way that incurs rounding error only once
(define (flvector-sum xs)
(define n (flvector-length xs))
;; Vector of remainders
(define rs (make-flvector n))
;; Loop over `xs'
(let i-loop ([#{i : Nonnegative-Fixnum} 0]
;; p = Number of valid remainders in `rs'
[#{p : Nonnegative-Fixnum} 0])
(cond
[(i . fx< . n)
;; Add x consecutively to each remainder, storing the remainder of *those* additions in `rs'
(let j-loop ([#{j : Nonnegative-Fixnum} 0]
;; q = Number of remainders generated by this j-loop:
[#{q : Nonnegative-Fixnum} 0]
[x (unsafe-flvector-ref xs i)])
(cond
[(j . fx< . p)
(define r (unsafe-flvector-ref rs j))
;; Get the largest of x and r, or x if it's not rational
(let-values ([(x r) (if ((flabs x) . fl< . (flabs r)) (values r x) (values x r))])
;; Add with remainder
(define z (fl+ x r))
(define-values (hi lo)
(cond [(flrational? z) (values z (fl- r (fl- z x)))]
[else (values x r)]))
(cond [(fl= lo 0.0)
;; No remainder: don't store (makes average case O(n*log(n)))
(j-loop (unsafe-fx+ j 1) q hi)]
[else
;; Store the remainder, increment the counter
(unsafe-flvector-set! rs q lo)
(j-loop (unsafe-fx+ j 1) (unsafe-fx+ q 1) hi)]))]
[else
;; Store the sum so far as the last remainder
(unsafe-flvector-set! rs q x)
(i-loop (fx+ i 1) (unsafe-fx+ q 1))]))]
[else
;; Add all the remainders
(let j-loop ([#{j : Nonnegative-Fixnum} 0] [acc 0.0])
(cond [(j . fx< . p) (j-loop (unsafe-fx+ j 1) (fl+ acc (unsafe-flvector-ref rs j)))]
[else acc]))])))
(: flvector-sums (FlVector -> FlVector)) (: flvector-sums (FlVector -> FlVector))
;; Returns the partial sums of the elements in xs in a way that incurs rounding error only once
;; for each
;; This function works just like `flvector-sum', but keeps track of partial sums instead of
;; summing all the remainders at the end
(define (flvector-sums xs) (define (flvector-sums xs)
(define n (flvector-length xs)) (define n (flvector-length xs))
(define rs (make-flvector n)) (define rs (make-flvector n))
(define ss (make-flvector n)) (define ss (make-flvector n))
(let j-loop ([#{j : Nonnegative-Fixnum} 0] (let i-loop ([#{i : Nonnegative-Fixnum} 0]
[#{m : Nonnegative-Fixnum} 0]) [#{p : Nonnegative-Fixnum} 0])
(cond (cond
[(j . fx< . n) [(i . fx< . n)
(define x (unsafe-flvector-ref xs j)) (let j-loop ([#{j : Nonnegative-Fixnum} 0]
(let p-loop ([#{p : Nonnegative-Fixnum} 0] [#{q : Nonnegative-Fixnum} 0]
[#{x : Flonum} x] [x (unsafe-flvector-ref xs i)]
[#{s : Flonum} 0.0] [s 0.0])
[#{i : Nonnegative-Fixnum} 0])
(cond (cond
[(p . fx< . m) [(j . fx< . p)
(define r (unsafe-flvector-ref rs p)) (define r (unsafe-flvector-ref rs j))
(let-values ([(x r) (if ((flabs x) . fl< . (flabs r)) (values r x) (values x r))]) (let-values ([(x r) (if ((flabs x) . fl< . (flabs r)) (values r x) (values x r))])
(define z (fl+ x r)) (define z (fl+ x r))
(define-values (hi lo) (define-values (hi lo)
(cond [(flrational? z) (values z (fl- r (fl- z x)))] (cond [(flrational? z) (values z (fl- r (fl- z x)))]
[else (values x r)])) [else (values x r)]))
(cond [(fl= lo 0.0) (cond [(fl= lo 0.0)
(p-loop (unsafe-fx+ p 1) hi s i)] (j-loop (unsafe-fx+ j 1) q hi s)]
[else [else
(unsafe-flvector-set! rs i lo) (unsafe-flvector-set! rs q lo)
(p-loop (unsafe-fx+ p 1) hi (fl+ s lo) (unsafe-fx+ i 1))]))] (j-loop (unsafe-fx+ j 1) (unsafe-fx+ q 1) hi (fl+ s lo))]))]
[else [else
(unsafe-flvector-set! rs i x) (unsafe-flvector-set! rs q x)
(unsafe-flvector-set! ss j (fl+ s x)) (unsafe-flvector-set! ss i (fl+ s x))
(j-loop (fx+ j 1) (unsafe-fx+ i 1))]))] (i-loop (fx+ i 1) (unsafe-fx+ q 1))]))]
[else ss]))) [else ss])))
(: flsum ((Listof Flonum) -> Flonum))
(define (flsum xs) (flvector-sum (list->flvector xs)))

View File

@ -1,8 +1,12 @@
#lang typed/racket/base #lang typed/racket/base
(require racket/pretty) (require racket/pretty
racket/fixnum
racket/flonum
"exception.rkt")
(provide pretty-print-constructor) (provide pretty-print-constructor
check-flvector-lengths!)
(: port-next-column (Output-Port -> Natural)) (: port-next-column (Output-Port -> Natural))
;; Helper to avoid the annoying #f column value ;; Helper to avoid the annoying #f column value
@ -59,3 +63,9 @@
[else [else
;; No pretty printer, or printing to infinite-width lines, so print on one line ;; No pretty printer, or printing to infinite-width lines, so print on one line
(print-all port 'one-line)])) (print-all port 'one-line)]))
(: check-flvector-lengths! (Symbol Index FlVector * -> Void))
(define (check-flvector-lengths! name n . xss)
(for: ([xs (in-list xss)])
(unless (fx= n (flvector-length xs))
(raise-length-error name "FlVector" xs n))))

View File

@ -6,7 +6,7 @@
racket/future racket/future
"../../base.rkt" "../../base.rkt"
"../../flonum.rkt" "../../flonum.rkt"
"../../parameters.rkt" "../parameters.rkt"
"../unsafe.rkt") "../unsafe.rkt")
(provide vector-fft flvector-fft! (provide vector-fft flvector-fft!

View File

@ -7,8 +7,9 @@
(only-in typed/racket/base (only-in typed/racket/base
ann inst : λ: define: make-predicate -> ann inst : λ: define: make-predicate ->
Flonum Real Boolean Any Integer Index Natural Exact-Positive-Integer Flonum Real Boolean Any Integer Index Natural Exact-Positive-Integer
Nonnegative-Real Sequenceof Fixnum Values Number Nonnegative-Real Sequenceof Fixnum Values Number Float-Complex
All U List Vector Listof Vectorof Struct)) All U List Vector Listof Vectorof Struct FlVector
Symbol Output-Port))
"utils.rkt") "utils.rkt")
@(define typed-eval (make-math-eval)) @(define typed-eval (make-math-eval))
@ -30,15 +31,20 @@ For now, if you need speed, use the @racketmodname[typed/racket] language.
@defmodule[math/array] @defmodule[math/array]
One of the most common ways to structure data is with an array: a grid of homogeneous, One of the most common ways to structure data is with an array: a rectangular grid of
independent elements, usually consisting of rows and columns. But an array data type homogeneous, independent elements. But an array data type
is usually absent from functional languages' libraries. This is probably because arrays is usually absent from functional languages' libraries. This is probably because arrays
are perceived as requiring users to operate on them using destructive updates, write are perceived as requiring users to operate on them using destructive updates, write
loops that micromanage array elements, and in general, stray far from the declarative loops that micromanage array elements, and in general, stray far from the declarative
ideal. ideal.
@margin-note{TODO: Cite Haskell array paper} @(define array-pdf
Normally, they do. However, experience in Python, and more recently Data-Parallel Haskell, "http://research.microsoft.com/en-us/um/people/simonpj/papers/ndp/RArrays.pdf")
@margin-note*{* @bold{Regular, shape-polymorphic, parallel arrays in Haskell},
Gabriele Keller, Manuel Chakravarty, Roman Leshchinskiy, Simon Peyton Jones,
and Ben Lippmeier. ICFP 2010. @hyperlink[array-pdf]{(PDF)}}
Normally, they do. However, experience in Python, and more recently Data-Parallel Haskell*,
has shown that providing the right data types and a rich collection of whole-array operations has shown that providing the right data types and a rich collection of whole-array operations
allows working effectively with arrays in a functional, declarative style. As a bonus, allows working effectively with arrays in a functional, declarative style. As a bonus,
doing so opens the possibility of parallelizing nearly every operation. doing so opens the possibility of parallelizing nearly every operation.
@ -277,6 +283,14 @@ because @racket[nums]'s second axis was stretched during broadcasting. Also, the
@racket[#[#["aa"] #["ba"] #["ca"]]] in @racket[lets] is repeated because @racket[lets]'s first @racket[#[#["aa"] #["ba"] #["ca"]]] in @racket[lets] is repeated because @racket[lets]'s first
axis was stretched. axis was stretched.
Even more concretely:
@interaction[#:eval typed-eval
(define ds
(array-shape-broadcast (list (array-shape nums) (array-shape lets))))
ds
(array-broadcast nums ds)
(array-broadcast lets ds)]
@subsubsection[#:tag "array:broadcasting:control"]{Broadcasting Control} @subsubsection[#:tag "array:broadcasting:control"]{Broadcasting Control}
The parameter @racket[array-broadcasting] controls how pointwise operations @tech{broadcast} The parameter @racket[array-broadcasting] controls how pointwise operations @tech{broadcast}
@ -514,17 +528,17 @@ Returns an array with @tech{shape} @racket[ds] and @tech{procedure} @racket[proc
Analogous to @racket[build-vector], but the result is @tech{non-strict}. Analogous to @racket[build-vector], but the result is @tech{non-strict}.
@examples[#:eval typed-eval @examples[#:eval typed-eval
(eval:alts (eval:alts
(define: fibs : (Array Exact-Positive-Integer) (define: fibs : (Array Natural)
(build-array (build-array
#(10) (λ: ([js : Indexes]) #(10) (λ: ([js : Indexes])
(define j (vector-ref js 0)) (define j (vector-ref js 0))
(cond [(j . < . 2) 1] (cond [(j . < . 2) j]
[else (+ (array-ref fibs (vector (- j 1))) [else (+ (array-ref fibs (vector (- j 1)))
(array-ref fibs (vector (- j 2))))])))) (array-ref fibs (vector (- j 2))))]))))
(void)) (void))
(eval:alts (eval:alts
fibs fibs
(ann (array #[1 1 2 3 5 8 13 21 34 55]) (Array Exact-Positive-Integer)))] (ann (array #[0 1 1 2 3 5 8 13 21 34]) (Array Natural)))]
Because @racket[build-array] returns a non-strict array, @racket[fibs] may refer to itself Because @racket[build-array] returns a non-strict array, @racket[fibs] may refer to itself
within its definition. Of course, this naïve implementation computes its elements in time within its definition. Of course, this naïve implementation computes its elements in time
exponential in the size of @racket[fibs]. A quick, widely applicable fix is given in exponential in the size of @racket[fibs]. A quick, widely applicable fix is given in
@ -550,18 +564,18 @@ The example in @racket[build-array]'s documentation computes the Fibonacci numbe
time. Speeding it up to linear time only requires wrapping its definition with @racket[array-lazy]: time. Speeding it up to linear time only requires wrapping its definition with @racket[array-lazy]:
@interaction[#:eval typed-eval @interaction[#:eval typed-eval
(eval:alts (eval:alts
(define: fibs : (Array Exact-Positive-Integer) (define: fibs : (Array Natural)
(array-lazy (array-lazy
(build-array (build-array
#(10) (λ: ([js : Indexes]) #(10) (λ: ([js : Indexes])
(define j (vector-ref js 0)) (define j (vector-ref js 0))
(cond [(j . < . 2) 1] (cond [(j . < . 2) j]
[else (+ (array-ref fibs (vector (- j 1))) [else (+ (array-ref fibs (vector (- j 1)))
(array-ref fibs (vector (- j 2))))]))))) (array-ref fibs (vector (- j 2))))])))))
(void)) (void))
(eval:alts (eval:alts
fibs fibs
(ann (array #[1 1 2 3 5 8 13 21 34 55]) (Array Exact-Positive-Integer)))] (ann (array #[0 1 1 2 3 5 8 13 21 34]) (Array Natural)))]
Printing a lazy array computes and caches all of its elements, as does applying Printing a lazy array computes and caches all of its elements, as does applying
@racket[array-strict] to it. @racket[array-strict] to it.
} }
@ -633,6 +647,16 @@ have the value @racket[on-value]; the rest have the value @racket[off-value].
@section{Conversion} @section{Conversion}
@defform[(Listof* A)]{
Equivalent to @racket[(U A (Listof A) (Listof (Listof A)) ...)] if infinite unions were allowed.
This is used as an argument type to @racket[list*->array] and as the return type of
@racket[array->list*].
}
@defform[(Vectorof* A)]{
Like @racket[(Listof* A)], but for vectors. See @racket[vector*->array] and @racket[array->vector*].
}
@deftogether[(@defproc[(list->array [lst (Listof A)]) (Array A)] @deftogether[(@defproc[(list->array [lst (Listof A)]) (Array A)]
@defproc[(array->list [arr (Array A)]) (Listof A)])]{ @defproc[(array->list [arr (Array A)]) (Listof A)])]{
Convert lists to single-axis arrays and back. If @racket[arr] has no axes or more than one axis, Convert lists to single-axis arrays and back. If @racket[arr] has no axes or more than one axis,
@ -652,12 +676,6 @@ For conversion between nested lists and multidimensional arrays, see @racket[lis
Like @racket[list->array] and @racket[array->list], but for vectors. Like @racket[list->array] and @racket[array->list], but for vectors.
} }
@defform[(Listof* A)]{
Equivalent to @racket[(U A (Listof A) (Listof (Listof A)) ...)] if infinite unions were allowed.
This is used as an argument type to @racket[list*->array] and as the return type of
@racket[array->list*].
}
@defproc[(list*->array [lsts (Listof* A)] [pred? ((Listof* A) -> Any : A)]) (Array A)]{ @defproc[(list*->array [lsts (Listof* A)] [pred? ((Listof* A) -> Any : A)]) (Array A)]{
Converts a nested list of elements of type @racket[A] to an array. The predicate @racket[pred?] Converts a nested list of elements of type @racket[A] to an array. The predicate @racket[pred?]
identifies elements of type @racket[A]. The shape of @racket[lsts] must be rectangular. identifies elements of type @racket[A]. The shape of @racket[lsts] must be rectangular.
@ -676,10 +694,6 @@ without it, there is no way to distinguish between rows and elements.
The inverse of @racket[list*->array]. The inverse of @racket[list*->array].
} }
@defform[(Vectorof* A)]{
Like @racket[(Listof* A)], but for vectors. See @racket[vector*->array] and @racket[array->vector*].
}
@defproc[(vector*->array [vecs (Vectorof* A)] [pred? ((Vectorof* A) -> Any : A)]) (Array A)]{ @defproc[(vector*->array [vecs (Vectorof* A)] [pred? ((Vectorof* A) -> Any : A)]) (Array A)]{
Like @racket[list*->array], but accepts nested vectors of elements. Like @racket[list*->array], but accepts nested vectors of elements.
@examples[#:eval typed-eval @examples[#:eval typed-eval
@ -725,10 +739,12 @@ The axis number @racket[axis] must be nonnegative and less than the number of @r
@defparam[array-custom-printer @defparam[array-custom-printer
print-array print-array
(All (A) ((Array A) Symbol Output-Port (U Boolean Zero One) -> Any))]{ (All (A) ((Array A)
A parameter that controls array printing. Symbol
Output-Port
(U Boolean 0 1) -> Any))]{
A parameter whose value is used to print subtypes of @racket[Array].
} }
(All (A) ((Array A) Symbol Output-Port (U Boolean Zero One) -> Any))
@defproc[(print-array [arr (Array A)] @defproc[(print-array [arr (Array A)]
[name Symbol] [name Symbol]
@ -737,16 +753,19 @@ A parameter that controls array printing.
Any]{ Any]{
Prints an array using @racket[array] syntax, using @racket[name] instead of @racket['array] Prints an array using @racket[array] syntax, using @racket[name] instead of @racket['array]
as the head form. This function is set as the value of @racket[array-custom-printer] when as the head form. This function is set as the value of @racket[array-custom-printer] when
@racketmodname[math/array] is required. @racketmodname[math/array] is first required.
Well-behaved @racket[Array] subtypes do not call this function directly to print themselves. Well-behaved @racket[Array] subtypes do not call this function directly to print themselves.
They call the current @racket[array-custom-printer]: They call the current @racket[array-custom-printer]:
@interaction[#:eval typed-eval @interaction[#:eval typed-eval
((array-custom-printer) (eval:alts
(array #[0 1 2 3]) ((array-custom-printer)
'my-cool-array (array #[0 1 2 3])
(current-output-port) 'my-cool-array
#t)] (current-output-port)
#t)
(eval:result "" "(my-cool-array #[0 1 2 3])"))]
See @racket[prop:custom-write] for the meaning of the @racket[port] and @racket[mode] arguments.
} }
@ -846,6 +865,9 @@ an error.
@examples[#:eval typed-eval @examples[#:eval typed-eval
(array-map (λ: ([x : String]) (string-append x "!")) (array-map (λ: ([x : String]) (string-append x "!"))
(array #[#["Hello" "I"] #["Am" "Shouting"]])) (array #[#["Hello" "I"] #["Am" "Shouting"]]))
(array-map string-append
(array #[#["Hello" "I"] #["Am" "Shouting"]])
(array "!"))
(array-map + (index-array #(3 3 3)) (array 2)) (array-map + (index-array #(3 3 3)) (array 2))
(array-map + (index-array #(2 2)) (index-array #(3 3)))] (array-map + (index-array #(2 2)) (index-array #(3 3)))]
@ -874,66 +896,6 @@ optimizer to replace @racket[f] with something unchecked and type-specific (for
replace @racket[*] with @racket[unsafe-fl*]), at the expense of code size. replace @racket[*] with @racket[unsafe-fl*]), at the expense of code size.
} }
@deftogether[(@defform[(array-abs arr)]
@defform[(array-round arr)]
@defform[(array-floor arr)]
@defform[(array-ceiling arr)]
@defform[(array-truncate arr)]
@defform[(array-sqrt arr)]
@defform[(array-sqr arr)]
@defform[(array-log arr)]
@defform[(array-exp arr)]
@defform[(array-sin arr)]
@defform[(array-cos arr)]
@defform[(array-tan arr)]
@defform[(array-asin arr)]
@defform[(array-acos arr)]
@defform[(array-atan arr)]
@defform[(array-inexact->exact arr)]
@defform[(array-exact->inexact arr)]
@defform[(array-fl arr)])]{
Equivalent to @racket[(array-map f arr)], where @racket[f] is respectively
@racket[abs],
@racket[round],
@racket[floor],
@racket[ceiling],
@racket[truncate],
@racket[sqrt],
@racket[sqr],
@racket[log],
@racket[exp],
@racket[sin],
@racket[cos],
@racket[tan],
@racket[asin],
@racket[acos],
@racket[atan],
@racket[inexact->exact],
@racket[exact->inexact],
or @racket[fl].
Instead of @racket[array-fl], you might consider using @racket[array->flarray], which returns
a mutable array of flonums, stored unboxed in an flvector.
}
@deftogether[(@defform[(array-magnitude arr)]
@defform[(array-angle arr)]
@defform[(array-conjugate arr)]
@defform[(array-real-part arr)]
@defform[(array-imag-part arr)]
@defform[(array-fc arr)])]{
Equivalent to @racket[(array-map f arr)], where @racket[f] is respectively
@racket[magnitude],
@racket[angle],
@racket[conjugate],
@racket[real-part],
@racket[imag-part],
or @racket[number->float-complex].
Instead of @racket[array-fc], you might consider using @racket[array->fcarray], which returns
a mutable array of float-complex numbers, stored unboxed in a pair of flvectors.
}
@deftogether[(@defform[(array+ arrs ...)] @deftogether[(@defform[(array+ arrs ...)]
@defform[(array* arrs ...)] @defform[(array* arrs ...)]
@defform[(array- arr0 arrs ...)] @defform[(array- arr0 arrs ...)]
@ -953,10 +915,24 @@ returns sensible answers, so do @racket[(array+)] and @racket[(array*)].
Equivalent to @racket[(array* arr (array x))], but faster. Equivalent to @racket[(array* arr (array x))], but faster.
} }
@deftogether[(@defform[(array-expt arr0 arr1)] @deftogether[(@defform[(array-abs arr)]
@defform[(array-make-rectangular arr0 arr1)])]{ @defform[(array-sqr arr)]
Equivalent to @racket[(array-map expt arr0 arr1)] and @defform[(array-sqrt arr)]
@racket[(array-map make-rectangular arr0 arr1)], respectively. @defform[(array-conjugate arr)])]{
Equivalent to @racket[(array-map f arr)], where @racket[f] is respectively
@racket[abs],
@racket[sqr],
@racket[sqrt],
or @racket[conjugate].
}
@deftogether[(@defform[(array-real-part arr)]
@defform[(array-imag-part arr)]
@defform[(array-make-rectangular arr0 arr1)]
@defform[(array-magnitude arr)]
@defform[(array-angle arr)]
@defform[(array-make-polar arr0 arr1)])]{
Conversions to and from complex numbers, lifted to operate on arrays.
} }
@deftogether[(@defform[(array< arr0 arr1 arrs ...)] @deftogether[(@defform[(array< arr0 arr1 arrs ...)]
@ -972,7 +948,7 @@ Equivalent to @racket[(array-map f arr0 arr1 arrs ...)], where @racket[f] is res
@defform[(array-and arr ...)] @defform[(array-and arr ...)]
@defform[(array-or arr ...)] @defform[(array-or arr ...)]
@defform[(array-if cond-arr true-arr false-err)])]{ @defform[(array-if cond-arr true-arr false-err)])]{
@racket[not], @racket[and], @racket[or] and @racket[if] lifted to operate on arrays. Boolean operators lifted to operate on arrays.
The short-cutting behavior of @racket[array-and], @racket[array-or] and @racket[array-if] The short-cutting behavior of @racket[array-and], @racket[array-or] and @racket[array-if]
can keep array arguments' elements from being referred to (and thus computed). However, can keep array arguments' elements from being referred to (and thus computed). However,
@ -1061,6 +1037,7 @@ If @racket[idxs] and @racket[vals] do not have the same shape, they are @tech{br
(define idxs (array #['#(0 0) '#(1 1)])) (define idxs (array #['#(0 0) '#(1 1)]))
(array-indexes-set! arr idxs (array -1)) (array-indexes-set! arr idxs (array -1))
arr] arr]
When indexes are repeated in @racket[idxs], they are mutated in some unspecified order.
} }
@defproc[(array-slice-ref [arr (Array A)] [specs (Listof Slice-Spec)]) (Array A)]{ @defproc[(array-slice-ref [arr (Array A)] [specs (Listof Slice-Spec)]) (Array A)]{
@ -1068,17 +1045,19 @@ Returns a transformation of @racket[arr] according to the list of slice specific
@racket[specs]. See @secref{array:slice-specs} for documentation and examples. @racket[specs]. See @secref{array:slice-specs} for documentation and examples.
} }
@defproc[(slice-indexes-array [ds In-Indexes] [specs (Listof Slice-Spec)]) (Array Indexes)]{
Returns the indexes of the elements that would be retrieved if an array with shape @racket[ds]
were sliced according to @racket[specs].
Equivalent to @racketblock[(array-slice-ref (indexes-array ds) specs)]
}
@defproc[(array-slice-set! [arr (Settable-Array A)] [specs (Listof Slice-Spec)] [vals (Array A)]) @defproc[(array-slice-set! [arr (Settable-Array A)] [specs (Listof Slice-Spec)] [vals (Array A)])
Void]{ Void]{
Like @racket[array-indexes-set!], but for slice specifications. Equivalent to Like @racket[array-indexes-set!], but for slice specifications. Equivalent to
@racketblock[(let ([idxs (slice-indexes-array (array-shape arr) specs)]) @racketblock[(let ([idxs (slice-indexes-array (array-shape arr) specs)])
(array-indexes-set! arr idxs vals))] (array-indexes-set! arr idxs vals))]
When a slice specification refers to an element in @racket[arr] more than once, the element is
mutated more than once in some unspecified order.
}
@defproc[(slice-indexes-array [ds In-Indexes] [specs (Listof Slice-Spec)]) (Array Indexes)]{
Returns the indexes of the elements that would be retrieved if an array with shape @racket[ds]
were sliced according to @racket[specs].
Equivalent to @racketblock[(array-slice-ref (indexes-array ds) specs)]
} }
@subsection[#:tag "array:slice-specs"]{Slice Specifications} @subsection[#:tag "array:slice-specs"]{Slice Specifications}
@ -1217,10 +1196,10 @@ Removing the second axis by collapsing it to the row with index @racket[1]:
Removing the second-to-last axis (which for @racket[arr] is the same as the second): Removing the second-to-last axis (which for @racket[arr] is the same as the second):
@interaction[#:eval typed-eval @interaction[#:eval typed-eval
(array-slice-ref arr (list ::... 1 (::)))] (array-slice-ref arr (list ::... 1 (::)))]
All of these examples can be done using @racket[array-axis-ref], but including it in slice All of these examples can be done using @racket[array-axis-ref]. However, removing an axis
specifications can be handy: relative to the dimension of the array (e.g. the second-to-last axis) is easier to do
@interaction[#:eval typed-eval using @racket[array-slice-ref], and it is sometimes convenient to combine axis removal with
(array-slice-ref arr (list ::... 1 (:: #f #f 2)))] other slice operations.
@subsubsection{@racket[Slice-New-Axis]: add an axis} @subsubsection{@racket[Slice-New-Axis]: add an axis}
@ -1570,10 +1549,31 @@ Every fold, including @racket[array-axis-fold], is ultimately defined using
@section{Other Array Operations} @section{Other Array Operations}
@;{array-fft @subsection{Fast Fourier Transform}
array-inverse-fft
array-axis-fft @margin-note{Wikipedia: @hyperlink["http://wikipedia.org/wiki/Discrete_Fourier_transform"]{Discrete
array-axis-inverse-fft Fourier Transform}}
@defproc[(array-axis-fft [arr (Array Number)] [k Integer]) (Array Float-Complex)]{
Performs a discrete Fourier transform on axis @racket[k] of @racket[arr]. The length of @racket[k]
must be an integer power of two. (See @racket[power-of-two?].) The scaling convention is
determined by the parameter @racket[dft-convention], which defaults to the convention used in
signal processing.
The transform is done in parallel using @racket[max-math-threads] threads.
}
@defproc[(array-axis-inverse-fft [arr (Array Number)] [k Integer]) (Array Float-Complex)]{
The inverse of @racket[array-axis-fft], performed by parameterizing the forward transform on
@racket[(dft-inverse-convention)].
}
@defproc[(array-fft [arr (Array Number)]) FCArray]{
Performs a discrete Fourier transform on each axis of @racket[arr] using @racket[array-axis-fft].
}
@defproc[(array-inverse-fft [arr (Array Number)]) FCArray]{
The inverse of @racket[array-fft], performed by parameterizing the forward transform on
@racket[(dft-inverse-convention)].
} }
@ -1585,100 +1585,143 @@ array-axis-inverse-fft
@subsection{Flonum Arrays} @subsection{Flonum Arrays}
@defidform[FlArray]{ @defidform[FlArray]{
The type of @deftech{flonum arrays}, a subtype of @racket[(Settable-Array Flonum)] that stores its
elements in an @racket[FlVector]. A flonum array is always strict.
}
@defform[(flarray #[#[...] ...])]{
Like @racket[array], but creates @tech{flonum arrays}. The listed elements must be real numbers,
and may be exact.
@examples[#:eval typed-eval
(flarray 0.0)
(flarray #['x])
(flarray #[#[1 2] #[3 4]])]
} }
@defproc[(array->flarray [arr (Array Real)]) FlArray]{ @defproc[(array->flarray [arr (Array Real)]) FlArray]{
Returns an flonum array that has approximately the same elements as @racket[arr]. Returns a flonum array that has approximately the same elements as @racket[arr]. Exact
The elements may lose precision during the conversion. elements will likely lose precision during conversion.
} }
@;{ @defproc[(flarray-data [arr FlArray]) FlVector]{
FlArray Returns the elements of @racket[arr] in a flonum vector, in row-major order.
flarray-scale @examples[#:eval typed-eval
flarray-round (flvector->list (flarray-data (flarray #[#[1 2] #[3 4]])))]
flarray-floor }
flarray-map
flarray-truncate @defproc[(flarray-map [f (Flonum ... -> Flonum)] [arrs FlArray] ...) FlArray]{
flarray-abs Maps the function @racket[f] over the arrays @racket[arrs]. If the arrays do not have the same
flarray-sqr shape, they are @tech{broadcast} first. If the arrays do have the same shape, this operation can
flarray-sqrt be quite fast.
flarray-log
flarray-exp The function @racket[f] is meant to accept the same number of arguments as the number of its
flarray-sin following flonum array arguments. However, a current limitation in Typed Racket requires @racket[f]
flarray-cos to accept @italic{any} number of arguments. To map a single-arity function such as @racket[fl+],
flarray-tan for now, use @racket[inline-flarray-map] or @racket[array-map].
flarray-asin }
flarray-acos
flarray-atan @defform[(inline-flarray-map f arrs ...)
flarray+ #:contracts ([f (Flonum ... -> Flonum)]
flarray* [arrs FlArray])]{
flarray-data Like @racket[inline-array-map], but for flonum arrays.
flarray
flarray-ceiling @bold{This is currently unavailable in untyped Racket.}
array->flarray }
inline-flarray-map
flarray- @deftogether[(@defproc[(flarray+ [arr0 FlArray] [arr1 FlArray]) FlArray]
flarray/ @defproc[(flarray* [arr0 FlArray] [arr1 FlArray]) FlArray]
flarray-expt @defproc*[([(flarray- [arr FlArray]) FlArray]
flarray-min [(flarray- [arr0 FlArray] [arr1 FlArray]) FlArray])]
flarray-max @defproc*[([(flarray/ [arr FlArray]) FlArray]
flarray= [(flarray/ [arr0 FlArray] [arr1 FlArray]) FlArray])]
flarray< @defproc[(flarray-min [arr0 FlArray] [arr1 FlArray]) FlArray]
flarray<= @defproc[(flarray-max [arr0 FlArray] [arr1 FlArray]) FlArray]
flarray> @defproc[(flarray-scale [arr FlArray] [x Flonum]) FlArray]
flarray>= @defproc[(flarray-abs [arr FlArray]) FlArray]
@defproc[(flarray-sqr [arr FlArray]) FlArray]
@defproc[(flarray-sqrt [arr FlArray]) FlArray])]{
Arithmetic lifted to flonum arrays.
} }
@subsection{Float-Complex Arrays} @subsection{Float-Complex Arrays}
@defidform[FCArray]{ @defidform[FCArray]{
The type of @deftech{float-complex arrays}, a subtype of @racket[(Settable-Array Float-Complex)]
that stores its elements in a pair of @racket[FlVector]s. A float-complex array is always strict.
}
@defform[(fcarray #[#[...] ...])]{
Like @racket[array], but creates @tech{float-complex arrays}. The listed elements must be numbers,
and may be exact.
@examples[#:eval typed-eval
(fcarray 0.0)
(fcarray #['x])
(fcarray #[#[1 2+1i] #[3 4+3i]])]
} }
@defproc[(array->fcarray [arr (Array Number)]) FCArray]{ @defproc[(array->fcarray [arr (Array Number)]) FCArray]{
Returns a float-complex array that has approximately the same elements as @racket[arr]. Returns a float-complex array that has approximately the same elements as @racket[arr]. Exact
The elements may lose precision during the conversion. elements will likely lose precision during conversion.
} }
@;{ @deftogether[(@defproc[(fcarray-real-data [arr FCArray]) FlVector]
FCArray @defproc[(fcarray-imag-data [arr FCArray]) FlVector])]{
fcarray-fft Return the real and imaginary parts of @racket[arr]'s elements in flonum vectors, in row-major order.
inline-fcarray-map @examples[#:eval typed-eval
fcarray-imag-data (define arr (fcarray #[#[1 2+1i] #[3 4+3i]]))
fcarray-real-data (flvector->list (fcarray-real-data arr))
fcarray (flvector->list (fcarray-imag-data arr))]
array->fcarray
fcarray-scale
fcarray-sqr
fcarray-sqrt
fcarray-conjugate
fcarray-magnitude
fcarray-angle
fcarray-exp
fcarray-sin
fcarray-cos
fcarray-tan
fcarray-acos
fcarray+
fcarray*
fcarray-
fcarray/
fcarray-expt
fcarray-real-part
fcarray-imag-part
fcarray-make-rectangular
fcarray-map
fcarray-log
fcarray-asin
fcarray-atan
} }
@defproc[(fcarray-map [f (Float-Complex ... -> Float-Complex)] [arrs FCArray] ...) FCArray]{
Maps the function @racket[f] over the arrays @racket[arrs]. If the arrays do not have the same
shape, they are @tech{broadcast} first. If the arrays do have the same shape, this operation can
be quite fast.
The function @racket[f] is meant to accept the same number of arguments as the number of its
following float-complex array arguments. However, a current limitation in Typed Racket requires
@racket[f] to accept @italic{any} number of arguments. To map a single-arity function, for now,
use @racket[inline-fcarray-map] or @racket[array-map].
}
@defform[(inline-fcarray-map f arrs ...)
#:contracts ([f (Float-Complex ... -> Float-Complex)]
[arrs FCArray])]{
Like @racket[inline-array-map], but for float-complex arrays.
@bold{This is currently unavailable in untyped Racket.}
}
@deftogether[(@defproc[(fcarray+ [arr0 FCArray] [arr1 FCArray]) FCArray]
@defproc[(fcarray* [arr0 FCArray] [arr1 FCArray]) FCArray]
@defproc*[([(fcarray- [arr FCArray]) FCArray]
[(fcarray- [arr0 FCArray] [arr1 FCArray]) FCArray])]
@defproc*[([(fcarray/ [arr FCArray]) FCArray]
[(fcarray/ [arr0 FCArray] [arr1 FCArray]) FCArray])]
@defproc[(fcarray-scale [arr FCArray] [z Float-Complex]) FCArray]
@defproc[(fcarray-sqr [arr FCArray]) FCArray]
@defproc[(fcarray-sqrt [arr FCArray]) FCArray]
@defproc[(fcarray-conjugate [arr FCArray]) FCArray])]{
Arithmetic lifted to float-complex arrays.
}
@deftogether[(@defproc[(fcarray-real-part [arr FCArray]) FlArray]
@defproc[(fcarray-imag-part [arr FCArray]) FlArray]
@defproc[(fcarray-make-rectangular [arr0 FlArray] [arr1 FlArray]) FCArray]
@defproc[(fcarray-magnitude [arr FCArray]) FlArray]
@defproc[(fcarray-angle [arr FCArray]) FlArray]
@defproc[(fcarray-make-polar [arr0 FlArray] [arr1 FlArray]) FCArray])]{
Conversions to and from complex numbers, lifted to flonum and float-complex arrays.
}
@;{==================================================================================================} @;{==================================================================================================}
@;{
@section{Unsafe Operations} @section{Unsafe Operations}
@;{
unsafe-array-ref unsafe-array-ref
unsafe-array-set! unsafe-array-set!
unsafe-array-proc unsafe-array-proc

View File

@ -22,7 +22,7 @@ as well as providing the values document below.
In general, the functions provided by @racketmodname[math/base] are @deftech{elementary} In general, the functions provided by @racketmodname[math/base] are @deftech{elementary}
functions, or those functions that can be defined in terms of a finite number of functions, or those functions that can be defined in terms of a finite number of
arithmetic operations, logarithms, exponentials, trigonometric functions, and constants. arithmetic operations, logarithms, exponentials, trigonometric functions, and constants.
For others, see @racketmodname[math/special-functions]. For others, see @racketmodname[math/special-functions] and @racketmodname[math/distributions].
@section{Constants} @section{Constants}

View File

@ -31,6 +31,8 @@ for Windows and Mac OS X, is installed on most Linux systems, and is
@hyperlink["http://www.mpfr.org/ports.html"]{easy to install} on all major platforms. @hyperlink["http://www.mpfr.org/ports.html"]{easy to install} on all major platforms.
See @secref{loading} for details. See @secref{loading} for details.
@local-table-of-contents[]
@section[#:tag "quick"]{Quick Start} @section[#:tag "quick"]{Quick Start}
@itemlist[#:style 'ordered @itemlist[#:style 'ordered

View File

@ -216,10 +216,10 @@ ordered distribution returns as random samples. Additionally, its @tech{cdf} acc
(ordered-dist? (discrete-dist '(a b c))) (ordered-dist? (discrete-dist '(a b c)))
(ordered-dist? (normal-dist))] (ordered-dist? (normal-dist))]
The median is stored in an @racket[ordered-dist] to allow interval probabilities to be calculated The median is stored in an @racket[ordered-dist] to allow interval probabilities to be computed
accurately. For example, for @racket[d = (normal-dist)], whose median is @racket[0.0], accurately. For example, for @racket[d = (normal-dist)], whose median is @racket[0.0],
@racket[(real-dist-prob d -2.0 -1.0)] is calculated using lower-tail probabilities, and @racket[(real-dist-prob d -2.0 -1.0)] is computed using lower-tail probabilities, and
@racket[(real-dist-prob d 1.0 2.0)] is calculated using upper-tail probabilities. @racket[(real-dist-prob d 1.0 2.0)] is computed using upper-tail probabilities.
} }
@defidform[Real-Dist]{ @defidform[Real-Dist]{
@ -280,6 +280,9 @@ The first four are synonyms for @racket[ordered-dist-cdf], @racket[ordered-dist-
(Discrete-Dist A)])] (Discrete-Dist A)])]
@defproc[(discrete-dist-values [d (Discrete-Dist A)]) (Listof A)] @defproc[(discrete-dist-values [d (Discrete-Dist A)]) (Listof A)]
@defproc[(discrete-dist-probs [d (Discrete-Dist A)]) (Listof Positive-Flonum)])]{ @defproc[(discrete-dist-probs [d (Discrete-Dist A)]) (Listof Positive-Flonum)])]{
@bold{Warning:} The types and functions for discrete distributions will probably change soon,
as part of overhauling how @racket[math/statistics] handles weighted samples.
Represents families of unordered, discrete distributions over values of type @racket[A], with equality Represents families of unordered, discrete distributions over values of type @racket[A], with equality
decided by @racket[equal?]. decided by @racket[equal?].
@ -311,8 +314,7 @@ or over extended integers. The most common definitions use the extended reals, s
@tech{distribution object} constructors return objects of type @racket[Real-Dist]. @tech{distribution object} constructors return objects of type @racket[Real-Dist].
(Another reason is that the extended integers correspond with the type (Another reason is that the extended integers correspond with the type
@racket[(U Integer +inf.0 -inf.0)]. Values of this type are difficult to use as integers: in @racket[(U Integer +inf.0 -inf.0)]. Values of this type have little support in Racket's library.)
practice, they are the same as values of type @racket[Real].)
This leaves us with a quandary and two design decisions users should be aware of. The quandary is This leaves us with a quandary and two design decisions users should be aware of. The quandary is
that, when an integer distribution is defined over the reals, it has a @tech{cdf}, but @italic{no that, when an integer distribution is defined over the reals, it has a @tech{cdf}, but @italic{no
@ -422,7 +424,7 @@ independent events.
@section{Real Distribution Families} @section{Real Distribution Families}
The @tech{distribution object} constructors documented in this section return unique, useful The @tech{distribution object} constructors documented in this section return uniquely defined
distributions for the largest possible parameter domain. This usually means that they return distributions for the largest possible parameter domain. This usually means that they return
distributions for a larger domain than their mathematical counterparts are defined on. distributions for a larger domain than their mathematical counterparts are defined on.
@ -523,18 +525,13 @@ Represents the Cauchy distribution family parameterized by mode and scale.
Represents the family of distributions whose densities are Dirac delta functions. Represents the family of distributions whose densities are Dirac delta functions.
@examples[#:eval untyped-eval @examples[#:eval untyped-eval
((dist-pdf (delta-dist)) 0) (pdf (delta-dist) 0)
((dist-pdf (delta-dist)) 1) (pdf (delta-dist) 1)
(plot (for/list ([μ (in-list '(-1 0 1))] (plot (for/list ([μ (in-list '(-1 0 1))]
[i (in-naturals)]) [i (in-naturals)])
(function (dist-cdf (delta-dist μ)) (function (dist-cdf (delta-dist μ))
#:color i #:style i #:label (format "δ(~a)" μ))) #:color i #:style i #:label (format "δ(~a)" μ)))
#:x-min -2 #:x-max 2 #:y-label "probability")] #:x-min -2 #:x-max 2 #:y-label "probability")]
When a distribution with a scale parameter has scale zero, it behaves like a delta distribution:
@interaction[#:eval untyped-eval
((dist-pdf (normal-dist 0 0)) 0)
((dist-pdf (normal-dist 0 0)) 1)
(plot (function (dist-cdf (normal-dist 0 0)) -1e-300 1e-300))]
} }
@subsection{Exponential Distributions} @subsection{Exponential Distributions}
@ -548,7 +545,7 @@ When a distribution with a scale parameter has scale zero, it behaves like a del
Represents the exponential distribution family parameterized by mean, or scale. Represents the exponential distribution family parameterized by mean, or scale.
@bold{Warning:} The exponential distribution family is often parameterized by @italic{rate}, which @bold{Warning:} The exponential distribution family is often parameterized by @italic{rate}, which
is the reciprocal of mean or scale. If you have rates, construct exponential distributions using is the reciprocal of mean or scale. Construct exponential distributions from rates using
@racketblock[(exponential-dist (/ 1.0 rate))] @racketblock[(exponential-dist (/ 1.0 rate))]
@examples[#:eval untyped-eval @examples[#:eval untyped-eval
@ -579,7 +576,7 @@ Represents the gamma distribution family parameterized by shape and scale. The @
parameter must be nonnegative. parameter must be nonnegative.
@bold{Warning:} The gamma distribution family is often parameterized by shape and @italic{rate}, @bold{Warning:} The gamma distribution family is often parameterized by shape and @italic{rate},
which is the reciprocal of scale. If you have rates, construct gamma distributions using which is the reciprocal of scale. Construct gamma distributions from rates using
@racketblock[(gamma-dist shape (/ 1.0 rate))] @racketblock[(gamma-dist shape (/ 1.0 rate))]
@examples[#:eval untyped-eval @examples[#:eval untyped-eval
@ -648,8 +645,7 @@ and scale. In this parameterization, the variance is @racket[(* 1/3 (sqr (* pi s
Represents the normal distribution family parameterized by mean and standard deviation. Represents the normal distribution family parameterized by mean and standard deviation.
@bold{Warning:} The normal distribution family is often parameterized by mean and @italic{variance}, @bold{Warning:} The normal distribution family is often parameterized by mean and @italic{variance},
which is the square of standard deviation. If you have variances, construct normal distributions which is the square of standard deviation. Construct normal distributions from variances using
using
@racketblock[(normal-dist mean (sqrt var))] @racketblock[(normal-dist mean (sqrt var))]
@examples[#:eval untyped-eval @examples[#:eval untyped-eval
@ -776,7 +772,7 @@ distribution centered at @racket[x].
@section[#:tag "dist:flonum"]{Low-Level Distribution Functions} @section[#:tag "dist:flonum"]{Low-Level Distribution Functions}
The following functions are provided for users who need lower overhead than that of The following functions are provided for users who need lower overhead than that of
@tech{distribution objects}, such as (currently) untyped Racket users, and library writers who @tech{distribution objects}, such as untyped Racket users (currently), and library writers who
are implementing their own distribution abstractions. are implementing their own distribution abstractions.
Because applying these functions is meant to be fast, none of them have optional arguments. In Because applying these functions is meant to be fast, none of them have optional arguments. In
@ -854,7 +850,7 @@ Low-level flonum functions used to implement @racket[cauchy-dist].
@defproc[(fldelta-inv-cdf [mean Flonum] [p Flonum] [log? Any] [1-p? Any]) Flonum])]{ @defproc[(fldelta-inv-cdf [mean Flonum] [p Flonum] [log? Any] [1-p? Any]) Flonum])]{
Low-level flonum functions used to implement @racket[delta-dist]. Low-level flonum functions used to implement @racket[delta-dist].
If you need delta-distributed random samples, use @racket[(make-flvector n mean)]. To get delta-distributed random samples, use @racket[(make-flvector n mean)].
} }
@deftogether[ @deftogether[

View File

@ -2,12 +2,15 @@
@(require scribble/eval @(require scribble/eval
racket/sandbox racket/sandbox
(for-label racket/base (for-label racket/base racket/vector racket/list
math plot math plot
(only-in typed/racket/base Flonum Real Boolean Any Listof Integer)) (only-in typed/racket/base
->
Flonum Integer Index Real Boolean Any Listof Vectorof FlVector))
"utils.rkt") "utils.rkt")
@(define untyped-eval (make-untyped-math-eval)) @(define untyped-eval (make-untyped-math-eval))
@interaction-eval[#:eval untyped-eval (require racket/list)]
@title[#:tag "flonum"]{Flonums} @title[#:tag "flonum"]{Flonums}
@(author-neil) @(author-neil)
@ -17,6 +20,8 @@
For convenience, @racketmodname[math/flonum] re-exports @racketmodname[racket/flonum] For convenience, @racketmodname[math/flonum] re-exports @racketmodname[racket/flonum]
as well as providing the functions document below. as well as providing the functions document below.
@local-table-of-contents[]
@section{Additional Flonum Functions} @section{Additional Flonum Functions}
@defproc[(fl [x Real]) Flonum]{ @defproc[(fl [x Real]) Flonum]{
@ -61,6 +66,8 @@ The @racket[sum] function does the same for heterogenous lists of reals.
Worst-case time complexity is O(@italic{n}@superscript{2}), though the pathological Worst-case time complexity is O(@italic{n}@superscript{2}), though the pathological
inputs needed to observe quadratic time are exponentially improbable and are hard inputs needed to observe quadratic time are exponentially improbable and are hard
to generate purposely. Expected time complexity is O(@italic{n} log(@italic{n})). to generate purposely. Expected time complexity is O(@italic{n} log(@italic{n})).
See @racket[flvector-sums] for a variant that computes all the partial sums in @racket[xs].
} }
@deftogether[(@defproc[(flsinh [x Flonum]) Flonum] @deftogether[(@defproc[(flsinh [x Flonum]) Flonum]
@ -496,4 +503,89 @@ it is not zero and @racket[((abs x) . <= . +max-subnormal.0)].
@examples[#:eval untyped-eval +max-subnormal.0] @examples[#:eval untyped-eval +max-subnormal.0]
} }
@section{Additional Flonum Vector Functions}
@defproc[(build-flvector [n Integer] [proc (Index -> Flonum)]) FlVector]{
Creates a length-@racket[n] flonum vector by applying @racket[proc] to the indexes
from @racket[0] to @racket[(- n 1)]. Analogous to @racket[build-vector].
@examples[#:eval untyped-eval
(flvector->list (build-flvector 10 fl))]
}
@defform[(inline-build-flvector n proc)
#:contracts ([n Integer]
[proc (Index -> Flonum)])]{
Like @racket[build-flvector], but always inlined. This increases speed at the expense of code size.
}
@defproc[(flvector-map [proc (Flonum Flonum ... -> Flonum)] [xs FlVector] [xss FlVector] ...)
FlVector]{
Applies @racket[proc] to the corresponding elements of @racket[xs] and @racket[xss]. Analogous to
@racket[vector-map].
The @racket[proc] is meant to accept the same number of arguments as the number of its following
flonum vector arguments. However, a current limitation in Typed Racket requires @racket[proc]
to accept @italic{any} number of arguments. To map a single-arity function such as @racket[fl+]
over the corresponding number of flonum vectors, for now, use @racket[inline-flvector-map].
}
@defform[(inline-flvector-map proc xs xss ...)
#:contracts ([proc (Flonum Flonum ... -> Flonum)]
[xs FlVector]
[xss FlVector])]{
Like @racket[flvector-map], but always inlined.
}
@defproc[(flvector-copy! [dest FlVector]
[dest-start Integer]
[src FlVector]
[src-start Integer 0]
[src-end Integer (flvector-length src)])
Void]{
Like @racket[vector-copy!], but for flonum vectors.
}
@deftogether[(@defproc[(list->flvector [vs (Listof Real)]) FlVector]
@defproc[(flvector->list [xs FlVector]) (Listof Flonum)]
@defproc[(vector->flvector [vs (Vectorof Real)]) FlVector]
@defproc[(flvector->vector [xs FlVector]) (Vectorof Flonum)])]{
Convert between lists and flonum vectors, and between vectors and flonum vectors.
}
@deftogether[(@defproc[(flvector+ [xs FlVector] [ys FlVector]) FlVector]
@defproc[(flvector* [xs FlVector] [ys FlVector]) FlVector]
@defproc*[([(flvector- [xs FlVector]) FlVector]
[(flvector- [xs FlVector] [ys FlVector]) FlVector])]
@defproc*[([(flvector/ [xs FlVector]) FlVector]
[(flvector/ [xs FlVector] [ys FlVector]) FlVector])]
@defproc[(flvector-scale [xs FlVector] [y Flonum]) FlVector]
@defproc[(flvector-abs [xs FlVector]) FlVector]
@defproc[(flvector-sqr [xs FlVector]) FlVector]
@defproc[(flvector-sqrt [xs FlVector]) FlVector]
@defproc[(flvector-min [xs FlVector] [ys FlVector]) FlVector]
@defproc[(flvector-max [xs FlVector] [ys FlVector]) FlVector])]{
Arithmetic lifted to operate on flonum vectors.
}
@defproc[(flvector-sum [xs FlVector]) Flonum]{
Like @racket[flsum], but operates on flonum vectors. In fact, @racket[flsum] is defined in terms
of @racket[flvector-sum].
}
@defproc[(flvector-sums [xs FlVector]) FlVector]{
Computes the partial sums of the elements in @racket[xs] in a way that incurs rounding error only
once for each partial sum.
@examples[#:eval untyped-eval
(flvector->list
(flvector-sums
(flvector 1.0 1e-16 1e-16 1e-16 1e-16 1e100 -1e100)))]
Compare the same example computed by direct summation:
@interaction[#:eval untyped-eval
(rest
(reverse
(foldl (λ (x xs) (cons (+ x (first xs)) xs))
(list 0.0)
'(1.0 1e-16 1e-16 1e-16 1e-16 1e100 -1e100))))]
}
@(close-eval untyped-eval) @(close-eval untyped-eval)

View File

@ -2,7 +2,7 @@
@(require scribble/eval @(require scribble/eval
racket/sandbox racket/sandbox
(for-label racket/base (for-label racket/base racket/unsafe/ops
math plot math plot
(only-in typed/racket/base (only-in typed/racket/base
Flonum Real Integer Natural Zero Positive-Integer Exact-Rational Flonum Real Integer Natural Zero Positive-Integer Exact-Rational

View File

@ -17,10 +17,11 @@
@defmodule[math/statistics] @defmodule[math/statistics]
xxx intro @bold{Warning:} The documentation for this module is delayed while the
types for weighted samples get reworked. Please wait.
something about accepting weighted samples whenever it makes sense @;{something about accepting weighted samples whenever it makes sense
(time it doesn't make sense: autocorrelation) (time it doesn't make sense: autocorrelation)}
@local-table-of-contents[] @local-table-of-contents[]

View File

@ -0,0 +1,45 @@
#lang scribble/manual
@(require scribble/eval
racket/sandbox
(for-label racket/base racket/future
math
(only-in typed/racket/base
Real Boolean Integer Natural Number Listof
Positive-Flonum Float-Complex Any List Positive-Integer))
"utils.rkt")
@(define untyped-eval (make-untyped-math-eval))
@title[#:tag "utils"]{Stuff That Doesn't Belong Anywhere Else}
@(author-neil)
@defmodule[math/utils]
@defparam[max-math-threads num Positive-Integer]{
The maximum number of threads a parallelized @racketmodname[math] function
will use. The default value is @racket[(max 1 (processor-count))].
}
@defparam[dft-convention lst (List Real Real)]{
A parameter controlling the convention used for scaling discrete Fourier transforms, such as those
performed by @racket[array-fft]. The default value is @racket['(1 -1)], which represents the convention
used in signal processing.
In general, if @racket[lst] is @racket[(list a b)] and @racket[n] is the length of a transformed
array axis or vector, then
@itemlist[@item{Each sum is scaled by @racket[(expt n (/ (- a 1) 2))].}
@item{Each exponential in the sum has its argument scaled by @racket[b].}]
Conveniently, a Fourier transform with convention @racket[(list (- a) (- b))] is the inverse
of a Fourier transform with convention @racket[(list a b)].
See Mathematica's
@hyperlink["http://reference.wolfram.com/mathematica/tutorial/FourierTransforms.html"]{documentation
on @tt{Fourier}}, from which this excellent idea was stolen.
}
@defproc[(dft-inverse-convention) (List Real Real)]{
Returns the convention used for inverse Fourier transforms, given the current convention.
}
@(close-eval untyped-eval)

View File

@ -15,10 +15,10 @@ for working with numbers and collections of numbers. These include
@item{Special functions} @item{Special functions}
@item{@racket[Bigfloat]s, or arbitrary-precision floating-point numbers} @item{@racket[Bigfloat]s, or arbitrary-precision floating-point numbers}
@item{Probability distributions} @item{Probability distributions}
@item{Statistical functions} @item{Statistical functions (currently undergoing refactoring)}
@item{Number-theoretic functions} @item{Number-theoretic functions}
@item{@racket[Array]s for storing and transforming large rectangular data sets} @item{@racket[Array]s for storing and transforming large rectangular data sets}
@item{Linear algebra functions} @item{Linear algebra functions (currently under review)}
] ]
With this library, we hope to support a wide variety of applied mathematics in With this library, we hope to support a wide variety of applied mathematics in
@ -42,3 +42,4 @@ be used in untyped Racket. Exceptions and performance warnings are in @bold{bold
@include-section["math-array.scrbl"] @include-section["math-array.scrbl"]
@include-section["math-statistics.scrbl"] @include-section["math-statistics.scrbl"]
@include-section["math-distributions.scrbl"] @include-section["math-distributions.scrbl"]
@include-section["math-utils.scrbl"]

6
collects/math/utils.rkt Normal file
View File

@ -0,0 +1,6 @@
#lang racket
(require "private/parameters.rkt")
(provide (all-from-out
"private/parameters.rkt"))