
- Range checking was inconsistent between the sequence and macro forms - The macro form could crash due to unsafe vector refs Fixes involved refactoring the range checks so they are shared between both versions, and changing the contract slightly so start and stop are checked before the sequence runs. This allows unsafe vector refs and earlier error notifications at the cost making some valid programs (e.g. those using some condition to stop a comprehension hitting an invalid index) now be invalid. Only crazy people would rely on the old behaviour, so it isn't a problem in practice.
222 lines
7.5 KiB
Racket
222 lines
7.5 KiB
Racket
#lang scribble/doc
|
|
@(require "mz.ss"
|
|
(for-label racket/flonum))
|
|
|
|
@(define fl-eval (make-base-eval))
|
|
@(interaction-eval #:eval fl-eval (require racket/flonum))
|
|
|
|
@title[#:tag "flonums"]{Flonums}
|
|
|
|
@defmodule[racket/flonum]
|
|
|
|
The @racketmodname[racket/flonum] library provides operations like
|
|
@racket[fl+] that consume and produce only
|
|
@tech{flonums}. Flonum-specific operations provide can better
|
|
performance when used consistently, and they are as safe as generic
|
|
operations like @racket[+].
|
|
|
|
@guidealso["fixnums+flonums"]
|
|
|
|
@; ------------------------------------------------------------------------
|
|
|
|
@section{Flonum Arithmetic}
|
|
|
|
@deftogether[(
|
|
@defproc[(fl+ [a flonum?] [b flonum?]) flonum?]
|
|
@defproc[(fl- [a flonum?] [b flonum?]) flonum?]
|
|
@defproc[(fl* [a flonum?] [b flonum?]) flonum?]
|
|
@defproc[(fl/ [a flonum?] [b flonum?]) flonum?]
|
|
@defproc[(flabs [a flonum?]) flonum?]
|
|
)]{
|
|
|
|
Like @racket[+], @racket[-], @racket[*], @racket[/], and @racket[abs],
|
|
but constrained to consume @tech{flonums}. The result is always a
|
|
@tech{flonum}.}
|
|
|
|
@deftogether[(
|
|
@defproc[(fl= [a flonum?] [b flonum?]) boolean?]
|
|
@defproc[(fl< [a flonum?] [b flonum?]) boolean?]
|
|
@defproc[(fl> [a flonum?] [b flonum?]) boolean?]
|
|
@defproc[(fl<= [a flonum?] [b flonum?]) boolean?]
|
|
@defproc[(fl>= [a flonum?] [b flonum?]) boolean?]
|
|
@defproc[(flmin [a flonum?] [b flonum?]) flonum?]
|
|
@defproc[(flmax [a flonum?] [b flonum?]) flonum?]
|
|
)]{
|
|
|
|
Like @racket[=], @racket[<], @racket[>], @racket[<=], @racket[>=],
|
|
@racket[min], and @racket[max], but constrained to consume
|
|
@tech{flonums}.}
|
|
|
|
@deftogether[(
|
|
@defproc[(flround [a flonum?]) flonum?]
|
|
@defproc[(flfloor [a flonum?]) flonum?]
|
|
@defproc[(flceiling [a flonum?]) flonum?]
|
|
@defproc[(fltruncate [a flonum?]) flonum?]
|
|
)]{
|
|
|
|
Like @racket[round], @racket[floor], @racket[ceiling], and
|
|
@racket[truncate], but constrained to consume @tech{flonums}.}
|
|
|
|
@deftogether[(
|
|
@defproc[(flsin [a flonum?]) flonum?]
|
|
@defproc[(flcos [a flonum?]) flonum?]
|
|
@defproc[(fltan [a flonum?]) flonum?]
|
|
@defproc[(flasin [a flonum?]) flonum?]
|
|
@defproc[(flacos [a flonum?]) flonum?]
|
|
@defproc[(flatan [a flonum?]) flonum?]
|
|
@defproc[(fllog [a flonum?]) flonum?]
|
|
@defproc[(flexp [a flonum?]) flonum?]
|
|
@defproc[(flsqrt [a flonum?]) flonum?]
|
|
)]{
|
|
|
|
Like @racket[sin], @racket[cos], @racket[tan], @racket[asin],
|
|
@racket[acos], @racket[atan], @racket[log], @racket[exp], and
|
|
@racket[flsqrt], but constrained to consume and produce
|
|
@tech{flonums}. The result is @racket[+nan.0] when a number outside
|
|
the range @racket[-1.0] to @racket[1.0] is given to @racket[flasin] or
|
|
@racket[flacos], or when a negative number is given to @racket[fllog]
|
|
or @racket[flsqrt].}
|
|
|
|
|
|
@defproc[(->fl [a exact-integer?]) flonum?]{
|
|
|
|
Like @racket[exact->inexact], but constrained to consume exact
|
|
integers, so the result is always a @tech{flonum}.}
|
|
|
|
|
|
@defproc[(fl->exact-integer [a flonum?]) exact-integer?]{
|
|
|
|
Like @racket[inexact->exact], but constrained to consume an
|
|
@tech{integer} @tech{flonum}, so the result is always an exact
|
|
integer.}
|
|
|
|
|
|
@deftogether[(
|
|
@defproc[(make-flrectangular [a flonum?] [b flonum?])
|
|
(and/c complex? inexact? (not/c real?))]
|
|
@defproc[(flreal-part [a (and/c complex? inexact? (not/c real?))]) flonum?]
|
|
@defproc[(flimag-part [a (and/c complex? inexact? (not/c real?))]) flonum?]
|
|
)]{
|
|
|
|
Like @racket[make-rectangular], @racket[real-part], and
|
|
@racket[imag-part], but both parts of the complex number must be
|
|
inexact.}
|
|
|
|
@; ------------------------------------------------------------------------
|
|
|
|
@section{Flonum Vectors}
|
|
|
|
A @deftech{flvector} is like a @tech{vector}, but it holds only
|
|
inexact real numbers. This representation can be more compact, and
|
|
unsafe operations on @tech{flvector}s (see
|
|
@racketmodname[racket/unsafe/ops]) can execute more efficiently than
|
|
unsafe operations on @tech{vectors} of inexact reals.
|
|
|
|
An f64vector as provided by @racketmodname[ffi/vector] stores the
|
|
same kinds of values as an @tech{flvector}, but with extra
|
|
indirections that make f64vectors more convenient for working with
|
|
foreign libraries. The lack of indirections make unsafe
|
|
@tech{flvector} access more efficient.
|
|
|
|
Two @tech{flvectors} are @racket[equal?] if they have the same length,
|
|
and if the values in corresponding slots of the @tech{flvectors} are
|
|
@racket[equal?].
|
|
|
|
@defproc[(flvector? [v any/c]) boolean?]{
|
|
|
|
Returns @racket[#t] if @racket[v] is a @tech{flvector}, @racket[#f] otherwise.}
|
|
|
|
@defproc[(flvector [x flonum?] ...) flvector?]{
|
|
|
|
Creates a @tech{flvector} containing the given inexact real numbers.
|
|
|
|
@mz-examples[#:eval fl-eval (flvector 2.0 3.0 4.0 5.0)]}
|
|
|
|
@defproc[(make-flvector [size exact-nonnegative-integer?]
|
|
[x flonum? 0.0])
|
|
flvector?]{
|
|
|
|
Creates a @tech{flvector} with @racket[size] elements, where every
|
|
slot in the @tech{flvector} is filled with @racket[x].
|
|
|
|
@mz-examples[#:eval fl-eval (make-flvector 4 3.0)]}
|
|
|
|
@defproc[(flvector-length [vec flvector?]) exact-nonnegative-integer?]{
|
|
|
|
Returns the length of @racket[vec] (i.e., the number of slots in the
|
|
@tech{flvector}).}
|
|
|
|
|
|
@defproc[(flvector-ref [vec flvector?] [pos exact-nonnegative-integer?])
|
|
flonum?]{
|
|
|
|
Returns the inexact real number in slot @racket[pos] of
|
|
@racket[vec]. The first slot is position @racket[0], and the last slot
|
|
is one less than @racket[(flvector-length vec)].}
|
|
|
|
@defproc[(flvector-set! [vec flvector?] [pos exact-nonnegative-integer?]
|
|
[x flonum?])
|
|
flonum?]{
|
|
|
|
Sets the inexact real number in slot @racket[pos] of @racket[vec]. The
|
|
first slot is position @racket[0], and the last slot is one less than
|
|
@racket[(flvector-length vec)].}
|
|
|
|
@defproc[(flvector-copy [vec flvector?]
|
|
[start exact-nonnegative-integer? 0]
|
|
[end exact-nonnegative-integer? (vector-length v)])
|
|
flvector?]{
|
|
|
|
Creates a fresh @tech{flvector} of size @racket[(- end start)], with all of the
|
|
elements of @racket[vec] from @racket[start] (inclusive) to
|
|
@racket[end] (exclusive).}
|
|
|
|
|
|
@defproc[(in-flvector [vec flvector?]
|
|
[start exact-nonnegative-integer? 0]
|
|
[stop (or/c exact-integer? #f) #f]
|
|
[step (and/c exact-integer? (not/c zero?)) 1])
|
|
sequence?]{
|
|
Returns a sequence equivalent to @racket[vec] when no optional
|
|
arguments are supplied.
|
|
|
|
The optional arguments @racket[start], @racket[stop], and
|
|
@racket[step] are as in @racket[in-vector].
|
|
|
|
A @racket[in-flvector] application can provide better
|
|
performance for @tech{flvector} iteration when it appears directly in a @racket[for] clause.
|
|
}
|
|
|
|
@deftogether[(
|
|
@defform*[((for/flvector (for-clause ...) body ...)
|
|
(for/flvector #:length length-expr (for-clause ...) body ...))]
|
|
@defform*[((for*/flvector (for-clause ...) body ...)
|
|
(for*/flvector #:length length-expr (for-clause ...) body ...))])]{
|
|
|
|
Like @scheme[for/vector] or @scheme[for*/vector], but for
|
|
@tech{flvector}s.}
|
|
|
|
@defproc[(shared-flvector [x flonum?] ...) flvector?]{
|
|
|
|
Creates a @tech{flvector} containing the given inexact real numbers.
|
|
When @tech{places} are enabled, the new @tech{flvector} is
|
|
allocated in the @tech{shared memory space}.
|
|
|
|
@mz-examples[#:eval fl-eval (shared-flvector 2.0 3.0 4.0 5.0)]}
|
|
|
|
|
|
@defproc[(make-shared-flvector [size exact-nonnegative-integer?]
|
|
[x flonum? 0.0])
|
|
flvector?]{
|
|
|
|
Creates a @tech{flvector} with @racket[size] elements, where every
|
|
slot in the @tech{flvector} is filled with @racket[x].
|
|
When @tech{places} are enabled, the new @tech{flvector} is
|
|
allocated in the @tech{shared memory space}.
|
|
|
|
@mz-examples[#:eval fl-eval (make-shared-flvector 4 3.0)]}
|
|
|
|
@; ------------------------------------------------------------
|
|
|
|
@close-eval[fl-eval]
|