278: Supplemental Numerics

by Peter McGoron

Status

This SRFI is currently in draft status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-278@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

This SRFI defines miscellaneous procedures on numbers that were either missing from the R7RS or are common extensions.

Issues

  1. If you have experience with writing numeric procedures like these, I would like your feedback. I have never written code like this before.
  2. I am unsure whether the requirements on the inverse hyperbolic functions are sufficient to capture the behavior shown in the examples.
  3. Are there better ways to test the procedures? Like known pathological inputs?

Rationale

This SRFI adds a few procedures that can be categorized into the following:

The extended-domain procedures are more useful because they can be used without invoking “it is an error” behavior. For example, in this SRFI, (exact-integer? '()) and (nan? '()) both return #f. (Some proposed extensions to standard procedures, such as gcd on rational arguments, should be a part of a different SRFI, such as SRFI 141 extended to non-integers.)

The R6RS procedures are useful when determining whether a number is exactly on the real number line, as opposed to being approximately on the real number line. Procedures like R6RS’s div-and-mod are not supplied. They are similarly relegated to an extended SRFI 141.

The common extensions are the conjugate procedure and the (inverse) hyperbolic functions. The (inverse) hyperbolic functions are commonly provided on Schemes that provide complex arithmetic (for example, Gambit, Chez, Racket, Gauche, and Guile) because those implementations are required to implement complex (inverse) trigonometric functions, which are closely connected to complex (inverse) hyperbolic functions.

The procedure round-away has been added to correspond to the roundTiesToAway rounding mode in IEEE 754-2019.

Specification

Requirement level verbs are in strong text.

The names of arguments have the same requirements as the R7RS. It is an error to call a procedure with a list of arguments that do not match the description given here.

When an example evaluates to an inexact number, that number is approximate. The number that an implementation evaluates to should be close in both parts of a complex number to that value. An exception is when one part of a complex value is an infinity or a zero. An implementation should evaluate to a number that has the appropriately signed infinity or zero in that part (in the sense of eqv?).

Library

The following are exported from the library defined by this SRFI.

conjugate round-away strictly-real? strictly-rational? strictly-integer? exact-integer? nan? sinh cosh tanh asinh acosh atanh

(srfi 278)
procedure
(conjugate z)

Returns the complex conjugate of the procedure.

If the implementation distinguishes the sign of inexact zero in the imaginary part of a complex number, then it must flip the sign of the inexact zero.

This procedure returns an exact value given an exact argument.

Note: If non-real complex numbers are not provided, this procedure is just the identity function.

(conjugate 1.0) ⇒ 1.0
(conjugate 1+2i) ⇒ 1-2i
(conjugate 1.0+0.0i) ⇒ 1.0-0.0i
(conjugate 1.0-0.0i) ⇒ 1.0+0.0i
(srfi 278)
procedure
(round-away x)

Round x to an integer, with ties broken by returning the number greater in absolute value. Equivalent to the IEEE 754-2019 [2] rounding mode roundTiesToAway.

This procedure returns an exact value given an exact argument.

(round-away 2.5) ⇒ 3.0
(round-away 5/2) ⇒ 3
(round-away 2.4) ⇒ 2.0
(round-away -2.5) ⇒ -3.0
(round-away 3.6) ⇒ 4.0
(round-away 3.5) ⇒ 4.0
(round-away 3.4) ⇒ 3.0
(srfi 278)
procedure
(strictly-real? obj)
(strictly-rational? obj)
(strictly-integer? obj)

Returns #t if the obj is of the corresponding type, (zero? (imag-part obj)) is #t, and (exact? (imag-part obj)).

Rationale: These procedures have the semantics of real?, rational?, and integer? in the R6RS. It is sometimes useful to have a number represented internally as a complex number even when its imaginary part is inexact zero: this occurs when one wants to use the sign of the inexact zero for computations. It is intended that a number that is strictly-real?, etc. is not represented internally as a compound number (compnum), and that all complex numbers with an exact zero imaginary part are normalized and represented as flonums, bignums, fixnums, ratnums, etc.

Another reason to distinguish between real? and strictly-real? is the interpretation of what it means for the imaginary part of a number to be inexact zero. When a number is inexact zero, it is only approximately that number. As such, if a number has an inexact zero imaginary part, then we don’t know if it is actually on the real axis, or if the actual result of the computation was actually slightly above or below the real axis. On the other hand, if the imaginary part is exactly zero, then the the number has to be on the real axis.

