eqv? issues summarized

23 views
Skip to first unread message

Alex Shinn

unread,
Mar 21, 2012, 11:32:49 AM3/21/12
to scheme-re...@googlegroups.com
There are too many posts and tangents in the other
thread, so I'm summarizing the issues here.

Scheme provides eq?, eqv? and equal? as different
gradations of equality comparison. eq? is object
identity, which is somewhat implementation dependent
but both extremely efficient and useful.

equal? is a high-level equality comparison which
recursively compares structures, comparing leaf
nodes with eqv?.

Beyond minor details, and the cycle handling of
equal? (which we already voted is required), neither
of these are especially ambiguous or controversial.

The biggest issues concern how we define eqv?.
To a certain extent this is arbitrary, and alternatives can
be defined at the user-level, but we want a good
default in the core language.

R5RS basically thinks of eqv? as a cleaned up eq?,
hiding away the implementation details that arise
from different internal numeric implementations
and the need to heap-allocate some numbers. In
practice this means eqv? is the same as eq?,
except that characters are compared with char=?
and numbers with = plus same exactness.

This is a middle of the road approach. A broader
approach would be to remove the exactness
requirement (and still broader approaches could
allow string comparison, etc.).

R6RS takes a narrower approach, trying to
expose as many differences as possible. The
exact text of R6RS is [(eqv? obj1 obj2) returns
true if]:

Obj1 and obj2 are both exactnumber objects and are numerically
equal (see =, section 11.7).

Obj1 and obj2 are both inexactnumber objects, are numerically
equal (see =, section 11.7), and yield the same results (in the
sense of eqv?) when passed as arguments to any other procedure
that can be defined as a finite composition of Scheme’s
standard arithmetic procedures.

In the draft R7RS, we have not made this change
(nor has it been brought up for vote) so we have the
R5RS semantics, i.e. numbers are eqv? if they are
of the same exactness and they are =.

Instead of addressing this change directly, we have
two separate items:

#229 (eqv? +nan.0 x) => ?
#345 (eqv? -0.0 0.0) => ?

Item #229, re-opened because it was incorrectly
stated, was _still_ incorrect and has just been fixed.
The "same" semantics is not from R6RS, which in
fact lists this as one of the "unspecified" cases.
Therefore "same" is incompatible with both R5 and
R6 and needs strong justification to pass.

Item #345, on the other hand, fairly clearly should
be #true in R5 and #false in R6. The default here
is again R5, and the justification for an "unspecified"
vote would be the de-facto split in results from
existing implementations.

Both of these need to be kept consistent with the
definition we use for eqv?. An objection has been
raised, and we may need to strike these and replace
them with a unified item for eqv?, but I'd ask you
to continue discussing them and vote on them as-is
for the time being.

</impartial-chair-hat>

Personally, I have concerns about the motivation,
definition, and implementation of R6RS eqv?.

The motivation as others state is the desire to be able
to expose differences in IEEE floats not otherwise exposed
by =. I think this is an extremely specific and low-level
operation, is moot in the case of implementations without
IEEE floats, and is better served by specialized utilities
such as decode-float. eqv? above all should be consistent
and easy to remember the semantics for.

Of a greater concern, however, is the definition as stated
in R6RS, which seems overly vague and fragile, as the
result can change with the introduction of new standard
arithmetic procedures (I'm not sure exactly what that
means but assume it refers to everything in 11.7).
Moreover, this definition is inherently implementation
dependent. R6RS made strict requirements on the
existence of the full numeric tower and the use of exact
IEEE 754 semantics which R7RS (small) does not require.
On this basis, the R6RS eqv? has no place in R7RS.

The implementation, as well, seems to suggest of a
maze of various branches. One argument made was that in
effect eqv? on numbers would just be a bitwise comparison,
but it may not be so simple (even in R6RS). For example,
the following should all return #true under the R6RS
definitions, though every one of them may have a different
internal representation:

