3 views

Skip to first unread message

Aug 9, 2003, 1:54:28 PM8/9/03

to

Infinities in Scheme

--------------------

http://swissnet.ai.mit.edu/~jaffer/III/RAWI

--------------------

http://swissnet.ai.mit.edu/~jaffer/III/RAWI

Introduction

============

The three special values inf, -inf, and nan of IEEE Standard 754 are

well-defined and integrated into 754's arithmetic system.

With nearly every Scheme implementation using IEEE floating-point

numbers, we should consider advancing the language to reap more of the

benefits of IEEE-754 by standardizing Scheme syntaxes for infinities.

Doing so would also improve storage and communication of numerical

data between programs.

Background

==========

Checks for division by zero (and their absence) remain one of the most

common programming errors. Table 1, for example, shows Scheme48 and

MIT-Scheme signaling errors evaluating (string->number "1/0"). Is it

merely a coincidence that these implementations are the least tolerant

(among those tested) of division by zeros?

The realization that division by zero "works" lets initialization of

variables precede bounds checks and gives flexibility in placement of

those checks. Halting of programs need not occur in order to test

limit and corner cases. Preserving infinities in data sets can free

presentation programs from imposing arbitrary range limits.

Apparatus

=========

* Scheme interpreter or compiler.

* The Scheme program "inf.scm"

http://swissnet.ai.mit.edu/~jaffer/III/inf.scm

Procedures

==========

* Invoke Scheme interactively, then (load "inf.scm");

or

* Edit the end of "inf.scm" to call TRYDIVS with or without an

argument as appropriate for the Scheme's eval. Then compile

"inf.scm" and run.

Method

======

REAL-INFS in "inf.scm" is a list of all known (to me) literal

representations of inf, -inf, and nan.

COMPLEX-INFS in "inf.scm" is a list of the combinations within each

group of infinity representations in one or both components of complex

numbers.

The procedure STR2NUM prints its string argument, tries to convert

that string to a number, and writes out that number on the same line

if successful.

* STR2NUM is called with each string in REAL-INFS.

* STR2NUM is called with each string in COMPLEX-INFS.

* The procedure TRYDIVS calls / with all possible combinations of

one or two exact or inexact zeros, printing each expression and

its result.

* The procedure INEX-PROPS calls / with the combinations having

inexact denominator "0." and prints HTML rows detailing the

numerical predicates applied to the ratio.

If an error occurs while interactively running "inf.scm", the tests

can be run manually:

* (for-each str2num real-infs)

* (for-each str2num complex-infs)

* (trydivs (interaction-environment))

* (inex-props (interaction-environment))

string->number

==============

Table 1: string->number of (real) infinity strings

Input glibc 2.2 Gambit Mz Scheme SCM Scheme 48 MIT Scheme

strtod() 3.0 202 5d8 0.57 7.8

=======================================================================

"+inf.0" inf [2] +inf.0

"-inf.0" -inf[2] -inf.0

"+nan.0" nan [2] +nan.0

"-nan.0" nan [2] +nan.0

"nan.0" nan [2]

"+inf." inf [1] +inf.

"-inf." -inf[1] -inf.

"+nan." nan [1] +nan.

"-nan." nan [1]

"nan." nan [1]

"+INF" inf

"-Inf" -inf

"inf" inf

"+NAN" nan

"-Nan" nan

"nan" nan

"+#.#" 5.5

"-#.#" -5.5

"#.#"

"1/0" 1/0 [r] [s]

"-1/0" () -1/0 [r] [s]

"0/0" 0/0 [r] [s]

=======================================================================

[1], [2] Characters left at end

[s] ;Division by zero signaled by /.

[r] Error: rational division by zero

Notes:

* Empty entries indicate #f was returned.

* scanf() reads identically with strtod().

* strtod() also accepts "infinity", but no substrings of it other

than "inf".

* Gambit string->number returns (). when passed "-1/0" or "-0/0".

* Gambit string->number does not accept "-nan.".

* MzScheme string->number accepts "-nan.0".

Table 2: string->number of complex infinity strings

Input Gambit 3.0 Input MzScheme 202 Input SCM 5d8

============= ========== ============== ============ ========== =========

"inf.+i" "inf.0+i" "1/0+i" 1/0+1.0i

"-inf.+i" -inf.+i "-inf.0+i" -inf.0+1.0i "-1/0+i" -1/0+1.0i

"+nan.+i" +nan.+i "+nan.0+i" +nan.0+1.0i "0/0+i" 0/0+1.0i

"-nan.+i" "-nan.0+i" +nan.0+1.0i "+1/0i" 0.0+1/0i

"+inf.i" +inf.i "+inf.0i" "-1/0i" 0.0-1/0i

"-inf.i" -inf.i "-inf.0i" "+0/0i" 0.0+0/0i

"+nan.i" +nan.i "+nan.0i" "-0/0i" 0.0+0/0i

"-nan.i" "-nan.0i" "1/0+1/0i" 1/0+1/0i

"0+inf.i" +inf.i "0+inf.0i" 0+inf.0i "1/0-1/0i" 1/0-1/0i

"0-inf.i" -inf.i "0-inf.0i" 0-inf.0i "1/0+0/0i" 1/0+0/0i

"0+nan.i" +nan.i "0+nan.0i" 0+nan.0i "1/0-0/0i" 1/0+0/0i

"0-nan.i" "0-nan.0i" 0+nan.0i "-1/0+1/0i" -1/0+1/0i

"inf.+inf.i" "inf.0+inf.0i" "-1/0-1/0i" -1/0-1/0i

"inf.-inf.i" "inf.0-inf.0i" "-1/0+0/0i" -1/0+0/0i

"inf.+nan.i" "inf.0+nan.0i" "-1/0-0/0i" -1/0+0/0i

"inf.-nan.i" "inf.0-nan.0i" "0/0+1/0i" 0/0+1/0i

"-inf.+inf.i" -inf.+inf.i "-inf.0+inf.0i" -inf.0+inf.0i "0/0-1/0i" 0/0-1/0i

"-inf.-inf.i" -inf.-inf.i "-inf.0-inf.0i" -inf.0-inf.0i "0/0+0/0i" 0/0+0/0i

"-inf.+nan.i" -inf.+nan.i "-inf.0+nan.0i" -inf.0+nan.0i "0/0-0/0i" 0/0+0/0i

"-inf.-nan.i" "-inf.0-nan.0i" -inf.0+nan.0i

"+nan.+inf.i" +nan.+inf.i "+nan.0+inf.0i" +nan.0+inf.0i

"+nan.-inf.i" +nan.-inf.i "+nan.0-inf.0i" +nan.0-inf.0i

"+nan.+nan.i" +nan.+nan.i "+nan.0+nan.0i" +nan.0+nan.0i

"+nan.-nan.i" "+nan.0-nan.0i" +nan.0+nan.0i

"-nan.+inf.i" "-nan.0+inf.0i" +nan.0+inf.0i

"-nan.-inf.i" "-nan.0-inf.0i" +nan.0-inf.0i

"-nan.+nan.i" "-nan.0+nan.0i" +nan.0+nan.0i

"-nan.-nan.i" "-nan.0-nan.0i" +nan.0+nan.0i

"+1/0i" ... [g]

============================================================================

[g] *** ERROR -- REAL expected

