July 27, 2014
On Sunday, 27 July 2014 at 18:22:50 UTC, Ola Fosheim Gr wrote:
> On Sunday, 27 July 2014 at 18:00:29 UTC, Fool wrote:
>> Thus we do not have transitivity of incomparability:
>
> You are right, I forgot to test the case where only c is NaN. Well, that makes floats suck even more! :-)

In fact, IEEE 754 was designed by brilliant people:

'Non-Extended  encodings are all "Lexicographically Ordered", which means that if two floating-point numbers in the same format are ordered (say x < y), then they are ordered the same way when their bits are reinterpreted as Sign-Magnitude integers. Consequently, processors need no floating-point hardware to search, sort and window floating-point arrays quickly. (However, some processors reverse byte-order!)' [1]

Is a function for comparing floating-point numbers this way available in Phobos?

[1] W. Kahan: "Lecture Notes on the Status of IEEE Standard 754 for Binary Floating-Point Arithmetic", 1997. URL http://www.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF
July 27, 2014
On Sunday, 27 July 2014 at 19:04:09 UTC, Fool wrote:
> define ~ such that a ~ b = (a <= b or b <= a)
                                     ^^ and, of course

What should I say, I'm a fool... ;-)
July 27, 2014
On 7/26/2014 9:46 AM, H. S. Teoh via Digitalmars-d wrote:
> On Fri, Jul 25, 2014 at 11:27:57PM -0700, Walter Bright via Digitalmars-d wrote:
>> I welcome a PR from you on this!
>
> https://github.com/D-Programming-Language/dlang.org/pull/620

Thanks!

July 27, 2014
On Sunday, 27 July 2014 at 19:04:09 UTC, Fool wrote:
> If a candidate for opCmp does not match the default equivalence relation == (defined implicitly or explicitly specified using opEquals) it should not be defined at all.

Does this mean that you agree that opCmp should define a total order?

July 27, 2014
On Sunday, 27 July 2014 at 20:45:25 UTC, Ola Fosheim Grøstad wrote:
> On Sunday, 27 July 2014 at 19:04:09 UTC, Fool wrote:
>> If a candidate for opCmp does not match the default equivalence relation == (defined implicitly or explicitly specified using opEquals) it should not be defined at all.
>
> Does this mean that you agree that opCmp should define a total order?

I think that it should be documented to require properties of a strict partial order (irreflexivity and transitivity, and thus asymmetry) and recommended to model a strict weak order such that (stable) sorting is defined.
July 27, 2014
I think that some confusion is due to == is regarded as meaning equality while it only means equivalence.

Modifying the RGB color example: there is a natural order < on the red channel. Given this ordering, two RGB colors are equivalent if and only if their red values coincide. In this sense, for example, the colors (0, 0, 0) and (0, 255, 255) equivalent although they are not equal.
July 27, 2014
On Sunday, 27 July 2014 at 21:07:08 UTC, Fool wrote:
> I think that some confusion is due to == is regarded as meaning equality while it only means equivalence.

But I thought it was confirmed in this thread by the language designers that "==" is equality in D, thus "===" in other languages are not needed?
July 28, 2014
On Sun, Jul 27, 2014 at 07:04:08PM +0000, Fool via Digitalmars-d wrote:
> On Sunday, 27 July 2014 at 00:43:40 UTC, H. S. Teoh via Digitalmars-d wrote:
> >https://github.com/D-Programming-Language/dlang.org/pull/620
> 
> Thank you for this.
> 
> There is still a problem, I think.
> 
> Defining opEquals only makes sense if a user wants to replace equality by some equivalence relation (different from equality).

Not necessarily. The user type may be implemented in a way where member-wise binary comparison is not the correct implementation of equality. For example, it could be a tree structure implemented by integer indices into a backing array of nodes. There is no way the compiler could know, in general, how to correctly compare two instances of such a structure, since the bit-level representation of two equal objects may be completely different, yet they represent equivalent trees. You're still implementing equality, but it's equality that's not the same as binary equality.


> The user is not forced to define opEquals such that it models an equivalence relation but it hardly makes sense.

Well, in theory, if you *really* wanted to mess with the language (or would-be readers of your code), you *could* implement an arbitrary binary boolean predicate in opEquals, like defining a.opEquals(b) to be ackermannFunction(a-17,b) == sqrt(19*zetaFunction(b/PI)).  The compiler won't stop you -- and, due to computability theory, it can't, in general, decide if your opEquals satisfies the axioms of an equivalence relation -- but it begs the question, why? If you set out to shoot yourself in the foot, it shouldn't be surprising if you blast your toes off. :-P