(strictly-real? 1.0) ⇒ #t
(strictly-real? 1) ⇒ #t
(strictly-real? 1+0i) ⇒ #t
(strictly-real? 1.0+0.0i) ⇒ #f
(strictly-real? 1.0-0.0i) ⇒ #f
(srfi 278)
procedure
(exact-integer? obj)
(nan? obj)

These procedures are the same as their counterparts in the Reports, except that they return #f when passed an object that is not number?.

Rationale: Implementations are encouraged to replace the versions of these procedures in (scheme base) with the one defined in this SRFI. The ones defined in this SRFI are backwards-compatible with the versions described in the R7RS.

(srfi 278)
procedure
(sinh z)
(cosh z)
(tanh z)

Calculates the value of the hyperbolic function for z.

(sinh 0) ⇒ 0.0
(sinh +inf.0) ⇒ +inf.0
(sinh -inf.0) ⇒ -inf.0
(cosh 0) ⇒ 1.0
(cosh +inf.0) ⇒ +inf.0
(cosh -inf.0) ⇒ +inf.0
(sinh +1.0i) ⇒ +.8414709848078965i
(srfi 278)
procedure
(asinh z)
(acosh z)
(atanh z)

Calculates the principal value of the inverse hyperbolic function at z.

It is an error to call these values on exact numbers on a location where the procedure is undefined mathematically. The implementation should raise an exception in such a scenario.

In general, inverse hyperbolic functions are multiply valued. The following principal expressions are derived from the table in the Reports and from [1]. (For those that cannot render the math, this image shows the equations.)

The value of logz for non-real z is defined in terms of log as

logz=log|z|+(anglez)i

where anglez is the angle of z=aeiθ specified as

anglez=b+2in

with n chosen such that πanglezπ.

With log defined this way, the values of the transcendental functions relevant to this SRFI go according to the following formulæ:

sin1z=ilog(iz+1-z2)cos1z=π2sin1ztan1z=log(1+iz)log(1iz)2itanh1z=log(1+z)log(1-z)2sinh1z=log(z+1+z2)cosh1z=2log(1+z2+z-12)

(The inverse trigonometric functions are included for comparison.)

When an implementation distinguishes the sign of inexact zero in some number, and if that number lies on a branch cut, then the implementation must return a value reasonably close to the appropriate one-sided limit of the function approaching the branch cut.

(atanh 1.0+0.0i) ⇒ -inf.0+.7853981633974483i
(atanh 1.0-0.0i) ⇒ -inf.0-.7853981633974483i
(atanh -1.0+0.0i) ⇒ +inf.0+.7853981633974483i
(atanh -1.0-0.0i) ⇒ +inf.0-.7853981633974483i
(atanh 0.0+1.0i) ⇒ 0.0+0.7853981633974483i
(atanh 1)error
(atanh 0.0-1.0i) ⇒ 0.0-.7853981633974483i
(acosh 0.0+0.0i) ⇒ 0.+1.5707963267948966i
(acosh 0.0-0.0i) ⇒ 0.-1.5707963267948966i
(acosh 1.0+0.0i) ⇒ 0.+3.141592653589793i
(acosh 1.0-0.0i) ⇒ 0.-3.141592653589793i
(asinh 0.0+2.0i) ⇒ 1.3169578969248166+1.5707963267948966i
(asinh -0.0+2.0i) ⇒ -1.3169578969248166+1.5707963267948966i

Implementation

A sample implementation is available in the SRFI repository. It depends on complex numbers, inexact numbers, SRFI 144, inexact infinities, and signed zeroes. In addition, complex numbers must be able to store signed zeros in any part. (Some implementations do not allow this, like Gauche.) The sample implementation has been tested on Chibi Scheme. A test suite that depends on those features is also available.

An implementation without complex numbers support can copy the implementations of the (inverse) hyperbolic functions from SRFI 144 instead of using the implementation in this repository. The other parts of the implementation are portable R7RS.

Acknowledgements

I thank Bradley Lucier and the Gambit project for writing high-quality implementations of the (inverse) hyperbolic functions. I have used Gambit to check that my code outputs the correct values.

I thank William Kahan for doing the hard part for me (and many other people).

References

[1]: Kahan, W. Branch cuts for complex elementary functions; or, Much ado about nothing's sign bit. In Iserles, A., and Powell, M. (eds.), The state of the art in numerical analysis. Clarendon Press (1987) pp 165-211.

[2]: IEEE Computer Society. IEEE Standard for Floating-Point Arithmetic (IEEE STD 754-2019). doi:10.1109/IEEESTD.2019.8766229. (2019). ISBN 978-1-5044-5924-2.

© 2026 Peter McGoron.

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 (including the next paragraph) 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