TOC »
SRFI 144: Flonums
Abstract
This SRFI describes numeric procedures applicable to flonums, a subset of the inexact real numbers provided by a Scheme implementation. In most Schemes, the flonums and the inexact reals are the same. These procedures are semantically equivalent to the corresponding generic procedures, but allow more efficient implementations.
Rationale
Flonum arithmetic is already supported by many systems, mainly to remove type-dispatching overhead. Standardizing flonum arithmetic increases the portability of code that uses it. Standardizing the range or precision of flonums would make flonum operations inefficient on some systems, which would defeat their purpose. Therefore, this SRFI specifies some of the semantics of flonums, but makes the range and precision implementation-dependent. However, this SRFI, unlike C99, does assume that the floating-point radix is 2.
The source of most of the variables and procedures in this SRFI is the C99/Posix <math.h> library, which should be available directly or indirectly to Scheme implementers. (Note: the C90 version of <math.h> lacks arcsinh, arccosh, arctanh, erf, and tgamma.)
In addition, some procedures and variables are provided from the R6RS flonum library, the Chicken flonum routines, and the Chicken mathh egg. Lastly, a few procedures are flonum versions of R7RS-small numeric procedures.
The SRFI text is by John Cowan; the portable implementation is by Will Clinger.
Specification
It is required that all flonums have the same range and precision. That is, if 12.0f0 is a 32-bit inexact number and 12.0 is a 64-bit inexact number, they cannot both be flonums. In this situation, it is recommended that the 64-bit numbers be flonums.
When a C99 variable, procedure, macro, or operator is specified for a procedure in this SRFI, the semantics of the Scheme variable or procedure are the same as its C equivalent. The definitions given here of such procedures are informative only; for precise definitions, users and implementers must consult the Posix or C99 standards. This applies particularly to the behavior of these procedures on -0.0, +inf.0, -inf.0, and +nan.0. However, conformance to this SRFI does not require that these numbers exist or are flonums.
When a variable is bound to, or a procedure returns, a mathematical expression, it is understood that the value is the best flonum approximation to the mathematically correct value.
It is an error, except as otherwise noted, for an argument not to be a flonum. If the mathematically correct result is not a real number, the result is +nan.0 if the implementation supports that number, or an arbitrary flonum if not.
Flonum operations must be at least as accurate as their generic counterparts when applied to flonum arguments. In some cases, operations should be more accurate than their naive generic expansions because they have a smaller total roundoff error.
This SRFI uses x, y, z as parameter names for flonum arguments. Exact integer parameters are designated n.
Mathematical Constants
The following (mostly C99) constants are provided as Scheme variables.
- fl-econstant
Bound to the mathematical constant e. (C99 M_E)
- fl-1/econstant
Bound to 1/e. (C99 M_E)
- fl-e-2constant
Bound to e^2.
- fl-e-pi/4constant
Bound to e^(π/4).
- fl-log2-econstant
Bound to log2(e). (C99 M_LOG2E)
- fl-log10-econstant
Bound to log10(e). (C99 M_LOG10E)
- fl-log-2constant
Bound to ln(2). (C99 M_LN2)
- fl-1/log-2constant
Bound to 1/ln(2). (C99 M_LN2)
- fl-log-3constant
Bound to ln(3).
- fl-log-piconstant
Bound to ln(π).
- fl-log-10constant
Bound to ln(10). (C99 M_LN10)
- fl-1/log-10constant
Bound to 1/ln(10). (C99 M_LN10)
- fl-piconstant
Bound to the mathematical constant π. (C99 M_PI)
- fl-1/piconstant
Bound to 1/π. (C99 M_1_PI)
- fl-2piconstant
Bound to 2π.
- fl-pi/2constant
Bound to π/2. (C99 M_PI_2)
- fl-pi/4constant
Bound to π/4. (C99 M_PI_4)
- fl-pi-squaredconstant
Bound to π^2.
- fl-degreeconstant
Bound to π/180, the number of radians in a degree.
- fl-2/piconstant
Bound to 2/π. (C99 M_2_PI)
- fl-2/sqrt-piconstant
Bound to 2/√π. (C99 M_2_SQRTPI)
- fl-sqrt-2constant
Bound to √2. (C99 M_SQRT2)
- fl-sqrt-3constant
Bound to √3.
- fl-sqrt-5constant
Bound to √5.
- fl-sqrt-10constant
Bound to √10.
- fl-1/sqrt-2constant
Bound to 1/√2. (C99 M_SQRT1_2)
- fl-cbrt-2constant
Bound to ∛2.
- fl-cbrt-3constant
Bound to ∛3.
- fl-4thrt-2constant
Bound to ∜2.
- fl-phiconstant
Bound to the mathematical constant φ.
- fl-log-phiconstant
Bound to log(φ).
- fl-1/log-phiconstant
Bound to 1/log(φ).
- fl-eulerconstant
Bound to the mathematical constant γ (Euler's constant).
- fl-e-eulerconstant
Bound to e^γ.
- fl-sin-1constant
Bound to sin(1).
- fl-cos-1constant
Bound to cos(1).
- fl-gamma-1/2constant
Bound to Γ(1/2).
- fl-gamma-1/3constant
Bound to Γ(1/3).
- fl-gamma-2/3constant
Bound to Γ(2/3).
Implementation Constants
- fl-greatestconstant
- fl-leastconstant
Bound to the largest/smallest positive finite flonum. (e.g. C99 DBL_MAX and C11 DBL_TRUE_MIN)
- fl-epsilonconstant
Bound to the appropriate machine epsilon for the hardware representation of flonums. (C99 DBL_EPSILON in <float.h>)
- fl-fast-fl+*constant
Bound to #t if (fl+* x y z) executes about as fast as, or faster than, (fl+ (fl* x y) z); bound to #f otherwise. (C99 FP_FAST_FMA)
So that the value of this variable can be determined at compile time, R7RS implementations and other implementations that provide a features function should provide the feature fl-fast-fl+* if this variable is true, and not if it is false or the value is unknown at compile time.
- fl-integer-exponent-zeroconstant
Bound to whatever exact integer is returned by (flinteger-exponent 0.0). (C99 FP_ILOGB0)
- fl-integer-exponent-nanconstant
Bound to whatever exact integer is returned by (flinteger-exponent +nan.0). (C99 FP_ILOGBNAN)
Constructors
- flonum numberprocedure
If number is an inexact real number and there exists a flonum that is the same (in the sense of =) to number, returns that flonum. If number is a negative zero, an infinity, or a NaN, return its flonum equivalent. If such a flonum does not exist, returns the nearest flonum, where "nearest" is implementation-dependent. If number is not a real number, it is an error. If number is exact, applies inexact or exact->inexact to number first.
- fladjacent x yprocedure
Returns a flonum adjacent to x in the direction of y. Specifically: if x < y, returns the smallest flonum larger than x; if x > y, returns the largest flonum smaller than x; if x = y, returns x. (C99 nextafter)
- flcopysign x yprocedure
Returns a flonum whose magnitude is the magnitude of x and whose sign is the sign of y. (C99 copysign)
- make-flonum x nprocedure
Returns x × 2n, where n is an integer with an implementation-dependent range. (C99 ldexp)
Accessors
- flinteger-fraction xprocedure
Returns two values, the integral part of x as a flonum and the fractional part of x as a flonum. (C99 modf)
- flexponent xprocedure
Returns the exponent of x. (C99 logb)
- flinteger-exponent xprocedure
Returns the same as flexponent truncated to an exact integer. If x is zero, returns fl-integer-exponent-zero; if x is a NaN, returns fl-integer-exponent-nan; if x is infinite, returns a large implementation-dependent exact integer. (C99 ilogb)
- flnormalized-fraction-exponent xprocedure
Returns two values, a correctly signed fraction y whose absolute value is between 0.5 (inclusive) and 1.0 (exclusive), and an exact integer exponent n such that x = y(2^n). (C99 frexp)
- flsign-bit xprocedure
Returns 0 for positive flonums and 1 for negative flonums and -0.0. The value of (flsign-bit +nan.0) is implementation-dependent, reflecting the sign bit of the underlying representation of NaNs. (C99 signbit)
Predicates
- flonum? objprocedure
Returns #t if obj is a flonum and #f otherwise.
- fl=? x y z ...procedure
- fl<? x y z ...procedure
- fl>? x y z ...procedure
- fl<=? x y z ...procedure
- fl>=? x y z ...procedure
These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing; they return #f otherwise. These predicates must be transitive. (C99 =, <, >, <=, >= operators respectively)
- flunordered? x yprocedure
Returns #t if x and y are unordered according to IEEE rules. This means that one of them is a NaN.
These numerical predicates test a flonum for a particular property, returning #t or #f.
- flinteger? xprocedure
Tests whether x is an integral flonum.
- flzero? xprocedure
Tests whether x is zero. Beware of roundoff errors.
- flpositive? xprocedure
Tests whether x is positive.
- flnegative? xprocedure
Tests whether x is negative. Note that (flnegative? -0.0) must return #f; otherwise it would lose the correspondence with (fl<? -0.0 0.0), which is #f according to IEEE 754.
- flodd? xprocedure
Tests whether the flonum x is odd. It is an error if x is not an integer.
- fleven? xprocedure
Tests whether the flonum x is even. It is an error if x is not an integer.
- flfinite? xprocedure
Tests whether the flonum x is finite. (C99 isfinite)
- flinfinite? xprocedure
Tests whether the flonum x is infinite. (C99 isinf)
- flnan? xprocedure
Tests whether the flonum x is NaN. (C99 isnan)
- flnormalized? xprocedure
Tests whether the flonum x is normalized. (C11 isnormal; in C99, use fpclassify(x) == FP_NORMAL)
- fldenormalized? xprocedure
Tests whether the flonum x is denormalized. (C11 issubnormal; in C99, use fpclassify(x) == FP_SUBNORMAL)
Arithmetic
- flmax x ...procedure
- flmin x ...procedure
Return the maximum/minimum argument. If there are no arguments, these procedures return -inf.0 or +inf.0 if the implementation provides these numbers, and (fl- fl-greatest) or fl-greatest otherwise. (C99 fmax fmin)
- fl+ x ...procedure
- fl* x ...procedure
Return the flonum sum or product of their flonum arguments. (C99 + * operators respectively)
- fl+* x y zprocedure
Returns xy + z as if to infinite precision and rounded only once. The boolean constant fl-fast-fl+* indicates whether this procedure executes about as fast as, or faster than, a multiply and an add of flonums. (C99 fma)
- fl- x y ...procedure
- fl/ x y ...procedure
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. (C99 - / operators respectively)
- flabs xprocedure
Returns the absolute value of x. (C99 fabs)
- flabsdiff x yprocedure
Returns |x - y|.
- flposdiff x yprocedure
Returns the difference of x and y if it is non-negative, or zero if the difference is negative. (C99 fdim)
- flsgn xprocedure
Returns (flcopysign 1.0 x).
- flnumerator xprocedure
- fldenominator xprocedure
Returns the numerator/denominator of x as a flonum; the result is computed as if x was represented as a fraction in lowest terms. The denominator is always positive. The numerator of an infinite flonum is itself. The denominator of an infinite or zero flonum is 1.0. The numerator and denominator of a NaN is a NaN.
- flfloor xprocedure
Returns the largest integral flonum not larger than x. (C99 floor)
- flceiling xprocedure
Returns the smallest integral flonum not smaller than x. (C99 ceil)
- flround xprocedure
Returns the closest integral flonum to x, rounding to even when x represents a number halfway between two integers. (Not the same as C99 round, which rounds away from zero)
- fltruncate xprocedure
Returns the closest integral flonum to x whose absolute value is not larger than the absolute value of x (C99 trunc)
Exponents and logarithms
- flexp xprocedure
Returns e^x. (C99 exp)
- flexp2 xprocedure
Returns 2x. (C99 exp2)
- flexp-1 xprocedure
Returns e^x - 1, but is much more accurate than flexp for very small values of x. It is recommended for use in algorithms where accuracy is important. (C99 expm1)
- flsquare xprocedure
Returns x^2.
- flcbrt xprocedure
Returns ∛x. (C99 cbrt)
- flhypot x yprocedure
Returns the length of the hypotenuse of a right triangle whose sides are of length |x| and |y|. (C99 hypot)
- flexpt x yprocedure
Returns x^y. If x is zero, then the result is zero. (C99 pow)
- fllog xprocedure
Returns ln(x). (C99 log)
- fllog1+ xprocedure
Returns ln(x + 1), but is much more accurate than fllog for values of x near 0. It is recommended for use in algorithms where accuracy is important. (C99 log1p)
- fllog2 xprocedure
Returns log2(x). (C99 log2)
- fllog10 xprocedure
Returns log10(x). (C99 log10)
- make-fllog-base xprocedure
Returns a procedure that calculates the base-x logarithm of its argument. If x is 1.0 or less than 1.0, it is an error.
Trigonometric functions
- flsin xprocedure
Returns sin(x). (C99 sin)
- flcos xprocedure
Returns cos(x). (C99 cos)
- fltan xprocedure
Returns tan(x). (C99 tan)
- flasin xprocedure
Returns arcsin(x). (C99 asin)
- flacos xprocedure
Returns arccos(x). (C99 acos)
- (flatan [y] x)procedure
Returns arctan(x). (C99 atan)
With two arguments, returns arctan(y/x) in the range [-π,π], using the signs of x and y to choose the correct quadrant for the result. (C99 atan2)
- flsinh xprocedure
Returns sinh(x). (C99 sinh)
- flcosh xprocedure
Returns cosh(x). (C99 cosh)
- fltanh xprocedure
Returns tanh(x). (C99 tanh)
- flasinh xprocedure
Returns arcsinh(x). (C99 asinh)
- flacosh xprocedure
Returns arccosh(x). (C99 acosh)
- flatanh xprocedure
Returns arctanh(x). (C99 atanh)
Integer division
- flquotient x yprocedure
Returns the quotient of x/y as an integral flonum, truncated towards zero.
- flremainder x yprocedure
Returns the truncating remainder of x/y as an integral flonum.
- flremquo x yprocedure
Returns two values, the rounded remainder of x/y and the low-order n bits (as a correctly signed exact integer) of the rounded quotient. The value of n is implementation-dependent but at least 3. This procedure can be used to reduce the argument of the inverse trigonometric functions, while preserving the correct quadrant or octant. (C99 remquo)
Special functions
- flgamma xprocedure
Returns Γ(x), the gamma function applied to x. This is equal to (x-1)! for integers. (C99 tgamma)
- flloggamma xprocedure
Returns two values, log |Γ(x)| without internal overflow, and the sign of Γ(x) as 1.0 if it is positive and -1.0 if it is negative. (C99 lgamma)
- flfirst-bessel n xprocedure
Returns the nth order Bessel function of the first kind applied to x, Jn(x). (jn, which is an XSI Extension of C99)
- flsecond-bessel n xprocedure
Returns the nth order Bessel function of the second kind applied to x, Yn(x). (yn, which is an XSI Extension of C99)
- flerf xprocedure
Returns the error function erf(x). (C99 erf)
- flerfc xprocedure
Returns the complementary error function, 1 - erf(x). (C99 erfc)
Acknowledgements
This SRFI would not have been possible without Taylor Campbell, the R6RS editors, and the ISO C Working Group.
Author
John Cowan, Will Clinger
Maintainer
Repository
https://git.sr.ht/~dieggsy/srfi-144
Copyright
Copyright (C) John Cowan (2016). All Rights Reserved. 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. Editor: Arthur A. Gleckler
Version History
- 0.1.2
- Fix tests, ensure flround behaves to spec
- 0.1.1
- More idiomatic error messages, ensure correctness of fl-fast-fl+* value/feature
- 0.1.0
- Ported to CHICKEN 5