This SRFI is currently in withdrawn status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-77@nospamsrfi.schemers.org
. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
This SRFI is being submitted by members of the Scheme Language Editor's Committee as part of the R6RS Scheme standardization process. The purpose of such ``R6RS SRFIs'' is to inform the Scheme community of features and design ideas under consideration by the editors and to allow the community to give the editors some direct feedback that will be considered during the design process.
At the end of the discussion period, this SRFI will be withdrawn. When the R6RS specification is finalized, the SRFI may be revised to conform to the R6RS specification and then resubmitted with the intent to finalize it. This procedure aims to avoid the situation where this SRFI is inconsistent with R6RS. An inconsistency between R6RS and this SRFI could confuse some users. Moreover it could pose implementation problems for R6RS compliant Scheme systems that aim to support this SRFI. Note that departures from the SRFI specification by the Scheme Language Editor's Committee may occur due to other design constraints, such as design consistency with other features that are not under discussion as SRFIs.
Scheme's arithmetic system was designed to allow a wide variety of implementations. After many years of implementation experience, however, most implementations now fall into a small number of categories, and the benefits of continued experimentation no longer justify the confusion and portability problems that have resulted from giving implementations so much freedom in this area. Moreover, the R5RS generic arithmetic is difficult to implement as efficiently as purely fixnum or purely flonum arithmetic. (Fixnum arithmetic is typically limited-precision integer arithmetic implemented using one or more representations that may be especially efficient on the executing machine; flonum arithmetic is typically limited-precision floating-point arithmetic using one or more representations that may be especially efficient on the executing machine.)
This SRFI is an effort to extend and clarify the R5RS arithmetic to make it more portable, more comprehensive, and enable faster programs.
Furthermore, one of us (Sperber) has argued that Scheme's arithmetic requires radical overhaul. The other (Clinger) agrees that revisions are needed. Whether these revisions qualify as radical is best left to the judgement of individual readers.
This SRFI proposes to revise section 6.2 ("Numbers") of R5RS by:
eqv?
to
behave more sensibly with inexact numbers
Members of the Scheme community are encouraged to express themselves on the following issues:
x|53
default for the mantissa width discriminates
against implementations that default to unusually good representations,
such as IEEE extended precision. Are there any such implementations?
Do we expect such implementations in the near future?
exact-bit-set?
,
exact-copy-bit
,
fixnum-bit-set?
,
fx-bit-set?
,
fixnum-copy-bit
, and
fxcopy-bit
.
The ordering of arguments to the following procedures have
also been changed so the original value comes first, then
the two integers that select the bit field, and then the
bit source or rotation count:
exact-copy-bit-field
,
fixnum-copy-bit-field
,
fxcopy-bit-field
,
exact-rotate-bit-field
,
fixnum-rotate-bit-field
, and
fxrotate-bit-field
.
Furthermore new shift operations have been introduced that
require a non-negative shift count:
exact-arithmetic-shift-left
,
exact-arithmetic-shift-right
,
fixnum-arithmetic-shift-left
,
fixnum-arithmetic-shift-right
,
fxarithmetic-shift-left
,
fxarithmetic-shift-right
,
fixnum-logical-shift-left
,
fixnum-logical-shift-right
.
fixnum-bit-count
and
fxbit-count
is negative, should they return a
negative result?
real-valued?
, ... operators have been added.
div
and mod
operators
of the previous draft have been changed to use
non-negative representatives in all cases.
The new div0
and mod0
operators
provide representatives centered around zero.
quotient
, remainder
, and
modulo
procedures were removed.
exact-
, fixnum-
, or fx
prefixes, and the order of arguments has been changed in some
cases.
fixnum
instead of
fx
.
fx
.
fixnum+/carry
,
fixnum-/carry
, and
fixnum*/carry
operators have been added.
fxabs
,
fxgcd
,
fxlcm
,
flgcd
,
fllcm
, and
flonum->fixnum
operators have been deleted.
exact-
prefix (instead of ex
).
The inexact generic operations have been renamed to carry an
inexact-
prefix (instead of in
).
exact-integer-sqrt
procedure was added.
flfinite?
, flinfinite?
,
inexact-finite?
, inexact-infinite?
,
finite?
, and infinite?
were added.
Most implementations of Scheme fall into one of the following categories:
The portability problems can most easily be solved by requiring all implementations to support the full numeric tower. To prevent that requirement from making Scheme substantially more difficult to implement, we provide a reference implementation that constructs the full numeric tower from a fixnum/flonum base. To ensure the portability of such reference implementations, the fixnum/flonum base must be described and (at least partially) standardized.
Fixnum/flonum arithmetic is already supported by many systems, mainly for efficiency. Standardization of fixnum/flonum arithmetic would increase the portability of code that uses it, but we cannot standardize the precision of fixnum/flonum arithmetic without making it inefficient on some systems, which would defeat its purpose. We therefore propose to specify the syntax and much of the semantics of fixnum/flonum arithmetic, but to make the precision a parameter of the specification.
Several details of R5RS are inconsistent or incomplete with respect to the IEEE standards for binary floating point arithmetic, which are generally used to implement Scheme's inexact real arithmetic. Furthermore, some details of R5RS make it unnecessarily difficult to implement Scheme's arithmetic efficiently.
This SRFI is incompatible with SRFI 70 [Jaffer 2005] in several ways, including:
+nan.0
as a real number whose value is so
indeterminate that it might represent any real number within
the closed interval [-inf.0
,+inf.0
].
Moreover, unlike SRFI 70, this alternative operations for integer
division div
, mod
, div0
, and
mod0
, which are slightly more generally applicable and
easier to specify. It also does not extend the gcd
and
lcm
to rational numbers.
The sections on Fixnums, Flonums, Exact Arithmetic, and Inexact Arithmetic are new in the SRFI and not in SRFI 70. This SRFI also omits SRFI 70's discussion of infinities and offers its own.
Other, more minor differences with SRFI 70 are highlighted in the hypertext. (The sections mentioned in the previous paragraph are not marked up, as they would be (almost in the case of generic exact arithmetic) completely red.
We assume that Section 6.2.3 ("Implementation restrictions") of R5RS remains essentially as it stands. The text of this SRFI describes the differences between the proposed additions and changes to R5RS and/or SRFI 70.
The R6RS is expected to describe some kind of library facility, but this SRFI does not rely on that feature. We expect some of the new arithmetic procedures specified by this SRFI will be available only within certain libraries.Positive infinity is regarded as a real (but not rational) number, whose value is indeterminate but greater than all rational numbers. Negative infinity is regarded as a real (but not rational) number, whose value is indeterminate but less than all rational numbers.
A NaN is regarded as a real (but not rational) number whose value is so indeterminate that it might represent any real number, including positive or negative infinity, and might even be greater than positive infinity or less than negative infinity.
This SRFI is written as though infinities and NaNs are representable, and specifies many operations with respect to these numbers in ways that are consistent with the IEEE 754 standard for binary floating point arithmetic. Although implementations of Scheme are not required to represent infinities and NaNs, an implementation must report a violation of an implementation restriction whenever it is unable to represent an infinity or NaN as required by the specification below. This requirement also applies to conversions between numbers and external representations, including the reading of program source code.
Note: We expect the R6RS to refine this specification in enough detail so programs can specify exception handlers that recover from these particular violations of implementation restrictions by substituting alternatives values for the unrepresentable infinity or NaN.
This SRFI adds the following external representations to Scheme:
+inf.0
represents the result of
(/ 1.0 0.0)
-inf.0
represents the result of
(/ -1.0 0.0)
+nan.0
represents the result of
(/ 0.0 0.0)
, and may represent other NaNs as well.
(This SRFI does not require read/write invariance for NaNs.)
|
p
is an external representation that denotes the
best binary floating point approximation to x
using a p-bit significand.
For example, 1.1|53
is an external representation for the
best approximation to 1.1 in IEEE double precision.
x|
53
.
Implementations that use binary floating point representations
of real numbers should represent x|
p
using a p-bit significand if practical, or by a greater
precision if a p-bit significand is not practical, or
by the largest available precision if p or more bits
of significand is not practical within the implementation.
Note: The precision of a significand should not be confused with the number of bits used to represent the significand. In the IEEE floating point standards, for example, the significand's most significant bit is implicit in single and double precision but is explicit in extended precision. Whether that bit is implicit or explicit does not affect the mathematical precision. In implementations that use binary floating point, the default precision can be calculated by calling the following procedure:
(define (precision) (do ((n 0 (+ n 1)) (x 1.0 (/ x 2.0))) ((= 1.0 (+ 1.0 x)) n)))
Note: When the underlying floating-point representation is IEEE double precision, the
|
p suffix should not be omitted for all cases: Denormalized numbers have diminished precision, and therefore should carry a|
p suffix with the actual width of the significand.
The number->string
procedure is generalized
over the R5RS version
to support the x|
p notation.
To be consistent with this SRFI,
the write
procedure would be required to write
inexact numbers in the external representation produced by
number->string
with one argument.
Implementations are not required to use floating-point representations, but every implementation is required to designate a subset of its inexact reals as flonums, and to convert certain external representations into flonums.
The R6RS section on the lexical structure of numerical tokens should read as as follows:
The following rules for
<num R>
,<complex R>
,<real R>
,<ureal R>
,<uinteger R>
, and<prefix R>
should be replicated for R = 2, 8, 10, and 16. There are no rules for<decimal 2>
,<decimal 8>
, and<decimal 16>
, which means that numbers containing decimal points or exponents or mantissa widths must be in decimal radix.<num R> --> <prefix R> <complex R> <complex R> --> <real R> | <real R> @ <real R> | <real R> + <ureal R> i | <real R> - <ureal R> i | <real R> + i | <real R> - i | + <ureal R> i | - <ureal R> i | + i | - i <real R> --> <sign> <ureal R> <ureal R> --> <uinteger R> | <uinteger R> / <uinteger R> | <decimal R> <mantissa width> | inf.0 | nan.0 <decimal 10> --> <uinteger 10> <suffix> | . <digit 10>+ #* <suffix> | <digit 10>+ . <digit 10>* #* <suffix> | <digit 10>+ #* . #* <suffix> <uinteger R> --> <digit R>+ #* <prefix R> --> <radix R> <exactness> | <exactness> <radix R> <suffix> --> <empty> | <exponent marker> <sign> <digit 10>+ <exponent marker> --> e | s | f | d | l <mantissa width> -> <empty> | | <digit 10>+ <sign> --> <empty> | + | - <exactness> --> <empty> | #i | #e <radix 2> --> #b <radix 8> --> #o <radix 10> --> <empty> | #d <radix 16> --> #x <digit 2> --> 0 | 1 <digit 8> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 <digit 10> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <digit 16> --> <digit 10> | a | b | c | d | e | f
If a <decimal 10>
does not contain a non-empty <mantissa width>
and does not contain one of the exponent markers s
, f
, d
, or l
,
but does contain a decimal point or the exponent marker e, then
it is an external representation for a flonum.
Furthermore inf.0
, +inf.0
, -inf.0
, nan.0
, +nan.0
, and -nan.0
are
external representations for flonums. Some or all of the other
external representations for inexact reals may also represent
flonums, but that is not required by this SRFI.
If a <decimal 10>
contains a non-empty <mantissa width>
or one
of the exponent markers s
, f
, d
, or l
, then it represents an
inexact number, but does not necessarily represent a flonum.
The R6RS is expected to require implementations to provide a "safe" mode in which specified exceptional situations must be detected and handled in standard ways, while allowing (but not requiring) implementations to support an "unsafe" mode that is not guaranteed to detect those situations or to handle them in the standard way even when detected. These modes may interact with many features of Scheme, but are particularly relevant to the fixnum and flonum operations. In safe mode, these operations must check that their arguments are actually fixnums or flonums respectively, or perform possible additional checking as required by the specifications of the operations. In unsafe mode, these operations are not required to perform such checking. This distinction allows programmers to request more efficient numerical code for those operations at the cost of less effective run-time checking.
This SRFI uses the phrase "all bets are off" to describe situations in which the behavior of a procedure is unspecified when executing in unsafe mode. Specifically, a procedure call for which all bets are off is free to crash the system.
The R6RS specification of eqv? for numbers should be changed as follows.
The eqv?
procedure returns #t
if:
=
, section see section 6.2
Numbers), or=
, section see section 6.2 Numbers), and
yield the same results (in the sense of eqv?
) when passed
as arguments to any other procedure that can be defined
as a finite composition of Scheme's standard arithmetic
procedures.
The eqv?
procedure returns #f
if:
=
procedure
returns #f
, or eqv?
) when passed as arguments to any other procedure
that can be defined as a finite composition of Scheme's
standard arithmetic procedures.
number?
obj
complex?
obj
real?
obj
rational?
obj
integer?
obj
These numerical type predicates can be applied to any kind of argument, including non-numbers. They return #t if the object is of the named type, and otherwise they return #f. In general, if a type predicate is true of a number then all higher type predicates are also true of that number. Consequently, if a type predicate is false of a number, then all lower type predicates are also false of that number.
If z is
an inexact a complex number, then
`(real? z)' is true if and only if
`(zero? (imag-part z))'
and `(exact? (imag-part z))' are both true.
If x is a real number, then `(rational? x)' is true if and only if there exist exact integers k1 and k2 such that `(= x (/ k1 k2))' and `(= (numerator x) k1)' and `(= (denominator x) k2)' are all true. Thus infinities and NaNs are not rational numbers.
If q is a rational number, then `(integer? q)' is true if and only if `(= (denominator q) 1)' is true. If q is not a rational number, then `(integer? q)' is false.(and (finite? x) (= x (round x)))
(complex? 3+4i) ==> #t (complex? 3) ==> #t (real? 3) ==> #t (real? -2.5+0.0i) ==> #f (real? -2.5+0i) ==> #t (real? -2.5) ==> #t (real? #e1e10) ==> #t (rational? 6/10) ==> #t (rational? 6/3) ==> #t (rational? 2) ==> #t (integer? 3+0i) ==> #t (integer? 3.0) ==> #t (integer? 8/4) ==> #t (number? +nan.0) ==> #t (complex? +nan.0) ==> #t (real? +nan.0) ==> #t (rational? +nan.0) ==> #f (complex? +inf.0) ==> #t (real? -inf.0) ==> #t (rational? -inf.0) ==> #f (integer? -inf.0) ==> #f
Note: In many implementations therational?
procedure will be the same asreal?
, and thecomplex?
procedure will be the same asnumber?
, but unusual implementations may be able to represent some irrational numbers exactly or may extend the number system to support some kind of non-complex numbers.
Note: The behavior of these type predicates on inexact numbers is unreliable, because any inaccuracy may affect the result.
real-valued?
obj
rational-valued?
obj
integer-valued?
obj
These numerical type predicates can be applied to any kind of
argument, including non-numbers. They return #t
if the object is a number and is equal in the sense of
=
to some object
of the named type, and otherwise they return #f
.
(real-valued? +nan.0) ==> #f (real-valued? -inf.0) ==> #t (real-valued? 3) ==> #t (real-valued? -2.5+0.0i) ==> #t (real-valued? -2.5+0i) ==> #t (real-valued? -2.5) ==> #t (real-valued? #e1e10) ==> #t (rational-valued? +nan.0) ==> #f (rational-valued? -inf.0) ==> #f (rational-valued? 6/10) ==> #t (rational-valued? 6/10+0.0i) ==> #t (rational-valued? 6/10+0i) ==> #t (rational-valued? 6/3) ==> #t (integer-valued? 3+0i) ==> #t (integer-valued? 3+0.0i) ==> #t (integer-valued? 3.0) ==> #t (integer-valued? 3.0+0.0i) ==> #t (integer-valued? 8/4) ==> #t
Note: The behavior of these type predicates on inexact numbers is unreliable, because any inaccuracy may affect the result.
exact?
z
inexact?
z
These numerical predicates provide tests for the exactness of a quantity. For any Scheme number, precisely one of these predicates is true.
(exact? 5) ==> #t (inexact? +inf.0) ==> #t
exact->inexact
z
inexact->exact
z
Exact->inexact
returns an inexact representation of z.
If inexact numbers of the appropriate type have bounded precision,
then the value returned is an inexact number that is nearest to
the argument.
If an exact argument has no reasonably close inexact equivalent,
then a violation of an implementation restriction may be reported.
Inexact->exact
returns an exact representation of
z.
The value returned is the exact number that is numerically
closest to the argument; in most cases, the result of this
procedure should be numerically equal to its argument.
If an inexact argument has no reasonably close exact equivalent,
then a violation of an implementation restriction may be reported.
These procedures implement the natural one-to-one correspondence between exact and inexact integers throughout an implementation-dependent range.
Exact->inexact
and
inexact->exact
are idempotent.
real->flonum
x
Real->flonum
returns a flonum representation of
x, which must be a real number.
The value returned is a flonum that is numerically closest to the
argument.
Rationale: The flonums are a subset of the inexact reals, but may be a proper subset. The
real->flonum
procedure converts an arbitrary real to the flonum type required by flonum-specific procedures.
Note: If flonums are represented in binary floating point, then implementations are strongly encouraged to break ties by preferring the floating point representation whose least significant bit is zero.
number->string
z
number->string
z radix
number->string
z radix precision
Radix must be an exact integer, either 2, 8, 10, or 16.
If omitted, radix defaults to 10.
If a precision is specified, then z must be an
inexact complex number, precision must be an exact
positive integer, and the radix must be 10.
The procedure number->string
takes a
number and a radix and returns as a string an external representation of
the given number in the given radix such that
(let ((number number) (radix radix)) (eqv? number (string->number (number->string number radix) radix)))
is true. It is an error if no possible result makes this expression true.
If a precision is specified, then the representations of the inexact real components of the result, unless they are infinite or NaN, specify an explicit <mantissa width> p, and p is the least p ≥ precision for which the above expression is true.
If z is inexact, the radix is 10, and the above expression and condition can be satisfied by a result that contains a decimal point, then the result contains a decimal point and is expressed using the minimum number of digits (exclusive of exponent, trailing zeroes, and mantissa width) needed to make the above expression and condition true [Burger, Dybvig 1996; Clinger 1990]; otherwise the format of the result is unspecified.
The result returned by number->string
never contains an explicit radix prefix.
Note: The error case can occur only when z is not a complex number or is a complex number with a non-rational real or imaginary part.
Rationale: If z is an inexact number represented using binary floating point, and the radix is 10, then the above expression is normally satisfied by a result containing a decimal point. The unspecified case allows for infinities, NaNs, and representations other than binary floating point.
string->number
string
string->number
string radix
Returns a number of the maximally precise representation expressed by the
given string. Radix must be an exact integer, either 2, 8, 10,
or 16. If supplied, radix is a default radix that may be overridden
by an explicit radix prefix in string (e.g. "#o177"). If radix
is not supplied, then the default radix is 10. If string is not
a syntactically valid notation for a number, then string->number
returns #f.
(string->number "100") ==> 100
(string->number "100" 16) ==> 256
(string->number "1e2") ==> 100.0
(string->number "15##") ==> 1500.0
(string->number "+inf.0") ==> +inf.0
(string->number "-inf.0") ==> -inf.0
(string->number "+nan.0") ==> +nan.0
Note: The domain ofstring->number
may be restricted by implementations in the following ways.String->number
is permitted to return #f whenever string contains an explicit radix prefix. If all numbers supported by an implementation are real, thenstring->number
is permitted to return #f whenever string uses the polar or rectangular notations for complex numbers. If all numbers are integers, thenstring->number
may return #f whenever the fractional notation is used. If all numbers are exact, thenstring->number
may return #f whenever an exponent marker or explicit exactness prefix is used, or if a # appears in place of a digit. If all inexact numbers are integers, thenstring->number
may return #f whenever a decimal point is used. An implementation may return#f
for"+nan.0"
.
For various kinds of arithmetic (fixnum, flonum, exact, inexact, and generic), this SRFI provides operations for performing integer division. They rely on mathematical operations div, mod, div0, and mod0, that are defined as follows:
div, mod, div0, and mod0 each accept two real numbers x1 and x2 as operands, where x2 must be nonzero.
div returns an integer, mod returns a real. Their results are specified by
x1 div x2 ==> nd x1 mod x2 ==> xmwhere
Examples:
5 div 3 = 1 5 div -3 = -1 5 mod 3 = 2 5 mod -3 = 2
Div0 and mod0 are like div and mod, except the result of mod0 lies within a half-open interval centered on zero. The results are specified by
x1 div0 x2 ==> nd x1 mod0 x2 ==> xmwhere:
Examples:
5 div 3 = 2 5 div -3 = -2 5 mod 3 = -1 5 mod -3 = -1
Rationale: The half-open symmetry about zero is convenient for some purposes.
A subrange of the exact integers is designated as the set of fixnums. Conversely, a fixnum is an exact integer whose value lies within this fixnum range.
Every implementation must define its fixnum range as a closed interval [-2w-1, 2w-1 - 1] such that w is a a (mathematical) integer w ≥ 24. Every mathematical integer within an implementation's fixnum range must correspond to an exact integer that is representable within the implementation.
This section specifies two kinds of operations on fixnums.
Operations whose names begin with fixnum
perform arithmetic modulo 2w.
Operations whose names begin with fx
perform integer arithmetic on their fixnum arguments,
but signal an error if the result is not a fixnum.
Rationale: The operations whose names begin with
fixnum
implement arithmetic on a quotient ring of the integers, but their results will not be the same in every implementation because the particular ring is parameterized by w. The operations whose names begin withfx
do not have as nice a closure property, and the arguments that cause them to signal an error will not be the same in every implementation, but any results they return without signalling an error will be the same in all implementations.
Some operations
(e.g. fixnum<
and fx<
)
behave the same in both sets.
Rationale: Duplication of names reduces bias toward either set, and saves programmers from having to remember which names are supplied.
We will use fx, fx1 and fx2 as metavariables that range over fixnums.
If an argument to the following procedures that corresponds to a fixnum metavariable is not actually a fixnum, then these procedures signal an error, unless the implementation is running in unsafe mode, in which case all bets are off.
fixnum?
obj
This returns #t if obj is an exact integer within the fixnum range, and otherwise returns #f.
fixnum-width
least-fixnum
greatest-fixnum
These procedures return w, -2w-1 and 2w-1 - 1, the width, minimum and the maximum value of the fixnum range, respectively.
fixnum=
fx1 fx2 fx3 ...
fixnum>
fx1 fx2 fx3 ...
fixnum<
fx1 fx2 fx3 ...
fixnum>=
fx1 fx2 fx3 ...
fixnum<=
fx1 fx2 fx3 ...
fx=
fx1 fx2 fx3 ...
fx>
fx1 fx2 fx3 ...
fx<
fx1 fx2 fx3 ...
fx>=
fx1 fx2 fx3 ...
fx<=
fx1 fx2 fx3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing,
#f
otherwise.
fixnum-zero?
fx
fixnum-positive?
fx
fixnum-negative?
fx
fixnum-odd?
fx
fixnum-even?
fx
fxzero?
fx
fxpositive?
fx
fxnegative?
fx
fxodd?
fx
fxeven?
fx
These numerical predicates test a fixnum for a particular property, returning #t or #f. The five properties tested by these procedures are: whether the number is zero, greater than zero, less than zero, odd, or even.
fixnum-max
fx1 fx2 ...
fixnum-min
fx1 fx2 ...
fxmax
fx1 fx2 ...
fxmin
fx1 fx2 ...
These procedures return the maximum or minimum of their arguments.
fixnum+
fx1 ...
fixnum*
fx1 ...
These procedures return the unique fixnum that is congruent mod 2w to the sum or product of their arguments.
fx+
fx1 fx2
fx*
fx1 fx2
These procedures return the sum or product of their arguments, provided that sum or product is a fixnum. An error is signalled if that sum or product is not a fixnum, unless the implementation is running in unsafe mode, in which case all bets are off.
Rationale: These procedures are restricted to two arguments because their generalizations to three or more arguments would require precision proportional to the number of arguments.
fixnum-
fx1 fx2 ...
fixnum-
fx
With two or more arguments, this procedure returns the unique fixnum that is congruent mod 2w to the difference of its arguments, associating to the left. With one argument, however, it returns the the unique fixnum that is congruent mod 2w to the additive inverse of its argument.
fx-
fx1 fx2
fx-
fx
With two arguments, this procedure returns the difference of its arguments, provided that difference is a fixnum.
With one argument, this procedure returns the additive inverse of its argument, provided that integer is a fixnum.
An error is signalled if the mathematically correct result of this procedure is not a fixnum.
(fx- (least-fixnum)) ==> error
fixnum-div+mod
fx1 fx2
fixnum-div
fx1 fx2
fixnum-mod
fx1 fx2
fixnum-div0+mod0
fx1 fx2
fixnum-div0
fx1 fx2
fixnum-mod0
fx1 fx2
These procedures implement number-theoretic integer division modulo 2w. Each procedure returns the unique fixnum(s) congruent modulo 2w to the result(s) specified in the section on Integer Division. An error is signalled if the second argument is zero, unless the implementation is running in unsafe mode, in which case all bets are off.
(fixnum-div x1 x2) ==> x1 div x2 (fixnum-mod x1 x2) ==> x1 mod x2 (fixnum-div+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (fixnum-div0 x1 x2) ==> x1 div0 x2 (fixnum-mod0 x1 x2) ==> x1 mod0 x2 (fixnum-div0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
fxdiv+mod
fx1 fx2
fxdiv
fx1 fx2
fxmod
fx1 fx2
fxdiv0+mod0
fx1 fx2
fxdiv0
fx1 fx2
fxmod0
fx1 fx2
These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in the section on Integer Division. An error is signalled if a result specified by that section is not a fixnum, unless the implementation is running in unsafe mode, in which case all bets are off. An error is signalled if the second argument is zero, unless the implementation is running in unsafe mode, in which case all bets are off.
(fxdiv x1 x2) ==> x1 div x2 (fxmod x1 x2) ==> x1 mod x2 (fxdiv+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (fxdiv0 x1 x2) ==> x1 div0 x2 (fxmod0 x1 x2) ==> x1 mod0 x2 (fxdiv0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
fixnum+/carry
fx1 fx2 fx3
Returns the two fixnum results of the following computation:
(let* ((s (+ fx1 fx2 fx3)) (s0 (mod0 s (expt 2 (fixnum-width)))) (s1 (div0 s (expt 2 (fixnum-width))))) (values s0 s1))
Note: The results returned by the
fixnum+/carry
,fixnum-/carry
, andfixnum*/carry
procedures depend upon the precision w, so there are nofx
equivalents to these procedures.
fixnum-/carry
fx1 fx2 fx3
Returns the two fixnum results of the following computation:
(let* ((d (- fx1 fx2 fx3)) (d0 (mod0 d (expt 2 (fixnum-width)))) (d1 (div0 d (expt 2 (fixnum-width))))) (values d0 d1))
fixnum*/carry
fx1 fx2 fx3
Returns the two fixnum results of the following computation:
(let* ((s (+ (* fx1 fx2) fx3)) (s0 (mod0 s (expt 2 (fixnum-width)))) (s1 (div0 s (expt 2 (fixnum-width))))) (values s0 s1))
fixnum-not
fx
fxnot
fx
Both of these procedures return the unique fixnum that is congruent mod 2w to the one's-complement of their argument.
fixnum-and
fx1 ...
fixnum-ior
fx1 ...
fixnum-xor
fx1 ...
fxand
fx1 ...
fxior
fx1 ...
fxxor
fx1 ...
These procedures return the fixnum that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the fixnum (either -1 or 0) that acts as identity for the operation.
fixnum-if
fx1 fx2 fx3
fxif
fx1 fx2 fx3
These procedures return the fixnum result of the following computation:
(fixnum-ior (fixnum-and fx1 fx2) (fixnum-and (fixnum-not fx1) fx3))
fixnum-bit-count
fx
fxbit-count
fx
If the argument fx is non-negative, these procedures return the number of 1 bits in the two's complement representation of fx. Otherwise they return the number of 0 bits in the two's complement representation of fx.
fixnum-length
fx
fxlength
fx
These procedures return the fixnum result of the following computation:
(do ((result 0 (+ result 1)) (bits (if (fixnum-negative? fx) (fixnum- fx) fx) (fixnum-logical-shift-right bits 1))) ((fixnum-zero? bits) result))
fixnum-first-bit-set
fx
fxfirst-bit-set
fx
These procedures return the index of the least significant 1 bit in the two's complement representation of their argument. If the argument is 0, then -1 is returned.
(fixnum-first-bit-set 0) ==> -1 (fixnum-first-bit-set 1) ==> 0 (fixnum-first-bit-set -4) ==> 2
fixnum-bit-set?
fx1 fx2
If the second argument is non-negative, this procedure returns the fixnum result of the following computation:
(not (fixnum-zero? (fixnum-and fx1 (fixnum-logical-shift-left 1 fx2))))If the second argument is negative, then an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
fxbit-set?
fx fx2
If the first argument is negative, or greater than or equal
to (fixnum-width)
, then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result returned by fixnum-bit-set?
.
fixnum-copy-bit
fx1 fx2 fx3
If the second argument is non-negative, then this procedure returns the fixnum result of the following computation:
(let* ((mask (fixnum-logical-shift-left 1 fx2))) (fixnum-if mask (fixnum-logical-shift-left fx3 fx2) fx2))If the second argument is negative, then an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
fxcopy-bit
fx1 fx2 fx3
If the second argument is negative, or greater than or equal
to (fixnum-width)
, or the third argument is
anything other than 0 or 1, then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result returned by fixnum-copy-bit
.
fixnum-bit-field
fx1 fx2 fx3
If the second and third arguments are non-negative, this procedure returns the fixnum result of the following computation:
(let* ((mask (fixnum-not (fixnum-logical-shift-left -1 fx3)))) (fixnum-logical-shift-right (fixnum-and fx1 mask) fx2))If the second or third argument is negative, then an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
fxbit-field
fx1 fx2 fx3
If the second or third argument is negative,
or greater than (fixnum-width)
,
or the second argument is greater than the third,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result returned by fixnum-bit-field
.
fixnum-copy-bit-field
fx1 fx2 fx3 fx4
If the second and third arguments are non-negative, this procedure returns the fixnum result of the following computation:
(let* ((to fx1) (start fx2) (end fx3) (from fx4) (mask1 (fixnum-logical-shift-left -1 start)) (mask2 (fixnum-not (fixnum-logical-shift-left -1 end))) (mask (fixnum-and mask1 mask2))) (fixnum-if mask from to))If the second or third argument is negative, then an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
fxcopy-bit-field
fx1 fx2 fx3 fx4
If the second or third argument is negative,
or greater than (fixnum-width)
,
or the second argument is greater than the third,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result returned by fixnum-copy-bit-field
.
fixnum-arithmetic-shift
fx1 fx2
Returns the unique fixnum that is congruent mod 2w to the result of the following computation:
(exact-floor (* fx1 (expt 2 fx2)))
fxarithmetic-shift
fx1 fx2
If the absolute value of the second argument
is greater than or equal to (fixnum-width)
,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. If
(exact-floor (* fx1 (expt 2 fx2)))is a fixnum, then that fixnum is returned. Otherwise an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
fixnum-arithmetic-shift-left
fx1 fx2
fixnum-arithmetic-shift-right
fx1 fx2
If the second argument is non-negative, then
fixnum-arithmetic-shift-left
returns the same result as fixnum-arithmetic-shift
,
and
(fixnum-arithmetic-shift-right fx1 fx2)
returns the same result as
(fixnum-arithmetic-shift fx1 (fixnum- fx2))
.
If the second argument is negative,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off.
fxarithmetic-shift-left
fx1 fx2
fxarithmetic-shift-right
fx1 fx2
If the second argument is non-negative, then
fxarithmetic-shift-left
behaves the same as fxarithmetic-shift
,
and
(fxarithmetic-shift-right fx1 fx2)
behaves the same as
(fxarithmetic-shift fx1 (fixnum- fx2))
.
If the second argument is negative,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off.
fixnum-logical-shift-left
fx1 fx2
This procedure behaves the same as fixnum-arithmetic-shift-left
.
fixnum-logical-shift-right
fx1 fx2
If the second argument is non-negative, then this procedure returns the result of the following computation:
(let* ((n fx1) (shift fx2) (shifted (fixnum-arithmetic-shift-right n shift))) (let* ((mask-width (fixnum- (fixnum-width) (fixnum-mod shift (fixnum-width)))) (mask (fixnum-not (fixnum-logical-shift-left -1 mask-width)))) (fixnum-and shifted mask))If the second argument is negative, then an error is signalled, unless the implementation is running in unsafe mode, in which case all bets are off.
Note: The results of
fixnum-logical-shift-left
andfixnum-logical-shift-left
can depend upon the precision w, so they have nofx
equivalents.
fixnum-rotate-bit-field
fx1 fx2 fx3 fx4
If the second, third, and fourth arguments are non-negative, this procedure returns the result of the following computation:
(let* ((n fx1) (start fx2) (end fx3) (count fx4) (width (fixnum- end start))) (if (fixnum-positive? width) (let* ((count (fixnum-mod count width)) (field0 (fixnum-bit-field n start end)) (field1 (fixnum-logical-shift-left field0 count)) (field2 (fixnum-logical-shift-right field0 (fixnum- width count))) (field (fixnum-ior field1 field2))) (fixnum-copy-bit-field n field start end)) n))
fxrotate-bit-field
fx1 fx2 fx3 fx4
If the second, third, or fourth argument is negative,
or greater than (fixnum-width)
,
or the fourth argument is greater than or equal to
the difference between the third and second arguments,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result as the fixnum-rotate-bit-field
procedure.
fixnum-reverse-bit-field
fx1 fx2 fx3
Returns the fixnum obtained from the first argument by reversing the bit field specified by the second and third arguments.
(fixnum-reverse-bit-field #b1010010 1 4) ==> 88 ; #b1011000 (fixnum-reverse-bit-field #b1010010 91 -4) ==> 82 ; #b1010010
fxreverse-bit-field
fx1 fx2 fx3
If the second or third argument is negative,
or greater than (fixnum-width)
,
or the second argument is greater than the third,
then an error is signalled,
unless the implementation is running in unsafe mode, in which
case all bets are off. Otherwise this procedure returns the
same result as the fixnum-reverse-bit-field
procedure.
Implementations are not required to use floating-point representations, but every implementation is required to designate a subset of its inexact reals as flonums, and to convert certain external representations into flonums. The flonums must be closed under the flonum operations described in this section.
We will use fl, fl1 and fl2 as
metavariables that range over flonums, and ifl,
ifl1 and ifl2 as metavariables that range over
integer-valued flonums, i.e. flonums for which the
integer-valued?
predicate is true.
If an argument to the following procedures that corresponds to a (integral) flonum metavariable is not actually a (integral) flonum, then these procedures signal an error, unless the implementation is running in unsafe mode, in which case all bets are off.
flonum?
obj
This returns #t if obj is a flonum, and otherwise returns #f.
fl=
fl1 fl2 fl3 ...
fl<
fl1 fl2 fl3 ...
fl<=
fl1 fl2 fl3 ...
fl>
fl1 fl2 fl3 ...
fl>=
fl1 fl2 fl3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing,
#f
otherwise. These
predicates are required to be transitive.
(fl= +inf.0 +inf.0) ==> #t (fl= -inf.0 +inf.0) ==> #f (fl= -inf.0 -inf.0) ==> #t (fl= 0.0 -0.0) ==> #t (fl< 0.0 -0.0) ==> #f (fl= +nan.0 fl) ==> #f (fl< +nan.0 fl) ==> #f
flinteger?
fl
flzero?
fl
flpositive?
fl
flnegative?
fl
flodd?
ifl
fleven?
ifl
flfinite?
fl
flinfinite?
fl
flnan?
fl
These numerical predicates test a flonum for a particular property,
returning #t or #f.
Flinteger?
tests it if the number is an integer,
flzero?
tests if
it is fl=
to zero, flpositive?
tests if it is greater
than zero, flnegative?
tests if it is less
than zero, flodd?
tests if it is odd,
fleven?
tests if it is even,
flfinite?
tests if it is not an infinity and not a NaN,
flinfinite?
tests if it is an infinity,
flnan?
tests if it is a NaN.
(flnegative? -0.0) ==> #f (flfinite? +inf.0) ==> #f (flfinite? 5.0) ==> #t (flinfinite? 5.0) ==> #f (flinfinite? +inf.0) ==> #t
Note: `
(flnegative? -0.0)
' must return#f
, else it would lose the correspondence with(fl< -0.0 0.0)
, which is#f
according to the IEEE standards.
flmax
fl1 fl2 ...
flmin
fl1 fl2 ...
These procedures return the maximum or minimum of their arguments.
fl+
fl1 ...
fl*
fl1 ...
These procedures return the flonum sum or product of their flonum arguments. In general, they should return the flonum that best approximates the mathematical sum or product. (For implementations that represent flonums as IEEE binary floating point numbers, the meaning of "best" is reasonably well-defined by the IEEE standards.)
(fl+ +inf.0 -inf.0) ==> +nan.0 (fl+ +nan.0 fl) ==> +nan.0 (fl* +nan.0 fl) ==> +nan.0
fl-
fl1 fl2 ...
fl-
fl
fl/
fl1 fl2 ...
fl/
fl
With two or more arguments, these procedures return the flonum difference or quotient of their flonum arguments, associating to the left. With one argument, however, they return the additive or multiplicative flonum inverse of their argument. In general, they should return the flonum that best approximates the mathematical difference or quotient. (For implementations that represent flonums as IEEE binary floating point numbers, the meaning of "best" is reasonably well-defined by the IEEE standards.)
(fl- +inf.0 +inf.0) ==> +nan.0
For undefined quotients, fl/
behaves as specified by the
IEEE standards:
(fl/ 1.0 0.0) ==> +inf.0 (fl/ -1.0 0.0) ==> -inf.0 (fl/ 0.0 0.0) ==> +nan.0
flabs
fl
This returns the absolute value of its argument.
fldiv+mod
fl1 fl2
fldiv
fl1 fl2
flmod
fl1 fl2
fldiv0+mod0
fl1 fl2
fldiv0
fl1 fl2
flmod0
fl1 fl2
These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in the section on Integer Division. For zero divisors, these procedures may return a NaN or some meaningless flonum.
(fldiv x1 x2) ==> x1 div x2 (flmod x1 x2) ==> x1 mod x2 (fldiv+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (fldiv0 x1 x2) ==> x1 div0 x2 (flmod0 x1 x2) ==> x1 mod0 x2 (fldiv0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
flnumerator
fl
fldenominator
fl
These procedures return the numerator or denominator of their argument as a flonum; the result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.
(flnumerator +inf.0) ==> +inf.0 (flnumerator -inf.0) ==> -inf.0 (fldenominator +inf.0) ==> 1.0 (fldenominator -inf.0) ==> 1.0 (flnumerator 0.75) ==> 3.0 ; example (fldenominator 0.75) ==> 4.0 ; exampleThe following behavior is strongly recommended but not required by R6RS:
(flnumerator -0.0) ==> -0.0
flfloor
fl
flceiling
fl
fltruncate
fl
flround
fl
These procedures return integral flonums for flonum arguments that are
not infinities or NaNs. For such arguments,
flfloor
returns the largest integral flonum not larger than fl.
Flceiling
returns the smallest integral flonum not smaller than fl.
Fltruncate
returns the integral flonum closest to fl whose absolute
value is not larger than the absolute value of fl. Flround
returns the
closest integral flonum to fl, rounding to even when fl is halfway between two
integers.
Rationale:
Flround
rounds to even for consistency with the default rounding mode specified by the IEEE floating point standard.
Although infinities and NaNs are not integers, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN:
(flfloor +inf.0) ==> +inf.0 (flceiling -inf.0) ==> -inf.0 (fltruncate +nan.0) ==> +nan.0
flexp
fl
fllog
fl
flsin
fl
flcos
fl
fltan
fl
flasin
fl
flatan
fl
flatan
fl1 fl2
These procedures compute the usual transcendental functions. Fllog
computes the natural logarithm of fl (not the base ten logarithm).
Flasin
, flacos
, and flatan
compute arcsine (sin-1),
arccosine (cos-1), and arctangent (tan-1), respectively.
`(flatan fl1 fl2)'
computes the
arc tangent of fl1/fl2. The range of
flatan
lies between -pi/2 and
pi/2, both inclusive if -0.0 is distinguished, both exclusive otherwise.
In general, the mathematical functions log, arcsine, arccosine, and arctangent are multiply defined. The value of log z is defined to be the one whose imaginary part lies in the range from -pi (exclusive) to pi (inclusive). With log defined this way, the values of sin-1 fl, cos-1 z, and tan-1 z are according to the following formulae:
sin-1 z = -i log (i z + sqrt(1 - z2))
cos-1 z = pi / 2 - sin-1 z
tan-1 z = (log (1 + i z) - log (1 - i z)) / (2 i)
If the function has a real-valued limit as its argument tends toward positive infinity, then that is the value returned by the function applied to +inf.0. If the function has a real-valued limit as its argument tends toward negative infinity, then that is the value returned by the function applied to -inf.0.
In the event that these formulae do not yield a real result for the given arguments, the result may be a NaN, or may be some meaningless flonum.
Implementations that use IEEE binary floating point arithmetic are encouraged to follow the relevant standards for these procedures.
Specifically, the range of `(flatan x
y)'
is as in the following table. The asterisk (*)
indicates that the entry applies to implementations that distinguish
minus zero.
y Condition | x Condition | Range of result | |
---|---|---|---|
y = 0.0 | x > 0.0 | 0.0 | |
* | y = +0.0 | x > 0.0 | +0.0 |
* | y = -0.0 | x > 0.0 | -0.0 |
y > 0.0 | x > 0.0 | 0.0 < result< pi/2 | |
y > 0.0 | x = 0.0 | pi/2 | |
y > 0.0 | x < 0.0 | pi/2 < result< pi | |
y = 0.0 | x < 0 | pi | |
* | y = +0.0 | x < 0.0 | +pi |
* | y = -0.0 | x < 0.0 | -pi |
y < 0.0 | x < 0.0 | -pi< result< -pi/2 | |
y < 0.0 | x = 0.0 | -pi/2 | |
y < 0.0 | x > 0.0 | -pi/2 < result< 0.0 | |
y = 0.0 | x = 0.0 | undefined | |
* | y = +0.0 | x = +0.0 | +0.0 |
* | y = -0.0 | x = +0.0 | -0.0 |
* | y = +0.0 | x = -0.0 | +pi |
* | y = -0.0 | x = -0.0 | -pi |
The above specification follows the branch cut specification of Common Lisp in [Pitman 1996], and [Steele 1990], which in turn cites [Penfield 1981]; refer to these sources for more detailed discussion of branch cuts, boundary conditions, and implementation of these functions.
(flexp +inf.0) ==> +inf.0 (flexp -inf.0) ==> 0.0 (fllog +inf.0) ==> +inf.0 (fllog 0.0) ==> -inf.0 (fllog -0.0) ==> unspecified ; if -0.0 is distinguished (fllog -inf.0) ==> +nan.0 (flatan -inf.0) ==> -1.5707963267948965 ; approximately (flatan +inf.0) ==> 1.5707963267948965 ; approximately
flsqrt
fl
Returns the principal square root of z. For a negative argument, the result may be a NaN, or may be some meaningless flonum.
(flsqrt +inf.0) ==> +inf.0
flexpt
fl1 fl2
Returns fl1 raised to the power fl2. For nonzero fl1
fl1fl2 = ez2 log z1
0fl is 1 if z = 0, and 0 if fl is positive. Otherwise, the result may be a NaN, or may be some meaningless flonum.
fixnum->flonum
fx
Returns a flonum that is numerically closest to its argument.
Note: The result of this procedure may not be numerically equal to its argument, because the fixnum precision may be greater than the flonum precision.
If the argument to fixnum->flonum
is not a fixnum,
then an error is signalled, unless the implementation is
running in unsafe mode, in which case all bets are off.
The exact arithmetic provides generic operations on exact numbers; these operations correspond to their mathematical counterparts. The exact numbers include rationals of arbitrary precision, and exact rectangular complex numbers. A rational number with a denominator of 1 is indistinguishable from its numerator. An exact rectangular complex number with a zero imaginary part is indistinguishable from its real part.
exact-number?
ex
exact-complex?
ex
exact-rational?
ex
exact-integer?
ex
These numerical type predicates can be applied to any kind of argument, including non-numbers. They return #t if the object is an exact number of the named type, and otherwise return #f. In general, if a type predicate is true of a number then all higher type predicates are also true of that number. Consequently, if a type predicate is false of a number, then all lower type predicates are also false of that number.
We will use ex, ex1, ex2, and ex3 as metavariables that range over the exact complex numbers, ef, ef1, ef2, and ef3 as metavariables that range over the exact rational numbers, and ei, ei1, ei2, and ei3 as metavariables that range over the exact integers.
If an argument to the following procedures that corresponds to an exact (rational, integer) metavariable is not actually an exact (rational, integer) number, then these procedures signal an error (and should signal an error even in unsafe mode).
exact=
ex1 ex2 ex3 ...
exact>?
ef1 ef2 ef3 ...
exact<?
ef1 ef2 ef3 ...
exact>=?
ef1 ef2 ef3 ...
exact<=?
ef1 ef2 ef3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing
#f
otherwise.
exact-zero?
ex
exact-positive?
ef
exact-negative?
ef
exact-odd?
ei
exact-even?
ei
These numerical predicates test an exact number for a particular property,
returning #t or #f.
Exact-zero?
tests if
the number is exact=?
to zero, exact-positive?
tests if it is greater
than zero, exact-negative?
tests if it is less
than zero, exact-odd?
tests if it is odd,
exact-even?
tests if it is even.
exact-max
ef1 ef2 ...
exact-min
ef1 ef2 ...
These procedures return the maximum or minimum of their arguments.
exact+
ex1 ex2 ...
exact*
ex1 ex2 ...
These procedures return the sum or product of their arguments.
exact-
ex1 ex2 ...
exact-
ex
exact/
ex1 ex2 ...
exact/
ex
With two or more arguments, these procedures return the difference or
quotient of their arguments, associating to the left. With one
argument, however, they return the additive or multiplicative inverse
of their argument. Exact/
signals an error
if a divisor is 0.
exact-abs
ef
This procedure returns the absolute value of its argument.
exact-div+mod
ef1 ef2
exact-div
ef1 ef2
exact-mod
ef1 ef2
exact-div0+mod0
ef1 ef2
exact-div0
ef1 ef2
exact-mod0
ef1 ef2
These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in the section on Integer Division. In each case, x1 must be neither infinite nor a NaN, and x2 must be nonzero; otherwise, an exception is raised.
(exact-div x1 x2) ==> x1 div x2 (exact-mod x1 x2) ==> x1 mod x2 (exact-div+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (exact-div0 x1 x2) ==> x1 div0 x2 (exact-mod0 x1 x2) ==> x1 mod0 x2 (exact-div0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
exact-gcd
ei1 ei2 ...
exact-lcm
ei1 ei2 ...
These procedures return the greatest common divisor or least common multiple of their arguments.
exact-numerator
ef
exact-denominator
ef
These procedures return the numerator or denominator of their argument. The result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.
exact-floor
ef
exact-ceiling
ef
exact-truncate
ef
exact-round
ef
These procedures return exact integers.
Exact-floor
returns the largest integer not larger than ef.
Exact-ceiling
returns the smallest integer not smaller than ef.
Exact-truncate
returns the integer closest to ef whose absolute
value is not larger than the absolute value of ef. Exact-round
returns the
closest integer to ef, rounding to even when ef is halfway between two
integers.
exact-expt
ef1 ei2
Returns ef1 raised to the power ei2. 0ei is 1 if ei = 0 and 0 if ei is positive. Otherwise, this procedure signals an error.
exact-make-rectangular
ex1 ex2
exact-real-part
ex
exact-imag-part
ex
The arguments of exact-make-rectangular
must be exact
rationals. Suppose z is a complex number such that
z = ef1 + ef2*i. Then:
(exact-make-rectangular ef1 ef2) ==> z (exact-real-part z) ==> ef1 (exact-imag-part z) ==> ef2
exact-integer-sqrt
ei
Ei must be a non-negative exact integer; if it is not, an
error is signalled. Exact-integer-sqrt
returns two
non-negative exact integers s and r where
ei = s2 + r and
ei < (s+1)2.
exact-not
ei
Returns the exact integer whose two's complement representation is the one's complement of the two's complement representation of its argument.
exact-and
ei1 ...
exact-ior
ei1 ...
exact-xor
ei1 ...
These procedures return the exact integer that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the integer (either -1 or 0) that acts as identity for the operation.
exact-if
ei1 ei2 ei3
Returns the exact integer that is the result of the following computation:
(exact-ior (exact-and ei1 ei2) (exact-and (exact-not ei1) ei3))
exact-bit-count
ei
If the argument is non-negative, this procedure returns the number of 1 bits in the two's complement representation of its argument. Otherwise it returns the number of 0 bits in the two's complement representation of its argument.
exact-length
ei
These procedures return the exact integer that is the result of the following computation:
(do ((result 0 (+ result 1)) (bits (if (exact-negative? ei) (exact- ei) ei) (exact-arithmetic-shift bits -1))) ((exact-zero? bits) result))
exact-first-bit-set
ei
This procedures returns the index of the least significant 1 bit in the two's complement representation of its argument. If the argument is 0, then -1 is returned.
(exact-first-bit-set 0) ==> -1 (exact-first-bit-set 1) ==> 0 (exact-first-bit-set -4) ==> 2
exact-bit-set?
ei1 ei2
If the second argument is negative, then an error is signalled. Otherwise returns the result of the following computation:
(not (exact-zero? (exact-and (exact-arithmetic-shift-left 1 ei2) ei1)))
exact-copy-bit
ei1 ei2 ei3
If the second argument is negative, or the third argument is anything other than 0 or 1, then an error is signalled. Otherwise returns the result of the following computation:
(let* ((mask (exact-arithmetic-shift-left 1 ei2))) (exact-if mask (exact-arithmetic-shift-left ei3 ei2) ei1))
exact-bit-field
ei1 ei2 ei3
If the second or third argument is negative, or the second argument is greater than the third, then an error is signalled. Otherwise returns the result of the following computation:
(let* ((mask (exact-not (exact-arithmetic-shift-left -1 ei3)))) (exact-arithmetic-shift-right (exact-and ei1 mask) ei2))
exact-copy-bit-field
ei1 ei2 ei3 ei4
If the second or third argument is negative, or the second argument is greater than the third, then an error is signalled. Otherwise returns the result of the following computation:
(let* ((to fx1) (start fx2) (end fx3) (from fx4) (mask1 (exact-logical-shift-left -1 start)) (mask2 (exact-not (exact-arithmetic-shift-left -1 end))) (mask (fixnum-and mask1 mask2))) (exact-if mask from to))
exact-arithmetic-shift
ei1 ei2
Returns the exact integer result of the following computation:
(exact-floor (* ei1 (expt 2 ei2)))
exact-arithmetic-shift-left
ei1 ei2
exact-arithmetic-shift-right
ei1 ei2
If the second argument is non-negative, then
exact-arithmetic-shift-left
returns the same result as exact-arithmetic-shift
,
and
(exact-arithmetic-shift-right fx1 fx2)
returns the same result as
(exact-arithmetic-shift fx1 (exact- fx2))
.
If the second argument is negative,
then an error is signalled.
exact-rotate-bit-field
ei1 ei2 ei3 ei4
If the second, third, and fourth arguments are non-negative, or the fourth argument is greater than or equal to the difference between the second and third arguments, then an error is signalled.
(let* ((n ei1) (start ei2) (end ei3) (count ei4) (width (exact- end start))) (if (exact-positive? width) (let* ((count (exact-mod count width)) (field0 (exact-bit-field n start end)) (field1 (exact-arithmetic-shift field0 count)) (field2 (exact-arithmetic-shift field0 (exact- width count))) (field (exact-ior field1 field2))) (exact-copy-bit-field n field start end)) n))
exact-reverse-bit-field
ei1 ei2 ei3
If the second or third argument is negative, or the second argument is greater than the third, then an error is signalled. Otherwise returns the result obtained from the first argument by reversing the bit field specified by the second and third arguments.
(exact-reverse-bit-field #b1010010 1 4) ==> 88 ; #b1011000 (exact-reverse-bit-field #b1010010 91 -4) ==> error
The inexact arithmetic provides generic operations on inexact numbers. The inexact numbers include inexact reals and inexact complex numbers, both of which are distinguishable from the exact numbers. The inexact complex numbers include the flonums, and the procedures described here behave consistently with the corresponding flonum procedures if passed flonum arguments.
inexact-number?
obj
inexact-complex?
obj
inexact-real?
obj
inexact-rational?
obj
inexact-integer?
obj
These numerical type predicates can be applied to any kind of argument, including non-numbers. They return #t if the object is an inexact number of the named type, and otherwise they return #f. In general, if a type predicate is true of a number then all higher type predicates are also true of that number. Consequently, if a type predicate is false of a number, then all lower type predicates are also false of that number.
We will use in, in1, in2, and in3 as metavariables that range over the inexact numbers, ir, ir1, ir2, and ir3 as metavariables that range over the inexact real numbers, if, if1, if2, and if3 as metavariables that range over the inexact rationals. and ii, ii1, ii2, and ii3 as metavariables that range over the inexact integers.
If an argument to the following procedures that corresponds to an inexact metavariable is not actually an inexact number, then these procedures signal an error (and should signal an error even in unsafe mode). The same holds true for arguments corresponding to inexact real metavariables.
inexact=?
in1 in2 in3 ...
inexact>?
ir1 ir2 ir3 ...
inexact<?
ir1 ir2 ir3 ...
inexact>=?
ir1 ir2 ir3 ...
inexact<=?
ir1 ir2 ir3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing
#f
otherwise. These
predicates are required to be transitive.
inexact-zero?
in
inexact-positive?
ir
inexact-negative?
ir
inexact-odd?
ii
inexact-even?
ii
inexact-finite?
in
inexact-infinite?
in
inexact-nan?
in
These numerical predicates test an inexact number for a particular property,
returning #t or #f.
Inexact-zero?
tests if
the number is inexact=?
to zero, inexact-positive?
tests if it is greater
than zero, inexact-negative?
tests if it is less
than zero, inexact-odd?
tests if it is odd,
inexact-even?
tests if it is even,
inexact-finite?
tests if it is not an infinity and not a NaN,
inexact-infinite?
tests if it is an infinity,
inexact-nan?
tests if it is a NaN.
inexact-max
ir1 ir2 ...
inexact-min
ir1 ir2 ...
These procedures return the maximum or minimum of their arguments.
inexact+
in1 in2 ...
inexact*
in1 in2 ...
These procedures return the sum or product of their arguments.
inexact-
in1 in2 ...
inexact-
in
inexact/
in1 in2 ...
inexact/
in
With two or more arguments, these procedures return the difference or quotient of their arguments, associating to the left. With one argument, however, they return the additive or multiplicative inverse of their argument.
inexact-abs
in
This procedure returns the absolute value of its argument.
inexact-div+mod
ir1 ir2
inexact-div
ir1 ir2
inexact-mod
ir1 ir2
inexact-div0+mod0
ir1 ir2
inexact-div0
ir1 ir2
inexact-mod0
ir1 ir2
These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in the section on Integer Division. In each case, x1 must be neither infinite nor a NaN, and x2 must be nonzero; otherwise, an exception is raised.
(inexact-div x1 x2) ==> x1 div x2 (inexact-mod x1 x2) ==> x1 mod x2 (inexact-div+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (inexact-div0 x1 x2) ==> x1 div0 x2 (inexact-mod0 x1 x2) ==> x1 mod0 x2 (inexact-div0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
inexact-gcd
ii1 ii2 ...
inexact-lcm
ii1 ii2 ...
These procedures return the greatest common divisor or least common multiple of their arguments.
inexact-numerator
if
inexact-denominator
if
These procedures return the numerator or denominator of their argument. The result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.
inexact-floor
ir
inexact-ceiling
ir
inexact-truncate
ir
inexact-round
ir
These procedures return inexact integers
for real arguments that are
not infinities or NaNs. For such arguments,
inexact-floor
returns the largest integer not larger than ir.
Inexact-ceiling
returns the smallest integer not smaller than ir.
Inexact-truncate
returns the integer closest to in whose absolute
value is not larger than the absolute value of in. Inexact-round
returns the
closest integer to in, rounding to even when in is halfway between two
integers.
Rationale:
Round
rounds to even for consistency with the default rounding mode specified by the IEEE floating point standard.
Although infinities and NaNs are not integers, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN.
inexact-exp
in
inexact-log
in
inexact-sin
in
inexact-cos
in
inexact-tan
in
inexact-asin
in
inexact-atan
in
inexact-atan
ir1 ir2
These procedures compute the usual transcendental functions. Inexact-log
computes the natural logarithm of in (not the base ten logarithm).
Inexact-asin
, Inexact-acos
, and Inexact-atan
compute arcsine (sin-1),
arccosine (cos-1), and arctangent (tan-1), respectively.
The two-argument variant of Inexact-atan
computes `(inexact-angle
(inexact-make-rectangular ir1 ir2))' (see below).
In general, the mathematical functions log, arcsine, arccosine, and arctangent are multiply defined. The value of log z is defined to be the one whose imaginary part lies in the range from -pi (inclusive if -0.0 is distinguished, exclusive otherwise) to pi (inclusive). With log defined this way, the values of sin-1 z, cos-1 z, and tan-1 z are according to the following formulae:
sin-1 z = -i log (i z + sqrt(1 - z2))
cos-1 z = pi / 2 - sin-1 z
tan-1 z = (log (1 + i z) - log (1 - i z)) / (2 i)
If the function has a real-valued limit as its argument tends toward
positive infinity, then that is the value returned by the function
applied to +inf.0
.
If the function has a real-valued limit as its argument tends toward
negative infinity, then that is the value returned by the function
applied to -inf.0
.
In the event that these formulae do
not yield a real result for the given arguments, the
result may be +nan.0
, or may be some meaningless inexact number.
Specifically, the range of `(inexact-atan x
y)'
is as in the following table. The asterisk (*)
indicates that the entry applies to implementations that distinguish
minus zero.
y Condition | x Condition | Range of result | |
---|---|---|---|
y = 0.0 | x > 0.0 | 0.0 | |
* | y = +0.0 | x > 0.0 | +0.0 |
* | y = -0.0 | x > 0.0 | -0.0 |
y > 0.0 | x > 0.0 | 0.0 < result< pi/2 | |
y > 0.0 | x = 0.0 | pi/2 | |
y > 0.0 | x < 0.0 | pi/2 < result< pi | |
y = 0.0 | x < 0 | pi | |
* | y = +0.0 | x < 0.0 | +pi |
* | y = -0.0 | x < 0.0 | -pi |
y < 0.0 | x < 0.0 | -pi< result< -pi/2 | |
y < 0.0 | x = 0.0 | -pi/2 | |
y < 0.0 | x > 0.0 | -pi/2 < result< 0.0 | |
y = 0.0 | x = 0.0 | undefined | |
* | y = +0.0 | x = +0.0 | +0.0 |
* | y = -0.0 | x = +0.0 | -0.0 |
* | y = +0.0 | x = -0.0 | +pi |
* | y = -0.0 | x = -0.0 | -pi |
The above specification follows the branch cut specification of Common Lisp in [Pitman 1996], and [Steele 1990], which in turn cites [Penfield 1981]; refer to these sources for more detailed discussion of branch cuts, boundary conditions, and implementation of these functions.
inexact-sqrt
in
Returns the principal square root of z. For a negative
argument, the result may be +nan.0
, or may be some
meaningless inexact number. With log defined as above,
the value of `(inexact-sqrt in)'
could be
expressed as
e(log in) / 2
inexact-expt
in1 in2
Returns in1 raised to the power in2. For nonzero in1
in1in2 = ein2 log in1
0.0z is 1 if z = 0.0, and 0.0 if `(inexact-real-part z)' is positive. Otherwise, this procedure reports a violation of an implementation restriction or returns an unspecified number.
inexact-make-rectangular
ir1 ir2
inexact-make-polar
ir1 ir2
inexact-real-part
in
inexact-imag-part
in
inexact-magnitude
in
inexact-angle
in
Suppose in1, in2, in3, and in4 are inexact rational numbers, and z is a complex number, such that z = in1 + in2*i = in3 * ei*in4. Then (inexactly):
(inexact-make-rectangular in1 in2) ==> z
(inexact-make-rectangular in3 in4) ==> z
(inexact-real-part z) ==> in1
(inexact-imag-part z) ==> in2
(inexact-magnitude z) ==> |in3|
(inexact-angle z) ==> inangle
where -pi <= inangle <= pi with inangle = in4 + 2pi n for some integer n.
(inexact-angle -1.0) ==> pi (inexact-angle -1.0+0.0) ==> pi (inexact-angle -1.0-0.0) ==> -pi ; if -0.0 is distinguished
Moreover, suppose in1, in2 are such that either in1 or in2 is an infinity, then
(inexact-make-rectangular in1 in2) ==> z (inexact-magnitude z) ==> +inf.0
The section on exactness reads as follows:
Scheme numbers are either exact or inexact. A number is exact if it was written as an exact constant or was derived from exact numbers using only exact operations.A number is inexact if it is infinite, if it was written as an inexact constant, if it was derived using inexact ingredients, or if it was derived using inexact operations. Thus inexactness is a contagious property of a number.A number is inexact if it was written as an inexact constant or was derived from inexact numbers. Thus inexactness is contagious. The generic operations generally return the correct exact result when all of their arguments are exact and the result is mathematically well-defined, but return an inexact result when any argument is inexact. Exceptions aresqrt
,exp
,log
,sin
,cos
,tan
,asin
,acos
,atan
,expt
,make-polar
,magnitude
, andangle
, which are allowed (but not required) to return inexact results even when given exact arguments, as indicated in the specification of these procedures.One general exception to the rule above is that an implementation may return an exact result despite inexact arguments if that exact result would be the correct result for all possible substitutions of exact arguments for the inexact ones.
Each exact number corresponds to a single mathematical number. It is the programmer's responsibility to avoid using exact numbers with magnitude or precision too large to be represented in the implementation. For inexact numbers, it is the programmer's responsibility to avoid using complex numbers with magnitude too large to be represented in the implementation.It is the programmer's responsibility to avoid using numbers with magnitude or significand too large to be represented in the implementation.
If two implementations produce exact results for a computation that did not involve inexact intermediate results, the two ultimate results will be mathematically equivalent. This is generally not true of computations involving inexact numbers because approximate methods such as floating point arithmetic may be used, but it is the duty of each implementation to make the result as close as practical to the mathematically ideal result.
Rational operations such as
+
should always produce exact results when given exact arguments.If the operation is unable to produce an exact result, then it may either report the violation of an implementation restriction or it may silently coerce its result to an inexact value. See section 6.2.3.
With the exception ofinexact->exact
exact-round
,exact-ceiling
,exact-floor
, andexact-truncate
, the operations described in this section must return inexact results when given any inexact arguments.
The procedures described here behave consistently with the
corresponding inexact-
procedure if passed inexact
arguments, and
with the corresponding exact-
procedure if passed exact
arguments.
We will use z, z1, z2, and z3 as metavariables that range over the complex numbers, x, x1, x2, and x3 as metavariables that range over the real numbers, q, q1, q2, and q3 as metavariables that range over the rationals. and n, n1, n2, and n3 as metavariables that range over the inexact integers.
If an argument to the following procedures that corresponds to a metavariable is not in the set specified for that metavariable, then these procedures signal an error (and should signal an error even in unsafe mode).
=
z1 z2 z3 ...
<
x1 x2 x3 ...
>
x1 x2 x3 ...
<=
x1 x2 x3 ...
>=
x1 x2 x3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing
#f
otherwise.
(= +inf.0 +inf.0) ==> #t (= -inf.0 +inf.0) ==> #f (= -inf.0 -inf.0) ==> #tFor any real number x that is neither infinite nor NaN:
(< -inf.0 x +inf.0)) ==> #t (> +inf.0 x -inf.0)) ==> #t
These predicates are required to be transitive.
Note: The traditional implementations of these predicates in Lisp-like languages are not transitive.
Note: While it is not an error to compare inexact numbers using these predicates, the results may be unreliable because a small inaccuracy may affect the result; this is especially true of
=
andzero?
. When in doubt, consult a numerical analyst.
zero?
z
positive?
x
negative?
x
odd?
n
even?
n
finite?
x
infinite?
x
nan?
x
These numerical predicates test a number for a particular property,
returning #t or #f. See note above.
Zero?
tests if
the number is =
to zero, positive?
tests if it is greater
than zero, negative?
tests if it is less
than zero, odd?
tests if it is odd,
even?
tests if it is even,
finite?
tests if it is not an infinity and not a NaN,
infinite?
tests if it is an infinity,
nan?
tests if it is a NaN.
(positive? +inf.0) ==> #t (negative? -inf.0) ==> #t (finite? +inf.0) ==> #f (finite? 5) ==> #t (finite? 5.0) ==> #t (infinite? 5.0) ==> #f (infinite? +inf.0) ==> #t
max
x1 x2 ...
min
x1 x2 ...
These procedures return the maximum or minimum of their arguments.
(max 3 4) ==> 4 ; exact (max 3.9 4) ==> 4.0 ; inexactFor any real number x:
(max +inf.0 x) ==> +inf.0 (min -inf.0 x) ==> -inf.0
Note: If any argument is inexact, then the result will also be inexact (unless the procedure can prove that the inaccuracy is not large enough to affect the result, which is possible only in unusual implementations). If
min
ormax
is used to compare numbers of mixed exactness, and the numerical value of the result cannot be represented as an inexact number without loss of accuracy, then the procedure may report a violation of an implementation restriction.
+
z1 ...
*
z1 ...
These procedures return the sum or product of their arguments.
(+ 3 4) ==> 7 (+ 3) ==> 3 (+) ==> 0 (+ +inf.0 +inf.0) ==> +inf.0 (+ +inf.0 -inf.0) ==> +nan.0 (* 4) ==> 4 (*) ==> 1 (* 5 +inf.0) ==> +inf.0 (* -5 +inf.0) ==> -inf.0 (* +inf.0 +inf.0) ==> +inf.0 (* +inf.0 -inf.0) ==> -inf.0 (* 0 +inf.0) ==> 0 or +nan.0 (* 0 +nan.0) ==> 0 or +nan.0For any real number x that is neither infinite nor NaN:
(+ +inf.0 x) ==> +inf.0
(+ -inf.0 x) ==> -inf.0
(+ +nan.0 x) ==> +nan.0
For any real number x that is neither
infinite nor NaN nor 0:
(* +nan.0 x) ==> +nan.0
If any of these procedures are applied to mixed non-rational real and non-real complex arguments, they either report a violation of an implementation restriction or return an unspecified number.
-
z
-
z1 z2 ...
/
z
/
z1 z2 ...
With two or more arguments, these procedures return the difference or quotient of their arguments, associating to the left. With one argument, however, they return the additive or multiplicative inverse of their argument.
(- 3 4) ==> -1 (- 3 4 5) ==> -6 (- 3) ==> -3 (- +inf.0 +inf.0) ==> +nan.0 (/ 3 4 5) ==> 3/20 (/ 3) ==> 1/3 (/ 0.0) ==> +inf.0 (/ 1.0 0) ==> +inf.0 or error (/ -1 0.0) ==> -inf.0 (/ +inf.0) ==> 0.0 (/ 0 0.0) ==> +nan.0 0 or +nan.0 (/ 0.0 0) ==> +nan.0 or error (/ 0.0 0.0) ==> +nan.0
If any of these procedures are applied to mixed non-rational real and non-real complex arguments, they either report a violation of an implementation restriction or return an unspecified number.
abs
x
Abs
returns the absolute value of its argument.
(abs -7) ==> 7 (abs -inf.0) ==> +inf.0
div+mod
x1 x2
div
x1 x2
mod
x1 x2
div0+mod0
x1 x2
div0
x1 x2
mod0
x1 x2
These procedures implement number-theoretic integer division and return the results of the corresponding mathematical operations specified in the section on Integer Division. In each case, x1 must be neither infinite nor a NaN, and x2 must be nonzero; otherwise, an exception is raised.
(div x1 x2) ==> x1 div x2 (mod x1 x2) ==> x1 mod x2 (div+mod x1 x2) ==> x1 div x2, x1 mod x2 ; two return values (div0 x1 x2) ==> x1 div0 x2 (mod0 x1 x2) ==> x1 mod0 x2 (div0+mod0 x1 x2) ==> x1 div0 x2, x1 mod0 x2 ; two return values
gcd
lcm
Note: This is the R5RS definition.
These procedures return the greatest common divisor or least common multiple of their arguments. The result is always non-negative.
For exact integer arguments, these procedures are the familiar number
theoretic operators:
(gcd 32 -36) ==> 4 (gcd) ==> 0 (lcm 32 -36) ==> 288 (lcm 32.0 -36) ==> 288.0 ; inexact (lcm) ==> 1
numerator
q
denominator
q
These procedures return the numerator or denominator of their argument; the result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.
(numerator (/ 6 4)) ==> 3 (denominator (/ 6 4)) ==> 2 (denominator (exact->inexact (/ 6 4))) ==> 2.0
floor
x
ceiling
x
truncate
x
round
x
These procedures accept finite real numbers and return integers.
These procedures return inexact integers on
inexact arguments that are not infinities or NaNs,
and exact integers on exact rational arguments.
For such arguments,
floor
returns the largest integer not larger than x.
Ceiling
returns the smallest integer not smaller than x.
Truncate
returns the integer closest to x whose absolute
value is not larger than the absolute value of x. Round
returns the
closest integer to x, rounding to even when x is halfway between two
integers.
Rationale:
Round
rounds to even for consistency with the default rounding mode specified by the IEEE floating point standard.
Note: If the argument to one of these procedures is inexact, then the result will also be inexact. If an exact value is needed, the result should be passed to the
inexact->exact
procedure.
Although infinities and NaNs are not integers, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN.
(floor -4.3) ==> -5.0 (ceiling -4.3) ==> -4.0 (truncate -4.3) ==> -4.0 (round -4.3) ==> -4.0 (floor 3.5) ==> 3.0 (ceiling 3.5) ==> 4.0 (truncate 3.5) ==> 3.0 (round 3.5) ==> 4.0 ; inexact (round 7/2) ==> 4 ; exact (round 7) ==> 7 (floor +inf.0) ==> +inf.0 (ceiling -inf.0) ==> -inf.0 (round +nan.0) ==> +nan.0
rationalize
x y
Rationalize
returns the simplest rational number
differing from x by no more than y. A rational number r1 is
simpler than another rational number
r2 if r1 = p1/q1 and r2 = p2/q2
(in lowest terms) and |p1|<= |p2| and |q1| <= |q2|.
Thus 3/5 is simpler than 4/7.
Although not all rationals are comparable in this ordering (consider 2/7
and 3/5) any interval contains a rational number that is simpler than
every other rational number in that interval (the simpler 2/5 lies
between 2/7 and 3/5). Note that 0 = 0/1 is the simplest rational of
all.
(rationalize (inexact->exact .3) 1/10) ==> 1/3 ; exact (rationalize .3 1/10) ==> #i1/3 ; inexact (rationalize +inf.0 3) ==> +inf.0 (rationalize +inf.0 +inf.0) ==> +nan.0 (rationalize 3 +inf.0) ==> 0.0
exp
z
log
z
sin
z
cos
z
tan
z
asin
z
acos
z
atan
z
atan
y x
These procedures compute the usual transcendental functions.
Exp
computes the base-e exponential
of z.
Log
computes the natural logarithm of z (not the base ten logarithm).
Asin
, acos
, and atan
compute arcsine (sin-1),
arccosine (cos-1), and arctangent (tan-1), respectively.
The two-argument variant of `atan' computes (angle
(make-rectangular x y)) (see below), even in implementations
that don't support general complex numbers.
In general, the mathematical functions log, arcsine, arccosine, and
arctangent are multiply defined. The value of log z is
defined to be the one whose imaginary part lies in the range from -pi
(exclusive) (inclusive if -0.0 is
distinguished, exclusive otherwise) to pi (inclusive).
The value of log z for non-real z is defined in terms of log on real numbers as
log z = log |z| + xanglei
where xangle is the angle of z as specified below.
With log defined this way, the values of sin-1 z, cos-1 z, and tan-1 z are according to the following formulae:
sin-1 z = -i log (i z + sqrt(1 - z2))
cos-1 z = pi / 2 - sin-1 z
tan-1 z = (log (1 + i z) - log (1 - i z)) / (2 i)
If the function has a real-valued limit as its argument tends toward
positive infinity, then that is the value returned by the function
applied to +inf.0
.
If the function has a real-valued limit as its argument tends toward
negative infinity, then that is the value returned by the function
applied to -inf.0
.
These procedures may return inexact results even when given exact arguments.
In the event that these formulae do
not yield a real result for the given arguments, the
result may be +nan.0
, or may be some meaningless inexact
number.
Specifically, the range of `(atan x
y)'
is as in the following table. The asterisk (*)
indicates that the entry applies to implementations that distinguish
minus zero.
y Condition | x Condition | Range of result | |
---|---|---|---|
y = 0.0 | x > 0.0 | 0.0 | |
* | y = +0.0 | x > 0.0 | +0.0 |
* | y = -0.0 | x > 0.0 | -0.0 |
y > 0.0 | x > 0.0 | 0.0 < result< pi/2 | |
y > 0.0 | x = 0.0 | pi/2 | |
y > 0.0 | x < 0.0 | pi/2 < result< pi | |
y = 0.0 | x < 0 | pi | |
* | y = +0.0 | x < 0.0 | +pi |
* | y = -0.0 | x < 0.0 | -pi |
y < 0.0 | x < 0.0 | -pi< result< -pi/2 | |
y < 0.0 | x = 0.0 | -pi/2 | |
y < 0.0 | x > 0.0 | -pi/2 < result< 0.0 | |
y = 0.0 | x = 0.0 | undefined | |
* | y = +0.0 | x = +0.0 | +0.0 |
* | y = -0.0 | x = +0.0 | -0.0 |
* | y = +0.0 | x = -0.0 | +pi |
* | y = -0.0 | x = -0.0 | -pi |
* | y = +0.0 | x = 0 | pi/2 |
* | y = -0.0 | x = 0 | -pi/2 |
The above specification follows the branch cut specification of Common Lisp in [Pitman 1996], and [Steele 1990], which in turn cites [Penfield 1981]; refer to these sources for more detailed discussion of branch cuts, boundary conditions, and implementation of these functions.
(exp +inf.0) ==> +inf.0 (exp -inf.0) ==> 0.0 (log +inf.0) ==> +inf.0 (log 0.0) ==> -inf.0 (log 0) is an error (log -inf.0) ==> +nan.0 +inf.0+pii (atan -inf.0) ==> -1.5707963267948965 ; approximately (atan +inf.0) ==> 1.5707963267948965 ; approximately (log -1.0+0.0i) ==> 0.0+pii (log -1.0-0.0i) ==> 0.0-pii ; if -0.0 is distinguished
The functions
sin
, cos
, tan
,
asin
, and acos
either return
+nan.0
or
report a violation of an implementation restriction
when given +inf.0
,
-inf.0
, or +nan.0
as an argument.
sqrt
z
Returns the principal square root of z. For real rational z, the
result will have either positive real part, or zero real part and
non-negative imaginary part.
With log defined as above,
the value of `(sqrt in)'
could be
expressed as
e(log in) / 2
Sqrt
may return an inexact result even when given
an exact argument.
(sqrt -5) ==> 0.0+2.23606797749979i (sqrt +inf.0) ==> +inf.0 (sqrt -inf.0) ==> +nan.0 +inf.0i
expt
z1 z2
Returns z1 raised to the power z2. For nonzero z1
z1z2 = ez2 log z1
0z is 1 if z = 0, and 0 if `(real-part z)' is positive. Otherwise, this procedure reports a violation of an implementation restriction or returns an unspecified number.
For an exact z1 and an exact integer z2, `(expt z1 z2)' must return an exact result. For all other values of z1 and z2, `(expt z1 z2)' may return an inexact result, even when both z1 and z2 are exact.
0^0 is 1.
For inexact arguments not both zero
(define (expt z1 z2) (exp (* (if (zero? z1) (real-part z2) z2) (log z1))))
(expt 0.0 z)
(expt 5 3) ==> 125 (expt 5 -3) ==> 1/125 (expt 5 0) ==> 1 (expt 0 5) ==> 0 (expt 0 5+.0000312i) ==> 0 (expt 0 -5) ==> +inf.0 unspecified (expt 0 -5+.0000312i) ==> +inf.0 unspecified (expt 0 0) ==> +nan.0 1 (expt 0.0 0.0) ==> +nan.0 1.0
make-rectangular
x1 x2
make-polar
x3 x4
real-part
z
imag-part
z
magnitude
z
angle
z
These procedures are part of every implementation that supports
general
complex numbers. Suppose x1, x2, x3, and x4 are
real numbers and z is a complex number such that
z = x1 + i x2 = x3 ei x4
Then
(make-rectangular x1 x2) ==> z
(make-polar x3 x4) ==> z
(real-part z) ==> x1
(imag-part z) ==> x2
(magnitude z) ==> |x3|
(angle z) ==> xangle
where -pi <<= xangle
<= pi with xangle = in4 + 2pi
n for some integer n.
Moreover, suppose x1, x2 are such that either x1 or x2 is an infinity, then
(make-rectangular x1 x2) ==> z (magnitude z) ==> +inf.0
Make-polar
, magnitude
, and
angle
may return inexact results even when given exact
arguments.
(angle -1) ==> pi (angle +inf.0) ==> 0.0 (angle -inf.0) ==> pi (angle -1.0+0.0) ==> pi (angle -1.0-0.0) ==> -pi ; if -0.0 is distinguished
Rationale:.Magnitude
is the same asabs
for a real argument, butabs
must be present in all implementations, whereasmagnitude
need only be present in implementations that support general complex numbers
Background and Rationale concerning two issues of R6RS arithmetic (written by William D Clinger, 29 July 2005)
(Most experts who read this note will want to start with the section Problems With Flow Analysis, thereby skipping the history and background information that is intended to make this note more self-contained and accessible.)
In 1998, for the Scheme workshop before ICFP '98 in Baltimore, Brad Lucier proposed several changes that were intended to bring Scheme's inexact arithmetic into line with the IEEE floating point standards and with other recommended practice for transcendental functions and complex arithmetic. Most of Lucier's proposals would have applied only to implementations that use IEEE floating point for inexact arithmetic, and would thus act as recommendations, much like the appendices on inexact arithmetic that were published with the IEEE standard for Scheme. A few of Lucier's proposals would have required changes to the Scheme standards themselves, however.
Few of the workshop attendees knew enough about the IEEE floating point standards to discuss Lucier's proposal. A straw poll was taken, and came out 31-0 in favor of bringing Scheme into line with IEEE floating point and with current practice, trusting experts to work out the details.
Here are the highlights of Lucier's proposal, taken verbatim from my notes on the 1998 workshop:
The behavior of
eqv?
on inexact numbers would change. If x and y are inexact reals represented as IEEE floating point numbers, then`(eqv? x y)'
would be true if and only if x and y are equal and have the same base, sign, number of bits in the exponent, number of bits in the significand, and the same biased exponents and significands. For example,`(eqv? +0. -0.)
would be false, as would`(eqv? 1e8 1d8)'
in an implementation for which1d8
has more precision than1e8
. In most implementations`(eqv? x y)'
would be computed by a bit-level comparison of the floating point representations for x and y.
`(real? 4.3+0.i)'
and`(real? 4.3-0.i)'
would be false, although`(real? 4.3+0i)'
and`(real? 4.3-0i)'
would remain true (assuming an implementation allows the real and imaginary parts of a complex number to have a different exactness, which is not required by the Scheme standards and would not be required by Lucier's proposal).
Truncate
,round
,ceiling
, andfloor
would be defined only on rationals, not on all reals. The motivation for this is that infinities and NaNs would be reals but not rationals, and there is no meaningful integer value that these procedures could return for infinities and NaNs. Similarly the first argument torationalize
would be required to be a rational.The branch cuts for certain transcendental functions would change to conform to current practice.
Kahan reportedly would like for
`(max 1 +nan.0 2)'
to return 2 instead of+nan.0
, but this would conflict with the guiding principle of Scheme's inexact arithmetic so I oppose this. Returning an inexact2.0
would be consistent with Scheme's arithmetic, and would not require any changes to the Scheme standards.
The purpose of this note is to explain why it is desirable for Scheme's reals to have an exact zero as their imaginary part.
This note also discusses whether the proposed "flonum" type should be a synonym for "inexact real", or merely a subset of the inexact reals.
Scheme's numerical types are the exactness types { exact, inexact }, the tower types { integer, rational, real, complex, number }, and the Cartesian product of the exactness types with the tower types, where < t1, t2 > is regarded as a subtype of both t1 and t2.
These types have an aesthetic symmetry to them, but they are not equally important. Judging by the number of R5RS procedures whose domain is restricted to values of some numerical type, the most important numerical types are the exact integers, the integers, the rationals, the reals, and the complex numbers.
Many programmers and implementors regard R5RS's focus on those particular numerical types as something of a mistake. In practice, there is reason to believe that the most important numerical types are the exact integers, the exact rationals, the inexact reals, and the inexact complex numbers. The following section explores one of the reasons those four types are so important in practice.
Scheme's types are not completely arbitrary. Each type corresponds to a set of values that turns up repeatedly as the natural domain or range of the functions that are computed by Scheme's standard procedures. The reason these types turn up so often is that they are closed under certain sets of operations.
The exact integers, for example, are closed under the integral
operations of addition, subtraction, and multiplication. The
exact rationals are closed under the rational operations, which
consist of the integral operations plus division (although we
must make a special case for division by zero). The reals (and
inexact reals) are closed under some (often inexact) interpretation
of rational and irrational operations such as exp and sin, but are
not closed under operations such as log
, sqrt
, and expt
. The complex
(and inexact complex) numbers are closed under the largest set
of operations.
The Scheme standards give implementations considerable freedom with respect to the representation of expressed values, but the usual approach is to represent the numerical types as unions of the representation types that appear on the right hand sides of the following domain equations:
exact integer | = | fixnum + bignum |
exact rational | = | fixnum + bignum + ratnum |
inexact real | = | flonum |
inexact complex | = | flonum + compnum |
integer | = | fixnum + bignum + subset of flonum |
rational | = | fixnum + bignum + ratnum + subset of flonum |
real | = | fixnum + bignum + ratnum + flonum |
complex | = | rectangular + compnum |
These domain equations are typical of most implementations, but many variations are possible. The flonum representation type, for example, is often divided into several distinct precisions.
A naive implementation of Scheme's arithmetic operations is slow compared to the arithmetic operations of most other languages, mainly because most operations must perform some sort of case dispatch on the representation types of their arguments. The potential for this case dispatch arises when the type of an operation's argument is represented by a union of two or more representation types, or because the operation is required to signal an error when given an argument of an incorrect type. (The second reason can be regarded as a special case of the first.)
To make Scheme's arithmetic more efficient, many implementations provide sets of operations whose domain is restricted to a single representation type, and which are not expected to signal an error when given arguments of incorrect type.
Alternatively, or in addition, several compilers perform some kind of flow analysis that attempts to infer the representation types of expressions. When a single representation type can be inferred for each argument of an operation, and those types match the types expected by some representation-specific version of the operation, then the compiler can substitute the specific version for the more general version that was specified in the source code.
Flow analysis is performed by solving the type and interval constraints that arise from such things as:
`(if (< i n) E1 E2)'
`(if (real? x) <real_case> <unreal_case>)'
`(+ <flonum> <flonum>)'
always evaluates to a flonum)
The purpose of flow analysis (as motivated in this note) is to infer a single representation type for each argument of an operation. That places a premium on predicates and closure properties from which a single representation type can be inferred.
In practice, the most important single representation types are fixnum, flonum, and compnum. These are the representation types for which a short sequence of machine code can be generated when the representation type is known, but for which considerably less efficient code will probably have to be generated when the representation type cannot be inferred.
The fixnum representation type is not closed under any R5RS operations, so it is hard for flow analysis to infer the fixnum type from portable R5RS code. Sometimes the combination of a more general type (e.g. exact integer) and an interval (e.g. [0,n), where n is known to be a fixnum) can imply the fixnum representation type. Adding fixnum-specific operations that map fixnums to fixnums (by computing modulo 2^n, say) greatly increases the number of fixnum representation types that a compiler can infer.
The flonum representation type is not closed under operations
such as sqrt
and expt
, so flow analysis tends to break down in
the presence of those operations. This is unfortunate, because
those operations are normally used only with arguments for which
the result is expected to be a flonum. Adding flonum-specific
versions such as flsqrt
and flexpt
improves the effectiveness
of flow analysis.
The R5RS creates a more insidious problem by defining `(real? z)'
to be true if and only if `(zero? (imag-part z))'
is true. This
means, for example, that -2.5+0.0i
is real. If -2.5+0.0i
is
represented as a compnum, then the compiler cannot rely on x
being a flonum during the <real_case> of
`(if (real? x) <real_case> <unreal_case>)'
. This problem could
be fixed by writing all of the arithmetic operations so that
any compnum with a zero imaginary part is converted to a flonum
before it is returned, but that merely creates an analogous
problem for compnum arithmetic, as explained below. A better
way to fix the problem is as Lucier recommended: change the
definition of Scheme's real numbers by defining `(real? z)'
to
be true if and only if `(imag-part z)'
is an exact zero.
The compnum representation type is closed under virtually all operations, provided no operation that accepts two compnums as its argument ever returns a flonum. To work around the problem described in the paragraph above, several implementations automatically convert compnums with a zero imaginary part to the flonum representation. This practice virtually destroys the effectiveness of flow analysis for inferring the compnum representation, so it is not a good workaround. To improve the effectiveness of flow analysis, it is better to change the definition of Scheme's real numbers as described in the paragraph above.
To improve the effectiveness of flow analysis and to improve the efficiency of arithmetic, I recommend that the R6RS:
fx+
fl+
`(imag-part 2.0)'
is an exact zero
When flonum-specific operations are added to Scheme, should they take any inexact real as arguments? Or should their arguments be restricted to some subtype of the inexact reals?
Another way to describe this issue is to specify that the flonum-specific operations take flonums as arguments and return flonums as results. Then the question becomes: Are the flonums coextensive with the inexact reals? Or are the flonums allowed to be a proper subset of the inexact reals?
I do not think this question is terribly important. Most current implementations have only one representation for inexact reals, and having only one representation for the inexact reals improves the effectiveness of flow analysis, so implementations that try to provide efficient arithmetic on inexact reals are likely to make "flonum" synonymous with "inexact real" even if the R6RS allows otherwise.
One reason for allowing "flonum" to be a proper subtype of "inexact real" is to give implementations freedom to experiment with unusual representation strategies. Another possibility is that an implementation might take "flonum" to mean the representation that is supported most efficiently by the hardware, e.g. IEEE double precision, while providing other precisions that might be more space-efficient for certain applications.
On the other hand, defining "flonum" to be a synonym for
"inexact real" would simplify the presentation of flonum
arithmetic, and would eliminate a couple of procedures that
would otherwise have to be provided and somehow specified
(e.g. real->flonum
and flonum?
).
I recommend that the R6RS define "flonum" as a synonym for "inexact real", but this is not a strong recommendation. It doesn't matter very much.
The reference implementation contains a reference implementation for most of the procedures described here, written in mostly R5RS Scheme, and based purely on integer and flonum arithmetic of the underlying Scheme implementation. It builds the entire numeric tower on fixnums and flonums. The code is set up to run under Scheme 48, but should be easy to adapt to other Scheme systems. It will be completed upon withdrawal of this SRFI.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.