> Similarly, the user is free to define opCmp without restriction. In practice, however, it does not seem to make any sense if <= does not even model a preorder (reflexive and transitive) or one of >, <=, < does not match.

The problem with imposing these kinds of restrictions, is that they are generally not enforceable (at least, not without significantly crippling legitimate use cases). At some point, we have to stop babysitting the programmer and trust that he's competent enough to not try to subvert the language to make it do stuff it wasn't intended to do. As somebody once said:

	Unix was not designed to stop people from doing stupid things,
	because that would also stop them from doing clever things.
	-- Doug Gwyn

We're not talking about Unix here, but the same principle applies.


> It turns out that intuition of many people around here is not at random. Let A be a set and <= a preorder on A. For all a, b in A define ~ such that a ~ b = (a <= b or b <= a). Then ~ is an equivalence relation. (Let me know if you need a proof.)
> 
> Clearly, it is possible to define different equivalence relations on a set.  The same is true for orderings.
> 
> Now opEquals and opCmp are used to define a default equivalence relation and ordering on a type, respectively.
> 
> Please excuse my lack of creativity: in presence of opCmp I cannot see
> a single sensible use case for defining a.opEquals(b) different from
> a.opCmp(b) == 0.

Floating-point numbers? ;-)

One-point compactification of the reals?

There are legitimate use cases for this, though admittedly, it's not very common. That's why originally I proposed that opEquals would *default* to opCmp()==0, but the user could override that if need be.


> Those examples mentioned before are skewed.
> 
> If a candidate for opCmp does not match the default equivalence relation == (defined implicitly or explicitly specified using opEquals) it should not be defined at all.

Well, certainly, they have to be consistent, otherwise you will get
strange results from your operators. :) But "consistent" may not
necessarily be opEquals = (opCmp()==0).


T

-- 
Life would be easier if I had the source code. -- YHL
July 28, 2014
On Monday, 28 July 2014 at 00:23:36 UTC, H. S. Teoh via Digitalmars-d wrote:
> On Sun, Jul 27, 2014 at 07:04:08PM +0000, Fool via
>> Defining opEquals only makes sense if a user wants to replace equality
>> by some equivalence relation (different from equality).
>
> Not necessarily. The user type may be implemented in a way where
> member-wise binary comparison is not the correct implementation of
> equality. For example, it could be a tree structure implemented by
> integer indices into a backing array of nodes. There is no way the
> compiler could know, in general, how to correctly compare two instances
> of such a structure, since the bit-level representation of two equal
> objects may be completely different, yet they represent equivalent
> trees. You're still implementing equality, but it's equality that's not
> the same as binary equality.

I think we agree except for a subtle difference in defining equality and equivalence. In my personal language there is a single equality but there are many equivalences.


> The problem with imposing these kinds of restrictions, is that they are
> generally not enforceable (at least, not without significantly crippling
> legitimate use cases). At some point, we have to stop babysitting the
> programmer and trust that he's competent enough to not try to subvert
> the language to make it do stuff it wasn't intended to do. As somebody
> once said:
>
> 	Unix was not designed to stop people from doing stupid things,
> 	because that would also stop them from doing clever things.
> 	-- Doug Gwyn
>
> We're not talking about Unix here, but the same principle applies.

I agree.


>> Please excuse my lack of creativity: in presence of opCmp I cannot see
>> a single sensible use case for defining a.opEquals(b) different from
>> a.opCmp(b) == 0.
>
> Floating-point numbers? ;-)

Thank you for pushing me there! It's true.

So D has to separate opEquals and opCmp since otherwise a user could not define floating-point 'equality' and 'comparison' himself in the same way as it is defined by the language.

I'm convinced know. :-)

Thanks!
July 28, 2014
On Sunday, 27 July 2014 at 21:16:52 UTC, Ola Fosheim Grøstad wrote:
> But I thought it was confirmed in this thread by the language designers that "==" is equality in D, thus "===" in other languages are not needed?

For me two instances of a class located at different memory locations can never be equal since they can be distinguished. They can only be equivalent with respect to some relation.

That said, I am not a native speaker, and probably wrong.