23 views

Skip to first unread message

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.

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

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

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.

> 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

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.

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.

(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.

(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

(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

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

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

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.

>[...]

>

> 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

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)

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:

> 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

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.

--

John Cowan co...@ccil.org http://ccil.org/~cowan

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

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

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

(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

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"?

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

(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

(= 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

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

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.

> 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

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

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

Search

Clear search

Close search

Google apps

Main menu