(eqv? 0.5 #i1/2) => #true
(eqv? 0.5 0.5L0) => #true
(eqv? 0.5 0.5+0i) => #true

whereas we would end up with:

(eqv? -0.0 -0.0L0) => #false
(eqv? -0.0 -0.0+0i) => #false

Finally, the option in #229 to require (eqv? +nan.0 +nan.0)
=> #true is simply inconsistent with R5RS, R6RS and reality.

--
Alex

John Cowan

unread,
Mar 21, 2012, 9:52:08 PM3/21/12
to scheme-re...@googlegroups.com
Alex Shinn scripsit:

> Of a greater concern, however, is the definition as stated in R6RS,
> which seems overly vague and fragile, as the result can change with
> the introduction of new standard arithmetic procedures (I'm not sure
> exactly what that means but assume it refers to everything in 11.7).
> Moreover, this definition is inherently implementation dependent.
> R6RS made strict requirements on the existence of the full numeric
> tower and the use of exact IEEE 754 semantics which R7RS (small) does
> not require.

Actually, R6RS does not require IEEE semantics either: it only says
what to do if you have IEEE flonums. It is perfectly conformant to use
floats with no infinity, NaN, or 0.0 if you prefer.

> [T]he following should all return #true under the R6RS definitions,


> though every one of them may have a different internal representation:
>
> (eqv? 0.5 #i1/2) => #true

The difference here is or should be merely notational, no different from
#i2/4 or 0.500.

> (eqv? 0.5 0.5L0) => #true

This is false if there is a distinction between e-floats and l-floats,
because you can get different answers when passing these to /.

> (eqv? 0.5 0.5+0i) => #true

This is definitely false, because (real? 0.5) is true whereas
(real? 0.5+0.5i) is false in R6RS.

> Finally, the option in #229 to require (eqv? +nan.0 +nan.0) => #true
> is simply inconsistent with R5RS, R6RS and reality.

True, because they do not satisfy =, which is a requirement in both R5RS
and R6RS. However, this case is explicitly indeterminate in draft 6.

--
John Cowan http://ccil.org/~cowan co...@ccil.org
'Tis the Linux rebellion / Let coders take their place,
The Linux-nationale / Shall Microsoft outpace,
We can write better programs / Our CPUs won't stall,
So raise the penguin banner of / The Linux-nationale. --Greg Baker

Alex Shinn

unread,
Mar 21, 2012, 10:08:19 PM3/21/12
to scheme-re...@googlegroups.com
On Thu, Mar 22, 2012 at 10:52 AM, John Cowan <co...@mercury.ccil.org> wrote:
> Alex Shinn scripsit:
>
>> Of a greater concern, however, is the definition as stated in R6RS,
>> which seems overly vague and fragile, as the result can change with
>> the introduction of new standard arithmetic procedures (I'm not sure
>> exactly what that means but assume it refers to everything in 11.7).
>> Moreover, this definition is inherently implementation dependent.
>> R6RS made strict requirements on the existence of the full numeric
>> tower and the use of exact IEEE 754 semantics which R7RS (small) does
>> not require.
>
> Actually, R6RS does not require IEEE semantics either: it only says
> what to do if you have IEEE flonums.  It is perfectly conformant to use
> floats with no infinity, NaN, or 0.0 if you prefer.
>
>> [T]he following should all return #true under the R6RS definitions,
>> though every one of them may have a different internal representation:
>>
>>   (eqv? 0.5 #i1/2) => #true
>
> The difference here is or should be merely notational, no different from
> #i2/4 or 0.500.

It may or may not be notational - an implementation
could support inexact-tagged ratios.

>>   (eqv? 0.5 0.5L0) => #true
>
> This is false if there is a distinction between e-floats and l-floats,
> because you can get different answers when passing these to /.

Not necessarily - 1/2 can be represented exactly by
both floats and doubles, and the promotion rules are
implementation dependent. As a trivial case, floats
could only be used for compact storage in memory,
and be automatically promoted to double on _any_
computation.

>>   (eqv? 0.5 0.5+0i) => #true
>
> This is definitely false, because (real? 0.5) is true whereas
> (real? 0.5+0.5i) is false in R6RS.

Note I wrote 0i, not 0.0i. None of the standards forbids
mixed exactness complex numbers, and it may be the
case that it's impossible to tell the difference between
0.5+0i and 0.5 using standard arithmetic operations.

--
Alex

John Cowan

unread,
Mar 21, 2012, 11:53:54 PM3/21/12
to scheme-re...@googlegroups.com
Alex Shinn scripsit:

> >> � (eqv? 0.5 0.5L0) => #true


> >
> > This is false if there is a distinction between e-floats and l-floats,
> > because you can get different answers when passing these to /.
>
> Not necessarily - 1/2 can be represented exactly by
> both floats and doubles, and the promotion rules are
> implementation dependent.

True that they're implementation-dependent, but assuming promotion toward
more precise values, dividing 0.5 by 0.1 generates fewer bits than
dividing 0.5L by 0.1.

> As a trivial case, floats could only be used for compact storage in
> memory, and be automatically promoted to double on _any_ computation.

That's what pre-ISO C used to do, and it turns out to be a *very*
bad idea. Any system that cares enough to provide more than one kind
of float scalars will want to do arithmetic on single-precision floats
in single precision, as IEEE prescribes.

> >> � (eqv? 0.5 0.5+0i) => #true


> >
> > This is definitely false, because (real? 0.5) is true whereas
> > (real? 0.5+0.5i) is false in R6RS.
>
> Note I wrote 0i, not 0.0i. None of the standards forbids mixed
> exactness complex numbers, and it may be the case that it's impossible
> to tell the difference between 0.5+0i and 0.5 using standard arithmetic
> operations.

True. Here, for the record, are how the test Schemes represent complex
numbers:

Exact, inexact, and mixed complex numbers: MIT, Gambit, Chibi, Mosh,
STklos.

Exact and inexact complex numbers only (mixed complex numbers become
inexact): Racket, Chicken with the numbers egg, Scheme48/scsh, Kawa,
Chez, Vicare, Larceny, Ypsilon, IronScheme.

Inexact complex numbers only: Gauche, Guile, SISC, SCM, KSi, Scheme
7, UMB.

No complex numbers: Chicken, Bigloo, Ikarus, NexJ, SigScheme, Shoe,
TinyScheme, Scheme 9, Dream, RScheme, BDC, XLisp, Rep, Schemik, Elk,
VX, Oaklisp, Owl Lisp.

--
My confusion is rapidly waxing John Cowan
For XML Schema's too taxing: co...@ccil.org
I'd use DTDs http://www.ccil.org/~cowan
If they had local trees --
I think I best switch to RELAX NG.

Bradley Lucier

unread,
Mar 22, 2012, 2:53:06 PM3/22/12
to scheme-re...@googlegroups.com, Bradley Lucier
On Thu, 2012-03-22 at 00:32 +0900, Alex Shinn wrote:

The implementation, as well, seems to suggest of a
maze of various branches.  One argument made was that in
effect eqv? on numbers would just be a bitwise comparison,
but it may not be so simple (even in R6RS).  For example,
the following should all return #true under the R6RS
definitions, though every one of them may have a different
internal representation:

  (eqv? 0.5 #i1/2)  => #true
  (eqv? 0.5 0.5L0)  => #true

Well, I haven't worked in a Scheme with multiple length floating-point numbers, but I presume that the output of various functions would be in the same precision as the input.  I doubt that

(sqrt 0.5)

and

(sqrt 0.5L)

would be =, as the latter would likely have more bits precision.  So I suspect that these numbers would not be eqv? in R6RS.


  (eqv? 0.5 0.5+0i)  => #true

whereas we would end up with:

  (eqv? -0.0 -0.0L0)  => #false

Again, I suspect that (angle -0.) and (angle -0.0L0) would have different values, so these numbers would not be eqv? in R6RS.


  (eqv? -0.0 -0.0+0i)  => #false

Here this just seems to be different source notations for the same number; I doubt that

(string->number "1")

and

(string->number "000000000000000000000000000000000000000000000000000000001")

would ever be represented internally in two different ways, and I doubt that

(string->number "-0.0")

and

(string->number "-0.0+0i")

would be represented internally in two different ways.


Finally, the option in #229 to require (eqv? +nan.0 +nan.0)
=> #true is simply inconsistent with R5RS, R6RS and reality.

Or, perhaps, against the laws of man and nature?  (Sorry, a bit of teasing.)  Stating this in terms of source code introduces another level of uncertainty, in that we don't know which NaN

(string->number "+nan.0")

will produce, or whether it will produce the same NaN at each call.





I think it's unfortunate that Scheme eqv? for numbers was defined in such a way that when IEEE arithmetic came along with NaNs then

(eq? x y) => (eqv? x y)

was broken.

To summarize my views:

1.  The function "=" is completely outside the eq?/eqv?/equal? hierarchy---it serves completely different purposes.

2.  I think that

(eq? x y) => (eqv? x y)

is so important a property that it should be a defining property of eqv?.

3.  I think eqv? should imply substitutability:  For all "pure" functions except eq?

(eqv? x y) => (equal? (f x) (f y))

I think this is what the R6RS definition is trying to achieve.

Now, I can't say what the various ballot options might mean because I haven't studied the ballot yet (and I find the options generally confusing), but this would be my goals for the "right" definition of eqv?

Brad

John Cowan

unread,
Mar 22, 2012, 9:06:31 PM3/22/12
to scheme-re...@googlegroups.com, Bradley Lucier
Bradley Lucier scripsit:

> Well, I haven't worked in a Scheme with multiple length floating-point
> numbers, but I presume that the output of various functions would be
> in the same precision as the input. I doubt that (sqrt 0.5) and
> (sqrt 0.5L) would be =, as the latter would likely have more bits
> precision. So I suspect that these numbers would not be eqv? in R6RS.

Recent versions of Racket support 32-bit as well as the default 64-bit
floats. Indeed, 5.0F0 and 5.0 are = but they are not eqv?, since their
square roots are 2.23606797749979 and 2.2360680103302f0 respectively.
Obviously, there's a bug in the 32-bit float printing routine; it's
been fixed in a later version.

> Again, I suspect that (angle -0.) and (angle -0.0L0) would have
> different values, so these numbers would not be eqv? in R6RS.

Quite so: the 64-bit version is 3.141592653589793 and the 32-bit version
is 3.1415927410125732f0.

> I think it's unfortunate that Scheme eqv? for numbers was defined in
> such a way that when IEEE arithmetic came along with NaNs then
>
> (eq? x y) => (eqv? x y)
>
> was broken.

It isn't broken. As R6RS 11.5 says, eq? returns #t only when eqv? would
also return #t. This is equivalent to your material conditional.
Put yet another way, it is impossible for objects to be eq? when they
are not eqv?.

I tested eq? and eqv? against my 45 Schemes (up from 39) on NaNs derived
from (- +inf.0 +inf.0) and (* inf.0 0.0), and in none of them did
eq? return true and eqv? return false. The other three combinations
all occur: for example, Racket returns #f for both, Guile returns #f
for eq? and #t for eqv?, and SCM returns #t for both.

> 1. The function "=" is completely outside the eq?/eqv?/equal?
> hierarchy---it serves completely different purposes.

I agree.

> 2. I think that (eq? x y) => (eqv? x y) is so important a property
> that it should be a defining property of eqv?.

It's a defining property of eq?, actually, but that comes to the same
thing in practice.

> 3. I think eqv? should imply substitutability: For all "pure"
> functions except eq? (eqv? x y) => (equal? (f x) (f y)) I think this
> is what the R6RS definition is trying to achieve.

I agree that it's what R6RS is trying to achieve.

--
John Cowan http://www.ccil.org/~cowan co...@ccil.org
Please leave your values Check your assumptions. In fact,
at the front desk. check your assumptions at the door.
--sign in Paris hotel --Cordelia Vorkosigan

Bradley Lucier

unread,
Mar 22, 2012, 10:13:26 PM3/22/12
to scheme-re...@googlegroups.com

On Mar 22, 2012, at 9:06 PM, John Cowan wrote:

>
> Bradley Lucier scripsit:


>
>> I think it's unfortunate that Scheme eqv? for numbers was defined in
>> such a way that when IEEE arithmetic came along with NaNs then
>>
>> (eq? x y) => (eqv? x y)
>>
>> was broken.
>
> It isn't broken. As R6RS 11.5 says, eq? returns #t only when eqv? would
> also return #t. This is equivalent to your material conditional.
> Put yet another way, it is impossible for objects to be eq? when they
> are not eqv?.

It's possible when "=" is used as part of the definition of "eqv?" for IEEE NaNs, as in R5RS, which is what I meant to say.

Brad

Alex Shinn

unread,
Mar 22, 2012, 11:57:13 PM3/22/12
to scheme-re...@googlegroups.com, Bradley Lucier
On Fri, Mar 23, 2012 at 3:53 AM, Bradley Lucier <luc...@math.purdue.edu> wrote:
>[...]

>
> To summarize my views:
>
> 1.  The function "=" is completely outside the eq?/eqv?/equal?
> hierarchy---it serves completely different purposes.

Unfortunately, we have no other way to define the
equivalence of numbers.

> 2.  I think that
>
> (eq? x y) => (eqv? x y)
>
> is so important a property that it should be a defining property of eqv?.
>
> 3.  I think eqv? should imply substitutability:  For all "pure" functions
> except eq?
>
> (eqv? x y) => (equal? (f x) (f y))
>
> I think this is what the R6RS definition is trying to achieve.

I can sympathize with these points, but I think R6RS failed
to achieve them. I think the cure in this worse than the
disease, by introducing greater confusion and incompatibility.

In a nutshell, R6RS is trying to define eqv? as indicating whether
two numbers are _implemented_ differently, and this is
difficult for the user to understand, and varies too much per
implementation.

Whereas in R5 we have:

(eqv? 0.5 0.5L) => #true
(eqv? 0.5 0.5+0.0i) => #true

in R6 this becomes

(eqv? 0.5 0.5L) => unspecified
(eqv? 0.5 0.5+0.0i) => #false

In fact, almost everything becomes technically unspecified
with the loose R5/R7 numeric tower, but even making reasonable
assumptions there are many new unspecified results, such
that the proposed eqv? seems to be of limited use. That
combined with the backwards incompatibility leads me to
think this is a bad change.

> Now, I can't say what the various ballot options might mean because I
> haven't studied the ballot yet (and I find the options generally confusing),
> but this would be my goals for the "right" definition of eqv?

I apologize if there is confusion on any ballot item, but it
does take me a considerable amount of time to organize,
clarify and write up all the tickets as a ballot, and time
restraints prevent me from improving as much as I'd like.

However, we're working together here, and I welcome
contributions and clarifications on any or all items!

--
Alex

John Cowan

unread,
Mar 23, 2012, 12:59:41 AM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
Alex Shinn scripsit:

> In a nutshell, R6RS is trying to define eqv? as indicating whether
> two numbers are _implemented_ differently,

I disagree. IMO, R6RS is trying to define eqv? as indicating whether
two numbers are mathematically distinct: that is, whether (= (f x) (f
y)) is true for every f that doesn't involve non-standard procedures.
It's still possible for two numbers to be `eqv?` even though they are
implemented completely differently, as long as they are indiscernible
other than by `eq?`.

--
John Cowan co...@ccil.org http://ccil.org/~cowan
Any sufficiently-complicated C or Fortran program contains an ad-hoc,
informally-specified bug-ridden slow implementation of half of Common Lisp.
--Greenspun's Tenth Rule of Programming (rules 1-9 are unknown)

Alex Shinn

unread,
Mar 23, 2012, 3:42:22 AM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
On Fri, Mar 23, 2012 at 1:59 PM, John Cowan <co...@mercury.ccil.org> wrote:
> Alex Shinn scripsit:
>
>> In a nutshell, R6RS is trying to define eqv? as indicating whether
>> two numbers are _implemented_ differently,
>
> I disagree.  IMO, R6RS is trying to define eqv? as indicating whether
> two numbers are mathematically distinct:

We've already seen examples where this is not the case.
0.5 and 0.5L are not mathematically distinct. However,
they may be implemented differently, and if so the R6RS
semantics requires them to not be eqv?.

--
Alex

John Cowan

unread,
Mar 23, 2012, 10:21:24 AM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
Alex Shinn scripsit:

> We've already seen examples where this is not the case. 0.5 and 0.5L
> are not mathematically distinct. However, they may be implemented
> differently, and if so the R6RS semantics requires them to not be eqv?.

They are indeed mathematically distinct using inexact arithmetic,
which is a perfectly legitimate set of mathematical functions, however
confusingly named.

It's the old, old story. Droid meets droid. Droid becomes chameleon.
Droid loses chameleon, chameleon becomes blob, droid gets blob back
again. It's a classic tale. --Kryten, Red Dwarf

John Cowan

unread,
Mar 23, 2012, 2:05:56 PM3/23/12
to Bradley Lucier, scheme-re...@googlegroups.com
Bradley Lucier scripsit:

> On Fri, 2012-03-23 at 01:05 -0400, John Cowan wrote:
>
> > Bradley Lucier scripsit:
> >

> > > It's possible when "=" is used as part of the definition of "eqv?" for
> > > IEEE NaNs, as in R5RS, which is what I meant to say.
> >

> > Even so. If = returns #f, then `eqv?` must return #f, and then `eq?` must
> > return #f, even if the two objects are pointer-equal. Both R5RS and R6RS
> > agree on this.
>
> Did you mean not to CC this to the mail list?

No, that was an accident, so I'm adding them back and leaving this
message unstripped.

> As to your point, if eq? is object identity, then if two objects occupy
> exactly the same region of memory, I can think of no stronger notion of
> "identity", so I would say that these two objects are eq? regardless of
> the value of (= x y).

That's a plausible argument, and I'd be inclined to agree with you.
It just happens to be inconsistent with both R5RS (on the assumption that R5RS systems treat (= +nan.0 +nan.0) as false) and R6RS.

R5RS says: "The eqv? procedure returns #f if: [...] obj1 and obj2 are
numbers for which the = procedure returns #f. [...] Eq? [...] will
return true only when eqv? would also return true."

R6RS says: "The eqv? procedure returns #f if one of the following holds:
[...] Obj1 and obj2 yield different results (in the sense of eqv?) when


passed as arguments to any other procedure that can be defined as a finite

composition of Scheme’s standard arithmetic procedures. [...] The
eq? predicate [...] returns #t only when eqv? would also return #t."

--
A: "Spiro conjectures Ex-Lax." John Cowan
Q: "What does Pat Nixon frost her cakes with?" co...@ccil.org
--"Jeopardy" for generative semanticists http://www.ccil.org/~cowan

Bradley Lucier

unread,
Mar 23, 2012, 2:50:51 PM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
I do not interpret the R6RS language as disallowing

(let ((x (/ 0. 0.))) (eqv? x x)) => #t

If obj1 and obj2 are NaNs that occupy exactly the same region of memory (so are "pointer-equivalent), then I can think of no other scheme procedure f for which
(f obj1)

and

(f obj2)

are not eqv?.  And if f takes two arguments, I can think of no Scheme function for which

(let ((x <some computation>))
(eqv? (f obj1 x) (f obj2 x)))

is #f.  So I believe that both

(eq? obj1 obj2) => #t

and

(eqv? obj1 obj2) => #t

are allowed.

Brad

John Cowan

unread,
Mar 23, 2012, 3:47:58 PM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
Bradley Lucier scripsit:

> If obj1 and obj2 are NaNs that occupy exactly the same region of memory
> (so are "pointer-equivalent), then I can think of no other scheme
> procedure f for which (f obj1) and (f obj2) are not eqv?.

Indeed, there can't possibly be any.

So R5RS (extended with (= +nan.0 +nan.0) => #f) allows eq? to be true and
eqv? to be false, but R6RS does not. In practice, only a few R5RS Schemes
(STklos, KSi, RScheme, BDC) report #t for (= +nan.0 +nan.0).

--
John Cowan co...@ccil.org http://www.ccil.org/~cowan
Is it not written, "That which is written, is written"?

Bradley Lucier

unread,
Mar 23, 2012, 4:25:52 PM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
On Fri, 2012-03-23 at 15:47 -0400, John Cowan wrote:
Bradley Lucier scripsit:

> If obj1 and obj2 are NaNs that occupy exactly the same region of memory
> (so are "pointer-equivalent), then I can think of no other scheme
> procedure f for which (f obj1) and (f obj2) are not eqv?.

Indeed, there can't possibly be any.

So R5RS (extended with (= +nan.0 +nan.0) => #f) allows eq? to be true and
eqv? to be false, but R6RS does not.  In practice, only a few R5RS Schemes
(STklos, KSi, RScheme, BDC) report #t for (= +nan.0 +nan.0).


But this implies that if nan1 and nan2 are "pointer-equal" then in R6RS

(eq? nan1 nan2) => #t

so

(eqv nan1 nan2) =>#t

which seems to contradict your previous statement that



> Even so.  If = returns #f, then `eqv?` must return #f, and then `eq?` must
> return #f, even if the two objects are pointer-equal.  Both R5RS and R6RS
> agree on this.

If I follow your reasoning, then in R6RS, assuming that nan1 and nan2 occupy the same area of memory (and so are "pointer-equal") then

(= nan1 nan2) => #f  ;; by properties of IEEE = applied to NaNs

Yet

(eq? nan1 nan2) => #t

is allowed and

(eqv? nan1 nan2) => #t

the latter because there are no functions for which

(eqv? (f nan1) (f nan2)) => #t.

Brad

John Cowan

unread,
Mar 23, 2012, 4:48:56 PM3/23/12
to scheme-re...@googlegroups.com, Bradley Lucier
Bradley Lucier scripsit:

> But this implies that if nan1 and nan2 are "pointer-equal" then in

> R6RS (eq? nan1 nan2) => #t, so (eqv nan1 nan2) =>#t, which seems to


> contradict your previous statement that

> > If = returns #f, then `eqv?` must return #f, and then `eq?` must


> > return #f, even if the two objects are pointer-equal.

I meant to contradict it: my statement immediately above is wrong.

> If I follow your reasoning, then in R6RS, assuming that nan1 and nan2
> occupy the same area of memory (and so are "pointer-equal") then

> (= nan1 nan2) => #f by properties of IEEE = applied to NaNs. Yet
> (eq? nan1 nan2) => #t is allowed and (eqv? nan1 nan2) => #t, the latter


> because there are no functions for which (eqv? (f nan1) (f nan2)) => #t.

Just so. eq? implies eqv?, as you originally postulated. But eqv?
does not imply =, because of the behavior of NaNs, nor does = imply
eqv?, because eqv? is sensitive to exactness.

--
John Cowan co...@ccil.org http://ccil.org/~cowan
No man is an island, entire of itself; every man is a piece of the
continent, a part of the main. If a clod be washed away by the sea,
Europe is the less, as well as if a promontory were, as well as if a
manor of thy friends or of thine own were: any man's death diminishes me,
because I am involved in mankind, and therefore never send to know for
whom the bell tolls; it tolls for thee. --John Donne

Alex Shinn

unread,
Mar 25, 2012, 8:17:36 PM3/25/12
to scheme-re...@googlegroups.com, Bradley Lucier
On Fri, Mar 23, 2012 at 11:21 PM, John Cowan <co...@mercury.ccil.org> wrote:
> Alex Shinn scripsit:
>
>> We've already seen examples where this is not the case.  0.5 and 0.5L
>> are not mathematically distinct.  However, they may be implemented
>> differently, and if so the R6RS semantics requires them to not be eqv?.
>
> They are indeed mathematically distinct using inexact arithmetic,
> which is a perfectly legitimate set of mathematical functions, however
> confusingly named.

Not necessarily - as I suggested earlier, single precision flonums
could exist only as a storage efficiency feature, and auto-promote
to double on any computation (or at least on any computation
where the result would differ as a double). You mentioned earlier
C compilers did this, and that it was a mistake, but I think that's
only because of C's static typing requiring conversion _back_ to
single precision. In Scheme you would never have to convert
back from double precision.

--
Alex

Alex Shinn

unread,
Mar 25, 2012, 8:35:25 PM3/25/12
to scheme-re...@googlegroups.com, Bradley Lucier

Right. The R6RS definition is carefully worded to leave the semantics
of +nan.0 unspecified. The conditions for #true are that the numbers be
both = and yield the same results for any finite composition of standard
arithmetic procedures. The condition for #false is only that they yield
different results for some composition. Thus +nan.0 returning #false
for = but not yielding any differing results satisfies neither of these and
so is unspecified.

We can change the wording so that +nan.0 would be specified one
way or the other, add in an exception for +nan.0, or leave it unspecified.

Note you have to be careful if you want to change the wording such
that (eqv? +nan.0 +nan.0) is true. For example, if you remove the
requirement that the initial two numbers be =, e.g. comparing only results
of other operations, then you would get (eqv? +nan.0 +nan.0) => #true
for any two NaN objects, even ones with different bit patterns, because
these can't be distinguished.

That's another reason I think the motivation here is to expose
implementation details, not some pure mathematical concept
of identity.

--
Alex

John Cowan

unread,
Mar 26, 2012, 11:54:24 AM3/26/12
to scheme-re...@googlegroups.com, Bradley Lucier
Alex Shinn scripsit:

> Not necessarily - as I suggested earlier, single precision flonums
> could exist only as a storage efficiency feature, and auto-promote
> to double on any computation (or at least on any computation
> where the result would differ as a double). You mentioned earlier
> C compilers did this, and that it was a mistake, but I think that's
> only because of C's static typing requiring conversion _back_ to
> single precision. In Scheme you would never have to convert
> back from double precision.

In practice, single-precision floats are important in array work, where
you are indeed storing them back into single-precision containers.

--
Long-short-short, long-short-short / Dactyls in dimeter, John Cowan
Verse form with choriambs / (Masculine rhyme): co...@ccil.org
One sentence (two stanzas) / Hexasyllabically
Challenges poets who / Don't have the time. --robison who's at texas dot net

Reply all
Reply to author
Forward
0 new messages