digitalmars.D - Should this be correct behaviour?
- Janice Caron (13/13) Nov 29 2007 Should this be correct behaviour?
- Walter Bright (10/26) Nov 29 2007 You are comparing two array *references* which point to the same array.
- BCS (2/12) Nov 29 2007 That dup should have copied. The references should not be equal.
- Steven Schveighoffer (6/18) Nov 29 2007 my guess is the function to compare arrays of any type does a bit for bi...
- Sean Kelly (6/23) Nov 29 2007 Nope. It calls _adEq, which in turn calls TypeInfo_Af.equals, which
- Derek Parnell (13/21) Nov 29 2007 I don't know which is better either as I can see arguments for both.
- Sean Kelly (7/28) Nov 29 2007 For what it's worth, I think the reason for the current behavior is to
- Janice Caron (10/15) Nov 29 2007 They don't compare not equal even in normal use. They compare as being
- Sean Kelly (5/24) Nov 30 2007 Probably not. I guess the array code could test if the value being
- Janice Caron (11/14) Nov 29 2007 I didn't say that (a[n] != b[n]) is true. I said that (a[n] == b[n])
- Janice Caron (4/22) Nov 29 2007 I don't understand that. It must do. Isn't that how == works for arrays?
- Don Clugston (11/40) Nov 30 2007 Whenever that situation happens, we also have (f == f) even when (f[0] ...
Should this be correct behaviour? float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ assert(f[0] == g[0]); /* Fails */ Certainly it is correct for the second assert to fail, because f[0] and g[0] both contain nan, and as we all know, (nan != nan). Essentially, the second assert (correctly) fails because the elements have not been initialised, and so we can't do the compare. My question is, shouldn't the first assert also fail? Put another way, how can two arrays be considered equal, if their elements are not considered equal? I realise that everything is behaving according to spec. But is it sensible?
Nov 29 2007
Janice Caron wrote:Should this be correct behaviour?Yes.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ assert(f[0] == g[0]); /* Fails */ Certainly it is correct for the second assert to fail, because f[0] and g[0] both contain nan, and as we all know, (nan != nan). Essentially, the second assert (correctly) fails because the elements have not been initialised, and so we can't do the compare. My question is, shouldn't the first assert also fail? Put another way, how can two arrays be considered equal, if their elements are not considered equal?You are comparing two array *references* which point to the same array. The two references clearly are the same. (f == g) does not compare the contents of the arrays.I realise that everything is behaving according to spec. But is it sensible?Yes: float a; float b = a; assert(b == a); // fails And this is how floating point works.
Nov 29 2007
Reply to Walter,Janice Caron wrote:That dup should have copied. The references should not be equal.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ My question is, shouldn't the first assert also fail?You are comparing two array *references* which point to the same array.
Nov 29 2007
"BCS" wroteReply to Walter,my guess is the function to compare arrays of any type does a bit for bit compare? from what I can see in the docs, comparing two arrays is only defined for strings. -SteveJanice Caron wrote:That dup should have copied. The references should not be equal.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ My question is, shouldn't the first assert also fail?You are comparing two array *references* which point to the same array.
Nov 29 2007
Steven Schveighoffer wrote:"BCS" wroteNope. It calls _adEq, which in turn calls TypeInfo_Af.equals, which then calls TypeInfo_f.equals for each element. The problem is that TypeInfo_f.equals is implemented to return true if either a and b are equal *or* if a and b are both NaN. I have no idea why it does this. SeanReply to Walter,my guess is the function to compare arrays of any type does a bit for bit compare?Janice Caron wrote:That dup should have copied. The references should not be equal.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ My question is, shouldn't the first assert also fail?You are comparing two array *references* which point to the same array.
Nov 29 2007
On Thu, 29 Nov 2007 13:29:00 -0800, Sean Kelly wrote:Steven Schveighoffer wrote:I don't know which is better either as I can see arguments for both. (1) If (a[n] != b[n]) is true then (a == b) should be false. however ... (2) If .dup is designed to make an exact copy of an array then the resulting array should be equal to the original array. I'm tending to think that I prefer the existing D behaviour because it allows easier generic code for templates and just 'feels' right. -- Derek (skype: derek.j.parnell) Melbourne, Australia 30/11/2007 10:25:36 AMmy guess is the function to compare arrays of any type does a bit for bit compare?Nope. It calls _adEq, which in turn calls TypeInfo_Af.equals, which then calls TypeInfo_f.equals for each element. The problem is that TypeInfo_f.equals is implemented to return true if either a and b are equal *or* if a and b are both NaN. I have no idea why it does this.
Nov 29 2007
Derek Parnell wrote:On Thu, 29 Nov 2007 13:29:00 -0800, Sean Kelly wrote:For what it's worth, I think the reason for the current behavior is to allow sane interaction with AAs. If NaNs compared not equal via TypeInfo comparisons then any NaN used as an AA key would result in an insertion that was lost forever. With this in mind, I think the current behavior makes the most sense as well. SeanSteven Schveighoffer wrote:I don't know which is better either as I can see arguments for both. (1) If (a[n] != b[n]) is true then (a == b) should be false. however ... (2) If .dup is designed to make an exact copy of an array then the resulting array should be equal to the original array. I'm tending to think that I prefer the existing D behaviour because it allows easier generic code for templates and just 'feels' right.my guess is the function to compare arrays of any type does a bit for bit compare?Nope. It calls _adEq, which in turn calls TypeInfo_Af.equals, which then calls TypeInfo_f.equals for each element. The problem is that TypeInfo_f.equals is implemented to return true if either a and b are equal *or* if a and b are both NaN. I have no idea why it does this.
Nov 29 2007
On Nov 30, 2007 12:23 AM, Sean Kelly <sean f4.ca> wrote:If NaNs compared not equal via TypeInfo comparisonsThey don't compare not equal even in normal use. They compare as being neither == nor !=. (I know you know that. Just trying to be precise here).then any NaN used as an AA key would result in an insertion that was lost forever. With this in mind, I think the current behavior makes the most sense as well.There is another way of looking at it though. Using NaN as array key sounds like a bug to me. Should it even be permitted? Let's think this through - the interpretation of NaN here is either "unassigned variable", or "I don't know the answer" (for example, infinity divided by infinity). Is it even sensible to allow such a beast to be an array key?
Nov 29 2007
Janice Caron wrote:On Nov 30, 2007 12:23 AM, Sean Kelly <sean f4.ca> wrote:Probably not. I guess the array code could test if the value being inserted were equal to itself and if so, throw an exception? Seems a bit of a corner case to test for explicitly though. SeanIf NaNs compared not equal via TypeInfo comparisonsThey don't compare not equal even in normal use. They compare as being neither == nor !=. (I know you know that. Just trying to be precise here).then any NaN used as an AA key would result in an insertion that was lost forever. With this in mind, I think the current behavior makes the most sense as well.There is another way of looking at it though. Using NaN as array key sounds like a bug to me. Should it even be permitted? Let's think this through - the interpretation of NaN here is either "unassigned variable", or "I don't know the answer" (for example, infinity divided by infinity). Is it even sensible to allow such a beast to be an array key?
Nov 30 2007
On Nov 29, 2007 11:32 PM, Derek Parnell <derek nomail.afraid.org> wrote:(1) If (a[n] != b[n]) is true then (a == b) should be false.I didn't say that (a[n] != b[n]) is true. I said that (a[n] == b[n]) is false. Not the same. In fact, (a[n] == b[n]) and (a[n] != b[n]) are both false. So we might suppose that (a == b) and (a != b) should also both be false.I'm tending to think that I prefer the existing D behaviour because it allows easier generic code for templates and just 'feels' right.I don't actually have an opinion one way or the other. Both approaches feel equally right to me. I just wanted to make sure we all understood the behaviour, and that there was some consensus on which approach is most sensible. Sean's analysis is interesting though. His comment "I have no idea why it does this." is one that I'd like to see answered.
Nov 29 2007
On 11/29/07, Walter Bright <newshound1 digitalmars.com> wrote:I don't see why. I duped the array.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ assert(f[0] == g[0]); /* Fails */ My question is, shouldn't the first assert also fail? Put another way, how can two arrays be considered equal, if their elements are not considered equal?You are comparing two array *references* which point to the same array. The two references clearly are the same.(f == g) does not compare the contents of the arrays.I don't understand that. It must do. Isn't that how == works for arrays?I meant, is it sensible that (f == g), given that (f[0] == g[0]) is false?I realise that everything is behaving according to spec. But is it sensible?Yes: float a; float b = a; assert(b == a); // fails And this is how floating point works.
Nov 29 2007
Janice Caron wrote:On 11/29/07, Walter Bright <newshound1 digitalmars.com> wrote:Whenever that situation happens, we also have (f == f) even when (f[0] == f[0]) is false. It's really quite unfortunate that the normal floating point == is defined to be false for NaNs, rather than being a simple bitwise comparison. It wrecks generic code, and it eliminates huge classes of optimisation opportunities. IMHO, a different operator should have been invented; but that's the fault of IEEE754, not D. At least we can control the damage by restricting the unhelpful behaviour to the built-in FP types. A function call could be provided for the case when you really want it to fail if there are any NaNs in either of the arrays. But "containsNaN(arr[])" is probably more useful in that situation anyway.I don't see why. I duped the array.float[] f = new float[1]; float[] g = f.dup; assert(f == g); /* Passes */ assert(f[0] == g[0]); /* Fails */ My question is, shouldn't the first assert also fail? Put another way, how can two arrays be considered equal, if their elements are not considered equal?You are comparing two array *references* which point to the same array. The two references clearly are the same.(f == g) does not compare the contents of the arrays.I don't understand that. It must do. Isn't that how == works for arrays?I meant, is it sensible that (f == g), given that (f[0] == g[0]) is false?I realise that everything is behaving according to spec. But is it sensible?Yes: float a; float b = a; assert(b == a); // fails And this is how floating point works.
Nov 30 2007