(make-rectangular #f 1)

Notes:

* Empty entries indicate #f was returned.

* MzScheme string->number accepts imaginary infinities only with a

real 0 part prepended, eg. "0+inf.0i".

Reading and Writing Infinities

==============================

The floating-point string conversions in GNU glibc 2.2 support reading

and writing of infinite values:

* inf is positive infinity

* -inf is negative infinity

* nan is Not-a-Number.

I have not discovered which standard specifies these codes for string

representation, if any. They may have been inherited from the IEEE

754 nomenclature.

Although not specified by the Revised^5 Report on the Algorithmic

Language Scheme, a few Scheme implementations support reading and

literal use of their representations of infinities.

The richness of Scheme's syntax of numerical constants provides

several opportunities to support infinities. An idea which has

occurred to several authors independently is to use # in place of all

digits in a number:

* +#.# is positive infinity;

* -#.# is negative; and

* #.# is NaN (not a number).

This notation is compact and would not be easily mistaken for any

other Scheme object. The problem arises when these objects are

components of complex numbers. The coefficient of i must be prefixed

by a sign, making +#.#i ambiguous. Remediations like disallowing

complex NaNs would be modifying semantics in pursuit of syntax; not a

good practice.

Gambit and MzScheme both use strings derived from IEEE-754

nomenclature:

* +inf. versus +inf.0

* -inf. versus -inf.0

* +nan. versus +nan.0

Requiring the leading sign character prevents confusion with

identifiers, but "+inf" spoofs "+i". NaN, an intrinsically unsigned

construct, is required to have a sign prefix by both systems. Gambit

does not recognize "-nan." as NaN. MzScheme recognizes both "+nan.0"

and "-nan.0" as NaN, but always prints "+nan.0".

SCM prints infinities as rational numbers with denominators of "0".

SCM's existing reader decoded this format without modification:

* 1/0 is positive infinity;

* -1/0 is negative infinity; and

* 0/0 is NaN (not a number).

SCM's infinities look like exact rational numbers, but are actually

inexacts. The inclusion of a decimal point (eg. 1/0.) would not be

R5RS-compliant syntax. Prepending #i (eg. #i1/0, #i-1/0, #i0/0) is

less evocative than the compact 3 and 4 character versions.

Since an implementation is allowed to coerce the result of division by

0 to inexact, SCM always does so.

If one of these procedures is unable to deliver an exact result

when given exact arguments, then it may either report a violation

of an implementation restriction or it may silently coerce its

result to an inexact number.

Division by zero

================

Table 3 catalogs the results of dividing exact and inexact numbers by

exact and inexact zeros. In both MzScheme and MIT-Scheme (/ 0 0.)

returns "0". An inexact "0." is apparently weaker than an exact "0"

in those implementations.

Table 3: Division by Zero

glibc Mz MIT Scheme

quotient SCM Guile Bigloo 2.2 Elk Gambit Scheme Scheme 48

5d8* 1.3.4 2.5c printf 3.0 3.0 202 7.8 0.57

==========================================================================

(/ 0.) 1/0 +#.# +#.# inf Inf.0 +inf. +inf.0 [t] [r]

(/ -1. 0.) -1/0 -#.# -#.# inf -Inf.0 -inf. -inf.0 [t] [r]

(/ -1 0.) -1/0 -#.# -#.# -inf -Inf.0 -inf. -inf.0 [t] [r]

(/ 0. 0.) 0/0 #.# #.# nan NaN +nan. +nan.0 [a] [r]

(/ 0 0.) 0/0 #.# #.# nan NaN +nan. 0 0 [r]

(/ -1. 0) -1/0 -#.# -#.# -inf [e] [g] [d] [t] [r]

(/ 0. 0) 0/0 #.# #.# nan [e] [g] [d] [a] [r]

(/ 0 0) 0/0 #.# [b] [c] [e] [g] [d] [s] [r]

(/ 0) 1/0 +#.# [b] [c] [e] [g] [d] [s] [r]

(/ -1 0) -1/0 -#.# [b] [c] [e] [g] [d] [s] [r]

==========================================================================

* Earlier versions of SCM printed identically to Guile.

[a] ;Anonymous arithmetic error

[b] *** ERROR:bigloo:arithmetic procedure:

`floating point' exception -- reached

[c] Floating point exception

[d] /: division by zero

[e] /: argument out of range: 0

[g] *** ERROR IN (stdin)@7.19 -- Division by zero

[r] Error: rational division by zero

[s] ;Division by zero signaled by /.

[t] ;Division by zero

Table 4: Properties of special quotients

==========================================================================

inexact exact rational integer real positive zero negative

1/0 * * * * *

SCM -1/0 * * * * *

0/0 * * *

+#.# * * * * *

Guile -#.# * * * * *

#.# * * *

+inf.0 * * * * *

MzScheme -inf.0 * * * * *

+nan.0 * * *

Inf.0 * * * * *

Elk -Inf.0 * * * * *

NaN * *

+#.# * * * *

Bigloo -#.# * * * *

#.# * * *

+inf. * * *

Gambit -inf. * * *

+nan. * *

==========================================================================

Table 4 shows the numerical properties of each of the special values.

None of the implementations support exact infinities. The only

variations are in the RATIONAL and INTEGER columns.

Discussion

==========

The glibc syntax for infinities has two undesirable aspects:

* Nothing visually distinguishes inf and nan from text words.

* Inf and nan will be meaningless acronyms to people unfamiliar

with IEEE-754 who encounter them in data files.

Gambit and MzScheme address the first problem by requiring a sign

prefix. Glibc reads signed infinities, so they would interoperate in

one direction. But both implementations add suffixes to inf and nan

which strtod() and scanf() do not ignore.

The denominator of 0 infinity representations improve both aspects.

Conclusion

==========

This survey of infinities in Scheme shows general agreement among

implementations that scalar infinities are inexact reals. Infinities

are allowed as independent real and imaginary components of complex

numbers.

Several implementations provide read/write invariance of inexact

complex infinities; but their syntaxes are incompatible. Settling on

one signed-nan-inf or denominator-of-0 format for infinities would

eliminate needless incompatibility and augment Scheme's substantial

numerical capabilities.

Copyright 2003 Aubrey Jaffer

-----------------------------------------------------------------------

I am a guest and *not* a member of the MIT Artificial Intelligence Lab.

My actions and comments do not reflect in any way on MIT.

agj @ alum.mit.edu Go Figure!

Aug 11, 2003, 7:18:47 AM8/11/03

to

Aubrey Jaffer <a...@alum.mit.edu> writes:

> Reading and Writing Infinities

> ==============================

>

> The floating-point string conversions in GNU glibc 2.2 support reading

> and writing of infinite values:

>

> * inf is positive infinity

> * -inf is negative infinity

> * nan is Not-a-Number.

>

> I have not discovered which standard specifies these codes for string

> representation, if any. They may have been inherited from the IEEE

> 754 nomenclature.

> Reading and Writing Infinities

> ==============================

>

> The floating-point string conversions in GNU glibc 2.2 support reading

> and writing of infinite values:

>

> * inf is positive infinity

> * -inf is negative infinity

> * nan is Not-a-Number.

>

> I have not discovered which standard specifies these codes for string

> representation, if any. They may have been inherited from the IEEE

> 754 nomenclature.

> The richness of Scheme's syntax of numerical constants provides

> several opportunities to support infinities.

Indeed. I'm surprised that you didn't mention a slight variation of

> Gambit and MzScheme both use strings derived from IEEE-754

> nomenclature:

>

> * +inf. versus +inf.0

> * -inf. versus -inf.0

> * +nan. versus +nan.0

which would be

#+inf

#-inf

#nan

I have a pre-draft SRFI (for extended literal constants) floating

around on my drive at home which proposes just such a thing for

Schemes which support IEEE infinities and NaNs. Is there a problem

with my proposed syntax (apart from the fact that no-one currently

implements it)?

> Requiring the leading sign character prevents confusion with

> identifiers, but "+inf" spoofs "+i". NaN, an intrinsically unsigned

> construct, is required to have a sign prefix by both systems. Gambit

> does not recognize "-nan." as NaN. MzScheme recognizes both "+nan.0"

> and "-nan.0" as NaN, but always prints "+nan.0".

david rush

--

He who would make his own liberty secure, must guard even his enemy

from repression

-- Thomas Paine

Aug 11, 2003, 10:16:09 AM8/11/03

to

David Rush <dr...@aol.net> writes:

> Aubrey Jaffer <a...@alum.mit.edu> writes:

> > Reading and Writing Infinities

> > ==============================

>

> > The richness of Scheme's syntax of numerical constants provides

> > several opportunities to support infinities.

>

> Indeed. I'm surprised that you didn't mention a slight variation of

>

> > Gambit and MzScheme both use strings derived from IEEE-754

> > nomenclature:

> >

> > * +inf. versus +inf.0

> > * -inf. versus -inf.0

> > * +nan. versus +nan.0

>

> which would be

>

> #+inf

> #-inf

> #nan

>

> I have a pre-draft SRFI (for extended literal constants) floating

> around on my drive at home which proposes just such a thing for

> Schemes which support IEEE infinities and NaNs. Is there a problem

> with my proposed syntax (apart from the fact that no-one currently

> implements it)?

#+inf and #-inf conditionally (on presence of feature INF) skip the next

s-expression in Common-Lisp and SCM.

Aug 11, 2003, 10:51:02 AM8/11/03

to

David Rush wrote:

> Indeed. I'm surprised that you didn't mention a slight variation of

>

>

>>Gambit and MzScheme both use strings derived from IEEE-754

>>nomenclature:

>>

>> * +inf. versus +inf.0

>> * -inf. versus -inf.0

>> * +nan. versus +nan.0

>

>

> which would be

>

> #+inf

> #-inf

> #nan

>

> I have a pre-draft SRFI (for extended literal constants) floating

> around on my drive at home which proposes just such a thing for

> Schemes which support IEEE infinities and NaNs. Is there a problem

> with my proposed syntax (apart from the fact that no-one currently

> implements it)?

>

I'm not a fan of the above. Many Schemes dispatch on sharp constants

using the first character following the sharp. This wouldn't look very

nice in that respect. Better would be #!+inf, #!-inf, #!nan.

However, I'm actually a bigger fan of the denominator-of-0 approach, as

it is more mathematically explicit as to what is indicated.

Scott

Aug 11, 2003, 1:05:21 PM8/11/03

to

"Scott G. Miller" <scgm...@freenetproject.org> writes:

> David Rush wrote:

> > #+inf

> > #-inf

> > #nan

> > Is there a problem

> > with my proposed syntax (apart from the fact that no-one currently

> > implements it)?

>

> I'm not a fan of the above. Many Schemes dispatch on sharp

> constants using the first character following the sharp. This

> wouldn't look very nice in that respect. Better would be #!+inf,

> #!-inf, #!nan.

> David Rush wrote:

> > #+inf

> > #-inf

> > #nan

> > Is there a problem

> > with my proposed syntax (apart from the fact that no-one currently

> > implements it)?

>

> I'm not a fan of the above. Many Schemes dispatch on sharp

> constants using the first character following the sharp. This

> wouldn't look very nice in that respect. Better would be #!+inf,

> #!-inf, #!nan.

Ok, although I think that #!-inf looks a bit clunky.

> However, I'm actually a bigger fan of the denominator-of-0 approach,

> as it is more mathematically explicit as to what is indicated.

Is it really? What about (exp 9876543.4)? denominator-of-zero actually

obfuscates the source of that 'infinity'

Aug 12, 2003, 6:53:39 AM8/12/03

to

Slightly off-topic, but if we have NaN in Scheme, it's nice

that we agree on the result of comparison of NaN's.

that we agree on the result of comparison of NaN's.

As far as I know, all implementations that support NaN

return #f for (= nan nan), which I think is IEEE754 compliant.

However, some implementations (AFAIK, all but Bigloo)

return #t for (eqv? nan nan) in some cases.

SCM5d8

> (let ((nan (/ 0.0 0.0))) (eqv? nan nan))

#t

> (let ((nan (/ 0.0 0.0))) (= nan nan))

#f

Petite Chez Scheme 6.0a

> (let ((nan (/ 0.0 0.0))) (eqv? nan nan))

#t

> (let ((nan (/ 0.0 0.0))) (= nan nan))

#f

Guile 1.6.0

guile> (let ((nan (/ 0.0 0.0))) (eqv? nan nan))

#t

guile> (let ((nan (/ 0.0 0.0))) (= nan nan))

#f

R5RS says "The eqv? procedure returns #f if ...

obj1 and obj2 are numbers for which the = procedure returns #f",

so should these eqv?'s always return #f?

Cf. http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Gauche:NaN%A4%CE%B0%B7%A4%A4&l=en

Aug 13, 2003, 11:30:52 AM8/13/03

to

sh...@acm.org (Shiro Kawai) writes:

>

> As far as I know, all implementations that support NaN

> return #f for (= nan nan), which I think is IEEE754 compliant.

> However, some implementations (AFAIK, all but Bigloo)

> return #t for (eqv? nan nan) in some cases.

>

> As far as I know, all implementations that support NaN

> return #f for (= nan nan), which I think is IEEE754 compliant.

> However, some implementations (AFAIK, all but Bigloo)

> return #t for (eqv? nan nan) in some cases.

Excellent catch! The appended patch fixes SCM so that:

> (= 0/0 0/0)

#f

> (eqv? 0/0 0/0)

#f

> (let ((nan 0/0)) (= nan nan))

#t

> (let ((nan 0/0)) (eqv? nan nan))

#t

Also fixed is (inexact->exact 0/0), which was never returning.

-=-=-=-=-

*** scl.c.~1.51.~ Tue Aug 12 14:17:07 2003

--- scl.c Wed Aug 13 11:15:42 2003

***************

*** 1112,1117 ****

--- 1113,1119 ----

# else

ASRTGO(NIMP(y) && INEXP(y), bady);

# endif

+ if (x==y) return BOOL_T;

if (REALPART(x) != REALPART(y)) return BOOL_F;

if CPLXP(x)

return (CPLXP(y) && (IMAG(x)==IMAG(y))) ? BOOL_T : BOOL_F;

***************

*** 2356,2362 ****

SCM ans = MAKINUM((long)u);

if (INUM(ans)==(long)u) return ans;

}

! ASRTGO(!IS_INF(u), badz); /* problem? */

return dbl2big(u);

}

# else

--- 2358,2364 ----

SCM ans = MAKINUM((long)u);

if (INUM(ans)==(long)u) return ans;

}

! ASRTGO(!(IS_INF(u) || (u)!=(u)), badz); /* problem? */

return dbl2big(u);

}

# else

Aug 13, 2003, 12:23:48 PM8/13/03

to

In article <vht4r0l...@aarau.ai.mit.edu>,

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>sh...@acm.org (Shiro Kawai) writes:

>>

>> As far as I know, all implementations that support NaN

>> return #f for (= nan nan), which I think is IEEE754 compliant.

>> However, some implementations (AFAIK, all but Bigloo)

>> return #t for (eqv? nan nan) in some cases.

>

>Excellent catch! The appended patch fixes SCM so that:

>

>> (= 0/0 0/0)

>#f

>> (eqv? 0/0 0/0)

>#f

>> (let ((nan 0/0)) (= nan nan))

>#t

>> (let ((nan 0/0)) (eqv? nan nan))

>#t

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>sh...@acm.org (Shiro Kawai) writes:

>>

>> As far as I know, all implementations that support NaN

>> return #f for (= nan nan), which I think is IEEE754 compliant.

>> However, some implementations (AFAIK, all but Bigloo)

>> return #t for (eqv? nan nan) in some cases.

>

>Excellent catch! The appended patch fixes SCM so that:

>

>> (= 0/0 0/0)

>#f

>> (eqv? 0/0 0/0)

>#f

>> (let ((nan 0/0)) (= nan nan))

>#t

>> (let ((nan 0/0)) (eqv? nan nan))

>#t

At the 1998 Scheme workshop in Baltimore I argued that the semantics of =

and eqv? should be decoupled. = is about numerics; eqv? is about equivalence

under substitution. This is how the next version of Gambit will do it

(and perhaps the current version as well), and I think this is the right way

to go. I can't understand your reasoning at all; under IEEE 754, (= nan nan)

should always be false.

Brad

[zakon:~] lucier% /usr/local/Gambit-C/bin/gsc

Gambit Version 4.0 beta 1

> (eqv? (/ 0. 0.) (/ 0. 0.))

#t

> (= (/ 0. 0.) (/ 0. 0.))

#f

> (let ((nan (/ 0. 0.))) (eqv? nan nan))

#t

> (let ((nan (/ 0. 0.))) (= nan nan))

#f

Aug 13, 2003, 7:59:13 PM8/13/03

to

b...@cs.purdue.edu (Bradley J Lucier) writes:

> In article <vht4r0l...@aarau.ai.mit.edu>,

> Aubrey Jaffer <a...@alum.mit.edu> wrote:

> >sh...@acm.org (Shiro Kawai) writes:

> >>

> >> As far as I know, all implementations that support NaN

> >> return #f for (= nan nan), which I think is IEEE754 compliant.

> >> However, some implementations (AFAIK, all but Bigloo)

> >> return #t for (eqv? nan nan) in some cases.

> >

> >Excellent catch! The appended patch fixes SCM so that:

> >

> >> (= 0/0 0/0)

> >#f

> >> (eqv? 0/0 0/0)

> >#f

> >> (let ((nan 0/0)) (= nan nan))

> >#t

> >> (let ((nan 0/0)) (eqv? nan nan))

> >#t

>

> At the 1998 Scheme workshop in Baltimore I argued that the semantics

> of = and eqv? should be decoupled. = is about numerics; eqv? is about

> equivalence under substitution. This is how the next version of

> Gambit will do it (and perhaps the current version as well), and I

> think this is the right way to go. I can't understand your reasoning

> at all; under IEEE 754, (= nan nan) should always be false.

R5RS *recommends* that IEEE-754 be followed, but

http://swissnet.ai.mit.edu/~jaffer/r5rs_8.html#SEC49

R5RS "Equivalence predicates" requires:

`Eq?''s behavior on numbers and characters is

implementation-dependent, but it will always return either true or

false, and will return true only when `eqv?' would also return true.

Under this rule, even Bigloo is non-compliant:

Bigloo (2.5c)

Welcome to the interpreter

1:=> (let ((nan (/ 0. 0.))) (eq? nan nan))

#t

1:=> (let ((nan (/ 0. 0.))) (eqv? nan nan))

#f

1:=> (let ((nan (/ 0. 0.))) (= nan nan))

#f

> Gambit Version 4.0 beta 1

>

> > (eqv? (/ 0. 0.) (/ 0. 0.))

> #t

> > (= (/ 0. 0.) (/ 0. 0.))

> #f

> > (let ((nan (/ 0. 0.))) (eqv? nan nan))

> #t

> > (let ((nan (/ 0. 0.))) (= nan nan))

> #f

This same section of R5RS mandates that EQV? follow = for numbers of the

same type.

-=-=-=-=-

I searched through IEEE-754; it is silent about the string

representations of infinities and NaN.

I have updated http://swissnet.ai.mit.edu/~jaffer/III/RAWI with data

collected from Kawa-1.7.

Aug 13, 2003, 10:28:50 PM8/13/03

to

In article <vhtoeyt...@chur.ai.mit.edu>,

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>b...@cs.purdue.edu (Bradley J Lucier) writes:

>R5RS "Equivalence predicates" requires:

>

> `Eq?''s behavior on numbers and characters is

> implementation-dependent, but it will always return either true or

> false, and will return true only when `eqv?' would also return true.

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>b...@cs.purdue.edu (Bradley J Lucier) writes:

>R5RS "Equivalence predicates" requires:

>

> `Eq?''s behavior on numbers and characters is

> implementation-dependent, but it will always return either true or

> false, and will return true only when `eqv?' would also return true.

My proposal follows this.

>> Gambit Version 4.0 beta 1

>>

>> > (eqv? (/ 0. 0.) (/ 0. 0.))

>> #t

>> > (= (/ 0. 0.) (/ 0. 0.))

>> #f

>> > (let ((nan (/ 0. 0.))) (eqv? nan nan))

>> #t

>> > (let ((nan (/ 0. 0.))) (= nan nan))

>> #f

>

>This same section of R5RS mandates that EQV? follow = for numbers of the

>same type.

Yes, and I'm suggesting a change.

This is part of a larger proposal I made to the '98 Scheme workshop that is

included below. Will Clinger said afterwards that, in his opinion, only the

definition of eqv? needed to be changed to implement these suggestions.

Brad

Proposals for integrating IEEE Floating-Point Arithmetic Standards 754

and 854 with RnRS.

I've gone over all of the back issues of the rrrs-authors mailing list

(OK, I haven't read everything about exceptions and modules, but ...),

and I would like to make certain proposals for Scheme arithmetic that I

believe would bring it more in line with IEEE 754 and 854 arithmetic,

*if* this arithmetic is used to implements (some) inexact numbers in

a Scheme system. If other inexact number systems are used, then my

suggestions would have no force.

Note that the IEEE arithmetic standards say nothing about mixing integer

(or exact) arithmetic with floating-point (or inexact) arithmetic; many of

my suggestions below try to Do-the-Right-Thing (TM) in these situations.

General Principles:

1. If an expression contains Not-a-Numbers (NaNs), and the same result

would be obtained for any substitution of those NaNs by finite or infinite

numbers, then that result should be returned.

2. I'm motivated by the following ansatz, taken from the

sequence+ultrafilter construction of the non-standard reals. On input,

+0. represents all sequences of positive numbers tending to zero;

-0. represents all sequences of negative numbers tending to zero;

+inf. represents all sequences of numbers tending to positive infinity;

-inf. represents all sequences of numbers tending to negative infinity;

and NaN represents all sequences of numbers. Results of operations

between these quantities and exact numbers should be motivated by applying

the same operation to all numbers of the sequence, e.g.,

(* 0 NaN) => the sequence (* 0 x1) (* 0 x2) (* 0 x3) .... for any (x1,

x2, ...)

=> the sequence 0 0 0 0 0 0 0 ... => exact 0

3. As a consequence of (2), +0. cannot be considered to lie exactly on

zero, it lies a little to the right of zero on the number line; similarly,

-0. lies a little to the left of zero.

Recommendations:

1. Infinities:

I suggest that Scheme adopt standard read and write forms for IEEE

positive and negative infinity, e.g., +inf. -inf.

2. Not-a-Numbers:

I suggest that Scheme adopt standard write forms for IEEE NaNs that

at least indicate the sign of the NaN, e.g., +nan. -nan.

3. eqv?:

If x and y are two inexact numbers implemented as IEEE floating point

numbers, then

(eqv? x y) => #t

if and only if x and y have the same base, sign, number of exponent

digits, biased exponents, number of significand digits, and significands.

Rationale: No matter what bit-level representation is used for IEEE

floating-point numbers (and Motorola, Intel, and others use several,

beyond the issue of byte ordering), the quantities I specified above

are well-defined by IEEE 754 and 854.

The current definition of eqv? does not distinguish between -0. and +0. (since

they are both equal (in the sense of Scheme =) and inexact. However,

operations on +0. and -0. can yield very different results, e.g.,

(/ 1. -0) => -inf.

(/ 1. +0.) => +inf.

Also, since

(= x x) => #f

if x is a NaN, the current definition would say that any Nan is not

eqv to itself, which doesn't make much sense.

4. Non-coercion of exact 0:

If x is any number, and 0 represents exact zero, then

(+ x 0) => x

(- x 0) => x

(- 0 x) => (- x)

(* x 0) => 0

(/ 0 x) => 0

(/ x 0) => error

Rationale: These results follow from a generalization of Priciple 1 that

goes as follows: If an expression contains inexact numbers, and the

result of the expression does not change no matter what exact numbers

are substituted for the inexact numbers, then that result should be

returned. There are other reasons for wanting to do this; the biggest

practical reason is that it makes operations between reals and complexes,

where the real x is coerced to (make-rectangular x 0), *much* easier

to get correct. Here are some other arguments.

IEEE arithmetic has two zeros associated with the two affine

infinities. Thus, there is no clear a priori choice of which inexact

0 (+0. or -0.) exact zero should be coerced to in these expressions.

IBM and Motorola indicate in their notes on the fused-multiply-add

instruction

a*b+c => d

that if one wants to only multiply two numbers, then one needs to set

d to -0., since if a*b is -0.,

-0. + +0. => +0.

will give the wrong result. In a similar way, the exact zero in

(+ x 0)

should be coerced to -0., not +0., when x is an IEEE floating-point

number. Similar analyses can be done with the other expressions given

above.

These rules simplify many basic arithmetic computations on complex numbers

with IEEE-conforming real and imaginary parts.

5. Extending the order operators to 0 or 1 arguments.

For any numbers x

(< x) => #t

(= x) => #t

etc.

Also

(<) => #t

etc.

Rationale: These operators are defined as asking whether a sequence

satisfies a certain order relationship. These order relationships are

automatically satisfied by sequences of length 0 or 1. This would simplify

(apply op lst) if lst is a list of 0 or 1 elements.

Note that even though

(op NaN x) => #f

for any order op, if

(op x) => #t

for any finite or infinite x (which I believe should be true), then

(op NaN) => #t

by General Principle 1.

6. Transcendental functions with special exact arguments

I think it's time to require

(log 1) => 0

(exp 0) => 1

(sin 0) => 0

(cos 0) => 1

(tan 0) => 0

(atan 0) => 0

(asin 0) => 0

etc.

7. Complex numbers with imaginary parts +0. or -0.

If IEEE arithmetic had only one zero, then I might be willing to have, e.g.,

(real? 1+0.i) => #t

However, it has two zeros, and I believe that those zeros should be considered

as lying either slightly above or slightly below the real axis (as the

specifications of the branch cuts of many transcendental functions already

consider them), so if the imaginary part of a number is represented using

IEEE arithmetic, I suggest

(real? 1.+0.i) => #f

(real? 1.-0.i) => #f

but still

(real? 1.+0i) => #t

If 1.+0.i is not real, it is not rational, integer, etc.

I realize that a similar argument could be made that Scheme should have

(integer? +0.) => #f

(integer? -0.) => #f

but I'm not sure that would be acceptable.

8. sqrt and log

If an implementation does not support complex numbers, and x is less

than zero then

(sqrt x) => nan.

as is required by IEEE 754; note that IEEE 754 also requires

(sqrt -0.) => -0.

and

(sqrt nan.) => nan.

I suggest that if x is not a NaN, and the sign of x is negative, then

(log x) => nan.

(log +0.) => -inf.

(log nan.) => nan.

without noting the sign of the NaNs. The first two requirements could

follow from my General Principle 2.

If an implementation does support complex numbers, then an argument

could be made that

(sqrt nan) => nan.+nan.i

following principle 2; similarly for log. However, I do not suggest

that the results of (sqrt nan) or (log nan) depend on whether complex

numbers are implemented.

9. magnitude

If z is a complex number, and one of the components of z is positive or

negative infinity, then

(magnitude z) => +inf.

whether or not the other component is a NaN. This is from Principle 1

(and is given as an example in some of Kahan's lecture notes).

10. max and min

There are two ways to deal with NaN arguments in max and min---either

return one of the NaN arguments, or treat NaN arguments as missing values.

The second choice is what Kahan suggests and what Apple implements.

I suggest we pick one of these ways of dealing with NaNs so that programs

can be portable; I don't care which way, but I generally don't like

differing with Kahan without a reason.

11. rational?

If arg is +inf., -inf., or a NaN, then

(real? arg) => #t

but

(rational? arg) => #f

Rationale: while the usual operations of arithmetic are defined in IEEE

754 and 854 as well for +inf., -inf., and NaNs as they are for other

floating-point numbers, there are some Scheme operations that do not

make sense with these arguments---numerator, denominator, round, etc.

(See below.) rational? should be a predicate that checks whether these

operators will return a reasonable result.

12. truncate, round, ceiling, floor

If op is one of truncate, round, ceiling, floor, and numerator, then

(op -0.) => -0.

and

(denominator -0.) => 1.

If op is any of the previous operators, then

(rational? arg) => #f

implies

(op arg) => error

Rationale: These operations should preserve the sign of zero, since -0.

is as much an integer as +0.

The listed ops do not make sense for objects that are not rational?.

13. rationalize

If x is not rational? (see above) or y is not greater or equal to zero

(rationalize x y) => error

If y is +inf. and x is inexact rational then

(rationalize x y) => 0.

or if x is exact rational then

(rationalize x y) => 0

13. atan, asin, acos, log, etc.

The complex functions with branch cuts should be changed to conform

to the following pages in the CL Hyperspec:

http://www.harlequin.com/education/books/HyperSpec/Body/fun_asincm_acoscm_atan.html

http://www.harlequin.com/education/books/HyperSpec/Issues/iss069-writeup.html

These changes conform to the interpretation given above of +0. and

-0. lying to the right and to the left of exact zero.

Aug 16, 2003, 12:47:53 AM8/16/03

to

b...@cs.purdue.edu (Bradley J Lucier) writes:

> In article <vhtoeyt...@chur.ai.mit.edu>,

> Aubrey Jaffer <a...@alum.mit.edu> wrote:

> >b...@cs.purdue.edu (Bradley J Lucier) writes:

> >R5RS "Equivalence predicates" requires:

> >

> > `Eq?''s behavior on numbers and characters is

> > implementation-dependent, but it will always return either true or

> > false, and will return true only when `eqv?' would also return true.

>

> My proposal follows this.

>

> >> Gambit Version 4.0 beta 1

> >>

> >> > (eqv? (/ 0. 0.) (/ 0. 0.))

> >> #t

> >> > (= (/ 0. 0.) (/ 0. 0.))

> >> #f

> >> > (let ((nan (/ 0. 0.))) (eqv? nan nan))

> >> #t

> >> > (let ((nan (/ 0. 0.))) (= nan nan))

> >> #f

The reflexivity of equality is one of the most fundamental

mathematical principles. Is there any branch of mathematics in which

an object is not equal to itself? Acquiescence with floating-point

NaNs not being equal to themselves was responsible for non-conforming

(with R5RS) behavior in every Scheme implemenation tested.

> >

> >This same section of R5RS mandates that EQV? follow = for numbers of the

> >same type.

>

> Yes, and I'm suggesting a change:

>

> Proposals for integrating IEEE Floating-Point Arithmetic Standards 754

> and 854 with RnRS.

>

> I've gone over all of the back issues of the rrrs-authors mailing list

> (OK, I haven't read everything about exceptions and modules, but ...),

> and I would like to make certain proposals for Scheme arithmetic that I

> believe would bring it more in line with IEEE 754 and 854 arithmetic,

> *if* this arithmetic is used to implements (some) inexact numbers in

> a Scheme system. If other inexact number systems are used, then my

> suggestions would have no force.

Why would only Scheme be changing? Scheme already corrects some

deficiencies of IEEE-754. In "How to read floating point numbers

accurately" [ACM PLDI, 1990], William Clinger writes:

Consider the problem of converting decimal scientific notation for a

number into the best binary floating point approximation to that

number, for some fixed precision. This problem cannot be solved

using arithmetic of any fixed precision. Hence the IEEE Standard

for Binary Floating-Point Arithmetic does not require the result of

such a conversion to be the best approximation.

So reason has priority over IEEE-754 in defining Scheme.

> Note that the IEEE arithmetic standards say nothing about mixing integer

> (or exact) arithmetic with floating-point (or inexact) arithmetic; many of

> my suggestions below try to Do-the-Right-Thing (TM) in these situations.

>

> General Principles:

>

> 1. If an expression contains Not-a-Numbers (NaNs), and the same result

> would be obtained for any substitution of those NaNs by finite or infinite

> numbers, then that result should be returned.

>

> 2. I'm motivated by the following ansatz, taken from the

> sequence+ultrafilter construction of the non-standard reals. On input,

> +0. represents all sequences of positive numbers tending to zero;

> -0. represents all sequences of negative numbers tending to zero;

> +inf. represents all sequences of numbers tending to positive infinity;

> -inf. represents all sequences of numbers tending to negative infinity;

> and NaN represents all sequences of numbers. Results of operations

> between these quantities and exact numbers should be motivated by applying

> the same operation to all numbers of the sequence, e.g.,

>

> (* 0 NaN) => the sequence (* 0 x1) (* 0 x2) (* 0 x3) .... for any (x1, x2, ...)

> => the sequence 0 0 0 0 0 0 0 ... => exact 0

>

> 3. As a consequence of (2), +0. cannot be considered to lie exactly on

> zero, it lies a little to the right of zero on the number line; similarly,

> -0. lies a little to the left of zero.

Similarly, +0+1 would behave differently as an argument to

(lambda (x) (/ 1 (- x 1)))

than would -0+1. If we are to have shadings of every rational number,

then a zero-divisor transcendental element (eg. infinitesimal) must be

adjoined to the field. This is not difficult; most Schemes implement

complex numbers as reals (actually the rationals) with +i adjoined.

> Recommendations:

>

> 1. Infinities:

>

> I suggest that Scheme adopt standard read and write forms for IEEE

> positive and negative infinity, e.g., +inf. -inf.

Which IEEE specification makes the strings "+inf." and "-inf."

standard? The trailing periods are not recognized by glibc-2.2.

The "IEEE Standard for Binary Floating-Point Arithmetic" [ANSI/IEEE

Std 754Â1985] states:

... Over/underflow, NaNs, and infinities encountered during binary to

decimal conversion should be indicated to the user by appropriate

strings. NaNs encoded in decimal strings are not specified in this

standard.

> 2. Not-a-Numbers:

>

> I suggest that Scheme adopt standard write forms for IEEE NaNs that

> at least indicate the sign of the NaN, e.g., +nan. -nan.

Which sign of NaN should (sin (/ 1.0 0.0)) return?

> 3. eqv?:

>

> If x and y are two inexact numbers implemented as IEEE floating

> point numbers, then

>

> (eqv? x y) => #t

>

> if and only if x and y have the same base, sign, number of exponent

> digits, biased exponents, number of significand digits, and significands.

What about infinities?

> Rationale: No matter what bit-level representation is used for IEEE

> floating-point numbers (and Motorola, Intel, and others use several,

> beyond the issue of byte ordering), the quantities I specified above

> are well-defined by IEEE 754 and 854.

>

> The current definition of eqv? does not distinguish between -0. and

> +0. (since they are both equal (in the sense of Scheme =) and

> inexact. However, operations on +0. and -0. can yield very

> different results, e.g.,

>

> (/ 1. -0) => -inf.

> (/ 1. +0.) => +inf.

>

> Also, since

>

> (= x x) => #f

>

> if x is a NaN, the current definition would say that any Nan is not

> eqv to itself, which doesn't make much sense.

I agree. So I am changing SCM so (= NaN NaN) ==> #t.

> 4. Non-coercion of exact 0:

>

> If x is any number, and 0 represents exact zero, then

>

> (+ x 0) => x

> (- x 0) => x

> (- 0 x) => (- x)

> (* x 0) => 0

> (/ 0 x) => 0

> (/ x 0) => error

>

> Rationale: These results follow from a generalization of Priciple 1

> that goes as follows: If an expression contains inexact numbers, and

> the result of the expression does not change no matter what exact

> numbers are substituted for the inexact numbers, then that result

> should be returned.

I don't find this distinction between exact and inexact compelling.

What if the substitution of the exact number causes an error?

> There are other reasons for wanting to do this; the biggest

> practical reason is that it makes operations between reals and

> complexes, where the real x is coerced to (make-rectangular x 0),

> *much* easier to get correct.

Complex coercions already work for me. Can you give an example where

they don't?

> Here are some other arguments. ...

>

> 5. Extending the order operators to 0 or 1 arguments.

>

> For any numbers x

>

> (< x) => #t

> (= x) => #t

> etc.

>

> Also

>

> (<) => #t

> etc.

>

> Rationale: These operators are defined as asking whether a sequence

> satisfies a certain order relationship. These order relationships

> are automatically satisfied by sequences of length 0 or 1. This

> would simplify (apply op lst) if lst is a list of 0 or 1 elements.

This is not specific to floating-point but is a reasonable idea.

I grepped through the rrrs-authors archive but didn't find this

discussed.

> 6. Transcendental functions with special exact arguments

>

> I think it's time to require

>

> (log 1) => 0

> (exp 0) => 1

> (sin 0) => 0

> (cos 0) => 1

> (tan 0) => 0

> (atan 0) => 0

> (asin 0) => 0

> etc.

An essential feature of trigonometric functions is that they are

periodic. When you treat just one value of argument specially, you

make it non-periodic.

What problem does requiring this solve?

> 7. Complex numbers with imaginary parts +0. or -0. ...

The rest is more signs dancing on zeros. 1/x is no more special a

function than 1/(x-1) or 1/(x-2). Having infinitesimals only around

zero just doesn't work. Signs of zeros are unnecessary and should be

ignored.

If you start with a system which is inconsistent, then you can prove

anything about it. Without first fixing IEEE-754's inconsistent

elements, constructs exercising those elements will suffer.

Aug 16, 2003, 3:22:29 PM8/16/03

to

In article <m2ptj6r...@aubrey.jaffer>,

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>b...@cs.purdue.edu (Bradley J Lucier) writes:

>

>> In article <vhtoeyt...@chur.ai.mit.edu>,

>> Aubrey Jaffer <a...@alum.mit.edu> wrote:

>> >b...@cs.purdue.edu (Bradley J Lucier) writes:

>> >R5RS "Equivalence predicates" requires:

>> >

>> > `Eq?''s behavior on numbers and characters is

>> > implementation-dependent, but it will always return either true or

>> > false, and will return true only when `eqv?' would also return true.

>>

>> My proposal follows this.

>>

>> >> Gambit Version 4.0 beta 1

>> >>

>> >> > (eqv? (/ 0. 0.) (/ 0. 0.))

>> >> #t

>> >> > (= (/ 0. 0.) (/ 0. 0.))

>> >> #f

>> >> > (let ((nan (/ 0. 0.))) (eqv? nan nan))

>> >> #t

>> >> > (let ((nan (/ 0. 0.))) (= nan nan))

>> >> #f

>

>The reflexivity of equality is one of the most fundamental

>mathematical principles. Is there any branch of mathematics in which

>an object is not equal to itself? Acquiescence with floating-point

>NaNs not being equal to themselves was responsible for non-conforming

>(with R5RS) behavior in every Scheme implemenation tested.

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>b...@cs.purdue.edu (Bradley J Lucier) writes:

>

>> In article <vhtoeyt...@chur.ai.mit.edu>,

>> Aubrey Jaffer <a...@alum.mit.edu> wrote:

>> >b...@cs.purdue.edu (Bradley J Lucier) writes:

>> >R5RS "Equivalence predicates" requires:

>> >

>> > `Eq?''s behavior on numbers and characters is

>> > implementation-dependent, but it will always return either true or

>> > false, and will return true only when `eqv?' would also return true.

>>

>> My proposal follows this.

>>

>> >> Gambit Version 4.0 beta 1

>> >>

>> >> > (eqv? (/ 0. 0.) (/ 0. 0.))

>> >> #t

>> >> > (= (/ 0. 0.) (/ 0. 0.))

>> >> #f

>> >> > (let ((nan (/ 0. 0.))) (eqv? nan nan))

>> >> #t

>> >> > (let ((nan (/ 0. 0.))) (= nan nan))

>> >> #f

>

>The reflexivity of equality is one of the most fundamental

>mathematical principles. Is there any branch of mathematics in which

>an object is not equal to itself? Acquiescence with floating-point

>NaNs not being equal to themselves was responsible for non-conforming

>(with R5RS) behavior in every Scheme implemenation tested.

You know as well as I do that there are several (many) notions of equality

in lisp(s). I'm suggesting that an object is always eq?/eqv?/equal? to

itself; it happens to be useful to have a NaN be not = to itself.

>> >This same section of R5RS mandates that EQV? follow = for numbers of the

>> >same type.

>>

>> Yes, and I'm suggesting a change:

>>

>> Proposals for integrating IEEE Floating-Point Arithmetic Standards 754

>> and 854 with RnRS.

>>

>> I've gone over all of the back issues of the rrrs-authors mailing list

>> (OK, I haven't read everything about exceptions and modules, but ...),

>> and I would like to make certain proposals for Scheme arithmetic that I

>> believe would bring it more in line with IEEE 754 and 854 arithmetic,

>> *if* this arithmetic is used to implement (some) inexact numbers in

>> a Scheme system. If other inexact number systems are used, then my

>> suggestions would have no force.

>

>Why would only Scheme be changing? Scheme already corrects some

>deficiencies of IEEE-754. In "How to read floating point numbers

>accurately" [ACM PLDI, 1990], William Clinger writes:

>

> Consider the problem of converting decimal scientific notation for a

> number into the best binary floating point approximation to that

> number, for some fixed precision. This problem cannot be solved

> using arithmetic of any fixed precision. Hence the IEEE Standard

> for Binary Floating-Point Arithmetic does not require the result of

> such a conversion to be the best approximation.

>

>So reason has priority over IEEE-754 in defining Scheme.

Having exact binary-decimal conversion in Scheme in no way contradicts

IEEE-754, it's a very reasonable extension to IEEE-754.

>> 3. As a consequence of (2), +0. cannot be considered to lie exactly on

>> zero, it lies a little to the right of zero on the number line; similarly,

>> -0. lies a little to the left of zero.

>

>Similarly, +0+1 would behave differently as an argument to

>

> (lambda (x) (/ 1 (- x 1)))

>

>than would -0+1. If we are to have shadings of every rational number,

>then a zero-divisor transcendental element (eg. infinitesimal) must be

>adjoined to the field. This is not difficult; most Schemes implement

>complex numbers as reals (actually the rationals) with +i adjoined.

What do you mean here by +0+1 and -0+1? Your notation seems quite nonstandard.

>> Recommendations:

>>

>> 1. Infinities:

>>

>> I suggest that Scheme adopt standard read and write forms for IEEE

>> positive and negative infinity, e.g., +inf. -inf.

>

>Which IEEE specification makes the strings "+inf." and "-inf."

>standard? The trailing periods are not recognized by glibc-2.2.

>The "IEEE Standard for Binary Floating-Point Arithmetic" [ANSI/IEEE

>Std 754Â1985] states:

>

> ... Over/underflow, NaNs, and infinities encountered during binary to

> decimal conversion should be indicated to the user by appropriate

> strings. NaNs encoded in decimal strings are not specified in this

> standard.

"E.g." means "for example"; your comments are addressing something I didn't

write.

>> 2. Not-a-Numbers:

>>

>> I suggest that Scheme adopt standard write forms for IEEE NaNs that

>> at least indicate the sign of the NaN, e.g., +nan. -nan.

>

>Which sign of NaN should (sin (/ 1.0 0.0)) return?

Signs of NaNs could be useful in creating, e.g., signalling versus

non-signalling NaNs. If you have a system that deals with both types of

NaNs, and uses the signs of those NaNs to differentiate them, it would be

nice to have an input notation for this.

>> 3. eqv?:

>>

>> If x and y are two inexact numbers implemented as IEEE floating

>> point numbers, then

>>

>> (eqv? x y) => #t

>>

>> if and only if x and y have the same base, sign, number of exponent

>> digits, biased exponents, number of significand digits, and significands.

>

>What about infinities?

What about them? All those quantities are precisely defined for both

infinities and NaNs.

>> Rationale: No matter what bit-level representation is used for IEEE

>> floating-point numbers (and Motorola, Intel, and others use several,

>> beyond the issue of byte ordering), the quantities I specified above

>> are well-defined by IEEE 754 and 854.

>>

>> The current definition of eqv? does not distinguish between -0. and

>> +0. (since they are both equal (in the sense of Scheme =) and

>> inexact. However, operations on +0. and -0. can yield very

>> different results, e.g.,

>>

>> (/ 1. -0) => -inf.

>> (/ 1. +0.) => +inf.

>>

>> Also, since

>>

>> (= x x) => #f

>>

>> if x is a NaN, the current definition would say that any Nan is not

>> eqv to itself, which doesn't make much sense.

>

>I agree. So I am changing SCM so (= NaN NaN) ==> #t.

And I'm divorcing numerical = from other notions of identity/equality in

Scheme.

>> 4. Non-coercion of exact 0:

>>

>> If x is any number, and 0 represents exact zero, then

>>

>> (+ x 0) => x

>> (- x 0) => x

>> (- 0 x) => (- x)

>> (* x 0) => 0

>> (/ 0 x) => 0

>> (/ x 0) => error

>>

>> Rationale: These results follow from a generalization of Priciple 1

>> that goes as follows: If an expression contains inexact numbers, and

>> the result of the expression does not change no matter what exact

>> numbers are substituted for the inexact numbers, then that result

>> should be returned.

>

>I don't find this distinction between exact and inexact compelling.

>What if the substitution of the exact number causes an error?

???

>> There are other reasons for wanting to do this; the biggest

>> practical reason is that it makes operations between reals and

>> complexes, where the real x is coerced to (make-rectangular x 0),

>> *much* easier to get correct.

>

>Complex coercions already work for me. Can you give an example where

>they don't?

(* 1 +inf.+inf.i) => (* (make-rectangular 1 0) +inf.+inf.i)

=> (make-rectangular (- (* 1 +inf.) (* 0 +inf.))

(+ (* 0 +inf.) (* 1 +inf.)))

=> (make-rectangular (- (* 1. +inf.) (* 0. +inf.))

(+ (* 0. +inf.) (* 1. +inf.)))

=> (make-rectangular (- +inf. +nan.)

(+ +nan. +inf.))

=> +nan.+nan.i

My way (* 1 +inf.+inf.i) => +inf.+inf.i.

>> 6. Transcendental functions with special exact arguments

>>

>> I think it's time to require

>>

>> (log 1) => 0

>> (exp 0) => 1

>> (sin 0) => 0

>> (cos 0) => 1

>> (tan 0) => 0

>> (atan 0) => 0

>> (asin 0) => 0

>> etc.

>

>An essential feature of trigonometric functions is that they are

>periodic. When you treat just one value of argument specially, you

>make it non-periodic.

The period of these functions is either Pi or 2Pi. If you goes to the trouble

of having an exact representation of rational multiples of Pi in the your number

system, I'd presume you'd go to the trouble of making the appropriate

trigonometric functions periodic at those multiples.

>What problem does requiring this solve?

Mainly elementary functions of complex arguments; for example, Gambit gives

(- (expt (sqrt -1) (sqrt -1)) (exp (- (* (atan 1) 2)))) => 0.

Note that the imaginary part is exact 0.

>> 7. Complex numbers with imaginary parts +0. or -0. ...

>

>The rest is more signs dancing on zeros. 1/x is no more special a

>function than 1/(x-1) or 1/(x-2). Having infinitesimals only around

>zero just doesn't work. Signs of zeros are unnecessary and should be

>ignored.

>

>If you start with a system which is inconsistent, then you can prove

>anything about it. Without first fixing IEEE-754's inconsistent

>elements, constructs exercising those elements will suffer.

First, I agree that IEEE-754 is, in some ways, inconsistent. I claim it is

also useful.

Second, my introductory paragraph says

>> I would like to make certain proposals for Scheme arithmetic that I

>> believe would bring it more in line with IEEE 754 and 854 arithmetic,

>> *if* this arithmetic is used to implement (some) inexact numbers in

>> a Scheme system. If other inexact number systems are used, then my

>> suggestions would have no force.

You don't want to implement IEEE-754 in Scheme. Fine. I'm not making

suggestions for people who don't want to implement IEEE-754 in Scheme.

Brad

Aug 18, 2003, 5:38:43 PM8/18/03

to

Aubrey Jaffer <a...@alum.mit.edu> wrote:

> sh...@acm.org (Shiro Kawai) writes:

>>

>> As far as I know, all implementations that support NaN

>> return #f for (= nan nan), which I think is IEEE754 compliant.

>> However, some implementations (AFAIK, all but Bigloo)

>> return #t for (eqv? nan nan) in some cases.

>

> Excellent catch! The appended patch fixes SCM so that:

>

>> (= 0/0 0/0)

> #f

>> (eqv? 0/0 0/0)

> #f

>> (let ((nan 0/0)) (= nan nan))

> #t

> sh...@acm.org (Shiro Kawai) writes:

>>

>> As far as I know, all implementations that support NaN

>> return #f for (= nan nan), which I think is IEEE754 compliant.

>> However, some implementations (AFAIK, all but Bigloo)

>> return #t for (eqv? nan nan) in some cases.

>

> Excellent catch! The appended patch fixes SCM so that:

>

>> (= 0/0 0/0)

> #f

>> (eqv? 0/0 0/0)

> #f

>> (let ((nan 0/0)) (= nan nan))

> #t

umm... how so? why should comparing (numericaly) 0/0 with

0/0 be different depedning on whetever it is compared

directly or assigned (whetever via set! or let) to a location?

This looks really broken.

---

Sander

+++ Out of cheese error +++

Aug 18, 2003, 5:53:15 PM8/18/03

to

Aubrey Jaffer <a...@alum.mit.edu> wrote:

>

> The reflexivity of equality is one of the most fundamental

> mathematical principles. Is there any branch of mathematics in which

> an object is not equal to itself? Acquiescence with floating-point

> NaNs not being equal to themselves was responsible for non-conforming

> (with R5RS) behavior in every Scheme implemenation tested.

>

>

> The reflexivity of equality is one of the most fundamental

> mathematical principles. Is there any branch of mathematics in which

> an object is not equal to itself? Acquiescence with floating-point

> NaNs not being equal to themselves was responsible for non-conforming

> (with R5RS) behavior in every Scheme implemenation tested.

>

NaN needs to be numericaly (that is in teh sence of =) be unequal to

*any* number, including itself. If this is not so, why bother with

IEEE 754 if you are going to implement something that is like IEEE 754

but not quite it ? You might then just as well deifine division by zero

to return #unspecific.

If you don't bother to actually implement what IEEE 754 specifies then

you *should* *not* call what you implement IEEE754 or imply in any

way that there is a relation, because otherwise people might assume

you actually implement it (which would in no way be even approximating

truth) and teh resulting programs would be failing in various bizzare and

often unpredictable ways.

--

Aug 19, 2003, 11:43:15 PM8/19/03

to

And I know the more stringent EQ? is #t only if the less stringent EQV?

is #t. That is true for Lisp and Scheme.

> I'm suggesting that an object is always eq?/eqv?/equal? to

> itself; it happens to be useful to have a NaN be not = to itself.

How is it useful? No longer does a loop halving an (inexact) variable

terminate when the halved variable is equal to the non-halved variable

-- Unless it checks for NaN explicitly.

> >> Recommendations:

>

> >> 2. Not-a-Numbers:

> >>

> >> I suggest that Scheme adopt standard write forms for IEEE NaNs that

> >> at least indicate the sign of the NaN, e.g., +nan. -nan.

> >

> >Which sign of NaN should (sin (/ 1.0 0.0)) return?

>

> Signs of NaNs could be useful in creating, e.g., signalling versus

> non-signalling NaNs. If you have a system that deals with both types of

> NaNs, and uses the signs of those NaNs to differentiate them, it would be

> nice to have an input notation for this.

Using sign to indicate something unreleated to arithmetic is bad

practice. To distinguish NaNs, how about "NaN" and "NaNq"?

> >> 3. eqv?:

> >>

> >> If x and y are two inexact numbers implemented as IEEE floating

> >> point numbers, then

> >>

> >> (eqv? x y) => #t

> >>

> >> if and only if x and y have the same base, sign, number of exponent

> >> digits, biased exponents, number of significand digits, and significands.

> >

> >What about infinities?

>

> What about them? All those quantities are precisely defined for both

> infinities and NaNs.

In that case, NaN == NaN because all of the fields you mentioned have

the same values.

> >> 4. Non-coercion of exact 0:

> >>

> >> If x is any number, and 0 represents exact zero, then

> >>

> >> (+ x 0) => x

> >> (- x 0) => x

> >> (- 0 x) => (- x)

> >> (* x 0) => 0

> >> (/ 0 x) => 0

> >> (/ x 0) => error

> >>

> >> Rationale: These results follow from a generalization of Priciple 1

> >> that goes as follows: If an expression contains inexact numbers, and

> >> the result of the expression does not change no matter what exact

> >> numbers are substituted for the inexact numbers, then that result

> >> should be returned.

> >

> >I don't find this distinction between exact and inexact compelling.

> >What if the substitution of the exact number causes an error?

>

> ???

(/ 0 x) does not => 0 because (/ 0 0) is an error.

> >> There are other reasons for wanting to do this; the biggest

> >> practical reason is that it makes operations between reals and

> >> complexes, where the real x is coerced to (make-rectangular x 0),

> >> *much* easier to get correct.

> >

> >Complex coercions already work for me. Can you give an example where

> >they don't?

>

> (* 1 +inf.+inf.i) => (* (make-rectangular 1 0) +inf.+inf.i)

> => (make-rectangular (- (* 1 +inf.) (* 0 +inf.))

> (+ (* 0 +inf.) (* 1 +inf.)))

> => (make-rectangular (- (* 1. +inf.) (* 0. +inf.))

> (+ (* 0. +inf.) (* 1. +inf.)))

> => (make-rectangular (- +inf. +nan.)

> (+ +nan. +inf.))

> => +nan.+nan.i

>

> My way (* 1 +inf.+inf.i) => +inf.+inf.i.

SCM gives the same answer *without* making your distinctions between

exact and inexact zeros:

SCM version 5d8, Copyright (C) 1990-2002 Free Software Foundation.

SCM comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.

This is free software, and you are welcome to redistribute it

under certain conditions; type `(terms)' for details.

> (* 1 1/0+1/0i)

1/0+1/0i

> >> 6. Transcendental functions with special exact arguments

> >>

> >> I think it's time to require

> >>

> >> (log 1) => 0

> >> (exp 0) => 1

> >> (sin 0) => 0

> >> (cos 0) => 1

> >> (tan 0) => 0

> >> (atan 0) => 0

> >> (asin 0) => 0

> >> etc.

> >

> >An essential feature of trigonometric functions is that they are

> >periodic. When you treat just one value of argument specially, you

> >make it non-periodic.

>

> The period of these functions is either Pi or 2Pi. If you goes to the trouble

> of having an exact representation of rational multiples of Pi in the your number

> system, I'd presume you'd go to the trouble of making the appropriate

> trigonometric functions periodic at those multiples.

>

> >What problem does requiring this solve?

>

> Mainly elementary functions of complex arguments; for example, Gambit gives

>

> (- (expt (sqrt -1) (sqrt -1)) (exp (- (* (atan 1) 2)))) => 0.

SCM returns 0.0 for that expression -- so those exact identities

apparently are *not* required.

> (- (expt (sqrt -1) (sqrt -1)) (exp (- (* (atan 1) 2))))

0.0

> Note that the imaginary part is exact 0.

R5RS (http://www.swiss.ai.mit.edu/~jaffer/r5rs_8.html#SEC55)

does not allow mixed exactness:

- procedure: exact? Z

- procedure: inexact? Z

These numerical predicates provide tests for the exactness of a

quantity. For any Scheme number, precisely one of these predicates

is true.

Aug 20, 2003, 11:52:24 AM8/20/03

to

In article <vhtwud9...@aarau.ai.mit.edu>,

Aubrey Jaffer <a...@alum.mit.edu> wrote:

...

Aubrey Jaffer <a...@alum.mit.edu> wrote:

...

It's clear we have different backgrounds and viewpoints in this issue. To

be frank, I consider some of your arguments to be nearly ludicrous and I don't

find them to be worth response. So I will back out of this discussion now.

Brad

Aug 20, 2003, 1:42:40 PM8/20/03

to

As I see it, eq? isn't a mathematical equivalence at all.

eq? is not a mathematical equivalence predicate at all.

eq? is a test to see whether two things refer to the same

memory location. So, I'd expect

(eq? foo foo) => #t

regardless of what value was stored in foo.

eqv? however, is a value-equivalence predicate.

So I'd expect

(eqv? foo foo) => #t

whenever foo was bound to some meaningful and comparable

value. According to IEEE, a NaN is not both meaningful

and comparable. We could allow eqv? to return true because

eq? returns true in this case, guaranteeing that they are

from the same expression - that whatever the indeterminate

value may be, it is definitely the same indeterminate value.

I don't know whether this would be considered a violation

of IEEE.

But if we have

(eqv? (/ 1 0) (/ 1 0)) => #t,

I'd say that's wrong. These NaNs don't come from the same

expression, even though they come from lexically identical

expressions. They are incomparable, and IEEE specifies that

the results of comparison ought to be #f.

Bear

Aug 20, 2003, 2:06:19 PM8/20/03

to

Aubrey Jaffer <a...@alum.mit.edu> writes:

> b...@cs.purdue.edu (Bradley J Lucier) writes:

>

>> I'm suggesting that an object is always eq?/eqv?/equal? to

>> itself; it happens to be useful to have a NaN be not = to itself.

>

> How is it useful? No longer does a loop halving an (inexact) variable

> terminate when the halved variable is equal to the non-halved variable

> -- Unless it checks for NaN explicitly.

I'd have to agree with Bradley Lucier on this. There's a rationale

behind NaN != NaN. It's not what a Schemer would do, but it *is* what

is specified by IEEE 754 arithmetic. Kahan points out:

`NaNs must conform to mathematically consistent rules that were

deduced, not invented arbitrarily, in 1977 during the design of the

Intel 8087 that preceded IEEE 754.'

I suppose providing `IEEE754=' as a primitive that returned #f when

presented with EQ? NaN would be workable.

>> >The reflexivity of equality is one of the most fundamental

>> >mathematical principles. Is there any branch of mathematics in which

>> >an object is not equal to itself? Acquiescence with floating-point

>> >NaNs not being equal to themselves was responsible for non-conforming

>> >(with R5RS) behavior in every Scheme implemenation tested.

This is circular reasoning. You are saying `NaN must = NaN' because

Schemes that implement it that way do that, but Schemes that don't do

not.

> Using sign to indicate something unreleated to arithmetic is bad

> practice. To distinguish NaNs, how about "NaN" and "NaNq"?

I agree with Aubrey Jaffer on this.

>> >> 3. eqv?:

>> >>

>> >> If x and y are two inexact numbers implemented as IEEE floating

>> >> point numbers, then

>> >>

>> >> (eqv? x y) => #t

>> >>

>> >> if and only if x and y have the same base, sign, number of exponent

>> >> digits, biased exponents, number of significand digits, and significands.

>> >

>> >What about infinities?

>>

>> What about them? All those quantities are precisely defined for both

>> infinities and NaNs.

>

> In that case, NaN == NaN because all of the fields you mentioned have

> the same values.

Frankly, I don't understand what EQV? is for.

Originally, EQ? meant `compare these bits with those'. But that

means that fixnums are EQ? when =, but bignums aren't. So we paper

over that with EQV?. But it seems to me that EQ? means two things:

1. SYMBOL-EQ? Is this symbol the same as that.

2. MUTABLE-EQ? If I were to mutate this, would that change.

(although not quite, it works with some immutable

things, too)

>> >> 6. Transcendental functions with special exact arguments

>> >>

>> >> I think it's time to require

>> >>

>> >> (log 1) => 0

>> >> (exp 0) => 1

>> >> (sin 0) => 0

>> >> (cos 0) => 1

>> >> (tan 0) => 0

>> >> (atan 0) => 0

>> >> (asin 0) => 0

>> >> etc.

>> >

>> >An essential feature of trigonometric functions is that they are

>> >periodic. When you treat just one value of argument specially, you

>> >make it non-periodic.

I'd go with Bradley Lucier on this one. These functions are defined

exactly for those inputs. I'd expect them to produce exact results

for *any* result that is representable exactly.

Aug 24, 2003, 11:31:01 PM8/24/03

to

Someone suggested to me privately that it would be useful if we could

work something out here. Aubrey's comments have made me make my

thinking about notation of NaNs more precisely; perhaps some

discussion of the other points would be helpful, too.

work something out here. Aubrey's comments have made me make my

thinking about notation of NaNs more precisely; perhaps some

discussion of the other points would be helpful, too.

Brad

Aubrey Jaffer <a...@alum.mit.edu> wrote in message news:<vhtwud9...@aarau.ai.mit.edu>...

> b...@cs.purdue.edu (Bradley J Lucier) writes:

>

> > In article <m2ptj6r...@aubrey.jaffer>,

> > Aubrey Jaffer <a...@alum.mit.edu> wrote:

> > >b...@cs.purdue.edu (Bradley J Lucier) writes:

> > >

> > >> In article <vhtoeyt...@chur.ai.mit.edu>,

> > >> Aubrey Jaffer <a...@alum.mit.edu> wrote:

> > >> >b...@cs.purdue.edu (Bradley J Lucier) writes:

>

> And I know the more stringent EQ? is #t only if the less stringent EQV?

> is #t. That is true for Lisp and Scheme.

Yes, and my proposal wouldn't change this.

> > I'm suggesting that an object is always eq?/eqv?/equal? to

> > itself; it happens to be useful to have a NaN be not = to itself.

>

> How is it useful? No longer does a loop halving an (inexact) variable

> terminate when the halved variable is equal to the non-halved variable

> -- Unless it checks for NaN explicitly.

It is useful in various ways that I'm not going to list here. They

aren't a secret, go to Kahan's web site if you're interested.

> > >> Recommendations:

>

> > >> 2. Not-a-Numbers:

> > >>

> > >> I suggest that Scheme adopt standard write forms for IEEE NaNs that

> > >> at least indicate the sign of the NaN, e.g., +nan. -nan.

> > >

> > >Which sign of NaN should (sin (/ 1.0 0.0)) return?

> >

> > Signs of NaNs could be useful in creating, e.g., signalling versus

> > non-signalling NaNs. If you have a system that deals with both types of

> > NaNs, and uses the signs of those NaNs to differentiate them, it would be

> > nice to have an input notation for this.

>

> Using sign to indicate something unreleated to arithmetic is bad

> practice. To distinguish NaNs, how about "NaN" and "NaNq"?

OK, my entire concern is that there are many different NaNs (any

floating point number with the maximum exponent and nonzero fractional

part of the mantissa) and it would be good to be able both to print

and to read any bit pattern for a NaN that may be produced as output

or relevant as input by the hardware or the library on any given

system. Perhaps +nan.xxxxxxxx where x is a hex digit and there are 8

(or 16 or however many are necessary) hex digits to specify a NaN.

>

> > >> 3. eqv?:

> > >>

> > >> If x and y are two inexact numbers implemented as IEEE floating

> > >> point numbers, then

> > >>

> > >> (eqv? x y) => #t

> > >>

> > >> if and only if x and y have the same base, sign, number of exponent

> > >> digits, biased exponents, number of significand digits, and significands.

> > >

> > >What about infinities?

> >

> > What about them? All those quantities are precisely defined for both

> > infinities and NaNs.

>

> In that case, NaN == NaN because all of the fields you mentioned have

> the same values.

This is getting nonsensical. My proposal divorces eqv? from =.

Period. And this statement was about eqv?, not =.

> > >> 4. Non-coercion of exact 0:

> > >>

> > >> If x is any number, and 0 represents exact zero, then

> > >>

> > >> (+ x 0) => x

> > >> (- x 0) => x

> > >> (- 0 x) => (- x)

> > >> (* x 0) => 0

> > >> (/ 0 x) => 0

> > >> (/ x 0) => error

> > >>

> > >> Rationale: These results follow from a generalization of Priciple 1

> > >> that goes as follows: If an expression contains inexact numbers, and

> > >> the result of the expression does not change no matter what exact

> > >> numbers are substituted for the inexact numbers, then that result

> > >> should be returned.

> > >

> > >I don't find this distinction between exact and inexact compelling.

> > >What if the substitution of the exact number causes an error?

> >

> > ???

>

> (/ 0 x) does not => 0 because (/ 0 0) is an error.

Yes, that's true. In grade school you learn you can't divide by zero;

in university you learn that in any ring 0 does not have an inverse;

having

(/ 0 x) => 0

unconditionally is not a safe optimization.

And you're being inconsistent---you object to (* 0 x) => 0

unconditionally.

> > >> There are other reasons for wanting to do this; the biggest

> > >> practical reason is that it makes operations between reals and

> > >> complexes, where the real x is coerced to (make-rectangular x 0),

> > >> *much* easier to get correct.

> > >

> > >Complex coercions already work for me. Can you give an example where

> > >they don't?

> >

> > (* 1 +inf.+inf.i) => (* (make-rectangular 1 0) +inf.+inf.i)

> > => (make-rectangular (- (* 1 +inf.) (* 0 +inf.))

> > (+ (* 0 +inf.) (* 1 +inf.)))

> > => (make-rectangular (- (* 1. +inf.) (* 0. +inf.))

> > (+ (* 0. +inf.) (* 1. +inf.)))

> > => (make-rectangular (- +inf. +nan.)

> > (+ +nan. +inf.))

> > => +nan.+nan.i

> >

> > My way (* 1 +inf.+inf.i) => +inf.+inf.i.

>

> SCM gives the same answer *without* making your distinctions between

> exact and inexact zeros:

>

> SCM version 5d8, Copyright (C) 1990-2002 Free Software Foundation.

> SCM comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.

> This is free software, and you are welcome to redistribute it

> under certain conditions; type `(terms)' for details.

> > (* 1 1/0+1/0i)

> 1/0+1/0i

I said that this property makes it easier to get complex

multiplication correct, not that it was necessary to get it correct;

it is certainly possible to get it correct without having this

property by special casing real * complex, purely imaginary * complex,

etc.

>

> > >> 6. Transcendental functions with special exact arguments

> > >>

> > >> I think it's time to require

> > >>

> > >> (log 1) => 0

> > >> (exp 0) => 1

> > >> (sin 0) => 0

> > >> (cos 0) => 1

> > >> (tan 0) => 0

> > >> (atan 0) => 0

> > >> (asin 0) => 0

> > >> etc.

> > >

> > >An essential feature of trigonometric functions is that they are

> > >periodic. When you treat just one value of argument specially, you

> > >make it non-periodic.

> >

> > The period of these functions is either Pi or 2Pi. If you goes to the trouble

> > of having an exact representation of rational multiples of Pi in the your number

> > system, I'd presume you'd go to the trouble of making the appropriate

> > trigonometric functions periodic at those multiples.

> >

> > >What problem does requiring this solve?

> >

> > Mainly elementary functions of complex arguments; for example, Gambit gives

> >

> > (- (expt (sqrt -1) (sqrt -1)) (exp (- (* (atan 1) 2)))) => 0.

>

> SCM returns 0.0 for that expression -- so those exact identities

> apparently are *not* required.

>

> > (- (expt (sqrt -1) (sqrt -1)) (exp (- (* (atan 1) 2))))

> 0.0

They may not be *required* to solve this problem, but they still solve

the problem, which is the only thing I claimed.

> > Note that the imaginary part is exact 0.

>

> R5RS (http://www.swiss.ai.mit.edu/~jaffer/r5rs_8.html#SEC55)

> does not allow mixed exactness:

>

> - procedure: exact? Z

> - procedure: inexact? Z

> These numerical predicates provide tests for the exactness of a

> quantity. For any Scheme number, precisely one of these predicates

> is true.

And your point is? Should I have said that the result is real,

instead of saying that its imaginary part is exact zero?

Brad

Aug 25, 2003, 6:21:51 PM8/25/03

to

I've put together a small test program that computes the values of +, -, *, and

/ when the arguments are complex and the real and imaginary parts are all

possible combinations of

/ when the arguments are complex and the real and imaginary parts are all

possible combinations of

(define arguments (list 0

1

-1

plus-zero

minus-zero

1.

-1.

plus-infinity

minus-infinity

not-a-number))

The program and the results for Gambit can be found at

http://www.math.purdue.edu/~lucier/scheme/complex-tests

While some work is needed to port it to other Scheme (I used Gambit's built-in

exception handler) the results should be independent of the Scheme's system

notation for infinities and not-a-numbers.

The algorithms in Gambit use the ideas in my previous proposal, so if you find

that any of these 40,000 results should be different, I'd like to hear about

it. Hopefully you'll be able to compare the results from your favorite Scheme

with Gambit's results.

Brad Lucier

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu